-- File: [Thyme]<Thyme>System>CSIM01>spGlobalsimpl.mesa
-- Last editted:
-- by Barth, July 11, 1983 12:19 PM
-- SChen April 19, 1983 1:45 PM
-- Wilhelm April 27, 1982 4:05 PM, reformated by Barth and stored under
-- [Cherry]<Barth>Thyme>1.97> .
-- Details at end of file.
DIRECTORY spGlobals, AltoDefs, CWF, IODefs, StreamDefs,
StringDefs, ComLineDefs, AbsAllocDefs;
spGlobalsImpl: PROGRAM
IMPORTS spGlobals, CWF, StreamDefs, StringDefs, ComLineDefs,
A: AbsAllocDefs
EXPORTS spGlobals =
BEGIN
OPEN spGlobals;
inputFileName: PUBLIC STRING ← [40];
inputFile: StreamDefs.StreamHandle;
maxInclude: CARDINAL = 10;
fileStack: ARRAY[0..maxInclude) OF StreamDefs.StreamHandle;
fileStackTop: CARDINAL;
line: STRING = [256];
chars: STRING = [256];
char: CHARACTER ← ';;
cptr: CARDINAL ← 0;
genSymCtr: CARDINAL ← 10000;
item: PUBLIC itemType;
value: PUBLIC REAL;
newString: PUBLIC LONG STRING;
keyList: ARRAY keys OF STRING ← ["node",
"resistor",
"capacitor",
"inductor",
"voltage",
"current",
"run",
"print",
"circuit",
"model",
"plot",
"ic",
"dump",
"asserts",
"checkpoint",
"library",
""];
initialHistory: PUBLIC history ← [0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0];
makeRealThing: PUBLIC PROCEDURE[last: realThingPtr]
RETURNS[new: realThingPtr] =
BEGIN
new ← A.Allocate[SIZE[realThing]];
new↑ ← [last, TRUE, unReal[]]
END;
makeName: PUBLIC PROCEDURE[last: namePtr] RETURNS[new: namePtr] =
BEGIN
new ← A.Allocate[SIZE[nameBlk]];
new↑ ← [NIL, last, NIL, NIL, NIL, nodeName[]]
END;
makeConLink: PUBLIC PROCEDURE[last: conLinkPtr, conName: namePtr]
RETURNS[new: conLinkPtr] =
BEGIN
new ← A.Allocate[SIZE[conLink]];
new↑ ← [last, conName]
END;
makeBranchLink: PUBLIC PROCEDURE[last: branchLinkPtr, b: branchPtr,
positiveNode: BOOLEAN]
RETURNS[new: branchLinkPtr] =
BEGIN
new ← A.Allocate[SIZE[branchLink]];
new↑ ← [last, b, NIL, positiveNode]
END;
makeExpr: PUBLIC PROCEDURE RETURNS[e: expressionPtr] =
BEGIN
e ← A.Allocate[SIZE[expressionNode]];
e↑ ← [NIL,]
END;
makeNode: PUBLIC PROCEDURE RETURNS[n: nodePtr] =
BEGIN
n ← A.Allocate[SIZE[node]];
n↑ ← [NIL, NIL, NIL, NIL, NIL, NIL, NIL,
initialHistory, FALSE, FALSE, FALSE]
END;
makeResistor: PUBLIC PROCEDURE RETURNS[r: resistorPtr] =
BEGIN
r ← A.Allocate[SIZE[resistor branch]];
r↑ ← [NIL, NIL, NIL, NIL, NIL, 0.0, NIL, 0, resistor[]]
END;
makeCapacitor: PUBLIC PROCEDURE RETURNS[c: capacitorPtr] =
BEGIN
c ← A.Allocate[SIZE[capacitor branch]];
c↑ ← [NIL, NIL, NIL, NIL, NIL, 0.0, NIL, 0, capacitor[NIL]]
END;
makeInductor: PUBLIC PROCEDURE RETURNS[l: inductorPtr] =
BEGIN
l ← A.Allocate[SIZE[inductor branch]];
l↑ ← [NIL, NIL, NIL, NIL, NIL, 0.0, NIL, 0,
inductor[NIL, initialHistory]]
END;
makeVoltage: PUBLIC PROCEDURE RETURNS[v: vSourcePtr] =
BEGIN
v ← A.Allocate[SIZE[vSource branch]];
v↑ ← [NIL, NIL, NIL, NIL, NIL, 0.0, NIL, 0,
vSource[NIL, 0.0, 0.0]]
END;
makeCurrent: PUBLIC PROCEDURE RETURNS[i: iSourcePtr] =
BEGIN
i ← A.Allocate[SIZE[iSource branch]];
i↑ ← [NIL, NIL, NIL, NIL, NIL, 0.0, NIL, 0, iSource[NIL]]
END;
makeFunction: PUBLIC PROCEDURE RETURNS[f: functionPtr] =
BEGIN
f ← A.Allocate[SIZE[fn modFuncBlk]];
f↑ ← [NIL, NIL, NIL, NIL, NIL, fn[, NIL]]
END;
makeModel: PUBLIC PROCEDURE RETURNS[m: modelPtr] =
BEGIN
m ← A.Allocate[SIZE[mod modFuncBlk]];
m↑ ← [NIL, NIL, NIL, NIL, NIL, mod[, NIL, NIL, NIL]]
END;
makeModBranch: PUBLIC PROCEDURE[last: modBrPtr, b: branchPtr]
RETURNS[mb: modBrPtr] =
BEGIN
mb ← A.Allocate[SIZE[modelBranch]];
mb↑ ← [last, b]
END;
makeArgSource: PUBLIC PROCEDURE[na: CARDINAL] RETURNS[a: argSource] =
BEGIN
a ← DESCRIPTOR[A.Allocate[SIZE[nodePtr]*na], na];
END;
makeArgNames: PUBLIC PROCEDURE[na: CARDINAL] RETURNS[a: argNames] =
BEGIN
a ← DESCRIPTOR[A.Allocate[SIZE[namePtr]*na], na];
END;
makeArgList: PUBLIC PROCEDURE[na: CARDINAL] RETURNS[a: argList] =
BEGIN
a ← DESCRIPTOR[A.Allocate[SIZE[REAL]*na], na];
END;
makeTreeNode: PUBLIC PROCEDURE[inst: cktInstNamePtr]
RETURNS[t: instTreePtr] =
BEGIN
t ← A.Allocate[SIZE[instTreeNode]];
t↑ ← [NIL, NIL, NIL, inst, NIL, NIL]
END;
makeLongString: PUBLIC PROCEDURE[len: CARDINAL]
RETURNS[ls: LONG STRING] =
BEGIN
ls ← A.Allocate[2 + (len + 1)/2];
ls↑ ← [length: 0, maxlength: len, text:]
END;
openInputFile: PUBLIC PROCEDURE =
BEGIN
inputFile ← ComLineDefs.OpenFile[inputFileName, ".thy"];
line.length ← 0;
fileStackTop ← 0
END;
includeFile: PROCEDURE =
BEGIN
fname: STRING = [40];
i: CARDINAL ← 0;
nextChar[TRUE];
UNTIL char = IODefs.TAB OR char = IODefs.CR OR char = ' DO
IF i = 40 THEN EXIT;
fname[i] ← char;
nextChar[FALSE];
i ← i + 1
ENDLOOP;
fname.length ← i;
IF fileStackTop < maxInclude THEN
BEGIN
ENABLE
StreamDefs.FileNameError =>
BEGIN
error[103, FALSE];
GOTO fileError
END;
fileStack[fileStackTop] ← inputFile;
inputFile ← StreamDefs.NewByteStream[fname, StreamDefs.Read];
fileStackTop ← fileStackTop + 1
EXITS fileError => NULL
END
ELSE error[104, FALSE];
next[]
END;
popIncludeFile: PROCEDURE =
BEGIN
IF fileStackTop > 0 THEN
BEGIN
fileStackTop ← fileStackTop - 1;
inputFile ← fileStack[fileStackTop];
nextChar[FALSE];
next[]
END
ELSE item ← eof
END;
newLine: PROCEDURE =
BEGIN
cptr ← 0;
line.length ← 0;
DO
IF inputFile.endof[inputFile] THEN char ← IODefs.ControlZ
ELSE char ← inputFile.get[inputFile];
line[line.length] ← char;
line.length ← line.length + 1;
IF char = IODefs.ControlZ OR char = IODefs.CR THEN EXIT;
ENDLOOP;
IF char = IODefs.ControlZ THEN
BEGIN
line[line.length] ← IODefs.CR;
line.length ← line.length + 1
END;
CWF.WF1["%s", line]
END;
nextChar: PROCEDURE[skip: BOOLEAN] =
BEGIN
DO
IF cptr >= line.length THEN newLine[];
char ← line[cptr];
cptr ← cptr + 1;
IF char # ' THEN EXIT;
IF ~skip THEN EXIT
ENDLOOP
END;
scaleFactor: PROCEDURE RETURNS[s: INTEGER] =
BEGIN
s ← SELECT char FROM
'M => 6,
'k => 3,
'K => 3,
'm => -3,
'u => -6,
'n => -9,
'p => -12,
ENDCASE => 0;
IF s # 0 THEN nextChar[FALSE];
SELECT char FROM
'F, 'H, 'V, 'A, 's => nextChar[TRUE]
ENDCASE
END;
next: PUBLIC PROCEDURE =
BEGIN
minusExp, validReal: BOOLEAN ← FALSE;
exp: INTEGER ← 0;
f1, f10: REAL;
SELECT char FROM
IODefs.ControlZ => popIncludeFile[];
'! => includeFile[];
IODefs.TAB, IODefs.SP, IODefs.CR =>
BEGIN
nextChar[TRUE];
next[]
END;
'{ => BEGIN
item ← leftC;
nextChar[TRUE]
END;
'; => BEGIN
item ← semi;
nextChar[TRUE]
END;
': => BEGIN
item ← colon;
nextChar[TRUE]
END;
'[ => BEGIN
item ← leftB;
nextChar[TRUE]
END;
'] => BEGIN
item ← rightB;
nextChar[TRUE]
END;
', => BEGIN
item ← comma;
nextChar[TRUE]
END;
'= => BEGIN
nextChar[FALSE];
IF char = '> THEN
BEGIN
item ← implies;
nextChar[TRUE]
END
ELSE item ← equal
END;
'← => BEGIN
item ← leftArrow;
nextChar[TRUE]
END;
'} => BEGIN
item ← rightC;
nextChar[TRUE]
END;
'/ => BEGIN
item ← slash;
nextChar[TRUE]
END;
'↑ => BEGIN
item ← upArrow;
nextChar[TRUE]
END;
'@ => BEGIN
item ← atSign;
nextChar[TRUE]
END;
'| => BEGIN
item ← vertical;
nextChar[TRUE]
END;
'& => BEGIN
item ← amperesand;
nextChar[TRUE]
END;
'+ => BEGIN
item ← plus;
nextChar[TRUE]
END;
'- => BEGIN
item ← minus;
nextChar[FALSE];
IF char = '- THEN
BEGIN
UNTIL char = IODefs.CR OR char = IODefs.ControlZ DO
nextChar[TRUE];
IF char = '- THEN
BEGIN
nextChar[FALSE];
IF char # '- THEN LOOP;
nextChar[TRUE];
EXIT
END
ENDLOOP;
next[]
END
END;
'* => BEGIN
item ← star;
nextChar[TRUE]
END;
'\ => BEGIN
item ← backSlash;
nextChar[TRUE]
END;
'> => BEGIN
nextChar[FALSE];
IF char = '= THEN
BEGIN
item ← greatEqual;
nextChar[TRUE]
END
ELSE item ← greater
END;
'< => BEGIN
nextChar[FALSE];
IF char = '= THEN
BEGIN
item ← lessEqual;
nextChar[TRUE]
END
ELSE item ← less
END;
'# => BEGIN
item ← pound;
nextChar[TRUE]
END;
'~ => BEGIN
item ← squiggle;
nextChar[TRUE]
END;
'( => BEGIN
item ← leftP;
nextChar[TRUE]
END;
') => BEGIN
item ← rightP;
nextChar[TRUE]
END;
'' => BEGIN
item ← quote;
nextChar[TRUE]
END;
'" => BEGIN
item ← string;
chars.length ← 0;
DO
nextChar[FALSE];
IF char = IODefs.ControlZ THEN
BEGIN
error[213, FALSE];
EXIT
END;
IF char = '" THEN
BEGIN
nextChar[FALSE];
IF char # '" THEN EXIT
END;
chars[chars.length] ← char;
chars.length ← chars.length + 1
ENDLOOP;
newString ← makeLongString[chars.length];
FOR i: CARDINAL IN [0..chars.length) DO
newString[i] ← chars[i]
ENDLOOP;
newString.length ← chars.length
END;
'? => BEGIN
CWF.SWF1[chars, "?%u", @genSymCtr];
genSymCtr ← genSymCtr + 1;
newString ← chars;
item ← name;
nextChar[TRUE]
END;
'$ => BEGIN
nextChar[FALSE];
chars.length ← 0;
UNTIL char = '$ DO
IF char = IODefs.ControlZ THEN
BEGIN
error[214, FALSE];
EXIT
END;
StringDefs.AppendChar[chars, char];
nextChar[FALSE]
ENDLOOP;
nextChar[TRUE];
newString ← chars;
item ← name
END;
IN ['A..'Z],
IN ['a..'z] =>
BEGIN
chars.length ← 0;
UNTIL char ~IN ['A..'Z] AND char ~IN ['a..'z]
AND char ~IN ['0..'9] DO
StringDefs.AppendChar[chars, char];
nextChar[FALSE]
ENDLOOP;
IF chars.length=3 THEN BEGIN
IF chars[0]='M OR chars[0]='m THEN BEGIN
IF chars[1]='A OR chars[1]='a THEN BEGIN IF chars[2]='X OR chars[2]='x THEN BEGIN
item ← maximum; GOTO done;
END;
END ELSE IF chars[1]='I OR chars[1]='i THEN BEGIN
IF chars[2]='N OR chars[2]='n THEN BEGIN
item ← minimum; GOTO done;
END;
END;
END;
END;
newString ← chars;
item ← name
EXITS
done => IF char=IODefs.SP OR char=IODefs.CR OR
char=IODefs.TAB THEN nextChar[TRUE];
END;
'.,
IN ['0..'9] =>
BEGIN
item ← number;
value ← 0.0;
UNTIL char ~IN ['0..'9] DO
validReal ← TRUE;
value ← value*10.0 + (char - '0);
nextChar[FALSE]
ENDLOOP;
IF char = '. THEN
BEGIN
nextChar[FALSE];
f10 ← 0.1;
UNTIL char ~IN ['0..'9] DO
validReal ← TRUE;
value ← value + f10*(char - '0);
f10 ← 0.1*f10;
nextChar[FALSE]
ENDLOOP
END;
IF char = 'e OR char = 'E THEN
BEGIN
nextChar[FALSE];
minusExp ← char = '-;
IF minusExp OR char = '+ THEN nextChar[FALSE];
IF char ~IN ['0..'9] THEN validReal ← FALSE
ELSE
UNTIL char ~IN ['0..'9] DO
exp ← exp*10 + (char - '0);
nextChar[FALSE]
ENDLOOP;
IF minusExp THEN exp ← -exp
END;
exp ← exp + scaleFactor[];
validReal ← validReal AND exp < 37 AND exp > -37;
IF validReal THEN
BEGIN
f1 ← 1.0E+1; f10 ← 1.0E+10;
IF exp < 0 THEN
BEGIN f1 ← 1.0/f1;f10 ← 1.0/f10; exp ← -exp END;
UNTIL exp < 10 DO
value ← value*f10;
exp ← exp - 10
ENDLOOP;
UNTIL exp = 0 DO
value ← value*f1;
exp ← exp - 1
ENDLOOP
END
ELSE error[102, FALSE]
END
ENDCASE =>
BEGIN
nextChar[TRUE];
error[101, FALSE]
END
END;
getSignedNumber: PUBLIC PROCEDURE RETURNS[n: REAL ← 1.0] =
BEGIN
negative: BOOLEAN ← item = minus;
IF negative THEN next[];
IF item = number THEN
BEGIN
n ← IF negative THEN -value ELSE value;
next[]
END
ELSE error[105, FALSE]
END;
LongEqualStrings: PUBLIC PROCEDURE[s, S: LONG STRING]
RETURNS[eq: BOOLEAN ← FALSE] =
BEGIN
IF s.length = S.length THEN
FOR i: CARDINAL IN [0..s.length) DO
eq ← s.text[i] = S[i];
IF ~eq THEN EXIT
ENDLOOP
END;
LongStringGetsString: PUBLIC PROCEDURE[s, S: LONG STRING] =
BEGIN
FOR i: CARDINAL IN [0..S.length) DO
s.text[i] ← S.text[i]
ENDLOOP;
s.length ← S.length
END;
searchKey: PUBLIC PROCEDURE RETURNS[index: keys] =
BEGIN
FOR i: keys IN keys DO
index ← i;
IF newString.length # keyList[i].length THEN LOOP;
FOR j: CARDINAL IN [0..newString.length) DO
IF keyList[i][j] # StringDefs.LowerCase[newString[j]] THEN EXIT;
REPEAT
FINISHED => RETURN;
ENDLOOP
ENDLOOP;
END;
GetLineAndCptr: PUBLIC PROCEDURE RETURNS[STRING, CARDINAL] =
BEGIN
RETURN[line, cptr]
END;
line.length ← 0;
char ← ' ;
END.
4/19/83:-
original: [Cherry]<Barth>Thyme>1.97>spGlobalsimpl.mesa
changes:
1. next - modified to parse MAX and MIN. (Lower cases are also allowed.)