home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / cmdline / wildcard / wildcard.src
Encoding:
C/C++ Source or Header  |  1989-10-26  |  6.1 KB  |  374 lines

  1. /*
  2.  *    setargv.c ->    parse arguments
  3.  *
  4.  *    This code evolved out of a requirement for expansion of wild-card
  5.  *    arguments given on the command line.  Turbo C's wildarg.obj
  6.  *    actually produces a reference to __wildargv, which still doesn't
  7.  *    do the job I needed (for example, directory names are not
  8.  *    expanded).
  9.  *
  10.  *    This version both expands wild-card arguments and converts them
  11.  *    to lower case (a cosmetic thing for me).  Arguments that are
  12.  *    quoted (with either " or ') are left alone, but the quote
  13.  *    characters are stripped.  A leading quote may be escaped with
  14.  *    a backslash (\" or \').  Quotes within arguments (ARG="a b c")
  15.  *    are not handled in the Un*x fashion.  If no matching filename
  16.  *    is found, the argument is passed unchanged.
  17.  *
  18.  *    Two conditional-compilation flags are provided:
  19.  *        FIXARG0:    convert argv[0] to lower case and switch
  20.  *                all backslashes to slashes (cosmetic)
  21.  *        SORTARGS:    use qsort() to sort the expansions of
  22.  *                each argument
  23.  *
  24.  *    Further enhancements greatly appreciated.
  25.  *
  26.  *    This code placed in the public domain on October 25, 1989 by
  27.  *    its original author, Frank Whaley.
  28.  */
  29.  
  30. #define    MAXARG    1024    /*  max arguments  */
  31.  
  32. #include <ctype.h>
  33. #include <dir.h>
  34. #include <dos.h>
  35. #include <mem.h>
  36. #include <string.h>
  37. #include <alloc.h>
  38.  
  39.     /*  let's do some things with macros...  */
  40. #define    ISQUOTE(c)    (((c)=='"')||((c)=='\''))
  41. #define    ISBLANK(c)    (((c)==' ')||((c)=='\t'))
  42.  
  43.  
  44. static char *cl;        /*  -> local copy of command line  */
  45.  
  46.     /*  the following are used by run-time startup (c0?.obj)  */
  47. extern int _argc;        /*  number of args  */
  48. extern char **_argv;        /*  arg ptrs  */
  49.  
  50.     /*  forward declarations  */
  51. static void *allocopy(void *src, int len);
  52. static void getreg(char *av[]);
  53. static void getwild(char *av[]);
  54.  
  55.  
  56. /*
  57.  *    _setargv() ->    set argument vector
  58.  */
  59. void
  60. _setargv()
  61. {
  62.     char buf[128];        /*  working buffer  */
  63.     char far *cline;    /*  generic far ptr  */
  64.     char *av[MAXARG];    /*  working vector  */
  65.     int len;        /*  command line length  */
  66.  
  67.     /*  copy program name from environment  */
  68.     cl = buf;
  69.     cline = MK_FP(*(int far *)MK_FP(_psp, 0x2c), 0);
  70.     while ( *cline )
  71.     {
  72.         if ( !*++cline )
  73.         {
  74.             cline++;
  75.         }
  76.     }
  77.     cline += 3;
  78.     while ( *cline )
  79.     {
  80. #ifdef    FIXARG0
  81.         *cl = tolower(*cline++);
  82.         if ( *cl == '\\' )
  83.         {
  84.             *cl = '/';
  85.         }
  86.         cl++;
  87. #else
  88.         *cl++ = *cline++;
  89. #endif
  90.     }
  91.     *cl = '\0';
  92.     av[0] = allocopy(buf, strlen(buf) + 1);
  93.  
  94.     /*  copy cmd line from PSP  */
  95.     cl = buf;
  96.     cline = MK_FP(_psp, 0x80);
  97.     len = *cline++;
  98.     while ( len )
  99.     {
  100.         *cl++ = *cline++;
  101.         len--;
  102.     }
  103.     *cl = 0;
  104.  
  105.     _argc = 1;
  106.     cl = buf;
  107.     while ( *cl )
  108.     {
  109.         /*  deblank  */
  110.         while ( ISBLANK(*cl) )
  111.         {
  112.             cl++;
  113.         }
  114.  
  115.         /*  pick next argument  */
  116.         while ( *cl && (_argc < MAXARG) )
  117.         {
  118.             if ( iswild() )
  119.             {
  120.                 getwild(av);
  121.             }
  122.             else
  123.             {
  124.                 getreg(av);
  125.             }
  126.  
  127.             /*  deblank  */
  128.             while ( ISBLANK(*cl) )
  129.             {
  130.                 cl++;
  131.             }
  132.         }
  133.     }
  134.  
  135.     /*  copy argument vector  */
  136.     _argv = allocopy(av, _argc * sizeof(char *));
  137. }
  138.  
  139.  
  140. /*
  141.  *    does current argument contain a wildcard ??
  142.  */
  143. static int
  144. iswild()
  145. {
  146.     char *s = cl;
  147.  
  148.     if ( ISQUOTE(*s) )
  149.     {
  150.         return ( 0 );
  151.     }
  152.  
  153.     while ( *s && !ISBLANK(*s) )
  154.     {
  155.         if ( (*s == '\\') && ISQUOTE(*(s + 1)) )
  156.         {
  157.             s += 2;
  158.         }
  159.         else if ( (*s == '?') || (*s == '*') )
  160.         {
  161.             return ( 1 );
  162.         }
  163.  
  164.         s++;
  165.     }
  166.  
  167.     return ( 0 );
  168. }
  169.  
  170.  
  171. /*
  172.  *    allocopy() ->    allocate space for a copy of something
  173.  */
  174. static void *
  175. allocopy(void *src, int len)
  176. {
  177.     void *copy;
  178.  
  179.     copy = sbrk(len);
  180.     if ( copy == (void *)(-1) )
  181.     {
  182.         write(2, "\nMemory shortage\n", 17);
  183.         exit(1);
  184.     }
  185.     return ( memcpy(copy, src, len) );
  186. }
  187.  
  188.  
  189. /*
  190.  *    getreg() ->    pick a regular argument from command line
  191.  */
  192. static void
  193. getreg(char *av[])
  194. {
  195.     char buf[128];
  196.     char *bp = buf;
  197.     char quote;
  198.  
  199.     /*  copy argument (minus quotes) into local buffer  */
  200.     if ( ISQUOTE(*cl) )
  201.     {
  202.         quote = *cl++;
  203.         while ( *cl&& (*cl != quote) )
  204.         {
  205.             *bp++ = *cl++;
  206.         }
  207.     }
  208.     else
  209.     {
  210.         while ( *cl && !ISBLANK(*cl) )
  211.         {
  212.             if ( (*cl == '\\') && ISQUOTE(*(cl + 1)) )
  213.             {
  214.                 cl++;
  215.             }
  216.  
  217.             *bp++ = *cl++;
  218.         }
  219.     }
  220.     *bp = '\0';
  221.  
  222.     /*  skip over terminator char  */
  223.     if ( *cl )
  224.     {
  225.         cl++;
  226.     }
  227.  
  228.     /*  store ptr to copy of string  */
  229.     av[_argc++] = allocopy(buf, strlen(buf) + 1);
  230. }
  231.  
  232.  
  233. /*
  234.  *    lwrcat() ->    concatenate strings, conver to lower case
  235.  */
  236. static char *
  237. lwrcat(char *s, char *t)
  238. {
  239.     char *cp = s;
  240.  
  241.     while ( *cp )
  242.     {
  243.         cp++;
  244.     }
  245.     /*  avoid a warning  */
  246.     while ( *t )
  247.     {
  248.         *cp++ = tolower(*t++);
  249.     }
  250.     *cp = '\0';
  251.  
  252.     return ( s );
  253.     }
  254.  
  255.  
  256. /*
  257.  *    pickpath() ->    pick pathname from argument
  258.  */
  259. static void
  260. pickpath(char *arg, char *path)
  261. {
  262.     char *t;
  263.     int n;
  264.  
  265.     /*  find beginning of basename  */
  266.     for ( t = arg + strlen(arg) - 1; t >= arg; t-- )
  267.     {
  268.         if ( (*t == '\\') || (*t == '/') || (*t == ':') )
  269.         {
  270.             break;
  271.         }
  272.     }
  273.  
  274.     /*  pick off path  */
  275.     for ( n = (t - arg) + 1, t = arg; n--; )
  276.     {
  277.         *path = tolower(*t);
  278.         path++;
  279.         t++;
  280.     }
  281.     *path = '\0';
  282. }
  283.  
  284.  
  285. #ifdef    SORTARGS
  286. /*
  287.  *    mycmp() ->    comparison routine for qsort()
  288.  */
  289. static int
  290. mycmp(char **s, char **t)
  291. {
  292.     return ( strcmp(*s, *t) );
  293. }
  294. #endif
  295.  
  296.  
  297. /*
  298.  *    getwild() ->    get wildcard argument from command line
  299.  */
  300. static void
  301. getwild(char *av[])
  302. {
  303.     char path[128];
  304.     char srch[128];
  305.     char *s = srch;
  306.     struct ffblk f;
  307. #ifdef    SORTARGS
  308.     char **firstv = &av[_argc];
  309.     int nmatched = 0;
  310. #endif
  311.  
  312.     /*  pick search string  */
  313.     while ( *cl && !ISBLANK(*cl) )
  314.     {
  315.         *s++ = *cl++;
  316.     }
  317.     *s = '\0';
  318.  
  319.     pickpath(srch, path);
  320.  
  321.     if ( findfirst(srch, &f, 0x17) )
  322.     {
  323.         /*  no match, just copy argument  */
  324.         av[_argc++] = allocopy(srch, strlen(srch) + 1);
  325.         return;
  326.     }
  327.  
  328.     /*  add name if not "." or ".."  */
  329.     if ( f.ff_name[0] != '.' )
  330.     {
  331.         strcpy(srch, path);
  332.         lwrcat(srch, f.ff_name);
  333.         av[_argc++] = allocopy(srch, strlen(srch) + 1);
  334. #ifdef    SORTARGS
  335.         nmatched++;
  336. #endif
  337.     }
  338.  
  339.     /*  find the rest  */
  340.     while ( !findnext(&f) && (_argc < MAXARG) )
  341.     {
  342.         if ( f.ff_name[0] != '.' )
  343.         {
  344.             strcpy(srch, path);
  345.             lwrcat(srch, f.ff_name);
  346.             av[_argc++] = allocopy(srch, strlen(srch) + 1);
  347. #ifdef    SORTARGS
  348.             nmatched++;
  349. #endif
  350.         }
  351.     }
  352.  
  353. #ifdef    SORTARGS
  354.     /*  sort these entries  */
  355.     qsort(firstv, nmatched, sizeof(char *), mycmp);
  356. #endif
  357. }
  358.  
  359.  
  360. /*
  361.  *    END of setargv.c
  362.  */
  363. -- 
  364. Frank Whaley
  365. Senior Development Engineer
  366. Quadratron Systems Incorporated
  367. few@quad1.quad.com
  368. uunet!ccicpg!quad1!few
  369.  
  370. Water separates the people of the world;
  371. Wine unites them.
  372.  
  373.  
  374.