home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_200 / 213_01 / wildexpr.c < prev    next >
Text File  |  1979-12-31  |  11KB  |  404 lines

  1. /* WILDEXPR.C    VERS:- 01.00  DATE:- 09/26/86  TIME:- 09:37:31 PM */
  2. /*
  3. %CC1 $1.C -X
  4. */
  5. /* 
  6. Description:
  7.  
  8. Modification of Van Nuys Toolkit - BDS C distribution version of WILDEXP:
  9.     use of <du:>, by conversion to <u/d:> form;
  10.     expansion of <d?:> and <?/d:>;
  11.     all output given uu/d: prefix, even files in current drive/user area;
  12.     restructuring of much of the code.
  13.  
  14. Size of code:            hex bytes
  15.     this version:        CC1         wildcard nos & du: (d?:, ?/d:)
  16.     Van Nuys:        C8E        user numbers (u/d: form only)
  17.     BDS C v1.50a:        A8E        no user numbers (d: form only)
  18. (Inclusion of wildcard user numbers costs a little but not much.)
  19. (The size of the du_ud() function is not included in the value cited for the
  20.     memory requirement for this version)
  21.  
  22. The number of !names allowed is 40 (= 2 !d?: + 8 !du:).
  23.  
  24. NOTE:
  25. There must be a <du:> --> <u/d:> conversion function = du_ud().
  26. If the conversion is required only for WILDCARD, then it is sufficient
  27.     to compile and link the du_ud function given at the end of this file.
  28. A more general approach is to modify DEFF.CRL and DEFF2.CRL, 
  29.     by adding the functions of STDLIB3R to DEFF.CRL, and 
  30.     by patching the functions of DEFF2.CRL, as described in STDLIB3R.
  31. If this is done, then all file opening, creation etc operations accept the
  32.     <du:> form.
  33.  
  34.  
  35. By J.A. Rupley, Tucson, Arizona
  36. Coded for BDS C compiler, version 1.50a
  37. */
  38.  
  39.  
  40.         /* page eject */
  41.  
  42. /*********************************************************************
  43. *                               WILDEXP                              *
  44. *********************************************************************/
  45. /*
  46.     WILDEXP.C     v2.0    12/26/83
  47.     BDS C Command-line Wild-card expansion utility
  48.     
  49.     Revised by JA Rupley -- to include expansion of ?/ = d?:, and
  50.                 conversion of du: -> u/d:
  51.     Revised by Gene Mallory
  52.     Written by Leor Zolman
  53.  
  54.     Lets ambiguous file names appear on the command line to C programs,
  55.     automatically expanding the parameter list to contain all files that
  56.     fit the afn's. Returns ERROR if something went wrong; usually, this
  57.     is due to MAXITEMS being set too low; the "MAXITEMS" defined constant
  58.     sets the maximum number of matches that WILDEXP can handle. If you
  59.     need to be able to process directories with more entries than this,
  60.     be sure to modify MAXITEMS to be bigger than the largest expected
  61.     directory size.
  62.  
  63.     An afn preceded by a "!" causes all names matching the given afn to
  64.     be EXCLUDED from the resulting expansion list. Thus, to yield a
  65.     command line containing all files except "COM" files, you'd say:
  66.  
  67.         A>progname !*.com <cr>
  68.  
  69.     Another example: to get all files on B: except .C files, say:
  70.  
  71.         A>prognam b:*.* !b:*.c <cr>
  72.  
  73.     When giving a "!" afn, "*" chars in the string matches to the end of
  74.     either the filename or extension, just like CP/M, but "?" chars match
  75.     ONE and ONLY ONE character in either the filename or extension.
  76.  
  77.     To use WILDEXP, begin your "main" function as follows:
  78.  
  79.     ---------------------------------------------
  80.     main(argc,argv)
  81.     char **argv;
  82.     {
  83.     ...                       /* local declarations  */
  84.         dioinit(&argc,argv);        /* if using DIO      */
  85.         wildexp(&argc,&argv)        /* 1st state. in prog. */
  86.         ...
  87.     ---------------------------------------------
  88.  
  89.     and link WILDEXP.CRL in with your program. That's all there is to
  90.     it; note that "wildexp" uses the "sbrk" function to obtain storage,
  91.     so don't go playing around with memory that is outside of the
  92.     external or stack areas unless you obtain the memory through "sbrk"
  93.     or "alloc" calls.
  94. */
  95.  
  96.         /* page eject */
  97.  
  98. #include "BDSCIO.H"
  99.  
  100. #define MAXITEMS 1333 /* max no. of items after expansion */
  101. #define MAXUSERS 16 /* max user number in expansion of ?/ */
  102. #define NEED_DU_UD FALSE /* set true if du_ud() not in DEFF.CRL */
  103.  
  104. #define SEARCH_FIRST 17 /* BDOS calls */
  105. #define SEARCH_NEXT 18
  106. #define GET_DRIVE 25
  107. #define GET_USER 32
  108. #define SET_DISK 14
  109. #define SET_USER 32
  110. #define SET_DMA 26
  111.  
  112. wildexp(argcptr, argvptr)
  113. int *argcptr;        /* pointer to argc */
  114. char ***argvptr;        /* pointer to argv */
  115. {
  116.     int newargc;        /* new argc */
  117.     char **newargv;        /* new argv */
  118.     char **oldargv;        /* old argv */
  119.     int oldargc;        /* old argc */
  120.     int expargc;        /* expansion of ?/ and d? */
  121.     char **expargv;
  122.     char fcb[36];        /* fcb used for search for first/next calls */
  123.     char dmapos;        /* value returned by search calls */
  124.     char first_time;        /* used in search routine */
  125.     char tmpfn[20];        /* temporary file name */
  126.     char *p_tmp;        /* temporary pointer */
  127.     char *p_exp;        /* another temporary pointer */
  128.     char *notfns[40];        /* list of !<afn> entries */
  129.     int notcount;        /* count of entries in notfns */
  130.     char cur_drive;        /* current drive number */
  131.     char cur_user;        /* current user number */
  132.     char usrno;        /* this file user number */
  133.     char driveno;        /* this file drive number */
  134.     char buffer[128];        /* directory buffer */
  135.     int i, j, k;
  136.  
  137.     cur_drive = bdos(GET_DRIVE);
  138.     cur_user = bdos(GET_USER, 0xff);
  139.     bdos(SET_DMA, buffer);
  140.  
  141.     oldargv = *argvptr;
  142.     oldargc = *argcptr;
  143.     expargc = 1;
  144.     newargc = 1;
  145.     notcount = 0;
  146.  
  147.              /* page eject */
  148.  
  149.     /* get newargv and expargv space  */
  150.     if (((newargv = sbrk(MAXITEMS * 2 + 2)) == ERROR) ||
  151.         ((expargv = sbrk(MAXITEMS + 2)) == ERROR))
  152.         goto err_exit;
  153.  
  154.     /* change du: to #/d: form    */
  155.     /* expand all_users flag = ?/ = d?: */
  156.     /* at end of loop, handle..first name is a !name */
  157.     for (i = 1; i < oldargc; i++)
  158.     {
  159.         if (*(p_tmp = oldargv[i]) == '!')
  160.             p_tmp++;
  161.  
  162.         if (du_ud(p_tmp, tmpfn))
  163.             p_tmp = tmpfn;
  164.  
  165.         for (j = 0; j <= MAXUSERS; j++)
  166.         {
  167.             if ((p_exp = expargv[expargc++] = sbrk(20)) == ERROR)
  168.                 goto err_exit;
  169.             if (oldargv[i][0] == '!')
  170.                 *p_exp++ = '!';
  171.             if ((*p_tmp == '?') && (*(p_tmp + 1) == '/'))
  172.             {
  173.                 *p_exp++ = j / 10 + '0';
  174.                 *p_exp++ = j % 10 + '0';
  175.                 strcpy(p_exp, (p_tmp + 1));
  176.             }
  177.             else
  178.                 {
  179.                 strcpy(p_exp, p_tmp);
  180.                 break;
  181.             }
  182.         }
  183.         if (oldargv[1][0] == '!')
  184.         {
  185.             fsplit(&expargv[1][1], tmpfn, &usrno, &driveno,
  186.             cur_drive, cur_user);
  187.             strcpy(&tmpfn[5], "*.*");
  188.             oldargv[1] = tmpfn;
  189.             if (expargc > 2)
  190.                 *++oldargv[1] = '?';
  191.             i--;
  192.         }
  193.     }
  194.     oldargv = expargv;
  195.     oldargc = expargc;
  196.  
  197.     /* if not_flag on oldargv then add to not list .... */
  198.     /* else get directory files that match wildcard oldargv */
  199.     for (i = 1; i < oldargc; i++)
  200.     {
  201.         if (oldargv[i][0] == '!')
  202.             notfns[notcount++] = &oldargv[i][1];
  203.         else
  204.             {
  205.             p_tmp = fsplit(oldargv[i], tmpfn, &usrno, &driveno,
  206.             cur_drive, cur_user);
  207.             setfcb(fcb, p_tmp);
  208.             bdos(SET_DISK, driveno);
  209.             bdos(SET_USER, usrno);
  210.             first_time = TRUE;
  211.             while (1)
  212.             {
  213.                 if ((dmapos = bdos((first_time ? SEARCH_FIRST
  214.                     : SEARCH_NEXT), fcb)) == 255)
  215.                     break;
  216.                 first_time = FALSE;
  217.                 if (((newargv[newargc] = sbrk(20)) == ERROR) ||
  218.                     (newargc >= MAXITEMS))
  219.                     goto err_exit;
  220.                 makename(newargv[newargc++], tmpfn,
  221.                 (buffer + dmapos * 32));
  222.             }
  223.         }
  224.     }
  225.  
  226.     /* restore current drive and user */
  227.     bdos(SET_DISK, cur_drive);
  228.     bdos(SET_USER, cur_user);
  229.  
  230.     /*  Now eliminate all the NOT names  */
  231.     for (i = 0; i < notcount; i++)
  232.     {
  233.         p_tmp = fsplit(notfns[i], tmpfn, &usrno, &driveno,
  234.         cur_drive, cur_user);
  235.         strcpy(&tmpfn[5], p_tmp);
  236.         for (j = 1; j < newargc; j++)
  237.             while (match(tmpfn, newargv[j]))
  238.             {
  239.                 if (j == --newargc)
  240.                     break;
  241.                 for (k = j; k < newargc; k++)
  242.                     newargv[k] = newargv[k + 1];
  243.             }
  244.     }
  245.  
  246.     /* Replace argc and argv with new values....and exit*/
  247.     *argcptr = newargc;
  248.     *argvptr = newargv;
  249.  
  250.     return 0;
  251.  
  252. err_exit :
  253.     exit(puts("WILDEXP: Out of RAM space"));
  254. }
  255.  
  256.  
  257.         /* page eject */
  258.  
  259. void makename(dest, tmpfn, source)
  260. char *dest, *tmpfn, *source;
  261. {
  262.     int i;
  263.  
  264.     /* user and drive */
  265.     while (*tmpfn)
  266.         *dest++ = *tmpfn++;
  267.  
  268.     /* file name and type */
  269.     for (i = 1; i < 12; i++)
  270.     {
  271.         if ((source[i] &= 0x7f) == ' ')
  272.             continue;
  273.         if (i == 9)
  274.             *dest++ = '.';
  275.         *dest++ = source[i];
  276.     }
  277.     *dest = '\0';
  278. }
  279.  
  280.  
  281. int match(f1ptr, f2ptr)
  282. char *f1ptr, *f2ptr;
  283. {
  284.     char c;
  285.  
  286.     while (c = *f1ptr++)
  287.     {
  288.         switch (c)
  289.         {
  290.         case '?' :
  291.             if (*f2ptr && *f2ptr != '.')
  292.                 f2ptr++;
  293.             else
  294.                 return FALSE;
  295.             break;
  296.         case '*' :
  297.             while (*f1ptr && (*f1ptr++ != '.'))
  298.                 ;
  299.             while (*f2ptr && (*f2ptr++ != '.'))
  300.                 ;
  301.             break;
  302.         default :
  303.             if (c != *f2ptr++)
  304.                 return FALSE;
  305.         }
  306.     }
  307.  
  308.     if (!*f2ptr)
  309.         return TRUE;
  310.     else
  311.         return FALSE;
  312. }
  313.  
  314.  
  315. char *fsplit(bigname, dest, nu, nd, cur_drive, cur_user)
  316. char *bigname, *dest, *nu, *nd, cur_drive, cur_user;
  317. {
  318.     /* parse or set drive/user and set pointer to return filename */
  319.     if ((isdigit(bigname[0]) && (bigname[1] == '/'))
  320.         || (isdigit(bigname[0]) && isdigit(bigname[1]) 
  321.         && (bigname[2] == '/')))
  322.     {
  323.         *nu = atoi(bigname);
  324.         while (*bigname++ != '/')
  325.             ;
  326.     }
  327.     else
  328.         *nu = cur_user;
  329.     if (isalpha(bigname[0]) && (bigname[1] == ':'))
  330.     {
  331.         *nd = toupper(bigname[0]) - 'A';
  332.         bigname += 2;
  333.     }
  334.     else
  335.         *nd = cur_drive;
  336.  
  337.     /* put drive/user as uu/d: into dest array */
  338.     *dest++ = *nu / 10 + '0';
  339.     *dest++ = *nu % 10 + '0';
  340.     *dest++ = '/';
  341.     *dest++ = *nd + 'A';
  342.     *dest++ = ':';
  343.     *dest = '\0';
  344.  
  345.     return bigname;
  346. }
  347.  
  348.  
  349.         /* page eject */
  350.  
  351. #if NEED_DU_UD
  352. int du_ud(fname, temp)
  353. char *fname, *temp;
  354. {
  355.     int i, j, l;
  356.  
  357.     /* Set j = pointer to ':'        */
  358.     /* Exit if no du: or #/d: prefix    */
  359.     for (j = 0; fname[j] != ':'; j++)
  360.         if (fname[j] == NULL)
  361.             return 0;
  362.  
  363.     /* Exit if prefix already #/d:        */
  364.     for (i = 1; i < j; i++)
  365.         if (fname[i] == '/')
  366.             return 0;
  367.  
  368.     /* Set i = pointer to 1st user digit or to '?' */
  369.     /* if 'd:' only, then no userno and return <0>*/
  370.     for (i = 0; (isdigit(fname[i]) == FALSE) && (fname[i] != '?'); i++)
  371.         if (i == 0 && j == 1)
  372.             return 0;
  373.  
  374.     /* errors in du: designator:    */
  375.     /* 1st char not alpha or digit     */
  376.     /* neither 1st or 2nd char digit */
  377.     else
  378.         if (i == 1 && !isalpha(fname[0]))
  379.         return ERROR;
  380.     else
  381.         if (i > 1)
  382.         return ERROR;
  383.  
  384.     /* Now construct new file image in temp    */
  385.     /* First copy the user number        */
  386.     l = 0;
  387.     while (i < j)
  388.         temp[l++] = fname[i++];
  389.     temp[l++] = '/';
  390.     /* Then the drive designator if present    */
  391.     if (isalpha(fname[0]))
  392.     {
  393.         temp[l++] = fname[0];
  394.         temp[l++] = ':';
  395.     }
  396.     /* Then the filename            */
  397.     strcpy(&temp[l], &fname[j + 1]);
  398.  
  399.     return 1;
  400. }
  401. /* END OF DU_UD        */
  402. #endif
  403.  
  404.