-- SMBcdImpl.mesa
-- last edit by Schmidt, June 2, 1983 5:23 pm
-- last edit by Satterthwaite, July 26, 1983 12:41 pm
-- code to produce and read .modelBcd files
DIRECTORY
CS: TYPE USING [
CardFromRope, EndsIn, RopeFromStamp, RootName, StampFromRope],
FileIO: TYPE USING [Open],
IO: TYPE USING [
card, Close, EndOf, GetChar, GetSequence, LineAtATime, PutF, RIS, rope, STREAM],
Rope: TYPE USING [Cat, Fetch, Flatten, Length, ROPE, Substr, Text],
SMBcd: TYPE USING [],
SMCommentTableOps: TYPE USING [CommentM],
SMEval: TYPE USING [Eval],
SMFI: TYPE USING [BcdFileInfo, SrcFileInfo],
SMFIOps: TYPE USING [FindBcd, FindSource],
SMOps: TYPE USING [MS],
SMProj: TYPE USING [Proj, Analyzed, Find],
SMTree: TYPE Tree USING [ApplOp, Handle, Link],
SMTreeOps: TYPE USING [GetExt, OpName, Scan, ScanSons],
SMUtil: TYPE USING [ParseStream, PrettyPrint],
TimeStamp: TYPE USING [Stamp];
SMBcdImpl: CEDAR PROGRAM
IMPORTS CS, FileIO, IO, Rope, SMEval, SMFIOps, SMProj, SMTreeOps, SMUtil
EXPORTS SMBcd ~ {
OPEN Tree~~SMTree, TreeOps~~SMTreeOps;
SrcFIList: TYPE ~ LIST OF SMFI.SrcFileInfo;
BcdFIList: TYPE ~ LIST OF SMFI.BcdFileInfo;
ProjList: TYPE ~ LIST OF SMProj.Proj;
-- making .modelBcd files
WriteModelBcd: PUBLIC PROC[
ms: SMOps.MS, t: Tree.Link, modelFileName, bcdFileName: Rope.Text] ~ {
ENABLE UNWIND => {NULL};
srcFIList: SrcFIList ← NIL;
bcdFIList: BcdFIList ← NIL;
AddSrcFi: PROC[fiSrc: SMFI.SrcFileInfo] ~ {
FOR l: SrcFIList ← srcFIList, l.rest UNTIL l = NIL DO
IF fiSrc = l.first THEN RETURN;
ENDLOOP;
srcFIList ← CONS[fiSrc, srcFIList]};
AddBcdFi: PROC[fiBcd: SMFI.BcdFileInfo] ~ {
FOR l: BcdFIList ← bcdFIList, l.rest UNTIL l = NIL DO
IF fiBcd = l.first THEN RETURN;
ENDLOOP;
bcdFIList ← CONS[fiBcd, bcdFIList]};
projList: ProjList ← NIL;
AddProj: PROC[proj: SMProj.Proj] ~ {
FOR l: ProjList ← projList, l.rest UNTIL l = NIL DO
IF proj = l.first THEN RETURN;
ENDLOOP;
projList ← CONS[proj, projList]};
FindFiles: TreeOps.Scan ~ {
WITH t SELECT FROM
node: Tree.Handle => {
TreeOps.ScanSons[node, FindFiles];
IF TreeOps.OpName[node] IN Tree.ApplOp THEN
WITH TreeOps.GetExt[node] SELECT FROM
proj: SMProj.Proj => AddProj[proj];
ENDCASE;
};
fiSrc: SMFI.SrcFileInfo => AddSrcFi[fiSrc];
fiBcd: SMFI.BcdFileInfo => AddBcdFi[fiBcd];
ENDCASE => NULL;
};
outName: Rope.Text ~ (IF CS.EndsIn[bcdFileName, ".modelBcd"]
THEN bcdFileName ELSE CS.RootName[bcdFileName].Cat[".modelBcd"].Flatten[]);
outFile: IO.STREAM;
FindFiles[t];
outFile ← FileIO.Open[outName, $overwrite];
BuildTypeTables[outFile, srcFIList, bcdFIList];
BuildProjTable[outFile, projList];
SMUtil.PrettyPrint[out~outFile, root~ms.tree, comments~NIL];
outFile.Close[];
ms.out.PutF[".modelBcd file written on %s\n", IO.rope[outName]]};
BuildTypeTables: PROC[outFile: IO.STREAM, srcFIList: SrcFIList, bcdFIList: BcdFIList] ~ {
FOR l: SrcFIList ← srcFIList, l.rest UNTIL l = NIL DO
fiSrc: SMFI.SrcFileInfo ~ l.first;
outFile.PutF["%d %s\n", IO.card[fiSrc.create], IO.rope[fiSrc.shortName]];
SMUtil.PrettyPrint[out~outFile, root~fiSrc.type, comments~NIL];
outFile.PutF[".\n"];
ENDLOOP;
outFile.PutF[".\n"];
FOR l: BcdFIList ← bcdFIList, l.rest UNTIL l = NIL DO
fiBcd: SMFI.BcdFileInfo ~ l.first;
outFile.PutF["%s %s\n", IO.rope[CS.RopeFromStamp[fiBcd.stamp]], IO.rope[fiBcd.shortName]];
SMUtil.PrettyPrint[out~outFile, root~fiBcd.type, comments~NIL];
outFile.PutF[".\n"];
ENDLOOP;
outFile.PutF[".\n"]};
BuildProjTable: PROC[outFile: IO.STREAM, projList: ProjList] ~ {
FOR l: ProjList ← projList, l.rest UNTIL l = NIL DO
proj: SMProj.Proj ~ l.first;
outFile.PutF["%s %s", IO.rope[CS.RopeFromStamp[proj.stamp]], IO.rope[proj.localName]];
outFile.PutF[IF proj.interface THEN " T " ELSE " F "];
outFile.PutF["%d %d\n",
IO.card[proj.symbolPages.base], IO.card[proj.symbolPages.pages]];
ENDLOOP;
outFile.PutF[".\n"]};
-- reading .modelBcd files
GetLine: PROC[input: IO.STREAM] RETURNS[line: Rope.ROPE] ~ {
line ← input.GetSequence[IO.LineAtATime];
[] ← input.GetChar[]}; -- skip '\n
ReadModelBcdPrefix: PUBLIC PROC[ms: SMOps.MS, input: IO.STREAM] ~ {
ENABLE UNWIND => {NULL};
-- reconstruct the type table
ended: BOOL;
header, line: Rope.ROPE;
typeRope: Rope.ROPE;
WHILE ~input.EndOf DO
-- first line has the filename and create time (or terminator)
header ← GetLine[input];
typeRope ← NIL;
IF header.Fetch[0] = '. AND header.Length = 1 THEN EXIT;
ended ← input.EndOf;
WHILE ~ended DO
line ← GetLine[input];
IF line.Fetch[line.Length-1] = '. THEN ended ← TRUE
ELSE typeRope ← typeRope.Cat["\n", line];
ENDLOOP;
AddSrcFI[ms, header, typeRope];
ENDLOOP;
WHILE ~input.EndOf DO
-- first line has the filename and version stamp (or terminator)
header ← GetLine[input];
typeRope ← NIL;
IF header.Fetch[0] = '. AND header.Length = 1 THEN EXIT;
ended ← input.EndOf;
WHILE ~ended DO
line ← GetLine[input];
IF line.Fetch[line.Length-1] = '. THEN ended ← TRUE
ELSE typeRope ← typeRope.Cat["\n", line];
ENDLOOP;
AddBcdFI[ms, header, typeRope];
ENDLOOP;
-- reconstruct the projection table
WHILE ~input.EndOf DO
line ← GetLine[input];
IF line.Fetch[0] = '. AND line.Length = 1 THEN EXIT;
AddProj[ms, line];
ENDLOOP;
};
AddSrcFI: PROC[ms: SMOps.MS, header, typeRope: Rope.ROPE] ~ {
createTime: LONG CARDINAL;
fiSrc: SMFI.SrcFileInfo;
start, next: INT ← 0;
length: INT ~ header.Length;
NextToken: PROC ~ {
WHILE next < length AND header.Fetch[next] = ' DO next ← next + 1 ENDLOOP;
start ← next;
WHILE next < length AND header.Fetch[next] # ' DO next ← next + 1 ENDLOOP};
NextToken[];
createTime ← CS.CardFromRope[header.Substr[start, next-start]];
fiSrc ← SMFIOps.FindSource[createTime];
IF fiSrc.state < $analyzed THEN { -- move to SMFIImpl
fileName: Rope.Text;
NextToken[];
fileName ← header.Flatten[start, next];
fiSrc.host ← fiSrc.directory ← NIL; fiSrc.shortName ← fileName; fiSrc.version ← 0;
fiSrc.localName ← fiSrc.shortName; fiSrc.new ← FALSE;
fiSrc.type ← SMEval.Eval[ms, SMUtil.ParseStream[ms, IO.RIS[typeRope]], NIL];
fiSrc.state ← $analyzed;
IF ms.debugFlag THEN ms.out.PutF["Insert %s into fi\n", IO.rope[fileName]]};
};
AddBcdFI: PROC[ms: SMOps.MS, header, typeRope: Rope.ROPE] ~ {
stamp: TimeStamp.Stamp;
fiBcd: SMFI.BcdFileInfo;
start, next: INT ← 0;
length: INT ~ header.Length;
NextToken: PROC ~ {
WHILE next < length AND header.Fetch[next] = ' DO next ← next + 1 ENDLOOP;
start ← next;
WHILE next < length AND header.Fetch[next] # ' DO next ← next + 1 ENDLOOP};
NextToken[];
stamp ← CS.StampFromRope[header.Substr[start, next-start]];
fiBcd ← SMFIOps.FindBcd[stamp];
IF fiBcd.state < $analyzed THEN { -- move to SMFIImpl
fileName: Rope.Text;
NextToken[];
fileName ← header.Flatten[start, next];
fiBcd.host ← fiBcd.directory ← NIL; fiBcd.shortName ← fileName; fiBcd.version ← 0;
fiBcd.localName ← fiBcd.shortName;
fiBcd.type ← SMEval.Eval[ms, SMUtil.ParseStream[ms, IO.RIS[typeRope]], NIL];
fiBcd.state ← $analyzed;
IF ms.debugFlag THEN ms.out.PutF["Insert %s into fi\n", IO.rope[fileName]]};
};
AddProj: PROC[ms: SMOps.MS, line: Rope.ROPE] ~ {
stamp: TimeStamp.Stamp;
proj: SMProj.Proj;
start, next: INT ← 0;
length: INT ~ line.Length;
NextToken: PROC ~ {
WHILE next < length AND line.Fetch[next] = ' DO next ← next + 1 ENDLOOP;
start ← next;
WHILE next < length AND line.Fetch[next] # ' DO next ← next + 1 ENDLOOP};
NextToken[];
stamp ← CS.StampFromRope[line.Substr[start, next-start]];
proj ← SMProj.Find[stamp];
IF ~proj.Analyzed THEN { -- move to SMProjImpl
fileName: Rope.Text;
NextToken[];
fileName ← line.Flatten[start, next];
proj.host ← proj.directory ← NIL; proj.shortName ← fileName; proj.version ← 0;
NextToken[];
proj.interface ← (line.Fetch[start] = 'T);
NextToken[];
proj.symbolPages.base ← CS.CardFromRope[line.Substr[start, next-start]];
NextToken[];
proj.symbolPages.pages ← CS.CardFromRope[line.Substr[start, next-start]];
proj.localName ← proj.shortName;
proj.state ← $analyzed;
IF ms.debugFlag THEN ms.out.PutF["Insert %s into proj\n", IO.rope[fileName]]};
};
}.