(* Copyright (C) 1989, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* Last modified on Thu Nov 7 08:47:32 PST 1991 by kalsow *) (* modified on Fri Apr 20 06:55:30 1990 by muller *) (* modified on Mon Apr 25 17:43:09 1988 by stolfi *) MODULE ParseShell; IMPORT Text, Rd, Wr, TextRd, TextWr, List, Scan, Thread; <*FATAL Rd.Failure, Rd.EndOfFile, Wr.Failure, Thread.Alerted*> PROCEDURE CopyNormal (rd: Rd.T; wr: Wr.T) RAISES {Scan.BadFormat} = VAR ch: CHAR; BEGIN LOOP IF Rd.EOF (rd) THEN EXIT END; ch := Rd.GetChar (rd); IF (ch = ' ') OR (ch = '\t') OR (ch = '\n') OR (ch = '\'') OR (ch = '\"') THEN Rd.UnGetChar (rd); EXIT END; IF ch = '\\' THEN IF Rd.EOF (rd) THEN RAISE Scan.BadFormat END; ch := Rd.GetChar (rd) END; Wr.PutChar (wr, ch); END; END CopyNormal; PROCEDURE CopyQuoted (targetCh: CHAR; rd: Rd.T; wr: Wr.T) RAISES {Scan.BadFormat} = VAR ch: CHAR; BEGIN LOOP IF Rd.EOF (rd) THEN RAISE Scan.BadFormat END; ch := Rd.GetChar (rd); IF ch = targetCh THEN EXIT END; Wr.PutChar (wr, ch); END; END CopyQuoted; PROCEDURE ToList (command: Text.T): List.T RAISES {Scan.BadFormat} = VAR rd: Rd.T; wr: Wr.T; ch: CHAR; l: List.T; BEGIN l := NIL; rd := TextRd.New (command); LOOP TRY (* skip blanks *) REPEAT ch := Rd.GetChar (rd); UNTIL (ch # ' ') AND (ch # '\t') AND (ch # '\n'); EXCEPT Rd.EndOfFile => RETURN List.ReverseD (l); END; wr := TextWr.New (); LOOP IF (ch = '\"') OR (ch = '\'') THEN CopyQuoted (ch, rd, wr) ELSE Rd.UnGetChar (rd); CopyNormal (rd, wr) END; IF Rd.EOF (rd) THEN EXIT END; ch := Rd.GetChar (rd); IF (ch = ' ') OR (ch = '\t') OR (ch = '\n') THEN EXIT END END; l := List.New (TextWr.ToText (wr), l); END; END ToList; PROCEDURE ArgsToList (args: Args): List.T = VAR l: List.T; BEGIN l := NIL; IF args # NIL THEN FOR i := LAST (args^) TO 0 BY -1 DO l := List.New (args[i], l) END END; RETURN List.ReverseD (l) END ArgsToList; PROCEDURE ListToArgs (list: List.T; old: Args := NIL): Args = VAR new: Args; nOld, i: CARDINAL; BEGIN IF list = NIL THEN RETURN old ELSE (* prepend list elemens, discarding old^[0]: *) IF (old = NIL) THEN nOld := 0 ELSE nOld := MAX (0, NUMBER (old^) - 1) END; new := NEW (Args, List.Length (list) + nOld); i := 0; WHILE list # NIL DO new[i] := NARROW (list.first, Text.T); INC (i); list := list.tail; END; FOR j := 1 TO nOld DO new[i] := old[j]; INC (i) END; RETURN new; END; END ListToArgs; BEGIN END ParseShell.