home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / fileutil / tcggrep2.arj / GLOBARGV.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-11-24  |  4.6 KB  |  177 lines

  1. /*-
  2.  *      int globargv(&argc, &argv, globber)
  3.  *
  4.  * General purpose globbing routine for argv lists.  You can call
  5.  * globargv() near the beginning of a main program to glob the program
  6.  * argument list.  The new argv list will be dynamically allocated
  7.  * and NULL terminated.
  8.  *
  9.  * `globber' is a function declared as `char **globber(char *pattern)',
  10.  * and should behave the way GNU glob_filename() does.  That is as follows:
  11.  *      -- If there is a memory allocation overflow, return NULL
  12.  *      -- If there is a file access error (ENOENT, for instance),
  13.  *         return (char **) -1    [globargv() considers a file access
  14.  *         error to be equivalent to a `no match']
  15.  *      -- If there is no match, return a pointer to a NULL pointer
  16.  *      -- Otherwise, return a pointer to a NULL terminated array of
  17.  *         pointers to the globbing matches
  18.  *
  19.  * Note that globargv() runs an in-place sort on the array returned by
  20.  * globber().  I think this is unlikely to be a problem.
  21.  *
  22.  * The return value of globargv() is -1 if a memory allocation error
  23.  * occurred, otherwise 0.  Only in the latter case are argc and argv
  24.  * affected.
  25.  *
  26.  * Written by Barry Schwartz, 29 August 1990.
  27.  */
  28. /* modified for Turbo C Jim Segrave 00:13:55 Sat Nov 24 1990
  29.    added prototypes, casts, changed include file names, etc. so
  30.    it compiles without warnings.
  31.    added code so that duplicate globbed file names are discarded -
  32.    grep xxx *.c *
  33.    used to examine all .c files twice, now it doesn't
  34. */
  35.  
  36. #include <stdlib.h>
  37. #include <stddef.h>
  38. #include <string.h>
  39. #ifndef __TURBOC__
  40. #  include <search.h>
  41. #endif
  42.  
  43. /* Comparison function for qsort() */
  44. static int
  45. arg_compare(const void *arg1, const void *arg2)
  46. {
  47.     /* Use the TC library stricmp() function, which is a case
  48.      * insensitive version of strcmp */
  49.     return stricmp((const char *) arg1, (const char *) arg2);
  50. }
  51.  
  52.  
  53.  
  54. /*-
  55.  *       0 --> success
  56.  *      -1 --> memory allocation overflow
  57.  */
  58. int
  59. globargv(int *argc, char ***argv, char **(*globber)(char *))
  60. {
  61.     char **p;
  62.     char **newargv;
  63.     char **globber_output;
  64.     unsigned int number_of_new_args;
  65.     int newargc;
  66.     int oldarg_index;
  67.     char  **newargvp;
  68.  
  69.     newargv = malloc(2 * sizeof(char *));
  70.     if (!newargv)
  71.     goto cannot_allocate;
  72.     newargv[0] = (*argv)[0];    /* Program name */
  73.     newargv[1] = NULL;
  74.     newargc = 1;
  75.  
  76.     for (oldarg_index = 1; oldarg_index != *argc; ++oldarg_index)
  77.     {
  78.     globber_output = (*globber)((*argv)[oldarg_index]);
  79.     if (globber_output == NULL)
  80.         goto cannot_allocate;
  81.  
  82.     /* Count the number of new arguments (zero if no match or
  83.          * file error occurred) */
  84.     number_of_new_args = 0;
  85.     if (globber_output != (char **) -1)
  86.         for (p = globber_output; *p; ++p)
  87.         ++number_of_new_args;
  88.  
  89.     /* Sort the globber output in case-insensitive ascending
  90.          * ASCII order */
  91.     if (number_of_new_args > 1)
  92.         qsort(globber_output, number_of_new_args,
  93.                   sizeof(globber_output[0]), arg_compare);
  94.  
  95.     /* Incorporate the new arguments into the new argv list */
  96.     if (number_of_new_args == 0)
  97.     {
  98.         newargv = realloc(newargv, (newargc + 2) * sizeof(char *));
  99.         if (!newargv)
  100.         goto cannot_allocate;
  101.         newargv[newargc++] = (*argv)[oldarg_index];
  102.         newargv[newargc] = NULL;
  103.     }
  104.     else
  105.     {
  106.         newargv = realloc(newargv,
  107.             (newargc + number_of_new_args + 1) * sizeof(char *));
  108.         if (!newargv)
  109.         goto cannot_allocate;
  110.         for (p = globber_output; *p; ++p)
  111.             {
  112.             for (newargvp = newargv; *newargvp != NULL; ++newargvp)
  113.               if (strcmp (*newargvp, *p) == 0)
  114.                  goto nostore;
  115.                  
  116.         newargv[newargc++] = *p;
  117.         newargv[newargc] = NULL;
  118. nostore:;
  119.         }
  120.  
  121.         }
  122.     }
  123.  
  124.     /* Successful return */
  125.     *argv = newargv;
  126.     *argc = newargc;
  127.     return 0;
  128.  
  129. cannot_allocate:
  130.     /* Error occurred while allocating memory.  Any blocks already
  131.      * allocated should have been freed (by realloc()) when the error
  132.      * occurred. */
  133.     return -1;
  134. }
  135.  
  136.  
  137.  
  138. #ifdef TEST
  139.  
  140.  
  141. #include <stdio.h>
  142.  
  143.  
  144. int
  145. main(int argc, char **argv)
  146. {
  147.     extern int backslash_same_as_slash;
  148.     char **glob_filename(char *);
  149.  
  150.     backslash_same_as_slash = 1;
  151.     switch (globargv(&argc, &argv, glob_filename))
  152.     {
  153.     case -1:
  154.     fprintf(stderr, "memory allocation error, return value -1\n");
  155.     return -1;
  156.  
  157.     case 0:
  158.     {
  159.         int i;
  160.  
  161.         for (i = 0; i != argc; ++i)
  162.         printf("%s ", argv[i]);
  163.     }
  164.     putchar('\n');
  165.     if (argv[argc] != NULL)
  166.         fprintf(stderr, "argv[argc] is not NULL\n");
  167.     return 0;
  168.  
  169.     default:
  170.     fprintf(stderr, "illegal return value\n");
  171.     return 1;
  172.     }
  173. }
  174.  
  175.  
  176. #endif
  177.