-- OpDefsGenerator.mesa -- last edited by Johnsson, November 2, 1978 10:22 AM -- last edited by Satterthwaite, May 10, 1983 12:54 pm DIRECTORY Exec: TYPE USING [w], Format: TYPE USING [NumberFormat, Number, StringProc], Heap: TYPE USING [systemZone], LongString: TYPE USING [StringToNumber, StringToOctal], Segments: TYPE USING [FHandle, NewFile, Write], Streams: TYPE USING [ Handle, Write, CreateStream, Destroy, Ended, GetChar, GetIndex, NewStream, PutChar, PutWord, SetIndex], Strings: TYPE USING [String, AppendChar, AppendString], Time: TYPE USING [AppendCurrent], TTY: TYPE USING [Handle, GetChar, GetID, PutChar, PutLine, PutString]; OpDefsGenerator: PROGRAM IMPORTS Exec, Format, Heap, LongString, Segments, Streams, Strings, Time, TTY = { CompStrDesc: TYPE = RECORD[offset, length: CARDINAL]; nChars: CARDINAL; in, bOut: Streams.Handle; tty: TTY.Handle; nOpCodes: CARDINAL = 256; OpCode: TYPE = [0..nOpCodes); StringArray: TYPE = ARRAY OpCode OF Strings.String; NumberArray: TYPE = ARRAY OpCode OF CARDINAL; CharArray: TYPE = ARRAY OpCode OF CHAR; stringData: LONG POINTER TO StringArray _ (Heap.systemZone).NEW[StringArray _ ALL[NIL]]; push: LONG POINTER TO NumberArray _ (Heap.systemZone).NEW[NumberArray]; pop: LONG POINTER TO NumberArray _ (Heap.systemZone).NEW[NumberArray]; len: LONG POINTER TO NumberArray _ (Heap.systemZone).NEW[NumberArray]; mark: LONG POINTER TO CharArray _ (Heap.systemZone).NEW[CharArray]; Name: PROC[s: Strings.String] = { c: CHAR; nc: CARDINAL _ 0; CollectingChars: BOOL _ FALSE; s.length _ 0; DO IF Streams.Ended[in] THEN RETURN; c _ Streams.GetChar[in]; SELECT c FROM ' , '\t, '\n => IF CollectingChars THEN EXIT; IN ['0..'9] => { IF ~CollectingChars THEN { Streams.SetIndex[in, Streams.GetIndex[in]-1]; EXIT}; Strings.AppendChar[s,c]}; IN ['A..'Z], IN ['a..'z] => { CollectingChars _ TRUE; Strings.AppendChar[s,c]}; ENDCASE => SIGNAL SyntaxError; ENDLOOP; nChars _ nChars + s.length}; Atom: PROC[s: Strings.String, del: CHAR] = { c: CHAR; nc: CARDINAL _ 0; CollectingChars: BOOL _ FALSE; DO IF Streams.Ended[in] THEN SIGNAL SyntaxError; c _ Streams.GetChar[in]; SELECT c FROM ' , '\n => IF CollectingChars THEN EXIT; IN ['0..'9], IN ['A..'Z], IN ['a..'z], '+ => { s[nc] _ c; nc _ nc+1; CollectingChars _ TRUE}; ENDCASE => EXIT; ENDLOOP; s.length _ nc; IF c # del THEN SIGNAL SyntaxError}; SyntaxError: SIGNAL = CODE; CollectOpData: PROC[stream: Streams.Handle] = { name: STRING _ [20]; s: STRING _ [8]; code: CARDINAL; CRcount: CARDINAL _ 0; push^ _ pop^ _ len^ _ ALL[0]; mark^ _ ALL['F]; FOR i: OpCode IN OpCode DO IF stringData[i] # NIL THEN (Heap.systemZone).FREE[@stringData[i]]; ENDLOOP; nChars _ 0; UNTIL CRcount = 3 DO IF Streams.GetChar[in] = '\n THEN CRcount _ CRcount+1; ENDLOOP; code _ 177777b; THROUGH OpCode DO Name[name]; IF Streams.Ended[in] THEN EXIT; Atom[s, '(]; IF s.length = 1 AND s[0] = '+ THEN code _ code + 1 ELSE code _ LongString.StringToNumber[s, 8]; Atom[s, ')]; -- decimal, ignore it IF name.length # 0 THEN { stringData[code] _ (Heap.systemZone).NEW[StringBody[name.length]]; Strings.AppendString[stringData[code],name]}; Atom[s, ',]; push[code] _ LongString.StringToOctal[s]; Atom[s, ',]; pop[code] _ LongString.StringToOctal[s]; Atom[s, ',]; len[code] _ LongString.StringToOctal[s]; Atom[s, ';]; mark[code] _ s[0]; ENDLOOP; FOR i: OpCode IN OpCode DO IF i MOD 4 = 0 THEN { f: Format.NumberFormat = [8,TRUE,TRUE,3]; OutString[stream, "--"L]; OutNameR[stream, stringData[i],12]; OutNameR[stream, stringData[i+1],13]; OutNameR[stream, stringData[i+2],13]; OutNameR[stream, stringData[i+3],13]; OutString[stream, " "L]; OutNumF[stream, i,f]; OutChar[stream, '-]; OutNumF[stream, i+3,f]; OutString[stream, "\n "L]}; OutString[stream, " Q["L]; OutNum[stream, push[i]]; OutChar[stream, ',]; OutNum[stream, pop[i]]; OutChar[stream, ',]; OutNum[stream, len[i]]; OutChar[stream, ',]; OutChar[stream, mark[i]]; OutChar[stream, ']]; IF i MOD 4 = 3 THEN { IF i = OpCode.LAST THEN OutString[stream, "];"L] ELSE OutChar[stream, ',]; OutChar[stream, '\n]} ELSE OutChar[stream, ',]; ENDLOOP}; OctalDecimalError: SIGNAL [CARDINAL] = CODE; OpNameTooLong: ERROR [CARDINAL] = CODE; OutStrings: PROC = { charpos: CARDINAL _ 0; --Streams.Reset[bOut]; Streams.PutWord[bOut, CARDINAL.SIZE + nOpCodes*(CompStrDesc.SIZE)]; FOR i: OpCode IN OpCode DO j: CARDINAL = IF stringData[i] # NIL THEN stringData[i].length ELSE 0; Streams.PutWord[bOut, charpos]; Streams.PutWord[bOut, j]; charpos _ charpos + j; ENDLOOP; Streams.PutWord[bOut, nChars]; Streams.PutWord[bOut, nChars]; FOR i: OpCode IN OpCode DO IF stringData[i] # NIL THEN { FOR j: CARDINAL IN [0..stringData[i].length) DO Streams.PutChar[bOut, stringData[i][j]] ENDLOOP}; ENDLOOP; Streams.Destroy[bOut]}; OutOpParams: PROC = { stream: Streams.Handle _ Streams.NewStream[apoutfile, Streams.Write]; time: STRING _ [20]; GetTime[time]; OutString[stream, " -- generated by OpDefsGenerator "L]; OutString[stream, time]; OutString[stream, " Q: TYPE = PRIVATE RECORD [ push: [0..3], pop: [0..7], length: [0..3], mark: BOOL]; T: BOOL = TRUE; F: BOOL = FALSE; OpParms: PRIVATE ARRAY [0..256) OF Q = [\n"L]; CollectOpData[stream]; Streams.Destroy[stream]}; GetTime: PROC[time: STRING] = { Time.AppendCurrent[time]; time.length _ time.length - 3}; OutMopcodes: PROC = { stream: Streams.Handle _ Streams.NewStream[amoutfile, Streams.Write]; i: OpCode; j, l: CARDINAL; time: STRING _ [20]; GetTime[time]; OutString[stream, " -- generated by OpDefsGenerator "L]; OutString[stream, time]; OutChar[stream, '\n]; OutString[stream, modulename]; OutString[stream, ": DEFINITIONS = { op: TYPE = [0..400B); "L]; FOR i IN OpCode DO IF stringData[i] # NIL AND (l _ stringData[i].length) # 0 THEN { IF l > 10 THEN ERROR OpNameTooLong[i]; FOR j IN (l..10) DO OutChar[stream, ' ] ENDLOOP; OutString[stream, prefixString]; OutString[stream, stringData[i]]; OutString[stream, ": op = "L]; OutNumF[stream, i, [8,FALSE,FALSE,3]]; OutChar[stream, 'B]; OutChar[stream, ';]} ELSE { -- null item, check for rest of line empty FOR j _ i, j+1 DO IF stringData[j] # NIL AND stringData[j].length # 0 THEN EXIT; IF j MOD 4 = 3 THEN GOTO empty; ENDLOOP; FOR j IN [0..22) DO OutChar[stream, ' ]; ENDLOOP; EXITS empty => { blank: BOOL _ j-i=3; -- TRUE iff whole line empty i _ j; IF blank THEN LOOP}}; -- no CR IF (i MOD 4) # 3 THEN OutChar[stream, ' ] ELSE OutChar[stream, '\n]; ENDLOOP; OutString[stream, "}.\n"L]; Streams.Destroy[stream]}; OutNameR: PROC[stream: Streams.Handle, s: Strings.String, n: CARDINAL] = { l: CARDINAL _ IF s = NIL THEN 0 ELSE s.length; THROUGH (l..n] DO OutChar[stream, ' ]; ENDLOOP; OutString[stream, s]}; OutNameL: PROC[stream: Streams.Handle, s: Strings.String, n: CARDINAL] = { l: CARDINAL _ IF s = NIL THEN 0 ELSE s.length; OutString[stream, s]; THROUGH (l..n] DO OutChar[stream, ' ]; ENDLOOP}; OutNum: PROC[stream: Streams.Handle, n: CARDINAL] = INLINE { OutNumF[stream, n, [10,FALSE,FALSE,1]]}; OutNumF: PROC [stream: Streams.Handle, n: CARDINAL, f: Format.NumberFormat] = { PutNumber: Format.StringProc = {OutString[stream, s]}; Format.Number[n, f, PutNumber]}; OutString: PROC[stream: Streams.Handle, s: Strings.String] = { IF s # NIL THEN FOR i: CARDINAL IN [0..s.length) DO Streams.PutChar[stream, s[i]] ENDLOOP}; OutChar: PROC[stream: Streams.Handle, c: CHAR] = INLINE {Streams.PutChar[stream, c]}; OutListing: PROC[filename: STRING] = { stream: Streams.Handle _ Streams.NewStream[filename, Streams.Write]; time: STRING _ [18]; GetTime[time]; OutString[stream, filename]; OutString[stream, "; "L]; OutString[stream, time]; OutChar[stream, '\n]; OutString[stream, "Format: name octal(decimal)push,pop,count,mark\n\n"L]; FOR i: OpCode IN OpCode DO OutNameL[stream, stringData[i],8]; OutNumF[stream, i,[8,FALSE,FALSE,3]]; OutChar[stream, '(]; OutNumF[stream, i,[10,FALSE,FALSE,3]]; OutChar[stream, ')]; OutNum[stream, push[i]]; OutChar[stream, ',]; OutNum[stream, pop[i]]; OutChar[stream, ',]; OutNum[stream, len[i]]; OutChar[stream, ',]; OutChar[stream, mark[i]]; OutChar[stream, ';]; IF i MOD 4 = 3 THEN OutChar[stream, '\n] ELSE OutString[stream, " "L]; ENDLOOP; Streams.Destroy[stream]}; DefaultNames: TYPE = {infile, apoutfile, amoutfile, boutfile, listfile, modulename, prefix}; DefaultStrings: TYPE = ARRAY DefaultNames OF Strings.String; MopDefaults: DefaultStrings _ [ "OpCodes.txt", "OpParams", "Mopcodes.mesa", "OpNames.binary", "Mopcodes.list", "Mopcodes", "z"]; FopDefaults: DefaultStrings _ [ "FOpCodes.txt", "FOpParams", "FOpCodes.mesa", "FOpNames.binary", "FOpCodes.list", "FOpCodes", "q"]; infile: STRING _ [40]; apoutfile: STRING _ [40]; amoutfile: STRING _ [40]; boutfile: STRING _ [40]; listfile: STRING _ [40]; modulename: STRING _ [40]; prefixString: STRING _ [10]; outFH: Segments.FHandle; SetDefaults: PROC[p: LONG POINTER TO DefaultStrings] = { infile.length_0; Strings.AppendString[infile, p[$infile]]; apoutfile.length_0; Strings.AppendString[apoutfile, p[$apoutfile]]; amoutfile.length_0; Strings.AppendString[amoutfile, p[$amoutfile]]; boutfile.length_0; Strings.AppendString[boutfile, p[$boutfile]]; listfile.length_0; Strings.AppendString[listfile, p[$listfile]]; modulename.length_0; Strings.AppendString[modulename, p[$modulename]]; prefixString.length_0; Strings.AppendString[prefixString, p[$prefix]]}; GetResponse: PROC[prompt, response: STRING] = { tty.PutString[prompt]; tty.GetID[response]; tty.PutChar['\n]}; tty _ Exec.w; tty.PutString["\nMesa OpData Generator\n"]; DO DO tty.PutString["\nMopdata, Fopdata, or Quit: "]; SELECT tty.GetChar FROM 'm,'M => {tty.PutLine["Mopdata"]; SetDefaults[@MopDefaults]; EXIT}; 'f,'F => {tty.PutLine["Fopdata"]; SetDefaults[@FopDefaults]; EXIT}; 'q,'Q => {tty.PutLine["Quit"]; GOTO done}; ENDCASE; ENDLOOP; tty.PutLine["\nUse escape key to get defaults"]; GetResponse["Input file: ", infile]; IF infile.length = 0 THEN EXIT; GetResponse[" OpParams file: ", apoutfile]; GetResponse[" Mopcodes file: ", amoutfile]; GetResponse[" Module name (capitalize correctly): ", modulename]; GetResponse[" Prefix with: ", prefixString]; GetResponse[" binary file for OpName strings: ", boutfile]; GetResponse[" listing file: ", listfile]; in _ Streams.NewStream[infile]; bOut _ Streams.CreateStream[ outFH _ Segments.NewFile[boutfile, Segments.Write], Streams.Write]; OutOpParams[]; OutStrings[]; OutMopcodes[]; OutListing[listfile]; Streams.Destroy[in]; REPEAT done => NULL; ENDLOOP; }.