home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / plotting / imagetoo / imagetl1.lha / Imagetool / src+obj / wildcard.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-03-11  |  11.8 KB  |  604 lines

  1. /* cat > headers/wildcard.h << "EOF" */
  2. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  3. /* wildcard.h: header for wildcard.c file        */
  4. /*           The wildcard routine takes an input    */
  5. /*           wildcard pattern and returns a vector of    */
  6. /*           filename strings that match the given    */
  7. /*           wildcard pattern. The returned vector    */
  8. /*           ends with a NULL pointer. Output strings    */
  9. /*           are sorted in lexicographical order. The    */
  10. /*           malloc function is called to allocate    */
  11. /*           temporary space for the returned        */
  12. /*           2-dimension character array. In case    */
  13. /*           anything goes wrong, a char pointer    */
  14. /*           that contains NULL is returned.        */
  15. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  16. /* SCCS information: %W%    %G% - NCSA */
  17.  
  18. #define    wildcard_h    1
  19.  
  20. #include "all.h"
  21. #include "newext.h"
  22.  
  23.     static struct argnod    *gchain;
  24.     static char           *entry;
  25.     static char        *buffer, *bufptr;
  26.     static char         *nullname[1];
  27.  
  28. /* EOF */
  29. /* cat > src+obj/wildcard/addg.c << "EOF" */
  30. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  31. /* addg: The addg adds the string of concatinating    */
  32. /*     "as1""as2"'/'"++as3" at the end of the global    */
  33. /*     list headed by gchain.                */
  34. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  35. /* SCCS information: %W%    %G% - NCSA */
  36.  
  37. /* #include "wildcard.h" */
  38.  
  39. addg (as1, as2, as3)
  40.     char           *as1, *as2, *as3;
  41. {
  42.     register char  *s1, *s2;
  43.     register int    c;
  44.     struct argnod  *args, *rchain;
  45.  
  46.     args = (struct argnod *) bufptr;
  47.     args->argnxt = NULL;
  48.     if (gchain != NULL)
  49.     {
  50.         rchain = gchain;
  51.         while (rchain->argnxt != NULL)
  52.             rchain = rchain->argnxt;
  53.         rchain->argnxt = args;
  54.     }
  55.     else
  56.     {
  57.         gchain = args;
  58.     }
  59.  
  60.     s2 = args->argval;
  61.     s1 = as1;
  62.     while (c = *s1++)
  63.     {
  64.         if ((c &= STRIP) == 0)
  65.         {
  66.             *s2++ = '/';
  67.             break;
  68.         }
  69.         *s2++ = c;
  70.     }
  71.     s1 = as2;
  72.     while (*s2 = *s1++)
  73.         s2++;
  74.     if (s1 = as3)
  75.     {
  76.         *s2++ = '/';
  77.         while (*s2++ = *++s1);
  78.     }
  79.     bufptr += strlen (args->argval) + sizeof (args->argnxt) + BYTESPERWORD;
  80.     bufptr = (char *) ((unsigned) bufptr & ~(BYTESPERWORD - 1));
  81. }
  82. /* EOF */
  83. /* cat > src+obj/wildcard/gbrace.c << "EOF" */
  84. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  85. /* gbrace: The gbrace routine splits braces into    */
  86. /*       different patterns and puts them in a list    */
  87. /*       (gchain is the head pointer). It returns 0    */
  88. /*       when no braces found, -1 when syntax error    */
  89. /*       or a count indicates how many patterns have    */
  90. /*       been generated.                */
  91. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  92. /* SCCS information: %W%    %G% - NCSA */
  93.  
  94. /* #include "wildcard.h" */
  95.  
  96. gbrace (s1)
  97.     char           *s1;
  98. {
  99.     char           *sp, *tp;
  100.     char            s2[MAXNAMLEN + 1];
  101.     char            s3[MAXNAMLEN + 1];
  102.     int             i, cnt = 0;
  103.  
  104.     sp = s1;
  105.     while (*sp != '{')
  106.     {
  107.         if (*sp == '\0')
  108.         {
  109.             return (0);
  110.         }
  111.         sp++;
  112.     }
  113.     tp = s2;
  114.     *sp = '\0';
  115.     while (*++sp != '}')
  116.     {
  117.         if (*sp == ' ' || *sp == '\t' || *sp == '\0')
  118.         {
  119.             return (-1);
  120.         }
  121.         if (*sp == ',')
  122.         {
  123.             cnt++;
  124.             *tp++ = '\0';
  125.         }
  126.         else
  127.             *tp++ = *sp;
  128.     }
  129.     cnt++;
  130.     *tp = '\0';
  131.     tp = s2;
  132.     ++sp;
  133.     for (i = 0; i < cnt; i++)
  134.     {
  135.         strcpy (s3, tp);
  136.         addg (s1, strcat (s3, sp), NULL);
  137.         tp += strlen (tp) + 1;
  138.     }
  139.     return (cnt);
  140. }
  141. /* EOF */
  142. /* cat > src+obj/wildcard/gexpand.c << "EOF" */
  143. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  144. /* gexpand: This subroutine expands wildcard pattern    */
  145. /*        string, i.e. as, into a filename list    */
  146. /*        headed by gchain. The number of filenames    */
  147. /*        found is returned.                */
  148. /*        "*" in a pattern matches r.e "c*"        */
  149. /*        "?" in a pattern matches r.e. "c"        */
  150. /*        "[...]" in a pattern matches character    */
  151. /*        class                    */
  152. /*        "[...a-z...]" in a pattern matches a    */
  153. /*        through z.                */
  154. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  155. /* SCCS information: %W%    %G% - NCSA */
  156.  
  157. /* #include "wildcard.h" */
  158.  
  159. gexpand (as)
  160.     char           *as;
  161. {
  162.     register char  *s, *cs;
  163.     int             count = 0;
  164.     DIR            *dirp;
  165.     bool            left = 0;
  166.     char           *rescan = NULL;
  167.     struct argnod  *schain = gchain;
  168.  
  169.     s = cs = as;
  170.  
  171.         /* check for meta chars */
  172.     for (;;)
  173.     {
  174.         switch (*cs++)
  175.         {
  176.             case '/':
  177.                 left = 0;
  178.                 continue;
  179.             case '[':
  180.                 left++;
  181.                 continue;
  182.             case ']':
  183.                 if (left == 0)
  184.                     continue;
  185.             case '?':
  186.             case '*':
  187.             case '\0':
  188.                 cs--;
  189.                 break;
  190.             default:
  191.                 continue;
  192.         }
  193.         break;
  194.     }
  195.  
  196.         /* find the prefix that needs not be expanded */
  197.     for (;;)
  198.     {
  199.         if (cs == s)
  200.         {
  201.             s = "";
  202.             break;
  203.         }
  204.         else if (*--cs == '/')
  205.         {
  206.             *cs = '\0';
  207.             if (s == cs)
  208.                 s = "/";
  209.             break;
  210.         }
  211.     }
  212.  
  213.     dirp = opendir (*s ? s : ".");
  214.     if (*cs == '\0')
  215.         *cs++ = 0200;
  216.  
  217.     if (dirp != NULL)
  218.     {        /* open directory succeed */
  219.         register char  *rs;
  220.         struct direct  *e;
  221.  
  222.             /* check for rescan */
  223.         rs = cs;
  224.         do
  225.         {
  226.             if (*rs == '/')
  227.             {
  228.                 rescan = rs;
  229.                 *rs = '\0';
  230.                 gchain = NULL;
  231.             }
  232.         } while (*rs++);
  233.  
  234.             /* match all dir entries */
  235.         while (e = readdir (dirp))
  236.         {
  237.             strcpy (entry, e->d_name);
  238.             if (entry[0] == '.' && *cs != '.')
  239.                 continue;
  240.             if (gmatch (entry, cs))
  241.             {
  242.                 addg (s, entry, rescan);
  243.                 count++;
  244.             }
  245.         }
  246.         closedir (dirp);
  247.  
  248.             /* not the last dir, recursively matche the rest */
  249.         if (rescan)
  250.         {
  251.             register struct argnod *rchain;
  252.  
  253.             rchain = gchain;
  254.             gchain = schain;
  255.             if (count)
  256.             {
  257.                 count = 0;
  258.                 while (rchain)
  259.                 {
  260.                     count += gexpand (rchain->argval);
  261.                     rchain = rchain->argnxt;
  262.                 }
  263.             }
  264.             *rescan = '/';
  265.         }
  266.     }
  267.  
  268.         /* restore all 0200's back to slash char */
  269.     {
  270.         register char   c;
  271.  
  272.         s = as;
  273.         while (c = *s)
  274.             *s++ = (c & STRIP ? c : '/');
  275.     }
  276.     return (count);
  277. }
  278. /* EOF */
  279. /* cat > src+obj/wildcard/gmatch.c << "EOF" */
  280. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  281. /* gmatch: The function gmatch is to match string s    */
  282. /*       with the regular expression patter p. The    */
  283. /*       string s is usually a file name in a        */
  284. /*       directory file, which does not contain the    */
  285. /*       slash ('/') character. The function returns    */
  286. /*       zero (0) if s and p do not match; returns    */
  287. /*       non-zero otherwise.                */
  288. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  289. /* SCCS information: %W%    %G% - NCSA */
  290.  
  291. /* #include "wildcard.h" */
  292.  
  293. gmatch (s, p)
  294.     register char  *s, *p;
  295. {
  296.     register        scc;
  297.     char            c;
  298.     bool            ok = 0;
  299.     int             lc = 077777;
  300.     int             notflag = 0;
  301.  
  302.     if (scc = *s++)
  303.     {
  304.         if ((scc &= STRIP) == 0)
  305.             scc = 0200;
  306.     }
  307.     switch (c = *p++)
  308.     {
  309.         case '[':
  310.             if (*p == '!')
  311.             {
  312.                 notflag = 1;
  313.                 p++;
  314.             }
  315.             while (c = *p++)
  316.             {
  317.                 if (c == ']')
  318.                     return (ok ? gmatch (s, p) : 0);
  319.                 else if (c == '-')
  320.                 {
  321.                     if (notflag)
  322.                     {
  323.                         if (scc < lc || scc > *(p++))
  324.                             ok++;
  325.                         else
  326.                             return (0);
  327.                     }
  328.                     else if (lc <= scc && scc <= (*p++))
  329.                         ok++;
  330.                 }
  331.                 else
  332.                 {
  333.                     lc = c & STRIP;
  334.                     if (notflag)
  335.                     {
  336.                         if (scc && scc != lc)
  337.                             ok++;
  338.                         else
  339.                             return (0);
  340.                     }
  341.                     else if (scc == lc)
  342.                         ok++;
  343.                 }
  344.             }
  345.             return (0);
  346.         default:
  347.             if ((c & STRIP) != scc)
  348.                 return (0);
  349.         case '?':
  350.             return (scc ? gmatch (s, p) : 0);
  351.         case '*':
  352.             while (*p == '*')
  353.                 p++;
  354.             if (*p == 0)
  355.                 return (1);
  356.             --s;
  357.             while (*s)
  358.             {
  359.                 if (gmatch (s++, p))
  360.                     return (1);
  361.             }
  362.             return (0);
  363.         case '\0':
  364.             return (scc == 0);
  365.     }
  366. }
  367. /* EOF */
  368. /* cat > src+obj/wildcard/gsort.c << "EOF" */
  369. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  370. /* gsort: The shell sorting routine            */
  371. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  372. /* SCCS information: %W%    %G% - NCSA */
  373.  
  374. /* #include "wildcard.h" */
  375.  
  376. gsort (from, to)
  377.     char           *from[], *to[];
  378.  
  379. {
  380.     int             k, m, n;
  381.     register int    i, j;
  382.  
  383.     if ((n = to - from) <= 1)
  384.         return;
  385.     for (j = 1; j <= n; j *= 2);
  386.     for (m = 2 * j - 1; m /= 2;)
  387.     {
  388.         k = n - m;
  389.         for (j = 0; j < k; j++)
  390.         {
  391.             for (i = j; i >= 0; i -= m)
  392.             {
  393.                 register char **fromi;
  394.  
  395.                 fromi = &from[i];
  396.                 if (strcmp (fromi[m], fromi[0]) > 0)
  397.                 {
  398.                     break;
  399.                 }
  400.                 else
  401.                 {
  402.                     char           *s;
  403.  
  404.                     s = fromi[m];
  405.                     fromi[m] = fromi[0];
  406.                     fromi[0] = s;
  407.                 }
  408.             }
  409.         }
  410.     }
  411. }
  412. /* EOF */
  413. /* cat > src+obj/wildcard/wildcard.c << "EOF" */
  414. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  415. /* wildcard: main wildcard routine. Error number    */
  416. /*         returned for handling elsewhere.        */
  417. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  418. /* SCCS information: %W%    %G% - NCSA */
  419.  
  420. /* BUG: 1. Can't handle path = / properly!
  421.        Workaround: Add a period to the end. */
  422.  
  423. /* #include "wildcard.h" */
  424.  
  425. char          **
  426. wildcard (p, err)
  427.     char           *p;    /* input */
  428.     int            *err;    /* returns =    0 - No error.
  429.                         1 - Syntax error.
  430.                         2 - Memory allocation error */
  431. {
  432.     int             i, count = 0, bufsz = 0;
  433.     char            c, *ss, *sp;
  434.     char          **name;
  435.     char            string[MAXNAMLEN + 1];
  436.     register struct argnod *rchain, *schain;
  437.     char           *getenv ();
  438.  
  439.     char         stack_entry[MAXNAMLEN+1];
  440.     char        stack_buffer[BUFFERSIZ];
  441.  
  442.     *err = 0;
  443.  
  444.     nullname[0] = NULL;
  445.     gchain = NULL;
  446.     entry = stack_entry;
  447.     buffer = stack_buffer;
  448.  
  449. /*    entry = (char *) alloca (MAXNAMLEN+1);
  450.     if ((buffer = (char *) alloca (BUFFERSIZ)) == NULL)
  451.     {
  452.         *err = 2;
  453.         return (nullname);
  454.     }*/
  455.     bufptr = buffer + (BYTESPERWORD - 1);
  456.     bufptr = (char *) ((unsigned) bufptr & ~(BYTESPERWORD - 1));
  457.  
  458.         /* eliminate starting and trailing white space */
  459.     while (*p == ' ' || *p == '\t')
  460.         p++;
  461.     if ((i = strlen (p)) == 0)
  462.         return (nullname);
  463.     do
  464.     {
  465.         p[i--] = '\0';
  466.     } while (p[i] == ' ' || p[i] == '\t');
  467.  
  468.         /* eliminate trailing /'s except for the first */
  469.     i++;
  470.     do
  471.     {
  472.         p[i--] = '\0';
  473.     } while (p[i] == '/' && i > 0);
  474.  
  475.         /* BUG workaround: Add a period to fix the / problem */
  476.     if ( p[i] == '/')
  477.     {
  478.         p[++i] = '.';
  479.         p[++i] = '\0';
  480.     }
  481.  
  482.         /* handle the case speciall
  483. /* printf */
  484. /* sprintf (wkstr2, "p = %s", p);
  485. msg_write (wkstr2); */
  486.  
  487.         /* handle multiple brace pairs in a loop */
  488.  
  489.     addg (p, "", NULL);
  490.     do
  491.     {
  492.         rchain = gchain;
  493.         gchain = NULL;
  494.         while (rchain != NULL)
  495.         {
  496.             switch (gbrace (rchain->argval))
  497.             {
  498.                 case -1:
  499.                     *err = 1;
  500.                     return (nullname);
  501.                 case 0:
  502.                     break;
  503.                 default:
  504.                     rchain = rchain->argnxt;
  505.                     continue;
  506.             }
  507.             break;
  508.         }
  509.     } while (gchain != NULL);
  510.  
  511.         /* input pattern could really be a list because of braces
  512.            the following loop processes one pattern at a time */
  513.     schain = rchain;
  514.     do
  515.     {
  516.         int             rval;
  517.  
  518.         string[0] = '\0';
  519.         ss = rchain->argval;
  520.  
  521.             /* substitute ~[user] with an appropriate home dir */
  522.         if (*ss == '~')
  523.         {
  524.             if (isalpha (*++ss))
  525.             {
  526.                 struct passwd  *pp;
  527.  
  528.                 sp = ss;
  529.                 while (isalpha (*++ss));
  530.                 c = *ss;
  531.                 *ss = '\0';
  532.                 if ((pp = getpwnam (sp)) == NULL)
  533.                     return (nullname);
  534.                 *ss = c;
  535.                 strcpy (string, pp->pw_dir);
  536.             }
  537.             else
  538.             {
  539.                 if ((sp = getenv ("HOME")) == NULL)
  540.                     return (nullname);
  541.                 strcpy (string, sp);
  542.             }
  543.             if (*ss != '/' && *ss != '\0')
  544.                 return (nullname);
  545.         }
  546.  
  547.             /* do the real expansion and the results are appended
  548.                to a list headed by gchain */
  549.         rval = gexpand (strcat (string, ss));
  550.  
  551.             /* remember the count for each pattern which is used
  552.                for sorting with groups */
  553.         count += rval;
  554.         rchain->argval[0] = rval;
  555.     } while ((rchain = rchain->argnxt) != NULL);
  556.  
  557.         /* allocate tmp space for output */
  558.     name = (char **) calloc (count + 1, sizeof (char *));
  559.     if (name == NULL)
  560.     {
  561.         *err = 2;
  562.         return (nullname);
  563.     }
  564.     rchain = gchain;
  565.     for (i = 0; i < count; i++)
  566.     {
  567.         bufsz += strlen (rchain->argval) + 1;
  568.         rchain = rchain->argnxt;
  569.     }
  570.     bufptr = (char *) malloc (bufsz);
  571.     if (bufptr == NULL)
  572.     {
  573.         *err = 2;
  574.         return (nullname);
  575.     }
  576.  
  577.         /* copy the matched strings to the output buffer */
  578.     rchain = gchain;
  579.     for (i = 0; i < count; i++)
  580.     {
  581.         name[i] = bufptr;
  582.         strcpy (name[i], rchain->argval);
  583.         bufptr += strlen (name[i]) + 1;
  584.         rchain = rchain->argnxt;
  585.     }
  586.     name[count] = NULL;
  587.  
  588.         /* sort the output strings group by group */
  589.     rchain = schain;
  590.     i = 0;
  591.     do
  592.     {
  593.         int             j;
  594.  
  595.         j = i + (int) rchain->argval[0];
  596.         gsort (&name[i], &name[j]);
  597.         i = j;
  598.         rchain = rchain->argnxt;
  599.     } while (rchain != NULL);
  600.  
  601.     return (name);
  602. }
  603. /* EOF */
  604.