tomwalters@0: /* tomwalters@0: Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989 tomwalters@0: =========================================================================== tomwalters@0: tomwalters@0: Permission to use, copy, modify, and distribute this software without fee tomwalters@0: is hereby granted for research purposes, provided that this copyright tomwalters@0: notice appears in all copies and in all supporting documentation, and that tomwalters@0: the software is not redistributed for any fee (except for a nominal shipping tomwalters@0: charge). Anyone wanting to incorporate all or part of this software in a tomwalters@0: commercial product must obtain a license from the Medical Research Council. tomwalters@0: tomwalters@0: The MRC makes no representations about the suitability of this tomwalters@0: software for any purpose. It is provided "as is" without express or implied tomwalters@0: warranty. tomwalters@0: tomwalters@0: THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING tomwalters@0: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE tomwalters@0: A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY tomwalters@0: DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN tomwalters@0: AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF tomwalters@0: OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. tomwalters@0: */ tomwalters@0: tomwalters@0: /* ------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: The Leanest Resource Manager in the West. tomwalters@0: tomwalters@0: Options may be supplied as defaults (actually in the code), as command line tomwalters@0: arguments, and in a option file. The default arguments may be overridden by tomwalters@0: the option-file contents, which may be overridden from the command line. tomwalters@0: tomwalters@0: Copyright (c), 1989 The Medical Research Council of the United Kingdom. tomwalters@0: tomwalters@0: Author : Paul Manson tomwalters@0: Written : March 1st 1989 tomwalters@0: tomwalters@0: Edited : tomwalters@0: tomwalters@0: 2nd March 1989 (Paul Manson) Added the facility of searching the HOME directory tomwalters@0: for a option file if one is not found in the tomwalters@0: working directory. tomwalters@0: tomwalters@0: 8th March 1989 (Paul Manson) Enhanced the above by providing a OPTIONPATH tomwalters@0: search strategy for Unix. Currently MSDOS only tomwalters@0: searches for a option file in the directory tomwalters@0: where the program was found. tomwalters@0: tomwalters@0: 8th March 1989 (Paul Manson) Added the ability to refer to options via tomwalters@0: abbreviations of their names. At present, an abbrev. tomwalters@0: will match if it is exactly the same as precisely one tomwalters@0: option, or if it is the same as the first chars tomwalters@0: of that option (where is the length of the tomwalters@0: abbrev) and it matches no other option name. tomwalters@0: tomwalters@0: 9th March 1989 (Paul Manson) Added the readopts and writeopts calls, to implement tomwalters@0: option headers for files. Also altered the form tomwalters@0: of command line options accepted: See getopts.h for tomwalters@0: details. tomwalters@0: tomwalters@0: 10th March 1989 (Paul Manson) Added the "help" facility to provide a simple tomwalters@0: self-documentation facility. Also altered the tomwalters@0: Option type to put defaults and comments in tomwalters@0: the code. tomwalters@0: tomwalters@0: 16th March 1989 (Paul Manson) Altered the final argc/argv shuffling in getopts tomwalters@0: so that argv simply points at the first argument tomwalters@0: after the options. Also added fileopts. tomwalters@0: tomwalters@0: 29th March 1989 (Paul Manson) Altered ".res" to ".opt" to coincide with the new tomwalters@0: naming r'egime. Also added the spitOptionsFile call tomwalters@0: to automatically produce an options file with tomwalters@0: comments. To enable this facility, compile getopts tomwalters@0: with -DSPITHELP; to use it, type -spit. Do tomwalters@0: NOT distribute a spitting version of getopts! Altered tomwalters@0: Options-file scanning to permit trailing comments. tomwalters@0: tomwalters@0: 30th March 1989 (Paul Manson) Completely eradicated the blockWriteToFile used by tomwalters@0: writenopts. This is now done on a non-aligned basis, tomwalters@0: as this is likely to be quicker and less complex. tomwalters@0: tomwalters@0: 03rd April 1989 (Paul Manson) Added the calll to outputopt. tomwalters@0: tomwalters@0: 06th April 1989 (Paul Manson) Oh Joy! Oh Bliss! The once-much-maligned SPIT option tomwalters@0: is recieved into decent society, albeit in the guise tomwalters@0: of an options "editor" called 'update'. tomwalters@0: tomwalters@0: 10th April 1989 (Paul Manson) The 'update' option no longer exit(1)s, but tomwalters@0: carries on to execute the program. Also changed tomwalters@0: OptionFileName so that it correctly gets the tomwalters@0: cwd on the PC. tomwalters@0: tomwalters@0: 11th April 1989 (Paul Manson) Altered the OptionFileName routines to be EITHER tomwalters@0: for the PC or for Unix. tomwalters@0: tomwalters@0: 26th April 1989 (Paul Manson) Put in a temporary delta to the PC version so that it tomwalters@0: only looks for option files (and hence only creates tomwalters@0: option files) in the current directory. This will be tomwalters@0: abandoned when we determine a better search strategy. tomwalters@0: tomwalters@0: 15th June 1989 (Paul Manson) Altered SilentOption so that it is alterable, but is tomwalters@0: NOT visible in any way (ie. not printed by help or tomwalters@0: spit, and not output to headers). tomwalters@0: tomwalters@0: 11th July 1989 (Paul Manson) Altered so that "help" (and "update") only display tomwalters@0: (or output) the options which were either read in tomwalters@0: from the options file, or have been subsequently tomwalters@0: altered on the command line. The current implementation tomwalters@0: simply checks to see whether the default and current tomwalters@0: values for a particular option differ (either in value tomwalters@0: OR address!). tomwalters@0: tomwalters@0: 27th July 1989 (Paul Manson) Altered so that isON == !isOFF, and not the other way tomwalters@0: around -- this allows "2", "3", etc to masquerade as tomwalters@0: "1" while only "0" is "off". Also changed so that no tomwalters@0: quotes are output to file headers. tomwalters@0: tomwalters@0: tomwalters@0: July 1994 (MAA) Allowed spaces in strings, by adding double-quotes tomwalters@0: to the arguments. Bit of a hack, though. tomwalters@0: ------------------------------------------------------------------------------- */ tomwalters@0: tomwalters@0: #include "options.h" tomwalters@0: #include tomwalters@0: #include tomwalters@0: #if defined( NeXT) tomwalters@0: #include tomwalters@0: #else tomwalters@0: #include tomwalters@0: #endif tomwalters@0: #include tomwalters@0: tomwalters@0: #if !defined( lint ) tomwalters@0: static char *sccs_id = "@(#)options.c 1.14 Paul Manson (MRC-APU) 5/2/89"; tomwalters@0: #endif tomwalters@0: tomwalters@0: char defversion[64] = "not set yet" , *versionstr = defversion ; tomwalters@0: tomwalters@0: #if defined( PC ) tomwalters@0: #include tomwalters@0: #define DOT '.' tomwalters@0: #define BACKSLASH_CHAR '\\' tomwalters@0: #define SLASH_CHARACTER '/' tomwalters@0: #define OPTION_FILE_PREFIX "" tomwalters@0: #define OPTION_FILE_SUFFIX ".opt" tomwalters@0: #else tomwalters@0: #ifndef THINK_C tomwalters@0: #include tomwalters@0: #include tomwalters@0: #endif tomwalters@0: #define OPTION_FILE_PREFIX "." tomwalters@0: #define OPTION_FILE_SUFFIX "rc" tomwalters@0: #define OPTION_PATH "OPTIONSPATH" tomwalters@0: /* Environment variable for path */ tomwalters@0: #define DEFAULT_OPTION_PATH "." tomwalters@0: /* Path is first . then ~ (ie home) */ tomwalters@0: #endif tomwalters@0: tomwalters@0: #define MAX_LINE_LENGTH (256) tomwalters@0: #define MAX_NAME_LENGTH (128) tomwalters@0: #define FALSE (0) tomwalters@0: #define TRUE (1) tomwalters@0: #define HYPHEN_CHARACTER '-' tomwalters@0: #define BLANK_CHARACTER ' ' tomwalters@0: #define TAB_CHARACTER '\t' tomwalters@0: #define NEWLINE_CHARACTER '\n' tomwalters@0: #define DOUBLE_QUOTE_CHAR '\"' tomwalters@0: #define ERROR_RESULT (1234) tomwalters@0: #define EQUALS_CHARACTER '=' tomwalters@0: #define COMMENT_CHARACTER '#' tomwalters@0: #define NULL_CHARACTER '\000' tomwalters@0: #define CARRIAGE_RETURN '\r' tomwalters@0: tomwalters@0: /* Options-specific definitions for "ON", "OFF" and "NULL" */ tomwalters@0: tomwalters@0: #define ON_STRING (ON_OPTION) tomwalters@0: #define ON_ALIAS "1" tomwalters@0: tomwalters@0: #define OFF_STRING (OFF_OPTION) tomwalters@0: #define OFF_ALIAS "0" tomwalters@0: tomwalters@0: #define NULL_STRING (NULL_OPTION) tomwalters@0: #define NULL_ALIAS "null" tomwalters@0: tomwalters@0: #define NOT_USED "Not_used" tomwalters@0: tomwalters@0: /* For the search_path and Ambiguity procedures */ tomwalters@0: tomwalters@0: #define LINE_CHARS 200 tomwalters@0: #define AMBIGUOUS (-2) tomwalters@0: #define NO_MATCH (-1) tomwalters@0: #define DEFAULT_TOGGLE_VALUE (ON_STRING) tomwalters@0: tomwalters@0: /* For the readopts and writeopts procedures */ tomwalters@0: tomwalters@0: #define OPTION_HEADER_SIZE ( sizeof ( head_string_start ) - 1 + size_digits + 1 ) tomwalters@0: #define OPTION_HEADER_HEADER "header_bytes=" tomwalters@0: #define OPTION_HEADER_DIGITS (7) tomwalters@0: tomwalters@0: #define min(X,Y) (((X) < (Y)) ? (X) : (Y)) tomwalters@0: tomwalters@0: static char OptionHeaderHeader[] = OPTION_HEADER_HEADER; tomwalters@0: static char LineFeedArray[] = "\n"; tomwalters@0: static char EqualsArray[] = "="; /* Was " = " */ tomwalters@0: static char QuotesArray[] = "\""; tomwalters@0: tomwalters@0: /* For the OnLine Help Facility */ tomwalters@0: tomwalters@0: #define HELP_STRING "help" tomwalters@0: #define UPDATE_STRING "update" tomwalters@0: #define ALL_STRING "all" tomwalters@0: tomwalters@0: static int helpOnAllRequired = FALSE; tomwalters@0: static int helpOnOneRequired = FALSE; tomwalters@0: static int helpOnOneLocation = 0; tomwalters@0: static int updateAllRequired = FALSE; tomwalters@0: tomwalters@0: extern void exit(); tomwalters@0: static int thereWasAnOptionsFile = FALSE; tomwalters@0: static char *theOptionFileName = NULL; tomwalters@0: tomwalters@0: tomwalters@0: tomwalters@0: tomwalters@0: #ifndef PC tomwalters@0: /* ----------------------------------------------------------------------- tomwalters@0: tomwalters@0: search_path( file, path ) tomwalters@0: ========================= tomwalters@0: tomwalters@0: jwh - 4th jan 1987 tomwalters@0: tomwalters@0: searches through string path for file and returns full file name if it tomwalters@0: finds it. Returns NULL if file is not found. Path is specified in normal tomwalters@0: path format i.e. "dir1:dir2:dir3...". Works for "~" and "~/dir.." - tomwalters@0: substitutes HOME for "~". ~ only works for current user!! tomwalters@0: tomwalters@0: ----------------------------------------------------------------------- */ tomwalters@0: tomwalters@0: tomwalters@0: static char *search_path( file, path ) tomwalters@0: char *file, *path ; tomwalters@0: { tomwalters@0: #ifdef THINK_C tomwalters@0: return ( file ) ; tomwalters@0: #else tomwalters@0: char file_name[ LINE_CHARS ] ; tomwalters@0: int len_next ; tomwalters@0: struct stat buf ; tomwalters@0: extern getenv(); tomwalters@0: char *home_directory = (char *)getenv("HOME"); tomwalters@0: tomwalters@0: if( file[ 0 ] == '/' || file[ 0 ] == '.' && file[ 1 ] == '/' ) tomwalters@0: return ( strcpy( malloc((unsigned)(strlen(file) + 1)), file) ); tomwalters@0: tomwalters@0: do tomwalters@0: { tomwalters@0: len_next = ( strchr( path, ':' ) == NULL ) ? tomwalters@0: strlen( path ) : strchr( path, ':' ) - path ; tomwalters@0: tomwalters@0: if( *path == '~' ) tomwalters@0: { tomwalters@0: (void) strcpy( file_name, home_directory ) ; tomwalters@0: (void) strncpy( file_name + strlen( home_directory ), path+1, tomwalters@0: len_next-1 ) ; tomwalters@0: (void) sprintf( file_name + strlen( home_directory ) + len_next - 1 , tomwalters@0: "/%s", file ) ; tomwalters@0: } tomwalters@0: else tomwalters@0: { tomwalters@0: (void) strncpy( file_name, path, len_next ) ; tomwalters@0: (void) sprintf( file_name + len_next , "/%s", file ) ; tomwalters@0: } tomwalters@0: tomwalters@0: if( stat( file_name, &buf ) >= 0 && ( buf.st_mode & S_IFDIR ) == 0 ) tomwalters@0: return ( strcpy( malloc((unsigned)(strlen(file_name) + 1)), file_name) ); tomwalters@0: tomwalters@0: path = path + len_next + 1 ; tomwalters@0: } tomwalters@0: while( path[ -1 ] != '\0' ) ; tomwalters@0: tomwalters@0: /* return( NULL ) ; */ return( file ); /* If PATH is NULL, return FILE */ tomwalters@0: #endif tomwalters@0: } tomwalters@0: tomwalters@0: /* --------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: Return the Option File Name, given the Name of the Application (Unix Version) tomwalters@0: tomwalters@0: Edited: tomwalters@0: tomwalters@0: --------------------------------------------------------------------------------- */ tomwalters@0: char *UnixOptionFileName(appn) tomwalters@0: char *appn ; tomwalters@0: { tomwalters@0: char *temp; tomwalters@0: tomwalters@0: temp = malloc((unsigned) (strlen(appn) + strlen(OPTION_FILE_SUFFIX) + tomwalters@0: strlen(OPTION_FILE_PREFIX) + 1)); tomwalters@0: tomwalters@0: temp = strcpy(temp,OPTION_FILE_PREFIX); tomwalters@0: temp = strcat(temp,appn); tomwalters@0: temp = strcat(temp,OPTION_FILE_SUFFIX); tomwalters@0: tomwalters@0: tomwalters@0: return (temp); tomwalters@0: } tomwalters@0: #endif /* Unix Option File Stuff */ tomwalters@0: tomwalters@0: #if defined( PC ) tomwalters@0: tomwalters@0: /* --------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: Return the Option File Name, given the Name of the Application (PC Version) tomwalters@0: tomwalters@0: Edited: tomwalters@0: tomwalters@0: --------------------------------------------------------------------------------- */ tomwalters@0: char *PCOptionFileName(appn, onlyLocal) tomwalters@0: char *appn ; tomwalters@0: int onlyLocal; tomwalters@0: { tomwalters@0: char *temp; tomwalters@0: int i ; tomwalters@0: char *temp2, *lastPart; tomwalters@0: tomwalters@0: tomwalters@0: temp = malloc((unsigned) (strlen(appn) + strlen(OPTION_FILE_SUFFIX) + tomwalters@0: strlen(OPTION_FILE_PREFIX) + 1)); tomwalters@0: tomwalters@0: temp = strcpy(temp, appn); tomwalters@0: tomwalters@0: for (i = 0; temp[i] != NULL_CHARACTER; i++) tomwalters@0: if (temp[i] == BACKSLASH_CHAR) tomwalters@0: temp[i] = SLASH_CHARACTER; tomwalters@0: tomwalters@0: /* Strip Back to the Application Name */ tomwalters@0: if ((lastPart = strrchr(temp, SLASH_CHARACTER)) == NULL) tomwalters@0: lastPart = temp; tomwalters@0: else tomwalters@0: lastPart++; /* Skip over the actual "/" */ tomwalters@0: tomwalters@0: /* lastPart points to the tail name of the path */ tomwalters@0: tomwalters@0: if ((temp2 = strchr(lastPart,DOT)) == NULL) tomwalters@0: temp = strcat(temp,OPTION_FILE_SUFFIX); tomwalters@0: else tomwalters@0: temp2 = strcpy(temp2, OPTION_FILE_SUFFIX); tomwalters@0: tomwalters@0: if (onlyLocal) /* Remove the full path to give only a local name */ tomwalters@0: return( lastPart); tomwalters@0: else tomwalters@0: return (temp); tomwalters@0: } tomwalters@0: #endif /* PC Version of OptionFileName */ tomwalters@0: tomwalters@0: tomwalters@0: /* --------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: Check that there is no ambiguity in the (possibly abbreviated) . If there is tomwalters@0: no match whatever, return NO_MATCH. If there is a single exact match, or a single tomwalters@0: abbreviating match, return the index of the matched option; otherwise return tomwalters@0: AMBIGUOUS. tomwalters@0: tomwalters@0: --------------------------------------------------------------------------------- */ tomwalters@0: int Ambiguity(options, numOptions, name) tomwalters@0: Option options[] ; tomwalters@0: int numOptions; tomwalters@0: char *name ; tomwalters@0: { tomwalters@0: int i, matched, matchedExactly, matchedWhere, moreThanOneInexactMatch; tomwalters@0: tomwalters@0: matched = FALSE; tomwalters@0: matchedExactly = FALSE; tomwalters@0: moreThanOneInexactMatch = FALSE; tomwalters@0: tomwalters@0: for (i = 0; i < numOptions; i++) tomwalters@0: if (options[i].classification != OutputOption && tomwalters@0: strncmp(name, options[i].name, strlen(name)) == 0) { tomwalters@0: if (matched) { tomwalters@0: if (matchedExactly) { tomwalters@0: if (strcmp(name, options[i].name) == 0) { tomwalters@0: /* TWO Exact Matches */ tomwalters@0: return AMBIGUOUS; tomwalters@0: } tomwalters@0: } tomwalters@0: else { tomwalters@0: if (strcmp(name, options[i].name) == 0) { tomwalters@0: /* THIS is an exact match */ tomwalters@0: matchedExactly = TRUE; tomwalters@0: matchedWhere = i; tomwalters@0: } tomwalters@0: else { tomwalters@0: /* There are two inexact matches ... if there are no exact ones we tomwalters@0: have AMBIGUITY */ tomwalters@0: moreThanOneInexactMatch = TRUE; tomwalters@0: } tomwalters@0: } tomwalters@0: } tomwalters@0: else { tomwalters@0: if (strcmp(name, options[i].name) == 0) { tomwalters@0: /* This is an exact match */ tomwalters@0: matchedExactly = TRUE; tomwalters@0: } tomwalters@0: matched = TRUE; tomwalters@0: matchedWhere = i ; tomwalters@0: } tomwalters@0: } tomwalters@0: tomwalters@0: if (moreThanOneInexactMatch) tomwalters@0: return (AMBIGUOUS); tomwalters@0: else { tomwalters@0: if (matched) tomwalters@0: return (matchedWhere); tomwalters@0: else tomwalters@0: return (NO_MATCH); tomwalters@0: } tomwalters@0: tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* --------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: Search for the named option in the list of options. If it is found, return its tomwalters@0: location (index) in the options array. Otherwise, return NO_MATCH. tomwalters@0: tomwalters@0: --------------------------------------------------------------------------------- */ tomwalters@0: int LookUp(options, numOptions, name) tomwalters@0: Option options[] ; tomwalters@0: int numOptions; tomwalters@0: char *name ; tomwalters@0: { tomwalters@0: int i; tomwalters@0: tomwalters@0: for (i = 0; i < numOptions; i++) tomwalters@0: if (options[i].classification != OutputOption && strcmp(name, options[i].name) == 0) { tomwalters@0: return (i); tomwalters@0: } tomwalters@0: tomwalters@0: return (NO_MATCH); tomwalters@0: tomwalters@0: } tomwalters@0: tomwalters@0: extern helpRoutine *onLineHelpHandler; tomwalters@0: extern void updateOptionsFile(); tomwalters@0: tomwalters@0: /* --------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: Search for the named option in the list of options. If it is found, set its tomwalters@0: new value as indicated and return TRUE. If not, return either FALSE or AMBIGUOUS. tomwalters@0: tomwalters@0: Edited: tomwalters@0: tomwalters@0: 8th March 1989 (Paul Manson) Changed the call to LookUp to call Ambiguity instead, tomwalters@0: thus achieving the matching of abbreviated options. tomwalters@0: tomwalters@0: 15th March 1989 (Paul Manson) Reinstated the call to LookUp in the case that tomwalters@0: abbreviations (and hence ambiguity) are/is not tomwalters@0: permitted (ie. in option Header Files). tomwalters@0: tomwalters@0: --------------------------------------------------------------------------------- */ tomwalters@0: int LookUpAndStore(options, numOptions, name, value, permitAbbrevs, programName) tomwalters@0: Option options[] ; tomwalters@0: int numOptions ; tomwalters@0: char *name, *value; tomwalters@0: int permitAbbrevs; tomwalters@0: char *programName ; tomwalters@0: { tomwalters@0: int loc ; tomwalters@0: char *temp; tomwalters@0: tomwalters@0: /* Account for specific references to the "help" option, with different tomwalters@0: treatment of the "help=all" command */ tomwalters@0: if (strcmp(name, HELP_STRING) == 0) { tomwalters@0: /* Check whether it is asking for ALL help */ tomwalters@0: if (strcmp(value, ALL_STRING) == 0) { tomwalters@0: helpOnAllRequired = TRUE; tomwalters@0: helpOnOneRequired = FALSE; tomwalters@0: (*onLineHelpHandler)(options, numOptions, programName); tomwalters@0: exit(0); tomwalters@0: } tomwalters@0: /* Check for other specific kinds of help request */ tomwalters@0: /* else if (strcmp(value, _STRING) == 0) { */ tomwalters@0: tomwalters@0: tomwalters@0: else { tomwalters@0: /* Expand the (possibly abbreviated) option name */ tomwalters@0: if ((permitAbbrevs && ((loc = Ambiguity(options, numOptions, value)) >= 0)) || tomwalters@0: (!permitAbbrevs && ((loc = LookUp(options, numOptions, value)) >= 0))) { tomwalters@0: helpOnOneRequired = TRUE; tomwalters@0: helpOnAllRequired = FALSE; tomwalters@0: helpOnOneLocation = loc ; tomwalters@0: (*onLineHelpHandler)(options, numOptions, programName); tomwalters@0: exit(0); tomwalters@0: } tomwalters@0: else { tomwalters@0: if (loc == AMBIGUOUS) { tomwalters@0: (void) fprintf(stderr, "WARNING: The option name %s is AMBIGUOUS; please be more specific.\n", value); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: else { tomwalters@0: (void) fprintf(stderr, "WARNING: The %s program does not have an option named %s.\n", tomwalters@0: programName, value); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: } tomwalters@0: } tomwalters@0: } tomwalters@0: else if (strcmp(name, UPDATE_STRING) == 0) { tomwalters@0: /* Check whether it is asking for ALL updated */ tomwalters@0: if (strcmp(value, ALL_STRING) == 0) { tomwalters@0: updateAllRequired = TRUE ; tomwalters@0: updateOptionsFile(options, numOptions, programName, theOptionFileName); tomwalters@0: updateAllRequired = FALSE; tomwalters@0: helpOnAllRequired = TRUE ; tomwalters@0: helpOnOneRequired = FALSE; tomwalters@0: return (TRUE); tomwalters@0: } tomwalters@0: else { tomwalters@0: /* At present there is no use for a specific update call */ tomwalters@0: (void) fprintf(stderr, "options: The update option may not be altered!\n"); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: } tomwalters@0: else if ((permitAbbrevs && ((loc = Ambiguity(options, numOptions, name)) >= 0)) || tomwalters@0: (!permitAbbrevs && ((loc = LookUp(options, numOptions, name)) >= 0))) { tomwalters@0: /* It is a conventional "LookUpAndStore" operation */ tomwalters@0: temp = malloc((unsigned)(strlen(value) + 1)); tomwalters@0: temp = strcpy(temp, value); tomwalters@0: *(options[loc].value) = temp; tomwalters@0: return (TRUE); tomwalters@0: } tomwalters@0: else { tomwalters@0: if (loc == AMBIGUOUS) { tomwalters@0: #if defined( PC ) tomwalters@0: (void) fprintf(stderr, tomwalters@0: "ERROR: The name %s is AMBIGUOUS, and the value %s has not been assigned to any option\n", name, value); tomwalters@0: exit(1); tomwalters@0: #else tomwalters@0: (void) fprintf(stderr, tomwalters@0: "WARNING: The name %s is AMBIGUOUS, and the value %s has not been assigned to any option\n", name, value); tomwalters@0: return (AMBIGUOUS); tomwalters@0: #endif tomwalters@0: } tomwalters@0: else tomwalters@0: return (FALSE); tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* --------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: Skip Blanks and Tabs. Stop at a printable character or a newline or null. tomwalters@0: tomwalters@0: --------------------------------------------------------------------------------- */ tomwalters@0: char *skipBlanks (ptr) tomwalters@0: char *ptr; tomwalters@0: { tomwalters@0: while ((*ptr == BLANK_CHARACTER) || (*ptr == TAB_CHARACTER)) ptr++; tomwalters@0: tomwalters@0: return (ptr); tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* --------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: Ensure that the next character is an '='. If it is, return a pointer to the first tomwalters@0: character after the '='; otherwise, return NULL. tomwalters@0: tomwalters@0: --------------------------------------------------------------------------------- */ tomwalters@0: char *skipEquals (ptr) tomwalters@0: char *ptr; tomwalters@0: { tomwalters@0: if (ptr[0] == EQUALS_CHARACTER) tomwalters@0: return (++ptr); tomwalters@0: else tomwalters@0: return (NULL); tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* --------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: Read a name (ie. a token, a contiguous sequence of nonblank characters, or a tomwalters@0: quoted string) from the string pointed to by ptr, and copy it the buffer pointed tomwalters@0: to by . If successful, return a pointer to the character after the token; tomwalters@0: otherwise, return NULL. tomwalters@0: tomwalters@0: --------------------------------------------------------------------------------- */ tomwalters@0: char *getName (ptr, name) tomwalters@0: char *ptr, *name; tomwalters@0: { tomwalters@0: char *temp, *i, *namePtr; tomwalters@0: char stopChar; tomwalters@0: tomwalters@0: if (ptr[0] == DOUBLE_QUOTE_CHAR) { tomwalters@0: ptr++; tomwalters@0: stopChar = DOUBLE_QUOTE_CHAR; tomwalters@0: } tomwalters@0: else tomwalters@0: stopChar = BLANK_CHARACTER; tomwalters@0: tomwalters@0: temp = ptr; tomwalters@0: tomwalters@0: while (*temp != NULL_CHARACTER && tomwalters@0: *temp != NEWLINE_CHARACTER && tomwalters@0: *temp != CARRIAGE_RETURN && tomwalters@0: ((stopChar == DOUBLE_QUOTE_CHAR && *temp != stopChar) || tomwalters@0: (stopChar == BLANK_CHARACTER && tomwalters@0: (*temp != stopChar && *temp != TAB_CHARACTER && *temp != EQUALS_CHARACTER)))) tomwalters@0: temp++; tomwalters@0: tomwalters@0: if (stopChar == DOUBLE_QUOTE_CHAR && *temp != DOUBLE_QUOTE_CHAR) { tomwalters@0: (void) fprintf(stderr, "options: Improperly closed quoted string %s\n", --ptr); tomwalters@0: return (NULL); tomwalters@0: } tomwalters@0: tomwalters@0: namePtr = name; tomwalters@0: tomwalters@0: for (i = ptr; i < temp; ) tomwalters@0: *namePtr++ = *i++; tomwalters@0: tomwalters@0: *namePtr = NULL_CHARACTER; tomwalters@0: tomwalters@0: if (stopChar == DOUBLE_QUOTE_CHAR) tomwalters@0: temp++; tomwalters@0: tomwalters@0: tomwalters@0: return (temp); tomwalters@0: tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* ------------------------------------------------------------------------------ tomwalters@0: tomwalters@0: Read lines from the specified file, updating option settings as appropriate. tomwalters@0: tomwalters@0: Edits: 29th March 1989 (Paul Manson) Altered so that trailing comments allowed. tomwalters@0: tomwalters@0: ------------------------------------------------------------------------------ */ tomwalters@0: void processOptionFile (options, numOptions, OptionFile, theOptionFileName, tomwalters@0: limitedChars, checkOptions, programName) tomwalters@0: Option options[] ; tomwalters@0: int numOptions ; tomwalters@0: FILE *OptionFile ; tomwalters@0: char *theOptionFileName; tomwalters@0: int limitedChars ; tomwalters@0: int checkOptions ; tomwalters@0: char *programName ; tomwalters@0: { tomwalters@0: int result ; tomwalters@0: char name[MAX_NAME_LENGTH] ; tomwalters@0: char value[MAX_NAME_LENGTH] ; tomwalters@0: char *line, *linePtr; tomwalters@0: int maxCharsToRead ; tomwalters@0: int totalCharsRead ; tomwalters@0: tomwalters@0: result = EOF; tomwalters@0: totalCharsRead = 0 ; tomwalters@0: line = malloc((unsigned) MAX_LINE_LENGTH + 1); tomwalters@0: tomwalters@0: maxCharsToRead = ((limitedChars) ? (min(MAX_LINE_LENGTH, limitedChars)) : tomwalters@0: MAX_LINE_LENGTH); tomwalters@0: tomwalters@0: while (maxCharsToRead > 0 && ((line = fgets(line, maxCharsToRead + 1, tomwalters@0: OptionFile)) != NULL)) { tomwalters@0: tomwalters@0: if (line[0] == NULL_CHARACTER) tomwalters@0: break; /* In the case of a Option Header */ tomwalters@0: else tomwalters@0: if (limitedChars) { tomwalters@0: totalCharsRead += strlen(line); tomwalters@0: maxCharsToRead = min(MAX_LINE_LENGTH, limitedChars - totalCharsRead); tomwalters@0: } tomwalters@0: tomwalters@0: linePtr = skipBlanks(line); tomwalters@0: tomwalters@0: /* Check for Comments and Blank Lines */ tomwalters@0: if ((linePtr[0] == COMMENT_CHARACTER) || tomwalters@0: (linePtr[0] == NEWLINE_CHARACTER) || tomwalters@0: (linePtr[0] == CARRIAGE_RETURN ) || tomwalters@0: (linePtr[0] == NULL_CHARACTER)) tomwalters@0: continue; tomwalters@0: tomwalters@0: if ((linePtr = getName(linePtr, name)) == NULL) { tomwalters@0: (void) fprintf(stderr, "options: Missing or Invalid name\n"); tomwalters@0: result = ERROR_RESULT; tomwalters@0: break; tomwalters@0: } tomwalters@0: linePtr = skipBlanks(linePtr); tomwalters@0: if ((linePtr = skipEquals(linePtr)) == NULL) { tomwalters@0: (void) fprintf(stderr, "options: Expected an '=' after the name %s\n", name); tomwalters@0: result = ERROR_RESULT; tomwalters@0: break; tomwalters@0: } tomwalters@0: linePtr = skipBlanks(linePtr); tomwalters@0: if ((linePtr = getName(linePtr, value)) == NULL) { tomwalters@0: (void) fprintf(stderr, tomwalters@0: "options: Missing or Invalid value; name is %s\n", name); tomwalters@0: result = ERROR_RESULT; tomwalters@0: break; tomwalters@0: } tomwalters@0: linePtr = skipBlanks(linePtr); tomwalters@0: if ((*linePtr != NEWLINE_CHARACTER) && tomwalters@0: (*linePtr != NULL_CHARACTER) && tomwalters@0: (*linePtr != COMMENT_CHARACTER) && tomwalters@0: (*linePtr != CARRIAGE_RETURN)) { tomwalters@0: (void) fprintf(stderr, tomwalters@0: "options: Detected Trailing Garbage in the line %s = %s\n", tomwalters@0: name, value); tomwalters@0: result = ERROR_RESULT; tomwalters@0: break; tomwalters@0: } tomwalters@0: tomwalters@0: if (!LookUpAndStore(options, numOptions, name, value, checkOptions, programName) && tomwalters@0: checkOptions) { tomwalters@0: (void) fprintf(stderr, "options: Could not find Option Called %s\n", tomwalters@0: name); tomwalters@0: result = ERROR_RESULT; tomwalters@0: break; tomwalters@0: } tomwalters@0: tomwalters@0: } tomwalters@0: tomwalters@0: if (result != EOF) { tomwalters@0: (void) fprintf(stderr,"options: Error reading the Option File %s\n", tomwalters@0: theOptionFileName); tomwalters@0: (void) fprintf(stderr,"options: Remainder of File is as follows;\n"); tomwalters@0: (void) fputs(line, stderr); tomwalters@0: while ((line = fgets(line, MAX_LINE_LENGTH, OptionFile)) != NULL) tomwalters@0: (void) fputs(line, stderr); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* ------------------------------------------------------------------------------ tomwalters@0: tomwalters@0: OnLine Help Facility. This is simply the default handler which is to be called tomwalters@0: if the user specifies no replacement handler. tomwalters@0: tomwalters@0: ------------------------------------------------------------------------------ */ tomwalters@0: static void defaultHelpHandler(options, numOptions, progName) tomwalters@0: Option options[] ; tomwalters@0: int numOptions; tomwalters@0: char *progName ; tomwalters@0: { tomwalters@0: register int help, res; tomwalters@0: tomwalters@0: if (helpOnOneRequired) { tomwalters@0: res = helpOnOneLocation; tomwalters@0: (void) fprintf(stdout, "%-13s %-9s %-9s %s\n", options[res].name, tomwalters@0: ((*(options[res].value) == NULL) ? ("") : (*(options[res].value))), tomwalters@0: ((options[res].defaultValue == NULL) ? ("") : (options[res].defaultValue)), tomwalters@0: ((options[res].comment == NULL) ? ("") : (options[res].comment))); tomwalters@0: return; tomwalters@0: } tomwalters@0: tomwalters@0: help = -1; tomwalters@0: for (res = 0; res < numOptions; res++) tomwalters@0: if (strcmp(options[res].name, HELP_STRING) == 0) { tomwalters@0: help = res; tomwalters@0: break ; tomwalters@0: }; tomwalters@0: tomwalters@0: tomwalters@0: /************* Print head of help menu *****************/ tomwalters@0: if (help < 0) { tomwalters@0: (void) fprintf(stdout, "The Rotter who wrote the `%s' program hasn't provided any \n", tomwalters@0: progName); tomwalters@0: (void) fprintf(stdout, "form of on-line 'help' documentation, tsk tsk!\n\n"); tomwalters@0: (void) fprintf(stdout, tomwalters@0: "We can, however, provide you with the list of available options:\n\n"); tomwalters@0: } tomwalters@0: else { tomwalters@0: tomwalters@0: (void)fprintf(stdout,"%s\n", versionstr); tomwalters@0: (void) fprintf(stdout, tomwalters@0: "Usage: %s [options] %s\n\n", progName, options[help].comment); tomwalters@0: } tomwalters@0: tomwalters@0: (void) fprintf(stdout, "Option Name Current Default Comment\n"); tomwalters@0: (void) fprintf(stdout, "----------- ------- ------- -------\n"); tomwalters@0: tomwalters@0: for (res = numOptions-1 ; res >= 0 ; res-- ) tomwalters@0: if (options[res].classification < OutputOption && tomwalters@0: (!thereWasAnOptionsFile || helpOnAllRequired || tomwalters@0: strcmp(*(options[res].value), options[res].defaultValue) != 0 || tomwalters@0: *(options[res].value) != options[res].defaultValue)) tomwalters@0: (void) fprintf(stdout, "%-13s %-9s %-9s %s\n", options[res].name, tomwalters@0: ((*(options[res].value) == NULL) ? ("") : (*(options[res].value))), tomwalters@0: ((options[res].defaultValue == NULL) ? ("") : (options[res].defaultValue)), tomwalters@0: ((options[res].comment == NULL) ? ("") : (options[res].comment))); tomwalters@0: tomwalters@0: (void) fprintf(stdout, "\n"); tomwalters@0: return; tomwalters@0: } tomwalters@0: tomwalters@0: /* ----- Declare the handlerHolder variable ----- */ tomwalters@0: tomwalters@0: static helpRoutine *onLineHelpHandler = defaultHelpHandler; tomwalters@0: tomwalters@0: tomwalters@0: /* ------------------------------------------------------------------------------ tomwalters@0: tomwalters@0: Spit out the options to a file (with the appropriate option file name). tomwalters@0: tomwalters@0: Edits: 29th March 1989 (Paul Manson). For the sake of IBM/PC users, this routine tomwalters@0: will now spit lines with CR/LF pairs. tomwalters@0: 06th April 1989 (Paul Manson). This routine is no-longer conditionally tomwalters@0: compiled, but is now more widely accepted. tomwalters@0: tomwalters@0: ------------------------------------------------------------------------------ */ tomwalters@0: tomwalters@0: void updateOptionsFile(options, numOptions, programName, resFileName) tomwalters@0: Option options[] ; tomwalters@0: int numOptions ; tomwalters@0: char *programName; tomwalters@0: char *resFileName; tomwalters@0: { tomwalters@0: int res ; tomwalters@0: FILE *fptr; tomwalters@0: tomwalters@0: if ((fptr = fopen(resFileName, "w")) == NULL) { tomwalters@0: (void) fprintf(stderr, "Unable to Update Options File called %s.\n", resFileName); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: tomwalters@0: #if defined( PC ) || defined( THINK_C ) tomwalters@0: (void) fprintf(fptr ,"# %s\n", versionstr); tomwalters@0: (void) fprintf(fptr, "#\r\n# Options file for the %s program.\r\n#\r\n\r\n", programName); tomwalters@0: (void) fprintf(fptr, "#Option Name Current Default Comment\r\n"); tomwalters@0: (void) fprintf(fptr, "#----------- ------- ------- -------\r\n\r\n"); tomwalters@0: #else tomwalters@0: (void) fprintf(fptr ,"# %s\n", versionstr); tomwalters@0: (void) fprintf(fptr, "#\n# Options file for the %s program.\n#\n\n", programName); tomwalters@0: (void) fprintf(fptr, "#Option Name Current Default Comment\n"); tomwalters@0: (void) fprintf(fptr, "#----------- ------- ------- -------\n\n"); tomwalters@0: #endif tomwalters@0: tomwalters@0: for (res = numOptions-1; res >=0 ; res-- ) tomwalters@0: if (options[res].classification < OutputOption && *(options[res].value) != NULL && tomwalters@0: (updateAllRequired || tomwalters@0: strcmp(*(options[res].value), options[res].defaultValue) != 0 || tomwalters@0: *(options[res].value) != options[res].defaultValue)) { tomwalters@0: #if defined( PC ) tomwalters@0: (void) fprintf(fptr, "%-13s = %-9s # %-9s %s\r\n", options[res].name, tomwalters@0: ((*(options[res].value) == NULL) ? ("") : (*(options[res].value))), tomwalters@0: ((options[res].defaultValue == NULL) ? ("") : (options[res].defaultValue)), tomwalters@0: ((options[res].comment == NULL) ? ("") : (options[res].comment))); tomwalters@0: #else tomwalters@0: (void) fprintf(fptr, "%-13s = %-9s # %-9s %s\n", options[res].name, tomwalters@0: ((*(options[res].value) == NULL) ? ("") : (*(options[res].value))), tomwalters@0: ((options[res].defaultValue == NULL) ? ("") : (options[res].defaultValue)), tomwalters@0: ((options[res].comment == NULL) ? ("") : (options[res].comment))); tomwalters@0: #endif tomwalters@0: } tomwalters@0: tomwalters@0: if (fclose(fptr) == EOF) { tomwalters@0: (void) fprintf(stderr, "options: fclose failed on the options file %s.\n", resFileName); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: tomwalters@0: thereWasAnOptionsFile = TRUE; /* Cos there is one now! */ tomwalters@0: tomwalters@0: return; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* ------------------------------------------------------------------------------ tomwalters@0: tomwalters@0: Process the option file and then the command line options supplied. tomwalters@0: tomwalters@0: Edited: tomwalters@0: tomwalters@0: 2nd March 1989 (Paul Manson). Changed the calls to OptionFileName (ie. tomwalters@0: added a argument) to facilitate tomwalters@0: searching of HOME (etc) directories. Note tomwalters@0: that this is IGNORED for IBM/PCs. tomwalters@0: tomwalters@0: 8th March 1989 (Paul Manson). Ignore the above, as OPTIONSPATH is now tomwalters@0: used (in conjunction with search_path) to tomwalters@0: enable proper paths for Unix. tomwalters@0: tomwalters@0: 10th March 1989 (Paul Manson). Added the "help" facility and the default tomwalters@0: and comment stuff. tomwalters@0: tomwalters@0: 16th March 1989 (Paul Manson). Altered the final argc/argv shuffling so that tomwalters@0: argv simply points at the first argument after tomwalters@0: the options. tomwalters@0: tomwalters@0: July 1994 (MAA). Mended to allow spaces in command-line strings. tomwalters@0: tomwalters@0: ------------------------------------------------------------------------------ */ tomwalters@0: tomwalters@0: tomwalters@0: tomwalters@0: tomwalters@0: /* Assign the default options */ tomwalters@0: tomwalters@0: void default_nopts( options, numOptions ) tomwalters@0: Option options[] ; tomwalters@0: int numOptions ; tomwalters@0: { tomwalters@0: int i ; tomwalters@0: tomwalters@0: for (i = 0; i < numOptions; i++) tomwalters@0: *(options[i].value) = options[i].defaultValue ; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: tomwalters@0: /**************************************************************************** tomwalters@0: * Assign options from the rc file. tomwalters@0: * tomwalters@0: * The option file is called ".genxxxrc", where the "xxx" is determined tomwalters@0: * by the name of the application, (which is in argv[0]). tomwalters@0: * Here "rc" stands for "resource control". tomwalters@0: * The file-name is assigned to a string ptr "theOptionFileName". tomwalters@0: * On Unix, the path for the file-name is determined as follows: tomwalters@0: * if environment variable OPTION_PATH is set, then use this path. tomwalters@0: * else the default path is: tomwalters@0: * `.' (the current directory) tomwalters@0: * `~' (the users home directory) tomwalters@0: * The DEFAULT_OPTION_PATH for the option file is defined "." (see above). tomwalters@0: * This means look first in the current directory, and failing that in the tomwalters@0: * users home directory. tomwalters@0: * But these defaults can be overridden by setting an environment variable, tomwalters@0: * which is defined as OPTIONSPATH (see above). Thus the user could set a tomwalters@0: * new default path for option files by, eg: tomwalters@0: * setenv OPTIONSPATH ".:~/rcbin" tomwalters@0: * This would look first in the current directory, and failing that in a tomwalters@0: * directory ~/rcbin tomwalters@0: *****************************************************************************/ tomwalters@0: tomwalters@0: void rcfile_nopts( options, numOptions, file ) tomwalters@0: Option options[] ; tomwalters@0: int numOptions ; tomwalters@0: char *file ; tomwalters@0: { tomwalters@0: FILE *OptionFile ; tomwalters@0: char *OptionPathPtr ; tomwalters@0: tomwalters@0: tomwalters@0: #if defined( PC ) tomwalters@0: if (((OptionFile = fopen(theOptionFileName = tomwalters@0: PCOptionFileName( file, TRUE ), "r")) != NULL)) { tomwalters@0: /* ------------------------------------------------------------------------------------- tomwalters@0: Removed temporarily so the PC version ONLY examines and creates option files tomwalters@0: in the cwd. This will be changed when we determine a better strategy for tomwalters@0: PC directory PATH searches. tomwalters@0: tomwalters@0: ((OptionFile = fopen(theOptionFileName = tomwalters@0: PCOptionFileName( file, FALSE), "r")) != NULL)) { tomwalters@0: ---------------------------------------------------------------------------------------*/ tomwalters@0: #else tomwalters@0: if ((OptionPathPtr = (char *)getenv(OPTION_PATH)) == NULL) tomwalters@0: OptionPathPtr = DEFAULT_OPTION_PATH; tomwalters@0: tomwalters@0: if ((OptionFile = fopen(theOptionFileName = tomwalters@0: search_path(UnixOptionFileName( file ), tomwalters@0: OptionPathPtr), "r")) != NULL) { tomwalters@0: #endif tomwalters@0: tomwalters@0: /* Process the Option File */ tomwalters@0: tomwalters@0: (void) processOptionFile(options, numOptions, OptionFile, tomwalters@0: theOptionFileName, FALSE, TRUE, file ) ; tomwalters@0: (void) fclose(OptionFile); tomwalters@0: tomwalters@0: thereWasAnOptionsFile = TRUE; tomwalters@0: tomwalters@0: } tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* Assign options from the command line */ tomwalters@0: tomwalters@0: void cmd_line_nopts( options, numOptions, argc, argv ) tomwalters@0: Option options[] ; tomwalters@0: int numOptions ; tomwalters@0: int *argc ; tomwalters@0: char ***argv ; tomwalters@0: { tomwalters@0: int i, currentArg ; tomwalters@0: int finalArg, wasAHyphen ; tomwalters@0: char name[MAX_NAME_LENGTH] ; tomwalters@0: char value[MAX_NAME_LENGTH] ; tomwalters@0: char *line, *linePtr; tomwalters@0: char *tempstring; /* MAA 23-4-1994 */ tomwalters@0: char *tempstring2; /* MAA 23-4-1994 */ tomwalters@0: int count=0; tomwalters@0: tomwalters@0: tomwalters@0: /* MAA: next 3 lines */ tomwalters@0: linePtr = (char *) calloc((size_t) MAX_NAME_LENGTH, (size_t) sizeof(char)); tomwalters@0: tempstring = (char *) calloc((size_t) MAX_NAME_LENGTH, (size_t) sizeof(char)); tomwalters@0: tempstring2 = (char *) calloc((size_t) MAX_NAME_LENGTH, (size_t) sizeof(char)); tomwalters@0: tomwalters@0: tomwalters@0: finalArg = currentArg = 1; /* Ignore the Program Name */ tomwalters@0: line = malloc((unsigned) MAX_LINE_LENGTH); tomwalters@0: tomwalters@0: while (currentArg < *argc) { tomwalters@0: wasAHyphen = FALSE; tomwalters@0: linePtr = strcpy(line, (*argv)[currentArg]); tomwalters@0: if (linePtr[0] == HYPHEN_CHARACTER) { tomwalters@0: wasAHyphen = TRUE; tomwalters@0: linePtr++; /* Skip any leading hyphen */ tomwalters@0: } tomwalters@0: tomwalters@0: /* MAA: force doublequotes onto beg & end . A rather big hack ...*/ tomwalters@0: if (strchr(linePtr, BLANK_CHARACTER) != NULL){ tomwalters@0: strncpy(tempstring, linePtr, (int) strcspn(linePtr, "=")); tomwalters@0: strcat(tempstring, "=\""); tomwalters@0: tempstring2 = (char *) strrchr(linePtr, EQUALS_CHARACTER); tomwalters@0: tempstring2++; tomwalters@0: strcat(tempstring, tempstring2); tomwalters@0: strcat(tempstring, "\""); tomwalters@0: linePtr=tempstring;} tomwalters@0: tomwalters@0: tomwalters@0: if ((linePtr = getName(linePtr, name)) == NULL) { tomwalters@0: break; tomwalters@0: } tomwalters@0: tomwalters@0: if ((linePtr = skipEquals(linePtr)) == NULL) { tomwalters@0: if (!wasAHyphen) { tomwalters@0: break; /* Don't interpret as being options */ tomwalters@0: } tomwalters@0: if (strcmp(name, HELP_STRING) == 0) { tomwalters@0: #ifdef PC tomwalters@0: if (strncmp((*argv)[0]+strlen((*argv)[0])-strlen("gen.exe"), "gen", strlen("gen")) == 0) tomwalters@0: #else tomwalters@0: if (strcmp((*argv)[0], "gen") == 0) tomwalters@0: #endif tomwalters@0: /* Special case of gen -help */ tomwalters@0: usageHelp(); tomwalters@0: else tomwalters@0: /* Case of gen??? -help */ tomwalters@0: (*onLineHelpHandler)(options, numOptions, (*argv)[0]); tomwalters@0: exit(0); tomwalters@0: } tomwalters@0: tomwalters@0: if (strcmp(name, UPDATE_STRING) == 0) { tomwalters@0: /* Do the Update and Then Goto the Top of the Loop Again */ tomwalters@0: updateOptionsFile(options, numOptions, (*argv)[0], theOptionFileName); tomwalters@0: finalArg = ++currentArg; tomwalters@0: continue; tomwalters@0: } tomwalters@0: tomwalters@0: (void) strcpy(value, DEFAULT_TOGGLE_VALUE); tomwalters@0: } tomwalters@0: else { tomwalters@0: if ((linePtr = getName(linePtr, value)) == NULL) { tomwalters@0: break; tomwalters@0: } tomwalters@0: } tomwalters@0: tomwalters@0: if(!LookUpAndStore(options, numOptions, name, value, TRUE, (*argv)[0])) { tomwalters@0: (void) fprintf(stderr,"options: Could not find an Option called %s\n", name); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: tomwalters@0: finalArg = ++currentArg; tomwalters@0: } tomwalters@0: tomwalters@0: /* Reset the Command Line argc and argv */ tomwalters@0: /* The Original Version actually cut the options out of the argv array (by tomwalters@0: shifting the remaining arguments left), but the new version simply lets tomwalters@0: argv point to the next argument to be processed. tomwalters@0: tomwalters@0: if (finalArg > 1) { tomwalters@0: for (i = finalArg; i < *argc; i++) tomwalters@0: (*argv)[i - finalArg + 1] = (*argv)[i]; tomwalters@0: *argc = *argc - finalArg + 1; tomwalters@0: } tomwalters@0: tomwalters@0: */ tomwalters@0: tomwalters@0: *argv+= finalArg; tomwalters@0: *argc = *argc - finalArg; tomwalters@0: tomwalters@0: return; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: tomwalters@0: /* Assign options using defaults, then the rc file, then the command line */ tomwalters@0: tomwalters@0: void getnopts (options, numOptions, argc, argv) tomwalters@0: Option options[] ; tomwalters@0: int numOptions ; tomwalters@0: int *argc ; tomwalters@0: char ***argv ; tomwalters@0: { tomwalters@0: default_nopts( options, numOptions ) ; tomwalters@0: rcfile_nopts( options, numOptions, (*argv)[0] ) ; tomwalters@0: cmd_line_nopts( options, numOptions, argc, argv ) ; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: tomwalters@0: /* ------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: Read an option header from the specified file into the given options array. tomwalters@0: tomwalters@0: ------------------------------------------------------------------------------- */ tomwalters@0: void readnopts(options, numOptions, filePointer) tomwalters@0: Option options[] ; tomwalters@0: int numOptions; tomwalters@0: FILE *filePointer ; tomwalters@0: { tomwalters@0: long filePosition ; tomwalters@0: char first[200] ; tomwalters@0: int headerLength ; tomwalters@0: tomwalters@0: filePosition = ftell(filePointer); /* Save the Original Position */ tomwalters@0: tomwalters@0: /* Read the first line of the first block, or as much of it as possible */ tomwalters@0: tomwalters@0: if ((!fread(first, 1, strlen(OptionHeaderHeader) + OPTION_HEADER_DIGITS tomwalters@0: + strlen(LineFeedArray), filePointer)) || tomwalters@0: (strncmp(first, OptionHeaderHeader, strlen(OptionHeaderHeader)) != 0)) { tomwalters@0: /* Assume that this is NOT a option header */ tomwalters@0: if (fseek(filePointer, filePosition, 0)) { tomwalters@0: (void) fprintf(stderr, "options: Error fseeking Option Header File\n"); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: return; tomwalters@0: } tomwalters@0: tomwalters@0: /* Extract the Header Length in Bytes */ tomwalters@0: tomwalters@0: headerLength = atoi(first + strlen(OptionHeaderHeader)); tomwalters@0: tomwalters@0: /* Now, process the stuff. Need to "seek" past the first line before tomwalters@0: attempting to read anything, and shorten the headerLength accordingly */ tomwalters@0: tomwalters@0: (void) processOptionFile(options, numOptions, filePointer, tomwalters@0: "Unknown Option File", tomwalters@0: (headerLength - strlen(OptionHeaderHeader) - tomwalters@0: OPTION_HEADER_DIGITS - strlen(LineFeedArray)), tomwalters@0: FALSE, "???"); tomwalters@0: tomwalters@0: /* Make sure that the file pointer is set to the data area */ tomwalters@0: tomwalters@0: if (fseek(filePointer, filePosition + headerLength, 0)) { tomwalters@0: (void) fprintf(stderr, "options: Error fseeking Option Header File\n"); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* ------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: Count the number of bytes which will be written by writenopts, given the tomwalters@0: options array. tomwalters@0: tomwalters@0: ------------------------------------------------------------------------------- */ tomwalters@0: static int countBytesToWrite( options, numOptions ) tomwalters@0: Option options[] ; tomwalters@0: int numOptions; tomwalters@0: { tomwalters@0: int sum, i; tomwalters@0: tomwalters@0: sum = 0; tomwalters@0: tomwalters@0: for (i = 0; i < numOptions; i++) tomwalters@0: if((options[i].classification == OutputOption || tomwalters@0: options[i].classification == InOutOption) && tomwalters@0: *(options[i].value) != NULL && tomwalters@0: strcmp(*(options[i].value), NULL_STRING) != 0) tomwalters@0: sum += strlen(options[i].name) + strlen(EqualsArray) + tomwalters@0: strlen(*(options[i].value)) + strlen(LineFeedArray); /* + (2 * strlen(QuotesArray)); */ tomwalters@0: tomwalters@0: return (sum); tomwalters@0: } tomwalters@0: tomwalters@0: /* ------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: The descendent of the lost and lamented blockCopyStrToFile... writes a string tomwalters@0: to the indicated file. tomwalters@0: tomwalters@0: ------------------------------------------------------------------------------- */ tomwalters@0: static void WriteStringToFile(str, filePtr) tomwalters@0: char *str; tomwalters@0: FILE *filePtr; tomwalters@0: { tomwalters@0: if (!fwrite(str, 1, strlen(str), filePtr)) { tomwalters@0: (void) fprintf(stderr, "WriteStringToFile: Error printing %s to file.\n", str); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: tomwalters@0: return; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* ------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: Write an option header to the specified file from the information contained tomwalters@0: in the given options array. Remove the comments to get debugging info. tomwalters@0: tomwalters@0: ------------------------------------------------------------------------------- */ tomwalters@0: void writenopts(options, numOptions, filePointer) tomwalters@0: Option options[] ; tomwalters@0: int numOptions; tomwalters@0: FILE *filePointer ; tomwalters@0: { tomwalters@0: /*int bytesWritten ;*/ tomwalters@0: int i ; tomwalters@0: long filePosition ; tomwalters@0: int bytesToWrite ; tomwalters@0: int oddHeaderLength ; tomwalters@0: char DigitString[OPTION_HEADER_DIGITS + 2]; tomwalters@0: tomwalters@0: filePosition = ftell(filePointer); tomwalters@0: tomwalters@0: bytesToWrite = countBytesToWrite(options, numOptions) + tomwalters@0: strlen(OptionHeaderHeader) + OPTION_HEADER_DIGITS + tomwalters@0: strlen(LineFeedArray) + 1; tomwalters@0: tomwalters@0: if (oddHeaderLength = (bytesToWrite % 2)) tomwalters@0: bytesToWrite++; tomwalters@0: tomwalters@0: (void) WriteStringToFile(OptionHeaderHeader, filePointer); tomwalters@0: tomwalters@0: (void) sprintf(DigitString, "%0*d", OPTION_HEADER_DIGITS, bytesToWrite); tomwalters@0: tomwalters@0: /*(void) printf("bytesToWrite is %i.\n", bytesToWrite);*/ tomwalters@0: tomwalters@0: (void) WriteStringToFile(DigitString, filePointer); tomwalters@0: tomwalters@0: (void) WriteStringToFile(LineFeedArray, filePointer); tomwalters@0: tomwalters@0: /* Copy all of the Options */ tomwalters@0: tomwalters@0: for (i = 0; i < numOptions; i++) { tomwalters@0: tomwalters@0: if((options[i].classification == OutputOption || tomwalters@0: options[i].classification == InOutOption) && tomwalters@0: *(options[i].value) != NULL && tomwalters@0: strcmp(*(options[i].value), NULL_STRING) != 0) { tomwalters@0: tomwalters@0: (void) WriteStringToFile(options[i].name, filePointer); tomwalters@0: tomwalters@0: (void) WriteStringToFile(EqualsArray, filePointer); tomwalters@0: tomwalters@0: /* (void) WriteStringToFile(QuotesArray, filePointer); */ tomwalters@0: tomwalters@0: (void) WriteStringToFile(*(options[i].value), filePointer); tomwalters@0: tomwalters@0: /* (void) WriteStringToFile(QuotesArray, filePointer); */ tomwalters@0: tomwalters@0: (void) WriteStringToFile(LineFeedArray, filePointer); tomwalters@0: } tomwalters@0: } tomwalters@0: tomwalters@0: if (fputc(NULL_CHARACTER, filePointer) == EOF) { tomwalters@0: (void) fprintf(stderr, "writenopts: Error doing fputc of the last NULL character.\n"); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: tomwalters@0: if (oddHeaderLength && fputc(NULL_CHARACTER, filePointer) == EOF) { tomwalters@0: (void) fprintf(stderr, "writenopts: Error doing fputc of the odd-pad NULL character.\n"); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: tomwalters@0: if (fflush(filePointer)) { tomwalters@0: (void) fprintf(stderr, "options: Error while flushing the option header\n"); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: tomwalters@0: /* seek the fileptr to after the last byte of the header */ tomwalters@0: tomwalters@0: if (filePointer != stdout) { tomwalters@0: if (fseek(filePointer, filePosition + (long)bytesToWrite, 0)) { tomwalters@0: (void) fprintf(stderr, "options: Error fseeking Option Header File\n"); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: } tomwalters@0: tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* ---------------------------------------------------------------------------- tomwalters@0: tomwalters@0: A Little Routine to Count the Options in a Options Array .... This MUST tomwalters@0: Be NULL-Terminated ...... OR ELSE! tomwalters@0: tomwalters@0: ---------------------------------------------------------------------------- */ tomwalters@0: tomwalters@0: static int countOptions(options) tomwalters@0: Option options[]; tomwalters@0: { tomwalters@0: int numoptions; tomwalters@0: tomwalters@0: for (numoptions = 0; tomwalters@0: options[numoptions].name != NULL; /* DEATH TO ALL WHO TREAD HERE! */ tomwalters@0: numoptions++); tomwalters@0: tomwalters@0: return (numoptions); tomwalters@0: tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* ------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: The Counting version of getnopts -- you MUST null-terminate the options array. tomwalters@0: tomwalters@0: ------------------------------------------------------------------------------- */ tomwalters@0: tomwalters@0: void getopts (options, argc, argv) tomwalters@0: Option options[] ; tomwalters@0: int *argc ; tomwalters@0: char ***argv ; tomwalters@0: { tomwalters@0: (void) getnopts(options, countOptions(options), argc, argv); tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: void cmd_line_opts(options, argc, argv) tomwalters@0: Option options[] ; tomwalters@0: int *argc ; tomwalters@0: char ***argv ; tomwalters@0: { tomwalters@0: (void) cmd_line_nopts( options, countOptions(options), argc, argv ) ; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: tomwalters@0: /* ------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: The Counting version of readnopts -- you MUST null-terminate the options array. tomwalters@0: tomwalters@0: ------------------------------------------------------------------------------- */ tomwalters@0: void readopts(options, filePointer) tomwalters@0: Option options[] ; tomwalters@0: FILE *filePointer ; tomwalters@0: { tomwalters@0: (void) readnopts(options, countOptions(options), filePointer); tomwalters@0: } tomwalters@0: tomwalters@0: /* ------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: The Counting version of writenopts -- you MUST null-terminate the options array. tomwalters@0: tomwalters@0: ------------------------------------------------------------------------------- */ tomwalters@0: void writeopts(options, filePointer) tomwalters@0: Option options[] ; tomwalters@0: FILE *filePointer ; tomwalters@0: { tomwalters@0: (void) writenopts(options, countOptions(options), filePointer); tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* ------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: Packaging for convenience -- Guaranteed to be Listeria-free! tomwalters@0: tomwalters@0: ------------------------------------------------------------------------------- */ tomwalters@0: tomwalters@0: FILE *fileopts( res, argc, argv ) tomwalters@0: Option *res ; tomwalters@0: int *argc ; tomwalters@0: char **argv[]; tomwalters@0: { tomwalters@0: FILE *ifp ; tomwalters@0: int numOptions; tomwalters@0: #if defined( PC ) tomwalters@0: char *progName ; tomwalters@0: tomwalters@0: progName = (*argv)[0]; tomwalters@0: #endif tomwalters@0: tomwalters@0: numOptions = countOptions(res); tomwalters@0: tomwalters@0: getnopts( res, numOptions, argc, argv ) ; tomwalters@0: tomwalters@0: if( *argc > 0 ) { tomwalters@0: if((ifp = fopen( **argv, "r" )) == NULL) { tomwalters@0: (void) fprintf(stderr, "Unable to open the file %s.\n", **argv); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: } tomwalters@0: else tomwalters@0: #if defined( PC ) tomwalters@0: { tomwalters@0: /* PCs cannot take binmode files through standard input */ tomwalters@0: (void) (*onLineHelpHandler)( res, numOptions, progName ); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: #else tomwalters@0: ifp = stdin ; tomwalters@0: #endif tomwalters@0: tomwalters@0: (*argv)++ ; tomwalters@0: (*argc)-- ; tomwalters@0: tomwalters@0: readopts( res, ifp ) ; tomwalters@0: tomwalters@0: return( ifp ) ; tomwalters@0: tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* ------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: Packaging for convenience -- Guaranteed to be Listeria-free! tomwalters@0: tomwalters@0: ------------------------------------------------------------------------------- */ tomwalters@0: FILE *optoutput(str) tomwalters@0: char *str; tomwalters@0: { tomwalters@0: FILE *f; tomwalters@0: tomwalters@0: if (str == NULL) tomwalters@0: return (NULL); tomwalters@0: else if (str == DEFAULT_TOGGLE_VALUE) tomwalters@0: return (stdout); tomwalters@0: tomwalters@0: if ((f = fopen(str, "w")) == NULL) { tomwalters@0: (void) fprintf(stderr, "options: Could not open the file %s for output.\n", str); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: return (f); tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* ------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: OnLine Help from the user program. tomwalters@0: tomwalters@0: ------------------------------------------------------------------------------- */ tomwalters@0: void helpnopts(res, numRes, name) tomwalters@0: Option res[]; tomwalters@0: int numRes; tomwalters@0: char *name ; tomwalters@0: { tomwalters@0: (void) (*onLineHelpHandler)(res, numRes, name); tomwalters@0: } tomwalters@0: tomwalters@0: /* ------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: OnLine Help from the user program. (counting version) tomwalters@0: tomwalters@0: ------------------------------------------------------------------------------- */ tomwalters@0: void helpopts(res, name) tomwalters@0: Option res[]; tomwalters@0: char *name ; tomwalters@0: { tomwalters@0: #ifdef PC tomwalters@0: if (strncmp(name+strlen(name)-strlen("gen.exe"), "gen", strlen("gen")) == 0) tomwalters@0: #else tomwalters@0: if (strcmp(name, "gen") == 0) tomwalters@0: #endif tomwalters@0: /* Special case of gen */ tomwalters@0: usageHelp(); tomwalters@0: else tomwalters@0: /* Case of gen??? */ tomwalters@0: (void) (*onLineHelpHandler)(res, countOptions(res), name); tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* --------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: Allows an application program to install its very own helpHandler routine to tomwalters@0: override the default help-message handler. The behaviour of such a routine is tomwalters@0: implicitly trusted by , so you should only install your own handler tomwalters@0: when you are quite familiar with the Options structure format. This routine tomwalters@0: returns the address of the previously installed handler (which is initially the tomwalters@0: default handler) so that this may be reinstated at a later point. tomwalters@0: tomwalters@0: ---------------------------------------------------------------------------------- */ tomwalters@0: tomwalters@0: helpRoutine *helpOptsHandler(aHelpRoutine) tomwalters@0: helpRoutine *aHelpRoutine; tomwalters@0: { tomwalters@0: helpRoutine *temp; tomwalters@0: tomwalters@0: temp = onLineHelpHandler; tomwalters@0: tomwalters@0: onLineHelpHandler = aHelpRoutine; tomwalters@0: tomwalters@0: return (temp); tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* --------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: A convenience call which returns TRUE (1) if the optionStr is what options thinks tomwalters@0: of as "ON", "YES", "TRUE", or "1".... This merely allows us to hide the actual tomwalters@0: implementation of "ON" from the application programs. tomwalters@0: tomwalters@0: --------------------------------------------------------------------------------- */ tomwalters@0: tomwalters@0: int isOFF(optionStr) tomwalters@0: char *optionStr; tomwalters@0: { tomwalters@0: return (strcmp(OFF_STRING, optionStr) == 0 || tomwalters@0: strcmp(OFF_ALIAS , optionStr) == 0 || tomwalters@0: strcmp(NOT_USED , optionStr) == 0); tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* --------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: A convenience call which returns TRUE (1) if the optionStr is what options thinks tomwalters@0: of as "NULL", "NONE", nothing, zip, etc... This merely allows us to hide the actual tomwalters@0: implementation of "NULL" from the application programs. tomwalters@0: tomwalters@0: --------------------------------------------------------------------------------- */ tomwalters@0: tomwalters@0: int isNULL(optionStr) tomwalters@0: char *optionStr; tomwalters@0: { tomwalters@0: return (optionStr == NULL || tomwalters@0: strcmp(NULL_STRING, optionStr) == 0 || tomwalters@0: strcmp(NULL_ALIAS , optionStr) == 0); tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* --------------------------------------------------------------------------------- tomwalters@0: tomwalters@0: A routine to reduce the load on the application programmer by providing a simple tomwalters@0: boolean check for string equality WITHOUT CASE SIGNIFICANCE. This allows applications tomwalters@0: to leave case and typing problems within "options" reliably. tomwalters@0: tomwalters@0: --------------------------------------------------------------------------------- */ tomwalters@0: tomwalters@0: static char *stringToLowerCase(str) tomwalters@0: char *str; tomwalters@0: { tomwalters@0: register int i; tomwalters@0: tomwalters@0: if (str == NULL) tomwalters@0: return (str); tomwalters@0: else { tomwalters@0: for (i = 0; str[i] != NULL_CHARACTER; i++) tomwalters@0: if (isupper((char) str[i])) tomwalters@0: str[i] = (char) tolower((char) str[i]); tomwalters@0: return (str); tomwalters@0: } tomwalters@0: } tomwalters@0: tomwalters@0: extern int OptionStringsEqual(str1, str2) tomwalters@0: char *str1, *str2; tomwalters@0: { tomwalters@0: /* This routine copies the strings into two local buffers, converts them to tomwalters@0: lower case, and then compares them for equality. This local copy ensures tomwalters@0: that they are automatically deallocated on function return */ tomwalters@0: tomwalters@0: #define MAX_COPY_LENGTH (256) tomwalters@0: tomwalters@0: char lc1[MAX_COPY_LENGTH], lc2[MAX_COPY_LENGTH]; tomwalters@0: tomwalters@0: if (strlen(str1) < MAX_COPY_LENGTH && tomwalters@0: strlen(str2) < MAX_COPY_LENGTH) tomwalters@0: return (strcmp(stringToLowerCase(strcpy(lc1, str1)), tomwalters@0: stringToLowerCase(strcpy(lc2, str2))) == 0); tomwalters@0: else { tomwalters@0: (void) fprintf(stderr, "options: OptionStringsEqual() could not compare the strings %s and %s becaues one was more that %i characters long.\n", str1, str2, MAX_COPY_LENGTH); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: tomwalters@0: /* Print general usage information in response to: gen -help */ tomwalters@0: usageHelp() tomwalters@0: { tomwalters@0: (void)fprintf(stdout,"%s\n\n", versionstr); tomwalters@0: tomwalters@0: (void) fprintf(stdout, "Usage: genXXX [options] [file_name]\n"); tomwalters@0: (void) fprintf(stdout, " where XXX is one of the following abbreviations:\n\n\ tomwalters@0: wav waveform \n\ tomwalters@0: bmm basilar membrane motion \n\ tomwalters@0: nap neural activity pattern \n\ tomwalters@0: sai stabilized auditory image \n\ tomwalters@0: spl spiral version of auditory image \n\ tomwalters@0: sgm spectrogram \n\ tomwalters@0: cgm cochleogram " ) ; tomwalters@0: (void) fprintf(stdout, "\n\ tomwalters@0: asa auditory spectral analysis \n\ tomwalters@0: epn excitation pattern \n\n"); tomwalters@0: tomwalters@0: (void) fprintf(stdout, " [file_name] is a headerless wave file (2-byte binary integers).\n"); tomwalters@0: (void) fprintf(stdout, " [options] are parameters, options and swtiches that control\n"); tomwalters@0: (void) fprintf(stdout, " the AIM instructions and the AIM tools.\n\n"); tomwalters@0: tomwalters@0: (void) fprintf(stdout, " Help with options: genXXX [-help | -help=all | -help=option]\n"); tomwalters@0: #if !defined( PC ) tomwalters@0: (void) fprintf(stdout, " Path for options file, (.genXXXrc) = . (or setenv OPTIONSPATH)\n\n"); tomwalters@0: #endif tomwalters@0: tomwalters@0: (void) fprintf(stdout, "Processes Applied by AIM and Routes Through the Model: \n\n\ tomwalters@0: Process Auditory Speech Spectra \n\ tomwalters@0: -------------------------------- -------- ------ ------- \n\ tomwalters@0: Display input wave genwav genwav genwav \n\ tomwalters@0: Auditory filtering (gtf/tlf) genbmm \n\ tomwalters@0: Compression and rectification gensgm genasa " ) ; tomwalters@0: tomwalters@0: (void) fprintf(stdout, "\n\ tomwalters@0: Neural encoding (2D-AT/haircell) gennap \n\ tomwalters@0: Temporal integration (LP filter) gencgm genepn \n\ tomwalters@0: Strobed temporal integration gensai \n\ tomwalters@0: Spiral mapping of auditory image genspl \n\n"); tomwalters@0: tomwalters@0: (void) fprintf(stdout, "Output: genXXX output=on file_name \n"); tomwalters@0: (void) fprintf(stdout, " output is written to file: file_name.XXX \n"); tomwalters@0: tomwalters@0: (void) fprintf(stdout, "\n\ tomwalters@0: The format for 2-dimensional output format is by columns, with the \n\ tomwalters@0: lowest channel first in each column (bmm, nap, sgm, cgm, asa, epn).\n\ tomwalters@0: The format for auditory image output is by rows, for each image frame \n\ tomwalters@0: in succession, with the row of the lowest channel first (sai, spl).\n\n"); tomwalters@0: tomwalters@0: (void) fprintf(stdout, "The Auditory Image Model was developed at the Applied Psychology Unit\n"); tomwalters@0: (void) fprintf(stdout, "of the Medical Research Council, 15 Chaucer Road, Cambridge, U.K.\n\n"); tomwalters@0: tomwalters@0: (void) fprintf(stdout, "Copyright(c) Applied Psychology Unit, Medical Research Council, 1988-1995.\n"); tomwalters@0: tomwalters@0: }