[BACK]Return to str.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / make

Diff for /src/usr.bin/make/str.c between version 1.16 and 1.17

version 1.16, 2000/09/14 13:35:38 version 1.17, 2001/05/03 13:41:11
Line 1 
Line 1 
   /*      $OpenPackages$ */
 /*      $OpenBSD$       */  /*      $OpenBSD$       */
 /*      $NetBSD: str.c,v 1.13 1996/11/06 17:59:23 christos Exp $        */  /*      $NetBSD: str.c,v 1.13 1996/11/06 17:59:23 christos Exp $        */
   
Line 43 
Line 44 
   
 #ifndef lint  #ifndef lint
 #if 0  #if 0
 static char     sccsid[] = "@(#)str.c   5.8 (Berkeley) 6/1/90";  static char     sccsid[] = "@(#)str.c   5.8 (Berkeley) 6/1/90";
 #else  #else
 UNUSED  UNUSED
 static char rcsid[] = "$OpenBSD$";  static char rcsid[] = "$OpenBSD$";
Line 51 
Line 52 
 #endif                          /* not lint */  #endif                          /* not lint */
   
 /*-  /*-
  * str_concat --   * str_concati --
  *      concatenate the two strings, possibly inserting a separator   *      concatenate the two strings, possibly inserting a separator
  *   *
  * returns --   * returns --
  *      the resulting string in allocated space.   *      the resulting string in allocated space.
  */   */
 char *  char *
 str_concat(s1, s2, sep)  str_concati(s1, s2, e2, sep)
     const char *s1, *s2;      const char *s1, *s2, *e2;
     char sep;      int sep;
 {  {
     size_t len1, len2;      size_t len1, len2;
     char *result;      char *result;
   
     /* get the length of both strings */      /* get the length of both strings */
     len1 = strlen(s1);      len1 = strlen(s1);
     len2 = strlen(s2);      len2 = e2 - s2;
   
     /* space for separator */      /* space for separator */
     if (sep)      if (sep)
Line 78 
Line 79 
     memcpy(result, s1, len1);      memcpy(result, s1, len1);
   
     /* add separator character */      /* add separator character */
     if (sep)      if (sep)
         result[len1-1] = sep;          result[len1-1] = sep;
   
     /* copy second string plus EOS into place */      /* copy second string plus EOS into place */
Line 93 
Line 94 
  *      are ignored.   *      are ignored.
  *   *
  * returns --   * returns --
  *      Pointer to the array of pointers to the words.  To make life easier,   *      Pointer to the array of pointers to the words.  To make life easier,
  *      the first word is always the value of the .MAKE variable.   *      the first word is always the value of the .MAKE variable.
  */   */
 char **  char **
 brk_string(str, store_argc, expand, buffer)  brk_string(str, store_argc, buffer)
         const char *str;      const char *str;
         int *store_argc;      int *store_argc;
         Boolean expand;      char **buffer;
         char **buffer;  
 {  {
         register int argc, ch;      int argc;
         char inquote;      char ch;
         const char *p;      char inquote;
         char *start, *t;      const char *p;
         size_t len;      char *start, *t;
         int argmax = 50;      size_t len;
         size_t curlen = 0;      int argmax = 50;
         char **argv = (char **)emalloc((argmax + 1) * sizeof(char *));      size_t curlen = 0;
       char **argv = emalloc((argmax + 1) * sizeof(char *));
   
         /* skip leading space chars. */      /* skip leading space chars. */
         for (; *str == ' ' || *str == '\t'; ++str)      for (; *str == ' ' || *str == '\t'; ++str)
                 continue;          continue;
   
         /* allocate room for a copy of the string */      /* allocate room for a copy of the string */
         if ((len = strlen(str) + 1) > curlen)      if ((len = strlen(str) + 1) > curlen)
                 *buffer = emalloc(curlen = len);          *buffer = emalloc(curlen = len);
   
         /*      /*
          * copy the string; at the same time, parse backslashes,       * copy the string; at the same time, parse backslashes,
          * quotes and build the argument list.       * quotes and build the argument list.
          */       */
         argc = 0;      argc = 0;
         inquote = '\0';      inquote = '\0';
         for (p = str, start = t = *buffer;; ++p) {      for (p = str, start = t = *buffer;; ++p) {
                 switch(ch = *p) {          switch (ch = *p) {
                 case '"':          case '"':
                 case '\'':          case '\'':
                         if (inquote) {              if (inquote) {
                                 if (inquote == ch)                  if (inquote == ch)
                                         inquote = '\0';                      inquote = '\0';
                                 else                  else
                                         break;                      break;
                         } else {              } else {
                                 inquote = (char) ch;                  inquote = ch;
                                 /* Don't miss "" or '' */                  /* Don't miss "" or '' */
                                 if (start == NULL && p[1] == inquote) {                  if (start == NULL && p[1] == inquote) {
                                         start = t + 1;                      start = t + 1;
                                         break;                      break;
                                 }  
                         }  
                         if (!expand) {  
                                 if (!start)  
                                         start = t;  
                                 *t++ = ch;  
                         }  
                         continue;  
                 case ' ':  
                 case '\t':  
                 case '\n':  
                         if (inquote)  
                                 break;  
                         if (!start)  
                                 continue;  
                         /* FALLTHROUGH */  
                 case '\0':  
                         /*  
                          * end of a token -- make sure there's enough argv  
                          * space and save off a pointer.  
                          */  
                         if (!start)  
                             goto done;  
   
                         *t++ = '\0';  
                         if (argc == argmax) {  
                                 argmax *= 2;            /* ramp up fast */  
                                 argv = (char **)erealloc(argv,  
                                     (argmax + 1) * sizeof(char *));  
                         }  
                         argv[argc++] = start;  
                         start = (char *)NULL;  
                         if (ch == '\n' || ch == '\0')  
                                 goto done;  
                         continue;  
                 case '\\':  
                         if (!expand) {  
                                 if (!start)  
                                         start = t;  
                                 *t++ = '\\';  
                                 ch = *++p;  
                                 break;  
                         }  
   
                         switch (ch = *++p) {  
                         case '\0':  
                         case '\n':  
                                 /* hmmm; fix it up as best we can */  
                                 ch = '\\';  
                                 --p;  
                                 break;  
                         case 'b':  
                                 ch = '\b';  
                                 break;  
                         case 'f':  
                                 ch = '\f';  
                                 break;  
                         case 'n':  
                                 ch = '\n';  
                                 break;  
                         case 'r':  
                                 ch = '\r';  
                                 break;  
                         case 't':  
                                 ch = '\t';  
                                 break;  
                         }  
                         break;  
                 }                  }
                 if (!start)              }
                         start = t;              continue;
                 *t++ = (char) ch;          case ' ':
           case '\t':
           case '\n':
               if (inquote)
                   break;
               if (!start)
                   continue;
               /* FALLTHROUGH */
           case '\0':
               /*
                * end of a token -- make sure there's enough argv
                * space and save off a pointer.
                */
               if (!start)
                   goto done;
   
               *t++ = '\0';
               if (argc == argmax) {
                   argmax *= 2;            /* ramp up fast */
                   argv = erealloc(argv, (argmax + 1) * sizeof(char *));
               }
               argv[argc++] = start;
               start = NULL;
               if (ch == '\n' || ch == '\0')
                   goto done;
               continue;
           case '\\':
               switch (ch = *++p) {
               case '\0':
               case '\n':
                   /* hmmm; fix it up as best we can */
                   ch = '\\';
                   --p;
                   break;
               case 'b':
                   ch = '\b';
                   break;
               case 'f':
                   ch = '\f';
                   break;
               case 'n':
                   ch = '\n';
                   break;
               case 'r':
                   ch = '\r';
                   break;
               case 't':
                   ch = '\t';
                   break;
               }
                   break;
         }          }
 done:   argv[argc] = (char *)NULL;          if (!start)
         *store_argc = argc;              start = t;
         return(argv);          *t++ = ch;
       }
   done:
       argv[argc] = NULL;
       *store_argc = argc;
       return argv;
 }  }
   
 /* Iterate through a string word by word,  /* Iterate through a string word by word,
Line 230 
Line 218 
  */   */
 const char *  const char *
 iterate_words(end)  iterate_words(end)
     const char  **end;      const char  **end;
 {  {
     const char  *start, *p;      const char  *start, *p;
     char        state = 0;      char        state = 0;
     start = *end;      start = *end;
   
     while (isspace(*start))      while (isspace(*start))
         start++;          start++;
     if (*start == '\0')      if (*start == '\0')
         return NULL;          return NULL;
   
     for (p = start;; p++)      for (p = start;; p++)
         switch(*p) {          switch(*p) {
             case '\\':              case '\\':
                 if (p[1] != '\0')                  if (p[1] != '\0')
                     p++;                      p++;
                 break;                  break;
             case '\'':              case '\'':
             case '"':              case '"':
                 if (state == *p)                  if (state == *p)
                     state = 0;                      state = 0;
                 else if (state == 0)                  else if (state == 0)
                     state = *p;                      state = *p;
                 break;                  break;
             case ' ':              case ' ':
             case '\t':              case '\t':
                 if (state != 0)                  if (state != 0)
                     break;                      break;
                 /* FALLTHROUGH */                  /* FALLTHROUGH */
             case '\0':              case '\0':
                 *end = p;                  *end = p;
                 return start;                  return start;
             default:              default:
                 break;                  break;
             }              }
 }  }
   
 /*  /*
  * Str_Match --   * Str_Matchi --
  *   *
  * See if a particular string matches a particular pattern.   * See if a particular string matches a particular pattern.
  *   *
Line 277 
Line 265 
  * pattern: *?\[] (see the man page for details on what these mean).   * pattern: *?\[] (see the man page for details on what these mean).
  */   */
 Boolean  Boolean
 Str_Match(string, pattern)  Str_Matchi(string, pattern, end)
     const char *string;                 /* String */      const char *string;                 /* String */
     const char *pattern;                /* Pattern */      const char *pattern;                /* Pattern */
       const char *end;                    /* End of Pattern */
 {  {
     while (*pattern != '\0') {      while (pattern != end) {
         /* Check for a "*" as the next pattern character.  It matches          /* Check for a "*" as the next pattern character.  It matches
          * any substring.  We handle this by calling ourselves           * any substring.  We handle this by calling ourselves
          * recursively for each postfix of string, until either we           * recursively for each postfix of string, until either we
Line 290 
Line 279 
             pattern++;              pattern++;
             /* Skip over contiguous  sequences of `?*', so that recursive              /* Skip over contiguous  sequences of `?*', so that recursive
              * calls only occur on `real' characters.  */               * calls only occur on `real' characters.  */
             while (*pattern == '?' || *pattern == '*') {              while (pattern != end && (*pattern == '?' || *pattern == '*')) {
                 if (*pattern == '?') {                  if (*pattern == '?') {
                     if (*string == '\0')                      if (*string == '\0')
                         return FALSE;                          return FALSE;
Line 299 
Line 288 
                 }                  }
                 pattern++;                  pattern++;
             }              }
             if (*pattern == '\0')              if (pattern == end)
                 return TRUE;                  return TRUE;
             for (; *string != '\0'; string++)              for (; *string != '\0'; string++)
                 if (Str_Match(string, pattern))                  if (Str_Matchi(string, pattern, end))
                     return TRUE;                      return TRUE;
             return FALSE;              return FALSE;
         } else if (*string == '\0')          } else if (*string == '\0')
             return FALSE;              return FALSE;
         /* Check for a "[" as the next pattern character.  It is          /* Check for a "[" as the next pattern character.  It is
          * followed by a list of characters that are acceptable, or           * followed by a list of characters that are acceptable, or
          * by a range (two characters separated by "-").  */           * by a range (two characters separated by "-").  */
         else if (*pattern == '[') {          else if (*pattern == '[') {
             pattern++;              pattern++;
             if (*pattern == '\0')              if (pattern == end)
                 return FALSE;                  return FALSE;
             if (*pattern == '!' || *pattern == '^') {              if (*pattern == '!' || *pattern == '^') {
                 pattern++;                  pattern++;
                 if (*pattern == '\0')                  if (pattern == end)
                         return FALSE;                          return FALSE;
                 /* Negative match */                  /* Negative match */
                 for (;;) {                  for (;;) {
                     if (*pattern == '\\') {                      if (*pattern == '\\') {
                         if (*++pattern == '\0')                          if (++pattern == end)
                             return FALSE;                              return FALSE;
                     }                      }
                     if (*pattern == *string)                      if (*pattern == *string)
                         return FALSE;                          return FALSE;
                     if (pattern[1] == '-') {                      if (pattern[1] == '-') {
                         if (pattern[2] == '\0')                          if (pattern + 2 == end)
                             return FALSE;                              return FALSE;
                         if (*pattern < *string && *string <= pattern[2])                          if (*pattern < *string && *string <= pattern[2])
                             return FALSE;                              return FALSE;
Line 336 
Line 325 
                         pattern += 3;                          pattern += 3;
                     } else                      } else
                         pattern++;                          pattern++;
                     if (*pattern == '\0')                      if (pattern == end)
                         return FALSE;                          return FALSE;
                     /* The test for ']' is done at the end so that ']'                      /* The test for ']' is done at the end so that ']'
                      * can be used at the start of the range without '\' */                       * can be used at the start of the range without '\' */
                     if (*pattern == ']')                      if (*pattern == ']')
                         break;                          break;
                 }                  }
             } else {              } else {
                 for (;;) {                  for (;;) {
                     if (*pattern == '\\') {                      if (*pattern == '\\') {
                         if (*++pattern == '\0')                          if (++pattern == end)
                             return FALSE;                              return FALSE;
                     }                      }
                     if (*pattern == *string)                      if (*pattern == *string)
                         break;                          break;
                     if (pattern[1] == '-') {                      if (pattern[1] == '-') {
                         if (pattern[2] == '\0')                          if (pattern + 2 == end)
                             return FALSE;                              return FALSE;
                         if (*pattern < *string && *string <= pattern[2])                          if (*pattern < *string && *string <= pattern[2])
                             break;                              break;
Line 363 
Line 352 
                         pattern++;                          pattern++;
                     /* The test for ']' is done at the end so that ']'                      /* The test for ']' is done at the end so that ']'
                      * can be used at the start of the range without '\' */                       * can be used at the start of the range without '\' */
                     if (*pattern == '\0' || *pattern == ']')                      if (pattern == end || *pattern == ']')
                         return FALSE;                          return FALSE;
                 }                  }
                 /* Found matching character, skip over rest of class.  */                  /* Found matching character, skip over rest of class.  */
                 while (*pattern != ']') {                  while (*pattern != ']') {
                     if (*pattern == '\\')                      if (*pattern == '\\')
                         pattern++;                          pattern++;
                     /* A non-terminated character class is ok.  */                      /* A non-terminated character class is ok.  */
                     if (*pattern == '\0')                      if (pattern == end)
                         break;                          break;
                     pattern++;                      pattern++;
                 }                  }
Line 382 
Line 371 
             /* If the next pattern character is '\', just strip off the              /* If the next pattern character is '\', just strip off the
              * '\' so we do exact matching on the character that follows.  */               * '\' so we do exact matching on the character that follows.  */
             if (*pattern == '\\') {              if (*pattern == '\\') {
                 if (*++pattern == '\0')                  if (++pattern == end)
                     return FALSE;                      return FALSE;
             }              }
             /* There's no special character.  Just make sure that              /* There's no special character.  Just make sure that
              * the next characters of each string match.  */               * the next characters of each string match.  */
             if (*pattern != *string)              if (*pattern != *string)
                 return FALSE;                  return FALSE;
Line 399 
Line 388 
         return FALSE;          return FALSE;
 }  }
   
   
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * Str_SYSVMatch --   * Str_SYSVMatch --
Line 420 
Line 410 
     const char *m;      const char *m;
   
     if (*p == '\0') {      if (*p == '\0') {
         /* Null pattern is the whole string */          /* Null pattern is the whole string.  */
         *len = strlen(w);          *len = strlen(w);
         return w;          return w;
     }      }
   
     if ((m = strchr(p, '%')) != NULL) {      if ((m = strchr(p, '%')) != NULL) {
         /* check that the prefix matches */          /* Check that the prefix matches.  */
         for (; p != m && *w && *w == *p; w++, p++)          for (; p != m && *w && *w == *p; w++, p++)
              continue;               continue;
   
         if (p != m)          if (p != m)
             return NULL;        /* No match */              return NULL;        /* No match.  */
   
         if (*++p == '\0') {          if (*++p == '\0') {
             /* No more pattern, return the rest of the string */              /* No more pattern, return the rest of the string.  */
             *len = strlen(w);              *len = strlen(w);
             return w;              return w;
         }          }
Line 442 
Line 432 
   
     m = w;      m = w;
   
     /* Find a matching tail */      /* Find a matching tail.  */
     do      do {
         if (strcmp(p, w) == 0) {          if (strcmp(p, w) == 0) {
             *len = w - m;              *len = w - m;
             return m;              return m;
         }          }
     while (*w++ != '\0');      } while (*w++ != '\0');
   
   
     return NULL;      return NULL;
 }  }
   
Line 475 
Line 466 
     const char *m;      const char *m;
   
     if ((m = strchr(pat, '%')) != NULL) {      if ((m = strchr(pat, '%')) != NULL) {
         /* Copy the prefix */          /* Copy the prefix.  */
         Buf_AddInterval(buf, pat, m);          Buf_AddInterval(buf, pat, m);
         /* skip the % */          /* Skip the %.  */
         pat = m + 1;          pat = m + 1;
     }      }
   
     /* Copy the pattern */      /* Copy the pattern.  */
     Buf_AddChars(buf, len, src);      Buf_AddChars(buf, len, src);
   
     /* append the rest */      /* Append the rest.  */
     Buf_AddString(buf, pat);      Buf_AddString(buf, pat);
 }  }
   
Line 512 
Line 503 
   
     t = s = emalloc(end - begin + 1);      t = s = emalloc(end - begin + 1);
     while (begin != end) {      while (begin != end) {
         if (*begin == '\\') {          if (*begin == '\\') {
             begin++;              begin++;
             if (begin == end) {              if (begin == end) {
                 *t++ = '\\';                  *t++ = '\\';
                 break;                  break;
             }              }
             if (strchr(set, *begin) == NULL)              if (strchr(set, *begin) == NULL)
                 *t++ = '\\';                  *t++ = '\\';
         }          }
         *t++ = *begin++;          *t++ = *begin++;
     }      }
Line 527 
Line 518 
     return s;      return s;
 }  }
   
   char *
   lastchar(s, e, c)
       const char *s;
       const char *e;
       int c;
   {
       if (s != e)
           do {
               if (*--e == c)
                   return (char *)e;
           } while (e != s);
       return NULL;
   }

Legend:
Removed from v.1.16  
changed lines
  Added in v.1.17