-- 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]]}; }; }.