(* Copyright (C) 1989, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* Last modified on Wed Mar 4 08:42:55 PST 1992 by kalsow *) (* modified on Wed Mar 13 01:30:31 1991 by muller *) (* modified on Fri Jun 2 18:25:43 1989 by ellis *) (* modified on Tue Mar 22 22:33:04 1988 by stolfi *) MODULE ParseParams; IMPORT Text, Wr, Fmt, Scan, Thread, Params; VAR parsed: REF ARRAY OF BOOLEAN; (* Tells which parameters have been parsed *) err: Wr.T; (* Where to print error messages *) PROCEDURE BeginParsing (wr: Wr.T := NIL) = BEGIN err := wr; parsed := NEW (REF ARRAY OF BOOLEAN, NumParameters); FOR i := 0 TO NumParameters - 1 DO parsed[i] := FALSE END; NextParameter := 1; END BeginParsing; PROCEDURE KeywordPresent (key: Text.T): BOOLEAN = BEGIN FOR i := 1 TO NumParameters - 1 DO IF NOT parsed[i] AND Text.Equal (key, Params.Get(i)) THEN NextParameter := i + 1; parsed[i] := TRUE; RETURN TRUE; END END; RETURN FALSE END KeywordPresent; PROCEDURE GetKeyword (key: Text.T) RAISES {Scan.BadFormat} = BEGIN IF NOT KeywordPresent (key) THEN Error ("keyword \"", key, "\" not found."); RAISE Scan.BadFormat END; END GetKeyword; PROCEDURE EndParsing () RAISES {Scan.BadFormat} = CONST MaxBogus = 5; VAR bogus: CARDINAL; BEGIN (* Note: skips parameter 0 *) bogus := 0; FOR i := 1 TO NumParameters - 1 DO IF NOT parsed[i] THEN INC (bogus); IF bogus <= 5 THEN Error ("parameter ", Fmt.Int (i), " = \"", Params.Get (i), "\" extraneous or misplaced."); END; END; END; IF bogus > 0 THEN IF bogus > MaxBogus THEN Error ("(", Fmt.Int (bogus - MaxBogus), " more)."); END; RAISE Scan.BadFormat END; parsed := NIL; err := NIL; END EndParsing; PROCEDURE GetNextInt (lo := FIRST (INTEGER); hi := LAST (INTEGER)): INTEGER RAISES {Scan.BadFormat} = VAR nn: INTEGER; txt: Text.T; BEGIN txt := GetNext (); TRY nn := Scan.Int (txt); EXCEPT Scan.BadFormat => Error ("parameter ", Fmt.Int (NextParameter - 1), " = \"", txt, "\" should be an integer."); RAISE Scan.BadFormat END; IF (nn < lo) OR (nn > hi) THEN Error ("parameter ", Fmt.Int (NextParameter - 1), " = ", Fmt.Int (nn), " should be in [", Fmt.Int (lo), "..", Fmt.Int (hi), "]."); RAISE Scan.BadFormat END; RETURN nn END GetNextInt; PROCEDURE GetNextReal (lo := -9.9e+29; hi := 9.9e+29): REAL RAISES {Scan.BadFormat} = VAR x: REAL; txt: Text.T; BEGIN txt := GetNext (); TRY x := Scan.Real (txt); EXCEPT Scan.BadFormat => Error ("parameter ", Fmt.Int (NextParameter - 1), " = \"", txt, "\" should be a real number."); RAISE Scan.BadFormat END; IF (x < lo) OR (x > hi) THEN Error ("parameter ", Fmt.Int (NextParameter - 1), " = ", Fmt.Real (x), " should be in [", Fmt.Real (lo), "..", Fmt.Real (hi), "]."); RAISE Scan.BadFormat END; RETURN x END GetNextReal; PROCEDURE GetNext (): Text.T RAISES {Scan.BadFormat} = BEGIN IF (NextParameter >= NumParameters) OR parsed[NextParameter] THEN Error ("missing a parameter after parameter ", Fmt.Int (NextParameter - 1), " = \"", Params.Get (NextParameter - 1), "\"."); RAISE Scan.BadFormat END; parsed[NextParameter] := TRUE; NextParameter := NextParameter + 1; RETURN Params.Get (NextParameter - 1); END GetNext; PROCEDURE TestNext (key: Text.T): BOOLEAN RAISES {} = BEGIN IF (NextParameter >= NumParameters) OR parsed[NextParameter] OR NOT Text.Equal (key, Params.Get (NextParameter)) THEN RETURN FALSE ELSE parsed[NextParameter] := TRUE; NextParameter := NextParameter + 1; RETURN TRUE END; END TestNext; PROCEDURE WasParsed (num: CARDINAL): BOOLEAN = BEGIN RETURN (num < NumParameters) AND parsed[num] END WasParsed; PROCEDURE UnparsedTail () = BEGIN NextParameter := NumParameters; WHILE (NextParameter > 1) AND NOT parsed[NextParameter - 1] DO NextParameter := NextParameter - 1 END END UnparsedTail; PROCEDURE GetParameter (num: CARDINAL): Text.T = BEGIN RETURN Params.Get (num); END GetParameter; PROCEDURE Error (a, b, c, d, e, f, g, h, j: TEXT := NIL) = <*FATAL Wr.Failure, Thread.Alerted*> BEGIN IF (err = NIL) THEN RETURN END; Wr.PutText (err, "ParseParams: "); IF (a # NIL) THEN Wr.PutText (err, a) END; IF (b # NIL) THEN Wr.PutText (err, b) END; IF (c # NIL) THEN Wr.PutText (err, c) END; IF (d # NIL) THEN Wr.PutText (err, d) END; IF (e # NIL) THEN Wr.PutText (err, e) END; IF (f # NIL) THEN Wr.PutText (err, f) END; IF (g # NIL) THEN Wr.PutText (err, g) END; IF (h # NIL) THEN Wr.PutText (err, h) END; IF (j # NIL) THEN Wr.PutText (err, j) END; Wr.PutChar (err, '\n'); END Error; BEGIN NumParameters := Params.Count; END ParseParams.