-- File: [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]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]Thyme>1.97>spGlobalsimpl.mesa changes: 1. next - modified to parse MAX and MIN. (Lower cases are also allowed.)