PositionedListImpl.mesa
Copyright Ó 1984, 1985, 1986, 1987, 1989, 1993 by Xerox Corporation. All rights reserved.
Swinehart, September 17, 1993 2:03 pm PDT
Russ Atkinson (RRA) March 2, 1987 7:36:27 pm PST
Last tweaked by Mike Spreitzer on February 22, 1988 6:04:50 pm PST
Willie-Sue, April 17, 1989 3:57:09 pm PDT
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: ROPENIL, -- command line passed from client
done: BOOLFALSE -- 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] = {
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
workstr: STREAM ¬ NIL;
chlook: CHAR;
delimiter for token: either blank, meaning blank
or switchchar (usually '-),
or '", or '", meaning '" not followed by another '".
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;
ch now contains a character to be included in the token
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};
}.