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