<<>> <> <> <> <> <> <> DIRECTORY Commander USING [Handle], CommanderOps USING [ArgumentVector, ArgHandleObject], IO USING [EndOfStream, Error, GetIndex, GetRopeLiteral, PutChar, RopeFromROS, RIS, ROS, SetIndex, STREAM], PositionedList USING [ PositionedArgumentList, PositionedArgumentVector, PositionedArgumentVectorPrivate, PositionedArgument ], Rope USING [Fetch, Length, ROPE, Size]; PositionedListImpl: CEDAR PROGRAM IMPORTS IO, Rope EXPORTS PositionedList ~ { OPEN PositionedList; Failed: ERROR [errorMsg: ROPE] = CODE; QuoteSyntaxError: ERROR = CODE; CPData: TYPE = RECORD [ ch: CHAR _ ' , -- first char of next token; initially blank swChar: CHAR, -- switch character ropeIndex: LONG INTEGER _ 0, -- index into Rope command line rope: ROPE _ NIL, -- command line passed from client done: BOOL _ FALSE -- used up all of command line ]; Handle: TYPE = Commander.Handle; ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; ParseToPositionedList: PUBLIC PROC [cmd: Handle, switchChar: CHAR ¬ '-] RETURNS [list: PositionedArgumentList, length: NAT ¬ 1] = { cpd: REF CPData ¬ NEW[CPData]; tail: PositionedArgumentList ¬ list ¬ LIST[[-cmd.command.Length, -1, cmd.command]]; cpd.swChar ¬ switchChar; cpd.rope ¬ cmd.commandLine; DO r: PositionedArgument ¬ IGet[cpd ! QuoteSyntaxError => GOTO Lose]; IF r.rope = NIL THEN EXIT; length ¬ length + 1; tail ¬ tail.rest ¬ LIST[r]; ENDLOOP; EXITS Lose => Failed["Syntax error in quoted string"]; }; IGet: PROC [cpd: REF CPData] RETURNS [result: PositionedArgument] = { <> <<(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>> workstr: STREAM ¬ NIL; chlook: CHAR; <> <> <> WHILE (cpd.ch = ' OR cpd.ch = ' ) AND GetCh[cpd] DO ENDLOOP; <<'/l also delimits a line>> IF cpd.done OR cpd.ch = '\n OR cpd.ch = '\l THEN RETURN [[0, -1, NIL]]; result.start ¬ cpd.ropeIndex-1; chlook ¬ ' ; IF cpd.ch = '" THEN --this makes the later code that considers that chlook might be '" obsolete (as of July 16th 1987), but we're chicken and so haven't deleted it yet--{ workstr ¬ IO.RIS[cpd.rope]; workstr.SetIndex[result.start]; result.rope ¬ IO.GetRopeLiteral[workstr !IO.Error, IO.EndOfStream => ERROR QuoteSyntaxError]; cpd.ropeIndex ¬ IO.GetIndex[workstr]; result.length ¬ cpd.ropeIndex - result.start; [] ¬ GetCh[cpd]; RETURN}; DO IF cpd.done OR (chlook # '" AND (cpd.ch = '\n OR cpd.ch = '\l) ) THEN GOTO EOL; SELECT chlook FROM ' , '\t => SELECT cpd.ch FROM ' , '", '\t => 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; <> IF workstr = NIL THEN workstr ¬ IO.ROS[]; IO.PutChar[workstr, cpd.ch]; IF NOT GetCh[cpd] THEN GOTO EOL; REPEAT EOL => IF chlook = '" THEN ERROR QuoteSyntaxError; ENDLOOP; IF workstr = NIL THEN RETURN [[0, -1, NIL]]; result.length ¬ cpd.ropeIndex - (IF cpd.done THEN 0 ELSE 1) - result.start; result.rope ¬ IO.RopeFromROS[workstr]; RETURN}; 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]; }; }; ParsePositioned: PUBLIC PROC [cmd: Handle, switchChar: CHAR ¬ '-] RETURNS [argv: PositionedArgumentVector] = { list: PositionedArgumentList ¬ NIL; nArgs: NAT ¬ 0; [list, nArgs] ¬ ParseToPositionedList[cmd: cmd, switchChar: switchChar]; argv ¬ NEW[PositionedArgumentVectorPrivate[nArgs]]; FOR i: NAT IN [0..nArgs) DO argv[i] ¬ list.first; list ¬ list.rest; ENDLOOP; RETURN}; StripVectorPositions: PUBLIC PROC [pargv: PositionedArgumentVector] RETURNS [argv: CommanderOps.ArgumentVector] ~ { argv ¬ NEW [CommanderOps.ArgHandleObject[pargv.argc]]; FOR i: NAT IN [0 .. argv.argc) DO argv[i] ¬ pargv[i].rope ENDLOOP; RETURN}; StripListPositions: PUBLIC PROC [plist: PositionedArgumentList] RETURNS [list: LIST OF ROPE] = { tail: LIST OF ROPE ¬ NIL; FOR plist ¬ plist, plist.rest WHILE plist#NIL DO this: LIST OF ROPE ~ LIST[plist.first.rope]; IF tail=NIL THEN list ¬ this ELSE tail.rest ¬ this; tail ¬ this; ENDLOOP; RETURN}; }.