Path: utzoo!utgpu!water!watmath!clyde!rutgers!sdcsvax!ucbvax!agate!violet.berkeley.edu!dean From: dean@violet.berkeley.edu (Dean Pentcheff) Newsgroups: comp.sys.ibm.pc Subject: Re: A Turbo C Question Summary: Routine enclosed. Message-ID: <6791@agate.BERKELEY.EDU> Date: 30 Jan 88 22:01:50 GMT References: <1282@nmtsun.nmt.edu> Sender: usenet@agate.BERKELEY.EDU Reply-To: dean@violet.berkeley.edu.UUCP (Dean Pentcheff) Followup-To: comp.sys.ibm.pc Organization: University of California, Berkeley Department of Zoology Lines: 169 In article <1282@nmtsun.nmt.edu> greg@nmtsun.UUCP (Greg Lindhorst) writes: >I have a stupid question to ask. How can one get Turbo C to expand >wild carded arguments on the command line? Well, there may be a better way to do it than the way I did it, but I couldn't find it. I did look at the assembly code for the C0x.c startup routines, and there was no trace of an option to do filename expansion. The elegant way to do things would be to rewrite those asm routines to do it. I'm lazy, though, so here's what I wrote: a routine which will filename expand an argv-type list of strings. Call it early on in your program (before processing arguments). It will allocate memory using malloc() as it sees fit. See other documentation in the comments at the top of the file. Have fun. Note: this is not a shar file, just text. --------- cut here (and check for a .signature at the end) ------------------- /* * glob.c * N. Dean Pentcheff 1/88 * dean@violet.berkeley.edu * * Do global filename expansion on an array of pointers to char. * * The Turbo startup routine groups any "double quoted" arguments together. * This routine does not filename expand any 'single quoted' argument or * group of arguments. It suppresses the single quotes. * * Prototype: int glob( char ** , char *** ) * * Argument: Expects an argv-like pointer to pointers to characters, and the * address of another argv-like pointer for the new replacement * globbed list. Doesn't touch first arg, clobbers second. The * two arguments may, in fact, be the same. For example: * argc = glob(argv, &argv); * will just glob and replace the original argv and argc. * * Returns: The number of (non-NULL) pointers in the new list. * * Limits: May filename-expand up to a (silently enforced) limit of * 200 arguments. Uses malloc() to get memory: if memory runs * out, exit(1) is called after a perror() message is printed. * Note: Compile using -DTESTPROG for a demo/test version including * a main(). See end of this file. */ #include #include #include #include #include #include #include #define MAXARGS 200 void docopy(char **, char *); void doglob(char ***, char *, char **); int glob(args, newlist) char **args; /* input pointer to pointers to characters */ char ***newlist; /* output pointer to pointer to pointers to char */ { char **cpp; /* used to step through the argument args */ char **new; /* list to return to caller built on this */ char *cp; /* general purpose character pointer */ int inquote; /* record if we're inside 'quoted' area */ /* Try to get memory for the new array of pointers to characters */ if ((new=*newlist=(char **)malloc(sizeof(char *)*(MAXARGS+1))) == NULL) { perror("glob"); exit(1); } /* Step through the argument array, globbing as required */ inquote = 0; for (cpp = args; (new-(*newlist)) < MAXARGS && *cpp != NULL; ++cpp) { if (inquote == 1) { /* in quoted area */ cp = *cpp; if (*cp && *(cp=(cp+strlen(cp)-1))=='\'') { /* ending? */ *cp = '\0'; /* suppress quote */ inquote = 0; } if (**cpp) /* don't create 0-length arguments */ docopy(new++, *cpp); } else { /* not in quoted area */ if (**cpp == '\'') { /* starting quote? */ for (cp=*cpp; *cp; ++cp) /* suppress quote */ *cp = *(cp+1); inquote = 1; cp = *cpp; if (*cp && *(cp=(cp+strlen(cp)-1))=='\'') { /* ending? */ *cp = '\0'; /* suppress quote */ inquote = 0; } if (**cpp) /* don't create 0-length arguments */ docopy(new++, *cpp); } else { /* not quoted, so try globbing */ doglob(&new, *cpp, *newlist); } } } *new = NULL; return((int) (new - (*newlist))); } static void doglob(dest, str, base) char ***dest; /* pointer to new array of pointers to characters */ char *str; /* string to glob */ char **base; /* beginning of new array of pointers to characters */ { struct ffblk ffb; /* DOS file structure */ char *cp; /* general purpose character pointer */ if (findfirst(str, &ffb, 0) < 0) { docopy((*dest)++, str); /* no glob matches, just copy arg */ } else do { docopy(*dest, ffb.ff_name); /* copy this globbed filename match */ for (cp = **dest; *cp; ++cp) /* lowercase it */ *cp = tolower(*cp); ++(*dest); /* increment output array */ } while ((*dest - base) < MAXARGS && findnext(&ffb) == 0); return; } static void docopy(cp1, cp2) char **cp1; char *cp2; { if ((*cp1 = (char *)malloc(strlen(cp2)+1)) == NULL) { /* get memory */ perror("glob docopy"); exit(1); } else { strcpy(*cp1, cp2); /* copy the string into it */ } return; } #ifdef TESTPROG /* * Mainline test program. To use, compile using: * tcc -otryglob -DTESTPROG glob.c * NDP 1/88 */ void main(argc, argv) int argc; char **argv; { int nargc; char **nargv; nargc = glob(argv, &nargv); printf("Originally, %d arguments. Finally, %d arguments.\n\n", argc, nargc); while (*nargv != NULL) { printf("%s\n", *nargv++); } } #endif TESTPROG ----------------- Dean Pentcheff (dean@violet.berkeley.edu) ----------------- "A university is a place where people pay high prices for goods which they then proceed to leave on the counter when they go out of the store." Loren Eiseley