Brad Appleton <brad@hcx1.ssd.csd.harris.com> (05/18/91)
Submitted-by: Brad Appleton <brad@hcx1.ssd.csd.harris.com> Posting-number: Volume 19, Issue 84 Archive-name: parseargs/patch05c Patch-To: parseargs: Volume 17, Issue 45-57 #!/bin/sh # do not concatenate these parts, unpack them in order with /bin/sh # file PATCH05 continued # if test ! -r _shar_seq_.tmp; then echo 'Please unpack part 1 first!' exit 1 fi (read Scheck if test "$Scheck" != 3; then echo Please unpack part "$Scheck" next! exit 1 else exit 0 fi ) < _shar_seq_.tmp || exit 1 if test ! -f _shar_wnt_.tmp; then echo 'x - still skipping PATCH05' else echo 'x - continuing file PATCH05' sed 's/^X//' << 'SHAR_EOF' >> 'PATCH05' && - { "argv", "set %s=", "'", "';\n", "'\\%c'", "'" }, - - /* KSH : Positional parms in -- ; Assignment Syntax: name="value"; */ - { "--", "%s=", "'", "';\n", "'\\%c'", "'" }, - - /* SH : Positional parms in -- ; Assignment Syntax: name="value"; */ - { "--", "%s=", "'", "';\n", "'\\%c'", "'" }, - - /* RC : Positional parms in -- ; Assignment Syntax: name="value"; */ - { "*", "%s=", "'", "';\n", "''", "'" }, - - /* AWK : Positional parms in ARGV; Assignment Syntax: name\nvalue\n\n; */ - { "ARGV", "%s\n", "", "\n\n", "'\034'", "\n" }, X - /* PERL : Positional parms in ARGV; Assignment Syntax: $name=value\n; */ - { "ARGV", "$%s = ", "'", "';\n", "\\'", "'" } - }; X /*************************************************************************/ X X /* define all current arg-vector types */ --- 189,309 ---- X ** the Bourne shell ("sh") will be assumed. X ** X ** If the user wishes to use a value other than "TRUE" for a boolean ! ** flag that is true, this may be done using the -T string option. The ! ** same may also be done for a boolean flag that is false using the -F ! ** string option. X ** X ** Parseargs will only set the values of variables that correspond to ! ** arguments that were given on the command line. If a particular ! ** argument was not supplied on the command line, then no assignment is ! ** made for the corresponding shell variable and it will have the same ! ** value that it had before parseargs was invoked. The only exception to ! ** this is that if the -u option is specified, then the positional ! ** parameters are unset before any shell variable assignments (which may ! ** reset the positional parameters) are made. X ***^^*********************************************************************/ X ! /* type used to index into the shell-info array */ ! typedef unsigned shellidx_t; ! ! /* possible shell names and corresponding types */ ! typedef enum { ! SH, ! BASH, ! CSH, /* tcsh & itcsh are equivalent to csh for our purposes */ ! KSH, ! RC, ! ZSH, ! ASH, /* not yet supported */ ! CLAM, /* not yet supported */ ! AWK, ! PERL ! } shell_t; X X /* structure for shell-specific info */ X typedef struct { ! shell_t type; /* type of shell */ ! char *name; /* name of the shell */ ! ! char *unset; /* syntax used to unset positional parameters */ ! ! char *sclset; /* syntax used to set scalars (%s is the scalar name) */ ! char *sclpfx; /* prefix used for scalars */ ! char *sclsfx; /* suffix used for scalars */ ! ! char *aryset; /* syntax used to set arrays (%s is the array name) */ ! char *arypfx; /* prefix used for arrays */ ! char *arysep; /* separator used for arrays */ ! char *arysfx; /* suffix used for arrays */ ! X char *escape; /* format to escape chars (%c is the char to escape) */ X char *metachars; /* special characters that need to be escaped */ X } shell_info; X ! ! /* array of shell info records for supported shells */ X static CONST shell_info Shell[] = { + { + SH, "sh", + "shift $#;\n", + "%s=", "'", "';\n", + "%s=", "'", "'%s'", "';\n", + "'\\%c'", "'" + }, + { + BASH, "bash", + "shift $#;\n", + "%s=", "'", "';\n", + "%s=", "'", "'%s'", "';\n", + "'\\%c'", "'" + }, + { + KSH, "ksh", + "set --;\n", + "%s=", "'", "';\n", + "set %cA %s ", "'", "'%s'", "';\n", + "'\\%c'", "'" + }, + { + CSH, "csh", + "set argv=();\n", + "set %s=", "'", "';\n", + "set %s=", "( '", "'%s'", "' );\n", + "'\\%c'", "'" + }, + { + ZSH, "zsh", + "argv=();\n", + "%s=", "'", "';\n", + "%s=", "( '", "'%s'", "' );\n", + "'\\%c'", "'" + }, + { + RC, "rc", + "*=();\n", + "%s=", "'", "';\n", + "%s=", "( '", "'%s'", "' );\n", + "''", "'" + }, + { + PERL, "perl", + "@ARGV = ();\n", + "$%s = ", "'", "';\n", + "@%s = ", "( '", "', '", "' );\n", + "\\%c", "'" + }, + { + AWK, "awk", + "ARGV\n\n", + "%s\n", "", "\n\n", + "%s\n", "", "%s", "\n\n", + "''", "'" + } + }; X ! static size_t NumShells = ( sizeof(Shell) / sizeof(shell_info) ); X X X /*************************************************************************/ X X /* define all current arg-vector types */ *************** *** 319,325 **** X static ARGDESC *UsrArgd = ARGDESCNULL; /* users arg-table */ X static cmdarg_t *UsrVals = CMDARGNULL; /* variable names & values */ X static int UsrArgc = 0; /* # of arg-table entries */ ! static shell_t UsrSh; /* shell indicator */ X static BOOL UseStdin = TRUE; /* read argd from stdin */ X X static char *ShellName = CHARNULL; /* name of user's shell */ --- 374,380 ---- X static ARGDESC *UsrArgd = ARGDESCNULL; /* users arg-table */ X static cmdarg_t *UsrVals = CMDARGNULL; /* variable names & values */ X static int UsrArgc = 0; /* # of arg-table entries */ ! static shellidx_t UsrSh; /* shell indicator */ X static BOOL UseStdin = TRUE; /* read argd from stdin */ X X static char *ShellName = CHARNULL; /* name of user's shell */ *************** *** 928,938 **** X #endif X { X int isatty ARGS((int)); ! int fread ARGS((ARBPTR, size_t, size_t, FILE *)); X FILE *fp; X char *buf; ! register int nchars = 0; /* # bytes read */ ! register int bufsiz = 0; /* actual buffer-size needed */ X X /* open file if necessary */ X if ( UseStdin ) { --- 983,997 ---- X #endif X { X int isatty ARGS((int)); ! #ifdef __ANSI_C__ ! size_t fread( ARBPTR, size_t, size_t, FILE * ); ! #else ! int fread(); ! #endif X FILE *fp; X char *buf; ! register size_t nchars = 0; /* # bytes read */ ! register size_t bufsiz = 0; /* actual buffer-size needed */ X X /* open file if necessary */ X if ( UseStdin ) { *************** *** 967,977 **** X */ X do { X /* read fildes into the buffer */ ! nchars = fread( &(buf[bufsiz]), sizeof(char), BUFFER_SIZE, fp ); ! if ( nchars < 0 ) { X eprintf( "\ X %s: Fatal Error:\n\ ! \tBad status from read() while reading argument descriptor table\n", X Cmd_Name ); X free(buf); X cleanup(); --- 1026,1036 ---- X */ X do { X /* read fildes into the buffer */ ! nchars = (size_t) fread( &(buf[bufsiz]), sizeof(char), BUFFER_SIZE, fp ); ! if ( ferror(fp) ) { X eprintf( "\ X %s: Fatal Error:\n\ ! \tBad return from fread() while reading argument descriptor table\n", X Cmd_Name ); X free(buf); X cleanup(); *************** *** 997,1008 **** X X X /*************************************************************************** ! ** ^FUNCTION: get_shell_type - return shell corresponding to given string X ** X ** ^SYNOPSIS: X */ X #ifndef __ANSI_C__ ! static shell_t get_shell_type( sh_str ) X /* X ** ^PARAMETERS: X */ --- 1056,1067 ---- X X X /*************************************************************************** ! ** ^FUNCTION: get_shell_index - return shell corresponding to given string X ** X ** ^SYNOPSIS: X */ X #ifndef __ANSI_C__ ! static shell_t get_shell_index( sh_str ) X /* X ** ^PARAMETERS: X */ *************** *** 1012,1018 **** X #endif /* !__ANSI_C__ */ X X /* ^DESCRIPTION: ! ** Get_shell_type will retrun the shell-type for the named shell. If X ** No corresponding shell is known, then an error message is printed X ** and execution is terminated. X ** --- 1071,1077 ---- X #endif /* !__ANSI_C__ */ X X /* ^DESCRIPTION: ! ** Get_shell_index will return the shell-type for the named shell. If X ** No corresponding shell is known, then an error message is printed X ** and execution is terminated. X ** *************** *** 1029,1063 **** X ** Trivial. X ***^^**********************************************************************/ X #ifdef __ANSI_C__ ! static shell_t get_shell_type ( const char *sh_str ) X #endif X { ! if ( strEQ( sh_str, BOURNE_SHELL ) ) ! return SH; ! else if ( strEQ( sh_str, TC_SHELL ) ) ! return TCSH; ! else if ( strEQ( sh_str, C_SHELL ) ) ! return CSH; ! else if ( strEQ( sh_str, KORN_SHELL ) ) ! return KSH; ! else if ( strEQ( sh_str, BOURNE_AGAIN_SHELL ) ) ! return BASH; ! else if ( strEQ( sh_str, RC_SHELL ) ) ! return RC; ! else if ( strEQ( sh_str, AWK_LANG ) ) ! return AWK; ! else if ( strEQ( sh_str, PERL_LANG ) ) ! return PERL; ! ! else { ! eprintf( "%s: Fatal Error: unknown shell '%s'\n", ! Cmd_Name, sh_str ); ! eprintf( "\tKnown shells are: %s, %s, %s, %s, %s, %s, %s, and %s\n", ! AWK_LANG, BOURNE_AGAIN_SHELL, C_SHELL, KORN_SHELL, RC_SHELL, ! PERL_LANG, BOURNE_SHELL, TC_SHELL ); ! cleanup(); ! exit( e_SYNTAX ); ! } X } X X --- 1088,1120 ---- X ** Trivial. X ***^^**********************************************************************/ X #ifdef __ANSI_C__ ! static shellidx_t get_shell_index ( const char *sh_str ) X #endif X { ! int i; ! register char *sh = sh_str; ! ! /* special case to recognize tcsh & itcsh */ ! if ( strEQ( sh, "tcsh" ) ) ++sh; ! if ( strEQ( sh, "itcsh" ) ) sh += 2; ! ! for ( i = 0 ; i < NumShells ; i++ ) { ! if ( strEQ( sh, Shell[i].name ) ) return (shellidx_t) i; ! } ! ! usrerr( "Unknown shell \"%s\"", sh_str ); ! eprintf( "\tKnown shells are listed below:\n" ); ! for ( i = 0 ; i < NumShells ; i++ ) { ! if ( strEQ( "csh", Shell[i].name ) ) { ! eprintf( "\t\tcsh/tcsh/itcsh\n" ); ! } ! else { ! eprintf( "\t\t%s\n", Shell[i].name ); ! } ! } ! ! cleanup(); ! exit( e_SYNTAX ); X } X X *************** *** 1316,1324 **** X static void put_char_arg( FILE *fp, int ch ) X #endif X { ! /* newline needs to be escaped specially for CSH, TCSH, and PERL */ X if ( ch == '\n' ) { ! if ( UsrSh == CSH || UsrSh == TCSH ) { X fprintf( fp, "\\\n" ); X return; X } --- 1373,1381 ---- X static void put_char_arg( FILE *fp, int ch ) X #endif X { ! /* newline needs to be escaped specially for CSH */ X if ( ch == '\n' ) { ! if ( Shell[ UsrSh ].type == CSH ) { X fprintf( fp, "\\\n" ); X return; X } *************** *** 1516,1525 **** X #endif /* !__ANSI_C__ */ X X /* ^DESCRIPTION: ! ** Parseargs treats ARGLIST and ARGVEC arguments in a special way. The ! ** method used for setting up an argument list depends largely upon the ! ** syntax of shell that was specified on the command line via the -s option ! ** (although an ARGLIST argument is treated the same as an ARGVEC argument). X ** X ** ^Resetting_the_Positional_Parameters_to_an_Argument_List: X ** For the Bourne, Bourne-Again, and Korn shells, if the variable name --- 1573,1586 ---- X #endif /* !__ANSI_C__ */ X X /* ^DESCRIPTION: ! ** Parseargs treats ARGLIST arguments in a special way. The method used ! ** for setting up an argument list depends largely upon the syntax of ! ** shell that was specified on the command line via the -s option ! ** (although ARGLIST arguments are treated exactly the same as ARGVEC ! ** arguments). With the exception perl which always uses a comma to ! ** separate array elements, all shells will use the string specified ! ** with the -S option as the field separator between elements of an ! ** array (the default field separator is a space character). X ** X ** ^Resetting_the_Positional_Parameters_to_an_Argument_List: X ** For the Bourne, Bourne-Again, and Korn shells, if the variable name *************** *** 1532,1544 **** X ** parameters will be unset if the associated list of command line X ** arguments is not encountered). X ** ! ** Similarly for the C and TC shells, if the variable name corresponding ! ** to the ARGLIST argument is "argv", then the positional parameters ! ** of the calling program will be re-assigned to the contents of the ! ** argument list. X ** X ** For the Plan 9 shell (rc), if the variable name corresponding to the ! ** ARGLIST argument is "*", then the positional parameters of the calling X ** program will be re-assigned to the contents of the argument list. X ** X ** For awk and perl, if the variable name corresponding to the ARGLIST --- 1593,1605 ---- X ** parameters will be unset if the associated list of command line X ** arguments is not encountered). X ** ! ** Similarly for the C & Z shells (zsh, csh, tcsh, itcsh), if the ! ** variable name corresponding to the ARGLIST argument is "argv", then ! ** the positional parameters of the calling program will be re-assigned ! ** to the contents of the argument list. X ** X ** For the Plan 9 shell (rc), if the variable name corresponding to the ! ** ARGLIST argument is "*", then the positional parameters of then calling X ** program will be re-assigned to the contents of the argument list. X ** X ** For awk and perl, if the variable name corresponding to the ARGLIST *************** *** 1553,1562 **** X ** name='arg1 arg2 ...' X ** X ** After invoking parseargs, if you wish to go through all the words in ! ** the variable name and one of the words in name contains an IFS charac- ! ** ter (such as a space or a tab), then that particular word will be ! ** treated by the Bourne shell as two distinct words. ! ** X ** Also for the Bourne shell, If the associated variable name is NOT X ** "--" and the -A option WAS specified, then that variable is treated X ** as the root name of an array that is set using the following syntax: --- 1614,1622 ---- X ** name='arg1 arg2 ...' X ** X ** After invoking parseargs, if you wish to go through all the words in ! ** the variable name and one of the words in name contains an IFS ! ** character (such as a space or a tab), then that particular word will ! ** be treated by the Bourne shell as two distinct words. X ** Also for the Bourne shell, If the associated variable name is NOT X ** "--" and the -A option WAS specified, then that variable is treated X ** as the root name of an array that is set using the following syntax: *************** *** 1584,1590 **** X ** "--" and the -A option WAS specified, then that variable is assigned X ** using the +A option of the set command (which preserves any array X ** elements that were not overwritten by the set command). - ** X ** It should be noted that there is a bug in versions of the Korn shell X ** earlier than 11/16/88a, in which the following: X ** --- 1644,1649 ---- *************** *** 1598,1613 **** X ** X ** set -A save_parms "$@" X ** ! ** ^C_and_TC_Shell_Argument_Lists: ! ** For the C and TC shells, ARGLIST variables are treated as word-lists ! ** and are assigned using the following syntax: X ** X ** set name = ( 'arg1' 'arg2' ... ) X ** X ** The first item will be in $name[1], the second item will be in X ** $name[2], etc ..., and all items may be given by $name. Notice that ! ** Korn shell arrays start at index zero whereas C and TC shell word- ! ** lists start at index one. X ** X ** ^Bourne-Again_Shell_Argument_Lists: X ** At present, the Free Software Foundation's Bourne-Again shell is --- 1657,1672 ---- X ** X ** set -A save_parms "$@" X ** ! ** ^C_Shell_Argument_Lists: ! ** For the C shells (csh, tcsh, itcsh), ARGLIST variables are treated as ! ** word-lists and are assigned using the following syntax: X ** X ** set name = ( 'arg1' 'arg2' ... ) X ** X ** The first item will be in $name[1], the second item will be in X ** $name[2], etc ..., and all items may be given by $name. Notice that ! ** Korn shell arrays start at index zero whereas C shell word-lists start ! ** at index one. X ** X ** ^Bourne-Again_Shell_Argument_Lists: X ** At present, the Free Software Foundation's Bourne-Again shell is *************** *** 1615,1631 **** X ** bash supports arrays. X ** X ** ^Plan_9_Shell_Argument_Lists: ! ** For the Plan 9 shell, if the associated variable name is not "*" then ! ** it is considered to be a word-list and set using the following syntax: X ** X ** name=( 'arg1' 'arg2' ... ) X ** X ** ^Awk_Argument_Lists: ! ** For awk, if the -A option is not given, then the output for thes X ** variable-list will be a line with the variable name, followed by a X ** line with each of the values (each value will be separated with the X ** field separator specified using the -S option - which defaults to a ! ** space character): X ** X ** name X ** arg1 arg2 ... --- 1674,1702 ---- X ** bash supports arrays. X ** X ** ^Plan_9_Shell_Argument_Lists: ! ** For the Plan 9 shell, if the associated variable name is not "*" ! ** then it is considered to be a word-list and set using the following ! ** syntax: X ** X ** name=( 'arg1' 'arg2' ... ) X ** + ** ^Z_Shell_Argument_Lists: + ** For the Z shell, ARGLIST variables are treated as word-lists and are + ** assigned using the following syntax: + ** + ** name = ( 'arg1' 'arg2' ... ) + ** + ** The first item will be in $name[1], the second item will be in + ** $name[2], etc ..., and all items may be given by $name. Notice that + ** Korn shell arrays start at index zero whereas Z and C shell word-lists + ** start at index one. + ** X ** ^Awk_Argument_Lists: ! ** For awk, if the -A option is not given, then the output for the X ** variable-list will be a line with the variable name, followed by a X ** line with each of the values (each value will be separated with the X ** field separator specified using the -S option - which defaults to a ! ** space). X ** X ** name X ** arg1 arg2 ... *************** *** 1650,1662 **** X ** @name=( 'arg1' , 'arg2' , ... ); X ** X ** ^A_Final_Note_on_Argument_Lists: ! ** The word-lists used by the C shell, the arrays used by the Korn shell, ! ** The Plan 9 shell, awk, & perl, and the positional parameters used by ! ** all shells (if overwritten by parseargs) will preserve any IFS ! ** characters in their contents. That us to say that if an item in one ! ** of the aforementioned multi-word lists contains any IFS characters, ! ** it will not be split up into multiple items but will remain a single ! ** item which contains IFS characters. X ** X ** ^REQUIREMENTS: X ** <val> should correspond to the vlue of the argument indicated by <ad> --- 1721,1733 ---- X ** @name=( 'arg1' , 'arg2' , ... ); X ** X ** ^A_Final_Note_on_Argument_Lists: ! ** The word-lists used by the C and Z shells, the arrays used by the Korn ! ** shell, the Plan 9 shell, awk, perl, and the positional parameters used ! ** by all shells (if overwritten by parseargs) will preserve any IFS ! ** characters in their contents. That is to say that if an item in one ! ** of the aforementioned multi-word lists contains any IFS characters, it ! ** will not be split up into multiple items but will remain a single item ! ** which contains IFS characters. X ** X ** ^REQUIREMENTS: X ** <val> should correspond to the vlue of the argument indicated by <ad> *************** *** 1676,1757 **** X static void print_argvector( const ARGDESC *ad, const cmdarg_t *val ) X #endif X { ! BOOL is_array = TRUE; X int i; X char *varname; X ! switch( UsrSh ) { ! case KSH : ! if ( strEQ( val->name, Shell[ UsrSh ].varname ) ) { ! fputs( "set -- ", stdout ); ! } ! else { ! printf( "set %cA %s ", ((ModArr) ? '+' : '-'), val->name ); ! } ! break; ! ! case TCSH : case CSH : case RC: case PERL : ! if ( UsrSh == PERL ) ! printf( "@%s = ", val->name ); ! else if ( UsrSh == RC ) ! printf( "%s=", val->name ); ! else /* UsrSh == CSH/TCSH */ ! printf( "set %s=", val->name ); ! fputc( '(', stdout ); ! break; ! ! case BASH: case SH : case AWK: ! if ( UsrSh == AWK ) is_array = FALSE; ! if ( strEQ( val->name, Shell[ UsrSh ].varname ) ) { ! fputs( ((UsrSh == AWK) ? "ARGV\n" : "set -- "), stdout ); ! } ! else { ! if ( ModArr ) { /* use fake array syntax */ ! i = strlen( val->name ); ! varname = (char *)ckalloc( (i + 4) * sizeof(char) ); ! for ( i = 0 ; i < val->value.Vector.count ; i++ ) { ! sprintf( varname, "%s%d", val->name, i+1 ); ! printf( Shell[ UsrSh ].setcmd, varname ); ! printf( Shell[ UsrSh ].prefix ); ! put_arg( stdout, ad, val, i ); ! printf( "%s", Shell[ UsrSh ].suffix ); ! } ! sprintf( varname, "%s_count", val->name ); ! printf( Shell[ UsrSh ].setcmd, varname ); ! printf( Shell[ UsrSh ].prefix ); ! printf( "%d", val->value.Vector.count ); ! printf( "%s", Shell[ UsrSh ].suffix ); ! free( varname ); ! if ( val->value.Vector.array ) { ! free( val->value.Vector.array ); ! val->value.Vector.array = NULL; ! } ! return; ! }/*if ModArr*/ ! else { ! is_array = FALSE; ! printf( Shell[ UsrSh ].setcmd, val->name ); ! printf( Shell[ UsrSh ].prefix ); ! } ! }/*else !positional-parms*/ ! break; ! ! }/*switch*/ ! X for ( i = 0 ; i < val->value.Vector.count ; i++ ) { - if ( is_array ) printf( Shell[ UsrSh ].prefix ); X put_arg( stdout, ad, val, i ); ! if ( is_array ) printf( Shell[ UsrSh ].prefix ); ! if ( i != (val->value.Vector.count - 1) ) { ! fputs( ((UsrSh == PERL) ? ", " : FieldSep), stdout ); X } - }/* end-for */ - - if ( UsrSh == CSH || UsrSh == TCSH || UsrSh == RC || UsrSh == PERL ) { - fputc( ')', stdout ); X } ! ! fputs( ((! is_array) ? Shell[ UsrSh ].suffix : ";\n"), stdout ); X } X X --- 1747,1798 ---- X static void print_argvector( const ARGDESC *ad, const cmdarg_t *val ) X #endif X { ! register shell_t cli = Shell[ UsrSh ].type; ! BOOL set_printed = FALSE; X int i; X char *varname; X ! /* need to check for '--' for sh, ksh, and bash */ ! if ( strEQ("--", val->name) && (cli == SH || cli == BASH || cli == KSH) ) { ! printf( "set -- " ); ! set_printed = TRUE; ! } ! /* if faking arrays for sh, bash, or awk -- do it now! */ ! else if ( ModArr && (cli == SH || cli == BASH || cli == AWK) ) { ! i = strlen( val->name ); ! varname = (char *)ckalloc( (i + 4) * sizeof(char) ); ! for ( i = 0 ; i < val->value.Vector.count ; i++ ) { ! sprintf( varname, "%s%d", val->name, i+1 ); ! printf( Shell[ UsrSh ].sclset, varname ); ! printf( Shell[ UsrSh ].sclpfx ); ! put_arg( stdout, ad, val, i ); ! printf( "%s", Shell[ UsrSh ].sclsfx ); ! } ! sprintf( varname, "%s_count", val->name ); ! printf( Shell[ UsrSh ].sclset, varname ); ! printf( Shell[ UsrSh ].sclpfx ); ! printf( "%d", val->value.Vector.count ); ! printf( "%s", Shell[ UsrSh ].sclsfx ); ! return; ! } ! ! /* print the array already */ ! if ( !set_printed ) { ! if ( cli == KSH ) { ! printf( Shell[ UsrSh ].aryset, ((ModArr) ? '+' : '-'), val->name ); ! } ! else { ! printf( Shell[ UsrSh ].aryset, val->name ); ! } ! } ! printf( Shell[ UsrSh ].arypfx ); X for ( i = 0 ; i < val->value.Vector.count ; i++ ) { X put_arg( stdout, ad, val, i ); ! if ( (i + 1) != val->value.Vector.count ) { ! printf( Shell[ UsrSh ].arysep, FieldSep ); X } X } ! printf( Shell[ UsrSh ].arysfx ); X } X X *************** *** 1838,1846 **** X ***^^*************************************************************/ X if ( ARG_isVALOPTIONAL(ad) ) { X sprintf(buf, "%s_flag", vals[i].name); ! printf( Shell[ UsrSh ].setcmd, buf); ! printf( Shell[ UsrSh ].prefix ); ! printf( "%s%s", StrTrue, Shell[ UsrSh ].suffix ); X X if ( !ARG_isVALGIVEN(ad) ) continue; X }/*if OPTARG*/ --- 1879,1887 ---- X ***^^*************************************************************/ X if ( ARG_isVALOPTIONAL(ad) ) { X sprintf(buf, "%s_flag", vals[i].name); ! printf( Shell[ UsrSh ].sclset, buf); ! printf( Shell[ UsrSh ].sclpfx ); ! printf( "%s%s", StrTrue, Shell[ UsrSh ].sclsfx ); X X if ( !ARG_isVALGIVEN(ad) ) continue; X }/*if OPTARG*/ *************** *** 1852,1865 **** X } X X /* print shell-specific variable prefix and name */ ! printf( Shell[ UsrSh ].setcmd, vals[i].name ); ! printf( Shell[ UsrSh ].prefix ); X X /* print shell-variable value */ X put_arg( stdout, ad, (vals + i), 0 ); X X /* print the shell-specific suffix */ ! printf( "%s", Shell[ UsrSh ].suffix ); X }/*if ARGGIVEN*/ X }/* end-for */ X } --- 1893,1906 ---- X } X X /* print shell-specific variable prefix and name */ ! printf( Shell[ UsrSh ].sclset, vals[i].name ); ! printf( Shell[ UsrSh ].sclpfx ); X X /* print shell-variable value */ X put_arg( stdout, ad, (vals + i), 0 ); X X /* print the shell-specific suffix */ ! printf( "%s", Shell[ UsrSh ].sclsfx ); X }/*if ARGGIVEN*/ X }/* end-for */ X } *************** *** 1898,1931 **** X static void unset_positional_parameters( void ) X #endif X { ! switch( UsrSh ) { ! case TCSH: case CSH: ! printf( "set argv=();\n" ); ! break; ! ! case PERL: ! printf( "@ARGV = ();\n" ); ! break; ! ! case KSH: ! printf( "set --;\n" ); ! break; ! ! case BASH: case SH: ! printf( "shift $#;\n" ); ! break; ! ! case RC: ! printf( "*=();\n" ); ! break; ! ! case AWK: ! printf( "%s%s", Shell[ UsrSh ].varname, Shell[ UsrSh ].suffix ); ! break; ! ! default: ! break; ! }/*switch*/ X } X X --- 1939,1945 ---- X static void unset_positional_parameters( void ) X #endif X { ! printf( Shell[ UsrSh ].unset ); X } X X *************** *** 2020,2029 **** X /* see if we need to "default" the shell name */ X if ( !PrUsage && !PrManual ) { X if ( !ShellName ) { ! UsrSh = SH; /* default to Bourne Shell */ X } X else { ! UsrSh = get_shell_type( basename( ShellName ) ); X } X } X --- 2034,2043 ---- X /* see if we need to "default" the shell name */ X if ( !PrUsage && !PrManual ) { X if ( !ShellName ) { ! UsrSh = get_shell_index( "sh" ); /* default to Bourne Shell */ X } X else { ! UsrSh = get_shell_index( basename( ShellName ) ); X } X } X diff -cNr ../patchlevel4/parseargs.h ./parseargs.h *** ../patchlevel4/parseargs.h Thu May 2 11:06:11 1991 --- ./parseargs.h Thu May 2 14:36:15 1991 *************** *** 605,610 **** --- 605,613 ---- X ** is useful when more than one call to the parseargs library is needed X ** to parse all the command-line arguments (which could occur if the X ** command-line argument came from a file or from two argv-vectors). + ** When this flag is set, then each call to parseargs will check for + ** missing required arguments (and will prompt the user for them if + ** desired). X ** X ** Keeping this flag on until the final set of arguments is parsed will X ** cause parseargs to not check for missing arguments until the last set diff -cNr ../patchlevel4/parseargs.pl ./parseargs.pl *** ../patchlevel4/parseargs.pl Thu May 2 11:06:11 1991 --- ./parseargs.pl Thu May 2 14:36:18 1991 *************** *** 54,65 **** X X sub parseargs { X local($argd, @argv) = ( pop(@_), $0, @_ ); ! local($unset, $end, $sh, $env) = ( '-u', '--', '-s', '-e' ); X local($parse_output, $_); X X $_ = $main'ENV{'PARSECNTL'}; X if ( /[^!~\^]\s*[KkLl]/ ) { ## KeyWords only! ! ($unset, $end, $sh, $env) = ( '+unset', '++', '+shell', '+env' ); X } X X if ( ! $main'PARSEOPTS ) { $main'PARSEOPTS = "$unset"; } --- 54,65 ---- X X sub parseargs { X local($argd, @argv) = ( pop(@_), $0, @_ ); ! local($unset, $sh, $env, $end) = ( '-u', '-s', '-e', '--' ); X local($parse_output, $_); X X $_ = $main'ENV{'PARSECNTL'}; X if ( /[^!~\^]\s*[KkLl]/ ) { ## KeyWords only! ! ($unset, $sh, $env, $end) = ( '+unset', '+shell', '+env', '++' ); X } X X if ( ! $main'PARSEOPTS ) { $main'PARSEOPTS = "$unset"; } diff -cNr ../patchlevel4/parseargs1.txt ./parseargs1.txt *** ../patchlevel4/parseargs1.txt Thu May 2 11:06:45 1991 --- ./parseargs1.txt Wed Dec 31 18:00:00 1969 *************** *** 1,1056 **** - - - - PARSEARGS(1) PARSEARGS(1) - - - - NAME - parseargs - parse command line arguments in shell scripts - - SYNOPSIS - parseargs [-#UMCAlouip1] [-S separator] [-T string] - [-F string] [-a arg-spec] [-e name] [-f file] - [-s shell] -- name [arguments ...] - - OPTIONS - -# just print the version and patchlevel, do not - parse the command line - - -U just print program usage, do not parse the - command line - - -M just print (n|t)roff -man manual page - template, do not parse the command line - - -S separator field-separator-string used to delimit array - elements (default= - - -T string string to use for true boolean arguments - (default=``TRUE'') - - -F string string to use for false boolean arguments - (default=``'') - - -C Ignore the difference between upper and lower - case when parsing single character options. - - -A modify array behavior for the specified shell. - - -a arg-spec argument specification string - - -e name read the arg-spec string from the environment - variable named name - - -f file read the arg-spec from file (default=stdin) - - -l Long-options only. Disable the parsing of - (single-character) options. - - -o Options only. Disable the parsing of long- - options (keywords). - - -s shell use shell command syntax (default=``sh'') - - -u unset positional parameters before assigning - variables - - -p prompt the user for missing required arguments - - - - - Page 1 - - - - - - - PARSEARGS(1) PARSEARGS(1) - - - - -i ignore bad command-line syntax and continue - processing (instead of aborting) - - -1 Force any and all non-positional parameters to - be specified before any positional parameters - on the command-line. - - ARGUMENTS - -- Indicates that any remaining options are - intended for the calling program. - - name name of calling program - - arguments arguments to calling program - - DESCRIPTION - Given a command name, a vector of string-valued arguments - such as that passed to a shell script, and a specification - string describing the possible arguments, parseargs matches - actual arguments to possible arguments, converts values to - the desired type, and diagnoses problems such as missing - arguments, extra arguments, and argument values that are - syntactically incorrect. Other behavior such as prompting - the user for missing arguments and ignoring bad command-line - syntax may be specified on the command-line through the use - of various options, or through the use of the ``PARSECNTL'' - environment variable. - - Given the command name and the argument specification - string, parseargs -U prints a reasonably friendly version of - the usage of the calling program on standard diagnostic - output. The ``verbosity'' of the usage message may be - controlled through the use of the ``USAGECNTL'' environment - variable. - - Given the command name and the argument specification - string, parseargs -M prints a template of the command-syntax - on standard output that is suitable for input to nroff or - troff using the -man macro package. - - Given no other arguments parseargs -# prints on standard - output, the current version and patchlevel of the running - version of parseargs. - - - The argument specification string contains one entry for - each possible flag. Entries in the argument specification - string are separated by commas. Each entry has five comma- - separated fields: a name, some flags, a type, a variable- - name, and a prompt. Each of these fields are described - below: - - - - - Page 2 - - - - - - - PARSEARGS(1) PARSEARGS(1) - - - - name The single character name of the associated flag. - For example, to indicate that the program is - expecting a ``-x'' flag, this field would contain - 'x'. Positional arguments (those without a ``-x'' - prefix) are indicated by passing a ``space'' - character. - - flags Flags modifying the semantics of this entry. - These should have one of ARGREQ to indicate a - required argument or ARGOPT to indicate an - optional argument (ARGOPT is the default unless - ARGREQ is specified). ARGPOS may be ``ored'' in - to indicate a positional argument that may also be - keyword matched. ARGVALOPT may be ``ored'' in to - indicate that an argument to the option may be - optionally supplied on the command-line, but is - not required. ARGVALREQ may be ``ored'' in to - indicate that an argument to the option is - required (this is the default behavior for options - that take arguments). ARGLIST may be ``ored'' in - (using the `|' character) to indicate that an - argument is actually a list of one or more - arguments from the command line. ARGHIDDEN may be - ``ored'' in to indicate a flag that should not be - printed in usage messages - for example, flags - intended for internal debugging purposes. - - type The type of the argument. Existing types include - argUsage (print usage message and exit), argBool - and argSBool (set Boolean flags), argUBool (unset - Boolean flags), argStr (string-valued arguments), - argChar (char-valued arguments), argInt (native - integer arguments), argShort (short integer - arguments), argLong (long integer arguments), - argFloat (short floating point arguments), - argDouble (long floating point arguments), and - argDummy (only used as part of usage message, not - matched on command-line). - - variable The name of the shell variable that should receive - the converted value. - - prompt The string used when prompting interactively for - argument values, and printed in usage messages. - This string may be followed by a textual - description that is enclosed in parentheses, - square brackets, curly braces, or angle brackets. - - The argument specification string must be terminated by the - single string: ``ENDOFARGS''. - - - - - - Page 3 - - - - - - - PARSEARGS(1) PARSEARGS(1) - - - - Note that the comma character (',') is used to separate all - fields within an entry, and to separate the entries - themselves. For this reason, no field in any entry may - contain a comma unless it appears inside of double or single - quotes. - - Parseargs will parse all command-line arguments for the - calling script and match them against the argument - specification string provided. The argument specification - string is read from standard input by default but may not - come from a terminal. The argument specification string may - be supplied as a single string argument by using the -a - ``string'' flag. Long argument specification strings - however, may limit the number of arguments to the script if - there is a limit to the number of arguments and/or - characters that may appear on the command line. For this - reason, the argument specification string may be stored: in - an environment variable using the -e name option; in a file - and read using the -f file option; or read from standard - input. When using the -e option, the user must remember to - use the name of an environment variable (not a mere shell - variable)! The default behavior is to read the argument - specification from standard input. - - SHELLS - After the command line has been parsed, parseargs will print - on standard output, a script to set the shell variables - which correspond to arguments that were present on the - command-line. This script may be evaluated by redirecting - it to a file and then executing the file, or by directly - evaluating the output from parseargs (under most UNIX - shells, this could be done using eval). If any arguments on - the command line contained any special characters that - needed to be escaped from the shell, these characters will - remain intact (not be evaluated by the shell) in the - corresponding shell variable. - - The -s shell option may be used to tell parseargs which - shell syntax to use. At present, parseargs only recognizes - ``sh'', ``csh'', ``ksh'', ``tcsh'', ``bash'', ``rc'', - ``awk'', and ``perl'' as valid command interpreters. Awk - output is slightly different from that of the other shells - in that the actual variable settings are not printed but - each line of an associative array is printed (the first - field is the array index, the second is the value for that - index). If no shell is specified, then the Bourne shell - (``sh'') will be assumed. - - If the user wishes to use a value other than ``TRUE'' for a - boolean flag that is true, this may be done using the -T - string option. The same may also be done for a boolean flag - that is false using the -F string option. - - - - Page 4 - - - - - - - PARSEARGS(1) PARSEARGS(1) - - - - Parseargs will only set the values of variables that - correspond to arguments that were given on the command line. - If a particular argument was not supplied on the command - line, then no assignment is made for the corresponding shell - variable and it will have the same value that it had before - parseargs was invoked. The only exception to this is that if - the -u option is specified, then the positional parameters - are unset before any shell variable assignments (which may - reset the positional parameters) are made. - - The double-dash (``--'') which precedes the name and - arguments of the calling program is needed in order for - parseargs to be able to distinguish options to itself from - options for the calling program. - - The default behavior of parseargs is to allow both single- - character options and long-options (keywords) on the - command-line. The user may specify that only options (long- - options) are to be permitted by specifying the -o (-l) - option on the command-line. - - SPECIFYING PARSE-BEHAVIOR - The -C, -p, -i, and -1 switches may be used to modify the - command-line parsing behavior of the invoking script. - Specifying -C will cause case-differences in single- - character options to be ignored. Specifying -p will cause - the user to be interactively prompted for any missing - required arguments. Specifying -i will cause syntactically - incorrect arguments to be ignored (instead of having a usage - message printed and execution terminated). Specifying -1 - will force all non-positional parameters to precede any - positional parameters on the command-line (hence anything on - the command-line after a positional parameter that resembles - a keyword parameter will nevertheles be interpreted as a - positional parameter). - - OPTIONS WITH OPTIONAL ARGUMENTS - Options that may take an optional argument need special - consideration. The shell programmer needs to know whether - or not the option was given, and (if given) if it was - accompanied by an argument. In order to accommodate this - need, parseargs will set an additional shell variable for - each argument that is given the ARGVALOPT flag if it is - supplied on the command line regardless of whether or not it - was accompanied by its optional argument. If the user has - defined an option which may optionally take an argument and - the option appears on the command line with or without its - associated argument, then the shell variable <name>_flag - will be assigned the value ``TRUE'' (or the value supplied - with the -T option to parseargs) where <name> is the name of - the shell variable associated with the option in the - argument description string. - - - - Page 5 - - - - - - - PARSEARGS(1) PARSEARGS(1) - - - - ARGUMENT LISTS - Parseargs treats ARGLIST arguments in a special way. The - method used for setting up an argument list depends largely - upon the syntax of shell that was specified on the command - line via the -s option (although ARGLIST arguments are - treated exactly the same as ARGVEC arguments). - Resetting the Positional Parameters to an Argument List - - For the Bourne, Bourne-Again, and Korn shells, if the - variable name corresponding to the ARGLIST argument is - ``--'', then the positional parameters of the calling - program will be re-assigned to the contents of the argument - list ($1 will be the first item, $2 the second item, and so - on). In this particular case, the calling program may wish - to use the -u option to reset the positional parameters to - NULL before making any shell-variable assignments (this way, - the positional parameters will be unset if the associated - list of command line arguments is not encountered). - - Similarly for the C and TC shells, if the variable name - corresponding to the ARGLIST argument is ``argv'', then the - positional parameters of the calling program will be re- - assigned to the contents of the argument list. - - For the Plan 9 shell (rc), if the variable name - corresponding to the ARGLIST argument is ``*'', then the - positional parameters of the calling program will be re- - assigned to the contents of the argument list. - - For awk and perl, if the variable name corresponding to the - ARGLIST argument is ``ARGV'', then the positional parameters - of the calling program will be re-assigned to the contents - of the argument list. - - Bourne Shell Argument Lists - - For the Bourne shell, if the associated variable name is NOT - ``--'' and the -A option was NOT specified, then that - variable is treated as a regular shell variable and is - assigned using the following syntax: - name='arg1 arg2 ...' - After invoking parseargs, if you wish to go through all the - words in the variable name and one of the words in name - contains an IFS character (such as a space or a tab), then - that particular word will be treated by the Bourne shell as - two distinct words. - Also for the Bourne shell, If the associated variable name - is NOT ``--'' and the -A option WAS specified, then that - variable is treated as the root name of an array that is set - using the following syntax: - name1='arg1' - name2='arg2' - - - - Page 6 - - - - - - - PARSEARGS(1) PARSEARGS(1) - - - - ... - and the variable ``name_count'' will be set to contain the - number of items in the array. The user may then step - through all the items in the array using the following - syntax: - i=1 - while [ $i -le $name_count ] ; do - eval echo "item #$i is: " \$name$i - i=`expr $i + 1` - done - Korn Shell Argument Lists - - For the Korn shell, if the associated variable name is NOT - ``--'', then that variable is treated as an array and is - assigned using the -A option of the set command. The first - item will be in ${name[0]}, the second item will be in - ${name[1]}, etc ..., and all items may be given by - ${name[*]} or ${name[@]}. If the associated variable name - is NOT ``--'' and the -A option WAS specified, then that - variable is assigned using the +A option of the set command - (which preserves any array elements that were not - overwritten by the set command). - It should be noted that there is a bug in versions of the - Korn shell earlier than 11/16/88a, in which the following: - set -A name 'arg1' 'arg2' ... - causes the positional parameters to be overwritten as an - unintentional side-effect. If your version of the Korn shell - is earlier than this and you wish to keep the contents of - your positional parameters after invoking parseargs than you - must save them yourself before you call parseargs. This may - be accomplished by the following: - set -A save_parms "$@" - - C and TC Shell Argument Lists - - For the C and TC shells, ARGLIST variables are treated as - word-lists and are assigned using the following syntax: - set name = ( 'arg1' 'arg2' ... ) - The first item will be in $name[1], the second item will be - in $name[2], etc ..., and all items may be given by $name. - Notice that Korn shell arrays start at index zero whereas C - and TC shell word-lists start at index one. - Bourne-Again Shell Argument Lists - - At present, the Free Software Foundation's Bourne-Again - shell is treated exactly the same as the Bourne Shell. This - will change when bash supports arrays. - - Plan 9 Shell Argument Lists - - For the Plan 9 shell, if the associated variable name is not - ``*'' then it is considered to be a word-list and set using - - - - Page 7 - - - - - - - PARSEARGS(1) PARSEARGS(1) - - - - the following syntax: - name=( 'arg1' 'arg2' ... ) - Awk Argument Lists - For awk, if the -A option is not given, then the output for - thes variable-list will be a line with the variable name, - followed by a line with each of the values (each value will - be separated with the field separator specified using the -S - option - which defaults to a space). - name - arg1 arg2 ... - If the -A option is given, then the associated variable is - considered the root name of an array. The ouput for the - array will consist of two lines for each item in the list - (as in the following example): - name1 - arg1 - - name2 - arg2 - - and the variable ``name_count'' will have an output line - showing the number of items in the array. - - Perl Argument Lists - - For perl, each argument list is considered an array and is - set using the following syntax: - @name=( 'arg1' , 'arg2' , ... ); - - A Final Note on Argument Lists - - The word-lists used by the C shell, the arrays used by the - Korn shell, the Plan 9 shell, awk, perl, and the positional - parameters used by all shells (if overwritten by parseargs) - will preserve any IFS characters in their contents. That is - to say that if an item in one of the aforementioned multi- - word lists contains any IFS characters, it will not be split - up into multiple items but will remain a single item which - contains IFS characters. - - SUPPLYING DEFAULT ARGUMENTS - Programs that use parseargs may be given default arguments - under UNIX and PCs through the use of environment variables - (symbols are used for VMS systems). If a C-program or - shell-script uses parseargs to implement a command named - ``cmd'' then the environment variable ``CMD_ARGS'' will be - parsed for any "default" arguments before the command-line - is parsed. The command-line will over-ride any options that - are specified in this environment variable (except that - ARGLISTs and ARGVECs set in ``CMD_ARGS'' will be appended - from the command-line if they are selected). - - - - - Page 8 - - - - - - - PARSEARGS(1) PARSEARGS(1) - - - - It is important to note that the contents of the - ``CMD_ARGS'' environment variable are NOT expanded by the - shell and hence any special characters (such as quotes or - back-slashes) will NOT be escaped or removed by parseargs. - Furthermore, it will not be possible to try and use a tab, - space, or newline character in the environment variable as - anything other than an argument separator. - - Lastly, parts of an option specification in ``CMD_ARGS'' may - NOT be continued on the command-line. As an example, if -f - requires an argument and CMD_ARGS="-f", then the command- - line "cmd bah" will NOT assign "bah" as the argument to -f - but will instead complain about a missing argument for -f. - Similarly, if -l takes a list of arguments and CMD_ARGS="-l - item1 item2", then the command-line "cmd bah", will NOT - assign "bah" to the end of the list containing "item1" and - "item2" but will instead treat "bah" as the first positional - parameter on the command-line. - - PARSING BEHAVIOR - The programmer may control parsing behavior through the use - of parsecntl(3). The user may set his (or her) own desired - parsing behavior through the use of the ``PARSECNTL'' - environment variable. By indicating any number of flags - (possibly negated) the user will directly modify the - behavior of the parseargs library. Flags may be combined by - placing a `+' or `|' character in between flags. A switch is - negated by immediately preceding it with a `!' or `-' - character. The possible ``flags'' are given by the - following table. Flags are case-insensitive. - - Prompt - Prompt the user for any missing arguments that are - required on the command-line. No special escaping or - quoting is performed on the user input. Required - arguments that expect a list of values will be - repeatedly prompted for (one item per line) until a - blank line (followed by a carriage return) is entered. - - Ignore - Ignore any unrecognized or improperly specified - command-line arguments and continue execution of the - program. Normally, if a required argument is unmatched - (or an argument is improperly specified), a usage - message is printed program execution is terminated. - - OptsOnly - Under UNIX, setting this flag will disable the parsing - of long-option syntax. This will cause all arguments - starting with `+' to always be treated as a positional - parameter (instead of a long-option). - - - - - Page 9 - - - - - - - PARSEARGS(1) PARSEARGS(1) - - - - KwdsOnly - Under UNIX, setting this flag disables the parsing of - single-character options. This will cause all - arguments starting with `-' to always be treated as a - positional parameter (instead of an option). - - LoptsOnly - Same as KwdsOnly. - - Flags1st - Setting this flag causes the parseargs library to force - any and all non-positional arguments to be specified - before any positional ones. As an example, under UNIX, - if this flag is SET then parseargs will consider the - command line "cmd -x arg" to consist of one option and - one positional argument; however the command line "cmd - arg -x" would be considered to consist of two - positional arguments (the -x option will be unmatched). - - If this flag is UNSET, then both of the previous - examples are considered to consist of one option and - one positional argument. - - CaseIgnore - Setting this flag will cause character-case to be - ignored when attempting to match single-character - argument names (i.e. causes "-i" and "-I" to be - considered equivalent). - - If the environment variable ``PARSECNTL'' is empty or - undefined, then the parsing behavior set by the programmer - is used. If the programmer has not explicitly used - parsecntl(3) to modify the parsing behavior, then the - default behavior will be ``Flags1st'' for Unix systems, - ``!Prompt + !Ignore'' for AmigaDOS systems, ``CaseIgnore'' - for MS-DOS and OS/2 systems, and ``Prompt'' for VMS systems. - - USAGE MESSAGES - Through the use of an environment variable (or a VMS - symbol), the user may control the syntax and the verbosity - of the command-usage messages that are printed by parseargs. - The desired level of verbosity may be set by defining the - environment variable ``USAGECNTL" to be a combination of - strings (case insensitive). The value of each string - controls one of three different ``modes'' of behavior in the - displaying of usage messages: The first ``mode'' is SHAR_EOF true || echo 'restore of PATCH05 failed' fi echo 'End of part 3' echo 'File PATCH05 is continued in part 4' echo 4 > _shar_seq_.tmp exit 0 exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.