-- MDSubrImpl.Mesa
-- last edit January 4, 1983 1:30 pm
-- last edit May 22, 1983 4:49 pm, Russ Atkinson
-- Pilot 6.0/ Mesa 7.0
DIRECTORY
CWF: TYPE USING [FWF0, FWF1, SWF1, SWF2, SWF3, WF0, WF1, WF2],
LongString: TYPE USING [EquivalentString],
IO: TYPE USING[PutChar],
MDSubr: TYPE USING [AddToLook, entNil, Entry, EntrySeq, HUGEDEPLIST, Look, lookNil,
LookSeq, LookupOtherSym, SMALLDEPLIST, StringSeq, WalkTheGraph],
Stream: TYPE USING [Handle, PutChar],
String: TYPE USING [AppendString],
Subr: TYPE USING [CopyString, EndsIn, FreeString, PackedTime,
strcpy, SubStrCopy, TTYProcs],
Time: TYPE USING [Current];
MDSubrImpl: PROGRAM
IMPORTS CWF, IO, LongString, MDSubr, Stream, String, Subr, Time
EXPORTS MDSubr = {
-- no MDS USAGE !!!
-- utilities
StripFirstWord: PUBLIC PROC[str, result: LONG STRING] = {
i: CARDINAL ← 0;
WHILE i < str.length AND i <result.maxlength DO
IF str[i] = ' THEN EXIT;
result[i] ← str[i];
i ← i + 1;
ENDLOOP;
result.length ← i;
Subr.SubStrCopy[str,str,i];
};
-- having to do with EntrySeq's
PrintEntries: PUBLIC PROC[entryseq: MDSubr.EntrySeq, sh: Stream.Handle,
stringseq: MDSubr.StringSeq, ttyhandle: Subr.TTYProcs] = {
i: CARDINAL;
j: CARDINAL;
ent, entchild: MDSubr.Entry;
stemp: STRING ← [200];
str: LONG STRING;
date: Subr.PackedTime ← Time.Current[];
WFsh: PROC[ch: CHAR] = {
IF sh = NIL THEN ttyhandle.out.PutChar[ch]
ELSE Stream.PutChar[sh, ch];
};
CWF.FWF1[WFsh, "-- created %lt\n"L, @date];
IF (str ← MDSubr.LookupOtherSym["PATH"L, stringseq]) ~= NIL THEN
CWF.FWF1[WFsh, "PATH = %s\n"L, str];
IF (str ← MDSubr.LookupOtherSym["MESACOMP"L, stringseq]) ~= NIL THEN
CWF.FWF1[WFsh, "MESACOMP = %s\n"L, str];
IF (str ← MDSubr.LookupOtherSym["MESABIND"L, stringseq]) ~= NIL THEN
CWF.FWF1[WFsh, "MESABIND = %s\n"L, str];
FOR i IN [0.. stringseq.size) DO
IF LongString.EquivalentString[stringseq[i].val, "local"L] THEN
CWF.FWF1[WFsh, "%s = local\n"L, stringseq[i].str];
ENDLOOP;
CWF.FWF0[WFsh,"\n"L];
FOR i IN [0..entryseq.size) DO
ent ← @entryseq[i];
IF ent.rule = NIL AND ent.depends[0] = MDSubr.entNil THEN LOOP;
-- CWF.WF3["Entry %d: '%s', Rule '%s'\n"L,@i,ent.name,ent.rule];
CWF.FWF1[WFsh,"%s:"L,ent.name];
j ← 0;
DO
IF ent.depends[j] = MDSubr.entNil THEN EXIT;
-- WF.WF1[" Depends on %d\n"L,@ent.depends[j]];
entchild ← @entryseq[ent.depends[j]];
CWF.FWF1[WFsh," %s"L,entchild.name];
j ← j + 1;
ENDLOOP;
CWF.FWF0[WFsh,"\n"L];
IF ent.rule ~= NIL THEN CWF.FWF1[WFsh,"= %s\n"L,ent.rule];
CWF.FWF0[WFsh,"\n"L];
ENDLOOP;
};
GetAnEntry: PUBLIC PROC[name: LONG STRING, entryseq: MDSubr.EntrySeq]
RETURNS[i: CARDINAL, new: BOOL] = {
FOR i IN [0..entryseq.size) DO
IF LongString.EquivalentString[name,entryseq[i].name] THEN
RETURN[i,FALSE];
ENDLOOP;
IF entryseq.size >= entryseq.maxsize THEN {
m: CARDINAL ← entryseq.maxsize;
CWF.WF1["Error - too many dependency entries > %d\n"L,@m]
}
ELSE {
-- other fields are defaulted
entryseq[entryseq.size] ← [name: Subr.CopyString[name, entryseq.entryzone],
depends: DESCRIPTOR[NIL, 0]];
entryseq[entryseq.size].depends ← DESCRIPTOR[entryseq.entryzone.NEW[
ARRAY[0..MDSubr.SMALLDEPLIST) OF CARDINAL], MDSubr.SMALLDEPLIST];
entryseq[entryseq.size].depends[0] ← MDSubr.entNil;
entryseq.size ← entryseq.size + 1;
};
RETURN[entryseq.size-1,TRUE];
};
AddToDepends: PUBLIC PROC[parent, child: CARDINAL, entryseq: MDSubr.EntrySeq] = {
i, max, len, inx: CARDINAL;
saved: LONG DESCRIPTOR FOR ARRAY OF CARDINAL;
entry: MDSubr.Entry;
temp: CARDINAL;
p: LONG POINTER;
IF parent = MDSubr.entNil THEN RETURN;
i ← 0;
len ← LENGTH[entryseq[parent].depends];
max ← len - 1;
entry ← @entryseq[parent];
WHILE i < max DO
inx ← entry.depends[i];
IF inx = child THEN RETURN; -- already there
IF inx = MDSubr.entNil THEN EXIT;
i ← i + 1;
REPEAT
FINISHED => {
-- CWF.WF1["Extending %s\n"L, entry.name];
IF len >= MDSubr.HUGEDEPLIST THEN {
CWF.WF0["Error - too many depends\n"L];
RETURN;
};
saved ← entry.depends;
p ← entryseq.entryzone.NEW[ARRAY[0..MDSubr.HUGEDEPLIST) OF CARDINAL];
entry.depends ← DESCRIPTOR[p,MDSubr.HUGEDEPLIST];
FOR i IN [0..LENGTH[saved]) DO
temp ← saved[i];
entry.depends[i] ← temp;
ENDLOOP;
i ← max;
p ← BASE[saved];
-- no frees allowed
-- longzone.FREE[@p];
};
ENDLOOP;
entry.depends[i] ← child;
entry.depends[i+1] ← MDSubr.entNil;
};
FreeEntrySeq: PUBLIC PROC[pentryseq: LONG POINTER TO MDSubr.EntrySeq] = {
entry: MDSubr.Entry;
longp: LONG POINTER;
IF pentryseq^ = NIL THEN RETURN;
IF FALSE THEN
-- no frees allowed
FOR i: CARDINAL IN [0..pentryseq^.size) DO
entry ← @(pentryseq^)[i];
Subr.FreeString[entry.name];
Subr.FreeString[entry.rule];
longp ← BASE[entry.depends];
-- IF longp ~= NIL THEN longzone.FREE[@longp];
entry^ ← [depends: DESCRIPTOR[NIL,0]];
ENDLOOP;
-- longzone.FREE[pentryseq];
pentryseq^ ← NIL;
};
-- proc is only called once for each node that is connected to firstinx
WalkTheGraph: PUBLIC PROC[firstinx: CARDINAL, entryseq:MDSubr.EntrySeq,
proc: PROC[MDSubr.Entry]] = {
RecurseThru: PROC[inx: CARDINAL, entryseq:MDSubr.EntrySeq,
proc: PROC[MDSubr.Entry]] = {
i: CARDINAL;
entry: MDSubr.Entry ← @entryseq[inx];
IF entry.visited THEN RETURN;
proc[entry]; -- call the users proc
entry.visited ← TRUE;
i ← 0;
WHILE entry.depends[i] ~= MDSubr.entNil DO
-- the recursive call
RecurseThru[entry.depends[i], entryseq, proc];
i ← i + 1;
ENDLOOP;
};
FOR i: CARDINAL IN [0 .. entryseq.size) DO
entryseq[i].visited ← FALSE;
ENDLOOP;
RecurseThru[firstinx, entryseq, proc];
};
-- look for a specific case of a .bcd depending on both a .config
-- and .mesa file
ThrowAwayLeaves: PUBLIC PROC[firstinx: CARDINAL, entryseq: MDSubr.EntrySeq,
lookseq: MDSubr.LookSeq, ismodel: BOOL] = {
RecurThrowAwayLeaves: PROC[entry: MDSubr.Entry] = {
i, j1, j2: CARDINAL;
lookj1, lookj2: MDSubr.Look;
IF ismodel AND Subr.EndsIn[entry.name, ".bcd"L] THEN {
i ← 0;
lookj1 ← NIL;
WHILE (j1 ← entry.depends[i]) ~= MDSubr.entNil DO
IF (Subr.EndsIn[entryseq[j1].name,".config"L]
OR Subr.EndsIn[entryseq[j1].name, ".mesa"L]) THEN {
lookj1 ← @lookseq[entryseq[j1].lookinx];
IF lookj1.presentonlocaldisk THEN RETURN;
};
i ← i + 1;
ENDLOOP;
-- if there was a .mesa or .config, and not on disk, then
-- throw out
IF lookj1 ~= NIL THEN {
entry.depends[0] ← MDSubr.entNil;
entry.rule ← NIL
};
}
ELSE {
IF Subr.EndsIn[entry.name, ".bcd"L]
AND (j1 ← entry.depends[0]) ~= MDSubr.entNil
AND (j2 ← entry.depends[1]) ~= MDSubr.entNil
AND entry.depends[2] = MDSubr.entNil
AND Subr.EndsIn[entryseq[j1].name,".config"L]
AND Subr.EndsIn[entryseq[j2].name, ".mesa"L] THEN {
lookj1 ← @lookseq[entryseq[j1].lookinx];
lookj2 ← @lookseq[entryseq[j2].lookinx];
IF NOT lookj1.presentonlocaldisk
AND NOT lookj2.presentonlocaldisk THEN
entry.depends[0] ← MDSubr.entNil
ELSE IF lookj1.presentonlocaldisk
AND NOT lookj2.presentonlocaldisk THEN
entry.depends[1] ← MDSubr.entNil
ELSE IF NOT lookj1.presentonlocaldisk
AND lookj2.presentonlocaldisk THEN {
entry.depends[0] ← j2;
entry.depends[1] ← MDSubr.entNil
};
};
};
};
FOR i: CARDINAL IN [0.. entryseq.size) DO
entryseq[i].visited ← FALSE;
ENDLOOP;
MDSubr.WalkTheGraph[firstinx, entryseq, RecurThrowAwayLeaves];
};
CheckNames: PUBLIC PROC[entryseq: MDSubr.EntrySeq, lookseq: MDSubr.LookSeq] = {
look: MDSubr.Look;
header: BOOL ← FALSE;
FOR i: CARDINAL IN [0..entryseq.size) DO
IF entryseq[i].lookinx ~= MDSubr.lookNil THEN {
look ← @lookseq[entryseq[i].lookinx];
IF NOT LongString.EquivalentString[look.name, entryseq[i].name]
THEN {
IF NOT header THEN {
CWF.WF0["Errors in look vs entry:\n"L];
header ← TRUE;
};
CWF.WF2["Err - look %s entry %s\n"L, look.name,
entryseq[i].name];
};
};
ENDLOOP;
-- CWF.WF0["Looks ok to me\n"L];
};
ConvertToLook: PUBLIC PROC[entryseq: MDSubr.EntrySeq, lookseq: MDSubr.LookSeq] = {
FOR i: CARDINAL IN [0..entryseq.size) DO
IF entryseq[i].lookinx = MDSubr.lookNil THEN {
entryseq[i].lookinx ← lookseq.size;
[] ← MDSubr.AddToLook[entryseq[i].name, lookseq];
};
ENDLOOP;
};
InsertOtherSym: PUBLIC PROC[str, val: LONG STRING, stringseq: MDSubr.StringSeq] = {
IF stringseq.size >= stringseq.maxsize THEN CWF.WF0["too many other syms\n"L]
ELSE {
stringseq[stringseq.size].str ← Subr.CopyString[str];
stringseq[stringseq.size].val ← Subr.CopyString[val];
stringseq.size ← stringseq.size + 1;
};
RETURN;
};
-- return the value corresponding to "str"
-- searches backwards to allow users to redefine the strings
LookupOtherSym: PUBLIC PROC[str: LONG STRING, stringseq: MDSubr.StringSeq]
RETURNS[LONG STRING] = {
FOR i: CARDINAL DECREASING IN [0..stringseq.size) DO
IF LongString.EquivalentString[str,stringseq[i].str] THEN
RETURN[stringseq[i].val];
ENDLOOP;
RETURN[NIL];
};
GetCompilerRule: PUBLIC PROC[stringseq: MDSubr.StringSeq, name: LONG STRING,
zone: UNCOUNTED ZONE] RETURNS[LONG STRING] = {
comprule: STRING ← [100];
str: LONG STRING;
pat: STRING ← [100];
count: CARDINAL ← 0;
str ← MDSubr.LookupOtherSym["PILOTMESACOMP"L, stringseq];
IF str = NIL THEN
str ← MDSubr.LookupOtherSym["MESACOMP"L, stringseq];
Subr.strcpy[pat, str];
FOR i: CARDINAL IN [0..pat.length) DO
IF pat[i] = '% THEN count ← count + 1;
ENDLOOP;
IF count = 0 THEN String.AppendString[pat, " %s"L];
IF count > 3 THEN CWF.WF1["Too many %% in '%s'\n"L, pat]
ELSE IF count = 3 THEN CWF.SWF3[comprule, pat, name, name, name]
ELSE IF count = 2 THEN CWF.SWF2[comprule, pat, name, name]
ELSE CWF.SWF1[comprule, pat, name];
RETURN[Subr.CopyString[comprule, zone]];
};
GetBinderRule: PUBLIC PROC[stringseq: MDSubr.StringSeq, name: LONG STRING,
zone: UNCOUNTED ZONE] RETURNS[LONG STRING] = {
comprule: STRING ← [100];
str: LONG STRING;
pat: STRING ← [100];
count: CARDINAL ← 0;
i: CARDINAL;
str ← MDSubr.LookupOtherSym["PILOTMESABIND"L, stringseq];
IF str = NIL THEN
str ← MDSubr.LookupOtherSym["MESABIND"L, stringseq];
Subr.strcpy[pat, str];
FOR i IN [0..pat.length) DO
IF pat[i] = '% THEN count ← count + 1;
ENDLOOP;
IF count = 0 THEN String.AppendString[pat, " %s"L];
IF count > 3 THEN CWF.WF1["Too many %% in '%s'\n"L, pat]
ELSE IF count = 3 THEN CWF.SWF3[comprule, pat, name, name, name]
ELSE IF count = 2 THEN CWF.SWF2[comprule, pat, name, name]
ELSE CWF.SWF1[comprule, pat, name];
RETURN[Subr.CopyString[comprule, zone]];
};
}.
IDEAS
1. comments in line.cm for error messages