(* Copyright (C) 1989, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* Last modified on Fri Mar 16 11:43:23 1990 by muller *) (* modified on Fri Sep 29 13:25:39 1989 by kalsow *) (* 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, M3toC, Wr, TextWr, Fmt, Scan; 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 IF wr # NIL THEN err := wr ELSE err := TextWr.New () END; 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 M3toC.argc - 1 DO IF NOT parsed[i] AND Text.Equal (key, M3toC.StoT (M3toC.argv[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 Wr.PutText (err, "ParseParams: keyword \"" & key & "\" not found.\n"); 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 M3toC.argc - 1 DO IF NOT parsed[i] THEN INC (bogus); IF bogus <= 5 THEN Wr.PutText (err, "ParseParams: parameter " & Fmt.Int (i) & " = \"" & M3toC.StoT (M3toC.argv[i]) & "\" extraneous or misplaced.\n"); END; END; END; IF bogus > 0 THEN IF bogus > MaxBogus THEN Wr.PutText (err, "(" & Fmt.Int (bogus - MaxBogus) & " more).\n"); 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 => Wr.PutText (err, "ParseParams: parameter " & Fmt.Int (NextParameter - 1) & " = \"" & txt & "\" should be an integer.\n"); RAISE Scan.BadFormat END; IF (nn < lo) OR (nn > hi) THEN Wr.PutText (err, "ParseParams: parameter " & Fmt.Int (NextParameter - 1) & " = " & Fmt.Int (nn) & " should be in [" & Fmt.Int (lo) & ".." & Fmt.Int (hi) & "].\n"); 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 => Wr.PutText (err, "ParseParams: parameter " & Fmt.Int (NextParameter - 1) & " = \"" & txt & "\" should be a real number.\n"); RAISE Scan.BadFormat END; IF (x < lo) OR (x > hi) THEN Wr.PutText (err, "ParseParams: parameter " & Fmt.Int (NextParameter - 1) & " = " & Fmt.Real (x) & " should be in [" & Fmt.Real (lo) & ".." & Fmt.Real (hi) & "].\n"); RAISE Scan.BadFormat END; RETURN x END GetNextReal; PROCEDURE GetNext (): Text.T RAISES {Scan.BadFormat} = BEGIN IF (NextParameter >= M3toC.argc) OR parsed[NextParameter] THEN Wr.PutText (err, "ParseParams: missing a parameter after parameter " & Fmt.Int (NextParameter - 1) & " = \"" & M3toC.StoT (M3toC.argv [NextParameter - 1]) & "\".\n"); RAISE Scan.BadFormat END; parsed[NextParameter] := TRUE; NextParameter := NextParameter + 1; RETURN M3toC.StoT (M3toC.argv[NextParameter - 1]); END GetNext; PROCEDURE TestNext (key: Text.T): BOOLEAN RAISES {} = BEGIN IF (NextParameter >= NumParameters) OR parsed[NextParameter] OR NOT Text.Equal (key, M3toC.StoT (M3toC.argv[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 M3toC.StoT (M3toC.argv [num]); END GetParameter; BEGIN NumParameters := M3toC.argc; END ParseParams.