home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 4 / FreshFish_May-June1994.bin / bsd / src / make / make-amiga / str.c < prev    next >
C/C++ Source or Header  |  1993-09-23  |  9KB  |  340 lines

  1. /*-
  2.  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
  3.  * Copyright (c) 1988, 1989 by Adam de Boor
  4.  * Copyright (c) 1989 by Berkeley Softworks
  5.  * All rights reserved.
  6.  *
  7.  * This code is derived from software contributed to Berkeley by
  8.  * Adam de Boor.
  9.  *
  10.  * Redistribution and use in source and binary forms, with or without
  11.  * modification, are permitted provided that the following conditions
  12.  * are met:
  13.  * 1. Redistributions of source code must retain the above copyright
  14.  *    notice, this list of conditions and the following disclaimer.
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in the
  17.  *    documentation and/or other materials provided with the distribution.
  18.  * 3. All advertising materials mentioning features or use of this software
  19.  *    must display the following acknowledgement:
  20.  *    This product includes software developed by the University of
  21.  *    California, Berkeley and its contributors.
  22.  * 4. Neither the name of the University nor the names of its contributors
  23.  *    may be used to endorse or promote products derived from this software
  24.  *    without specific prior written permission.
  25.  *
  26.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  27.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  30.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  32.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  33.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  34.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  35.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  36.  * SUCH DAMAGE.
  37.  */
  38.  
  39. #ifndef lint
  40. static char     sccsid[] = "@(#)str.c    5.8 (Berkeley) 6/1/90";
  41. #endif                /* not lint */
  42.  
  43. #include "make.h"
  44.  
  45. /*-
  46.  * str_concat --
  47.  *    concatenate the two strings, inserting a space or slash between them,
  48.  *    freeing them if requested.
  49.  *
  50.  * returns --
  51.  *    the resulting string in allocated space.
  52.  */
  53. char *
  54. str_concat(s1, s2, flags)
  55.     char *s1, *s2;
  56.     int flags;
  57. {
  58.     register int len1, len2;
  59.     register char *result;
  60.  
  61.     /* get the length of both strings */
  62.     len1 = strlen(s1);
  63.     len2 = strlen(s2);
  64.  
  65.     /* allocate length plus separator plus EOS */
  66.     result = emalloc((u_int)(len1 + len2 + 2));
  67.  
  68.     /* copy first string into place */
  69.     bcopy(s1, result, len1);
  70.  
  71.     /* add separator character */
  72.     if (flags & STR_ADDSPACE) {
  73.         result[len1] = ' ';
  74.         ++len1;
  75.     } else if (flags & STR_ADDSLASH) {
  76.         result[len1] = '/';
  77.         ++len1;
  78.     }
  79.  
  80.     /* copy second string plus EOS into place */
  81.     bcopy(s2, result + len1, len2 + 1);
  82.  
  83.     /* free original strings */
  84.     if (flags & STR_DOFREE) {
  85.         (void)free(s1);
  86.         (void)free(s2);
  87.     }
  88.     return(result);
  89. }
  90.  
  91. /*-
  92.  * brk_string --
  93.  *    Fracture a string into an array of words (as delineated by tabs or
  94.  *    spaces) taking quotation marks into account.  Leading tabs/spaces
  95.  *    are ignored.
  96.  *
  97.  * returns --
  98.  *    Pointer to the array of pointers to the words.  To make life easier,
  99.  *    the first word is always the value of the .MAKE variable.
  100.  */
  101. char **
  102. brk_string(str, store_argc)
  103.     register char *str;
  104.     int *store_argc;
  105. {
  106.     static int argmax, curlen;
  107.     static char **argv, *buf;
  108.     register int argc, ch;
  109.     register char inquote, *p, *start, *t;
  110.     int len;
  111.  
  112.     /* save off pmake variable */
  113.     if (!argv) {
  114.         argv = (char **)emalloc((argmax = 50) * sizeof(char *));
  115.         argv[0] = Var_Value(".MAKE", VAR_GLOBAL);
  116.     }
  117.  
  118.     /* skip leading space chars.
  119.     for (; *str == ' ' || *str == '\t'; ++str);
  120.  
  121.     /* allocate room for a copy of the string */
  122.     if ((len = strlen(str) + 1) > curlen)
  123.         buf = emalloc(curlen = len);
  124.  
  125.     /*
  126.      * copy the string; at the same time, parse backslashes,
  127.      * quotes and build the argument list.
  128.      */
  129.     argc = 1;
  130.     inquote = '\0';
  131.     for (p = str, start = t = buf;; ++p) {
  132.         switch(ch = *p) {
  133.         case '"':
  134.         case '\'':
  135.             if (inquote)
  136.                 if (inquote == ch)
  137.                     inquote = NULL;
  138.                 else
  139.                     break;
  140.             else
  141.                 inquote = ch;
  142.             continue;
  143.         case ' ':
  144.         case '\t':
  145.             if (inquote)
  146.                 break;
  147.             if (!start)
  148.                 continue;
  149.             /* FALLTHROUGH */
  150.         case '\n':
  151.         case '\0':
  152.             /*
  153.              * end of a token -- make sure there's enough argv
  154.              * space and save off a pointer.
  155.              */
  156.             *t++ = '\0';
  157.             if (argc == argmax) {
  158.                 argmax *= 2;        /* ramp up fast */
  159.                 if (!(argv = (char **)realloc(argv,
  160.                     argmax * sizeof(char *))))
  161.                 enomem();
  162.             }
  163.             argv[argc++] = start;
  164.             start = (char *)NULL;
  165.             if (ch == '\n' || ch == '\0')
  166.                 goto done;
  167.             continue;
  168.         case '\\':
  169.             switch (ch = *++p) {
  170.             case '\0':
  171.             case '\n':
  172.                 /* hmmm; fix it up as best we can */
  173.                 ch = '\\';
  174.                 --p;
  175.                 break;
  176.             case 'b':
  177.                 ch = '\b';
  178.                 break;
  179.             case 'f':
  180.                 ch = '\f';
  181.                 break;
  182.             case 'n':
  183.                 ch = '\n';
  184.                 break;
  185.             case 'r':
  186.                 ch = '\r';
  187.                 break;
  188.             case 't':
  189.                 ch = '\t';
  190.                 break;
  191.             }
  192.             break;
  193.         }
  194.         if (!start)
  195.             start = t;
  196.         *t++ = ch;
  197.     }
  198. done:    argv[argc] = (char *)NULL;
  199.     *store_argc = argc;
  200.     return(argv);
  201. }
  202.  
  203. /*
  204.  * Str_FindSubstring -- See if a string contains a particular substring.
  205.  * 
  206.  * Results: If string contains substring, the return value is the location of
  207.  * the first matching instance of substring in string.  If string doesn't
  208.  * contain substring, the return value is NULL.  Matching is done on an exact
  209.  * character-for-character basis with no wildcards or special characters.
  210.  * 
  211.  * Side effects: None.
  212.  */
  213. char *
  214. Str_FindSubstring(string, substring)
  215.     register char *string;        /* String to search. */
  216.     char *substring;        /* Substring to find in string */
  217. {
  218.     register char *a, *b;
  219.  
  220.     /*
  221.      * First scan quickly through the two strings looking for a single-
  222.      * character match.  When it's found, then compare the rest of the
  223.      * substring.
  224.      */
  225.  
  226.     for (b = substring; *string != 0; string += 1) {
  227.         if (*string != *b)
  228.             continue;
  229.         a = string;
  230.         for (;;) {
  231.             if (*b == 0)
  232.                 return(string);
  233.             if (*a++ != *b++)
  234.                 break;
  235.         }
  236.         b = substring;
  237.     }
  238.     return((char *) NULL);
  239. }
  240.  
  241. /*
  242.  * Str_Match --
  243.  * 
  244.  * See if a particular string matches a particular pattern.
  245.  * 
  246.  * Results: Non-zero is returned if string matches pattern, 0 otherwise. The
  247.  * matching operation permits the following special characters in the
  248.  * pattern: *?\[] (see the man page for details on what these mean).
  249.  * 
  250.  * Side effects: None.
  251.  */
  252. Str_Match(string, pattern)
  253.     register char *string;        /* String */
  254.     register char *pattern;        /* Pattern */
  255. {
  256.     char c2;
  257.  
  258.     for (;;) {
  259.         /*
  260.          * See if we're at the end of both the pattern and the
  261.          * string. If, we succeeded.  If we're at the end of the
  262.          * pattern but not at the end of the string, we failed.
  263.          */
  264.         if (*pattern == 0)
  265.             return(!*string);
  266.         if (*string == 0 && *pattern != '*')
  267.             return(0);
  268.         /*
  269.          * Check for a "*" as the next pattern character.  It matches
  270.          * any substring.  We handle this by calling ourselves
  271.          * recursively for each postfix of string, until either we
  272.          * match or we reach the end of the string.
  273.          */
  274.         if (*pattern == '*') {
  275.             pattern += 1;
  276.             if (*pattern == 0)
  277.                 return(1);
  278.             while (*string != 0) {
  279.                 if (Str_Match(string, pattern))
  280.                     return(1);
  281.                 ++string;
  282.             }
  283.             return(0);
  284.         }
  285.         /*
  286.          * Check for a "?" as the next pattern character.  It matches
  287.          * any single character.
  288.          */
  289.         if (*pattern == '?')
  290.             goto thisCharOK;
  291.         /*
  292.          * Check for a "[" as the next pattern character.  It is
  293.          * followed by a list of characters that are acceptable, or
  294.          * by a range (two characters separated by "-").
  295.          */
  296.         if (*pattern == '[') {
  297.             ++pattern;
  298.             for (;;) {
  299.                 if ((*pattern == ']') || (*pattern == 0))
  300.                     return(0);
  301.                 if (*pattern == *string)
  302.                     break;
  303.                 if (pattern[1] == '-') {
  304.                     c2 = pattern[2];
  305.                     if (c2 == 0)
  306.                         return(0);
  307.                     if ((*pattern <= *string) &&
  308.                         (c2 >= *string))
  309.                         break;
  310.                     if ((*pattern >= *string) &&
  311.                         (c2 <= *string))
  312.                         break;
  313.                     pattern += 2;
  314.                 }
  315.                 ++pattern;
  316.             }
  317.             while ((*pattern != ']') && (*pat