GPM.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
written in Mesa by Bill Paxton, November 1981
last written by Paxton June 21, 1982 10:54 am
Last Edited by: Maxwell, December 17, 1982 9:51 am
Last Edited by: Paul Rovner, June 14, 1983 5:38 pm
Doug Wyatt, March 1, 1985 11:49:43 am PST
originating from Strachey's General Purpose Macrogenerator
as described in Computer Journal, Oct. 1965. pp. 225-241
DIRECTORY
Rope USING [ROPE],
IO USING [STREAM];
GPM: CEDAR DEFINITIONS
= BEGIN
Handle: TYPE = REF Object;
Object: TYPE = RECORD [
stream: IO.STREAM,
st: REF Stack,
outputChar: CHAR ← 0C,
startCall: CHAR ← '&,
endCall: CHAR ← ';,
singleQuote: CHAR ← '', -- treat next char as if surrounded by startQuote, endQuote
startQuote: CHAR ← '<,
endQuote: CHAR ← '>,
sepArg: CHAR ← ',,
numArg: CHAR ← '~,
output: REF TEXT,
outputPtr: NAT ← 0,
s: Index, -- next available cell in the stack
e: Index, -- chain of name-value pairs for current definitions
h: Index, -- index of length cell for incomplete string on top of stack
h=0 means destination is output stream rather than stack
p: Index, -- start of chain of calls entered but not yet completed
f: Index, -- start of chain of calls started but not yet entered
i.e., have seen the & but not the matching ;
c: Index, -- index of next character to be scanned
c=0 means source is input stream rather than stack
a: CHAR, -- temp for use by NextCh and Load
w: Index, -- temp for use with Find
q: NAT -- level of nesting inside <'s
];
Stack: TYPE = RECORD [entries: SEQUENCE length:NAT OF Entry];
Index: TYPE = [0..maxIndex] ← 0;
maxIndex: NAT = LAST[NAT];
Entry: TYPE = RECORD [ data: INTEGER ];
data: SELECT kind:* FROM
index => [ index: Index ],
length => [ length: Index ],
char => [ char: CHARACTER ],
builtin => [ name: BuiltIn ],
ENDCASE];
BuiltIn: TYPE = [1..3];
DEF: BuiltIn = 1;
gpmVAL: BuiltIn = 2;
UPDATE: BuiltIn = 3;
Open: PROC [stream: IO.STREAM] RETURNS [Handle];
Close: PROC [self: Handle];
GetChar: PROC [self: Handle] RETURNS [char: CHAR];
GetIndex: PROC [self: Handle] RETURNS [i: LONG INTEGER];
Error: ERROR [ec: ErrorCode, errorMsg: Rope.ROPE];
ErrorCode: TYPE = { MacroError, EndOfStream };
DumpToStream: PROC [output: IO.STREAM, input: Handle];
END.