home *** CD-ROM | disk | FTP | other *** search
- /*-
- * int globargv(&argc, &argv, globber)
- *
- * General purpose globbing routine for argv lists. You can call
- * globargv() near the beginning of a main program to glob the program
- * argument list. The new argv list will be dynamically allocated
- * and NULL terminated.
- *
- * `globber' is a function declared as `char **globber(char *pattern)',
- * and should behave the way GNU glob_filename() does. That is as follows:
- * -- If there is a memory allocation overflow, return NULL
- * -- If there is a file access error (ENOENT, for instance),
- * return (char **) -1 [globargv() considers a file access
- * error to be equivalent to a `no match']
- * -- If there is no match, return a pointer to a NULL pointer
- * -- Otherwise, return a pointer to a NULL terminated array of
- * pointers to the globbing matches
- *
- * Note that globargv() runs an in-place sort on the array returned by
- * globber(). I think this is unlikely to be a problem.
- *
- * The return value of globargv() is -1 if a memory allocation error
- * occurred, otherwise 0. Only in the latter case are argc and argv
- * affected.
- *
- * Written by Barry Schwartz, 29 August 1990.
- */
-
- #include <stdlib.h>
- #include <stddef.h>
- #include <string.h>
- #include <search.h>
-
-
-
- /* Comparison function for qsort() */
- static int
- arg_compare(const char **arg1, const char **arg2)
- {
- /* Use the Microsoft library stricmp() function, which is a case
- * insensitive version of strcmp */
- return stricmp(*arg1, *arg2);
- }
-
-
-
- /*-
- * 0 --> success
- * -1 --> memory allocation overflow
- */
- int
- globargv(int *argc, char ***argv, char **(*globber)(char *))
- {
- char **p;
- char **newargv;
- char **globber_output;
- unsigned int number_of_new_args;
- int newargc;
- int oldarg_index;
-
- newargv = malloc(2 * sizeof(char *));
- if (!newargv)
- goto cannot_allocate;
- newargv[0] = (*argv)[0]; /* Program name */
- newargv[1] = NULL;
- newargc = 1;
-
- for (oldarg_index = 1; oldarg_index != *argc; ++oldarg_index)
- {
- globber_output = (*globber)((*argv)[oldarg_index]);
- if (globber_output == NULL)
- goto cannot_allocate;
-
- /* Count the number of new arguments (zero if no match or
- * file error occurred) */
- number_of_new_args = 0;
- if (globber_output != (char **) -1)
- for (p = globber_output; *p; ++p)
- ++number_of_new_args;
-
- /* Sort the globber output in case-insensitive ascending
- * ASCII order */
- if (number_of_new_args > 1)
- qsort(globber_output, number_of_new_args,
- sizeof(globber_output[0]), arg_compare);
-
- /* Incorporate the new arguments into the new argv list */
- if (number_of_new_args == 0)
- {
- newargv = realloc(newargv, (newargc + 2) * sizeof(char *));
- if (!newargv)
- goto cannot_allocate;
- newargv[newargc++] = (*argv)[oldarg_index];
- newargv[newargc] = NULL;
- }
- else
- {
- newargv = realloc(newargv,
- (newargc + number_of_new_args + 1) * sizeof(char *));
- if (!newargv)
- goto cannot_allocate;
- for (p = globber_output; *p; ++p)
- newargv[newargc++] = *p;
- newargv[newargc] = NULL;
- }
- }
-
- /* Successful return */
- *argv = newargv;
- *argc = newargc;
- return 0;
-
- cannot_allocate:
- /* Error occurred while allocating memory. Any blocks already
- * allocated should have been freed (by realloc()) when the error
- * occurred. */
- return -1;
- }
-
-
-
- #ifdef TEST
-
-
- #include <stdio.h>
-
-
- int
- main(int argc, char **argv)
- {
- extern int backslash_same_as_slash;
- char **glob_filename(char *);
-
- backslash_same_as_slash = 1;
- switch (globargv(&argc, &argv, glob_filename))
- {
- case -1:
- fprintf(stderr, "memory allocation error, return value -1\n");
- return -1;
-
- case 0:
- {
- int i;
-
- for (i = 0; i != argc; ++i)
- printf("%s ", argv[i]);
- }
- putchar('\n');
- if (argv[argc] != NULL)
- fprintf(stderr, "argv[argc] is not NULL\n");
- return 0;
-
- default:
- fprintf(stderr, "illegal return value\n");
- return 1;
- }
- }
-
-
- #endif
-