1 /* $NetBSD: str.c,v 1.12 1996/03/29 02:17:34 jtc Exp $ */ 2 3 /*- 4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 5 * Copyright (c) 1988, 1989 by Adam de Boor 6 * Copyright (c) 1989 by Berkeley Softworks 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * Adam de Boor. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 */ 40 41 #ifndef lint 42 #if 0 43 static char sccsid[] = "@(#)str.c 5.8 (Berkeley) 6/1/90"; 44 #else 45 static char rcsid[] = "$NetBSD: str.c,v 1.12 1996/03/29 02:17:34 jtc Exp $"; 46 #endif 47 #endif /* not lint */ 48 49 #include "make.h" 50 51 static char **argv, *buffer; 52 static int argmax, curlen; 53 54 /* 55 * str_init -- 56 * Initialize the strings package 57 * 58 */ 59 void 60 str_init() 61 { 62 char *p1; 63 argv = (char **)emalloc(((argmax = 50) + 1) * sizeof(char *)); 64 argv[0] = Var_Value(".MAKE", VAR_GLOBAL, &p1); 65 } 66 67 68 /* 69 * str_end -- 70 * Cleanup the strings package 71 * 72 */ 73 void 74 str_end() 75 { 76 if (argv[0]) { 77 free(argv[0]); 78 free((Address) argv); 79 } 80 if (buffer) 81 free(buffer); 82 } 83 84 /*- 85 * str_concat -- 86 * concatenate the two strings, inserting a space or slash between them, 87 * freeing them if requested. 88 * 89 * returns -- 90 * the resulting string in allocated space. 91 */ 92 char * 93 str_concat(s1, s2, flags) 94 char *s1, *s2; 95 int flags; 96 { 97 register int len1, len2; 98 register char *result; 99 100 /* get the length of both strings */ 101 len1 = strlen(s1); 102 len2 = strlen(s2); 103 104 /* allocate length plus separator plus EOS */ 105 result = emalloc((u_int)(len1 + len2 + 2)); 106 107 /* copy first string into place */ 108 memcpy(result, s1, len1); 109 110 /* add separator character */ 111 if (flags & STR_ADDSPACE) { 112 result[len1] = ' '; 113 ++len1; 114 } else if (flags & STR_ADDSLASH) { 115 result[len1] = '/'; 116 ++len1; 117 } 118 119 /* copy second string plus EOS into place */ 120 memcpy(result + len1, s2, len2 + 1); 121 122 /* free original strings */ 123 if (flags & STR_DOFREE) { 124 (void)free(s1); 125 (void)free(s2); 126 } 127 return(result); 128 } 129 130 /*- 131 * brk_string -- 132 * Fracture a string into an array of words (as delineated by tabs or 133 * spaces) taking quotation marks into account. Leading tabs/spaces 134 * are ignored. 135 * 136 * returns -- 137 * Pointer to the array of pointers to the words. To make life easier, 138 * the first word is always the value of the .MAKE variable. 139 */ 140 char ** 141 brk_string(str, store_argc, expand) 142 register char *str; 143 int *store_argc; 144 Boolean expand; 145 { 146 register int argc, ch; 147 register char inquote, *p, *start, *t; 148 int len; 149 150 /* skip leading space chars. */ 151 for (; *str == ' ' || *str == '\t'; ++str) 152 continue; 153 154 /* allocate room for a copy of the string */ 155 if ((len = strlen(str) + 1) > curlen) { 156 if (buffer) 157 free(buffer); 158 buffer = emalloc(curlen = len); 159 } 160 161 /* 162 * copy the string; at the same time, parse backslashes, 163 * quotes and build the argument list. 164 */ 165 argc = 1; 166 inquote = '\0'; 167 for (p = str, start = t = buffer;; ++p) { 168 switch(ch = *p) { 169 case '"': 170 case '\'': 171 if (inquote) 172 if (inquote == ch) 173 inquote = '\0'; 174 else 175 break; 176 else { 177 inquote = (char) ch; 178 /* Don't miss "" or '' */ 179 if (start == NULL && p[1] == inquote) { 180 start = t + 1; 181 break; 182 } 183 } 184 if (!expand) { 185 if (!start) 186 start = t; 187 *t++ = ch; 188 } 189 continue; 190 case ' ': 191 case '\t': 192 case '\n': 193 if (inquote) 194 break; 195 if (!start) 196 continue; 197 /* FALLTHROUGH */ 198 case '\0': 199 /* 200 * end of a token -- make sure there's enough argv 201 * space and save off a pointer. 202 */ 203 if (!start) 204 goto done; 205 206 *t++ = '\0'; 207 if (argc == argmax) { 208 argmax *= 2; /* ramp up fast */ 209 argv = (char **)erealloc(argv, 210 (argmax + 1) * sizeof(char *)); 211 } 212 argv[argc++] = start; 213 start = (char *)NULL; 214 if (ch == '\n' || ch == '\0') 215 goto done; 216 continue; 217 case '\\': 218 if (!expand) { 219 if (!start) 220 start = t; 221 *t++ = '\\'; 222 ch = *++p; 223 break; 224 } 225 226 switch (ch = *++p) { 227 case '\0': 228 case '\n': 229 /* hmmm; fix it up as best we can */ 230 ch = '\\'; 231 --p; 232 break; 233 case 'b': 234 ch = '\b'; 235 break; 236 case 'f': 237 ch = '\f'; 238 break; 239 case 'n': 240 ch = '\n'; 241 break; 242 case 'r': 243 ch = '\r'; 244 break; 245 case 't': 246 ch = '\t'; 247 break; 248 } 249 break; 250 } 251 if (!start) 252 start = t; 253 *t++ = (char) ch; 254 } 255 done: argv[argc] = (char *)NULL; 256 *store_argc = argc; 257 return(argv); 258 } 259 260 /* 261 * Str_FindSubstring -- See if a string contains a particular substring. 262 * 263 * Results: If string contains substring, the return value is the location of 264 * the first matching instance of substring in string. If string doesn't 265 * contain substring, the return value is NULL. Matching is done on an exact 266 * character-for-character basis with no wildcards or special characters. 267 * 268 * Side effects: None. 269 */ 270 char * 271 Str_FindSubstring(string, substring) 272 register char *string; /* String to search. */ 273 char *substring; /* Substring to find in string */ 274 { 275 register char *a, *b; 276 277 /* 278 * First scan quickly through the two strings looking for a single- 279 * character match. When it's found, then compare the rest of the 280 * substring. 281 */ 282 283 for (b = substring; *string != 0; string += 1) { 284 if (*string != *b) 285 continue; 286 a = string; 287 for (;;) { 288 if (*b == 0) 289 return(string); 290 if (*a++ != *b++) 291 break; 292 } 293 b = substring; 294 } 295 return((char *) NULL); 296 } 297 298 /* 299 * Str_Match -- 300 * 301 * See if a particular string matches a particular pattern. 302 * 303 * Results: Non-zero is returned if string matches pattern, 0 otherwise. The 304 * matching operation permits the following special characters in the 305 * pattern: *?\[] (see the man page for details on what these mean). 306 * 307 * Side effects: None. 308 */ 309 int 310 Str_Match(string, pattern) 311 register char *string; /* String */ 312 register char *pattern; /* Pattern */ 313 { 314 char c2; 315 316 for (;;) { 317 /* 318 * See if we're at the end of both the pattern and the 319 * string. If, we succeeded. If we're at the end of the 320 * pattern but not at the end of the string, we failed. 321 */ 322 if (*pattern == 0) 323 return(!*string); 324 if (*string == 0 && *pattern != '*') 325 return(0); 326 /* 327 * Check for a "*" as the next pattern character. It matches 328 * any substring. We handle this by calling ourselves 329 * recursively for each postfix of string, until either we 330 * match or we reach the end of the string. 331 */ 332 if (*pattern == '*') { 333 pattern += 1; 334 if (*pattern == 0) 335 return(1); 336 while (*string != 0) { 337 if (Str_Match(string, pattern)) 338 return(1); 339 ++string; 340 } 341 return(0); 342 } 343 /* 344 * Check for a "?" as the next pattern character. It matches 345 * any single character. 346 */ 347 if (*pattern == '?') 348 goto thisCharOK; 349 /* 350 * Check for a "[" as the next pattern character. It is 351 * followed by a list of characters that are acceptable, or 352 * by a range (two characters separated by "-"). 353 */ 354 if (*pattern == '[') { 355 ++pattern; 356 for (;;) { 357 if ((*pattern == ']') || (*pattern == 0)) 358 return(0); 359 if (*pattern == *string) 360 break; 361 if (pattern[1] == '-') { 362 c2 = pattern[2]; 363 if (c2 == 0) 364 return(0); 365 if ((*pattern <= *string) && 366 (c2 >= *string)) 367 break; 368 if ((*pattern >= *string) && 369 (c2 <= *string)) 370 break; 371 pattern += 2; 372 } 373 ++pattern; 374 } 375 while ((*pattern != ']') && (*pattern != 0)) 376 ++pattern; 377 goto thisCharOK; 378 } 379 /* 380 * If the next pattern character is '/', just strip off the 381 * '/' so we do exact matching on the character that follows. 382 */ 383 if (*pattern == '\\') { 384 ++pattern; 385 if (*pattern == 0) 386 return(0); 387 } 388 /* 389 * There's no special character. Just make sure that the 390 * next characters of each string match. 391 */ 392 if (*pattern != *string) 393 return(0); 394 thisCharOK: ++pattern; 395 ++string; 396 } 397 } 398 399 400 /*- 401 *----------------------------------------------------------------------- 402 * Str_SYSVMatch -- 403 * Check word against pattern for a match (% is wild), 404 * 405 * Results: 406 * Returns the beginning position of a match or null. The number 407 * of characters matched is returned in len. 408 * 409 * Side Effects: 410 * None 411 * 412 *----------------------------------------------------------------------- 413 */ 414 char * 415 Str_SYSVMatch(word, pattern, len) 416 char *word; /* Word to examine */ 417 char *pattern; /* Pattern to examine against */ 418 int *len; /* Number of characters to substitute */ 419 { 420 char *p = pattern; 421 char *w = word; 422 char *m; 423 424 if (*p == '\0') { 425 /* Null pattern is the whole string */ 426 *len = strlen(w); 427 return w; 428 } 429 430 if ((m = strchr(p, '%')) != NULL) { 431 /* check that the prefix matches */ 432 for (; p != m && *w && *w == *p; w++, p++) 433 continue; 434 435 if (p != m) 436 return NULL; /* No match */ 437 438 if (*++p == '\0') { 439 /* No more pattern, return the rest of the string */ 440 *len = strlen(w); 441 return w; 442 } 443 } 444 445 m = w; 446 447 /* Find a matching tail */ 448 do 449 if (strcmp(p, w) == 0) { 450 *len = w - m; 451 return m; 452 } 453 while (*w++ != '\0'); 454 455 return NULL; 456 } 457 458 459 /*- 460 *----------------------------------------------------------------------- 461 * Str_SYSVSubst -- 462 * Substitute '%' on the pattern with len characters from src. 463 * If the pattern does not contain a '%' prepend len characters 464 * from src. 465 * 466 * Results: 467 * None 468 * 469 * Side Effects: 470 * Places result on buf 471 * 472 *----------------------------------------------------------------------- 473 */ 474 void 475 Str_SYSVSubst(buf, pat, src, len) 476 Buffer buf; 477 char *pat; 478 char *src; 479 int len; 480 { 481 char *m; 482 483 if ((m = strchr(pat, '%')) != NULL) { 484 /* Copy the prefix */ 485 Buf_AddBytes(buf, m - pat, (Byte *) pat); 486 /* skip the % */ 487 pat = m + 1; 488 } 489 490 /* Copy the pattern */ 491 Buf_AddBytes(buf, len, (Byte *) src); 492 493 /* append the rest */ 494 Buf_AddBytes(buf, strlen(pat), (Byte *) pat); 495 } 496