annotate glib/options.c @ 0:5242703e91d3 tip

Initial checkin for AIM92 aimR8.2 (last updated May 1997).
author tomwalters
date Fri, 20 May 2011 15:19:45 +0100
parents
children
rev   line source
tomwalters@0 1 /*
tomwalters@0 2 Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
tomwalters@0 3 ===========================================================================
tomwalters@0 4
tomwalters@0 5 Permission to use, copy, modify, and distribute this software without fee
tomwalters@0 6 is hereby granted for research purposes, provided that this copyright
tomwalters@0 7 notice appears in all copies and in all supporting documentation, and that
tomwalters@0 8 the software is not redistributed for any fee (except for a nominal shipping
tomwalters@0 9 charge). Anyone wanting to incorporate all or part of this software in a
tomwalters@0 10 commercial product must obtain a license from the Medical Research Council.
tomwalters@0 11
tomwalters@0 12 The MRC makes no representations about the suitability of this
tomwalters@0 13 software for any purpose. It is provided "as is" without express or implied
tomwalters@0 14 warranty.
tomwalters@0 15
tomwalters@0 16 THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
tomwalters@0 17 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
tomwalters@0 18 A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
tomwalters@0 19 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
tomwalters@0 20 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
tomwalters@0 21 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
tomwalters@0 22 */
tomwalters@0 23
tomwalters@0 24 /* -------------------------------------------------------------------------------
tomwalters@0 25
tomwalters@0 26 The Leanest Resource Manager in the West.
tomwalters@0 27
tomwalters@0 28 Options may be supplied as defaults (actually in the code), as command line
tomwalters@0 29 arguments, and in a option file. The default arguments may be overridden by
tomwalters@0 30 the option-file contents, which may be overridden from the command line.
tomwalters@0 31
tomwalters@0 32 Copyright (c), 1989 The Medical Research Council of the United Kingdom.
tomwalters@0 33
tomwalters@0 34 Author : Paul Manson
tomwalters@0 35 Written : March 1st 1989
tomwalters@0 36
tomwalters@0 37 Edited :
tomwalters@0 38
tomwalters@0 39 2nd March 1989 (Paul Manson) Added the facility of searching the HOME directory
tomwalters@0 40 for a option file if one is not found in the
tomwalters@0 41 working directory.
tomwalters@0 42
tomwalters@0 43 8th March 1989 (Paul Manson) Enhanced the above by providing a OPTIONPATH
tomwalters@0 44 search strategy for Unix. Currently MSDOS only
tomwalters@0 45 searches for a option file in the directory
tomwalters@0 46 where the program was found.
tomwalters@0 47
tomwalters@0 48 8th March 1989 (Paul Manson) Added the ability to refer to options via
tomwalters@0 49 abbreviations of their names. At present, an abbrev.
tomwalters@0 50 will match if it is exactly the same as precisely one
tomwalters@0 51 option, or if it is the same as the first <n> chars
tomwalters@0 52 of that option (where <n> is the length of the
tomwalters@0 53 abbrev) and it matches no other option name.
tomwalters@0 54
tomwalters@0 55 9th March 1989 (Paul Manson) Added the readopts and writeopts calls, to implement
tomwalters@0 56 option headers for files. Also altered the form
tomwalters@0 57 of command line options accepted: See getopts.h for
tomwalters@0 58 details.
tomwalters@0 59
tomwalters@0 60 10th March 1989 (Paul Manson) Added the "help" facility to provide a simple
tomwalters@0 61 self-documentation facility. Also altered the
tomwalters@0 62 Option type to put defaults and comments in
tomwalters@0 63 the code.
tomwalters@0 64
tomwalters@0 65 16th March 1989 (Paul Manson) Altered the final argc/argv shuffling in getopts
tomwalters@0 66 so that argv simply points at the first argument
tomwalters@0 67 after the options. Also added fileopts.
tomwalters@0 68
tomwalters@0 69 29th March 1989 (Paul Manson) Altered ".res" to ".opt" to coincide with the new
tomwalters@0 70 naming r'egime. Also added the spitOptionsFile call
tomwalters@0 71 to automatically produce an options file with
tomwalters@0 72 comments. To enable this facility, compile getopts
tomwalters@0 73 with -DSPITHELP; to use it, type <prog> -spit. Do
tomwalters@0 74 NOT distribute a spitting version of getopts! Altered
tomwalters@0 75 Options-file scanning to permit trailing comments.
tomwalters@0 76
tomwalters@0 77 30th March 1989 (Paul Manson) Completely eradicated the blockWriteToFile used by
tomwalters@0 78 writenopts. This is now done on a non-aligned basis,
tomwalters@0 79 as this is likely to be quicker and less complex.
tomwalters@0 80
tomwalters@0 81 03rd April 1989 (Paul Manson) Added the calll to outputopt.
tomwalters@0 82
tomwalters@0 83 06th April 1989 (Paul Manson) Oh Joy! Oh Bliss! The once-much-maligned SPIT option
tomwalters@0 84 is recieved into decent society, albeit in the guise
tomwalters@0 85 of an options "editor" called 'update'.
tomwalters@0 86
tomwalters@0 87 10th April 1989 (Paul Manson) The 'update' option no longer exit(1)s, but
tomwalters@0 88 carries on to execute the program. Also changed
tomwalters@0 89 OptionFileName so that it correctly gets the
tomwalters@0 90 cwd on the PC.
tomwalters@0 91
tomwalters@0 92 11th April 1989 (Paul Manson) Altered the OptionFileName routines to be EITHER
tomwalters@0 93 for the PC or for Unix.
tomwalters@0 94
tomwalters@0 95 26th April 1989 (Paul Manson) Put in a temporary delta to the PC version so that it
tomwalters@0 96 only looks for option files (and hence only creates
tomwalters@0 97 option files) in the current directory. This will be
tomwalters@0 98 abandoned when we determine a better search strategy.
tomwalters@0 99
tomwalters@0 100 15th June 1989 (Paul Manson) Altered SilentOption so that it is alterable, but is
tomwalters@0 101 NOT visible in any way (ie. not printed by help or
tomwalters@0 102 spit, and not output to headers).
tomwalters@0 103
tomwalters@0 104 11th July 1989 (Paul Manson) Altered so that "help" (and "update") only display
tomwalters@0 105 (or output) the options which were either read in
tomwalters@0 106 from the options file, or have been subsequently
tomwalters@0 107 altered on the command line. The current implementation
tomwalters@0 108 simply checks to see whether the default and current
tomwalters@0 109 values for a particular option differ (either in value
tomwalters@0 110 OR address!).
tomwalters@0 111
tomwalters@0 112 27th July 1989 (Paul Manson) Altered so that isON == !isOFF, and not the other way
tomwalters@0 113 around -- this allows "2", "3", etc to masquerade as
tomwalters@0 114 "1" while only "0" is "off". Also changed so that no
tomwalters@0 115 quotes are output to file headers.
tomwalters@0 116
tomwalters@0 117
tomwalters@0 118 July 1994 (MAA) Allowed spaces in strings, by adding double-quotes
tomwalters@0 119 to the arguments. Bit of a hack, though.
tomwalters@0 120 ------------------------------------------------------------------------------- */
tomwalters@0 121
tomwalters@0 122 #include "options.h"
tomwalters@0 123 #include <stdio.h>
tomwalters@0 124 #include <string.h>
tomwalters@0 125 #if defined( NeXT)
tomwalters@0 126 #include <stdlib.h>
tomwalters@0 127 #else
tomwalters@0 128 #include <malloc.h>
tomwalters@0 129 #endif
tomwalters@0 130 #include <ctype.h>
tomwalters@0 131
tomwalters@0 132 #if !defined( lint )
tomwalters@0 133 static char *sccs_id = "@(#)options.c 1.14 Paul Manson (MRC-APU) 5/2/89";
tomwalters@0 134 #endif
tomwalters@0 135
tomwalters@0 136 char defversion[64] = "not set yet" , *versionstr = defversion ;
tomwalters@0 137
tomwalters@0 138 #if defined( PC )
tomwalters@0 139 #include <direct.h>
tomwalters@0 140 #define DOT '.'
tomwalters@0 141 #define BACKSLASH_CHAR '\\'
tomwalters@0 142 #define SLASH_CHARACTER '/'
tomwalters@0 143 #define OPTION_FILE_PREFIX ""
tomwalters@0 144 #define OPTION_FILE_SUFFIX ".opt"
tomwalters@0 145 #else
tomwalters@0 146 #ifndef THINK_C
tomwalters@0 147 #include <sys/types.h>
tomwalters@0 148 #include <sys/stat.h>
tomwalters@0 149 #endif
tomwalters@0 150 #define OPTION_FILE_PREFIX "."
tomwalters@0 151 #define OPTION_FILE_SUFFIX "rc"
tomwalters@0 152 #define OPTION_PATH "OPTIONSPATH"
tomwalters@0 153 /* Environment variable for path */
tomwalters@0 154 #define DEFAULT_OPTION_PATH "."
tomwalters@0 155 /* Path is first . then ~ (ie home) */
tomwalters@0 156 #endif
tomwalters@0 157
tomwalters@0 158 #define MAX_LINE_LENGTH (256)
tomwalters@0 159 #define MAX_NAME_LENGTH (128)
tomwalters@0 160 #define FALSE (0)
tomwalters@0 161 #define TRUE (1)
tomwalters@0 162 #define HYPHEN_CHARACTER '-'
tomwalters@0 163 #define BLANK_CHARACTER ' '
tomwalters@0 164 #define TAB_CHARACTER '\t'
tomwalters@0 165 #define NEWLINE_CHARACTER '\n'
tomwalters@0 166 #define DOUBLE_QUOTE_CHAR '\"'
tomwalters@0 167 #define ERROR_RESULT (1234)
tomwalters@0 168 #define EQUALS_CHARACTER '='
tomwalters@0 169 #define COMMENT_CHARACTER '#'
tomwalters@0 170 #define NULL_CHARACTER '\000'
tomwalters@0 171 #define CARRIAGE_RETURN '\r'
tomwalters@0 172
tomwalters@0 173 /* Options-specific definitions for "ON", "OFF" and "NULL" */
tomwalters@0 174
tomwalters@0 175 #define ON_STRING (ON_OPTION)
tomwalters@0 176 #define ON_ALIAS "1"
tomwalters@0 177
tomwalters@0 178 #define OFF_STRING (OFF_OPTION)
tomwalters@0 179 #define OFF_ALIAS "0"
tomwalters@0 180
tomwalters@0 181 #define NULL_STRING (NULL_OPTION)
tomwalters@0 182 #define NULL_ALIAS "null"
tomwalters@0 183
tomwalters@0 184 #define NOT_USED "Not_used"
tomwalters@0 185
tomwalters@0 186 /* For the search_path and Ambiguity procedures */
tomwalters@0 187
tomwalters@0 188 #define LINE_CHARS 200
tomwalters@0 189 #define AMBIGUOUS (-2)
tomwalters@0 190 #define NO_MATCH (-1)
tomwalters@0 191 #define DEFAULT_TOGGLE_VALUE (ON_STRING)
tomwalters@0 192
tomwalters@0 193 /* For the readopts and writeopts procedures */
tomwalters@0 194
tomwalters@0 195 #define OPTION_HEADER_SIZE ( sizeof ( head_string_start ) - 1 + size_digits + 1 )
tomwalters@0 196 #define OPTION_HEADER_HEADER "header_bytes="
tomwalters@0 197 #define OPTION_HEADER_DIGITS (7)
tomwalters@0 198
tomwalters@0 199 #define min(X,Y) (((X) < (Y)) ? (X) : (Y))
tomwalters@0 200
tomwalters@0 201 static char OptionHeaderHeader[] = OPTION_HEADER_HEADER;
tomwalters@0 202 static char LineFeedArray[] = "\n";
tomwalters@0 203 static char EqualsArray[] = "="; /* Was " = " */
tomwalters@0 204 static char QuotesArray[] = "\"";
tomwalters@0 205
tomwalters@0 206 /* For the OnLine Help Facility */
tomwalters@0 207
tomwalters@0 208 #define HELP_STRING "help"
tomwalters@0 209 #define UPDATE_STRING "update"
tomwalters@0 210 #define ALL_STRING "all"
tomwalters@0 211
tomwalters@0 212 static int helpOnAllRequired = FALSE;
tomwalters@0 213 static int helpOnOneRequired = FALSE;
tomwalters@0 214 static int helpOnOneLocation = 0;
tomwalters@0 215 static int updateAllRequired = FALSE;
tomwalters@0 216
tomwalters@0 217 extern void exit();
tomwalters@0 218 static int thereWasAnOptionsFile = FALSE;
tomwalters@0 219 static char *theOptionFileName = NULL;
tomwalters@0 220
tomwalters@0 221
tomwalters@0 222
tomwalters@0 223
tomwalters@0 224 #ifndef PC
tomwalters@0 225 /* -----------------------------------------------------------------------
tomwalters@0 226
tomwalters@0 227 search_path( file, path )
tomwalters@0 228 =========================
tomwalters@0 229
tomwalters@0 230 jwh - 4th jan 1987
tomwalters@0 231
tomwalters@0 232 searches through string path for file and returns full file name if it
tomwalters@0 233 finds it. Returns NULL if file is not found. Path is specified in normal
tomwalters@0 234 path format i.e. "dir1:dir2:dir3...". Works for "~" and "~/dir.." -
tomwalters@0 235 substitutes HOME for "~". ~ only works for current user!!
tomwalters@0 236
tomwalters@0 237 ----------------------------------------------------------------------- */
tomwalters@0 238
tomwalters@0 239
tomwalters@0 240 static char *search_path( file, path )
tomwalters@0 241 char *file, *path ;
tomwalters@0 242 {
tomwalters@0 243 #ifdef THINK_C
tomwalters@0 244 return ( file ) ;
tomwalters@0 245 #else
tomwalters@0 246 char file_name[ LINE_CHARS ] ;
tomwalters@0 247 int len_next ;
tomwalters@0 248 struct stat buf ;
tomwalters@0 249 extern getenv();
tomwalters@0 250 char *home_directory = (char *)getenv("HOME");
tomwalters@0 251
tomwalters@0 252 if( file[ 0 ] == '/' || file[ 0 ] == '.' && file[ 1 ] == '/' )
tomwalters@0 253 return ( strcpy( malloc((unsigned)(strlen(file) + 1)), file) );
tomwalters@0 254
tomwalters@0 255 do
tomwalters@0 256 {
tomwalters@0 257 len_next = ( strchr( path, ':' ) == NULL ) ?
tomwalters@0 258 strlen( path ) : strchr( path, ':' ) - path ;
tomwalters@0 259
tomwalters@0 260 if( *path == '~' )
tomwalters@0 261 {
tomwalters@0 262 (void) strcpy( file_name, home_directory ) ;
tomwalters@0 263 (void) strncpy( file_name + strlen( home_directory ), path+1,
tomwalters@0 264 len_next-1 ) ;
tomwalters@0 265 (void) sprintf( file_name + strlen( home_directory ) + len_next - 1 ,
tomwalters@0 266 "/%s", file ) ;
tomwalters@0 267 }
tomwalters@0 268 else
tomwalters@0 269 {
tomwalters@0 270 (void) strncpy( file_name, path, len_next ) ;
tomwalters@0 271 (void) sprintf( file_name + len_next , "/%s", file ) ;
tomwalters@0 272 }
tomwalters@0 273
tomwalters@0 274 if( stat( file_name, &buf ) >= 0 && ( buf.st_mode & S_IFDIR ) == 0 )
tomwalters@0 275 return ( strcpy( malloc((unsigned)(strlen(file_name) + 1)), file_name) );
tomwalters@0 276
tomwalters@0 277 path = path + len_next + 1 ;
tomwalters@0 278 }
tomwalters@0 279 while( path[ -1 ] != '\0' ) ;
tomwalters@0 280
tomwalters@0 281 /* return( NULL ) ; */ return( file ); /* If PATH is NULL, return FILE */
tomwalters@0 282 #endif
tomwalters@0 283 }
tomwalters@0 284
tomwalters@0 285 /* ---------------------------------------------------------------------------------
tomwalters@0 286
tomwalters@0 287 Return the Option File Name, given the Name of the Application (Unix Version)
tomwalters@0 288
tomwalters@0 289 Edited:
tomwalters@0 290
tomwalters@0 291 --------------------------------------------------------------------------------- */
tomwalters@0 292 char *UnixOptionFileName(appn)
tomwalters@0 293 char *appn ;
tomwalters@0 294 {
tomwalters@0 295 char *temp;
tomwalters@0 296
tomwalters@0 297 temp = malloc((unsigned) (strlen(appn) + strlen(OPTION_FILE_SUFFIX) +
tomwalters@0 298 strlen(OPTION_FILE_PREFIX) + 1));
tomwalters@0 299
tomwalters@0 300 temp = strcpy(temp,OPTION_FILE_PREFIX);
tomwalters@0 301 temp = strcat(temp,appn);
tomwalters@0 302 temp = strcat(temp,OPTION_FILE_SUFFIX);
tomwalters@0 303
tomwalters@0 304
tomwalters@0 305 return (temp);
tomwalters@0 306 }
tomwalters@0 307 #endif /* Unix Option File Stuff */
tomwalters@0 308
tomwalters@0 309 #if defined( PC )
tomwalters@0 310
tomwalters@0 311 /* ---------------------------------------------------------------------------------
tomwalters@0 312
tomwalters@0 313 Return the Option File Name, given the Name of the Application (PC Version)
tomwalters@0 314
tomwalters@0 315 Edited:
tomwalters@0 316
tomwalters@0 317 --------------------------------------------------------------------------------- */
tomwalters@0 318 char *PCOptionFileName(appn, onlyLocal)
tomwalters@0 319 char *appn ;
tomwalters@0 320 int onlyLocal;
tomwalters@0 321 {
tomwalters@0 322 char *temp;
tomwalters@0 323 int i ;
tomwalters@0 324 char *temp2, *lastPart;
tomwalters@0 325
tomwalters@0 326
tomwalters@0 327 temp = malloc((unsigned) (strlen(appn) + strlen(OPTION_FILE_SUFFIX) +
tomwalters@0 328 strlen(OPTION_FILE_PREFIX) + 1));
tomwalters@0 329
tomwalters@0 330 temp = strcpy(temp, appn);
tomwalters@0 331
tomwalters@0 332 for (i = 0; temp[i] != NULL_CHARACTER; i++)
tomwalters@0 333 if (temp[i] == BACKSLASH_CHAR)
tomwalters@0 334 temp[i] = SLASH_CHARACTER;
tomwalters@0 335
tomwalters@0 336 /* Strip Back to the Application Name */
tomwalters@0 337 if ((lastPart = strrchr(temp, SLASH_CHARACTER)) == NULL)
tomwalters@0 338 lastPart = temp;
tomwalters@0 339 else
tomwalters@0 340 lastPart++; /* Skip over the actual "/" */
tomwalters@0 341
tomwalters@0 342 /* lastPart points to the tail name of the path */
tomwalters@0 343
tomwalters@0 344 if ((temp2 = strchr(lastPart,DOT)) == NULL)
tomwalters@0 345 temp = strcat(temp,OPTION_FILE_SUFFIX);
tomwalters@0 346 else
tomwalters@0 347 temp2 = strcpy(temp2, OPTION_FILE_SUFFIX);
tomwalters@0 348
tomwalters@0 349 if (onlyLocal) /* Remove the full path to give only a local name */
tomwalters@0 350 return( lastPart);
tomwalters@0 351 else
tomwalters@0 352 return (temp);
tomwalters@0 353 }
tomwalters@0 354 #endif /* PC Version of OptionFileName */
tomwalters@0 355
tomwalters@0 356
tomwalters@0 357 /* ---------------------------------------------------------------------------------
tomwalters@0 358
tomwalters@0 359 Check that there is no ambiguity in the (possibly abbreviated) <name>. If there is
tomwalters@0 360 no match whatever, return NO_MATCH. If there is a single exact match, or a single
tomwalters@0 361 abbreviating match, return the index of the matched option; otherwise return
tomwalters@0 362 AMBIGUOUS.
tomwalters@0 363
tomwalters@0 364 --------------------------------------------------------------------------------- */
tomwalters@0 365 int Ambiguity(options, numOptions, name)
tomwalters@0 366 Option options[] ;
tomwalters@0 367 int numOptions;
tomwalters@0 368 char *name ;
tomwalters@0 369 {
tomwalters@0 370 int i, matched, matchedExactly, matchedWhere, moreThanOneInexactMatch;
tomwalters@0 371
tomwalters@0 372 matched = FALSE;
tomwalters@0 373 matchedExactly = FALSE;
tomwalters@0 374 moreThanOneInexactMatch = FALSE;
tomwalters@0 375
tomwalters@0 376 for (i = 0; i < numOptions; i++)
tomwalters@0 377 if (options[i].classification != OutputOption &&
tomwalters@0 378 strncmp(name, options[i].name, strlen(name)) == 0) {
tomwalters@0 379 if (matched) {
tomwalters@0 380 if (matchedExactly) {
tomwalters@0 381 if (strcmp(name, options[i].name) == 0) {
tomwalters@0 382 /* TWO Exact Matches */
tomwalters@0 383 return AMBIGUOUS;
tomwalters@0 384 }
tomwalters@0 385 }
tomwalters@0 386 else {
tomwalters@0 387 if (strcmp(name, options[i].name) == 0) {
tomwalters@0 388 /* THIS is an exact match */
tomwalters@0 389 matchedExactly = TRUE;
tomwalters@0 390 matchedWhere = i;
tomwalters@0 391 }
tomwalters@0 392 else {
tomwalters@0 393 /* There are two inexact matches ... if there are no exact ones we
tomwalters@0 394 have AMBIGUITY */
tomwalters@0 395 moreThanOneInexactMatch = TRUE;
tomwalters@0 396 }
tomwalters@0 397 }
tomwalters@0 398 }
tomwalters@0 399 else {
tomwalters@0 400 if (strcmp(name, options[i].name) == 0) {
tomwalters@0 401 /* This is an exact match */
tomwalters@0 402 matchedExactly = TRUE;
tomwalters@0 403 }
tomwalters@0 404 matched = TRUE;
tomwalters@0 405 matchedWhere = i ;
tomwalters@0 406 }
tomwalters@0 407 }
tomwalters@0 408
tomwalters@0 409 if (moreThanOneInexactMatch)
tomwalters@0 410 return (AMBIGUOUS);
tomwalters@0 411 else {
tomwalters@0 412 if (matched)
tomwalters@0 413 return (matchedWhere);
tomwalters@0 414 else
tomwalters@0 415 return (NO_MATCH);
tomwalters@0 416 }
tomwalters@0 417
tomwalters@0 418 }
tomwalters@0 419
tomwalters@0 420
tomwalters@0 421 /* ---------------------------------------------------------------------------------
tomwalters@0 422
tomwalters@0 423 Search for the named option in the list of options. If it is found, return its
tomwalters@0 424 location (index) in the options array. Otherwise, return NO_MATCH.
tomwalters@0 425
tomwalters@0 426 --------------------------------------------------------------------------------- */
tomwalters@0 427 int LookUp(options, numOptions, name)
tomwalters@0 428 Option options[] ;
tomwalters@0 429 int numOptions;
tomwalters@0 430 char *name ;
tomwalters@0 431 {
tomwalters@0 432 int i;
tomwalters@0 433
tomwalters@0 434 for (i = 0; i < numOptions; i++)
tomwalters@0 435 if (options[i].classification != OutputOption && strcmp(name, options[i].name) == 0) {
tomwalters@0 436 return (i);
tomwalters@0 437 }
tomwalters@0 438
tomwalters@0 439 return (NO_MATCH);
tomwalters@0 440
tomwalters@0 441 }
tomwalters@0 442
tomwalters@0 443 extern helpRoutine *onLineHelpHandler;
tomwalters@0 444 extern void updateOptionsFile();
tomwalters@0 445
tomwalters@0 446 /* ---------------------------------------------------------------------------------
tomwalters@0 447
tomwalters@0 448 Search for the named option in the list of options. If it is found, set its
tomwalters@0 449 new value as indicated and return TRUE. If not, return either FALSE or AMBIGUOUS.
tomwalters@0 450
tomwalters@0 451 Edited:
tomwalters@0 452
tomwalters@0 453 8th March 1989 (Paul Manson) Changed the call to LookUp to call Ambiguity instead,
tomwalters@0 454 thus achieving the matching of abbreviated options.
tomwalters@0 455
tomwalters@0 456 15th March 1989 (Paul Manson) Reinstated the call to LookUp in the case that
tomwalters@0 457 abbreviations (and hence ambiguity) are/is not
tomwalters@0 458 permitted (ie. in option Header Files).
tomwalters@0 459
tomwalters@0 460 --------------------------------------------------------------------------------- */
tomwalters@0 461 int LookUpAndStore(options, numOptions, name, value, permitAbbrevs, programName)
tomwalters@0 462 Option options[] ;
tomwalters@0 463 int numOptions ;
tomwalters@0 464 char *name, *value;
tomwalters@0 465 int permitAbbrevs;
tomwalters@0 466 char *programName ;
tomwalters@0 467 {
tomwalters@0 468 int loc ;
tomwalters@0 469 char *temp;
tomwalters@0 470
tomwalters@0 471 /* Account for specific references to the "help" option, with different
tomwalters@0 472 treatment of the "help=all" command */
tomwalters@0 473 if (strcmp(name, HELP_STRING) == 0) {
tomwalters@0 474 /* Check whether it is asking for ALL help */
tomwalters@0 475 if (strcmp(value, ALL_STRING) == 0) {
tomwalters@0 476 helpOnAllRequired = TRUE;
tomwalters@0 477 helpOnOneRequired = FALSE;
tomwalters@0 478 (*onLineHelpHandler)(options, numOptions, programName);
tomwalters@0 479 exit(0);
tomwalters@0 480 }
tomwalters@0 481 /* Check for other specific kinds of help request */
tomwalters@0 482 /* else if (strcmp(value, _STRING) == 0) { */
tomwalters@0 483
tomwalters@0 484
tomwalters@0 485 else {
tomwalters@0 486 /* Expand the (possibly abbreviated) option name */
tomwalters@0 487 if ((permitAbbrevs && ((loc = Ambiguity(options, numOptions, value)) >= 0)) ||
tomwalters@0 488 (!permitAbbrevs && ((loc = LookUp(options, numOptions, value)) >= 0))) {
tomwalters@0 489 helpOnOneRequired = TRUE;
tomwalters@0 490 helpOnAllRequired = FALSE;
tomwalters@0 491 helpOnOneLocation = loc ;
tomwalters@0 492 (*onLineHelpHandler)(options, numOptions, programName);
tomwalters@0 493 exit(0);
tomwalters@0 494 }
tomwalters@0 495 else {
tomwalters@0 496 if (loc == AMBIGUOUS) {
tomwalters@0 497 (void) fprintf(stderr, "WARNING: The option name %s is AMBIGUOUS; please be more specific.\n", value);
tomwalters@0 498 exit(1);
tomwalters@0 499 }
tomwalters@0 500 else {
tomwalters@0 501 (void) fprintf(stderr, "WARNING: The %s program does not have an option named %s.\n",
tomwalters@0 502 programName, value);
tomwalters@0 503 exit(1);
tomwalters@0 504 }
tomwalters@0 505 }
tomwalters@0 506 }
tomwalters@0 507 }
tomwalters@0 508 else if (strcmp(name, UPDATE_STRING) == 0) {
tomwalters@0 509 /* Check whether it is asking for ALL updated */
tomwalters@0 510 if (strcmp(value, ALL_STRING) == 0) {
tomwalters@0 511 updateAllRequired = TRUE ;
tomwalters@0 512 updateOptionsFile(options, numOptions, programName, theOptionFileName);
tomwalters@0 513 updateAllRequired = FALSE;
tomwalters@0 514 helpOnAllRequired = TRUE ;
tomwalters@0 515 helpOnOneRequired = FALSE;
tomwalters@0 516 return (TRUE);
tomwalters@0 517 }
tomwalters@0 518 else {
tomwalters@0 519 /* At present there is no use for a specific update call */
tomwalters@0 520 (void) fprintf(stderr, "options: The update option may not be altered!\n");
tomwalters@0 521 exit(1);
tomwalters@0 522 }
tomwalters@0 523 }
tomwalters@0 524 else if ((permitAbbrevs && ((loc = Ambiguity(options, numOptions, name)) >= 0)) ||
tomwalters@0 525 (!permitAbbrevs && ((loc = LookUp(options, numOptions, name)) >= 0))) {
tomwalters@0 526 /* It is a conventional "LookUpAndStore" operation */
tomwalters@0 527 temp = malloc((unsigned)(strlen(value) + 1));
tomwalters@0 528 temp = strcpy(temp, value);
tomwalters@0 529 *(options[loc].value) = temp;
tomwalters@0 530 return (TRUE);
tomwalters@0 531 }
tomwalters@0 532 else {
tomwalters@0 533 if (loc == AMBIGUOUS) {
tomwalters@0 534 #if defined( PC )
tomwalters@0 535 (void) fprintf(stderr,
tomwalters@0 536 "ERROR: The name %s is AMBIGUOUS, and the value %s has not been assigned to any option\n", name, value);
tomwalters@0 537 exit(1);
tomwalters@0 538 #else
tomwalters@0 539 (void) fprintf(stderr,
tomwalters@0 540 "WARNING: The name %s is AMBIGUOUS, and the value %s has not been assigned to any option\n", name, value);
tomwalters@0 541 return (AMBIGUOUS);
tomwalters@0 542 #endif
tomwalters@0 543 }
tomwalters@0 544 else
tomwalters@0 545 return (FALSE);
tomwalters@0 546 }
tomwalters@0 547
tomwalters@0 548
tomwalters@0 549 }
tomwalters@0 550
tomwalters@0 551
tomwalters@0 552 /* ---------------------------------------------------------------------------------
tomwalters@0 553
tomwalters@0 554 Skip Blanks and Tabs. Stop at a printable character or a newline or null.
tomwalters@0 555
tomwalters@0 556 --------------------------------------------------------------------------------- */
tomwalters@0 557 char *skipBlanks (ptr)
tomwalters@0 558 char *ptr;
tomwalters@0 559 {
tomwalters@0 560 while ((*ptr == BLANK_CHARACTER) || (*ptr == TAB_CHARACTER)) ptr++;
tomwalters@0 561
tomwalters@0 562 return (ptr);
tomwalters@0 563 }
tomwalters@0 564
tomwalters@0 565
tomwalters@0 566 /* ---------------------------------------------------------------------------------
tomwalters@0 567
tomwalters@0 568 Ensure that the next character is an '='. If it is, return a pointer to the first
tomwalters@0 569 character after the '='; otherwise, return NULL.
tomwalters@0 570
tomwalters@0 571 --------------------------------------------------------------------------------- */
tomwalters@0 572 char *skipEquals (ptr)
tomwalters@0 573 char *ptr;
tomwalters@0 574 {
tomwalters@0 575 if (ptr[0] == EQUALS_CHARACTER)
tomwalters@0 576 return (++ptr);
tomwalters@0 577 else
tomwalters@0 578 return (NULL);
tomwalters@0 579 }
tomwalters@0 580
tomwalters@0 581
tomwalters@0 582 /* ---------------------------------------------------------------------------------
tomwalters@0 583
tomwalters@0 584 Read a name (ie. a token, a contiguous sequence of nonblank characters, or a
tomwalters@0 585 quoted string) from the string pointed to by ptr, and copy it the buffer pointed
tomwalters@0 586 to by <name>. If successful, return a pointer to the character after the token;
tomwalters@0 587 otherwise, return NULL.
tomwalters@0 588
tomwalters@0 589 --------------------------------------------------------------------------------- */
tomwalters@0 590 char *getName (ptr, name)
tomwalters@0 591 char *ptr, *name;
tomwalters@0 592 {
tomwalters@0 593 char *temp, *i, *namePtr;
tomwalters@0 594 char stopChar;
tomwalters@0 595
tomwalters@0 596 if (ptr[0] == DOUBLE_QUOTE_CHAR) {
tomwalters@0 597 ptr++;
tomwalters@0 598 stopChar = DOUBLE_QUOTE_CHAR;
tomwalters@0 599 }
tomwalters@0 600 else
tomwalters@0 601 stopChar = BLANK_CHARACTER;
tomwalters@0 602
tomwalters@0 603 temp = ptr;
tomwalters@0 604
tomwalters@0 605 while (*temp != NULL_CHARACTER &&
tomwalters@0 606 *temp != NEWLINE_CHARACTER &&
tomwalters@0 607 *temp != CARRIAGE_RETURN &&
tomwalters@0 608 ((stopChar == DOUBLE_QUOTE_CHAR && *temp != stopChar) ||
tomwalters@0 609 (stopChar == BLANK_CHARACTER &&
tomwalters@0 610 (*temp != stopChar && *temp != TAB_CHARACTER && *temp != EQUALS_CHARACTER))))
tomwalters@0 611 temp++;
tomwalters@0 612
tomwalters@0 613 if (stopChar == DOUBLE_QUOTE_CHAR && *temp != DOUBLE_QUOTE_CHAR) {
tomwalters@0 614 (void) fprintf(stderr, "options: Improperly closed quoted string %s\n", --ptr);
tomwalters@0 615 return (NULL);
tomwalters@0 616 }
tomwalters@0 617
tomwalters@0 618 namePtr = name;
tomwalters@0 619
tomwalters@0 620 for (i = ptr; i < temp; )
tomwalters@0 621 *namePtr++ = *i++;
tomwalters@0 622
tomwalters@0 623 *namePtr = NULL_CHARACTER;
tomwalters@0 624
tomwalters@0 625 if (stopChar == DOUBLE_QUOTE_CHAR)
tomwalters@0 626 temp++;
tomwalters@0 627
tomwalters@0 628
tomwalters@0 629 return (temp);
tomwalters@0 630
tomwalters@0 631 }
tomwalters@0 632
tomwalters@0 633
tomwalters@0 634 /* ------------------------------------------------------------------------------
tomwalters@0 635
tomwalters@0 636 Read lines from the specified file, updating option settings as appropriate.
tomwalters@0 637
tomwalters@0 638 Edits: 29th March 1989 (Paul Manson) Altered so that trailing comments allowed.
tomwalters@0 639
tomwalters@0 640 ------------------------------------------------------------------------------ */
tomwalters@0 641 void processOptionFile (options, numOptions, OptionFile, theOptionFileName,
tomwalters@0 642 limitedChars, checkOptions, programName)
tomwalters@0 643 Option options[] ;
tomwalters@0 644 int numOptions ;
tomwalters@0 645 FILE *OptionFile ;
tomwalters@0 646 char *theOptionFileName;
tomwalters@0 647 int limitedChars ;
tomwalters@0 648 int checkOptions ;
tomwalters@0 649 char *programName ;
tomwalters@0 650 {
tomwalters@0 651 int result ;
tomwalters@0 652 char name[MAX_NAME_LENGTH] ;
tomwalters@0 653 char value[MAX_NAME_LENGTH] ;
tomwalters@0 654 char *line, *linePtr;
tomwalters@0 655 int maxCharsToRead ;
tomwalters@0 656 int totalCharsRead ;
tomwalters@0 657
tomwalters@0 658 result = EOF;
tomwalters@0 659 totalCharsRead = 0 ;
tomwalters@0 660 line = malloc((unsigned) MAX_LINE_LENGTH + 1);
tomwalters@0 661
tomwalters@0 662 maxCharsToRead = ((limitedChars) ? (min(MAX_LINE_LENGTH, limitedChars)) :
tomwalters@0 663 MAX_LINE_LENGTH);
tomwalters@0 664
tomwalters@0 665 while (maxCharsToRead > 0 && ((line = fgets(line, maxCharsToRead + 1,
tomwalters@0 666 OptionFile)) != NULL)) {
tomwalters@0 667
tomwalters@0 668 if (line[0] == NULL_CHARACTER)
tomwalters@0 669 break; /* In the case of a Option Header */
tomwalters@0 670 else
tomwalters@0 671 if (limitedChars) {
tomwalters@0 672 totalCharsRead += strlen(line);
tomwalters@0 673 maxCharsToRead = min(MAX_LINE_LENGTH, limitedChars - totalCharsRead);
tomwalters@0 674 }
tomwalters@0 675
tomwalters@0 676 linePtr = skipBlanks(line);
tomwalters@0 677
tomwalters@0 678 /* Check for Comments and Blank Lines */
tomwalters@0 679 if ((linePtr[0] == COMMENT_CHARACTER) ||
tomwalters@0 680 (linePtr[0] == NEWLINE_CHARACTER) ||
tomwalters@0 681 (linePtr[0] == CARRIAGE_RETURN ) ||
tomwalters@0 682 (linePtr[0] == NULL_CHARACTER))
tomwalters@0 683 continue;
tomwalters@0 684
tomwalters@0 685 if ((linePtr = getName(linePtr, name)) == NULL) {
tomwalters@0 686 (void) fprintf(stderr, "options: Missing or Invalid name\n");
tomwalters@0 687 result = ERROR_RESULT;
tomwalters@0 688 break;
tomwalters@0 689 }
tomwalters@0 690 linePtr = skipBlanks(linePtr);
tomwalters@0 691 if ((linePtr = skipEquals(linePtr)) == NULL) {
tomwalters@0 692 (void) fprintf(stderr, "options: Expected an '=' after the name %s\n", name);
tomwalters@0 693 result = ERROR_RESULT;
tomwalters@0 694 break;
tomwalters@0 695 }
tomwalters@0 696 linePtr = skipBlanks(linePtr);
tomwalters@0 697 if ((linePtr = getName(linePtr, value)) == NULL) {
tomwalters@0 698 (void) fprintf(stderr,
tomwalters@0 699 "options: Missing or Invalid value; name is %s\n", name);
tomwalters@0 700 result = ERROR_RESULT;
tomwalters@0 701 break;
tomwalters@0 702 }
tomwalters@0 703 linePtr = skipBlanks(linePtr);
tomwalters@0 704 if ((*linePtr != NEWLINE_CHARACTER) &&
tomwalters@0 705 (*linePtr != NULL_CHARACTER) &&
tomwalters@0 706 (*linePtr != COMMENT_CHARACTER) &&
tomwalters@0 707 (*linePtr != CARRIAGE_RETURN)) {
tomwalters@0 708 (void) fprintf(stderr,
tomwalters@0 709 "options: Detected Trailing Garbage in the line %s = %s\n",
tomwalters@0 710 name, value);
tomwalters@0 711 result = ERROR_RESULT;
tomwalters@0 712 break;
tomwalters@0 713 }
tomwalters@0 714
tomwalters@0 715 if (!LookUpAndStore(options, numOptions, name, value, checkOptions, programName) &&
tomwalters@0 716 checkOptions) {
tomwalters@0 717 (void) fprintf(stderr, "options: Could not find Option Called %s\n",
tomwalters@0 718 name);
tomwalters@0 719 result = ERROR_RESULT;
tomwalters@0 720 break;
tomwalters@0 721 }
tomwalters@0 722
tomwalters@0 723 }
tomwalters@0 724
tomwalters@0 725 if (result != EOF) {
tomwalters@0 726 (void) fprintf(stderr,"options: Error reading the Option File %s\n",
tomwalters@0 727 theOptionFileName);
tomwalters@0 728 (void) fprintf(stderr,"options: Remainder of File is as follows;\n");
tomwalters@0 729 (void) fputs(line, stderr);
tomwalters@0 730 while ((line = fgets(line, MAX_LINE_LENGTH, OptionFile)) != NULL)
tomwalters@0 731 (void) fputs(line, stderr);
tomwalters@0 732 exit(1);
tomwalters@0 733 }
tomwalters@0 734 }
tomwalters@0 735
tomwalters@0 736
tomwalters@0 737 /* ------------------------------------------------------------------------------
tomwalters@0 738
tomwalters@0 739 OnLine Help Facility. This is simply the default handler which is to be called
tomwalters@0 740 if the user specifies no replacement handler.
tomwalters@0 741
tomwalters@0 742 ------------------------------------------------------------------------------ */
tomwalters@0 743 static void defaultHelpHandler(options, numOptions, progName)
tomwalters@0 744 Option options[] ;
tomwalters@0 745 int numOptions;
tomwalters@0 746 char *progName ;
tomwalters@0 747 {
tomwalters@0 748 register int help, res;
tomwalters@0 749
tomwalters@0 750 if (helpOnOneRequired) {
tomwalters@0 751 res = helpOnOneLocation;
tomwalters@0 752 (void) fprintf(stdout, "%-13s %-9s %-9s %s\n", options[res].name,
tomwalters@0 753 ((*(options[res].value) == NULL) ? ("") : (*(options[res].value))),
tomwalters@0 754 ((options[res].defaultValue == NULL) ? ("") : (options[res].defaultValue)),
tomwalters@0 755 ((options[res].comment == NULL) ? ("") : (options[res].comment)));
tomwalters@0 756 return;
tomwalters@0 757 }
tomwalters@0 758
tomwalters@0 759 help = -1;
tomwalters@0 760 for (res = 0; res < numOptions; res++)
tomwalters@0 761 if (strcmp(options[res].name, HELP_STRING) == 0) {
tomwalters@0 762 help = res;
tomwalters@0 763 break ;
tomwalters@0 764 };
tomwalters@0 765
tomwalters@0 766
tomwalters@0 767 /************* Print head of help menu *****************/
tomwalters@0 768 if (help < 0) {
tomwalters@0 769 (void) fprintf(stdout, "The Rotter who wrote the `%s' program hasn't provided any \n",
tomwalters@0 770 progName);
tomwalters@0 771 (void) fprintf(stdout, "form of on-line 'help' documentation, tsk tsk!\n\n");
tomwalters@0 772 (void) fprintf(stdout,
tomwalters@0 773 "We can, however, provide you with the list of available options:\n\n");
tomwalters@0 774 }
tomwalters@0 775 else {
tomwalters@0 776
tomwalters@0 777 (void)fprintf(stdout,"%s\n", versionstr);
tomwalters@0 778 (void) fprintf(stdout,
tomwalters@0 779 "Usage: %s [options] %s\n\n", progName, options[help].comment);
tomwalters@0 780 }
tomwalters@0 781
tomwalters@0 782 (void) fprintf(stdout, "Option Name Current Default Comment\n");
tomwalters@0 783 (void) fprintf(stdout, "----------- ------- ------- -------\n");
tomwalters@0 784
tomwalters@0 785 for (res = numOptions-1 ; res >= 0 ; res-- )
tomwalters@0 786 if (options[res].classification < OutputOption &&
tomwalters@0 787 (!thereWasAnOptionsFile || helpOnAllRequired ||
tomwalters@0 788 strcmp(*(options[res].value), options[res].defaultValue) != 0 ||
tomwalters@0 789 *(options[res].value) != options[res].defaultValue))
tomwalters@0 790 (void) fprintf(stdout, "%-13s %-9s %-9s %s\n", options[res].name,
tomwalters@0 791 ((*(options[res].value) == NULL) ? ("") : (*(options[res].value))),
tomwalters@0 792 ((options[res].defaultValue == NULL) ? ("") : (options[res].defaultValue)),
tomwalters@0 793 ((options[res].comment == NULL) ? ("") : (options[res].comment)));
tomwalters@0 794
tomwalters@0 795 (void) fprintf(stdout, "\n");
tomwalters@0 796 return;
tomwalters@0 797 }
tomwalters@0 798
tomwalters@0 799 /* ----- Declare the handlerHolder variable ----- */
tomwalters@0 800
tomwalters@0 801 static helpRoutine *onLineHelpHandler = defaultHelpHandler;
tomwalters@0 802
tomwalters@0 803
tomwalters@0 804 /* ------------------------------------------------------------------------------
tomwalters@0 805
tomwalters@0 806 Spit out the options to a file (with the appropriate option file name).
tomwalters@0 807
tomwalters@0 808 Edits: 29th March 1989 (Paul Manson). For the sake of IBM/PC users, this routine
tomwalters@0 809 will now spit lines with CR/LF pairs.
tomwalters@0 810 06th April 1989 (Paul Manson). This routine is no-longer conditionally
tomwalters@0 811 compiled, but is now more widely accepted.
tomwalters@0 812
tomwalters@0 813 ------------------------------------------------------------------------------ */
tomwalters@0 814
tomwalters@0 815 void updateOptionsFile(options, numOptions, programName, resFileName)
tomwalters@0 816 Option options[] ;
tomwalters@0 817 int numOptions ;
tomwalters@0 818 char *programName;
tomwalters@0 819 char *resFileName;
tomwalters@0 820 {
tomwalters@0 821 int res ;
tomwalters@0 822 FILE *fptr;
tomwalters@0 823
tomwalters@0 824 if ((fptr = fopen(resFileName, "w")) == NULL) {
tomwalters@0 825 (void) fprintf(stderr, "Unable to Update Options File called %s.\n", resFileName);
tomwalters@0 826 exit(1);
tomwalters@0 827 }
tomwalters@0 828
tomwalters@0 829 #if defined( PC ) || defined( THINK_C )
tomwalters@0 830 (void) fprintf(fptr ,"# %s\n", versionstr);
tomwalters@0 831 (void) fprintf(fptr, "#\r\n# Options file for the %s program.\r\n#\r\n\r\n", programName);
tomwalters@0 832 (void) fprintf(fptr, "#Option Name Current Default Comment\r\n");
tomwalters@0 833 (void) fprintf(fptr, "#----------- ------- ------- -------\r\n\r\n");
tomwalters@0 834 #else
tomwalters@0 835 (void) fprintf(fptr ,"# %s\n", versionstr);
tomwalters@0 836 (void) fprintf(fptr, "#\n# Options file for the %s program.\n#\n\n", programName);
tomwalters@0 837 (void) fprintf(fptr, "#Option Name Current Default Comment\n");
tomwalters@0 838 (void) fprintf(fptr, "#----------- ------- ------- -------\n\n");
tomwalters@0 839 #endif
tomwalters@0 840
tomwalters@0 841 for (res = numOptions-1; res >=0 ; res-- )
tomwalters@0 842 if (options[res].classification < OutputOption && *(options[res].value) != NULL &&
tomwalters@0 843 (updateAllRequired ||
tomwalters@0 844 strcmp(*(options[res].value), options[res].defaultValue) != 0 ||
tomwalters@0 845 *(options[res].value) != options[res].defaultValue)) {
tomwalters@0 846 #if defined( PC )
tomwalters@0 847 (void) fprintf(fptr, "%-13s = %-9s # %-9s %s\r\n", options[res].name,
tomwalters@0 848 ((*(options[res].value) == NULL) ? ("") : (*(options[res].value))),
tomwalters@0 849 ((options[res].defaultValue == NULL) ? ("") : (options[res].defaultValue)),
tomwalters@0 850 ((options[res].comment == NULL) ? ("") : (options[res].comment)));
tomwalters@0 851 #else
tomwalters@0 852 (void) fprintf(fptr, "%-13s = %-9s # %-9s %s\n", options[res].name,
tomwalters@0 853 ((*(options[res].value) == NULL) ? ("") : (*(options[res].value))),
tomwalters@0 854 ((options[res].defaultValue == NULL) ? ("") : (options[res].defaultValue)),
tomwalters@0 855 ((options[res].comment == NULL) ? ("") : (options[res].comment)));
tomwalters@0 856 #endif
tomwalters@0 857 }
tomwalters@0 858
tomwalters@0 859 if (fclose(fptr) == EOF) {
tomwalters@0 860 (void) fprintf(stderr, "options: fclose failed on the options file %s.\n", resFileName);
tomwalters@0 861 exit(1);
tomwalters@0 862 }
tomwalters@0 863
tomwalters@0 864 thereWasAnOptionsFile = TRUE; /* Cos there is one now! */
tomwalters@0 865
tomwalters@0 866 return;
tomwalters@0 867 }
tomwalters@0 868
tomwalters@0 869
tomwalters@0 870 /* ------------------------------------------------------------------------------
tomwalters@0 871
tomwalters@0 872 Process the option file and then the command line options supplied.
tomwalters@0 873
tomwalters@0 874 Edited:
tomwalters@0 875
tomwalters@0 876 2nd March 1989 (Paul Manson). Changed the calls to OptionFileName (ie.
tomwalters@0 877 added a <prefix> argument) to facilitate
tomwalters@0 878 searching of HOME (etc) directories. Note
tomwalters@0 879 that this is IGNORED for IBM/PCs.
tomwalters@0 880
tomwalters@0 881 8th March 1989 (Paul Manson). Ignore the above, as OPTIONSPATH is now
tomwalters@0 882 used (in conjunction with search_path) to
tomwalters@0 883 enable proper paths for Unix.
tomwalters@0 884
tomwalters@0 885 10th March 1989 (Paul Manson). Added the "help" facility and the default
tomwalters@0 886 and comment stuff.
tomwalters@0 887
tomwalters@0 888 16th March 1989 (Paul Manson). Altered the final argc/argv shuffling so that
tomwalters@0 889 argv simply points at the first argument after
tomwalters@0 890 the options.
tomwalters@0 891
tomwalters@0 892 July 1994 (MAA). Mended to allow spaces in command-line strings.
tomwalters@0 893
tomwalters@0 894 ------------------------------------------------------------------------------ */
tomwalters@0 895
tomwalters@0 896
tomwalters@0 897
tomwalters@0 898
tomwalters@0 899 /* Assign the default options */
tomwalters@0 900
tomwalters@0 901 void default_nopts( options, numOptions )
tomwalters@0 902 Option options[] ;
tomwalters@0 903 int numOptions ;
tomwalters@0 904 {
tomwalters@0 905 int i ;
tomwalters@0 906
tomwalters@0 907 for (i = 0; i < numOptions; i++)
tomwalters@0 908 *(options[i].value) = options[i].defaultValue ;
tomwalters@0 909 }
tomwalters@0 910
tomwalters@0 911
tomwalters@0 912
tomwalters@0 913 /****************************************************************************
tomwalters@0 914 * Assign options from the rc file.
tomwalters@0 915 *
tomwalters@0 916 * The option file is called ".genxxxrc", where the "xxx" is determined
tomwalters@0 917 * by the name of the application, (which is in argv[0]).
tomwalters@0 918 * Here "rc" stands for "resource control".
tomwalters@0 919 * The file-name is assigned to a string ptr "theOptionFileName".
tomwalters@0 920 * On Unix, the path for the file-name is determined as follows:
tomwalters@0 921 * if environment variable OPTION_PATH is set, then use this path.
tomwalters@0 922 * else the default path is:
tomwalters@0 923 * `.' (the current directory)
tomwalters@0 924 * `~' (the users home directory)
tomwalters@0 925 * The DEFAULT_OPTION_PATH for the option file is defined "." (see above).
tomwalters@0 926 * This means look first in the current directory, and failing that in the
tomwalters@0 927 * users home directory.
tomwalters@0 928 * But these defaults can be overridden by setting an environment variable,
tomwalters@0 929 * which is defined as OPTIONSPATH (see above). Thus the user could set a
tomwalters@0 930 * new default path for option files by, eg:
tomwalters@0 931 * setenv OPTIONSPATH ".:~/rcbin"
tomwalters@0 932 * This would look first in the current directory, and failing that in a
tomwalters@0 933 * directory ~/rcbin
tomwalters@0 934 *****************************************************************************/
tomwalters@0 935
tomwalters@0 936 void rcfile_nopts( options, numOptions, file )
tomwalters@0 937 Option options[] ;
tomwalters@0 938 int numOptions ;
tomwalters@0 939 char *file ;
tomwalters@0 940 {
tomwalters@0 941 FILE *OptionFile ;
tomwalters@0 942 char *OptionPathPtr ;
tomwalters@0 943
tomwalters@0 944
tomwalters@0 945 #if defined( PC )
tomwalters@0 946 if (((OptionFile = fopen(theOptionFileName =
tomwalters@0 947 PCOptionFileName( file, TRUE ), "r")) != NULL)) {
tomwalters@0 948 /* -------------------------------------------------------------------------------------
tomwalters@0 949 Removed temporarily so the PC version ONLY examines and creates option files
tomwalters@0 950 in the cwd. This will be changed when we determine a better strategy for
tomwalters@0 951 PC directory PATH searches.
tomwalters@0 952
tomwalters@0 953 ((OptionFile = fopen(theOptionFileName =
tomwalters@0 954 PCOptionFileName( file, FALSE), "r")) != NULL)) {
tomwalters@0 955 ---------------------------------------------------------------------------------------*/
tomwalters@0 956 #else
tomwalters@0 957 if ((OptionPathPtr = (char *)getenv(OPTION_PATH)) == NULL)
tomwalters@0 958 OptionPathPtr = DEFAULT_OPTION_PATH;
tomwalters@0 959
tomwalters@0 960 if ((OptionFile = fopen(theOptionFileName =
tomwalters@0 961 search_path(UnixOptionFileName( file ),
tomwalters@0 962 OptionPathPtr), "r")) != NULL) {
tomwalters@0 963 #endif
tomwalters@0 964
tomwalters@0 965 /* Process the Option File */
tomwalters@0 966
tomwalters@0 967 (void) processOptionFile(options, numOptions, OptionFile,
tomwalters@0 968 theOptionFileName, FALSE, TRUE, file ) ;
tomwalters@0 969 (void) fclose(OptionFile);
tomwalters@0 970
tomwalters@0 971 thereWasAnOptionsFile = TRUE;
tomwalters@0 972
tomwalters@0 973 }
tomwalters@0 974 }
tomwalters@0 975
tomwalters@0 976
tomwalters@0 977 /* Assign options from the command line */
tomwalters@0 978
tomwalters@0 979 void cmd_line_nopts( options, numOptions, argc, argv )
tomwalters@0 980 Option options[] ;
tomwalters@0 981 int numOptions ;
tomwalters@0 982 int *argc ;
tomwalters@0 983 char ***argv ;
tomwalters@0 984 {
tomwalters@0 985 int i, currentArg ;
tomwalters@0 986 int finalArg, wasAHyphen ;
tomwalters@0 987 char name[MAX_NAME_LENGTH] ;
tomwalters@0 988 char value[MAX_NAME_LENGTH] ;
tomwalters@0 989 char *line, *linePtr;
tomwalters@0 990 char *tempstring; /* MAA 23-4-1994 */
tomwalters@0 991 char *tempstring2; /* MAA 23-4-1994 */
tomwalters@0 992 int count=0;
tomwalters@0 993
tomwalters@0 994
tomwalters@0 995 /* MAA: next 3 lines */
tomwalters@0 996 linePtr = (char *) calloc((size_t) MAX_NAME_LENGTH, (size_t) sizeof(char));
tomwalters@0 997 tempstring = (char *) calloc((size_t) MAX_NAME_LENGTH, (size_t) sizeof(char));
tomwalters@0 998 tempstring2 = (char *) calloc((size_t) MAX_NAME_LENGTH, (size_t) sizeof(char));
tomwalters@0 999
tomwalters@0 1000
tomwalters@0 1001 finalArg = currentArg = 1; /* Ignore the Program Name */
tomwalters@0 1002 line = malloc((unsigned) MAX_LINE_LENGTH);
tomwalters@0 1003
tomwalters@0 1004 while (currentArg < *argc) {
tomwalters@0 1005 wasAHyphen = FALSE;
tomwalters@0 1006 linePtr = strcpy(line, (*argv)[currentArg]);
tomwalters@0 1007 if (linePtr[0] == HYPHEN_CHARACTER) {
tomwalters@0 1008 wasAHyphen = TRUE;
tomwalters@0 1009 linePtr++; /* Skip any leading hyphen */
tomwalters@0 1010 }
tomwalters@0 1011
tomwalters@0 1012 /* MAA: force doublequotes onto beg & end . A rather big hack ...*/
tomwalters@0 1013 if (strchr(linePtr, BLANK_CHARACTER) != NULL){
tomwalters@0 1014 strncpy(tempstring, linePtr, (int) strcspn(linePtr, "="));
tomwalters@0 1015 strcat(tempstring, "=\"");
tomwalters@0 1016 tempstring2 = (char *) strrchr(linePtr, EQUALS_CHARACTER);
tomwalters@0 1017 tempstring2++;
tomwalters@0 1018 strcat(tempstring, tempstring2);
tomwalters@0 1019 strcat(tempstring, "\"");
tomwalters@0 1020 linePtr=tempstring;}
tomwalters@0 1021
tomwalters@0 1022
tomwalters@0 1023 if ((linePtr = getName(linePtr, name)) == NULL) {
tomwalters@0 1024 break;
tomwalters@0 1025 }
tomwalters@0 1026
tomwalters@0 1027 if ((linePtr = skipEquals(linePtr)) == NULL) {
tomwalters@0 1028 if (!wasAHyphen) {
tomwalters@0 1029 break; /* Don't interpret <name> <value> as being options */
tomwalters@0 1030 }
tomwalters@0 1031 if (strcmp(name, HELP_STRING) == 0) {
tomwalters@0 1032 #ifdef PC
tomwalters@0 1033 if (strncmp((*argv)[0]+strlen((*argv)[0])-strlen("gen.exe"), "gen", strlen("gen")) == 0)
tomwalters@0 1034 #else
tomwalters@0 1035 if (strcmp((*argv)[0], "gen") == 0)
tomwalters@0 1036 #endif
tomwalters@0 1037 /* Special case of gen -help */
tomwalters@0 1038 usageHelp();
tomwalters@0 1039 else
tomwalters@0 1040 /* Case of gen??? -help */
tomwalters@0 1041 (*onLineHelpHandler)(options, numOptions, (*argv)[0]);
tomwalters@0 1042 exit(0);
tomwalters@0 1043 }
tomwalters@0 1044
tomwalters@0 1045 if (strcmp(name, UPDATE_STRING) == 0) {
tomwalters@0 1046 /* Do the Update and Then Goto the Top of the Loop Again */
tomwalters@0 1047 updateOptionsFile(options, numOptions, (*argv)[0], theOptionFileName);
tomwalters@0 1048 finalArg = ++currentArg;
tomwalters@0 1049 continue;
tomwalters@0 1050 }
tomwalters@0 1051
tomwalters@0 1052 (void) strcpy(value, DEFAULT_TOGGLE_VALUE);
tomwalters@0 1053 }
tomwalters@0 1054 else {
tomwalters@0 1055 if ((linePtr = getName(linePtr, value)) == NULL) {
tomwalters@0 1056 break;
tomwalters@0 1057 }
tomwalters@0 1058 }
tomwalters@0 1059
tomwalters@0 1060 if(!LookUpAndStore(options, numOptions, name, value, TRUE, (*argv)[0])) {
tomwalters@0 1061 (void) fprintf(stderr,"options: Could not find an Option called %s\n", name);
tomwalters@0 1062 exit(1);
tomwalters@0 1063 }
tomwalters@0 1064
tomwalters@0 1065 finalArg = ++currentArg;
tomwalters@0 1066 }
tomwalters@0 1067
tomwalters@0 1068 /* Reset the Command Line argc and argv */
tomwalters@0 1069 /* The Original Version actually cut the options out of the argv array (by
tomwalters@0 1070 shifting the remaining arguments left), but the new version simply lets
tomwalters@0 1071 argv point to the next argument to be processed.
tomwalters@0 1072
tomwalters@0 1073 if (finalArg > 1) {
tomwalters@0 1074 for (i = finalArg; i < *argc; i++)
tomwalters@0 1075 (*argv)[i - finalArg + 1] = (*argv)[i];
tomwalters@0 1076 *argc = *argc - finalArg + 1;
tomwalters@0 1077 }
tomwalters@0 1078
tomwalters@0 1079 */
tomwalters@0 1080
tomwalters@0 1081 *argv+= finalArg;
tomwalters@0 1082 *argc = *argc - finalArg;
tomwalters@0 1083
tomwalters@0 1084 return;
tomwalters@0 1085 }
tomwalters@0 1086
tomwalters@0 1087
tomwalters@0 1088
tomwalters@0 1089 /* Assign options using defaults, then the rc file, then the command line */
tomwalters@0 1090
tomwalters@0 1091 void getnopts (options, numOptions, argc, argv)
tomwalters@0 1092 Option options[] ;
tomwalters@0 1093 int numOptions ;
tomwalters@0 1094 int *argc ;
tomwalters@0 1095 char ***argv ;
tomwalters@0 1096 {
tomwalters@0 1097 default_nopts( options, numOptions ) ;
tomwalters@0 1098 rcfile_nopts( options, numOptions, (*argv)[0] ) ;
tomwalters@0 1099 cmd_line_nopts( options, numOptions, argc, argv ) ;
tomwalters@0 1100 }
tomwalters@0 1101
tomwalters@0 1102
tomwalters@0 1103
tomwalters@0 1104 /* -------------------------------------------------------------------------------
tomwalters@0 1105
tomwalters@0 1106 Read an option header from the specified file into the given options array.
tomwalters@0 1107
tomwalters@0 1108 ------------------------------------------------------------------------------- */
tomwalters@0 1109 void readnopts(options, numOptions, filePointer)
tomwalters@0 1110 Option options[] ;
tomwalters@0 1111 int numOptions;
tomwalters@0 1112 FILE *filePointer ;
tomwalters@0 1113 {
tomwalters@0 1114 long filePosition ;
tomwalters@0 1115 char first[200] ;
tomwalters@0 1116 int headerLength ;
tomwalters@0 1117
tomwalters@0 1118 filePosition = ftell(filePointer); /* Save the Original Position */
tomwalters@0 1119
tomwalters@0 1120 /* Read the first line of the first block, or as much of it as possible */
tomwalters@0 1121
tomwalters@0 1122 if ((!fread(first, 1, strlen(OptionHeaderHeader) + OPTION_HEADER_DIGITS
tomwalters@0 1123 + strlen(LineFeedArray), filePointer)) ||
tomwalters@0 1124 (strncmp(first, OptionHeaderHeader, strlen(OptionHeaderHeader)) != 0)) {
tomwalters@0 1125 /* Assume that this is NOT a option header */
tomwalters@0 1126 if (fseek(filePointer, filePosition, 0)) {
tomwalters@0 1127 (void) fprintf(stderr, "options: Error fseeking Option Header File\n");
tomwalters@0 1128 exit(1);
tomwalters@0 1129 }
tomwalters@0 1130 return;
tomwalters@0 1131 }
tomwalters@0 1132
tomwalters@0 1133 /* Extract the Header Length in Bytes */
tomwalters@0 1134
tomwalters@0 1135 headerLength = atoi(first + strlen(OptionHeaderHeader));
tomwalters@0 1136
tomwalters@0 1137 /* Now, process the stuff. Need to "seek" past the first line before
tomwalters@0 1138 attempting to read anything, and shorten the headerLength accordingly */
tomwalters@0 1139
tomwalters@0 1140 (void) processOptionFile(options, numOptions, filePointer,
tomwalters@0 1141 "Unknown Option File",
tomwalters@0 1142 (headerLength - strlen(OptionHeaderHeader) -
tomwalters@0 1143 OPTION_HEADER_DIGITS - strlen(LineFeedArray)),
tomwalters@0 1144 FALSE, "???");
tomwalters@0 1145
tomwalters@0 1146 /* Make sure that the file pointer is set to the data area */
tomwalters@0 1147
tomwalters@0 1148 if (fseek(filePointer, filePosition + headerLength, 0)) {
tomwalters@0 1149 (void) fprintf(stderr, "options: Error fseeking Option Header File\n");
tomwalters@0 1150 exit(1);
tomwalters@0 1151 }
tomwalters@0 1152
tomwalters@0 1153 }
tomwalters@0 1154
tomwalters@0 1155
tomwalters@0 1156 /* -------------------------------------------------------------------------------
tomwalters@0 1157
tomwalters@0 1158 Count the number of bytes which will be written by writenopts, given the
tomwalters@0 1159 options array.
tomwalters@0 1160
tomwalters@0 1161 ------------------------------------------------------------------------------- */
tomwalters@0 1162 static int countBytesToWrite( options, numOptions )
tomwalters@0 1163 Option options[] ;
tomwalters@0 1164 int numOptions;
tomwalters@0 1165 {
tomwalters@0 1166 int sum, i;
tomwalters@0 1167
tomwalters@0 1168 sum = 0;
tomwalters@0 1169
tomwalters@0 1170 for (i = 0; i < numOptions; i++)
tomwalters@0 1171 if((options[i].classification == OutputOption ||
tomwalters@0 1172 options[i].classification == InOutOption) &&
tomwalters@0 1173 *(options[i].value) != NULL &&
tomwalters@0 1174 strcmp(*(options[i].value), NULL_STRING) != 0)
tomwalters@0 1175 sum += strlen(options[i].name) + strlen(EqualsArray) +
tomwalters@0 1176 strlen(*(options[i].value)) + strlen(LineFeedArray); /* + (2 * strlen(QuotesArray)); */
tomwalters@0 1177
tomwalters@0 1178 return (sum);
tomwalters@0 1179 }
tomwalters@0 1180
tomwalters@0 1181 /* -------------------------------------------------------------------------------
tomwalters@0 1182
tomwalters@0 1183 The descendent of the lost and lamented blockCopyStrToFile... writes a string
tomwalters@0 1184 to the indicated file.
tomwalters@0 1185
tomwalters@0 1186 ------------------------------------------------------------------------------- */
tomwalters@0 1187 static void WriteStringToFile(str, filePtr)
tomwalters@0 1188 char *str;
tomwalters@0 1189 FILE *filePtr;
tomwalters@0 1190 {
tomwalters@0 1191 if (!fwrite(str, 1, strlen(str), filePtr)) {
tomwalters@0 1192 (void) fprintf(stderr, "WriteStringToFile: Error printing %s to file.\n", str);
tomwalters@0 1193 exit(1);
tomwalters@0 1194 }
tomwalters@0 1195
tomwalters@0 1196 return;
tomwalters@0 1197 }
tomwalters@0 1198
tomwalters@0 1199
tomwalters@0 1200 /* -------------------------------------------------------------------------------
tomwalters@0 1201
tomwalters@0 1202 Write an option header to the specified file from the information contained
tomwalters@0 1203 in the given options array. Remove the comments to get debugging info.
tomwalters@0 1204
tomwalters@0 1205 ------------------------------------------------------------------------------- */
tomwalters@0 1206 void writenopts(options, numOptions, filePointer)
tomwalters@0 1207 Option options[] ;
tomwalters@0 1208 int numOptions;
tomwalters@0 1209 FILE *filePointer ;
tomwalters@0 1210 {
tomwalters@0 1211 /*int bytesWritten ;*/
tomwalters@0 1212 int i ;
tomwalters@0 1213 long filePosition ;
tomwalters@0 1214 int bytesToWrite ;
tomwalters@0 1215 int oddHeaderLength ;
tomwalters@0 1216 char DigitString[OPTION_HEADER_DIGITS + 2];
tomwalters@0 1217
tomwalters@0 1218 filePosition = ftell(filePointer);
tomwalters@0 1219
tomwalters@0 1220 bytesToWrite = countBytesToWrite(options, numOptions) +
tomwalters@0 1221 strlen(OptionHeaderHeader) + OPTION_HEADER_DIGITS +
tomwalters@0 1222 strlen(LineFeedArray) + 1;
tomwalters@0 1223
tomwalters@0 1224 if (oddHeaderLength = (bytesToWrite % 2))
tomwalters@0 1225 bytesToWrite++;
tomwalters@0 1226
tomwalters@0 1227 (void) WriteStringToFile(OptionHeaderHeader, filePointer);
tomwalters@0 1228
tomwalters@0 1229 (void) sprintf(DigitString, "%0*d", OPTION_HEADER_DIGITS, bytesToWrite);
tomwalters@0 1230
tomwalters@0 1231 /*(void) printf("bytesToWrite is %i.\n", bytesToWrite);*/
tomwalters@0 1232
tomwalters@0 1233 (void) WriteStringToFile(DigitString, filePointer);
tomwalters@0 1234
tomwalters@0 1235 (void) WriteStringToFile(LineFeedArray, filePointer);
tomwalters@0 1236
tomwalters@0 1237 /* Copy all of the Options */
tomwalters@0 1238
tomwalters@0 1239 for (i = 0; i < numOptions; i++) {
tomwalters@0 1240
tomwalters@0 1241 if((options[i].classification == OutputOption ||
tomwalters@0 1242 options[i].classification == InOutOption) &&
tomwalters@0 1243 *(options[i].value) != NULL &&
tomwalters@0 1244 strcmp(*(options[i].value), NULL_STRING) != 0) {
tomwalters@0 1245
tomwalters@0 1246 (void) WriteStringToFile(options[i].name, filePointer);
tomwalters@0 1247
tomwalters@0 1248 (void) WriteStringToFile(EqualsArray, filePointer);
tomwalters@0 1249
tomwalters@0 1250 /* (void) WriteStringToFile(QuotesArray, filePointer); */
tomwalters@0 1251
tomwalters@0 1252 (void) WriteStringToFile(*(options[i].value), filePointer);
tomwalters@0 1253
tomwalters@0 1254 /* (void) WriteStringToFile(QuotesArray, filePointer); */
tomwalters@0 1255
tomwalters@0 1256 (void) WriteStringToFile(LineFeedArray, filePointer);
tomwalters@0 1257 }
tomwalters@0 1258 }
tomwalters@0 1259
tomwalters@0 1260 if (fputc(NULL_CHARACTER, filePointer) == EOF) {
tomwalters@0 1261 (void) fprintf(stderr, "writenopts: Error doing fputc of the last NULL character.\n");
tomwalters@0 1262 exit(1);
tomwalters@0 1263 }
tomwalters@0 1264
tomwalters@0 1265 if (oddHeaderLength && fputc(NULL_CHARACTER, filePointer) == EOF) {
tomwalters@0 1266 (void) fprintf(stderr, "writenopts: Error doing fputc of the odd-pad NULL character.\n");
tomwalters@0 1267 exit(1);
tomwalters@0 1268 }
tomwalters@0 1269
tomwalters@0 1270 if (fflush(filePointer)) {
tomwalters@0 1271 (void) fprintf(stderr, "options: Error while flushing the option header\n");
tomwalters@0 1272 exit(1);
tomwalters@0 1273 }
tomwalters@0 1274
tomwalters@0 1275 /* seek the fileptr to after the last byte of the header */
tomwalters@0 1276
tomwalters@0 1277 if (filePointer != stdout) {
tomwalters@0 1278 if (fseek(filePointer, filePosition + (long)bytesToWrite, 0)) {
tomwalters@0 1279 (void) fprintf(stderr, "options: Error fseeking Option Header File\n");
tomwalters@0 1280 exit(1);
tomwalters@0 1281 }
tomwalters@0 1282 }
tomwalters@0 1283
tomwalters@0 1284 }
tomwalters@0 1285
tomwalters@0 1286
tomwalters@0 1287 /* ----------------------------------------------------------------------------
tomwalters@0 1288
tomwalters@0 1289 A Little Routine to Count the Options in a Options Array .... This MUST
tomwalters@0 1290 Be NULL-Terminated ...... OR ELSE!
tomwalters@0 1291
tomwalters@0 1292 ---------------------------------------------------------------------------- */
tomwalters@0 1293
tomwalters@0 1294 static int countOptions(options)
tomwalters@0 1295 Option options[];
tomwalters@0 1296 {
tomwalters@0 1297 int numoptions;
tomwalters@0 1298
tomwalters@0 1299 for (numoptions = 0;
tomwalters@0 1300 options[numoptions].name != NULL; /* DEATH TO ALL WHO TREAD HERE! */
tomwalters@0 1301 numoptions++);
tomwalters@0 1302
tomwalters@0 1303 return (numoptions);
tomwalters@0 1304
tomwalters@0 1305 }
tomwalters@0 1306
tomwalters@0 1307
tomwalters@0 1308 /* -------------------------------------------------------------------------------
tomwalters@0 1309
tomwalters@0 1310 The Counting version of getnopts -- you MUST null-terminate the options array.
tomwalters@0 1311
tomwalters@0 1312 ------------------------------------------------------------------------------- */
tomwalters@0 1313
tomwalters@0 1314 void getopts (options, argc, argv)
tomwalters@0 1315 Option options[] ;
tomwalters@0 1316 int *argc ;
tomwalters@0 1317 char ***argv ;
tomwalters@0 1318 {
tomwalters@0 1319 (void) getnopts(options, countOptions(options), argc, argv);
tomwalters@0 1320 }
tomwalters@0 1321
tomwalters@0 1322
tomwalters@0 1323 void cmd_line_opts(options, argc, argv)
tomwalters@0 1324 Option options[] ;
tomwalters@0 1325 int *argc ;
tomwalters@0 1326 char ***argv ;
tomwalters@0 1327 {
tomwalters@0 1328 (void) cmd_line_nopts( options, countOptions(options), argc, argv ) ;
tomwalters@0 1329 }
tomwalters@0 1330
tomwalters@0 1331
tomwalters@0 1332
tomwalters@0 1333 /* -------------------------------------------------------------------------------
tomwalters@0 1334
tomwalters@0 1335 The Counting version of readnopts -- you MUST null-terminate the options array.
tomwalters@0 1336
tomwalters@0 1337 ------------------------------------------------------------------------------- */
tomwalters@0 1338 void readopts(options, filePointer)
tomwalters@0 1339 Option options[] ;
tomwalters@0 1340 FILE *filePointer ;
tomwalters@0 1341 {
tomwalters@0 1342 (void) readnopts(options, countOptions(options), filePointer);
tomwalters@0 1343 }
tomwalters@0 1344
tomwalters@0 1345 /* -------------------------------------------------------------------------------
tomwalters@0 1346
tomwalters@0 1347 The Counting version of writenopts -- you MUST null-terminate the options array.
tomwalters@0 1348
tomwalters@0 1349 ------------------------------------------------------------------------------- */
tomwalters@0 1350 void writeopts(options, filePointer)
tomwalters@0 1351 Option options[] ;
tomwalters@0 1352 FILE *filePointer ;
tomwalters@0 1353 {
tomwalters@0 1354 (void) writenopts(options, countOptions(options), filePointer);
tomwalters@0 1355 }
tomwalters@0 1356
tomwalters@0 1357
tomwalters@0 1358 /* -------------------------------------------------------------------------------
tomwalters@0 1359
tomwalters@0 1360 Packaging for convenience -- Guaranteed to be Listeria-free!
tomwalters@0 1361
tomwalters@0 1362 ------------------------------------------------------------------------------- */
tomwalters@0 1363
tomwalters@0 1364 FILE *fileopts( res, argc, argv )
tomwalters@0 1365 Option *res ;
tomwalters@0 1366 int *argc ;
tomwalters@0 1367 char **argv[];
tomwalters@0 1368 {
tomwalters@0 1369 FILE *ifp ;
tomwalters@0 1370 int numOptions;
tomwalters@0 1371 #if defined( PC )
tomwalters@0 1372 char *progName ;
tomwalters@0 1373
tomwalters@0 1374 progName = (*argv)[0];
tomwalters@0 1375 #endif
tomwalters@0 1376
tomwalters@0 1377 numOptions = countOptions(res);
tomwalters@0 1378
tomwalters@0 1379 getnopts( res, numOptions, argc, argv ) ;
tomwalters@0 1380
tomwalters@0 1381 if( *argc > 0 ) {
tomwalters@0 1382 if((ifp = fopen( **argv, "r" )) == NULL) {
tomwalters@0 1383 (void) fprintf(stderr, "Unable to open the file %s.\n", **argv);
tomwalters@0 1384 exit(1);
tomwalters@0 1385 }
tomwalters@0 1386 }
tomwalters@0 1387 else
tomwalters@0 1388 #if defined( PC )
tomwalters@0 1389 {
tomwalters@0 1390 /* PCs cannot take binmode files through standard input */
tomwalters@0 1391 (void) (*onLineHelpHandler)( res, numOptions, progName );
tomwalters@0 1392 exit(1);
tomwalters@0 1393 }
tomwalters@0 1394 #else
tomwalters@0 1395 ifp = stdin ;
tomwalters@0 1396 #endif
tomwalters@0 1397
tomwalters@0 1398 (*argv)++ ;
tomwalters@0 1399 (*argc)-- ;
tomwalters@0 1400
tomwalters@0 1401 readopts( res, ifp ) ;
tomwalters@0 1402
tomwalters@0 1403 return( ifp ) ;
tomwalters@0 1404
tomwalters@0 1405 }
tomwalters@0 1406
tomwalters@0 1407
tomwalters@0 1408 /* -------------------------------------------------------------------------------
tomwalters@0 1409
tomwalters@0 1410 Packaging for convenience -- Guaranteed to be Listeria-free!
tomwalters@0 1411
tomwalters@0 1412 ------------------------------------------------------------------------------- */
tomwalters@0 1413 FILE *optoutput(str)
tomwalters@0 1414 char *str;
tomwalters@0 1415 {
tomwalters@0 1416 FILE *f;
tomwalters@0 1417
tomwalters@0 1418 if (str == NULL)
tomwalters@0 1419 return (NULL);
tomwalters@0 1420 else if (str == DEFAULT_TOGGLE_VALUE)
tomwalters@0 1421 return (stdout);
tomwalters@0 1422
tomwalters@0 1423 if ((f = fopen(str, "w")) == NULL) {
tomwalters@0 1424 (void) fprintf(stderr, "options: Could not open the file %s for output.\n", str);
tomwalters@0 1425 exit(1);
tomwalters@0 1426 }
tomwalters@0 1427 return (f);
tomwalters@0 1428 }
tomwalters@0 1429
tomwalters@0 1430
tomwalters@0 1431 /* -------------------------------------------------------------------------------
tomwalters@0 1432
tomwalters@0 1433 OnLine Help from the user program.
tomwalters@0 1434
tomwalters@0 1435 ------------------------------------------------------------------------------- */
tomwalters@0 1436 void helpnopts(res, numRes, name)
tomwalters@0 1437 Option res[];
tomwalters@0 1438 int numRes;
tomwalters@0 1439 char *name ;
tomwalters@0 1440 {
tomwalters@0 1441 (void) (*onLineHelpHandler)(res, numRes, name);
tomwalters@0 1442 }
tomwalters@0 1443
tomwalters@0 1444 /* -------------------------------------------------------------------------------
tomwalters@0 1445
tomwalters@0 1446 OnLine Help from the user program. (counting version)
tomwalters@0 1447
tomwalters@0 1448 ------------------------------------------------------------------------------- */
tomwalters@0 1449 void helpopts(res, name)
tomwalters@0 1450 Option res[];
tomwalters@0 1451 char *name ;
tomwalters@0 1452 {
tomwalters@0 1453 #ifdef PC
tomwalters@0 1454 if (strncmp(name+strlen(name)-strlen("gen.exe"), "gen", strlen("gen")) == 0)
tomwalters@0 1455 #else
tomwalters@0 1456 if (strcmp(name, "gen") == 0)
tomwalters@0 1457 #endif
tomwalters@0 1458 /* Special case of gen */
tomwalters@0 1459 usageHelp();
tomwalters@0 1460 else
tomwalters@0 1461 /* Case of gen??? */
tomwalters@0 1462 (void) (*onLineHelpHandler)(res, countOptions(res), name);
tomwalters@0 1463 }
tomwalters@0 1464
tomwalters@0 1465
tomwalters@0 1466 /* ---------------------------------------------------------------------------------
tomwalters@0 1467
tomwalters@0 1468 Allows an application program to install its very own helpHandler routine to
tomwalters@0 1469 override the default help-message handler. The behaviour of such a routine is
tomwalters@0 1470 implicitly trusted by <options>, so you should only install your own handler
tomwalters@0 1471 when you are quite familiar with the Options structure format. This routine
tomwalters@0 1472 returns the address of the previously installed handler (which is initially the
tomwalters@0 1473 default handler) so that this may be reinstated at a later point.
tomwalters@0 1474
tomwalters@0 1475 ---------------------------------------------------------------------------------- */
tomwalters@0 1476
tomwalters@0 1477 helpRoutine *helpOptsHandler(aHelpRoutine)
tomwalters@0 1478 helpRoutine *aHelpRoutine;
tomwalters@0 1479 {
tomwalters@0 1480 helpRoutine *temp;
tomwalters@0 1481
tomwalters@0 1482 temp = onLineHelpHandler;
tomwalters@0 1483
tomwalters@0 1484 onLineHelpHandler = aHelpRoutine;
tomwalters@0 1485
tomwalters@0 1486 return (temp);
tomwalters@0 1487 }
tomwalters@0 1488
tomwalters@0 1489
tomwalters@0 1490 /* ---------------------------------------------------------------------------------
tomwalters@0 1491
tomwalters@0 1492 A convenience call which returns TRUE (1) if the optionStr is what options thinks
tomwalters@0 1493 of as "ON", "YES", "TRUE", or "1".... This merely allows us to hide the actual
tomwalters@0 1494 implementation of "ON" from the application programs.
tomwalters@0 1495
tomwalters@0 1496 --------------------------------------------------------------------------------- */
tomwalters@0 1497
tomwalters@0 1498 int isOFF(optionStr)
tomwalters@0 1499 char *optionStr;
tomwalters@0 1500 {
tomwalters@0 1501 return (strcmp(OFF_STRING, optionStr) == 0 ||
tomwalters@0 1502 strcmp(OFF_ALIAS , optionStr) == 0 ||
tomwalters@0 1503 strcmp(NOT_USED , optionStr) == 0);
tomwalters@0 1504 }
tomwalters@0 1505
tomwalters@0 1506
tomwalters@0 1507 /* ---------------------------------------------------------------------------------
tomwalters@0 1508
tomwalters@0 1509 A convenience call which returns TRUE (1) if the optionStr is what options thinks
tomwalters@0 1510 of as "NULL", "NONE", nothing, zip, etc... This merely allows us to hide the actual
tomwalters@0 1511 implementation of "NULL" from the application programs.
tomwalters@0 1512
tomwalters@0 1513 --------------------------------------------------------------------------------- */
tomwalters@0 1514
tomwalters@0 1515 int isNULL(optionStr)
tomwalters@0 1516 char *optionStr;
tomwalters@0 1517 {
tomwalters@0 1518 return (optionStr == NULL ||
tomwalters@0 1519 strcmp(NULL_STRING, optionStr) == 0 ||
tomwalters@0 1520 strcmp(NULL_ALIAS , optionStr) == 0);
tomwalters@0 1521 }
tomwalters@0 1522
tomwalters@0 1523
tomwalters@0 1524 /* ---------------------------------------------------------------------------------
tomwalters@0 1525
tomwalters@0 1526 A routine to reduce the load on the application programmer by providing a simple
tomwalters@0 1527 boolean check for string equality WITHOUT CASE SIGNIFICANCE. This allows applications
tomwalters@0 1528 to leave case and typing problems within "options" reliably.
tomwalters@0 1529
tomwalters@0 1530 --------------------------------------------------------------------------------- */
tomwalters@0 1531
tomwalters@0 1532 static char *stringToLowerCase(str)
tomwalters@0 1533 char *str;
tomwalters@0 1534 {
tomwalters@0 1535 register int i;
tomwalters@0 1536
tomwalters@0 1537 if (str == NULL)
tomwalters@0 1538 return (str);
tomwalters@0 1539 else {
tomwalters@0 1540 for (i = 0; str[i] != NULL_CHARACTER; i++)
tomwalters@0 1541 if (isupper((char) str[i]))
tomwalters@0 1542 str[i] = (char) tolower((char) str[i]);
tomwalters@0 1543 return (str);
tomwalters@0 1544 }
tomwalters@0 1545 }
tomwalters@0 1546
tomwalters@0 1547 extern int OptionStringsEqual(str1, str2)
tomwalters@0 1548 char *str1, *str2;
tomwalters@0 1549 {
tomwalters@0 1550 /* This routine copies the strings into two local buffers, converts them to
tomwalters@0 1551 lower case, and then compares them for equality. This local copy ensures
tomwalters@0 1552 that they are automatically deallocated on function return */
tomwalters@0 1553
tomwalters@0 1554 #define MAX_COPY_LENGTH (256)
tomwalters@0 1555
tomwalters@0 1556 char lc1[MAX_COPY_LENGTH], lc2[MAX_COPY_LENGTH];
tomwalters@0 1557
tomwalters@0 1558 if (strlen(str1) < MAX_COPY_LENGTH &&
tomwalters@0 1559 strlen(str2) < MAX_COPY_LENGTH)
tomwalters@0 1560 return (strcmp(stringToLowerCase(strcpy(lc1, str1)),
tomwalters@0 1561 stringToLowerCase(strcpy(lc2, str2))) == 0);
tomwalters@0 1562 else {
tomwalters@0 1563 (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 1564 exit(1);
tomwalters@0 1565 }
tomwalters@0 1566 }
tomwalters@0 1567
tomwalters@0 1568
tomwalters@0 1569
tomwalters@0 1570 /* Print general usage information in response to: gen -help */
tomwalters@0 1571 usageHelp()
tomwalters@0 1572 {
tomwalters@0 1573 (void)fprintf(stdout,"%s\n\n", versionstr);
tomwalters@0 1574
tomwalters@0 1575 (void) fprintf(stdout, "Usage: genXXX [options] [file_name]\n");
tomwalters@0 1576 (void) fprintf(stdout, " where XXX is one of the following abbreviations:\n\n\
tomwalters@0 1577 wav waveform \n\
tomwalters@0 1578 bmm basilar membrane motion \n\
tomwalters@0 1579 nap neural activity pattern \n\
tomwalters@0 1580 sai stabilized auditory image \n\
tomwalters@0 1581 spl spiral version of auditory image \n\
tomwalters@0 1582 sgm spectrogram \n\
tomwalters@0 1583 cgm cochleogram " ) ;
tomwalters@0 1584 (void) fprintf(stdout, "\n\
tomwalters@0 1585 asa auditory spectral analysis \n\
tomwalters@0 1586 epn excitation pattern \n\n");
tomwalters@0 1587
tomwalters@0 1588 (void) fprintf(stdout, " [file_name] is a headerless wave file (2-byte binary integers).\n");
tomwalters@0 1589 (void) fprintf(stdout, " [options] are parameters, options and swtiches that control\n");
tomwalters@0 1590 (void) fprintf(stdout, " the AIM instructions and the AIM tools.\n\n");
tomwalters@0 1591
tomwalters@0 1592 (void) fprintf(stdout, " Help with options: genXXX [-help | -help=all | -help=option]\n");
tomwalters@0 1593 #if !defined( PC )
tomwalters@0 1594 (void) fprintf(stdout, " Path for options file, (.genXXXrc) = . (or setenv OPTIONSPATH)\n\n");
tomwalters@0 1595 #endif
tomwalters@0 1596
tomwalters@0 1597 (void) fprintf(stdout, "Processes Applied by AIM and Routes Through the Model: \n\n\
tomwalters@0 1598 Process Auditory Speech Spectra \n\
tomwalters@0 1599 -------------------------------- -------- ------ ------- \n\
tomwalters@0 1600 Display input wave genwav genwav genwav \n\
tomwalters@0 1601 Auditory filtering (gtf/tlf) genbmm \n\
tomwalters@0 1602 Compression and rectification gensgm genasa " ) ;
tomwalters@0 1603
tomwalters@0 1604 (void) fprintf(stdout, "\n\
tomwalters@0 1605 Neural encoding (2D-AT/haircell) gennap \n\
tomwalters@0 1606 Temporal integration (LP filter) gencgm genepn \n\
tomwalters@0 1607 Strobed temporal integration gensai \n\
tomwalters@0 1608 Spiral mapping of auditory image genspl \n\n");
tomwalters@0 1609
tomwalters@0 1610 (void) fprintf(stdout, "Output: genXXX output=on file_name \n");
tomwalters@0 1611 (void) fprintf(stdout, " output is written to file: file_name.XXX \n");
tomwalters@0 1612
tomwalters@0 1613 (void) fprintf(stdout, "\n\
tomwalters@0 1614 The format for 2-dimensional output format is by columns, with the \n\
tomwalters@0 1615 lowest channel first in each column (bmm, nap, sgm, cgm, asa, epn).\n\
tomwalters@0 1616 The format for auditory image output is by rows, for each image frame \n\
tomwalters@0 1617 in succession, with the row of the lowest channel first (sai, spl).\n\n");
tomwalters@0 1618
tomwalters@0 1619 (void) fprintf(stdout, "The Auditory Image Model was developed at the Applied Psychology Unit\n");
tomwalters@0 1620 (void) fprintf(stdout, "of the Medical Research Council, 15 Chaucer Road, Cambridge, U.K.\n\n");
tomwalters@0 1621
tomwalters@0 1622 (void) fprintf(stdout, "Copyright(c) Applied Psychology Unit, Medical Research Council, 1988-1995.\n");
tomwalters@0 1623
tomwalters@0 1624 }