-- SMDFImpl.mesa
-- last edited by Schmidt June 1, 1983 5:45 pm
-- last edited by Satterthwaite, August 8, 1983 11:22 am
DIRECTORY
ConvertUnsafe: TYPE USING [ToRope],
CS: TYPE USING [RopeToString],
DFSubr: TYPE USING [AllocateDFSeq, DF, DFSeq, FreeDFSeq, LookupDF, NextDF, WriteOut],
FileStream: TYPE USING [GetLeaderPropertiesForCapability],
IO: TYPE USING [PutF, string],
Rope: TYPE USING [Fetch, IsEmpty, Length, ROPE, Text],
SMCommentTableOps: TYPE USING [FindNext],
SMDF: TYPE USING [],
SMEval: TYPE USING [CompMod],
SMFI: TYPE USING [BcdFileInfo, SrcFileInfo],
SMFIOps: TYPE USING [GetExtFromParse],
SMOps: TYPE USING [MS],
SMTree: TYPE Tree USING [Handle, Link],
SMTreeOps: TYPE USING [Scan, ScanSons],
Stream: TYPE USING [Delete, Handle, PutChar],
Subr: TYPE USING [CopyString, NewStream, SubrStop, Write],
ViewerClasses: TYPE USING [Viewer],
ViewerOps: TYPE USING [FindViewer, RestoreViewer];
SMDFImpl: CEDAR MONITOR
IMPORTS
ConvertUnsafe, CS, DFSubr, FileStream, IO, Rope, SMCommentTableOps, SMFIOps,
SMTreeOps, Stream, Subr, ViewerOps
EXPORTS SMDF ~ {
-- monitor is used to protect the DF software, which cannot
-- be called in parallel
ConstructDFFile: PUBLIC ENTRY PROC[ms: SMOps.MS, top: SMTree.Link] ~ TRUSTED {
ENABLE UNWIND => NULL;
dfFileName: STRING ← "Manufactured.DF"L;
dfseq: DFSubr.DFSeq;
sh: Stream.Handle;
viewer: ViewerClasses.Viewer;
comment: Rope.ROPE;
AnalSons: SMTreeOps.Scan ~ TRUSTED {
WITH t SELECT FROM
applyNode: SMTree.Handle =>
SELECT applyNode.name FROM
$apply => {
ext: SMTree.Link ← SMFIOps.GetExtFromParse[applyNode];
IF ext ~= NIL AND ISTYPE[ext, SMEval.CompMod] THEN {
compMod: SMEval.CompMod ← NARROW[ext];
AddToDFFile[ms, dfseq, compMod]};
SMTreeOps.ScanSons[applyNode, AnalSons]};
ENDCASE => SMTreeOps.ScanSons[applyNode, AnalSons];
ENDCASE => NULL;
};
dfseq ← DFSubr.AllocateDFSeq[maxEntries~500, zoneType~shared];
SMTreeOps.ScanSons[top, AnalSons];
sh ← Subr.NewStream[dfFileName, Subr.Write];
DFSubr.WriteOut[dfseq~dfseq, topLevelFile~NIL, outputStream~sh];
-- now add first comment for Imports, etc.
comment ← SMCommentTableOps.FindNext[ms.comments, 0].text;
-- the first two chars are skipped, they are undoubtedly - followed by -
FOR i: INT IN [2 .. comment.Length[]) DO Stream.PutChar[sh, comment.Fetch[i]] ENDLOOP;
Stream.Delete[sh];
DFSubr.FreeDFSeq[@dfseq];
viewer ← ViewerOps.FindViewer[ConvertUnsafe.ToRope[dfFileName]];
IF viewer ~= NIL THEN {
IF viewer.newVersion THEN
ms.out.PutF["Warning - you are already editing %s.\n", IO.string[dfFileName]]
ELSE ViewerOps.RestoreViewer[viewer]};
ms.out.PutF["DF file written on file Manufactured.DF\n"];
Subr.SubrStop[]; -- shuts down old DF world
};
AddToDFFile: PROC[
ms: SMOps.MS, dfseq: DFSubr.DFSeq, compMod: SMEval.CompMod] ~ TRUSTED {
fiSrc: SMFI.SrcFileInfo ← compMod.fiSrc;
fiBcd: SMFI.BcdFileInfo ← compMod.fiBcd;
createtime: LONG CARDINAL ← 0;
AddAFile[ms, dfseq, fiSrc.host, fiSrc.directory, fiSrc.shortname, fiSrc.version];
IF fiBcd.bcdPresent THEN
createtime ← FileStream.GetLeaderPropertiesForCapability[fiBcd.bcdCap].create;
AddAFile[ms, dfseq, fiBcd.host, fiBcd.directory, fiBcd.shortname, createtime]};
AddAFile: PROC[
ms: SMOps.MS, dfseq: DFSubr.DFSeq,
host, directory, shortname: Rope.Text, createTime: LONG CARDINAL] ~ TRUSTED {
df: DFSubr.DF;
str: STRING ← [100];
CS.RopeToString[to~str, from~shortname];
IF DFSubr.LookupDF[dfseq, str] ~= NIL THEN RETURN;
df ← DFSubr.NextDF[dfseq];
IF df = NIL THEN RETURN; -- too big
df.host ← Subr.CopyString[
IF Rope.IsEmpty[host] THEN "Unknown"L ELSE LOOPHOLE[host], dfseq.dfzone];
df.directory ← Subr.CopyString[
IF Rope.IsEmpty[directory] THEN "Unknown"L ELSE LOOPHOLE[directory], dfseq.dfzone];
df.shortname ← Subr.CopyString[LOOPHOLE[shortname], dfseq.dfzone];
df.version ← 0;
df.createtime ← createTime};
}.