Mercurial > hg > aim92
view tools/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 |
line wrap: on
line source
#include <stdio.h> #include <math.h> #include "options.h" #include "strmatch.h" #include "units.h" /* Defaults for i/o parameters. These are declared externally in options.h so they may be overridden by option assignment. */ int LINE_LENGTH = 256 ; /* max length of line for ascii data. */ int FIELDWIDTH = 0 ; /* field width for printf. */ /* (FIELDWIDTH=0 sets no extra fieldwidth. */ /* Positive integer fieldwidth sets right-justified */ /* columns, negative integer fieldwidth sets left- */ /* justified columns). */ int PRECISION = 3 ; /* precision (num decimal places) for printf, */ /* (PRECISION=0 sets integer output). */ /* Return a file pointer to a file `name' opened to read. If `name' is `-' then return stdin. If file `name' is not found return null pointer. */ FILE *fropen( name ) char *name ; { FILE *fopen() ; if ( isstr( name, "-" ) ) return stdin ; else return ( fopen( name, "r" ) ) ; } /* Generic options handler and file opener. Return a file pointer to an opened file, either stdin (if no args remained on command line after scanning) or the first name left on the command line. */ FILE *openopts( option, argc, argv ) Options *option ; int argc ; char *argv[] ; { FILE *fp ; int i ; if ( ( i = getopts( option, argc, argv ) ) == 0 ) return stdin ; if ( ( fp = fropen( argv[argc-i] ) ) == (FILE *)0 ) { fprintf(stderr, "%s: can't open %s\n", argv[0], argv[argc-i] ) ; exit( 1 ) ; } return ( fp ) ; } /* Options handler and two file opener. If one file is on command line after scanning options, then the first file fp1 is assumed to be the stdin. Otherwise two files are expected. Return 0 if incorrect number of files, otherwise return 1. (Note: fp1 and fp2 are pts to file ptrs, so pass them as &fp1, &fp2 if originally declared as file ptrs). */ open2opts( option, argc, argv, fp1, fp2 ) Options *option ; int argc ; char *argv[] ; FILE **fp1 ; FILE **fp2 ; { switch ( getopts( option, argc, argv ) ) { case 1 : *fp1 = stdin; if ( ( *fp2 = fropen( argv[argc-1] ) ) == (FILE *)0 ) { fprintf( stderr,"%s: can't open %s\n", argv[0], argv[argc-1] ) ; exit( 1 ) ; } break ; case 2 : if ( ( *fp1 = fropen( argv[argc-2] ) ) == (FILE *)0 ) { fprintf( stderr,"%s: can't open %s\n", argv[0], argv[argc-2] ) ; exit( 1 ) ; } if ( ( *fp2 = fropen( argv[argc-1] ) ) == (FILE *)0 ) { fprintf( stderr,"%s: can't open %s\n", argv[0], argv[argc-1] ) ; exit( 1 ) ; } break ; default : return ( 0 ) ; } return ( 1 ) ; } /* Build an options table. First assign all the option values with the defaults given in the table. Then scan the command line for arguments to overwrite corresponding vals. Argument syntax is one of the following three types (or combinations). Each syntax must contain either a leading '-' char or an embedded '=' char, to distinguish arguments from possible filenames. 1) -<name> FLAG_SYNTAX 2) -<name>[=]<value> ARG_SYNTAX 3) [-]<name>=<value> EQ_SYNTAX FLAG_SYNTAX takes no value. (The returned value is the empty string). ARG_SYNTAX takes a value after an optional '=' char. If the '=' char is not found, then the <value> is whatever follows the longest matching <name> string. Otherwise the <value> is whatever follows the '=' char. (The value is not allowed to be empty). EQ_SYNTAX takes a value which is whatever follows the '=' char. (The value is not allowed to be empty). It is assumed that all args remaining on the command line after an arg with invalid syntax must be filenames. These remain unscanned. Return argc, the number of args remaining unscanned on the command line, (argc=0 if no args left). To scan the remainder of the command line, and (eg) print the filenames:- if ( ( i = getopts( option, argc, argv, ) ) == 0 ) printf("stdin\n" ); else for ( ; i>0 ; i--) printf("[%s]\n", argv[argc-i] ); */ int getopts( option, argc, argv ) Options *option ; int argc ; char *argv[] ; { char *prog, *val ; int i, n, index[64], span[64] ; /* Assign option vals using the defaults */ for (i=0 ; option[i].name != (char *)0 ; i++) *(option[i].val) = option[i].dflt ; /* Overwrite option vals with corresponding vals found on command line */ prog = *argv ; while ( --argc > 0 && ++argv ) { /* find list of options all with longest matching name span */ /* returning if none, with argc args remaining */ if ( ( n = whichopt( option, *argv, index, span ) ) == 0 ) return ( argc ) ; /* check arg syntax, returning if invalid with argc args remaining */ for ( i=0 ; i<n && ( val = checksyntax( *argv, span[i], option[index[i]].type ) ) == (char *)0 ; i++ ) ; if ( val == (char *)0 ) return ( argc ) ; /* if whichopt was ambiguous, yet an arg is valid, then its an */ /* ambiguous option, (and not a possible filename). */ if ( n > 1 ) { fprintf(stderr,"%s: ambiguous option [%s]\n", prog, *argv ) ; exit ( 1 ) ; } /* do operation */ operate( option, *index, val ) ; side_effect( option, *index ) ; } return argc ; } /* Find the default value of the first option whose name unambiguously matches `s' (possibly abbreviated). Return a ptr to the default value of the matching option. Otherwise return the null ptr if a matching name is not found or is ambiguous. */ char *optdflt( option, s ) Options *option ; char *s ; { int i ; if ( ( i = optindex( option, s ) ) < 0 ) return ( (char *)0 ) ; return ( option[i].dflt ) ; } /* Find the option whose name unambiguously matches `s' (possibly abbreviated). Return the option list index of the matching option. Otherwise return -1 if a matching name is not found, or -2 if the name is ambiguous. */ int optindex( option, s ) Options *option ; char *s ; { int i, n, index[64], span[64] ; if ( ( n = whichopt( option, s, index, span ) ) == 0 ) return (-1) ; /* option not found */ if ( n > 1 ) return (-2) ; /* option name ambiguous */ return ( *index ) ; } /* Find the option whose name has the longest matching span with the head of `s' (the argument string, possibly abbreviated or with trailing value parts). Pass the option list index of the matching option back via arg `index'. Pass the length of the matching span back via arg `span'. Return the number of options found which have an equal longest matching span. (Any `-' at the head of `s' is skipped before matching). If there is an exact match (ie the longest matching span equals the length of the option name) then return an unambiguous match. */ int whichopt( option, s, index, span ) Options *option ; char *s ; int *index, *span ; { int i, j, n = 0, jmax = 0 ; if ( *s == '-' ) s++ ; /* Skip leading hyphen */ for ( i = 0 ; option[i].name != (char *)0 ; i++ ) { if ( ( j = streqspn( s, option[i].name ) ) > jmax ) { jmax = j ; /* a new longest matching span */ n = 0 ; index[n] = i ; span[n++] = j ; } else if ( j > 0 && j == jmax ) { /* ambiguous name with same matching span */ index[n] = i ; span[n++] = j ; } } for ( i = 0 ; i < n ; i++ ) /* check for an exact match */ if ( span[i] == strlen( option[index[i]].name ) ) { index[0] = index[i] ; span[0] = span[i] ; return 1 ; } return n ; } /* Check arg syntax and return a pointer to the value part, (or a pointer to the terminating null if the value part is empty). Return a NULL pointer if the syntax is invalid. It is assumed then that the current arg (and all remaining) is a filename. Print a warning if the syntax is an error rather than a possible filename, (the filename will not be found in this case). The check is arranged so that different option syntax types can be OR'd. */ char *checksyntax( s, span, type ) char *s ; int span, type ; { int i ; char *v, *val = (char *)0 ; if ( bitset( type, FLAG_SYNTAX ) ) { /* -<name> */ if ( *s == '-' && *(v = s+1 + span) == '\0' ) val = v ; } if ( bitset( type, ARG_SYNTAX ) ) { /* -<name>[=]<value> */ if ( *s == '-' ) { if ( *(v = s+1 + span) == '=' ) v++ ; if ( *v != '\0' ) val = v ; } } if ( bitset( type, EQ_SYNTAX ) ) { /* [-]<name>=<value> */ if ( *s == '-' ) s++ ; if ( *(v = s + span) == '=' && *++v != '\0' ) val = v ; } return ( val ) ; } /* Return 1 if string s a possible option, (ie. a string which is not a <number>, and contains either an embedded '=' or a leading '-'). Otherwise return 0. */ int isopt( s ) char *s ; { if ( isnumber( s ) ) return 0 ; if ( *s == '-' ) return 1 ; if ( strchr( s, '=' ) != (char *)0 ) return 1 ; return 0 ; } operate( option, i, val ) Options *option ; int i ; char *val ; { if ( bitset( option[i].type, LATCH ) ) /* LATCH */ *(option[i].val) = val ; else if ( bitset( option[i].type, AND ) ) /* AND */ *(option[i].val) = offstr ; else if ( bitset( option[i].type, OR ) ) /* OR */ *(option[i].val) = onstr ; else if ( bitset( option[i].type, TOGGLE ) ) { /* TOGGLE */ if ( isempty( val ) ) { if ( ison( *(option[i].val) ) ) *(option[i].val) = offstr ; else *(option[i].val) = onstr ; } else *(option[i].val) = val ; } } /* Side-effects of options type specifiers. */ side_effect( option, j ) Options *option ; int j ; { int i ; char *exstr ; if ( bitset( option[j].type, EXCLUDE ) ) { /* EXCLUDE */ if ( ison( *(option[j].val) ) ) exstr = offstr ; else exstr = onstr ; for ( i=0; option[i].name != (char *)0 ; i++) if ( i != j && bitset( option[i].type, EXCLUDE ) ) *(option[i].val) = exstr ; } } /* Separate an option value string `optval' into two string tokens at the first occurrence of a separator character `sep'. (Given as a string of one char). Return the tokens via the pointers `val1' and `val2' (which could be passed as the addresses of string pointers). Return BADVAL if the option value string is bad (meaning that either `optval' was null or empty, or the separator char was found but the 2nd token was missing). Return 1 if the option value string is good (meaning that either two tokens were found, or only the 1st token with no separator char, in which case `val2' will be a ptr to an empty string). (See routine strpsep()). */ int getvals( optval, val1, val2, sep ) char *optval ; char **val1, **val2 ; char *sep ; { *val1 = optval ; if ( isnull( *val2 = strsep( optval, sep ) ) ) return BADVAL ; return 1 ; } /* Parse a range selector of the form: a[-b] Return 0 if bad selectors, otherwise return 1. Items are numbered 1,2,...,max, (where max is 0 by convention). When either limit is "min", then set the respective value to 1. When either limit is "max", then set the respective value to 0. When `b' is missing, then set b=a. If (a==0) then seek eof and process the final item. Else seek past (a-1) items, and then process the next (b-a+1) items (or all items until eof if (b==0)). Eg: seekstart( a-1, bytes, fp ) ; for ( i = 0 ; ( b == 0 || i < b-a+1 ) ; i++ ) do process */ int selector( s, a, b ) char *s ; int *a, *b ; { char *val1, *val2 ; if ( getvals( s, &val1, &val2, "-" ) == BADVAL ) return ( 0 ) ; if ( ismin( val1 ) ) *a = 1 ; /* first object */ else if ( ismax( val1 ) ) *a = 0 ; /* last object */ else if ( ( *a = atoi( val1 ) ) <= 0 ) { /* intermediate object */ if ( *a == 0 ) fprintf( stderr,"warning: selected items are numbered 1,...,max\n" ) ; return ( 0 ) ; } if ( isempty( val2 ) ) *b = *a ; /* single object */ else if ( ismin( val2 ) ) *b = 1 ; else if ( ismax( val2 ) ) *b = 0 ; else if ( ( *b = atoi( val2 ) ) <= 0 ) { return ( 0 ) ; } if ( *b > 0 && ( *a == 0 || *a > *b ) ) return ( 0 ) ; return ( 1 ) ; } /* Parse a time range selector of the form: a[-b] The range is returned as limits meaning: start==a duration==b-a+1. (Note: when range=max or range=max-max then a==b==(-1) and duration==1). Return 0 if bad selectors, otherwise return 1. Time is numbered 0,2,...,max, (where max is (-1) by convention). When either limit is "min", then set the respective value to 0. When either limit is "max", then set the respective value to (-1). When `b' is missing, then set b=a. Time is specified as <number>[<units>], where <units> = {p, ms, s}. Empty units are interpreted as `p' (ie sample points). Convert `a' and `b' to sample points using the given samplerate. (Note: this is like selector() but using to_p() instead of atoi(), and numbering from 0 instead of 1). If (a<0) then seek eof and process the final item. Else seek past (a) items, and then process the next (b-a+1) items (or all items until eof if (b==-1)). Eg: seekstart( a, bytes, fp ) ; for ( i = 0 ; ( b < 0 || i < b-a+1 ) ; i++ ) do process */ int range( s, a, b, samplerate ) char *s ; int *a, *b ; int samplerate ; { char *val1, *val2 ; if ( getvals( s, &val1, &val2, "-" ) == BADVAL ) return ( 0 ) ; if ( ismin( val1 ) ) *a = 0 ; /* first object */ else if ( ismax( val1 ) ) *a = (-1) ; /* last object */ else if ( ( *a = to_p( val1, samplerate ) ) < 0 ) { return ( 0 ) ; } if ( isempty( val2 ) ) *b = *a ; /* single object */ else if ( ismin( val2 ) ) *b = 0 ; else if ( ismax( val2 ) ) *b = (-1) ; else if ( ( *b = to_p( val2, samplerate ) ) < 0 ) { return ( 0 ) ; } if ( *b >= 0 && ( *a < 0 || *a > *b ) ) return ( 0 ) ; return ( 1 ) ; } /* Seek n items of size bytes from current position in stream. (Unlike fseek, this works even when fp is stdin). Return the number of items actually read. Example: seekstart( n, sizeof(short), fp ); Datatype "ASCII" is a special case for which 0 is returned by the databytes routine, so bytes==0 is taken to mean seek n ascii lines. In general use: seekstart( n, databytes( typestr ), fp ) */ seekstart( n, bytes, fp ) int n, bytes ; FILE *fp ; { int i ; char *buf ; char *line ; if ( bytes == 0 ) { /* special case meaning ascii lines */ line = (char *)malloc( LINE_LENGTH ) ; for ( i = 0 ; i < n && fgets( line, LINE_LENGTH, fp ) != (char *)0 ; i++ ) ; free( line ) ; return ( i ) ; } if ( fp != stdin ) { if ( fseek( fp, (long)( n * bytes ), 1 ) == 0 ) return n ; /* if improper, look for any input */ } if ( ( buf = (char *)malloc( bytes ) ) == (char *)0 ) { fprintf( stderr, "seekstart: cannot allocate %d bytes\n", bytes ) ; exit( 1 ) ; } for ( i = 0 ; i < n && fread( buf, bytes, 1, fp ) ; i++ ) ; free( buf ) ; return ( i ) ; } /* Seek n items of of given type from current position in stream. This seekstart version takes a `type' arg instead of a size in `bytes'. The `type' is an index to the datatype list in options.h, obtained for example using: typeindex( typestr ). */ seektype( n, type, fp ) int n, type ; FILE *fp ; { return ( seekstart( n, typebytes( type ), fp ) ) ; } /* Read the next n items of `type' from the given stream. The `type' is an index to the datatype list in options.h, obtained for example using: typeindex( typestr ). Assign the item as a float in address `y', and return 1. Return 0 if eof or error. This can replace fread, eg: fread( &p, sizeof(short), 1, fp ) ( with short p ) becomes: readitem( &y, typeindex( "short" ), 1, fp ) ( with float y ) */ readitem( y, type, n, fp ) float *y ; int type ; int n ; FILE *fp ; { char c ; short s ; int i ; float f ; double d ; int j ; static char *line ; static int first = 1 ; switch ( type ) { case 0 : for ( j = 0 ; j < n ; j++ ) { if ( fread( &c, sizeof(char), 1, fp ) == 0 ) return 0 ; *y++ = (float)c ; } break ; case 1 : for ( j = 0 ; j < n ; j++ ) { if ( fread( &s, sizeof(short), 1, fp ) == 0 ) return 0 ; *y++ = (float)s ; } break ; case 2 : for ( j = 0 ; j < n ; j++ ) { if ( fread( &i, sizeof(int), 1, fp ) == 0 ) return 0 ; *y++ = (float)i ; } break ; case 3 : for ( j = 0 ; j < n ; j++ ) { if ( fread( &f, sizeof(float), 1, fp ) == 0 ) return 0 ; *y++ = (float)f ; } break ; case 4 : for ( j = 0 ; j < n ; j++ ) { if ( fread( &d, sizeof(double), 1, fp ) == 0 ) return 0 ; *y++ = (float)d ; } break ; case 5 : case 6 : if ( first ) { line = (char *)malloc( LINE_LENGTH ) ; first = 0 ; } for ( j = 0 ; j < n ; j++ ) { if ( fgets( line, LINE_LENGTH, fp ) == (char *)0 ) return 0 ; *y++ = atof( line ) ; } break ; } return 1 ; } /* Write the given n items of `type' onto the given stream. The `type' is an index to the datatype list in options.h, (obtained for example using: typeindex( typestr ) ). */ writeitem( y, type, n, fp ) float *y ; int type ; int n ; FILE *fp ; { char c ; short s ; int i ; float f ; double d ; int j ; switch ( type ) { case 0 : for ( j = 0 ; j < n ; j++ ) { c = (char) *y++ ; fwrite( &c, sizeof(char), 1, fp ) ; } break ; case 1 : for ( j = 0 ; j < n ; j++ ) { s = (short) *y++ ; fwrite( &s, sizeof(short), 1, fp ) ; } break ; case 2 : for ( j = 0 ; j < n ; j++ ) { i = (int) *y++ ; fwrite( &i, sizeof(int), 1, fp ) ; } break ; case 3 : for ( j = 0 ; j < n ; j++ ) { f = (float) *y++ ; fwrite( &f, sizeof(float), 1, fp ) ; } break ; case 4 : for ( j = 0 ; j < n ; j++ ) { d = (double) *y++ ; fwrite( &d, sizeof(double), 1, fp ) ; } break ; case 5 : case 6 : for ( j = 0 ; j < n ; j++ ) fprintf( fp, "%*.*f\n", FIELDWIDTH, PRECISION, *y++ ) ; break ; } } /* Read the next n items of `type' from the given stream within inclusive range limits `a' and `b', (found using, eg: range( rangestr, &a, &b, samplerate ) ). This is a version of readitem which incorporates the intial seek and handles range=max correctly. The `type' is an index to the datatype list in options.h, obtained for example using: typeindex( typestr ). Assign the item as a float in address `y', and return the number of items read. Return 0 if eof or error. */ nextitem( y, type, n, fp, a, b ) float *y ; int type ; int n ; FILE *fp ; int a, b ; { static int count = 0 ; /* total items read over all calls */ int num ; /* number items read this call */ float x ; if ( count == 0 ) { if ( a == (-1) ) { /* range=max or range=max-max */ if ( n == 1 && readitem( &x, type, 1, fp ) ) { *y = x ; while ( readitem( &x, type, 1, fp ) ) *y = x ; num = 1 ; } else num = 0 ; } else { if ( seektype( a, type, fp ) < a ) num = 0 ; else { if ( b >= 0 && n > b-a+1 ) /* n restricted by upper limit */ n = b-a+1 ; for ( num = 0 ; num < n && readitem( &x, type, 1, fp ) ; num++ ) y[num] = x ; } } count += num ; } else { if ( b >= 0 && count >= b-a+1 ) num = 0 ; else { if ( b >= 0 && n > b-a+1 - count ) /* n restricted by upper limit */ n = b-a+1 - count ; for ( num = 0 ; num < n && readitem( &x, type, 1, fp ) ; num++ ) y[num] = x ; } count += num ; } return num ; } /* Return the type index (to the datatype list in options.h) of the given type string. String matching allows for abbreviations. If the given type string is in error then return an error code (less than 0): -1 type string not found in datatype list. -2 type string is ambiguous. */ int typeindex( typestr ) char *typestr ; { return ( listindex( datatype, typestr ) ) ; } /* Return a number of bytes for a given type index (to the datatype list in options.h). Datatype "ASCII" is a special case for which 0 is returned. */ int typebytes( type ) int type ; { int bytes ; switch ( type ) { case 0 : bytes = sizeof( char ) ; break ; case 1 : bytes = sizeof( short ) ; break ; case 2 : bytes = sizeof( int ) ; break ; case 3 : bytes = sizeof( float ) ; break ; case 4 : bytes = sizeof( double ) ; break ; case 5 : /* ASCII */ case 6 : bytes = 0 ; break ; /* ascii */ } return ( bytes ) ; } /* Return a number of bytes for a given type string. The string can be a number (of bytes), or a token from the `datatype' list, (see options.h) with which it is matched, allowing for abbreviations. Datatype "ASCII" or "ascii" is a special case for which 0 is returned. If the given type string is in error then return an error code (less than 0): -1 type string not found in datatype list. -2 type string is ambiguous. -3 type string is a negative number. */ int databytes( typestr ) char *typestr ; { int type, bytes ; if ( isnumber( typestr ) ) { /* case of bytes number string */ if ( ( bytes = atoi( typestr ) ) < 0 ) return ( -3 ) ; else return bytes ; } if ( ( type = typeindex( typestr ) ) < 0 ) return type ; return ( typebytes( type ) ) ; } /* Check for over or underflow when the given float is scaled and cast into the given data type (an index to the datatype list in options.h). Return a more appropriate scale factor, or a scale factor of 1 if no over or underflow. The returned scale factor is the minimum scale factor over a succession of calls to check_overflow. */ float check_overflow( p, scale, type ) float p, scale ; int type ; { float f, p1 = p * scale ; static float first = 1 ; static float max, newscale ; if ( type >= 3 ) return ( 1. ) ; if ( first ) { switch ( type ) { case 0 : max = pow( 2., 8.*sizeof(char)-1 ) - 1 ; break ; case 1 : max = pow( 2., 8.*sizeof(short)-1 ) - 1 ; break ; case 2 : max = pow( 2., 8.*sizeof(int)-1 ) - 1 ; break ; } newscale = 1. ; first = 0 ; } if ( p1 > max ) f = max / p ; else if ( p1 < (-max) ) f = -( max / p ) ; else f = 1. ; if ( f < newscale ) newscale = f ; return ( newscale ) ; } /* Some particular string tests. */ /* Test for "on" or any <number> string other than "0". */ int ison( s ) char *s ; { return ( strcmp( "on", s ) == 0 || ( isnumber( s ) && strcmp( "0", s ) != 0 ) ) ; } /* Test for "off" or "0". */ int isoff( s ) char *s ; { return ( strcmp( "off", s ) == 0 || strcmp( "0", s ) == 0 ) ; } /* Test for "min". */ int ismin( s ) char *s ; { return ( strcmp( "min", s ) == 0 ) ; } /* Test for "max". */ int ismax( s ) char *s ; { return ( strcmp( "max", s ) == 0 ) ; } /*************************************************************************/ /* Print help for user help=on or -help gets standard help for all except SILENT options. help=all gets standard help for all options. help=syntax gets help with syntax instead of comment for all except SILENT. help=<name> gets help for the named option (which can be abbreviated). */ /* types of helpopts (see defines in options.h) helpopts standard usage, exit when done helpopts1 standard usage, supplied function for exit or additional help helpopts2 supplied usage and function for exit or additional help helpopts3 supplied usage, exit when done */ gethelp( helpstr, prog, applic, usage, option, tail ) char *helpstr ; char *prog ; char *applic ; char *usage ; Options *option ; int (*tail)() ; /* function for exit or additional help */ { int i, index[64], span[64] ; if ( isempty( helpstr ) || ison( helpstr ) || isstr( helpstr, "all" ) || isstr( helpstr, "syntax" ) ) help( prog, applic, usage, option, isstr( helpstr, "all" ), isstr( helpstr, "syntax" ) ) ; else { i = whichopt( option, helpstr, index, span ) ; if ( i == 0 ) fprintf(stderr,"%s: unknown option [%s]\n", prog, helpstr ) ; else if ( i > 1 ) fprintf(stderr,"%s: ambiguous option [%s]\n", prog, helpstr ) ; else helpshot( option[*index] ) ; /* single-line help i'th option */ } (*tail)() ; } help( prog, applic, usage, option, all, syntax ) char *prog, *applic, *usage ; Options *option ; int all, syntax ; { int i ; char *which_syntax(); if ( usage == (char *)0 ) /* a standard usage */ printf( "%s: %s\nUsage: %s [arguments] [file]\n", prog, applic, prog ); else printf( "%s: %s\nUsage: %s\n", prog, applic, usage ); if ( num_printed_opts( option, all ) > 0 ) { printf("name default comment\n"); printf("---------- ---------- --------.... \n"); } for (i=0 ; option[i].name != (char *)0 ; i++) { if ( !bitset( option[i].type, SILENT ) || all ) { if ( syntax ) syntaxline( option[i] ) ; else helpline( option[i] ) ; } } } helpline( option ) Options option ; { printf("%-10s ", option.name ); printf("%-10s ", option.dflt ); printf("%s\n" , option.help ); } syntaxline( option ) Options option ; { char *which_syntax(); printf("%-10s ", option.name ); printf("%-10s ", option.dflt ); printf("%s\n" , which_syntax( option.type ) ); } helpshot( option ) Options option ; { char *which_syntax(); printf("name: %s\n", option.name ); printf("default: %s\n", option.dflt ); printf("syntax: %s\n", which_syntax( option.type ) ); printf("comment: %s\n", option.help ); } /* Return the number of options which will get printed by help */ int num_printed_opts( option, all ) Options *option ; int all ; { int i, j=0 ; for (i=0 ; option[i].name != (char *)0 ; i++) if ( !bitset( option[i].type, SILENT ) ) j++ ; if ( all ) return ( i ) ; /* num all options */ else return ( j ) ; /* num non-SILENT options */ } char *which_syntax( type ) int type ; { if ( bitsset( type, ALL_SYNTAX ) ) return (char *)( All_Syntax ) ; if ( bitsset( type, VAL_SYNTAX ) ) return (char *)( Val_Syntax ) ; if ( bitsset( type, TOGGLE_SYNTAX ) ) return (char *)( Toggle_Syntax ) ; if ( bitsset( type, ONOFF_SYNTAX ) ) return (char *)( Onoff_Syntax ) ; if ( bitsset( type, EQ_SYNTAX ) ) return (char *)( Eq_Syntax ) ; if ( bitsset( type, ARG_SYNTAX ) ) return (char *)( Arg_Syntax ) ; if ( bitsset( type, FLAG_SYNTAX ) ) return (char *)( Flag_Syntax ) ; }