(* Copyright (C) 1989, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* Last modified on Wed Mar 4 08:33:23 PST 1992 by kalsow *) (* modified on Sat Sep 15 02:51:50 1990 by muller *) (* modified on Mon Sep 5 17:21:33 1988 by stolfi *) (* modified on Fri Jun 10 14:20:12 1988 by glassman *) INTERFACE ParseParams; (* Keyword-oriented parsing of UNIX command arguments. This package simplifies parsing of typical UNIX command line syntax, consisting of a number of switches and keyword-labeled arguments, followed by a list of zero or more positional arguments. The switches and keyword-labeled arguments may be omitted, repeated, and given in any order. The package includes procedures to check for the presence of a given keyword anywhere in the command line, to fetch and parse the argument(s) after a given keyword, to check for extraneous switches, and so forth. For simple facilities (i.e. only NumParameters and GetParameter), see Params.i3. Index: shell, command line switches; Unix, command line switches; command line parsing; parsing, command line; arguments, from command line; parameters, from command line; switches, from command line *) (* For example, here is how to parse the command prt -width [ -landscape ] [ -pages ] ... [ file ... ] where the switches can be given in any order: *) (* TRY *) (* ParseParams.BeginParsing(Stdio.stderr); *) (* ParseParams.GetKeyword("-width"); *) (* width := ParseParams.GetNextInt(1,100); *) (* *) (* IF ParseParams.KeywordPresent("-landscape") *) (* THEN orientation := Landscape *) (* ELSE orientation := Portrait *) (* END; *) (* *) (* nRanges := 0; *) (* WHILE ParseParams.KeywordPresent("-pages") DO *) (* ini[nRanges] := ParseParams.GetNextInt(1,10000); *) (* fin[nRanges] := ParseParams.GetNextInt(ini[nRanges],10000); *) (* nRanges := nRanges+1; *) (* END; *) (* *) (* ParseParams.UnparsedTail(); *) (* nFiles := 0; *) (* WHILE ParseParams.NextParameter < ParseParams.NumParameters DO *) (* file[nFiles] := ParseParams.GetNext(); *) (* nFiles := nFiles+1 *) (* END; *) (* *) (* ParseParams.EndParsing(); *) (* *) (* EXCEPT *) (* | Scan.BadFormat => *) (* Wr.PrintF(stderr, "Usage: prt [ -pages n1 n2 ]... "); *) (* Wr.PrintF(stderr, "-width n3 [ -landscape ] [ file ... ]\n"); *) (* RTMisc.Exit (1); *) (* END; *) IMPORT Text, Wr, Scan; VAR (* READONLY *) NumParameters: CARDINAL; (* Parameters are indexed from 0 (the command name) to NumParameters-1. *) VAR NextParameter: CARDINAL; (* NextParameter points to the next parameter to be parsed in sequential mode. It is initialized to 1 by BeginParsing, and is modified implicitly by most procedures in this interface. It may also be set explicitly by the client. *) PROCEDURE BeginParsing (wr: Wr.T := NIL); (* Prepares to parse the parameter line. Marks all parameters as 'unparsed', and sets NextParameter to 1. If the /wr/ parameter is not NIL, any of the parsing routines below that detects an error will print an explanatory error message on /wr/ (with a terminating newline) just before raising Scan.BadFormat. *) (* WARNING: The current implementation is not reentrant. Multi-threaded clients should make sure that at most one thread is parsing the command line (i.e., between BeginParsing and EndParsing) at any time. *) PROCEDURE KeywordPresent (key: Text.T): BOOLEAN; (* Scans the command line looking for an unparsed argument equal to the given key. If such an argument is found, marks it as 'parsed', sets NextParameter to point to the following one, and returns TRUE. If the key is not found, just returns FALSE. The search always begins with argument 1, ignoring the current value of NextParameter. *) PROCEDURE GetKeyword (key: Text.T) RAISES {Scan.BadFormat}; (* Same as KeywordPresent, but raises "Scan.BadFormat" if key is not found. *) PROCEDURE EndParsing () RAISES {Scan.BadFormat}; (* Checks if all parameters have been parsed. If not, raises Scan.BadFormat. *) PROCEDURE GetNext (): Text.T RAISES {Scan.BadFormat}; (* Returns the next parameter. Also marks that parameter as 'parsed' and increments NextParameter. Raises Scan.BadFormat if the next parameter does not exist or has already been parsed. *) PROCEDURE TestNext (key: Text.T): BOOLEAN RAISES {}; (* If the next parameter is the given text, returns TRUE, marks that parameter as 'parsed', and increments the value of NextParameter. If the next parameter does not exist, has been parsed, or does not match the given text, does none of those things and returns FALSE. *) PROCEDURE GetNextInt (lo := FIRST (INTEGER); hi := LAST (INTEGER)): INTEGER RAISES {Scan.BadFormat}; (* Returns the next parameter as an integer value. Like GetNext, marks that parameter as 'parsed' and increments NextParameter. Raises Scan.BadFormat if the parameter does not exist, has already been parsed, is not a valid number of the right type, or is not in [lo..hi]. *) PROCEDURE GetNextReal (lo := -9.9e+29; hi := 9.9e+29): REAL RAISES {Scan.BadFormat}; (* Returns the next parameter as an integer or real value. Like GetNext, marks that parameter as 'parsed' and increments NextParameter. Raises Scan.BadFormat if the parameter does not exist, has already been parsed, is not a valid number of the right type, or is not in [lo..hi]. *) PROCEDURE UnparsedTail (); (* Positions NextParameter right after all parameters parsed so far. *) PROCEDURE WasParsed (num: CARDINAL): BOOLEAN; (* TRUE if the parameter with given index has already been parsed. *) PROCEDURE GetParameter (num: CARDINAL): Text.T; (* Fetches the parameter with specified index. Does not check whether the parameter has already been parsed, does not mark it as parsed, and does not change NextParameter. Returns NIL if num >= NumParameters. *) END ParseParams.