home *** CD-ROM | disk | FTP | other *** search
- From: brad@hcx1.ssd.csd.harris.com (Brad Appleton)
- Newsgroups: comp.sources.misc
- Subject: v17i054: parseargs - functions to parse command line arguments, Part09/12
- Message-ID: <1991Mar18.155707.2176@sparky.IMD.Sterling.COM>
- Date: 18 Mar 91 15:57:07 GMT
- Approved: kent@sparky.imd.sterling.com
- X-Checksum-Snefru: 5c2e25a2 b3a18d0f 8698d8b5 d41be7ad
-
- Submitted-by: Brad Appleton <brad@hcx1.ssd.csd.harris.com>
- Posting-number: Volume 17, Issue 54
- Archive-name: parseargs/part09
-
- This is part 9 of parseargs
-
- #!/bin/sh
- # this is Part.09 (part 9 of a multipart archive)
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file parseargs/pgopen.c continued
- #
- if test ! -r _shar_seq_.tmp; then
- echo 'Please unpack part 1 first!'
- exit 1
- fi
- (read Scheck
- if test "$Scheck" != 9; 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 parseargs/pgopen.c'
- else
- echo 'x - continuing file parseargs/pgopen.c'
- sed 's/^X//' << 'SHAR_EOF' >> 'parseargs/pgopen.c' &&
- ** pager-file-pointer.
- **
- ** ^SIDE-EFECTS:
- ** None.
- **
- ** ^RETURN-VALUE:
- ** Zero if the pager is active; non-zero otherwise.
- **
- ** ^ALGORITHM:
- ** Trivial.
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X int pgactive( const FILE *pager_fp )
- #endif
- {
- X return ( (Pager_Type != PG_CLOSED) && (pager_fp) );
- }
- X
- X
- /***************************************************************************
- ** ^FUNCTION: pgclose - close the pager.
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X int pgclose( pager_fp )
- /*
- ** ^PARAMETERS:
- */
- X FILE *pager_fp;
- /* -- the file-pointer returned by pgopen()
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** Pgclose will flush any remaining output and close the pager.
- **
- ** ^REQUIREMENTS:
- ** pgopen() must first be called in order to obtain a valid
- ** pager-file-pointer.
- **
- ** ^SIDE-EFECTS:
- ** None.
- **
- ** ^RETURN-VALUE:
- ** Returns 0 if the pager was succesfully close; non-zero if it wasnt
- ** in use to begin with.
- **
- ** ^ALGORITHM:
- ** - if ( pager-not-in-use ) return 1
- ** - flush any remaining pager output
- ** - if we used popen() to open this pager then
- ** - call pclose to close the pager-program
- ** - unset the SIGPIPE signal-handler
- ** - wait for the pager-process to die
- ** end-if
- ** - reset the pager-file-pointer to NULL
- ** - set the pager-state to closed
- ** - return 0
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X int pgclose( FILE *pager_fp )
- #endif
- {
- X if ( Pager_Type == PG_CLOSED || !Pager_FP || !pager_fp ) return 1;
- X
- X fflush( Pager_FP );
- X
- X if ( Pager_Type == PG_ENV || Pager_Type == PG_DFLT ) {
- X signal( SIGPIPE, (void (*)())SIG_IGN );
- X wait( (int *) 0 );
- X }
- X
- X Pager_FP = (FILE *)NULL;
- X Pager_Type = PG_CLOSED;
- X
- X return 0;
- }
- X
- X
- /***************************************************************************
- ** ^FUNCTION: pgopen - open the pager
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X FILE *pgopen( fp, pager_cmd )
- /*
- ** ^PARAMETERS:
- */
- X FILE *fp;
- /* -- the file pointer to use if popen() fails
- */
- X char *pager_cmd;
- /* -- name of the pager-program to pass to popen()
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** Pgopen will attempt to "redirect" output from the given file
- ** pointer to the pager specified by <pager_cmd>. If <fp> is NOT
- ** connected to a terminal or <pager_cmd> cannot be succesfully
- ** opened, then <fp> is resturned output is sent to it unpaginated.
- ** Otherwise, pgopen will try to open <pager_cmd> for input. If it
- ** cannot succeed it tries to open $PAGER for input. If this also
- ** fails then /usr/ucb/more is tried. If all else fails, return <fp>.
- **
- ** ^REQUIREMENTS:
- ** pager_cmd should be the full-pathname name of a valid, executable
- ** program which reads from standard input and writes (one screenful
- ** at a time) to the terminal.
- **
- ** ^SIDE-EFECTS:
- ** If popen() succeeds, the SIGPIPE signal is trapped.
- **
- ** ^RETURN-VALUE:
- ** returns 0 upon success, non-zero if the pager is already in use.
- **
- ** ^ALGORITHM:
- ** - if the pager is already in use, return 1
- ** - if <fp> is not connected to a terminal, use it for output and return 0
- ** - set up recovery point for SIGPIPE signal
- ** - if we can open the pager_cmd, check for a SIGPIPE error
- ** - if either of the above fails, then try the same with $PAGER
- ** - if either of the above fails, then try the same with /usr/ucb/more
- ** - if either of the above fails, just use <fp> and return
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X FILE *pgopen( FILE *fp, const char *pager_cmd )
- #endif
- {
- X pager_t pg_type;
- X char pg_name[ MAX_NAME_LEN ];
- X
- X /* if a pager is already open - ignore this call */
- X if ( Pager_Type != PG_CLOSED || Pager_FP ) return fp;
- X
- X /*
- X ** dont page output if it has been redirected
- X */
- X if ( !isTERMINAL(fileno(fp)) ) {
- X Pager_Type = PG_FILE;
- X Pager_FP = fp;
- X return fp;
- X }
- X
- X *pg_name = '\0';
- X if ( pager_cmd ) strcpy( pg_name, pager_cmd );
- X pg_type = pg_pathname( pg_name );
- X Pager_FP = (FILE *)NULL;
- X
- X /* jump here after pg_error fields SIGPIPE */
- X if ( setjmp( pg_recover ) ) {
- X (void) pclose( Pager_FP );
- X Pager_FP = (FILE *)NULL;
- X pg_type = ( pg_type == PG_ENV ) ? PG_DFLT : PG_NONE;
- X }
- X
- X /* keep trying till we get a valid file-pointer */
- X while ( !Pager_FP ) {
- X switch( pg_type ) {
- X case PG_DFLT:
- X /* jump here if both $PAGER and DEFAULT-PAGER fail */
- X if ( setjmp( pg_recover )) {
- X (void) pclose( Pager_FP );
- X Pager_FP = (FILE *)NULL;
- X pg_type = PG_NONE;
- X continue;
- X }
- X /* fall through to next case */
- X
- X case PG_ENV:
- X signal( SIGPIPE, pg_error );
- X Pager_FP = (FILE *) popen( pg_name, "w" );
- X if ( !Pager_FP ) {
- X if ( pg_type == PG_ENV ) {
- X Pager_FP = (FILE *)NULL;
- X pg_type = PG_DFLT;
- X }
- X else {
- X Pager_FP = fp;
- X pg_type = PG_NONE;
- X }
- X }
- X else {
- X /*
- X ** Sleep for a bit, just so we block, and the child
- X ** process can get moving. Then attempt to write to
- X ** the pager pipeline. If the pager is bad then the
- X ** pipe will be broken and pg_error() will handle
- X ** the broken-pipe signal. Othwerwise, the write will
- X ** succeed and we'll reset the handler to ignore the
- X ** broken pipe signal.
- X */
- X sleep( 1 );
- X fputc( '\n', Pager_FP );
- X fflush( Pager_FP );
- X signal( SIGPIPE, (void (*)())SIG_IGN );
- X }
- X break;
- X
- X case PG_NONE:
- X case PG_FILE:
- X Pager_FP = fp;
- X break;
- X
- X default:
- X fprintf( stderr, "Unrecognized state [%d] in pgopen()\n",
- X pg_type );
- X exit( -1 );
- X }/*switch*/
- X }/*while*/
- X
- X Pager_Type = pg_type;
- X return Pager_FP;
- }
- X
- X
- /***************************************************************************
- ** ^FUNCTION: pg_error - handle error when trying to open a pager
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X static void pg_error()
- #endif
- /*
- ** ^PARAMETERS:
- ** None.
- **
- ** ^DESCRIPTION:
- ** Pgerror is called when the SIGPIPE signal is recieved. If SIGPIPE
- ** is recieved, it means that popen succesfully forked the shell to
- ** run the pager but the pager-command itself broke the read-end of
- ** the pipe between us (i.e. it is an invalid pager-program or it crashed).
- **
- ** When SIGPIPE is recieved, this routine will reset the signal handler
- ** to its previous value and jump to the recovery point set up by pgopen.
- **
- ** ^REQUIREMENTS:
- ** Pgopen must set up this function is the SIGPIPE handler function.
- **
- ** Pgopen must place the address of the desired recovery point in
- ** pg_recover.
- **
- ** ^SIDE-EFECTS:
- ** Resets SIGPIPE signal-handler and performs a non-local goto.
- **
- ** ^RETURN-VALUE:
- ** None.
- **
- ** ^ALGORITHM:
- ** Trivial.
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X static void pg_error( void )
- #endif
- {
- X signal( SIGPIPE, (void (*)())SIG_IGN );
- X longjmp( pg_recover, 1 );
- }
- X
- X
- /***************************************************************************
- ** ^FUNCTION: pg_pathname - get name of pager-program to use
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X static pager_t pg_pathname( pager_cmd )
- /*
- ** ^PARAMETERS:
- */
- X char *pager_cmd;
- /* -- name of the pager-program to verify
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** Pg_pathname will determine the name of the pager-program to attempt to
- ** open based on the values of pager_cmd, and $PAGER.
- **
- ** ^REQUIREMENTS:
- ** pager_cmd must be non-null and be large enough to hold any of the
- ** possible pager program-names to be opened.
- **
- ** ^SIDE-EFECTS:
- ** pager_cmd is over-written with the name of the pager-command to
- ** try to open for output
- **
- ** ^RETURN-VALUE:
- ** Returns PG_DFLT if /usr/ucb/more is to be used.
- ** Returns PG_ENV if $PAGER or <pager_cmd> is to be used.
- **
- ** ^ALGORITHM:
- ** - If pager_cmd is executable then compare it to /usr/ucb/more
- ** return PG_ENV if not-equal, else return PG_DFLT
- ** - Else
- ** - pager_cmd = $PAGER
- ** - If $PAGER is executable then compare it to /usr/ucb/more
- ** return PG_ENV if not-equal, else return PG_DFLT
- ** - Else
- ** pager_cmd = /usr/ucb/more
- ** return PG_DFLT
- ** End-if
- ** End-if
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X static pager_t pg_pathname( char *pager_cmd )
- #endif
- {
- X char *pg_name = pager_cmd, *getenv();
- X pager_t pg_type;
- X
- X if ( Pager_Type != PG_NONE ) pg_type = Pager_Type;
- X
- X /* see if the given pager is okay */
- X if ( !pg_name || !*pg_name || !access(pg_name, X_OK) ) {
- X pg_name = getenv("PAGER");
- X }
- X else {
- X pg_type = ( strcmp(pager_cmd, DEFAULT_PAGER) ) ? PG_ENV : PG_DFLT;
- X return pg_type;
- X }
- X
- X /* see if $PAGER is ok */
- X if ( !access(pg_name, X_OK) ) {
- X pg_type = ( strcmp(pg_name, DEFAULT_PAGER) ) ? PG_ENV : PG_DFLT;
- X strcpy( pager_cmd, pg_name );
- X }
- X else {
- X pg_type = PG_DFLT;
- X strcpy( pager_cmd, DEFAULT_PAGER );
- X }
- X
- X return pg_type;
- }/* pg_pathname */
- X
- X
- #endif /* USE_PAGER */
- SHAR_EOF
- echo 'File parseargs/pgopen.c is complete' &&
- chmod 0664 parseargs/pgopen.c ||
- echo 'restore of parseargs/pgopen.c failed'
- Wc_c="`wc -c < 'parseargs/pgopen.c'`"
- test 12588 -eq "$Wc_c" ||
- echo 'parseargs/pgopen.c: original size 12588, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= parseargs/pgopen.h ==============
- if test -f 'parseargs/pgopen.h' -a X"$1" != X"-c"; then
- echo 'x - skipping parseargs/pgopen.h (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting parseargs/pgopen.h (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'parseargs/pgopen.h' &&
- /*************************************************************************
- ** ^FILE: pgopen.h - include file for pgopen.c
- **
- ** ^DESCRIPTION:
- ** If USE_PAGER is #define'd then this file will define the function
- ** prototypes needed to use the paging library implemented in pgopen.c;
- ** Otherwise it will #define macros with the same name as the paging
- ** library routines which do NOT perform any paging.
- **
- ** ^HISTORY:
- ** 01/02/91 Brad Appleton <brad@ssd.csd.harris.com> Created
- ***^^**********************************************************************/
- X
- #ifndef NULL
- # include <stdio.h>
- #endif
- #include <useful.h>
- X
- #ifdef USE_PAGER
- X EXTERN FILE *pgopen ARGS(( FILE *, const char * ));
- X EXTERN int pgclose ARGS(( FILE * ));
- X EXTERN int pgactive ARGS(( const FILE * ));
- #else
- # define pgopen(fp,s) (( !fp ) ? fp : (fflush(fp), fp))
- # define pgclose(fp) (( !fp ) ? 0 : (fflush(fp), 0))
- # define pgactive(fp) ( fp )
- #endif
- SHAR_EOF
- chmod 0664 parseargs/pgopen.h ||
- echo 'restore of parseargs/pgopen.h failed'
- Wc_c="`wc -c < 'parseargs/pgopen.h'`"
- test 977 -eq "$Wc_c" ||
- echo 'parseargs/pgopen.h: original size 977, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= parseargs/stest.c ==============
- if test -f 'parseargs/stest.c' -a X"$1" != X"-c"; then
- echo 'x - skipping parseargs/stest.c (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting parseargs/stest.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'parseargs/stest.c' &&
- /*************************************************************************
- ** ^FILE: stest.c - test program for parseargs()
- **
- ** ^DESCRIPTION:
- ** This file is the test program for the parseargs(3) function libarary.
- ** It is used to test parseargs for all command-line styles (which presently
- ** includes: UNIX, VMS, AmigaDOS, MS-DOS, and OS/2).
- **
- ** ^HISTORY:
- ** --/--/-- Brad Appleton <brad@ssd.csd.harris.com>
- ** - Added structured block comments
- ** - Added an extra test for both old-style and new-style argument arrays
- ** - Added a test for triggers (ARGNOVAL arguments)
- ** - Added a test for arguments with optional values (using parsecntl())
- ** - Added arg-vector arguments
- **
- ** --/--/-- Peter da Silva <peter@ferranti.com>
- **
- ** --/--/-- Eric P. Allman <eric@Berkeley.EDU> Created
- ***^^**********************************************************************/
- X
- #include <useful.h>
- #include <parseargs.h>
- X
- VERSIONID("$Header: stest.c,v 2.0 89/12/24 00:56:29 eric Exp $");
- X
- static char Mode[4] = "OFF";
- X
- /***************************************************************************
- ** ^FUNCTION: argMine - example ARGNOVAL argument translation routine
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X BOOL argMine( ad, vp, copyf )
- /*
- ** ^PARAMETERS:
- */
- X ARGDESC *ad;
- /* -- the argument descriptor for this parameter.
- */
- X char *vp;
- /* -- a pointer to the string input value.
- */
- X BOOL copyf;
- /* -- if TRUE, the value will be destroyed later, and so should be
- ** copied if it will be retained (as for a string).
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** This routine is provided as a (very) simple example of how to use
- ** the ARGNOVAL flag to set up "trigger" arguments. Depending upon the
- ** implementation of the "trigger" function (this routine), the position
- ** of the corresponding argument on the command line may (or may not) be
- ** important.
- **
- ** ^REQUIREMENTS:
- ** ad should have ARGNOVAL set and this function as its ad_type.
- **
- ** ^SIDE-EFFECTS:
- ** The static global variable Mode is (re)written.
- **
- ** ^RETURN-VALUE:
- ** TRUE.
- **
- ** ^ALGORITHM:
- ** Trivial.
- ***^^**********************************************************************/
- /*ARGSUSED*/
- #ifdef __ANSI_C__
- X BOOL argMine( ARGDESC *ad, char *vp, BOOL copyf )
- #endif
- {
- X strcpy(Mode, "ON");
- X return TRUE;
- }
- X
- /*************************************************************************/
- X /* declare variables to hold values from the command-line */
- #define DEF_STR "Default String"
- X
- typedef ARGVEC_T(char *) strvec_t;
- X
- static int RepCount;
- static char *Name;
- static char *Str = DEF_STR;
- static char *DirName = ".";
- static BOOL XRated = FALSE;
- static BOOL XFlag = FALSE;
- static BOOL YFlag = TRUE;
- static BOOL ZFlag = FALSE;
- static char TabChar = ':';
- static ARGVEC_T(int) Integers = ARGVEC_EMPTY(int);
- static strvec_t Groups = ARGVEC_EMPTY(char *);
- static ArgList *Argv = (ArgList *)NULL;
- X
- /*************************************************************************/
- X /* declare a new style argument-descriptor array */
- static
- CMD_OBJECT
- X Cmd
- X
- CMD_NAME
- X "stest -- test program for parseargs"
- X
- CMD_DESCRIPTION
- X "This program is used to test parseargs for each desired command-line \
- style and for both old and new style argument-array declarations. The actual \
- name of the command will be <os>_test. parseargs will be called twice (with \
- the same command-line description) in order to test both the old and the new \
- syntax for declaring argument arrays."
- X
- CMD_ARGUMENTS
- X 'n', ARGREQ|ARGPOS, argStr, __ &Name, "name (name to look for)",
- X 's', ARGVALOPT, argStr, __ &Str, "STRing (optional string to use)",
- X 'g', ARGVEC, argStr, __ &Groups, "newsGROUPS (newsgroups to test)",
- X 'c', ARGOPT, argInt, __ &RepCount, "REPcount (repeat count per group)",
- X 'd', ARGOPT, argStr, __ &DirName, "DIRname (work directory)",
- X 'i', ARGVEC, argInt, __ &Integers, "INTegerS (vector of numbers)",
- X '#', ARGHIDDEN, argBool, __ &XRated, "XratedMODE (naughty! naughty!)",
- X
- X 'x', ARGOPT, argSBool, __ &XFlag, "Xflag (set X flag)",
- X 'y', ARGOPT, argUBool, __ &YFlag, "Yflag (unset Y flag)",
- X 'z', ARGOPT, argTBool, __ &ZFlag, "Zflag (toggle Z flag)",
- X
- X 't', ARGOPT, argChar, __ &TabChar, "TABchar (field delimiter)",
- X 'r', ARGNOVAL, argMine, __ NULL, "raw (trigger raw-mode \
- before processing any more arguments on the command-line)",
- X
- X ' ', ARGLIST, listStr, __ &Argv, "file (list of files)",
- X
- X END_ARGUMENTS
- CMD_END
- X
- X
- /*************************************************************************/
- X /* declare an old style argument-descriptor array */
- static ARGDESC Args[] =
- {
- X STARTOFARGS,
- X
- X 'n', ARGREQ|ARGPOS, argStr, __ &Name, "name (name to look for)",
- X 's', ARGVALOPT, argStr, __ &Str, "STRing (optional string to use)",
- X 'g', ARGVEC, argStr, __ &Groups, "newsGROUPS (newsgroups to test)",
- X 'c', ARGOPT, argInt, __ &RepCount, "REPcount (repeat count per group)",
- X 'd', ARGOPT, argStr, __ &DirName, "DIRname (work directory)",
- X 'i', ARGVEC, argInt, __ &Integers, "INTegerS (vector of numbers)",
- X '#', ARGHIDDEN, argBool, __ &XRated, "XratedMODE (naughty! naughty!)",
- X
- X 'x', ARGOPT, argSBool, __ &XFlag, "Xflag (set X flag)",
- X 'y', ARGOPT, argUBool, __ &YFlag, "Yflag (unset Y flag)",
- X 'z', ARGOPT, argTBool, __ &ZFlag, "Zflag (toggle Z flag)",
- X
- X 't', ARGOPT, argChar, __ &TabChar, "TABchar (field delimiter)",
- X 'r', ARGNOVAL, argMine, __ NULL, "raw (trigger raw-mode \
- before processing any more arguments on the command-line)",
- X
- X ' ', ARGLIST, listStr, __ &Argv, "file (list of files)",
- X
- X ENDOFARGS
- };
- X
- X
- /***************************************************************************
- ** ^FUNCTION: reset_args - reset argument values for another pass
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X static VOID reset_args()
- #endif
- /*
- ** ^PARAMETERS:
- ** None.
- **
- ** ^DESCRIPTION:
- ** Reset_args resets all the argument values to their corresponding
- ** default values so that we can (re)test the parseargs library.
- **
- ** ^REQUIREMENTS:
- ** None.
- **
- ** ^SIDE-EFECTS:
- ** All the static-global argument variables are rewritten.
- **
- ** ^RETURN-VALUE:
- ** None.
- **
- ** ^ALGORITHM:
- ** Trivial.
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X static void reset_args( void )
- #endif
- {
- X RepCount = 0;
- X Name = CHARNULL;
- X Str = DEF_STR;
- X DirName = ".";
- X XRated = FALSE;
- X XFlag = FALSE;
- X YFlag = TRUE;
- X ZFlag = FALSE;
- X TabChar = ':';
- X
- X vecFree(Integers, int);
- X vecDeepFree(Groups, char *);
- X listFree( Argv );
- X Argv = ARGLISTNULL;
- }
- X
- X
- /***************************************************************************
- ** ^FUNCTION: print_args - print current argument values
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X static void print_args( argd )
- /*
- ** ^PARAMETERS:
- */
- X ARGDESC *argd;
- /* -- the command whose arg-values are to be printed
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** Print the current values of all the command-line settings
- **
- ** ^REQUIREMENTS:
- ** The command-line should have already been parsed by one of the
- ** Xparseargs functions.
- **
- ** ^SIDE-EFECTS:
- ** Prints on stdout.
- **
- ** ^RETURN-VALUE:
- ** None.
- **
- ** ^ALGORITHM:
- ** Trivial.
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X static void print_args( const ARGDESC *argd )
- #endif
- {
- X int i, flags;
- X ArgList *ls;
- X
- X printf( "Name = \"%s\", DirName = \"%s\", RepCount = %d,\n",
- X Name, DirName, RepCount );
- X
- X printf( "XFlag = %d, YFlag = %d, ZFlag = %d, TabChar='%c'(%03o);\n",
- X XFlag, YFlag, ZFlag, TabChar, TabChar );
- X
- X printf( "XRated=%d, Raw-Mode = \"%s\"\n", XRated, Mode );
- X
- X /* to call parsecntl() to see if the optional value was supplied */
- X (VOID) parsecntl( (ARGDESC *)argd, pc_ARGFLAGS, pc_READ, "string", &flags);
- X
- X if ( BTEST(flags, ARGGIVEN) && !BTEST(flags, ARGVALGIVEN) ) {
- X printf("String=!No Value Given on CmdLine!\n" );
- X }
- X else {
- X printf("String=\"%s\"\n", Str);
- X }
- X
- X if (Groups.count) {
- X printf("Newsgroups:");
- X for (i = 0 ; i < Groups.count ; i++ ) {
- X printf(" %s", Groups.array[i]);
- X }
- X putchar('\n');
- X }
- X
- X if (Integers.count) {
- X printf("Integers:");
- X for (i = 0 ; i < Integers.count ; i++ ) {
- X printf(" %d", Integers.array[i]);
- X }
- X putchar('\n');
- X }
- X
- X if (Argv) printf("Remaining args: ");
- X for ( ls = Argv ; ls ; L_ADVANCE(ls) ) {
- X printf("%s", L_STRING(ls));
- X if ( L_NEXT(ls) ) {
- X putchar(' ');
- X }
- X else {
- X putchar('\n');
- X }
- X }/*for*/
- }
- X
- X
- /*ARGSUSED*/
- MAIN(argc, argv)
- {
- X parseargs(argv, Cmd); /* parse the command-line */
- X print_args(Cmd); /* print what we found */
- X
- X putchar('\n');
- X reset_args(); /* reset args for another pass */
- X
- X parseargs(argv, Args); /* parse same command-line using old-style argd */
- X print_args(Args); /* print what we found (should be same as before) */
- X
- X exit(0); /* wave bye-bye */
- }
- SHAR_EOF
- chmod 0664 parseargs/stest.c ||
- echo 'restore of parseargs/stest.c failed'
- Wc_c="`wc -c < 'parseargs/stest.c'`"
- test 9196 -eq "$Wc_c" ||
- echo 'parseargs/stest.c: original size 9196, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= parseargs/strfuncs.c ==============
- if test -f 'parseargs/strfuncs.c' -a X"$1" != X"-c"; then
- echo 'x - skipping parseargs/strfuncs.c (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting parseargs/strfuncs.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'parseargs/strfuncs.c' &&
- /**************************************************************************
- ** ^FILE: strfuncs.c - Miscellaneous string functions for parseargs
- **
- ** ^DESCRIPTION:
- ** This file implements a wide variety of functions to manipulate
- ** strings in way way or another. Some of the functions may already
- ** be included in the standard library of some C compilers.
- **
- ** The following functions are implemented:
- **
- ** strucpy() -- copy a string and map to uppercase
- ** strlcpy() -- copy a string and map to lowercase
- ** strupr() -- convert a string to uppercase
- ** strlwr() -- convert a string to lowercase
- ** strdup() -- return a (newly allocated) copy of a string
- ** strpbrk() -- return first occurrence of character in a set
- ** strspn() -- return length of initial prefix of a character set
- ** strcspn() -- return length of initial prefix of a character set
- ** strltrim() -- trim leftmost (leading) characters in a string
- ** strrtrim() -- trim rightmost (trailing) characters in a string
- ** strtrim() -- trim leading and trailing characters in a string
- ** strsplit() -- split a string up into a vector of tokens
- ** strjoin() -- join a vector of token into a single string
- ** get_name() -- return the aname (argument-name) of an argument
- ** get_keyword() -- return the sname (keyword-name) of an argument
- ** match() -- match two keywords (case insensitive) upto a unique prefix
- ** stricmp() -- case insensitive comparison of strings
- ** strnicmp() -- case insensitive length-limited comparison of strings
- ** basename() -- remove the leading directories (and disks) from a path
- ** indent_para() -- print an indented hanging paragraph
- **
- ** ^HISTORY:
- ** 01/02/91 Brad Appleton <brad@ssd.csd.harris.com> Created
- ** - changed from file misc.c to this name and added all of the strxxx
- ** functions (plus got rid of some unused functions).
- **
- ** --/--/-- Peter da Silva <peter@ferranti.com>
- **
- ** --/--/-- Eric P. Allman <eric@Berkeley.EDU> Created
- ***^^**********************************************************************/
- X
- #include <stdio.h>
- #include <ctype.h>
- #include <useful.h>
- X
- EXTERN VOID syserr ARGS((const char *, ...));
- X
- static CONST char WhiteSpace[] = " \t\n\r\v\f";
- X
- X
- #if ( defined(unix_style) || defined(ibm_style) )
- # define TO_KWDCASE(c) TOLOWER(c)
- #else
- # define TO_KWDCASE(c) TOUPPER(c)
- #endif
- X
- X
- /***************************************************************************
- ** ^FUNCTION: strucpy, strlcpy - copy dest to src, mapping to upper/lower case
- **
- ** ^SYNOPSIS:
- **
- ** char *strucpy( dest, src )
- ** char *strlcpy( dest, src )
- **
- ** ^PARAMETERS:
- ** char *dest;
- ** -- the address to start copying to
- **
- ** char *src;
- ** -- the address to start copying from
- **
- ** ^DESCRIPTION:
- ** Strlcpy (strucpy) copies src into dest (upto and including the
- ** terminating NUL byte) and all uppercase (lowercase) characters in
- ** src are mapped to lowercase (uppercase) before being copied into dest.
- **
- ** ^REQUIREMENTS:
- ** Dest must be non-null, and large enough to hold the copied result.
- **
- ** ^SIDE-EFECTS:
- ** Dest is (re)written
- **
- ** ^RETURN-VALUE:
- ** Address of dest.
- **
- ** ^ALGORITHM:
- ** Trivial.
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X char *strucpy( char *dest, const char *src )
- #else
- X char *strucpy( dest, src ) char *dest, *src;
- #endif
- {
- X register char *s1 = dest;
- X register CONST char *s2 = src;
- X
- X if ( !s2 ) return CHARNULL;
- X
- X for ( ; *s2 ; s1++, s2++ ) {
- X *s1 = TOUPPER( *s2 );
- X }
- X *s1 = '\0';
- X
- X return s1;
- }
- X
- X
- #ifdef __ANSI_C__
- X char *strlcpy( char *dest, const char *src )
- #else
- X char *strlcpy( dest, src ) char *dest, *src;
- #endif
- {
- X register char *s1 = dest;
- X register CONST char *s2 = src;
- X
- X if ( !s2 ) return CHARNULL;
- X
- X for ( ; *s2 ; s1++, s2++ ) {
- X *s1 = TOLOWER( *s2 );
- X }
- X *s1 = '\0';
- X
- X return s1;
- }
- X
- X
- /***************************************************************************
- ** ^FUNCTION: strupr, strlwr - convert a string to all upper/lower case
- **
- ** ^SYNOPSIS:
- ** char *strupr( str )
- ** char *strlwr( str )
- **
- ** ^PARAMETERS:
- ** char *str;
- ** -- the string to be converted
- **
- ** ^DESCRIPTION:
- ** Strupr (strlwr) converts all lowercase (uppercase) characters in <str>
- ** to uppercase (lowercase) and returns the address of <str>.
- **
- ** ^REQUIREMENTS:
- ** str should be non-null and non-empty.
- **
- ** ^SIDE-EFECTS:
- ** str is overwritten with the uppercase (lowercase) result.
- **
- ** ^RETURN-VALUE:
- ** Address of str.
- **
- ** ^ALGORITHM:
- ** Trivial.
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X char *strupr( char *str )
- #else
- X char *strupr( str ) char *str;
- #endif
- {
- X char *p = str;
- X
- X for ( ; p && *p ; p++ ) {
- X if ( islower(*p) ) *p = toupper(*p);
- X }
- X
- X return str;
- }
- X
- X
- #ifdef __ANSI_C__
- X char *strlwr( char *str )
- #else
- X char *strlwr( str ) char *str;
- #endif
- {
- X char *p = str;
- X
- X for ( ; p && *p ; p++ ) {
- X if ( isupper(*p) ) *p = tolower(*p);
- X }
- X
- X return str;
- }
- X
- X
- /***************************************************************************
- ** ^FUNCTION: stricmp, strnicmp - case insensitive string comparison
- **
- ** ^SYNOPSIS:
- ** int stricmp( s1, s2 )
- ** int strnicmp( s1, s2, n )
- **
- ** ^PARAMETERS:
- ** char *s1;
- ** -- first string to compare
- **
- ** char *s2;
- ** -- second string to compare
- **
- ** size_t n;
- ** -- The number of characters to compare
- **
- ** ^DESCRIPTION:
- ** Stricmp (strnicmp) is identical to strcmp (strncmp) except that it
- ** it performs a case-insensitive comparison of characters.
- **
- ** ^REQUIREMENTS:
- ** Both s1 and s2 should be non-null and non-empty
- **
- ** ^SIDE-EFECTS:
- ** None.
- **
- ** ^RETURN-VALUE:
- ** < 0 if s1 < s2
- ** = 0 if s1 matches s2
- ** > 0 if s1 > s2
- **
- ** ^ALGORITHM:
- ** Trivial.
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X int stricmp( const char *str1, const char *str2 )
- #else
- X int stricmp( str1, str2 ) char *str1, *str2;
- #endif
- {
- X register CONST char *s1 = str1, *s2 = str2;
- X register char c1, c2;
- X
- X if ( s1 == s2 ) return 0;
- X if ( !s1 ) return -1;
- X if ( !s2 ) return 1;
- X
- X for ( ; *s1 && *s2 ; s1++ , s2++ ) {
- X c1 = TOLOWER( *s1 );
- X c2 = TOLOWER( *s2 );
- X
- X if (c1 != c2) return (int)(c1 -c2);
- X }
- X return (*s1 == *s2) ? 0 : (int)(*s1 - *s2);
- }
- X
- X
- #ifdef __ANSI_C__
- X int strnicmp( const char *str1, const char *str2, size_t len )
- #else
- X int strnicmp( str1, str2, len ) char *str1, *str2; size_t len;
- #endif
- {
- X register CONST char *s1 = str1, *s2 = str2;
- X register char c1, c2;
- X
- X if ( s1 == s2 ) return 0;
- X if ( !s1 ) return -1;
- X if ( !s2 ) return 1;
- X
- X for ( ; *s1 && *s2 && len ; s1++ , s2++ , len-- ) {
- X c1 = TOLOWER( *s1 );
- X c2 = TOLOWER( *s2 );
- X
- X if (c1 != c2) return (int)(c1 -c2);
- X }
- X return (*s1 == *s2) ? 0 : (int)(*s1 - *s2);
- }
- X
- X
- #ifdef BSD
- X
- /***************************************************************************
- ** ^FUNCTION: strdup - copy a string
- **
- ** ^SYNOPSIS:
- */
- # ifndef __ANSI_C__
- X char *strdup( str )
- /*
- ** ^PARAMETERS:
- */
- X char *str;
- /* -- the string to replicate
- */
- # endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** Strdup allocates storrage and copies the given string into the
- ** newly acquired space (returning its address). The returned result
- ** should be deallocated using free().
- **
- ** ^REQUIREMENTS:
- ** str should be non-null
- **
- ** ^SIDE-EFFECTS:
- ** None.
- **
- ** ^RETURN-VALUE:
- ** Address of the newly allocated string.
- **
- ** ^ALGORITHM:
- ** Trivial.
- ***^^**********************************************************************/
- # ifdef __ANSI_C__
- X char *strdup( const char *str )
- # endif
- {
- X unsigned len = strlen(str) + 1;
- X char *p = malloc( len * sizeof(char) );
- X
- X if ( !p ) syserr( "Fatal Error -- out of memory" );
- X strcpy(p, str);
- X
- X return p;
- }
- X
- X
- /***************************************************************************
- ** ^FUNCTION: strpbrk - return the first occurrence of characters in a string
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X char *strpbrk( str1, str2 )
- /*
- ** ^PARAMETERS:
- */
- X char *str1;
- /* -- the string to be searched
- */
- X char *str2;
- /* -- the set of characters to be located
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** Strpbrk will attempt to locate the first occurence in str1 of any
- ** character from str2 and return the address of the first such
- ** occurrence. If str1 contains NO characters from str2, then NULL
- ** is returned.
- **
- ** ^REQUIREMENTS:
- ** Both str1 and str2 should be non-null and non-empty
- **
- ** ^SIDE-EFECTS:
- ** None.
- **
- ** ^RETURN-VALUE:
- ** A pointer to the first occurence in str1 of any char from str2.
- **
- ** ^ALGORITHM:
- ** - foreach char in str1
- ** - if char is in str2, return the address of char
- ** end-for
- ** - if we have reached the end of str1, return NULL
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X char *strpbrk( const char *str1, const char *str2 )
- #endif
- {
- X register CONST char *s1 = str1, *s2 = str2;
- X
- X if ( !s1 || !*s1 || !s2 || !*s2 ) return CHARNULL;
- X
- X for ( ; *s1 ; s1++ ) {
- X if ( strchr(s2, *s1) ) return (char *)s1;
- X }
- X
- X return CHARNULL;
- }
- X
- X
- /***************************************************************************
- ** ^FUNCTION: strspn, strcspn - identify leading runs of characters
- **
- ** ^SYNOPSIS:
- ** char *strspn( str1, str2 )
- ** char *strcspn( str1, str2 )
- **
- ** ^PARAMETERS:
- ** char *str1;
- ** -- the string to be searched
- **
- ** char *str2;
- ** -- the string to be searched
- **
- ** ^DESCRIPTION:
- ** Strspn (strcspn) attempts to determine the length of the longest
- ** leading prefix of str1 that consists entirely of character from
- ** (not from) str2.
- **
- ** ^REQUIREMENTS:
- ** Both str1 and str2 should be non-null and non-empty.
- **
- ** ^SIDE-EFECTS:
- ** None.
- **
- ** ^RETURN-VALUE:
- ** The length of the initial prefix in str1 consisting entirely
- ** of characters from (not from) str2.
- **
- ** ^ALGORITHM:
- ** - length = 0
- ** - for each char in str1
- ** - if char is in str2 (for strcspn) or not in str2 (for strcspn)
- ** then return length
- ** - else
- ** add 1 to length
- ** end-if
- ** end-for
- ** - if end-of-string then return length
- **
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X int strspn( const char *str1, const char *str2 )
- #else
- X int strspn( str1, str2 ) char *str1, *str2;
- #endif
- {
- X register CONST char *s1 = str1, *s2 = str2;
- X int len = 0;
- X
- X if ( !s1 || !*s1 || !s2 || !*s2 ) return 0;
- X while ( *s1 && strchr(s2, *s1++) ) ++len;
- X return len;
- }
- X
- X
- #ifdef __ANSI_C__
- X int strcspn( const char *str1, const char *str2 )
- #else
- X int strcspn( str1, str2 ) char *str1, *str2;
- #endif
- {
- X register CONST char *s1 = str1, *s2 = str2;
- X int len = 0;
- X
- X if ( !s1 || !*s1 || !s2 || !*s2 ) return 0;
- X while ( *s1 && !strchr(s2, *s1++) ) ++len;
- X return len;
- }
- X
- #endif /* BSD */
- X
- X
- /***************************************************************************
- ** ^FUNCTION: strltrim, strrtrim, strtrim - trim leading/trailing characters
- **
- ** ^SYNOPSIS:
- ** char *strltrim( str, charset )
- ** char *strrtrim( str, charset )
- ** char *strtrim( str, charset )
- **
- ** ^PARAMETERS:
- ** char *str;
- ** -- the string to be trimmed
- **
- ** char *charset;
- ** -- the set of characters to be trimmed
- **
- ** ^DESCRIPTION:
- ** Strltrim removes from str, all leftmost (leading) characters occurring
- ** in charset.
- **
- ** Strrtrim removes from str, all rightmost (trailing) characters occurring
- ** in charset.
- **
- ** Strtrim removes from str, all leading and trailing characters occurring
- ** in charset.
- **
- ** For each of these functions, if charset is NULL or empty, then the set
- ** of whitespace characters (space, tab, newline, carriage-return, form-feed
- ** and vertical-tab) is assumed.
- **
- ** ^REQUIREMENTS:
- ** str should be non-null and non-empty.
- **
- ** ^SIDE-EFECTS:
- ** characters may be removed from the beginning and/or end of str.
- **
- ** ^RETURN-VALUE:
- ** Address of str.
- **
- ** ^ALGORITHM:
- ** Trivial.
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X char *strltrim( char *str, const char *charset )
- #else
- X char *strltrim( str, charset ) char *str, *charset;
- #endif
- {
- X register int i;
- X
- X if ( !str || !*str ) return str;
- X /* if delim-string is NULL, whitespace is used */
- X if ( !charset ) charset = WhiteSpace;
- X
- X i = strspn( str, charset );
- X if ( i > 0 ) strcpy( str, &(str[i]) );
- X
- X return str;
- }
- X
- X
- #ifdef __ANSI_C__
- X char *strrtrim( char *str, const char *charset )
- #else
- X char *strrtrim( str, charset ) char *str, *charset;
- #endif
- {
- X register int i;
- X
- X if ( !str || !*str ) return str;
- X if ( !charset ) charset = WhiteSpace;
- X for ( i = strlen(str) - 1 ;
- X ( i >= 0 ) && (strchr( charset, str[i] )) ;
- X i--
- X ) ;
- X
- X str[i+1] = '\0';
- X
- X return str;
- }
- X
- X
- #ifdef __ANSI_C__
- X char *strtrim( char *str, const char *charset )
- #else
- X char *strtrim( str, charset ) char *str, *charset;
- #endif
- {
- X register int i;
- X
- X if ( !str || !*str ) return str;
- X if ( !charset ) charset = WhiteSpace;
- X i = strspn( str, charset );
- X if ( i > 0 ) strcpy( str, &(str[i]) );
- X
- X for ( i = strlen(str) - 1 ;
- X ( i >= 0 ) && (strchr( charset, str[i] )) ;
- X i--
- X ) ;
- X
- X str[i+1] = '\0';
- X
- X return str;
- }
- X
- X
- /***************************************************************************
- ** ^FUNCTION: strsplit - split a string into tokens
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X int strsplit( vec, token_str, separators )
- /*
- ** ^PARAMETERS:
- */
- X char **vec[];
- /* -- pointer to the string vector to be allocated
- */
- X char token_str[];
- /* -- the string to be split up
- */
- X char separators[];
- /* -- the delimiters that separate tokens
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** Strsplit will split token_str up into a vector of tokens that are
- ** separated by one or more characters from <separators>. The number
- ** of tokens found is returned and storage is allocated for the given
- ** vector (which may later be deallocated using free()).
- **
- ** If <separators> is NULL or empty, then the set of whitespace characters
- ** is used as the token delimiters.
- **
- ** ^REQUIREMENTS:
- ** vec must be non-NULL (it must be a valid address).
- ** token_str should be non-null and non-empty
- **
- ** ^SIDE-EFECTS:
- ** All leading and trailing characters from <separators> are removed
- ** from token_str. Furthermore, all remaining sequences in token_str
- ** of characters from <separators> are replaced with a single NUL-byte.
- **
- ** Token_str holds the actual storage for all the strings in the newly
- ** created vector.
- **
- ** ^RETURN-VALUE:
- ** The number of tokens parsed.
- **
- ** ^ALGORITHM:
- ** - count the number of tokens present while at the same time removing
- ** all leading and trailing delimiters, and replacing all other sequences
- ** of delimiters with the NUL character.
- ** - allocate a vector large enough to point to all the token strings.
- ** - for i in 0 .. (numtokens - 1) do
- ** - vector[i] = token_str
- ** - advance token_str to point at the next character past the
- ** righmost NUL-byte (which should be the start of the next token).
- ** end-for
- ** - return the number of tokens parsed.
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X int strsplit( char **vec[], char token_str[], const char separators[] )
- #endif
- {
- X register char c, *pread, *pwrite;
- X int i, count = 0;
- X
- X if ( !token_str ) return 0;
- X /* if delim-string is NULL, whitespace is used */
- X if ( !separators ) separators = WhiteSpace;
- X
- X /* trim leading separators */
- X pread = token_str;
- X while ( strchr(separators, *pread) ) ++pread;
- X token_str = pwrite = pread;
- X
- X /*
- X ** make first pass through string, counting # of tokens and
- X ** separating all tokens by a single '\0'
- X */
- X while ( c = *pread++ ) {
- X if ( !strchr(separators, c) ) {
- X *pwrite++ = c;
- X }
- X else {
- X *pwrite++ = '\0'; /* null terminate this token */
- X ++count; /* update token count */
- X while ( strchr(separators, *pread) ) ++pread;
- X }
- X }/*while*/
- X if ( *(pwrite - 1) ) {
- X ++count; /* dont forget last token */
- X *pwrite = '\0'; /* null-terminate */
- X }
- X
- X /* allocate space for the caller's vector (remember NULL at the end) */
- X (*vec) = (char **)malloc( (1 + count) * sizeof( char * ) );
- X if ( !*vec ) {
- X fprintf( stderr, "out of memory in strsplit() - aborting\n" );
- X exit( -1 );
- X }
- X
- X /* now go thru token-string again assigning pointers from vector */
- X pread = token_str;
- X for ( i = 0 ; i < count ; i++ ) {
- X (*vec)[i] = pread; /* assign pointer */
- X pread += strlen( pread ) + 1;
- X }/* end-for */
- X
- X /* set up the trailing pointer to NULL at the end */
- X (*vec)[ count ] = CHARNULL;
- X return count;
- }
- X
- X
- /***************************************************************************
- ** ^FUNCTION: strjoin - join a vector of tokens together
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X char *strjoin( argv, separator )
- /*
- ** ^PARAMETERS:
- */
- X char *argv[];
- /* -- pointer to the string vector to join together
- */
- X char separator[];
- /* -- the the string to use to separate tokens (if NULL, " " is used)
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** Strjoin will make a single string out of the given vector by copying
- ** all the tokens from the given vector (in order) toa newly allocated
- ** string. Each token will be separated by an occurence of <separator>.
- **
- ** If <separator> is NULL then a single space is used as the separator.
- ** If <separator> is empty, then no separator is used and the tokens are
- ** simply concatenated together.
- **
- ** ^REQUIREMENTS:
- ** argv must be non-NULL (it must be a valid address), and must be terminated
- ** by a pointer to NULL (argv[last+1] == NULL).
- **
- ** ^SIDE-EFECTS:
- ** Storage is allocated.
- **
- ** ^RETURN-VALUE:
- ** The addres of the newly-joined results (which should be deallocated
- ** using free()). Returns NULL if nothing was joined.
- **
- ** ^ALGORITHM:
- ** - count the number of characters to place in the joined-result.
- ** - allocate a string large-enough to copy the joined-result into.
- ** - copy each string into the string (with <separator> between tokens).
- ** - 0 return the result.
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X char *strjoin( const char *argv[], const char separator[] )
- #endif
- {
- X size_t sz = 0;
- X register char *p;
- X register CONST char *a, **av;
- X register int seplen;
- X char *result;
- X
- X /* if argv is NULL, nothing to do */
- X if ( !argv ) return CHARNULL;
- X if ( !separator ) separator = " ";
- X seplen = strlen( separator );
- X
- X /* figure out how much space we need */
- X for ( av = argv ; *av ; av++ ) {
- X if ( !**av ) continue;
- X sz += strlen( *av );
- X if ( seplen && *(av + 1) ) sz += seplen;
- X }
- X
- X /* allocate space */
- X result = (char *)malloc( (sz + 1) * sizeof(char) );
- X if ( !result ) syserr( "malloc failed in strjoin()" );
- X
- X /* join the strings together */
- X *result = '\0';
- X for ( av = argv, p = result ; (a = *av) ; av++ ) {
- X if ( !*a ) continue;
- X while ( (*p = *a++) ) ++p; /* copy token */
- X if ( seplen && *(av + 1) ) {
- X a = separator;
- X while ( (*p = *a++) ) ++p; /* copy separator */
- X }/*end-if*/
- X }/*end-for*/
- X
- X return result;
- }
- X
- X
- /***************************************************************************
- ** ^FUNCTION: get_name - return the aname (argument-name) of an argument
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X char *get_name( s, buf )
- /*
- ** ^PARAMETERS:
- */
- X char *s;
- /* -- the ad_prompt field of an ARGDESC struct
- */
- X char *buf;
- /* -- address to which the aname should be copied
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** Get_name will get the full argument name of the given argument
- ** (not just the keyword name) and copy it to buf.
- **
- ** ^REQUIREMENTS:
- ** Both s and buf must be non-null and non-empty.
- ** buf must be large enough to hold the result.
- **
- ** ^SIDE-EFECTS:
- ** buf is overwritten.
- **
- ** ^RETURN-VALUE:
- ** Address of the buffer containing the name.
- **
- ** ^ALGORITHM:
- ** determine the name of an argument from its prompt
- ** and copy the result in the given buffer
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X char *get_name( const char *s, char *buf )
- #endif
- {
- X /* <buf> must be large enough to hold the result! */
- X strlcpy(buf, s);
- X return buf;
- }
- X
- X
- /***************************************************************************
- ** ^FUNCTION: get_keyword - get the sname (keyword name) of an argument
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X char *get_keyword( s, buf )
- /*
- ** ^PARAMETERS:
- */
- X char *s;
- /* -- the ad_prompt field of an ARGDESC struct
- */
- X char *buf;
- /* -- address to which the sname should be copied
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** Get_name will get the keyword name of the given argument
- ** (not the entire argument name) and copy it to buf.
- **
- ** The sname (keyword-name) consists only of all uppercase characters
- ** from the ad_prompt field (in the order they occur). If the ad_prompt
- ** field contains NO uppercase characters, than the aname and the sname
- ** are equivalent (the entire string).
- **
- ** ^REQUIREMENTS:
- ** Both s and buf must be non-null and non-empty.
- ** buf must be large enough to hold the result.
- **
- ** ^SIDE-EFECTS:
- ** buf is overwritten.
- *
- ** ^RETURN-VALUE:
- ** Address of the buffer containing the keyword.
- **
- ** ^ALGORITHM:
- ** determine the keyword of an argument from its prompt
- ** and copy the result in the given buffer
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X char *get_keyword( const char *s, char *buf )
- #endif
- {
- X register char *p1 = (char *)s, *p2;
- X register int i, len = 0;
- X char *caps = CHARNULL;
- X
- X if ( !p1 ) return CHARNULL;
- X
- X /* find size to copy (use all caps if possible) */
- X for ( p1 = (char *)s ; *p1 ; p1++ ) {
- X if ( !caps && isupper( *p1 ) ) caps = p1;
- X if ( caps && isupper( *p1 ) ) ++len;
- X }
- X if ( !caps ) len = (int) (p1 - (char *)s);
- X
- X /* copy string into buffer and convert it to desired case */
- X /* <buf> must be large enough to hold the result! */
- X p1 = buf;
- X if ( len ) {
- X if ( !caps ) {
- X for ( p1 = buf, p2 = (char *)s, i = 0 ; i < len ; p1++, p2++, i++ ) {
- X *p1 = TO_KWDCASE(*p2);
- X }
- X }/*if*/
- X
- X else {
- X for ( p2 = caps, i = 0 ; i < len ; p2++ ) {
- X if ( isupper( *p2 ) ) {
- X *(p1++) = TO_KWDCASE(*p2);
- X ++i;
- X }
- X }/*for*/
- X }/*else*/
- X }/*if*/
- X *p1 = '\0';
- X
- X return buf; /* return buffer address */
- }
- #ifndef amiga_style
- X
- /***************************************************************************
- ** ^FUNCTION: match - match a keyword against a prospective argument
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X int match( candidate, target )
- /*
- ** ^PARAMETERS:
- */
- X char *candidate;
- /* -- the possible keyword argument
- */
- X char *target;
- /* -- the keyword to be matched
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** Match will attempt to see if the candidate string matches the
- ** target string (case insensitive). First a match is tried on the
- ** sname of the keyword, then on the aname. Candidate may be only
- ** a partial leading portion of the target as long as it is at least
- ** two characters long (unless the keyword is 1 character long).
- **
- ** No "partial" matching is accepted for AmigaDOS command-lines.
- **
- ** ^REQUIREMENTS:
- ** Both candidate and target should be non-null and non-empty.
- ** target should be the ad_prompt field of an ARGDESC structure.
- **
- ** ^SIDE-EFECTS:
- ** None.
- **
- ** ^RETURN-VALUE:
- * < 0 if candidate < target
- ** = 0 if candidate matches target
- ** > 0 if candidate > target
- **
- ** ^ALGORITHM:
- ** - attempt a partial match against the sname and return 0 if we succeed
- ** - attempt a partial match against the aname and return 0 if we succeed
- ** - if both the above fail return non-zero (no match).
- **
- ***^^**********************************************************************/
- X
- /* rewritten 8/20/90 --BDA */
- #define MINLEN 2 /* minimum # of characters to match */
- X
- #ifdef __ANSI_C__
- X int match ( const char *candidate, const char *target )
- #endif
- {
- X int i, clen, tlen, too_short=0;
- X CONST char *full_targ;
- X char *up_targ;
- X
- X
- X full_targ = target;
- X
- X /* make up_targ the uppercase portion of target */
- X up_targ = strdup( full_targ );
- X (VOID) get_keyword( full_targ, up_targ );
- X
- X /* match at least MINLEN characters if possible */
- X tlen = strlen( up_targ );
- X clen = strlen( candidate );
- X if ( (tlen >= MINLEN) && (clen < MINLEN) ) {
- X ++too_short; /* not long enough -- no match */
- X }
- X
- #ifdef vms_style
- X /* if first two chars are NO then match at least MINLEN+2 chars */
- X if ( !strnicmp(up_targ, "NO", 2) ) {
- X if ( (tlen >= (MINLEN + 2)) && (clen < (MINLEN + 2)) ) {
- X ++too_short; /* not long enough -- no match */
- X }
- X }
- #endif
- X
- X /* first try to match prefix of the uppercase portion */
- X i = (too_short) ? -1 : strnicmp(up_targ, candidate, clen);
- X
- X free( up_targ );
- X
- X /* did we match? */
- X if ( !i ) return 0; /* yes! */
- X
- X /* no! : compare the whole target
- X ** match at least MINLEN characters if possible
- X */
- X tlen = strlen(full_targ);
- X if ( (tlen >= MINLEN) && (clen < MINLEN) ) {
- X return -1; /* not long enough -- no match */
- X }
- X
- #ifdef vms_style
- X /* if first two chars are NO then match at least MINLEN+2 chars */
- X if ( !strnicmp(full_targ, "no", 2) ) {
- X if ( (tlen >= (MINLEN + 2)) && (clen < (MINLEN + 2)) ) {
- X return -1; /* not long enough -- no match */
- X }
- X }
- #endif
- X
- X return strnicmp(full_targ, candidate, clen);
- }
- X
- X
- /* here is the AmigaDOS version of match() */
- #else
- X
- # ifdef __ANSI_C__
- X int match( const char *candidate, const char *target )
- # else
- X int match( candidate, target) char *candidate, *target;
- # endif
- {
- X int i, j;
- X char c;
- X
- X i = j = 0;
- X
- X while ( isgraph(target[i]) || isgraph(candidate[i]) ) {
- X while ( islower(target[i]) ) i++;
- X if ( !isgraph(target[i]) ) {
- X if ( !isgraph(candidate[j]) ) return 0;
- X return stricmp(target, candidate);
- X }
- X c = islower( candidate[j] ) ? toupper(candidate[j]) : candidate[j];
- X if (target[i] != c) return stricmp(target, candidate);
- X i++;
- X j++;
- X }
- X return 0;
- }
- X
- #endif
- X
- X
- /***************************************************************************
- ** ^FUNCTION: basename - return the last component of a pathname
- **
- ** ^SYNOPSIS:
- ** char *basename( path )
- **
- ** ^PARAMETERS:
- ** path;
- ** -- the pathname to be truncated.
- **
- ** ^DESCRIPTION:
- ** Basename takes a pathname and strips of all leading components
- ** (except for the very last one) which refer to directories or
- ** disk-drives.
- **
- ** ^REQUIREMENTS:
- ** path should be non-null, non-empty, and should correspond to a valid
- ** pathname (absolute or relative).
- **
- ** ^SIDE-EFECTS:
- ** None under Unix and AmigaDOS.
- **
- ** Under VMS, the file version is removed and any .COM or .EXE extension
- ** is also removed.
- **
- ** Under MS-DOS, any .EXE, .COM, or .BAT extension is removed.
- **
- ** Under OS/2, any .EXE, .COM, or .CMD extension is removed.
- **
- ** ^RETURN-VALUE:
- ** The address of the basename of the path.
- **
- ** ^ALGORITHM:
- ** Trivial.
- ***^^**********************************************************************/
- X /* should use '\\' for MS-DOS & OS/2 and use ']' for VMS */
- #ifdef vms
- #define PATH_SEP ']'
- X
- X /* VAX/VMS version of basename */
- # ifdef __ANSI_C__
- X char *basename( char path[] )
- # else
- X char *basename( path ) char path[];
- # endif
- X {
- X char *base = strrchr( path, PATH_SEP );
- X char *vers = strrchr( path, ';' );
- X char *ext = strrchr( path, '.' );
- X
- X if ( !base ) {
- X if ( !(base = strrchr( path, ':' )) ) {
- X base = path;
- X }
- X else {
- X ++base;
- X }
- X }
- X else {
- X ++base;
- X }
- X
- X if ( vers ) *vers ='\0';
- X if ( ext && (!stricmp(ext, ".COM") || !stricmp(ext, ".EXE")) ) {
- X ext = '\0';
- X }
- X
- X return base;
- X }
- X
- #else
- #ifdef AmigaDOS
- X /* amiga version of basename() */
- # ifdef __ANSI_C__
- X char *basename( char path[] )
- # else
- X char *basename( path ) char path[];
- # endif
- X {
- X return path;
- X }
- #else
- #define PATH_SEP '/' /* default path-separator character */
- X
- X /* default version of basename() */
- # ifdef __ANSI_C__
- X char *basename( char path[] )
- # else
- X char *basename( path ) char path[];
- # endif
- X {
- X char *base = strrchr( path, PATH_SEP );
- X
- #if ( defined(MSDOS) || defined(OS2) )
- X /* remove the extension from .EXE, .COM, .BAT, and .CMD files */
- # ifdef OS2
- X if ( ext && (!stricmp(ext, ".CMD") ) *ext = '\0';
- # else
- X if ( ext && (!stricmp(ext, ".BAT") ) *ext = '\0';
- # endif
- X
- X if ( ext && (!stricmp(ext, ".COM") || !stricmp(ext, ".EXE")) ) {
- X ext = '\0';
- X }
- #endif
- X
- X if ( !base ) {
- #if ( defined(MSDOS) || defined(OS2) )
- X base = strrchr( path, '\\' );
- X if ( base ) return (base + 1);
- X if ( path[ 1 ] == ':' ) return (path + 2); /* just remove drive */
- X return (base + 1);
- #endif
- X return path;
- X }
- X else {
- X return (base + 1);
- X }
- X }
- #endif
- #endif
- X
- X
- /***************************************************************************
- ** ^FUNCTION: indent_para - print a hanging indented paragraph
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X VOID indent_para(fp, maxcols, margin, title, indent, text)
- /*
- ** ^PARAMETERS:
- */
- X FILE *fp;
- /* -- the stream to which output is sent
- */
- X int maxcols;
- /* -- the maximum width (in characters) of the output
- */
- X int margin;
- /* -- the number of spaces to use as the left margin
- */
- X char *title;
- /* -- the paragraph title
- */
- X int indent;
- /* -- the distance between the title and the paragraph body
- */
- X char *text;
- /* -- the body of the paragraph
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** Indent_para will print on fp, a titled, indented paragraph as follows:
- **
- ** <----------------------- maxcols --------------------------->
- ** <--- margin --> <-- indent -->
- ** title This is the first sentence
- ** of the paragraph. Etc ...
- **
- ** ^REQUIREMENTS:
- ** maxcols and indent must be positive numbers with maxcols > indent
- **
- ** ^SIDE-EFECTS:
- ** Output is printed to fp.
- **
- ** ^RETURN-VALUE:
- ** None.
- **
- ** ^ALGORITHM:
- ** Print the paragraph title and then print the text.
- ** Lines are automatically adjusted so that each one starts in the
- ** appropriate column.
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X void indent_para( FILE *fp, int maxcols, int margin,
- X const char *title, int indent, const char *text )
- #endif
- {
- X register int idx = 0;
- X BOOL first_line = TRUE;
- X int text_len = strlen(text);
- X char ch;
- X
- X /* print the title */
- X fprintf( fp, "%*s%-*s", margin, "", indent, title );
- X
- X idx = maxcols - margin - indent;
- X
- X if ( text_len <= idx )
- X fprintf(fp, "%s\n", text);
- X else
- X do {
- X /* backup to end of previous word */
- X while (idx && !isspace(text[idx])) --idx;
- X while (idx && isspace(text[idx])) --idx;
- X
- X /* print leading whitespace */
- X if (!first_line)
- X fprintf(fp, "%*s%-*s", margin, "", indent, "");
- X
- X ch = text[ ++idx ];
- X *((char *)text + idx) = '\0';
- X fprintf(fp, "%s\n", text);
- X *((char *)text + idx) = ch;
- X first_line = FALSE;
- X text = &(text[idx+1]);
- X text_len -= (idx+1);
- X
- X while (isspace(*text)) { /* goto next word */
- X ++text;
- X --text_len;
- X }
- X
- X idx = maxcols - margin - indent;
- X
- X if ( text_len <= idx ) /* print-last line */
- X fprintf(fp, "%*s%-*s%s\n", margin, "", indent, "", text);
- X } while ( text_len > idx );
- }
- X
- X
- #ifdef STRTEST
- X
- #define WS " \t\n\v\r\f\"'"
- X
- static char string2[] = " oh what a beautiful - morning! ";
- X
- static char string[] = "\n\
- \t' ', ARGREQ, argStr, Name, 'Name',\n\
- \t'n', ARGOPT|ARGLIST, listStr, Groups, 'newsGROUP (newsgroups test)',\n\
- \t'c', ARGOPT, argInt, RepCount, 'REPcount (number of reps)',\n\
- \t'd', ARGOPT, argStr, DirName, 'DIRname',\n\
- \t'x', ARGOPT, argBool, XFlag, 'Xflag (expand in X direction)',\n\
- \t' ', ARGOPT|ARGLIST, listStr, Argv, 'File',\n\
- \tENDOFARGS\n\
- ";
- X
- static char word_str[] = "HELP (print help and quit)";
- X
- main()
- #ifdef __ANSI_C__
- #endif
- {
- X char **vector;
- X unsigned i, numtoks;
- X
- X printf( "test of strtrim() and strsplit():\n\n" );
- X
- X printf( "unparsed string='%s'\n", string2 );
- X printf( "ltrimmed string='%s'\n", strltrim( string2, WS ) );
- X printf( "rtrimmed string='%s'\n", strrtrim( string2, WS ) );
- X
- X numtoks = strsplit( &vector, string, "," );
- X printf( "number of tokens=%d\n", numtoks );
- X for ( i = 0 ; i < numtoks ; i++ ) {
- X printf( "trimmed token[%d] = '%s'\n", i, strtrim( vector[i], WS ) );
- X }
- X
- X exit( 0 );
- }
- X
- #endif
- SHAR_EOF
- chmod 0664 parseargs/strfuncs.c ||
- echo 'restore of parseargs/strfuncs.c failed'
- Wc_c="`wc -c < 'parseargs/strfuncs.c'`"
- test 34399 -eq "$Wc_c" ||
- echo 'parseargs/strfuncs.c: original size 34399, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= parseargs/strfuncs.h ==============
- if test -f 'parseargs/strfuncs.h' -a X"$1" != X"-c"; then
- echo 'x - skipping parseargs/strfuncs.h (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting parseargs/strfuncs.h (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'parseargs/strfuncs.h' &&
- /***************************************************************************
- ** ^FILE: strfuncs.h - string functions
- **
- ** ^DESCRIPTION:
- ** External declarations for the functions implemented in strfuncs.c
- **
- ** ^HISTORY:
- ** 01/07/91 Brad Appleton <brad@ssd.csd.harris.com> Created
- ***^^**********************************************************************/
- X
- #ifndef STRFUNCS_H
- #define STRFUNCS_H
- X
- #include <useful.h>
- X
- EXTERN char *strucpy ARGS(( char *, const char * ));
- EXTERN char *strlcpy ARGS(( char *, const char * ));
- EXTERN char *strupr ARGS(( char * ));
- EXTERN char *strlwr ARGS(( char * ));
- EXTERN int stricmp ARGS(( const char *, const char * ));
- EXTERN int strnicmp ARGS(( const char *, const char *, size_t ));
- X
- #ifdef BSD
- X EXTERN char *strdup ARGS(( const char * ));
- X EXTERN char *strpbrk ARGS(( const char *, const char * ));
- X EXTERN int strspn ARGS(( const char *, const char * ));
- X EXTERN int strcspn ARGS(( const char *, const char * ));
- #endif
- X
- EXTERN char *strltrim ARGS(( char *, const char * ));
- EXTERN char *strrtrim ARGS(( char *, const char * ));
- EXTERN char *strtrim ARGS(( char *, const char * ));
- EXTERN int strsplit ARGS(( char ***, char *, const char * ));
- EXTERN char *strjoin ARGS(( const char **, const char * ));
- EXTERN char *get_name ARGS(( const char *, char * ));
- EXTERN char *get_keyword ARGS(( const char *, char * ));
- EXTERN int match ARGS(( const char *, const char * ));
- EXTERN char *basename ARGS(( char * ));
- EXTERN VOID indent_para ARGS(( FILE *, int, int,
- X const char *, int, const char * ));
- X
- #endif
- SHAR_EOF
- chmod 0664 parseargs/strfuncs.h ||
- echo 'restore of parseargs/strfuncs.h failed'
- Wc_c="`wc -c < 'parseargs/strfuncs.h'`"
- test 1729 -eq "$Wc_c" ||
- echo 'parseargs/strfuncs.h: original size 1729, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= parseargs/syserr.c ==============
- if test -f 'parseargs/syserr.c' -a X"$1" != X"-c"; then
- echo 'x - skipping parseargs/syserr.c (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting parseargs/syserr.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'parseargs/syserr.c' &&
- /*************************************************************************
- ** ^FILE: syserr.c - error-message printing routines
- **
- ** ^DESCRIPTION:
- ** This fill implements various routines for printing diagnostic
- ** messages on standard diagnostic output (stderr). The routines are:
- **
- ** usrerr() -- print message and any system message(s) and return
- ** syserr() -- print message and any system message(s) and exit
- ** eprintf() -- print to stderr and return
- **
- ** ^HISTORY:
- ** 01/02/91 Brad Appleton <brad@ssd.csd.harris.com>
- ** - Changed to use varargs/stdargs
- ** - Added structured comment blocks
- ** - Added eprintf()
- **
- ** --/--/-- Peter da Silva <peter@ferranti.com>
- **
- ** --/--/-- Eric P. Allman <eric@Berkeley.EDU> Created
- ***^^**********************************************************************/
- X
- #include <stdio.h>
- #include <useful.h>
- /* #include <funclist.h> */
- X
- VERSIONID("$Header: syserr.c,v 2.0 89/12/24 00:56:31 eric Exp $");
- X
- extern char *ProgName;
- extern int errno;
- EXTERN int vfprintf ARGS((FILE *, const char *, va_list));
- X
- X
- /***************************************************************************
- ** ^FUNCTION: _error_message - generic message printing routine.
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X static VOID _error_message( format, ap )
- /*
- ** ^PARAMETERS:
- */
- X char *format;
- SHAR_EOF
- true || echo 'restore of parseargs/syserr.c failed'
- fi
- echo 'End of part 9'
- echo 'File parseargs/syserr.c is continued in part 10'
- echo 10 > _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.
-