home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / PAX20.ZIP / WILD.C < prev    next >
C/C++ Source or Header  |  1990-11-12  |  7KB  |  318 lines

  1. /***
  2. *wild.c - wildcard expander
  3. *
  4. *   Copyright (c) 1985-1988, Microsoft Corporation.  All rights reserved.
  5. *
  6. *Purpose:
  7. *    expands wildcards in argv
  8. *
  9. *    handles '*' (none or more of any char), '?' (exactly one char), and
  10. *    '[string]' (chars which match string chars or between n1 and n2 if
  11. *    'n1-n2'in string inclusive)
  12. *
  13. *******************************************************************************/
  14.  
  15. #include <stdio.h>
  16. #include <ctype.h>
  17.  
  18.  
  19. /*
  20. ** these are the data structures
  21. **
  22. **     __argv
  23. **     -------     ------
  24. **     |     |---->|    |---->"arg0"
  25. **     -------     ------
  26. **                 |    |---->"arg1"
  27. **                 ------
  28. **                  ....
  29. **                 ------
  30. **                 |    |---->"argn"
  31. **                 ------
  32. **                 |NULL|
  33. **                 ------
  34. **                                       argend
  35. **                                       -------
  36. **     -------                           |     |
  37. **     |     | __argc                    -------
  38. **     -------                              |
  39. **                                          |
  40. **  arghead                                 V
  41. **  ------     ---------                ----------
  42. **  |    |---->|   |   |----> .... ---->|   |NULL|
  43. **  ------     ---------                ----------
  44. **               |                        |
  45. **               V                        V
  46. **            "narg0"                  "nargn"
  47. */
  48.  
  49. #define SLASHCHAR   '\\'
  50. #define FWDSLASHCHAR '/'
  51. #define SLASH       "\\"
  52. #define FWDSLASH    "/"
  53. #define STAR        "*.*"
  54.  
  55. #define WILDSTRING  "*?"
  56.  
  57. char *strdup();
  58. char *strpbrk();
  59. char *strcpy();
  60. char *strncpy();
  61. char *strcat();
  62. char *strlwr();
  63. char *malloc();
  64. char *_find();
  65.  
  66. static int match ();
  67. static int add ();
  68. static sort ();
  69.  
  70. extern int __argc;
  71. extern char **__argv;
  72.  
  73. struct argnode {
  74.     char *argptr;
  75.     struct argnode *nextnode;
  76. };
  77.  
  78. static struct argnode *arghead;
  79. static struct argnode *argend;
  80.  
  81. /***
  82. *int _cwild() - wildcard expander
  83. *
  84. *Purpose:
  85. *    expands wildcard in file specs in argv
  86. *
  87. *    handles '*' (none or more of any char), '?' (exactly one char), and
  88. *    '[string]' (chars which match string chars or between n1 and n2
  89. *    if 'n1-n2' in string inclusive)
  90. *
  91. *Entry:
  92. *
  93. *Exit:
  94. *    returns 0 if successful, -1 if any malloc() calls fail
  95. *    if problems with malloc, the old argc and argv are not touched
  96. *
  97. *Exceptions:
  98. *
  99. *******************************************************************************/
  100.  
  101. int
  102. _cwild ()
  103. {
  104.     char **argv = __argv;
  105.     struct argnode *nodeptr;
  106.     int argc;
  107.     char **tmp;
  108.     char *wchar;
  109.     int  ptr, sptr, arglen;
  110.  
  111.     arghead = argend = NULL;
  112.  
  113.     for (argv = __argv; *argv; argv++)  /* for each arg... */
  114.         if ( *(*argv)++ == '"' )
  115.             /* strip leading quote from quoted arg */
  116.         {
  117.             if (add(*argv))
  118.                 return(-1);
  119.         }
  120.         else if (wchar = strpbrk( *argv, WILDSTRING )) {
  121.             /* attempt to expand arg with wildcard */
  122.             if (match( *argv, wchar ))
  123.                 return(-1);
  124.         }
  125.         else if (add( *argv ))  /* normal arg, just add */
  126.             return(-1);
  127.  
  128.     /* count the args */
  129.     for (argc = 0, nodeptr = arghead; nodeptr;
  130.             nodeptr = nodeptr->nextnode, argc++)
  131.             ;
  132.  
  133.     /* try to get new arg vector */
  134.     if (!(tmp = (char **)malloc(sizeof(char *)*(argc+1))))
  135.         return(-1);
  136.  
  137.     /* the new arg vector... */
  138.     __argv = tmp;
  139.  
  140.     /* the new arg count... */
  141.     __argc = argc;
  142.  
  143.     /* install the new args */
  144.     for (nodeptr = arghead; nodeptr; nodeptr = nodeptr->nextnode)
  145.         *tmp++ = nodeptr->argptr;
  146.  
  147.     /* the terminal NULL */
  148.     *tmp = NULL;
  149.  
  150.     /* free up local data */
  151.     for (nodeptr = arghead; nodeptr; nodeptr = arghead) {
  152.         arghead = arghead->nextnode;
  153.         free(nodeptr);
  154.     }
  155.  
  156.     /* return success */
  157.     return(0);
  158. }
  159.  
  160.  
  161. /***
  162. *match(arg, ptr) - [STATIC]
  163. *
  164. *Purpose:
  165. *
  166. *Entry:
  167. *
  168. *Exit:
  169. *
  170. *Exceptions:
  171. *
  172. *******************************************************************************/
  173.  
  174. static int
  175. match (arg, ptr)
  176. char *arg;
  177. char *ptr;
  178. {
  179.     char *new;
  180.     int length;
  181.     char *all;
  182.     struct argnode *first;
  183.     int gotone = 0;
  184.  
  185.     while (ptr != arg && *ptr != SLASHCHAR && *ptr != FWDSLASHCHAR
  186.         && *ptr != ':') {
  187.         /* find first slash or ':' before wildcard */
  188.         ptr--;
  189.     }
  190.  
  191.     if (*ptr == ':' && ptr != arg+1) /* weird name, just add it as is */
  192.         return(add(arg));
  193.  
  194.     if (*ptr == SLASHCHAR || *ptr == FWDSLASHCHAR
  195.         || *ptr == ':') /* pathname */
  196.         length = ptr - arg + 1; /* length of dir prefix */
  197.  
  198.     if (new = _find(arg)) { /* get the first file name */
  199.         first = argend;
  200.  
  201.         do
  202.         { /* got a file name */
  203.             if (strcmp(new, ".") && strcmp(new, ".."))
  204.             {
  205.                 if (*ptr != SLASHCHAR && *ptr != ':' && *ptr != FWDSLASHCHAR )
  206.                 {
  207.                     /* current directory; don't need path */
  208.                     if (!(arg = strdup(new)))
  209.                         return(-1);
  210.  
  211.                     strlwr(arg);
  212.  
  213.                     if (add(arg))
  214.                         return(-1);
  215.                 }
  216.                 else    /* add full pathname */
  217.                 {
  218.                     if (!(all=malloc(length+strlen(new)+1)))
  219.                         return(-1);
  220.  
  221.                     strncpy(all,arg,length);
  222.                     strcpy(all+length,new);
  223.                     strlwr(all);
  224.  
  225.                     if (add(all))
  226.                         return(-1);
  227.                 }
  228.  
  229.                 gotone++;
  230.             }
  231.  
  232.         }
  233.         while (new = _find(NULL));  /* get following files */
  234.  
  235.         if (gotone) {
  236.             sort(first ? first->nextnode : arghead);
  237.             return(0);
  238.         }
  239.     }
  240.  
  241.     return(add(arg)); /* no match */
  242. }
  243.  
  244. /***
  245. *add(arg) - [STATIC]
  246. *
  247. *Purpose:
  248. *
  249. *Entry:
  250. *
  251. *Exit:
  252. *
  253. *Exceptions:
  254. *
  255. *******************************************************************************/
  256.  
  257. static int
  258. add (arg)
  259. char *arg;
  260. {
  261.     struct argnode *nodeptr;
  262.     char *ptr;
  263.  
  264.     if (!(nodeptr = (struct argnode *)malloc(sizeof(struct argnode))))
  265.         return(-1);
  266.  
  267.     for ( ptr = arg; *ptr != 0; ptr++ )
  268.       if ( *ptr == '\\' )
  269.         *ptr = '/';
  270.  
  271.     nodeptr->argptr = arg;
  272.     nodeptr->nextnode = NULL;
  273.  
  274.     if (arghead)
  275.         argend->nextnode = nodeptr;
  276.     else
  277.         arghead = nodeptr;
  278.  
  279.     argend = nodeptr;
  280.     return(0);
  281. }
  282.  
  283.  
  284. /***
  285. *sort(first) - [STATIC]
  286. *
  287. *Purpose:
  288. *
  289. *Entry:
  290. *
  291. *Exit:
  292. *
  293. *Exceptions:
  294. *
  295. *******************************************************************************/
  296.  
  297. static
  298. sort (first)
  299. struct argnode *first;
  300. {
  301.     struct argnode *nodeptr;
  302.     char *temp;
  303.  
  304.     if (first) /* something to sort */
  305.         while (nodeptr = first->nextnode) {
  306.             do  {
  307.                 if (strcmp(nodeptr->argptr, first->argptr) < 0) {
  308.                     temp = first->argptr;
  309.                     first->argptr = nodeptr->argptr;
  310.                     nodeptr->argptr = temp;
  311.                 }
  312.             }
  313.             while (nodeptr = nodeptr->nextnode);
  314.  
  315.             first = first->nextnode;
  316.         }
  317. }
  318.