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