/* arg_values This module contains a set of routines for aquiring values associated with argument strings in command lines. Usage: #include #include For IO_ERROR symbols int arg_values (type, argument, values, maximum); int type; The type of value(s) to get (in argvalues.h): STRING_VALUE INTEGER_VALUE LONG_VALUE FLOAT_VALUE char *argument; The argument string to search *values; The values vector to receive the values int maximum; The maximum number of values allowed char * chk_syntax (type, string) int type; As above char *string; The string to have its syntax checked Description: arg_values - The possible value types are: STRING (char *) INTEGER (int) LONG (long) FLOAT (float) The value(s) for an argument are always located immediately after the argument keyword, and separated from the keyword by a colon (:) character. There may be more than one value per argument. The value list is comma (,) or colon (:) separated in the argument string. The maximum number of values that will be obtained is indicated by maximum. Each value found is placed sequentially in the values vector. >>> WARNING <<< The argument string is chopped up into the value list strings by the replacement of trailing separator characters with EOS (0) values. If the original argument string is needed, a copy MUST be saved by the user. >>> NOTE <<< An argument with a list of strings, any one of which contains white space, must be enclosed in double quote (") characters (the entire argument string must be contained within the double quotes), and the individual strings in the list that contain whitespace must be enclosed in single quote (') characters. For example: "keyword:string_1,'string 2'" The values vector for STRINGS is an array of pointers to characters (char *). Each of these pointers refers to a location in the orginal argument string. The function returns the number of values actually found (0 if none found). If a syntax error occurs during value conversion, the search for values is halted and the following global variables have their values set: IO_ERROR is set to IE_BAD (Bad parameters) arg_string points to the bad character in the original argument string If no error occurs, IO_ERROR is FALSE (0) and arg_string points to the beginning of the values list in the original argument string. If dynamic memory cannot be allocated as needed, IO_ERROR is set to IE_NBF (No buffer space), and arg_string is NULL. chk_syntax - The string is checked to confirm that it is the character representation of a number of the specified type. For INTEGER_VALUE and LONG_VALUE only digits optionally preceeded by a sign (+ or -) are allowed. For FLOAT_VALUE the function atod declared as type int is used to return a pointer to the first invalid character in the string (which is EOS if the syntax is correct). A pointer to the first illegal character is returned for a string with bad syntax; otherwise NULL. ******************************************************************************/ #include #include IMPORTED STRING white_space; LOCAL STRING default_white; LOCAL STRING separators = " \t:,"; #define COLON ':' #define QUOTE '\'' STRING arg_string; /* Points to current value string */ INTEGER arg_index; /* Index to bad character in original arg string */ #define _ARG_VALUES_ #include #ifdef DEBUG LOCAL STRING type_names[] = { "STRING", "INTEGER", "LONG", "FLOAT" }; #endif GLOBAL STRING chk_syntax (); INTEGER arg_values (type, argument, values, maximum) COUNT type; STRING argument; union { STRING *are_strings; INTEGER *are_ints; LONG *are_longs; FLOAT *are_floats; } values; INTEGER maximum; { REGISTER STRING *strings; REGISTER STRING location; STRING pointers; IMPORTED LONG atol (); IMPORTED REAL atof (); #ifdef DEBUG COUNT count; printf ("arg_values: Searching for %d %s values\n\t%s\n", maximum, type_name[type], argument); #endif IO_ERROR = 0; if (maximum && (arg_string = search (argument, COLON))) { /* Parse the argument's value list into strings: */ #ifdef DEBUG if (type != STRING_VALUE) printf ("\t\tAllocate %d bytes of STRING array memory.\n", (sizeof (STRING) * (maximum + 1))); #endif if (type == STRING_VALUE) strings = values.are_strings; else if (! (strings = malloc (sizeof (STRING) * (maximum + 1)))) { arg_string = NULL; IO_ERROR = IE_NBF; return (NULL); } default_white = white_space; white_space = separators; #ifdef DEBUG printf ("Parse the argument list\n"); #endif maximum = arg_parse (++arg_string, strings, maximum); white_space = default_white; #ifdef DEBUG printf ("\t%d value strings:\n", maximum); for (count = 0; count < maximum; count++) printf ("\t\t%s\n", strings[count]); #endif if (type != STRING_VALUE) { /* Convert the value strings into the appropriate value vector: */ strings[maximum] = NULL; /* Mark end of values strings */ pointers = strings; for (maximum = 0; *strings; maximum++, strings++) { if (location = chk_syntax (type, *strings)) { arg_index = location - argument; arg_string = *strings; #ifdef DEBUG printf ("\tBad number syntax for %s\n\t(character %d of argument)\n", *strings, arg_index); #endif IO_ERROR = IE_BAD; break; } switch (type) { case INTEGER_VALUE: *values.are_ints++ = atoi (*strings); break; case LONG_VALUE: *values.are_longs++ = atol (*strings); break; case FLOAT_VALUE: *values.are_floats = atof (*strings); /* This kluge gets around a compiler bug in which pointers to float are not correctly autoincremented when used with indirection! */ values.are_floats++; break; } } mfree (pointers); #ifdef DEBUG printf ("\t\tPointers memory freed.\n"); #endif } } else maximum = 0; /* No values in this argument string */ return (maximum); } /* The string is checked to see if it has any illegal characters. If it does, a pointer to the bad character is returned; otherwise NULL is returned. */ STRING chk_syntax (type, string) COUNT type; STRING string; { IMPORTED INTEGER atod (); /* This way gives pntr to non-valid */ switch (type) { case INTEGER_VALUE: case LONG_VALUE: if (*string == '+' || *string == '-') string++; while (isdigit (*string++)); string--; break; case FLOAT_VALUE: string = (STRING)atod (string); break; default: return (NULL); } if (*string) return (string); else return (NULL); }