-- UECPImpl.mesa
-- Last edit by Gifford on June 18, 1982 10:55 am
DIRECTORY
Inline USING [LongCOPY],
Rope,
UECP;
UECPImpl: CEDAR PROGRAM
IMPORTS Inline, Rope
EXPORTS UECP = {
OPEN UECP;
UnmatchedQuote: ERROR = CODE;
CPData: TYPE = RECORD [
ch: CHARACTER ← ' , -- first char of next token; initially blank
swChar: CHARACTER, -- switch character
ropeIndex: LONG INTEGER ← 0, -- index into Rope command line
rope: Rope.ROPE ← NIL, -- command line passed from client
done: BOOLEAN ← FALSE, -- used up all of command line
argC: INT ← 0, -- number of tokens found
args: LIST OF Rope.ROPE ← NIL -- list of tokens
];
Parse: PUBLIC PROC [commands: Rope.ROPE, switchchar: CHARACTER ← '-] RETURNS [argv: Argv] = {
cpd: REF CPData ← NEW[CPData];
Fooey: PROC RETURNS [LIST OF Rope.ROPE, INT] = {
r: Rope.ROPE ← IGet[cpd];
IF r = NIL THEN RETURN [NIL, 1]
ELSE {
n: LIST OF Rope.ROPE;
c: INT;
[n, c] ← Fooey[];
RETURN [CONS[r, n], c+1];
};
};
cpd.swChar ← switchchar;
cpd.rope ← commands;
argv ← NIL;
[cpd.args, cpd.argC] ← Fooey[! UnmatchedQuote => GOTO Lose];
argv ← NEW[ArgHandleObject[cpd.argC]];
argv[0] ← "";
FOR i: NAT IN [1..argv.argc) DO
argv[i] ← cpd.args.first;
cpd.args ← cpd.args.rest;
ENDLOOP;
EXITS
Lose => NULL;
};--Parse
IGet: PROC [cpd: REF CPData] RETURNS [result: Rope.ROPE] = {
-- Returns next token.
-- This scanner
-- (1) ignores leading blanks,
-- (2) returns a quoted token intact (excluding the quotes),
-- (3) returns an unquoted token delimited by a blank (not included)
--or switchchar (included in next token), the default switchchar is '/
-- (4) returns NIL at CR or end of file.
-- (5) if the switchchar is '- then it must be preceded by a blank
chlook: CHARACTER;
workstr: REF TEXT;
-- delimiter for token: either blank, meaning blank
-- or switchchar (usually '/),
-- or '", or '", meaning '" not followed by another '".
RopeWP: PROC [c: CHARACTER] = {
IF workstr=NIL THEN workstr ← NEW[TEXT[40]];
IF workstr.length >= workstr.maxLength THEN TRUSTED {
old: REF TEXT ← workstr;
workstr ← NEW[TEXT[2*old.maxLength]];
Inline.LongCOPY[
from: LOOPHOLE[old, LONG POINTER] + 2, nwords: (old.maxLength + 1)/2,
to: LOOPHOLE[workstr, LONG POINTER] + 2];
workstr.length ← old.length;
};
workstr[workstr.length] ← c;
workstr.length ← SUCC[workstr.length];
};
WHILE cpd.ch = ' AND GetCh[cpd] DO ENDLOOP;
IF cpd.done OR cpd.ch = '\n THEN RETURN[NIL];
chlook ← ' ;
IF cpd.ch = '" THEN {
[] ← GetCh[cpd];
chlook ← '";
};
DO
IF cpd.done OR cpd.ch = '\n THEN GOTO EOL;
SELECT chlook FROM
' => SELECT cpd.ch FROM
' , '" => IF workstr#NIL THEN EXIT;
cpd.swChar => IF cpd.ch#'- AND workstr#NIL THEN EXIT;
ENDCASE;
'" => SELECT cpd.ch FROM
'" => IF (NOT GetCh[cpd]) OR (cpd.ch # '") THEN EXIT;
ENDCASE;
ENDCASE => ERROR;
-- ch now contains a character to be included in the token
RopeWP[cpd.ch];
IF NOT GetCh[cpd] THEN GOTO EOL;
REPEAT
EOL => IF chlook = '" THEN ERROR UnmatchedQuote;
ENDLOOP;
IF workstr = NIL OR workstr.length=0 THEN RETURN [NIL];
result ← Rope.FromRefText[workstr];
};--IGet
GetCh: PROC [cpd: REF CPData] RETURNS [BOOL] = {
IF cpd.ropeIndex >= Rope.Size[cpd.rope] THEN GOTO EOS;
cpd.ch ← Rope.Fetch[cpd.rope, cpd.ropeIndex];
cpd.ropeIndex ← SUCC[cpd.ropeIndex];
RETURN [TRUE];
EXITS
EOS => {
cpd.done ← TRUE;
cpd.ch ← ' ;
RETURN [FALSE];
};
}; -- GetCh
}.-- UECPImpl
CHANGE LOG
Created by Stewart on 19-Mar-82 17:31
Rename Open to Parse by Gifford 23-Mar-82 14:46:08
CEDAR PROGRAM, Schroeder, September 17, 1982 3:20 pm