home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume8 / make.gy / part01 / tstring.c < prev   
Encoding:
C/C++ Source or Header  |  1989-11-02  |  5.3 KB  |  320 lines

  1. /*
  2.  * tstring.c
  3.  *
  4.  * 88-10-01 v1.0    created by greg yachuk, placed in the public domain
  5.  * 88-10-06 v1.1    changed prerequisite list handling
  6.  * 88-11-11 v1.2    fixed some bugs and added environment variables
  7.  * 89-07-12 v1.3    stop appending shell commands, and flush output
  8.  * 89-08-01 v1.4 AB    lots of new options and code
  9.  * 89-10-30 v1.5 greggy    -f -S -q options, took some changes from v1.4
  10.  *
  11.  */
  12. #include <stdio.h>
  13. #include <ctype.h>
  14. #include <malloc.h>
  15. #include <string.h>
  16.  
  17. #include "tstring.h"
  18.  
  19.  
  20. char   *
  21. talloc(n)
  22. int     n;
  23. {
  24.     register char *s;
  25.  
  26.     s = malloc(n);
  27.     if (s == NULL)
  28.         terror(1, "no free memory");
  29.     return (s);
  30. }
  31.  
  32.  
  33. char   *
  34. trealloc(s, n)
  35. register char *s;
  36. int     n;
  37. {
  38.     s = realloc(s, n);
  39.     if (s == NULL)
  40.         talloc(n);    /* force an error */
  41.     return (s);
  42. }
  43.  
  44.  
  45. char   *
  46. tstrncpy(s, n)
  47. register char *s;
  48. int     n;
  49. {
  50.     s = strncpy(talloc(n + 1), s, n);
  51.     s[n] = '\0';
  52.     return (s);
  53. }
  54.  
  55.  
  56. terror(n, s)
  57. int     n;
  58. char   *s;
  59. {
  60.     fputs("Make: ", stderr);
  61.     fputs(s, stderr);
  62.     putc('\n', stderr);
  63.     if (n)
  64.         exit(n);
  65. }
  66.  
  67.  
  68. /*
  69.  * tstrspan -    move to the end of a quoted string, ignoring escaped quotes
  70.  */
  71. char   *
  72. tstrspan(str)
  73. char   *str;
  74. {
  75.     char    quote;
  76.  
  77.     if (*str != '\'' && *str != '"')
  78.         return (str + 1);
  79.  
  80.     quote = *str++;
  81.  
  82.     while (*str && *str != quote)
  83.     {
  84.         /* check for escaped quote */
  85.         if (*str == '\\' && str[1] == quote)
  86.             ++str;
  87.         ++str;
  88.     }
  89.  
  90.     return (str);
  91. }
  92.  
  93.  
  94. /*
  95.  * tunquote -    remove quotes from a string
  96.  */
  97. char   *
  98. tunquote(str)
  99. char   *str;
  100. {
  101.     char   *s;
  102.     char   *d;
  103.  
  104.     d = s = str;
  105.  
  106.     while (*s)
  107.     {
  108.         while (*s && *s == '"')
  109.             ++s;
  110.  
  111.         while (*s && *s != '"')
  112.             *d++ = *s++;
  113.     }
  114.  
  115.     *d = '\0';
  116.  
  117.     return (str);
  118. }
  119.  
  120.  
  121. /*
  122.  * tsplit -    split a string into two components, normally a directory
  123.  *        path and a filename.  If a pointer to a directory is
  124.  *        supplied, a string is allocated to contain the directory.
  125.  *        The filename is returned as a pointer into the supplied
  126.  *        string.
  127.  */
  128. char   *
  129. tsplit(s, seps, dp)
  130. char   *s;
  131. char   *seps;
  132. char  **dp;
  133. {
  134.     char   *d;        /* directory portion */
  135.     char   *f;        /* file portion */
  136.  
  137.     d = s;
  138.  
  139.     /* find the final separator */
  140.     while ((f = strpbrk(d, seps)) != NULL)
  141.         d = f + 1;
  142.  
  143.     /* back up to final component */
  144.     f = d;
  145.  
  146.     /* if we are still at the beginning, there was no Directory */
  147.     if (d == s || dp == NULL)
  148.         d = NULL;
  149.     else
  150.     {
  151.         int     len;
  152.  
  153.         /*
  154.          * by the time we get here, d points to the final separator
  155.          * char.  we can substitute a NULL for this sep-char.  Thus,
  156.          * we don't need to add 1 in the following length
  157.          * calculation.
  158.          */
  159.         len = d - s;
  160.  
  161.         d = talloc(len);
  162.         d[--len] = '\0';
  163.         while (--len >= 0)
  164.             d[len] = s[len];
  165.     }
  166.  
  167.     if (dp != NULL)
  168.         *dp = d;
  169.  
  170.     return (f);
  171. }
  172.  
  173.  
  174. /*
  175.  * token    - take an input string and return a token each call
  176.  *        - default token delimiter characters are `isspace()'
  177.  *        - separator chars are in addition to `isspace()'
  178.  *        - text between quotes (" and ') is a single token
  179.  *        - if requested, the separator char is returned
  180.  *
  181.  *    called as    s = token(string, seps, &schar);
  182.  *        or    s = token(string, NULL, NULL);
  183.  *
  184.  *    followed by    s = token(NULL, seps, NULL);
  185.  *        or    s = token(NULL, NULL, &schar);
  186.  *
  187.  *    returns NULL when no more tokens are available
  188.  */
  189. char   *
  190. token(s, sep, schar)
  191. char   *s;
  192. char   *sep;
  193. char   *schar;
  194. {
  195.     static char *olds = NULL;
  196.  
  197.     if (s)
  198.         olds = s;    /* we are starting all over again */
  199.  
  200.     if (schar)
  201.         *schar = '\0';
  202.  
  203.     if (!olds || !*olds)
  204.         return (NULL);    /* no tokens left */
  205.  
  206.     while (isspace(*olds) || (sep && strchr(sep, *olds)))
  207.         ++olds;        /* skip leading spaces and sep's */
  208.  
  209.     if (*olds == NULL)
  210.         return (NULL);    /* remainder is all separator's */
  211.  
  212.     s = olds;
  213.  
  214.     while (*olds)
  215.     {
  216.         if (isspace(*olds) || (sep && strchr(sep, *olds)))
  217.         {
  218.             if (schar)
  219.                 *schar = *olds;
  220.             *olds++ = '\0';    /* delimit the token */
  221.             return (s);
  222.         }
  223.         else if (*olds == '"' || *olds == '\'')
  224.         {
  225.             olds = tstrspan(olds);
  226.             if (*olds != '\0')
  227.                 ++olds;    /* didn't hit eos, so skip quote */
  228.         }
  229.         else
  230.             ++olds;    /* otherwise, pass over char */
  231.     }
  232.  
  233.     olds = NULL;
  234.     return (s);        /* return last token */
  235. }
  236.  
  237.  
  238. /*
  239.  * tokenize    - chop a string up into an array of (char *)'s
  240.  */
  241. char  **
  242. tokenize(input)
  243. char   *input;
  244. {
  245.     char  **argv;
  246.     register int argc = 0;
  247.     register int alen;
  248.  
  249.     alen = 20;        /* good initial guess */
  250.     argv = (char **) talloc((alen + 1) * sizeof(char *));
  251.  
  252.     input = token(input, NULL, NULL);    /* use default separators */
  253.     while (input)
  254.     {
  255.         if (alen == argc)
  256.             argv = (char **) trealloc((char *) argv,
  257.                          (alen <<= 1) * sizeof(char *));
  258.         argv[argc++] = input;
  259.         input = token(NULL, NULL, NULL);
  260.     }
  261.  
  262.     argv[argc] = NULL;    /* mark end of array */
  263.  
  264.     return (argv);
  265. }
  266.  
  267.  
  268. /*
  269.  * tgets    - read input, swallowing escaped newlines as necessary
  270.  */
  271. char   *
  272. tgets(fd)
  273. FILE   *fd;
  274. {
  275.     static char *input = NULL;
  276.     static int inlen = 0;
  277.     register char *ep;
  278.     int     len;
  279.  
  280.     if (inlen == 0)
  281.         input = talloc(inlen = 162);
  282.  
  283.     input[inlen - 2] = '\n';
  284.     ep = input - 1;
  285.     while ((fgets(input, inlen, fd)) != NULL)
  286.     {
  287.         for (;;)
  288.         {
  289.             while (input[inlen - 2] != '\n' && input[inlen - 2] != '\0')
  290.             {
  291.                 len = inlen;
  292.                 input = trealloc(input, inlen <<= 1);
  293.                 ep = &input[len - 2];
  294.                 input[inlen - 2] = '\n';
  295.                 fgets(ep + 1, len + 1, fd);
  296.             }
  297.  
  298.             while (*++ep);
  299.             *--ep = '\0';
  300.             do
  301.             {
  302.                 --ep;
  303.             } while (ep >= input && isspace(*ep));
  304.  
  305.             if (ep > input && *ep == '\\' && *--ep != '\\')
  306.                 fgets(ep + 1, inlen - (ep - input) - 1, fd);
  307.             else
  308.                 break;
  309.         }
  310.  
  311.         return (input);
  312.     }
  313.  
  314.     inlen = 0;
  315.     tfree(input);
  316.     input = NULL;
  317.  
  318.     return (NULL);
  319. }
  320.