/*------------------------------------------------------------------------- Routine: int UTdecOption (const char String[], const char Option[], const char **Arg) Purpose: Match a string to an option keyword Description: This subroutine checks for a match to an option keyword string. The keyword string can specify the minimum length for a match. The option keyword is a string with an optional asterisk ('*') which is used to indicate the minimum number of characters needed for a match. A trailing '#' indicates that an argument follows the keyword. A trailing '=' indicates that the argument is separated from the keyword by a '=' character. On finding an argument, this routine returns a pointer to the beginning of the argument part of the input string. Example keywords: "abc" - Simple option, all characters have to match "a*bc" - Variable length option, matches a substring of "abc" "ab#" - Simple keyword followed by an argument. The string "ab33" matches with an argument value of "33". "a*bc=" - Variable length keyword followed by an argument separated by a '=' character. The string "ab=33" matches with an argument value of "33". Parameters: <- int *UTdecOption Status status. -2, Matches an option, but argument missing 0, Not a recognized option 1, Matches an option, argument present or not needed -> const char String[] Input character string -> const char Option[] Input option keyword specification <- const char **Arg Argument string. For an option with the argument following as part of the input string, this is a pointer to a null terminated substring of String. If the decoded option does not take a value or the value is missing, this pointer will be NULL. Author / revision: P. Kabal Copyright (C) 1995 $Revision: 1.20 $ $Date: 1995/06/01 11:07:32 $ -------------------------------------------------------------------------*/ static char rcsid[] = "$Id: UTdecOption.c 1.20 1995/06/01 AFsp-V2R1 $"; #include #include #define NOSTAR 0 #define STAR 1 #define NOARG 0 #define HASH 1 #define EQUAL 2 #define NOMATCH 0 #define MATCH 1 #define MVAL -2 int UTdecOption (String, Option, Arg) const char String[]; const char Option[]; const char **Arg; { const char *k; const char *kend; const char *s; int lenk; int state, argt; /* See if an argument is needed NOARG - No argument allowed HASH - Argument follows directly EQUAL - Argument follows an equal sign kend is the character past the last one of interest for matching */ lenk = strlen (Option); kend = &Option[lenk]; argt = NOARG; if (lenk > 0) { if (Option[lenk-1] == '#') { --kend; argt = HASH; } else if (Option[lenk-1] == '=') { --kend; argt = EQUAL; } } /* Main loop to check matching characters */ state = NOSTAR; for (k = Option, s = String; k < kend && *s != '\0'; ++k) { if (*k == '*' && state == NOSTAR) { state = STAR; } else if (*s != *k) goto MisMatch; else ++s; } /* Update the state. Every option keyword has an implicit asterisk at the end if there is not an asterisk in the keyword */ if (state == NOSTAR && (k == kend || *k == '*')) state = STAR; /* Finished loop, check for a match */ /* There are two cases; String has been exhausted or not. The latter case has two subcases. But only one of these can result from falling out of the loop. The other corresponds to a jump out of the loop. (1) String finished if we have matched the minimum number of characters, then we have a match - return the null in String (no argument) (2) String not finished (a) Option is finished if no argument is expected - declare a mismatch if an argument is expected - the rest is an argument (b) Option not finished This results from a mismatch (goto MisMatch) no argument is expected - this is a true mismatch an argument is expected - a match if the mismatch is due to a '=' */ if (*s == '\0') { /* case (1) */ if (state == STAR) { *Arg = NULL; if (argt != NOARG) return MVAL; else return MATCH; } } else { /* case (2a) */ if (argt == HASH) { *Arg = s; return MATCH; } else if (argt == EQUAL && *s == '=') { *Arg = s+1; return MATCH; } } *Arg = NULL; return NOMATCH; /* ===================== */ /* Last characters tested did not match */ MisMatch: /* case (2b) */ if (state == STAR && argt == EQUAL && *s == '=') { *Arg = s+1; return MATCH; } *Arg = NULL; return NOMATCH; }