-- 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