Xref: utzoo alt.msdos.programmer:558 comp.sys.ibm.pc:36966 Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!wuarchive!gem.mps.ohio-state.edu!usc!srhqla!quad1!few From: few@quad1.quad.com (Frank Whaley) Newsgroups: alt.msdos.programmer,comp.sys.ibm.pc Subject: Turbo C wildcard expansion Keywords: TurboC wildcard Message-ID: <3574@gouda.quad.com> Date: 25 Oct 89 21:43:24 GMT Organization: Quadratron Systems, Westlake Village, CA Lines: 372 /* * setargv.c -> parse arguments * * This code evolved out of a requirement for expansion of wild-card * arguments given on the command line. Turbo C's wildarg.obj * actually produces a reference to __wildargv, which still doesn't * do the job I needed (for example, directory names are not * expanded). * * This version both expands wild-card arguments and converts them * to lower case (a cosmetic thing for me). Arguments that are * quoted (with either " or ') are left alone, but the quote * characters are stripped. A leading quote may be escaped with * a backslash (\" or \'). Quotes within arguments (ARG="a b c") * are not handled in the Un*x fashion. If no matching filename * is found, the argument is passed unchanged. * * Two conditional-compilation flags are provided: * FIXARG0: convert argv[0] to lower case and switch * all backslashes to slashes (cosmetic) * SORTARGS: use qsort() to sort the expansions of * each argument * * Further enhancements greatly appreciated. * * This code placed in the public domain on October 25, 1989 by * its original author, Frank Whaley. */ #define MAXARG 1024 /* max arguments */ #include #include #include #include #include #include /* let's do some things with macros... */ #define ISQUOTE(c) (((c)=='"')||((c)=='\'')) #define ISBLANK(c) (((c)==' ')||((c)=='\t')) static char *cl; /* -> local copy of command line */ /* the following are used by run-time startup (c0?.obj) */ extern int _argc; /* number of args */ extern char **_argv; /* arg ptrs */ /* forward declarations */ static void *allocopy(void *src, int len); static void getreg(char *av[]); static void getwild(char *av[]); /* * _setargv() -> set argument vector */ void _setargv() { char buf[128]; /* working buffer */ char far *cline; /* generic far ptr */ char *av[MAXARG]; /* working vector */ int len; /* command line length */ /* copy program name from environment */ cl = buf; cline = MK_FP(*(int far *)MK_FP(_psp, 0x2c), 0); while ( *cline ) { if ( !*++cline ) { cline++; } } cline += 3; while ( *cline ) { #ifdef FIXARG0 *cl = tolower(*cline++); if ( *cl == '\\' ) { *cl = '/'; } cl++; #else *cl++ = *cline++; #endif } *cl = '\0'; av[0] = allocopy(buf, strlen(buf) + 1); /* copy cmd line from PSP */ cl = buf; cline = MK_FP(_psp, 0x80); len = *cline++; while ( len ) { *cl++ = *cline++; len--; } *cl = 0; _argc = 1; cl = buf; while ( *cl ) { /* deblank */ while ( ISBLANK(*cl) ) { cl++; } /* pick next argument */ while ( *cl && (_argc < MAXARG) ) { if ( iswild() ) { getwild(av); } else { getreg(av); } /* deblank */ while ( ISBLANK(*cl) ) { cl++; } } } /* copy argument vector */ _argv = allocopy(av, _argc * sizeof(char *)); } /* * does current argument contain a wildcard ?? */ static int iswild() { char *s = cl; if ( ISQUOTE(*s) ) { return ( 0 ); } while ( *s && !ISBLANK(*s) ) { if ( (*s == '\\') && ISQUOTE(*(s + 1)) ) { s += 2; } else if ( (*s == '?') || (*s == '*') ) { return ( 1 ); } s++; } return ( 0 ); } /* * allocopy() -> allocate space for a copy of something */ static void * allocopy(void *src, int len) { void *copy; copy = sbrk(len); if ( copy == (void *)(-1) ) { write(2, "\nMemory shortage\n", 17); exit(1); } return ( memcpy(copy, src, len) ); } /* * getreg() -> pick a regular argument from command line */ static void getreg(char *av[]) { char buf[128]; char *bp = buf; char quote; /* copy argument (minus quotes) into local buffer */ if ( ISQUOTE(*cl) ) { quote = *cl++; while ( *cl&& (*cl != quote) ) { *bp++ = *cl++; } } else { while ( *cl && !ISBLANK(*cl) ) { if ( (*cl == '\\') && ISQUOTE(*(cl + 1)) ) { cl++; } *bp++ = *cl++; } } *bp = '\0'; /* skip over terminator char */ if ( *cl ) { cl++; } /* store ptr to copy of string */ av[_argc++] = allocopy(buf, strlen(buf) + 1); } /* * lwrcat() -> concatenate strings, conver to lower case */ static char * lwrcat(char *s, char *t) { char *cp = s; while ( *cp ) { cp++; } /* avoid a warning */ while ( *t ) { *cp++ = tolower(*t++); } *cp = '\0'; return ( s ); } /* * pickpath() -> pick pathname from argument */ static void pickpath(char *arg, char *path) { char *t; int n; /* find beginning of basename */ for ( t = arg + strlen(arg) - 1; t >= arg; t-- ) { if ( (*t == '\\') || (*t == '/') || (*t == ':') ) { break; } } /* pick off path */ for ( n = (t - arg) + 1, t = arg; n--; ) { *path = tolower(*t); path++; t++; } *path = '\0'; } #ifdef SORTARGS /* * mycmp() -> comparison routine for qsort() */ static int mycmp(char **s, char **t) { return ( strcmp(*s, *t) ); } #endif /* * getwild() -> get wildcard argument from command line */ static void getwild(char *av[]) { char path[128]; char srch[128]; char *s = srch; struct ffblk f; #ifdef SORTARGS char **firstv = &av[_argc]; int nmatched = 0; #endif /* pick search string */ while ( *cl && !ISBLANK(*cl) ) { *s++ = *cl++; } *s = '\0'; pickpath(srch, path); if ( findfirst(srch, &f, 0x17) ) { /* no match, just copy argument */ av[_argc++] = allocopy(srch, strlen(srch) + 1); return; } /* add name if not "." or ".." */ if ( f.ff_name[0] != '.' ) { strcpy(srch, path); lwrcat(srch, f.ff_name); av[_argc++] = allocopy(srch, strlen(srch) + 1); #ifdef SORTARGS nmatched++; #endif } /* find the rest */ while ( !findnext(&f) && (_argc < MAXARG) ) { if ( f.ff_name[0] != '.' ) { strcpy(srch, path); lwrcat(srch, f.ff_name); av[_argc++] = allocopy(srch, strlen(srch) + 1); #ifdef SORTARGS nmatched++; #endif } } #ifdef SORTARGS /* sort these entries */ qsort(firstv, nmatched, sizeof(char *), mycmp); #endif } /* * END of setargv.c */ -- Frank Whaley Senior Development Engineer Quadratron Systems Incorporated few@quad1.quad.com uunet!ccicpg!quad1!few Water separates the people of the world; Wine unites them.