home *** CD-ROM | disk | FTP | other *** search
- /*-------------------------------- ZGLOB.C (version 1.0) ----------------------*
- *
- * NAME:
- *
- * zglob - Zortech C++ v3.0 command line filename wildcard expansion.
- *
- * SYNOPSIS:
- *
- * int zglob(argc, argv, attr)
- * int *argc; <- pointer to argument.
- * char **argv[]; <- pointer to argument array pointer.
- * int attr; <- file type search attributes.
- *
- * DESCRIPTION:
- *
- * Zglob() expands command line arguments containing '*' and/or '?' into
- * existing file names. The wildcards can be in the file name or extension,
- * but not the path. The function arguments 'argc' and 'argv' are replaced
- * with the expanded argument count and list. Individual wildcard file name
- * arguments are sorted alphabetically in the expanded argument list. The
- * attribute argument is the file attribute of the files to be found. An
- * attribute value of 0 will find all normal files. The attribute bits are
- * defined in <dos.h>.
- *
- * Errors encountered during the expansion process (no match, no memory) are
- * written to ERROR. Zglob() returns a 1 on success, or a 0 on failure.
- *
- * Zglob() uses the Zortech C++ v3.0 library functions findfirst() and
- * findnext(). All other function calls are ANSI compliant. A singly linked
- * list is first built containing pointers to the expanded file names. When
- * the original argument list is exhausted, an array of pointers (argv) to
- * character strings is allocated. The argument pointers in the linked list
- * are then copied to the new argv. A vector of integers, which point to
- * where to old arguments start in the new argv, is also built. The integer
- * vector is used with qsort() to alphabetize individual wildcard arguments.
- *
- * USAGE:
- *
- * main(int argc, char *argv[])
- * {
- * int i;
- * if( !zglob(&argc,&argv,0)) <-- call with 0 attr.
- * return EXIT_FAILURE; <-- an errror occured, bye!
- * for( i=0; i<argc, i++) { ... } <-- as before, but expanded.
- *
- * AUTHOR:
- *
- * Version 1.0 - Jeff Dragovich (09/21/92).
- *
- * ACKNOWLEDGEMENTS:
- *
- * This routine is modeled after, and very similar to GLOB.C, v1.06, written
- * by Bob Kamins (11/28/87).
- *
- * BUGS:
- *
- * Allocated memory is not free()'d when an error occurs.
- * File name expansion is attempted on all arguments containing a wildcard.
- * Old argv and argc are lost forever.
- *
- *-----------------------------------------------------------------------------*/
- #include <stdio.h>
- #include <dos.h>
- #include <string.h>
- #include <stdlib.h>
- #include <io.h>
-
- int glob(int *, char ***, int);
- static int insert(char *);
- static int expand(char *, int);
- static int fcmp( char **, char **);
-
- typedef struct node Node; /* linked list node */
- struct node {
- char *s;
- Node *pn;
- };
-
- #define ERROR stdout /* predefined error output stream */
-
- static struct node *phead; /* pointer to list head */
- static struct node *ptail; /* pointer to list tail */
- static int newc; /* new number of arguments */
- static int *srtz; /* integer array of pointers to elements of */
- /* old arguments start location in new argv */
-
- /*------------------------------------------------------------------- zglob() */
- int zglob(int *argc, char **argv[], int attr)
- {
- int i;
- char **pnew;
- char err[] = "memory allocation error in zglob() : %s\n";
- struct node *pcurr,*pnext;
-
- newc = 0; /* just to make sure */
- phead = NULL;
-
- srtz = (int *)malloc( (*argc+1)*sizeof(int) ); /* integer vector */
- if( srtz == NULL ) {
- fprintf(ERROR,err,"srtz");
- return(0);
- }
-
- for( i=0; i<*argc; i++) { /* expand all arguments */
- srtz[i] = newc;
- if( !expand( (*argv)[i], attr ) ) return(0);
- }
- srtz[*argc] = newc;
-
- pnew = (char **)malloc( newc*sizeof(char *) ); /* new argv */
- if( pnew == NULL ) {
- fprintf(ERROR,err,"pnew");
- return(0);
- }
- for( i=0, pcurr=phead; i<newc; i++) { /* write over to new argv */
- pnew[i] = pcurr->s;
- pnext = pcurr->pn;
- free(pcurr); /* free up node */
- pcurr = pnext;
- }
- *argv = pnew;
-
- /* sort new argv by reference to old argv elements location */
-
- for( i=1; i<*argc; i++)
- qsort( &((*argv)[srtz[i]]), srtz[i+1]-srtz[i], sizeof(char**), fcmp);
- *argc = newc;
- free(srtz);
- return(1);
- }
- /*------------------------------------------------------------------ expand() */
- static int expand( char *argv, int attr)
- {
- int ret;
- struct FIND *pfind;
-
- if( strpbrk(argv,"*?") == NULL ) /* is there a wildcard */
- return( insert(argv) ); /* no, but add to list */
-
- pfind = findfirst(argv,attr); /* attempt to expand */
- if( pfind == NULL ) {
- fprintf(ERROR,"%s : No Match\n",argv); /* must be a "no match" */
- return(0); /* go back with error */
- }
- while( pfind != NULL ) { /* loop until no more matches */
- ret = insert(pfind->name); /* put expanded name in list */
- if ( !ret ) return(ret); /* must be a malloc error in insert() */
- pfind = findnext(); /* get next match */
- }
- return(1); /* everything ok */
- }
- /*------------------------------------------------------------------ insert() */
- static int insert(char *str)
- {
- char *p;
- struct node *nptr;
-
- p = (char *) malloc( strlen(str) + 1 ); /* new argv[i] */
- nptr = (struct node *)malloc( sizeof(struct node) ); /* get node */
- if( (p==NULL) || (nptr==NULL) ) { /* no memory */
- fprintf(ERROR,"memory allocation failure in glob()->insert()\n");
- return(0);
- }
- strcpy(p,str); /* copy over to heap */
- newc++; /* another argument */
-
- if( phead == NULL ) phead = nptr; /* update linked list */
- else ptail->pn = nptr;
- ptail = nptr;
- ptail->pn = NULL;
- ptail->s = p;
- return(1);
- }
- /*-------------------------------------------------------------------- fcmp() */
- static int fcmp( char **a, char **b ) /* used by qsort */
- {
- return( strcmp(*a,*b) );
- }
-