From pa.dec.com!decwrl!uunet!sparky!kent Tue Jul 16 09:11:11 PDT 1991 Article: 2484 of comp.sources.misc Newsgroups: comp.sources.misc Path: pa.dec.com!decwrl!uunet!sparky!kent From: David J. MacKenzie Subject: v20i093: tcexparg - Unix-style command line wildcards for Turbo C, Part01/01 Message-ID: <1991Jul12.040650.12777@sparky.IMD.Sterling.COM> X-Md4-Signature: 0a108f49c07a9e4f4ad5c33fb15346dd Sender: kent@sparky.IMD.Sterling.COM (Kent Landfield) Organization: Sterling Software, IMD Date: Fri, 12 Jul 1991 04:06:50 GMT Approved: kent@sparky.imd.sterling.com Lines: 276 Submitted-by: David J. MacKenzie Posting-number: Volume 20, Issue 93 Archive-name: tcexparg/part01 Environment: TurboC, DOS #! /bin/sh # This is a shell archive. Remove anything before this line, then feed it # into a shell via "sh file" or similar. To overwrite existing files, # type "sh file -c". # The tool that generated this appeared in the comp.sources.unix newsgroup; # send mail to comp-sources-unix@uunet.uu.net if you want that tool. # Contents: tcexparg.c # Wrapped by djm@rift.eng.umd.edu on Tue Jul 9 02:59:47 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH echo If this archive is complete, you will see the following message: echo ' "shar: End of archive."' if test -f 'tcexparg.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tcexparg.c'\" else echo shar: Extracting \"'tcexparg.c'\" \(6061 characters\) sed "s/^X//" >'tcexparg.c' <<'END_OF_FILE' X/* tcexparg.c - Unix-style command line wildcards for Turbo C 2.0 X X This file is in the public domain. X X Compile your main program with -Dmain=_main and link with this file. X X After that, it is just as if the operating system had expanded the X arguments, except that they are not sorted. The program name and all X arguments that are expanded from wildcards are lowercased. X X Syntax for wildcards: X * Matches zero or more of any character (except a '.' at X the beginning of a name). X ? Matches any single character. X [r3z] Matches 'r', '3', or 'z'. X [a-d] Matches a single character in the range 'a' through 'd'. X [!a-d] Matches any single character except a character in the X range 'a' through 'd'. X X The period between the filename root and its extension need not be X given explicitly. Thus, the pattern `a*e' will match 'abacus.exe' X and 'axyz.e' as well as 'apple'. Comparisons are not case sensitive. X X Authors: X The expargs code is a modification of wildcard expansion code X written for Turbo C 1.0 by X Richard Hargrove X Texas Instruments, Inc. X P.O. Box 869305, m/s 8473 X Plano, Texas 75086 X 214/575-4128 X and posted to USENET in September, 1987. X X The wild_match code was written by Rich Salz, rsalz@bbn.com, X posted to net.sources in November, 1986. X X The code connecting the two is by Mike Slomin, bellcore!lcuxa!mike2, X posted to comp.sys.ibm.pc in November, 1988. X X Major performance enhancements and bug fixes, and source cleanup, X by David MacKenzie, djm@ai.mit.edu. */ X X#include X#include X#include X#include X#include X X/* Number of new arguments to allocate space for at a time. */ X#define ARGS_INCREMENT 10 X X/* The name this program was run with, for error messages. */ Xstatic char *program_name; X Xstatic char **grow_argv (char **new_argv, int new_argc); Xstatic void fatal_error (const char *message); X Xint wild_match (char *string, char *pattern); Xchar *basename (char *path); X Xchar **expargs (int *, char **); X X#ifdef main X#undef main X#endif X Xint Xmain (int argc, char **argv, char **envp) X{ X argv = expargs (&argc, argv); X return _main (argc, argv, envp); X} X Xchar ** Xexpargs (int *pargc, char **argv) X{ X char path[MAXPATH + 1]; X char **new_argv; X struct ffblk block; X char *path_base; X char *arg_base; X int argind; X int new_argc; X int path_length; X int matched; X X program_name = argv[0]; X if (program_name && *program_name) X strlwr (program_name); X new_argv = grow_argv (NULL, 0); X new_argv[0] = argv[0]; X new_argc = 1; X X for (argind = 1; argind < *pargc; ++argind) X { X matched = 0; X if (strpbrk (argv[argind], "?*[") != NULL) X { X strncpy (path, argv[argind], MAXPATH - 3); X path_base = basename (path); X strcpy (path_base, "*.*"); X arg_base = argv[argind] + (path_base - path); X X if (!findfirst (path, &block, FA_DIREC)) X { X strlwr (path); X do X { X /* Only match "." and ".." explicitly. */ X if (*block.ff_name == '.' && *arg_base != '.') X continue; X path_length = stpcpy (path_base, block.ff_name) - path + 1; X strlwr (path_base); X if (wild_match (path, argv[argind])) X { X matched = 1; X new_argv[new_argc] = (char *) malloc (path_length); X if (new_argv[new_argc] == NULL) X fatal_error ("memory exhausted"); X strcpy (new_argv[new_argc++], path); X new_argv = grow_argv (new_argv, new_argc); X } X } while (!findnext (&block)); X } X } X if (matched == 0) X new_argv[new_argc++] = argv[argind]; X new_argv = grow_argv (new_argv, new_argc); X } X X *pargc = new_argc; X new_argv[new_argc] = NULL; X return &new_argv[0]; X} X X/* Return a pointer to the last element of PATH. */ X Xchar * Xbasename (char *path) X{ X char *tail; X X for (tail = path; *path; ++path) X if (*path == ':' || *path == '\\') X tail = path + 1; X return tail; X} X Xstatic char ** Xgrow_argv (char **new_argv, int new_argc) X{ X if (new_argc % ARGS_INCREMENT == 0) X { X new_argv = (char **) realloc X (new_argv, sizeof (char *) * (new_argc + ARGS_INCREMENT)); X if (new_argv == NULL) X fatal_error ("memory exhausted"); X } X return new_argv; X} X Xstatic void Xfatal_error (const char *message) X{ X putc ('\n', stderr); X if (program_name && *program_name) X { X fputs (program_name, stderr); X fputs (": ", stderr); X } X fputs (message, stderr); X putc ('\n', stderr); X exit (1); X} X X/* Shell-style pattern matching for ?, \, [], and * characters. X I'm putting this replacement in the public domain. X X Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986. */ X X/* The character that inverts a character class; '!' or '^'. */ X#define INVERT '!' X Xstatic int star (char *string, char *pattern); X X/* Return nonzero if `string' matches Unix-style wildcard pattern X `pattern'; zero if not. */ X Xint Xwild_match (char *string, char *pattern) X{ X int prev; /* Previous character in character class. */ X int matched; /* If 1, character class has been matched. */ X int reverse; /* If 1, character class is inverted. */ X X for (; *pattern; string++, pattern++) X switch (*pattern) X { X case '\\': X /* Literal match with following character; fall through. */ X pattern++; X default: X if (*string != *pattern) X return 0; X continue; X case '?': X /* Match anything. */ X if (*string == '\0') X return 0; X continue; X case '*': X /* Trailing star matches everything. */ X return *++pattern ? star (string, pattern) : 1; X case '[': X /* Check for inverse character class. */ X reverse = pattern[1] == INVERT; X if (reverse) X pattern++; X for (prev = 256, matched = 0; *++pattern && *pattern != ']'; X prev = *pattern) X if (*pattern == '-' X ? *string <= *++pattern && *string >= prev X : *string == *pattern) X matched = 1; X if (matched == reverse) X return 0; X continue; X } X X return *string == '\0'; X} X Xstatic int Xstar (char *string, char *pattern) X{ X while (wild_match (string, pattern) == 0) X if (*++string == '\0') X return 0; X return 1; X} END_OF_FILE if test 6061 -ne `wc -c <'tcexparg.c'`; then echo shar: \"'tcexparg.c'\" unpacked with wrong size! fi # end of 'tcexparg.c' fi echo shar: End of archive. 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.