OpDefsGenerator.mesa
last edited by Johnsson, November 2, 1978 10:22 AM
last edited by Satterthwaite, May 10, 1983 12:54 pm
Last Edited by: Maxwell, August 8, 1983 8:29 am
DIRECTORY
Commander: TYPE USING [Handle, Register],
FileIO: TYPE USING [Open, OpenFailed],
IO: TYPE USING [card, char, Close, CR, EndOf, GetChar, GetCard, GetToken, Put, PutChar, PutF, PutRope, rope, STREAM, time, UnsafePutBlock],
Rope: TYPE USING [Equal, Fetch, Length, ROPE];
OpDefsGenerator: PROGRAM
IMPORTS Commander, FileIO, IO, Rope = {
CompStrDesc: TYPE = RECORD[offset, length: CARDINAL];
nChars: CARDINAL;
nOpCodes: CARDINAL = 256;
OpCode: TYPE = [0..nOpCodes);
StringArray: TYPE = ARRAY OpCode OF Rope.ROPE;
NumberArray: TYPE = ARRAY OpCode OF CARDINAL;
CharArray: TYPE = ARRAY OpCode OF CHAR;
name: REF StringArray ← NEW[StringArray ← ALL[NIL]];
push: REF NumberArray ← NEW[NumberArray];
pop: REF NumberArray ← NEW[NumberArray];
len: REF NumberArray ← NEW[NumberArray];
mark: REF CharArray ← NEW[CharArray];
SyntaxError: SIGNAL = CODE;
CollectOpData: PROC[in, out: IO.STREAM] = {
id: Rope.ROPE;
code: CARDINAL;
CRcount: CARDINAL ← 0;
push^ ← pop^ ← len^ ← ALL[0];
mark^ ← ALL['F];
name^ ← ALL[NIL];
nChars ← 0;
UNTIL CRcount = 3 DO
IF IO.GetChar[in] = '\n THEN CRcount ← CRcount+1;
ENDLOOP;
code ← 177777b;
THROUGH OpCode DO
-- name octal(decimal)push,pop,len,mark;
id ← in.GetToken[];
IF IO.EndOf[in] THEN EXIT;
nChars ← nChars + id.Length[];
[] ← in.GetCard[]; -- octal number
[] ← in.GetChar[]; -- (
code ← in.GetCard[]; -- decimal number
[] ← in.GetChar[]; -- )
name[code] ← id;
push[code] ← in.GetCard[];
[] ← in.GetChar[]; -- ,
pop[code] ← in.GetCard[];
[] ← in.GetChar[]; -- ,
len[code] ← in.GetCard[];
[] ← in.GetChar[]; -- ,
mark[code] ← in.GetChar[];
ENDLOOP;
FOR i: OpCode IN OpCode DO
IF i MOD 4 = 0 THEN {
IO.PutF[out, "--%13g%13g%13g%13g ",
IO.rope[name[i]], IO.rope[name[i+1]],
IO.rope[name[i+2]], IO.rope[name[i+3]]];
IO.PutF[out, " %03b-%03b\n ", IO.card[i], IO.card[i+3]]};
IO.PutF[out, " Q[%b,%b,%b,%g],",
IO.card[push[i]], IO.card[pop[i]],
IO.card[len[i]], IO.char[mark[i]]];
IF i MOD 4 = 3 THEN {
IF i = OpCode.LAST THEN IO.PutRope[out, "];"]
ELSE IO.PutChar[out, ',];
IO.PutChar[out, '\n]}
ELSE IO.PutChar[out, ',];
ENDLOOP};
OctalDecimalError: SIGNAL [CARDINAL] = CODE;
OpNameTooLong: ERROR [CARDINAL] = CODE;
OutStrings: PROC[fileName: Rope.ROPE] = {
PutWord: PROC [stream: IO.STREAM, word: WORD] = {
stream.UnsafePutBlock[[@word, 0, 1]]};
out: IO.STREAM ← FileIO.Open[fileName];
charpos: CARDINAL ← 0;
PutWord[out, CARDINAL.SIZE + nOpCodes*(CompStrDesc.SIZE)];
FOR i: OpCode IN OpCode DO
j: CARDINAL = name[i].Length[];
PutWord[out, charpos];
PutWord[out, j];
charpos ← charpos + j;
ENDLOOP;
PutWord[out, nChars];
PutWord[out, nChars];
FOR i: OpCode IN OpCode DO
IF name[i] # NIL THEN {
FOR j: INT IN [0..name[i].Length[]) DO
IO.PutChar[out, name[i].Fetch[j]] ENDLOOP};
ENDLOOP;
IO.Close[out]};
OutOpParams: PROC[inName, outName: Rope.ROPE] = {
in: IO.STREAM ← FileIO.Open[inName, write];
out: IO.STREAM ← FileIO.Open[outName, write];
IO.PutRope[out, " -- generated by OpDefsGenerator "];
IO.Put[out, IO.time[]];
IO.PutRope[out, "
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"];
CollectOpData[in, out];
IO.Close[in];
IO.Close[out]};
OutMopcodes: PROC[filename, modulename, prefix: Rope.ROPE] = {
stream: IO.STREAM ← FileIO.Open[filename, write];
i: OpCode;
j: CARDINAL;
IO.PutRope[stream, " -- generated by OpDefsGenerator "];
IO.Put[stream, IO.time[]];
IO.PutChar[stream, '\n];
IO.PutRope[stream, modulename];
IO.PutRope[stream, ": DEFINITIONS = {
op: TYPE = [0..400B);
"];
FOR i IN OpCode DO
length: INT ← name[i].Length[];
IF length > 10 THEN OpNameTooLong[i];
IF length # 0
THEN stream.PutF["%11g: op = %3bB;", IO.rope[name[i]], IO.card[i]]
ELSE { -- null item, check for rest of line empty
FOR j ← i, j+1 DO
IF name[j].Length[] # 0 THEN EXIT;
IF j MOD 4 = 3 THEN GOTO empty;
ENDLOOP;
FOR j IN [0..22) DO stream.PutChar[' ]; 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 stream.PutChar[' ] ELSE stream.PutChar['\n];
ENDLOOP;
IO.PutRope[stream, "}.\n"];
IO.Close[stream]};
OutListing: PROC[filename: Rope.ROPE] = {
stream: IO.STREAM ← FileIO.Open[filename, write];
stream.PutF["%g; %g\n", IO.rope[filename], IO.time[]];
IO.PutRope[stream, "Format: name octal(decimal)push,pop,count,mark\n\n"];
FOR i: OpCode IN OpCode DO
stream.PutF["%-8g%3b(%3d)", IO.rope[name[i]], IO.card[i], IO.card[i]];
stream.PutF["%g,%g,%g,%g;", IO.card[push[i]], IO.card[pop[i]],
IO.card[len[i]], IO.char[mark[i]]];
IF i MOD 4 = 3 THEN IO.PutChar[stream, IO.CR] ELSE IO.PutRope[stream, " "];
ENDLOOP;
IO.Close[stream]};
GetResponse: PROC[cmd: Commander.Handle, prompt, default: Rope.ROPE]
RETURNS[response: Rope.ROPE] = {
cmd.out.PutRope[prompt];
IF default # NIL THEN cmd.out.Put[IO.rope[" ("], IO.rope[default], IO.rope[") "]];
response ← cmd.in.GetToken[];
IF response.Length[] = 0 THEN response ← default};
DoCommand: SAFE PROC[cmd: Commander.Handle] = TRUSTED {
listfile, modulename, prefix: Rope.ROPE;
infile, apoutfile, amoutfile, boutfile: Rope.ROPE;
cmd.out.PutRope["\nMesa OpData Generator\n"];
SELECT TRUE FROM
Rope.Equal[cmd.command, "Mopdata", FALSE] => {
infile ← "OpCodes.txt";
apoutfile ← "OpParams";
amoutfile ← "Mopcodes.mesa";
boutfile ← "OpNames.binary";
listfile ← "Mopcodes.list";
modulename ← "Mopcodes";
prefix ← "z"};
Rope.Equal[cmd.command, "Fopdata", FALSE] => {
infile ← "FOpCodes.txt";
apoutfile ← "FOpParams";
amoutfile ← "FOpCodes.mesa";
boutfile ← "FOpNames.binary";
listfile ← "FOpCodes.list";
modulename ← "FOpCodes";
prefix ← "q"};
ENDCASE => ERROR;
cmd.out.PutRope["\nType CR to get defaults\n"];
infile ← GetResponse[cmd, "Input file: ", infile];
IF infile.Length[] = 0 THEN GOTO badFile;
apoutfile ← GetResponse[cmd, " OpParams file: ", apoutfile];
amoutfile ← GetResponse[cmd, " Mopcodes file: ", amoutfile];
modulename ← GetResponse[cmd, " Module name (capitalize correctly): ", modulename];
prefix ← GetResponse[cmd, " Prefix with: ", prefix];
boutfile ← GetResponse[cmd, " binary file for OpName strings: ", boutfile];
listfile ← GetResponse[cmd, " listing file: ", listfile];
BEGIN
ENABLE FileIO.OpenFailed => GOTO badFile;
OutOpParams[listfile, apoutfile];
OutStrings[boutfile];
OutMopcodes[amoutfile, modulename, prefix];
OutListing[listfile];
END;
EXITS badFile => cmd.out.PutRope["\nError: bad file name.\n"]};
Commander.Register["Mopdata", DoCommand, "Generate Mop codes."];
Commander.Register["Fopdata", DoCommand, "Generate Fop codes."];
}.