home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 19.ddi / SOURCE / STARTUP / WILD.C_ / WILD.C
Encoding:
C/C++ Source or Header  |  1993-02-08  |  6.4 KB  |  297 lines

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