home *** CD-ROM | disk | FTP | other *** search
- /* > c.argfuncs - (c) Paul Witheridge - Version 1.02 - 02 June 1993 */
-
- /*===================================================================*/
- /* */
- /* This file includes the following functions: */
- /* */
- /* arganal - analyse standard arguments */
- /* displaytext - display help text etc */
- /* */
- /*===================================================================*/
-
- #include "kernel.h" /* ARC specifics */
- #include "swis.h" /* SWI names */
-
- #include <ctype.h> /* Character handling */
- #include <stddef.h> /* Standard definitions */
- #include <stdlib.h> /* General utilities */
- #include <stdio.h> /* Input/output */
- #include <string.h> /* String handling */
-
- #include "Beep.h" /* Beep header */
- #include "Useful.h" /* Useful defs */
- #include "Argfuncs.h" /* For checking */
-
- /*===================================================================*/
- /* */
- /* analargs - analyse command line arguments */
- /* -------- */
- /* */
- /* This function analyses standard command line arguments which can */
- /* be any combination of the following three types: */
- /* */
- /* (1) positional arguments (cannot begin with '-') */
- /* (2) option switches (single character preceded by '-') */
- /* (3) option value (follows option switch, cannot begin with '-') */
- /* */
- /* The arguments provided by the caller comprise: */
- /* */
- /* - count of command line arguments */
- /* - array of ptrs to command line arguments */
- /* - max number of position arguments allowed */
- /* - array of ptrs to ptrs for storing address of pos. args */
- /* - string of allowable option characters (upper case and */
- /* terminated by null byte) */
- /* - pointer to flag byte */
- /* - array of flag masks (unsigned char) for setting flags in */
- /* flag byte corresponding to option characters */
- /* - array of ptrs to ptrs for storing address of option value */
- /* args */
- /* */
- /*===================================================================*/
-
- void analargs(
- const int argc, /* Number of arguments */
- const char *argv[], /* Array of pointers to args */
- const int posnc, /* Number of positional args */
- const char **(**posnptr)[], /* Ptr to positional arg ptrs */
- const char options[], /* Option characters */
- unsigned char *flags, /* Pointer to flag byte */
- const unsigned char optflags[], /* Option flag settings */
- const char **optval[]) /* Ptrs to value ptrs */
- {
- /*-----------------------------------------------------------------*/
- /* Local definitions. */
- /*-----------------------------------------------------------------*/
-
- int argi ; /* Argument index */
- int opti ; /* Option index */
- int posni ; /* Positional argument index */
- const char *p ; /* Working pointer */
-
- /*-----------------------------------------------------------------*/
- /* Executable statements */
- /* */
- /* Make one or two passes through arguments. */
- /* */
- /* One pass is enough if caller has supplied array of pointers */
- /* to positional parameter pointers. */
- /* */
- /* Two passes are required if caller did not supply an array but */
- /* wants us to build him one. First pass counts the number of */
- /* positional parameters while the second fills them in. */
- /* */
- /* Multiple positional operands allowed up to maximum number */
- /* specified by caller - recognised because they do not start */
- /* with '-' and are not preceded by an option character which */
- /* takes a value. */
- /* */
- /* Multiple option arguments allowed - recognised because they */
- /* do begin with '-' which must be followed by a single */
- /* character which must be one of the charcters in the "options" */
- /* array and specifies the option selected. */
- /* */
- /* Option can set a global flag - flag setting specified by the */
- /* corresponding entry in the "optflags" array. */
- /* */
- /* Option may be followed by a value if corresponding pointer */
- /* in "optvals" array is non-null. Pointer points to actual */
- /* pointer which must be set to point to the value. */
- /* */
- /*-----------------------------------------------------------------*/
-
- do
- {
- posni = 0 ;
- for ( argi = 1 ; argi < argc ; argi++ )
- {
- /*-------------------------------------------------------------*/
- /* If arg starts with "-" it must be option. */
- /* */
- /* Reject it if not immediately followed by one of valid */
- /* option characters. Otherwise set flag in caller's flag */
- /* byte corresponding to that option. Then check for any */
- /* value immediately following (without space). If so, */
- /* reject it if no value allowed for this option. Otherwise */
- /* store pointer to value for caller. If no immediately */
- /* value, and value is expected, check if value follows */
- /* after space (i.e., next argument). If so, and it does not */
- /* start with "-", store pointer to value for caller. */
- /*-------------------------------------------------------------*/
-
- if ( argv[argi][0] == '-' )
- {
- if ( (p = strchr(options,toupper(argv[argi][1]))) == NULL )
- {
- goto badopts ;
- }
- opti = p - options ;
- *flags |= optflags[opti] ;
- if ( optval[opti] == NULL )
- {
- if ( argv[argi][2] != '\0' )
- {
- goto badopts ;
- }
- }
- else
- {
- if ( argv[argi][2] == '\0' )
- {
- argi++ ;
- if ( argi < argc && argv[argi][0] != '-' )
- {
- *optval[opti] = argv[argi] ;
- }
- else
- {
- argi-- ;
- }
- }
- else
- {
- *optval[opti] = &argv[argi][2] ;
- }
- }
- }
-
- /*-------------------------------------------------------------*/
- /* If arg does not start with "-" it must be positional */
- /* */
- /* If no array provided by caller then on first pass just */
- /* count number of positional parameters. */
- /* */
- /* If array provided, or on on second pass using array we */
- /* have created, either fill-in caller's pointers to the */
- /* positional arguments, or set up the array of pointers */
- /* to point to the appropriate "argv" pointer. */
- /*-------------------------------------------------------------*/
-
- else
- {
- if ( posni < posnc )
- {
- if ( *posnptr != NULL )
- {
- if ( (**posnptr)[posni] == NULL )
- {
- (**posnptr)[posni] = &argv[argi] ;
- }
- else
- {
- *(**posnptr)[posni] = argv[argi] ;
- }
- }
- posni++ ;
- }
- else
- {
- p = "positional argument" ;
- goto badargs ;
- }
- }
- }
-
- /*---------------------------------------------------------------*/
- /* At end of first pass, if caller did not provide and array */
- /* of pointers, allocate storage for one ourselves. */
- /*---------------------------------------------------------------*/
-
- if ( *posnptr != NULL )
- {
- break ;
- }
- else
- {
- if ( ( *posnptr = calloc(posni + 1,sizeof(char **)) ) == NULL )
- {
- puts("Too many arguments - out of memory") ;
- beep() ;
- exit(8) ;
- }
- }
- } FOREVER ;
-
- /*-----------------------------------------------------------------*/
- /* All done. Return. */
- /*-----------------------------------------------------------------*/
-
- return ;
-
- /*-----------------------------------------------------------------*/
- /* If bad argument found sound beep and exit with code 8 */
- /*-----------------------------------------------------------------*/
-
- badopts:
-
- p = "option" ;
-
- badargs:
-
- printf("ERROR - invalid %s: %s\n\n",p,argv[argi]) ;
- beep() ;
- exit(8) ;
- }
-
- /*===================================================================*/
- /* */
- /* displaytext - display help/syntax text */
- /* ----------- */
- /* */
- /* This function displays text according to the current text */
- /* window width. It is passed pointers to a text string and an */
- /* array of tab settings. */
- /* */
- /* Control characters (codes less than 0x20) have the following */
- /* special effects: */
- /* */
- /* 0x00 = end of string */
- /* */
- /* 0x01-0x1e = indices into tab settings array */
- /* */
- /* 0x1f = new line required */
- /* */
- /* The array of tab settings is an array of unsigned characters. */
- /* The first character is the indent to be used at the start of */
- /* each line. Other characters are indexed by characters 0x01 to */
- /* 0x1e in the text. */
- /* */
- /*===================================================================*/
-
- void displaytext(
- const char *text, /* Ptr to help text */
- const unsigned char tabs[]) /* Ptr to array of tab values */
-
- {
- int c ; /* Working character */
- int i = 0 ; /* Offset into current line */
- int b ; /* Count of blanks */
- int t ; /* Current indent */
- int l ; /* Line length */
- const char *p ; /* Working pointer */
-
- static const int varkeys[] =
- {
- 132,
- 134,
- -1
- } ;
-
- int varvals[2] ;
-
- _kernel_swi_regs swiregs ;
-
- swiregs.r[0] = (int)varkeys ;
- swiregs.r[1] = (int)varvals ;
- _kernel_swi(OS_ReadVduVariables,&swiregs,&swiregs) ;
-
- l = varvals[1] - varvals[0] ;
-
- b = t = tabs[0] ;
-
- while ( (c = *text) != '\0' )
- {
- if ( c <= 0x20 )
- {
- switch ( c )
- {
- case 0x20 : /* Process blank */
-
- b++ ;
- break;
-
- case 0x1f : /* Process new line */
-
- putchar('\n') ;
- i = 0 ;
- t = b = tabs[0] ;
- break;
-
- default : /* Process tab */
-
- t = tabs[c] ;
- if ( t > i + b )
- {
- b = t - i ;
- }
- }
- text++ ;
- }
- else
- {
- for ( p = text ; *p > 0x20 ; p++ ) ;
- if ( i + b + p - text > l )
- {
- putchar('\n') ;
- i = 0 ;
- b = t ;
- }
- for ( ; b > 0 ; b--, i++ )
- {
- putchar(' ') ;
- }
- for ( ; text < p ; text++, i++ )
- {
- putchar(*text) ;
- }
- }
- }
- }
-
- /*====================================================================*/
-