-- MDUtilImpl.Mesa
-- last edit by Schmidt, May 4, 1982 1:04 pm
-- last edit by Satterthwaite, January 31, 1983 9:29 am
-- Pilot 6.0/ Mesa 7.0
-- MDUtilImpl for the system modeller, defined in MDUtil
-- can't use the Dir stuff since it may not be around (e.g. Designmodel)
DIRECTORY
Ascii: TYPE USING [CR],
CWF: TYPE USING [FWF0, FWF1, FWF2, FWF3, FWFC, SetCode, SetWriteProcedure, SWF1, SWF3,
WF0, WF1, WF2, WF4, WFC, WFCR],
Dir: TYPE USING [DepSeq, FileInfo],
Directory: TYPE USING [Error, GetProperty, Handle, Lookup, PropertyType, PutProperty],
ExecOps: TYPE USING [Bind, Command, Outcome],
Feedback: TYPE USING [BeginItemProc, CreateProc, DestroyProc, FinishItemProc,
Handle, NoteProgressProc, Outcome, Procs],
File: TYPE USING [Capability],
FileStream: TYPE USING [EndOf],
IO: TYPE USING[GetChar, Handle, Put, PutChar,
SetEcho, Signal, string],
LongString: TYPE USING [AppendString, EqualString, EquivalentString],
MDModel: TYPE USING [APPLSymbol, GetFileInfo, HasAStringName,
LETSymbol, LISTSymbol, LocForType, LOCSymbol, LookForInstBcd, MODELSymbol, NarrowToAPPL,
NarrowToLET, NarrowToLIST, NarrowToLOC, NarrowToMODEL, NarrowToSTRING,
NarrowToTYPE, Sym, Symbol, SymbolSeq, TraverseList, TraverseTree, TYPESymbol],
MDUtil: TYPE USING [],
Rope: TYPE USING[Fetch, Length, Lower, ROPE, Text],
Runtime: TYPE USING [IsBound, RunConfig],
Stream: TYPE USING [Delete, GetChar, Handle, PutChar],
Subr: TYPE USING [AbortMyself, Any, CopyString, EndsIn, FreeString, NewStream,
Read, strcpy],
TemporarySpecialExecOps: TYPE USING [BindUsingFeedback],
TimeStamp: TYPE USING [Stamp],
TypeScript: TYPE USING[ResetUserAbort, TS, UserAbort];
-- this monitor is for the AcquireMsgLock, ReleaseMsgLock lock
MDUtilImpl: MONITOR
IMPORTS CWF, Directory, ExecOps, FileStream, IO, LongString,
MDModel, Rope, Runtime, Stream, Subr, TemporarySpecialExecOps, TypeScript
EXPORTS MDUtil = {
-- declarations used throughout this module
TooManySymbols: ERROR = CODE;
-- MDS Usage!!
msgLock: CONDITION;
msgLocked: BOOL ← FALSE;
--
controlloc: MDModel.LOCSymbol ← NIL; -- the location (e.g. @) of "CONTROL"
ss: MDModel.SymbolSeq ← NIL;
curlen: CARDINAL; -- the current output column on the terminal
globalTypeScript: TypeScript.TS ← NIL;
officialwindow: IO.Handle ← NIL;
globalmsgout: IO.Handle ← NIL;
-- Binder-specific feedback stuff
binderState: {normal, warnings, errors};
-- for hidden imports
MakeBinary, MakeSource: PROC[LONG STRING] RETURNS[Dir.DepSeq] ← NIL;
savespmodel: MDModel.MODELSymbol ← NIL;
-- endof MDS usage !!!
THRESHOLD: CARDINAL = 60;
INDENTSIZE: CARDINAL = 6;
MAXLINES: CARDINAL = 60;
AcquireMsgLock: PUBLIC ENTRY PROC =
{
ENABLE UNWIND => NULL;
WHILE msgLocked DO
WAIT msgLock;
ENDLOOP;
msgLocked ← TRUE;
};
ReleaseMsgLock: PUBLIC ENTRY PROC =
{
ENABLE UNWIND => NULL;
msgLocked ← FALSE;
NOTIFY msgLock;
};
AnyR: PUBLIC PROC[str: Rope.ROPE, ch: CHAR] RETURNS[BOOL] = {
len: CARDINAL ← str.Length[];
FOR i: CARDINAL IN [0..len) DO
IF str.Fetch[i] = ch THEN RETURN[TRUE];
ENDLOOP;
RETURN[FALSE];
};
IOConfirm: PUBLIC PROC[dch: CHAR, in, out: IO.Handle] RETURNS[CHAR] =
{
ch: CHAR;
old: IO.Handle;
DO {
ENABLE IO.Signal => TRUSTED {IF ec = Rubout THEN LOOP};
out.Put[IO.string["? "L]];
old ← IO.SetEcho[in, NIL];
ch ← in.GetChar[ ! UNWIND => [] ← IO.SetEcho[in, old]];
[] ← IO.SetEcho[in, old];
IF ch = '\n THEN ch ← dch;
ch ← Rope.Lower[ch];
RETURN[ch];
};
ENDLOOP;
};
-- if outsh = NIL then print on IOStream
PrintNewModelStream: PUBLIC PROC[symbolseq: MDModel.SymbolSeq,
sproot: MDModel.Symbol, outsh: Stream.Handle, title: Rope.Text,
dontdefault: BOOL, typeScript: TypeScript.TS, ttyout: IO.Handle] = {
wp: PROC[CHAR];
nlines: CARDINAL ← 0;
NoMore: SIGNAL = CODE;
Incr: PROC[ch: CHAR] = {
IF ch = Ascii.CR THEN {
curlen ← 0;
nlines ← nlines + 1;
}
ELSE curlen ← curlen + 1;
IF outsh = NIL THEN ttyout.PutChar[ch]
ELSE Stream.PutChar[outsh, ch];
};
ss ← symbolseq;
SetAllPrint[FALSE, symbolseq];
curlen ← 0;
wp ← CWF.SetWriteProcedure[Incr];
IF sproot.stype = typeLOC THEN {
sploc: MDModel.LOCSymbol;
spm: MDModel.MODELSymbol;
sploc ← MDModel.NarrowToLOC[sproot];
spm ← sploc.nestedmodel;
IF spm ~= NIL AND sploc.host ~= NIL THEN
CWF.WF4["--[%s]<%s>%s.%s\n"L, sploc.host, sploc.path,
sploc.tail, sploc.sext];
-- avoid printing the LOC
sproot ← spm;
};
IF sproot.stype = typeMODEL THEN {
spm: MDModel.MODELSymbol;
spm ← MDModel.NarrowToMODEL[sproot];
CWF.WF2["-- %s, %lt\n"L, spm.modelfilename, @spm.modelcreate];
};
IF title ~= NIL THEN CWF.WF1["-- %s\n"L, LOOPHOLE[title]];
PrintNewModel[sproot, ";\n"L, NIL, 0, TRUE, dontdefault, typeScript
! NoMore => CONTINUE];
CWF.WF0["\n"L];
[] ← CWF.SetWriteProcedure[wp];
};
-- indent = 0 means no indenting
-- indent > 0 means levels of indenting
PrintNewModel: PROC[p: MDModel.Symbol, sep: STRING, parent: MDModel.Symbol,
indent: CARDINAL, definitional, dontdefault: BOOL, typeScript: TypeScript.TS] = {
fprint: BOOL;
s: LONG STRING;
ProcPrintModel: PROC[sp: MDModel.Symbol] = {
IF fprint THEN CWF.WF0[sep];
IF curlen >= THRESHOLD THEN {
CWF.WFCR[];
FOR i: CARDINAL IN [0.. indent*INDENTSIZE) DO
CWF.WFC[' ];
ENDLOOP;
};
-- this puts () around PLUS and THEN arguments
IF Subr.Any[sep, 'U] OR Subr.Any[sep, 'N] THEN
CWF.WFC['(];
PrintNewModel[sp,sep,p, indent, definitional, dontdefault, typeScript];
IF Subr.Any[sep, 'U] OR Subr.Any[sep, 'N] THEN
CWF.WFC[')];
fprint ← TRUE;
};
IF p = NIL THEN {
CWF.WF0["{p is NIL}"L];
RETURN;
};
IF NOT dontdefault AND NOT p.print THEN {
IF definitional THEN {
-- this default may only be used in a place that allows
-- definitions
IF ConsiderColonAbbr[p, indent, typeScript] THEN RETURN;
IF ConsiderStarId[p, indent] THEN RETURN;
};
};
s ← NIL;
IF p.qualified THEN PrintQualified[p, ss]
ELSE IF p.stype IN MDModel.HasAStringName THEN {
s ← MDModel.Sym[p];
IF s ~= NIL THEN CWF.WF1["%s"L, s]
ELSE IF p.stype = typeSTRING THEN
CWF.WF1["""%s"""L, MDModel.NarrowToSTRING[p].strval]
ELSE CWF.WF0[">NULLSTR<"L];
};
IF (NOT p.print AND definitional) OR p.stype NOT IN MDModel.HasAStringName THEN {
p.print ← TRUE; -- this avoids recursive print loops
WITH pt: p SELECT FROM
typeTYPE => {
IF ss = NIL THEN ERROR;
IF p = ss.controlv THEN RETURN; -- CONTROL
CWF.WF1[": %s"L, IF pt.frameptr THEN "FRAMEPTRTYPE"L ELSE "TYPE"L];
IF NOT LongString.EquivalentString[pt.typeName, pt.typesym] THEN
CWF.WF1[" %s"L, pt.typeName];
IF pt.typeval ~= NIL THEN {
CWF.WF0["~"L]; --CWF.WF0[" == "L];
PrintNewModel[pt.typeval,sep,p, indent,
TRUE, dontdefault, typeScript];
};
};
typeLOC => {
IF TypeScript.UserAbort[typeScript]THEN SIGNAL Subr.AbortMyself;
PrintLoc[MDModel.NarrowToLOC[p], dontdefault, indent, parent, typeScript];
};
typePROC => {
CWF.WF0[": PROC ["L];
IF pt.procparm ~= NIL THEN
PrintNewModel[pt.procparm,",\n\t"L,p, indent,
TRUE, dontdefault, typeScript];
CWF.WF0["]\nRETURNS ["L];
IF pt.procret ~= NIL THEN
PrintNewModel[pt.procret,", "L,p, indent,
FALSE, dontdefault, typeScript];
CWF.WF0["] [\n"L];
IF pt.procval ~= NIL THEN
PrintNewModel[pt.procval,";\n"L,p, indent,
TRUE, dontdefault, typeScript];
CWF.WF0["\n]\n"L];
};
typeSTRING => {
CWF.WF1["""%s"""L,pt.strval];
};
typeAPPL => {
CWF.WF0[": "L];
-- CWF.WF0["{"L];
IF pt.appltype.stype = typeLIST THEN {
CWF.WF0["[\n"L];
PrintNewModel[pt.appltype,",\n"L,p,
indent+1, TRUE, dontdefault, typeScript];
CWF.WF0["\n\t]"L];
}
ELSE PrintNewModel[pt.appltype,sep,p,
indent, FALSE, dontdefault, typeScript];
-- CWF.WFC['}];
IF pt.applval ~= NIL THEN {
CWF.WF0["~"L]; -- CWF.WF0[" == "L];
PrintNewModel[pt.applval,sep,p, indent+1,
FALSE, dontdefault, typeScript];
};
};
typeLIST => {
oldsep: STRING ← sep;
fprint ← FALSE;
sep ← IF pt.listtype = plus THEN " PLUS "L
ELSE IF pt.listtype = then THEN " THEN "L
ELSE sep;
-- IF pt.rest = NIL THEN CWF.WF0[">ONELIST<"L];
MDModel.TraverseList[MDModel.NarrowToLIST[p],ProcPrintModel];
sep ← oldsep;
};
typeOPEN => {
CWF.WF0[ "OPEN "L];
PrintNewModel[pt.open,", "L,IF parent~=NIL THEN parent ELSE p,
indent, TRUE, dontdefault, typeScript];
};
typeLET => {
CWF.WF0[ "LET ["L];
PrintNewModel[pt.letgrp,", "L,
IF parent ~= NIL THEN parent ELSE p, indent,
TRUE, dontdefault, typeScript];
CWF.WF0[ "]"L];
IF pt.letval ~= NIL THEN {
CWF.WF0[" ~ "L]; -- CWF.WF0[" == "L];
PrintNewModel[pt.letval,sep,
IF parent ~= NIL THEN parent ELSE p,
indent, TRUE, dontdefault, typeScript];
};
};
typeMODEL => {
PrintNewModel[pt.model, sep, IF parent ~= NIL THEN parent ELSE p,
indent, TRUE, dontdefault, typeScript];
};
ENDCASE => ERROR; -- bad select PrintNewModel
}
ELSE IF p.stype = typeLET THEN CWF.WF0["{Unknown LET}"L];
-- ELSE IF s = NIL THEN Runtime.CallDebugger["s is NIL and p.print = FALSE"L];
};
-- must search all over for the a of a.b we use
PrintQualified: PROC[target: MDModel.Symbol, symbolseq: MDModel.SymbolSeq] = {
parent: MDModel.Symbol;
found: BOOL ← FALSE;
ProcAnal: PROC[spa: MDModel.Symbol, spmodel: MDModel.MODELSymbol]
RETURNS[proceed: BOOL ← TRUE] = {
sptype: MDModel.LISTSymbol;
spappl: MDModel.APPLSymbol;
IF found THEN RETURN[FALSE];
IF spa.stype ~= typeAPPL THEN RETURN;
spappl ← MDModel.NarrowToAPPL[spa];
IF spappl.appltype = NIL OR spappl.appltype.stype ~= typeLIST THEN RETURN;
sptype ← MDModel.NarrowToLIST[spappl.appltype];
MDModel.TraverseList[sptype, ProcList];
IF found THEN {
parent ← spappl;
RETURN[FALSE];
};
};
ProcList: PROC[sp: MDModel.Symbol] = {
IF target = sp THEN found ← TRUE;
};
IF NOT target.qualified THEN RETURN;
MDModel.TraverseTree[symbolseq.toploc, symbolseq, ProcAnal, TRUE];
IF found THEN
CWF.WF2["%s.%s"L, MDModel.Sym[parent], MDModel.Sym[target]]
ELSE CWF.WF1["%s"L, MDModel.Sym[target]];
};
PrintLoc: PROC[p: MDModel.LOCSymbol, dontdefault: BOOL, indent: CARDINAL,
parent: MDModel.Symbol, typeScript: TypeScript.TS] = {
CWF.WF0["@"L];
IF p.host ~= NIL THEN CWF.WF1["[%s]"L,p.host];
IF p.path ~= NIL THEN CWF.WF1["<%s>"L,p.path];
IF p.tail ~= NIL THEN CWF.WF1["%s"L,p.tail];
IF p.sext ~= NIL
AND (dontdefault OR NOT LongString.EquivalentString[p.sext, "mesa"L]) THEN {
CWF.WFC['.];
IF p.prinpart ~= 0 THEN {
FOR i: CARDINAL IN [0 .. p.prinpart) DO
CWF.WFC[p.sext[i]];
ENDLOOP;
CWF.WFC['*];
FOR i: CARDINAL IN [p.prinpart .. p.sext.length) DO
CWF.WFC[p.sext[i]];
ENDLOOP;
}
ELSE CWF.WF1["%s"L,p.sext];
};
IF p.createtime > 0 THEN CWF.WF1["!%lu"L,@p.createtime];
-- NO! ELSE IF p.bcdvers > 0 THEN CWF.WF1["!%lu"L,@p.bcdvers];
IF p.parmlist ~= NIL THEN {
CWF.WF0["["L];
IF NOT p.parmsdefaultable OR dontdefault THEN
PrintNewModel[p.parmlist,", "L,p, indent+1,
FALSE, dontdefault, typeScript];
CWF.WF0["]"L];
};
-- for the case where there is an OPEN @loc
IF p.nestedmodel ~= NIL AND parent.stype = typeOPEN THEN {
-- prints it SILENTLY to set the p.print bit
wp: PROC[CHAR];
NullPrint: PROC[ch: CHAR] = {};
wp ← CWF.SetWriteProcedure[NullPrint];
PrintNewModel[p.nestedmodel,", "L,p, indent+1, TRUE, dontdefault, typeScript];
[] ← CWF.SetWriteProcedure[wp];
};
p.print ← FALSE;
};
-- makes defaults like ":@id" equivalent to "id: TYPE = @id.mesa"
-- and ":@idImpl" equivalent to "idImpl: id = @idimpl.mesa"
ConsiderColonAbbr: PROC[sp: MDModel.Symbol, indent: CARDINAL,
typeScript: TypeScript.TS] RETURNS[success: BOOL] = {
sploc: MDModel.LOCSymbol;
WITH spt: sp SELECT FROM
typeTYPE => {
IF spt.typeval = NIL OR spt.typeval.stype ~= typeLOC THEN RETURN[FALSE];
sploc ← MDModel.NarrowToLOC[spt.typeval];
IF sploc.tail = NIL
OR NOT LongString.EquivalentString[sploc.sext, "mesa"L]
THEN RETURN[FALSE];
IF NOT LongString.EqualString[spt.typesym, sploc.tail] THEN RETURN[FALSE];
};
typeAPPL => {
stemp: STRING ← [30];
IF spt.applval = NIL OR spt.applval.stype ~= typeLOC THEN RETURN[FALSE];
sploc ← MDModel.NarrowToLOC[spt.applval];
IF sploc.tail = NIL
OR NOT LongString.EquivalentString[sploc.sext, "mesa"L]
THEN RETURN[FALSE];
IF NOT LongString.EqualString[spt.applsym, sploc.tail] THEN RETURN[FALSE];
Subr.strcpy[stemp, spt.applsym];
IF NOT Subr.EndsIn[stemp, "impl"L] THEN RETURN[FALSE];
stemp.length ← stemp.length - 4;
IF NOT LongString.EqualString[stemp, MDModel.Sym[spt.appltype]] THEN
RETURN[FALSE];
};
ENDCASE => RETURN[FALSE];
CWF.WF0[":"L];
sp.print ← TRUE;
PrintLoc[sploc, FALSE, indent, sp, typeScript];
RETURN[TRUE];
};
-- makes defaults like "*: id"
-- equivalent to "idImpl: id"
ConsiderStarId: PROC[sp: MDModel.Symbol, indent: CARDINAL] RETURNS[BOOL] = {
spappl: MDModel.APPLSymbol;
sptype: MDModel.Symbol;
stemp: STRING ← [30];
IF sp.stype ~= typeAPPL THEN RETURN[FALSE];
spappl ← MDModel.NarrowToAPPL[sp];
IF spappl.applval ~= NIL THEN RETURN[FALSE]; -- language does not allow this
sptype ← spappl.appltype;
IF sptype = NIL OR (sptype.stype NOT IN MDModel.HasAStringName) THEN
RETURN[FALSE];
CWF.SWF1[stemp, "%sImpl"L, MDModel.Sym[sptype]];
IF NOT LongString.EquivalentString[stemp, MDModel.Sym[sp]] THEN RETURN[FALSE];
CWF.WF1["**: %s"L, MDModel.Sym[sptype]];
sp.print ← TRUE;
RETURN[TRUE];
};
-- procedures to generate config's
-- if outsh = NIL then print on IOStream
-- fileparameters may be NIL
MakeConfig: PUBLIC PROC[spmodel: MDModel.MODELSymbol,
symbolseq: MDModel.SymbolSeq, outsh: Stream.Handle,
createtime: LONG CARDINAL, ttyout: IO.Handle, fileparameters: LONG STRING] = {
spappl: MDModel.APPLSymbol;
ConfigSh: PROC[ch: CHAR] = {
IF outsh = NIL THEN ttyout.PutChar[ch]
ELSE Stream.PutChar[outsh, ch];
};
savespmodel ← spmodel;
SetAllPrint[FALSE, symbolseq];
-- this gives MakeConfig the widest latitude in deciding
-- what to name things
FOR i: CARDINAL IN [0 .. symbolseq.size) DO
IF symbolseq[i].stype = typeAPPL THEN {
spappl ← MDModel.NarrowToAPPL[@symbolseq[i]];
IF spappl.configname ~= NIL THEN {
Subr.FreeString[spappl.configname];
spappl.configname ← NIL;
};
};
ENDLOOP;
IF createtime ~= 0 THEN {
str: STRING ← [100];
CWF.SWF1[str, "--%lu\n"L, @createtime];
IF outsh = NIL THEN ttyout.Put[IO.string[str]]
ELSE FOR i: CARDINAL IN [0 .. str.length) DO
Stream.PutChar[outsh, str[i]];
ENDLOOP;
};
[] ← PrintConfig[spmodel.model,";\n"L, ConfigSh, symbolseq, fileparameters];
};
-- returns TRUE if it printed anything, FALSE otherwise
PrintConfig: PROC[p: MDModel.Symbol, sep: STRING, ConfigSh: PROC[CHAR],
symbolseq: MDModel.SymbolSeq, fileparameters: LONG STRING]
RETURNS[BOOL] = {
fprint: BOOL ← FALSE;
isanimport: BOOL ← FALSE;
ProcPrintConfig: PROC[sp: MDModel.Symbol] = {
IF fprint THEN CWF.FWF0[ConfigSh,sep];
fprint ← PrintConfig[sp,sep, ConfigSh, symbolseq, fileparameters];
};
HandleArgsProc: PROC[sp: MDModel.Symbol] = {
spappl: MDModel.APPLSymbol;
IF sp = NIL OR sp.stype ~= typeAPPL THEN RETURN;
spappl ← MDModel.NarrowToAPPL[sp];
IF fprint THEN CWF.FWF0[ConfigSh,-- ", "L-- sep];
spappl.configname ← PickInterfaceName[spappl, symbolseq, isanimport];
CWF.FWF1[ConfigSh,"%s"L, spappl.configname];
fprint ← TRUE;
};
IF p = NIL THEN {
CWF.FWF0[ConfigSh,"{p is NIL}"L];
RETURN[FALSE];
};
IF p.stype = typeLOC OR p.stype = typeTYPE THEN RETURN[FALSE];
IF NOT p.print THEN WITH pt: p SELECT FROM
typePROC => {
CWF.FWF1[ConfigSh,"%s: CONFIGURATION "L,pt.procsym];
sep ← ", "L;
isanimport ← TRUE;
IF pt.procparm ~= NIL THEN {
CWF.FWF0[ConfigSh,"\n IMPORTS "L];
fprint ← FALSE;
MDModel.TraverseList[pt.procparm,HandleArgsProc];
};
isanimport ← FALSE;
IF pt.procret ~= NIL THEN {
CWF.FWF0[ConfigSh,"\n EXPORTS "L];
fprint ← FALSE;
MDModel.TraverseList[pt.procret,HandleArgsProc];
};
PrintControl[ConfigSh, symbolseq, p];
IF pt.procval ~= NIL THEN {
CWF.FWF0[ConfigSh," = {\n"L];
[] ← PrintConfig[pt.procval,";\n"L, ConfigSh, symbolseq, fileparameters];
CWF.FWF0[ConfigSh,"\n}.\n"L];
};
p.print ← TRUE;
fprint ← TRUE;
};
typeSTRING => CWF.FWF1[ConfigSh,"%s"L,pt.strval];
typeAPPL => {
IF FramePointerSpecialCase[p, ConfigSh, symbolseq,
fileparameters, HandleArgsProc, HandleVal] THEN RETURN[TRUE];
pt.configname ← PickInterfaceName[MDModel.NarrowToAPPL[p], symbolseq, FALSE];
IF pt.appltype ~= symbolseq.controlv THEN {
CWF.FWF1[ConfigSh,"%s ← "L,pt.configname];
fprint ← TRUE;
};
IF pt.applval ~= NIL THEN {
IF pt.applval.stype = typeLIST
AND MDModel.NarrowToLIST[pt.applval].listtype ~= normal THEN {
lp: MDModel.LISTSymbol ← MDModel.NarrowToLIST[pt.applval];
oldsep: STRING ← sep;
fprint ← FALSE;
sep ← IF lp.listtype = plus THEN " PLUS "L
ELSE IF lp.listtype=then THEN " THEN "L
ELSE sep;
MDModel.TraverseList[lp,HandleArgsProc];
sep ← oldsep;
}
ELSE IF pt.applval.stype = typeLOC THEN
fprint ← HandleVal[MDModel.NarrowToLOC[pt.applval],
ConfigSh, symbolseq, fileparameters]
ELSE fprint ← FALSE;
};
p.print ← TRUE;
};
typeLIST => {
oldsep: STRING ← sep;
fprint ← FALSE;
sep ← IF pt.listtype = plus THEN " PLUS "L
ELSE IF pt.listtype = then THEN " THEN "L
ELSE sep;
MDModel.TraverseList[MDModel.NarrowToLIST[p],
IF pt.listtype = normal THEN ProcPrintConfig ELSE HandleArgsProc];
sep ← oldsep;
};
typeLET => {
sep ← ", "L;
fprint ← FALSE;
IF FramePointerSpecialCase[p, ConfigSh, symbolseq,
fileparameters, HandleArgsProc, HandleVal] THEN RETURN[TRUE];
CWF.FWF0[ConfigSh, "["L];
MDModel.TraverseList[pt.letgrp, HandleArgsProc];
CWF.FWF0[ConfigSh,"] ← "L];
IF pt.letval ~= NIL AND pt.letval.stype = typeLOC THEN
fprint ← HandleVal[MDModel.NarrowToLOC[pt.letval], ConfigSh,
symbolseq, fileparameters];
};
typeTYPE, typeLOC, typeOPEN, typeMODEL => NULL;
ENDCASE => ERROR; -- bad select PrintConfig
RETURN[fprint];
};
PickInterfaceName: PROC[spappl: MDModel.APPLSymbol, symbolseq: MDModel.SymbolSeq,
isanimport: BOOL] RETURNS[configname: LONG STRING] = {
fi: Dir.FileInfo;
sptype: MDModel.TYPESymbol;
IF spappl.appltype = symbolseq.controlv THEN RETURN[NIL];
IF spappl.configname ~= NIL THEN RETURN[spappl.configname];
sptype ← MDModel.NarrowToTYPE[spappl.appltype];
IF sptype.frameptr THEN {
sploc: MDModel.LOCSymbol;
sploc ← MDModel.LocForType[sptype];
IF sploc ~= NIL THEN {
fi ← MDModel.GetFileInfo[sploc];
IF fi.moduleName ~= NIL THEN
RETURN[Subr.CopyString[fi.moduleName]];
};
RETURN[Subr.CopyString["FRAMEPTR"L]];
};
-- given that its not a POINTER TO FRAME,
-- for the special case where the record can't be named
-- the same as the module it implements;
-- because the Binder can't handle XImpl ← XImpl[Y];
IF spappl.applval ~= NIL AND spappl.applval.stype = typeLOC
AND LongString.EquivalentString[spappl.applsym,
MDModel.NarrowToLOC[spappl.applval].tail] THEN {
configname ← Subr.CopyString[MDModel.Sym[spappl.appltype]];
RETURN[configname];
};
-- nor can it handle [XImpl, ZImpl] ← XImpl[Y]
IF spappl.applval = NIL THEN {
splet: MDModel.LETSymbol;
-- splet ← LetParentOf[spappl, symbolseq];
splet ← spappl.letparent;
IF splet ~= NIL AND splet.letval ~= NIL
AND splet.letval.stype = typeLOC
AND LongString.EquivalentString[spappl.applsym,
MDModel.NarrowToLOC[splet.letval].tail] THEN {
configname ← Subr.CopyString[MDModel.Sym[spappl.appltype]];
RETURN[configname];
};
};
-- for imports and exports to the config where the names are crucial
IF isanimport THEN
configname ← Subr.CopyString[MDModel.Sym[spappl.appltype]]
ELSE
configname ← Subr.CopyString[spappl.applsym];
};
FramePointerSpecialCase: PROC[sp: MDModel.Symbol,
ConfigSh: PROC[CHAR], symbolseq: MDModel.SymbolSeq,
fileparameters: LONG STRING,
handleArgsProc: PROC[MDModel.Symbol],
handleVal: PROC[MDModel.LOCSymbol, PROC[CHAR],
MDModel.SymbolSeq, LONG STRING]
RETURNS[BOOL]]
RETURNS[isaspecialcase: BOOL] = {
spappl: MDModel.APPLSymbol;
sptype: MDModel.TYPESymbol;
isaspecialcase ← FALSE;
IF sp.stype = typeAPPL THEN {
spappl ← MDModel.NarrowToAPPL[sp];
sptype ← MDModel.NarrowToTYPE[spappl.appltype];
IF sptype.frameptr THEN {
sploc: MDModel.LOCSymbol;
fi: Dir.FileInfo;
sploc ← MDModel.NarrowToLOC[sptype.typeval];
fi ← MDModel.GetFileInfo[sploc];
CWF.FWF1[ConfigSh, "%s"L, IF fi.moduleName ~= NIL THEN
fi.moduleName ELSE sploc.tail];
isaspecialcase ← TRUE;
};
}
ELSE IF sp.stype = typeLET THEN {
numleft: CARDINAL;
framet: MDModel.TYPESymbol;
splet: MDModel.LETSymbol;
splet ← MDModel.NarrowToLET[sp];
[isaspecialcase, framet, numleft] ← FramePtrLet[splet];
IF isaspecialcase THEN {
CWF.WF1["%s is a special case.\n"L, framet.typesym];
IF numleft > 0 THEN {
splist: MDModel.LISTSymbol;
splist ← splet.letgrp;
CWF.FWF0[ConfigSh, "["L];
WHILE splist ~= NIL DO
IF splist.first ~= framet
AND MDModel.NarrowToAPPL[splist.first].appltype
~= framet THEN
handleArgsProc[splist.first];
splist ← splist.rest;
ENDLOOP;
CWF.FWF0[ConfigSh, "] ← "L];
};
[] ← HandleVal[MDModel.NarrowToLOC[splet.letval], ConfigSh,
symbolseq, fileparameters];
};
};
};
FramePtrLet: PROC[splet: MDModel.LETSymbol]
RETURNS[isaspecialcase: BOOL, framet: MDModel.TYPESymbol,
numleft: CARDINAL] = {
splist: MDModel.LISTSymbol;
isaspecialcase ← FALSE;
numleft ← 0;
framet ← NIL;
splist ← splet.letgrp;
WHILE splist ~= NIL DO
IF splist.first.stype = typeTYPE
AND MDModel.NarrowToTYPE[splist.first].frameptr THEN {
framet ← MDModel.NarrowToTYPE[splist.first];
EXIT;
};
splist ← splist.rest;
ENDLOOP;
IF splist = NIL THEN RETURN;
splist ← splet.letgrp;
WHILE splist ~= NIL DO
IF splist.first.stype = typeAPPL
AND MDModel.NarrowToAPPL[splist.first].appltype = framet THEN EXIT;
splist ← splist.rest;
ENDLOOP;
IF splist = NIL THEN RETURN;
isaspecialcase ← TRUE;
splist ← splet.letgrp;
WHILE splist ~= NIL DO
numleft ← numleft + 1;
splist ← splist.rest;
ENDLOOP;
numleft ← numleft - 2;
};
-- returns TRUE if something was printed
HandleVal: PROC[sploc: MDModel.LOCSymbol, ConfigSh: PROC[CHAR],
symbolseq: MDModel.SymbolSeq, fileparameters: LONG STRING]
RETURNS[fprint: BOOL] = {
s: LONG STRING;
fi: Dir.FileInfo;
HandleArgsProc: PROC[sp: MDModel.Symbol] = {
spappl: MDModel.APPLSymbol;
IF sp = NIL OR sp.stype ~= typeAPPL THEN RETURN;
spappl ← MDModel.NarrowToAPPL[sp];
IF fprint THEN CWF.FWF0[ConfigSh,", "L];
spappl.configname ← PickInterfaceName[spappl, symbolseq, FALSE];
CWF.FWF1[ConfigSh,"%s"L,spappl.configname];
fprint ← TRUE;
};
HandleHiddenImports: PROC = {
depseqbcd, depseqsrc: Dir.DepSeq;
bcdname: STRING ← [100];
sourcename: STRING ← [100];
lastsrc, start: CARDINAL;
IF MakeSource = NIL THEN RETURN;
IF NOT LongString.EquivalentString[sploc.sext, "Mesa"L] THEN RETURN;
CWF.SWF1[bcdname, "%s.BCD"L, sploc.tail];
CWF.SWF1[sourcename, "%s.Mesa"L, sploc.tail];
depseqsrc ← MakeSource[sourcename];
IF depseqsrc = NIL THEN RETURN;
depseqbcd ← MakeBinary[bcdname];
IF depseqbcd = NIL THEN RETURN;
FOR j: CARDINAL DECREASING IN [0 .. depseqsrc.size) DO
IF depseqsrc[j].relation = imports THEN {
lastsrc ← j;
EXIT;
};
REPEAT
FINISHED => RETURN;
ENDLOOP;
FOR i: CARDINAL IN [0 .. depseqbcd.size) DO
IF depseqbcd[i].relation = imports
AND LongString.EquivalentString[depseqsrc[lastsrc].moduleName,
depseqbcd[i].moduleName] THEN {
start ← i;
EXIT;
};
REPEAT
FINISHED => RETURN;
ENDLOOP;
FOR i: CARDINAL IN [start+1 .. depseqbcd.size) DO
IF depseqbcd[i].relation = imports THEN {
spappl: MDModel.APPLSymbol;
[spappl] ← MDModel.LookForInstBcd[depseqbcd[i].bcdFileName,
depseqbcd[i].bcdVers, symbolseq, savespmodel, NIL];
IF spappl ~= NIL THEN HandleArgsProc[spappl];
};
ENDLOOP;
};
fprint ← FALSE;
fi ← MDModel.GetFileInfo[sploc];
s ← IF fi.moduleName ~= NIL THEN fi.moduleName ELSE sploc.tail;
CWF.FWF1[ConfigSh, "%s["L, s];
IF fi.bcdFileName ~= NIL AND fileparameters ~= NIL THEN {
stemp: STRING ← [100];
CWF.SWF3[stemp, "%s%s: %s"L, IF fileparameters.length = 0 THEN ""L ELSE ", "L,
s, fi.bcdFileName];
LongString.AppendString[fileparameters, stemp];
};
MDModel.TraverseList[sploc.parmlist,HandleArgsProc];
HandleHiddenImports[];
CWF.FWF0[ConfigSh,"]"L];
fprint ← TRUE;
};
-- has the side effect of setting controlloc
PrintControl: PROC[ConfigSh: PROC[CHAR], symbolseq: MDModel.SymbolSeq,
sproot: MDModel.Symbol] = {
once: BOOL ← FALSE;
ProcAnal: PROC[spa: MDModel.Symbol, spmodel: MDModel.MODELSymbol]
RETURNS[proceed: BOOL ← TRUE] = {
spappl: MDModel.APPLSymbol;
-- this avoids searching into the nested models
IF spa.stype = typePROC AND controlloc ~= NIL THEN RETURN[FALSE];
IF spa.stype ~= typeAPPL THEN RETURN;
spappl ← MDModel.NarrowToAPPL[spa];
IF spappl.applsym ~= NIL
AND spappl.appltype = symbolseq.controlv THEN {
s: LONG STRING;
fi: Dir.FileInfo;
IF spappl.applval.stype ~= typeLOC THEN
CWF.WF0["Control error\n"L];
controlloc ← MDModel.NarrowToLOC[spappl.applval];
fi ← MDModel.GetFileInfo[controlloc];
s ← IF fi.moduleName ~= NIL THEN fi.moduleName
ELSE controlloc.tail;
IF NOT once THEN CWF.FWF1[ConfigSh,"\n CONTROL %s"L,s]
ELSE CWF.FWF1[ConfigSh,", %s"L,s];
once ← TRUE;
};
RETURN[TRUE];
};
controlloc ← NIL;
MDModel.TraverseTree[sproot, symbolseq, ProcAnal, TRUE];
IF NOT once THEN CWF.WF0["Warning - no CONTROL module\n"L]
ELSE CWF.FWF0[ConfigSh, "\n"L];
};
SetAllPrint: PROC[f: BOOL, symbolseq: MDModel.SymbolSeq] = {
FOR i: CARDINAL IN [0..symbolseq.size) DO
symbolseq[i].print ← f;
ENDLOOP;
};
-- from [Igor]<PreCascade>Utilities>CascadeExec.Mesa
-- Compiler-specific feedback stuff
MSGTTYProc: PROC[ch: CHAR] = {
globalmsgout.PutChar[ch];
};
StartBinding: Feedback.CreateProc = {
binderState ← normal;
CWF.WF1["\n%s"L, herald];
RETURN[NIL]
};
DoneBinding: Feedback.DestroyProc = {
IF trailer # NIL THEN CWF.WF1["%s"L, trailer];
CWF.WFCR[];
};
NewBinderSource: Feedback.BeginItemProc = {
CWF.FWF1[MSGTTYProc, "\n%s"L, item]};
NextBinderPass: Feedback.NoteProgressProc = {
SELECT state FROM
98 --warning-- => {
IF binderState = normal THEN
{CWF.FWF0[MSGTTYProc, " warnings "L]; binderState ← warnings}};
99 --error-- => {
IF binderState = normal OR binderState = warnings THEN
{CWF.FWF0[MSGTTYProc, " errors "L]; binderState ← errors}};
ENDCASE => CWF.FWFC[MSGTTYProc, '.]};
EndOfBinderSource: Feedback.FinishItemProc = {
CWF.FWFC[MSGTTYProc, ' ];
IF trailer # NIL THEN CWF.FWF1[MSGTTYProc, "%s"L, trailer]
};
RunBinder: PUBLIC PROC[cmd: STRING, typeScript: TypeScript.TS,
ttyin, ttyout, msgout: IO.Handle, confirm: REF BOOL]
RETURNS[outcome: ExecOps.Outcome] = {
binderFeedback: Feedback.Procs ← [create: StartBinding, destroy: DoneBinding,
beginItem: NewBinderSource, noteProgress: NextBinderPass,
finishItem: EndOfBinderSource];
cmd1: LONG STRING;
command: ExecOps.Command; -- PACKED ARRAY [0..900) OF CHAR;
dontconfirm: BOOL ← IF confirm = NIL THEN FALSE ELSE NOT (confirm↑);
globalmsgout ← msgout;
outcome ← aborted;
-- FOR i: CARDINAL IN [0 .. cmd.length) DO
-- command[i] ← cmd[i];
-- ENDLOOP;
CWF.WF1["Bind %s ... "L, cmd];
cmd[cmd.length] ← Ascii.CR;
cmd.length ← cmd.length + 1;
-- argghh!!!
cmd1 ← cmd;
command ← LOOPHOLE[cmd1+2];
IF dontconfirm OR IOConfirm['y, ttyin, ttyout] = 'y THEN {
CWF.WF0["Yes.\n"L];
IF LoadBinder[] THEN {
CWF.WF0["Binding ... "L];
AcquireMsgLock[];
outcome ← TemporarySpecialExecOps.BindUsingFeedback[
command, @binderFeedback
! UNWIND => ReleaseMsgLock[]];
ReleaseMsgLock[];
PrintOutcome[outcome];
IF outcome ~= ok AND outcome ~= aborted THEN {
logsh: Stream.Handle;
logsh ← Subr.NewStream["Binder.Log"L, Subr.Read];
WHILE NOT FileStream.EndOf[logsh] DO
IF TypeScript.UserAbort[typeScript]THEN {
CWF.WF0["\nAborted.\n"L];
EXIT;
};
ttyout.PutChar[Stream.GetChar[logsh]];
ENDLOOP;
TypeScript.ResetUserAbort[typeScript];
Stream.Delete[logsh];
};
};
}
ELSE CWF.WF0["No.\n"L];
globalmsgout ← NIL;
};
LoadBinder: PROC RETURNS[success: BOOL] = {
cap: File.Capability;
success ← TRUE;
IF Runtime.IsBound[ExecOps.Bind] THEN RETURN[TRUE]; -- already loaded
CWF.WF0["Loading ... "L];
{
ENABLE ANY => { CWF.WF0["failed.\n"L]; GOTO out};
cap ← Directory.Lookup["binder.bcd"L];
Runtime.RunConfig[file: cap, offset: 1, codeLinks: TRUE];
CWF.WF0["done.\n"L];
EXITS
out => success ← FALSE;
}};
PrintOutcome: PROC[o: ExecOps.Outcome] = {
CWF.WF0[SELECT o FROM
ok => "ok"L,
warnings => "warnings"L,
errors => "errors"L,
errorsAndWarnings => "errorsAndWarnings"L,
aborted => "aborted"L,
ENDCASE => ERROR];
CWF.WFCR[]
};
ModelCreateProperty: Directory.PropertyType = LOOPHOLE[217B];
SetModelCreateProperty: PUBLIC PROC[configcap: File.Capability,
create: LONG CARDINAL] = {
Directory.PutProperty[configcap, ModelCreateProperty,
DESCRIPTOR[@create, SIZE[LONG CARDINAL]], TRUE];
};
-- returns 0 if there is no such property
GetModelCreateProperty: PUBLIC PROC[configcap: File.Capability]
RETURNS[create: LONG CARDINAL] = {
arr: ARRAY[0 .. 1) OF LONG CARDINAL; -- to get around a bug
Directory.GetProperty[configcap, ModelCreateProperty,
DESCRIPTOR[BASE[arr], SIZE[LONG CARDINAL]]
! Directory.Error => IF type = invalidProperty THEN GOTO leave];
create ← arr[0];
EXITS
leave => create ← 0;
};
SupportInit: PUBLIC PROC[symbolseq: MDModel.SymbolSeq, typeScript: TypeScript.TS,
ttyout: IO.Handle] = {
ss ← symbolseq;
officialwindow ← ttyout;
globalTypeScript ← typeScript;
CWF.SetCode['v, CWFVRoutine];
CWF.SetCode['z, CWFZRoutine];
};
CWFVRoutine: PROC[uns: LONG POINTER, form: LONG STRING, wp: PROC[CHAR]] = {
p: LONG POINTER TO TimeStamp.Stamp ← uns;
net: CARDINAL ← p.net;
host: CARDINAL ← p.host;
IF p.time = 0 THEN
CWF.FWF2[wp, "(%u#%u#,Null)"L, @net, @host]
ELSE CWF.FWF3[wp, "(%u#%u#,%lt)"L, @net, @host, @p.time];
};
CWFZRoutine: PROC[uns: LONG POINTER, form: LONG STRING, wp: PROC[CHAR]] = {
sp: MDModel.Symbol ← uns;
IF ss = NIL THEN ERROR;
IF officialwindow = NIL THEN ERROR;
PrintNewModelStream[ss,sp, NIL, NIL, FALSE, globalTypeScript, officialwindow];
};
}.