1/*- 2 * Copyright (c) 1988, 1989, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 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 * @(#)str.c 5.8 (Berkeley) 6/1/90 39 */ 40 41#include <sys/cdefs.h>
| 1/*- 2 * Copyright (c) 1988, 1989, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 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 * @(#)str.c 5.8 (Berkeley) 6/1/90 39 */ 40 41#include <sys/cdefs.h>
|
42__FBSDID("$FreeBSD: head/usr.bin/make/str.c 105826 2002-10-23 23:16:43Z jmallett $");
| 42__FBSDID("$FreeBSD: head/usr.bin/make/str.c 106106 2002-10-28 23:33:57Z jmallett $");
|
43 44#include "make.h" 45 46static char **argv, *buffer; 47static int argmax, curlen; 48 49/* 50 * str_init -- 51 * Initialize the strings package 52 * 53 */ 54void 55str_init(void) 56{ 57 char *p1; 58 argv = (char **)emalloc(((argmax = 50) + 1) * sizeof(char *)); 59 argv[0] = Var_Value(".MAKE", VAR_GLOBAL, &p1); 60} 61 62 63/* 64 * str_end -- 65 * Cleanup the strings package 66 * 67 */ 68void 69str_end(void) 70{ 71 if (argv) { 72 if (argv[0]) 73 free(argv[0]); 74 free(argv); 75 } 76 if (buffer) 77 free(buffer); 78} 79 80/*- 81 * str_concat -- 82 * concatenate the two strings, inserting a space or slash between them, 83 * freeing them if requested. 84 * 85 * returns -- 86 * the resulting string in allocated space. 87 */ 88char * 89str_concat(char *s1, char *s2, int flags) 90{ 91 int len1, len2; 92 char *result; 93 94 /* get the length of both strings */ 95 len1 = strlen(s1); 96 len2 = strlen(s2); 97 98 /* allocate length plus separator plus EOS */ 99 result = emalloc((u_int)(len1 + len2 + 2)); 100 101 /* copy first string into place */ 102 memcpy(result, s1, len1); 103 104 /* add separator character */ 105 if (flags & STR_ADDSPACE) { 106 result[len1] = ' '; 107 ++len1; 108 } else if (flags & STR_ADDSLASH) { 109 result[len1] = '/'; 110 ++len1; 111 } 112 113 /* copy second string plus EOS into place */ 114 memcpy(result + len1, s2, len2 + 1); 115 116 /* free original strings */ 117 if (flags & STR_DOFREE) { 118 (void)free(s1); 119 (void)free(s2); 120 } 121 return(result); 122} 123 124/*- 125 * brk_string -- 126 * Fracture a string into an array of words (as delineated by tabs or 127 * spaces) taking quotation marks into account. Leading tabs/spaces 128 * are ignored. 129 * 130 * returns -- 131 * Pointer to the array of pointers to the words. To make life easier, 132 * the first word is always the value of the .MAKE variable. 133 */ 134char ** 135brk_string(char *str, int *store_argc, Boolean expand) 136{ 137 int argc, ch; 138 char inquote, *p, *start, *t; 139 int len; 140 141 /* skip leading space chars. */ 142 for (; *str == ' ' || *str == '\t'; ++str) 143 continue; 144 145 /* allocate room for a copy of the string */ 146 if ((len = strlen(str) + 1) > curlen) { 147 if (buffer) 148 free(buffer); 149 buffer = emalloc(curlen = len); 150 } 151 152 /* 153 * copy the string; at the same time, parse backslashes, 154 * quotes and build the argument list. 155 */ 156 argc = 1; 157 inquote = '\0'; 158 for (p = str, start = t = buffer;; ++p) { 159 switch(ch = *p) { 160 case '"': 161 case '\'': 162 if (inquote) { 163 if (inquote == ch) 164 inquote = '\0'; 165 else 166 break; 167 } else { 168 inquote = (char) ch; 169 /* Don't miss "" or '' */ 170 if (start == NULL && p[1] == inquote) { 171 start = t + 1; 172 break; 173 } 174 } 175 if (!expand) { 176 if (!start) 177 start = t; 178 *t++ = ch; 179 } 180 continue; 181 case ' ': 182 case '\t': 183 case '\n': 184 if (inquote) 185 break; 186 if (!start) 187 continue; 188 /* FALLTHROUGH */ 189 case '\0': 190 /* 191 * end of a token -- make sure there's enough argv 192 * space and save off a pointer. 193 */ 194 if (!start) 195 goto done; 196 197 *t++ = '\0'; 198 if (argc == argmax) { 199 argmax *= 2; /* ramp up fast */ 200 argv = (char **)erealloc(argv, 201 (argmax + 1) * sizeof(char *)); 202 } 203 argv[argc++] = start; 204 start = (char *)NULL; 205 if (ch == '\n' || ch == '\0') 206 goto done; 207 continue; 208 case '\\': 209 if (!expand) { 210 if (!start) 211 start = t; 212 *t++ = '\\'; 213 ch = *++p; 214 break; 215 } 216 217 switch (ch = *++p) { 218 case '\0': 219 case '\n': 220 /* hmmm; fix it up as best we can */ 221 ch = '\\'; 222 --p; 223 break; 224 case 'b': 225 ch = '\b'; 226 break; 227 case 'f': 228 ch = '\f'; 229 break; 230 case 'n': 231 ch = '\n'; 232 break; 233 case 'r': 234 ch = '\r'; 235 break; 236 case 't': 237 ch = '\t'; 238 break; 239 default: 240 break; 241 } 242 break; 243 default: 244 break; 245 } 246 if (!start) 247 start = t; 248 *t++ = (char) ch; 249 } 250done: argv[argc] = (char *)NULL; 251 *store_argc = argc; 252 return(argv); 253} 254 255/*
| 43 44#include "make.h" 45 46static char **argv, *buffer; 47static int argmax, curlen; 48 49/* 50 * str_init -- 51 * Initialize the strings package 52 * 53 */ 54void 55str_init(void) 56{ 57 char *p1; 58 argv = (char **)emalloc(((argmax = 50) + 1) * sizeof(char *)); 59 argv[0] = Var_Value(".MAKE", VAR_GLOBAL, &p1); 60} 61 62 63/* 64 * str_end -- 65 * Cleanup the strings package 66 * 67 */ 68void 69str_end(void) 70{ 71 if (argv) { 72 if (argv[0]) 73 free(argv[0]); 74 free(argv); 75 } 76 if (buffer) 77 free(buffer); 78} 79 80/*- 81 * str_concat -- 82 * concatenate the two strings, inserting a space or slash between them, 83 * freeing them if requested. 84 * 85 * returns -- 86 * the resulting string in allocated space. 87 */ 88char * 89str_concat(char *s1, char *s2, int flags) 90{ 91 int len1, len2; 92 char *result; 93 94 /* get the length of both strings */ 95 len1 = strlen(s1); 96 len2 = strlen(s2); 97 98 /* allocate length plus separator plus EOS */ 99 result = emalloc((u_int)(len1 + len2 + 2)); 100 101 /* copy first string into place */ 102 memcpy(result, s1, len1); 103 104 /* add separator character */ 105 if (flags & STR_ADDSPACE) { 106 result[len1] = ' '; 107 ++len1; 108 } else if (flags & STR_ADDSLASH) { 109 result[len1] = '/'; 110 ++len1; 111 } 112 113 /* copy second string plus EOS into place */ 114 memcpy(result + len1, s2, len2 + 1); 115 116 /* free original strings */ 117 if (flags & STR_DOFREE) { 118 (void)free(s1); 119 (void)free(s2); 120 } 121 return(result); 122} 123 124/*- 125 * brk_string -- 126 * Fracture a string into an array of words (as delineated by tabs or 127 * spaces) taking quotation marks into account. Leading tabs/spaces 128 * are ignored. 129 * 130 * returns -- 131 * Pointer to the array of pointers to the words. To make life easier, 132 * the first word is always the value of the .MAKE variable. 133 */ 134char ** 135brk_string(char *str, int *store_argc, Boolean expand) 136{ 137 int argc, ch; 138 char inquote, *p, *start, *t; 139 int len; 140 141 /* skip leading space chars. */ 142 for (; *str == ' ' || *str == '\t'; ++str) 143 continue; 144 145 /* allocate room for a copy of the string */ 146 if ((len = strlen(str) + 1) > curlen) { 147 if (buffer) 148 free(buffer); 149 buffer = emalloc(curlen = len); 150 } 151 152 /* 153 * copy the string; at the same time, parse backslashes, 154 * quotes and build the argument list. 155 */ 156 argc = 1; 157 inquote = '\0'; 158 for (p = str, start = t = buffer;; ++p) { 159 switch(ch = *p) { 160 case '"': 161 case '\'': 162 if (inquote) { 163 if (inquote == ch) 164 inquote = '\0'; 165 else 166 break; 167 } else { 168 inquote = (char) ch; 169 /* Don't miss "" or '' */ 170 if (start == NULL && p[1] == inquote) { 171 start = t + 1; 172 break; 173 } 174 } 175 if (!expand) { 176 if (!start) 177 start = t; 178 *t++ = ch; 179 } 180 continue; 181 case ' ': 182 case '\t': 183 case '\n': 184 if (inquote) 185 break; 186 if (!start) 187 continue; 188 /* FALLTHROUGH */ 189 case '\0': 190 /* 191 * end of a token -- make sure there's enough argv 192 * space and save off a pointer. 193 */ 194 if (!start) 195 goto done; 196 197 *t++ = '\0'; 198 if (argc == argmax) { 199 argmax *= 2; /* ramp up fast */ 200 argv = (char **)erealloc(argv, 201 (argmax + 1) * sizeof(char *)); 202 } 203 argv[argc++] = start; 204 start = (char *)NULL; 205 if (ch == '\n' || ch == '\0') 206 goto done; 207 continue; 208 case '\\': 209 if (!expand) { 210 if (!start) 211 start = t; 212 *t++ = '\\'; 213 ch = *++p; 214 break; 215 } 216 217 switch (ch = *++p) { 218 case '\0': 219 case '\n': 220 /* hmmm; fix it up as best we can */ 221 ch = '\\'; 222 --p; 223 break; 224 case 'b': 225 ch = '\b'; 226 break; 227 case 'f': 228 ch = '\f'; 229 break; 230 case 'n': 231 ch = '\n'; 232 break; 233 case 'r': 234 ch = '\r'; 235 break; 236 case 't': 237 ch = '\t'; 238 break; 239 default: 240 break; 241 } 242 break; 243 default: 244 break; 245 } 246 if (!start) 247 start = t; 248 *t++ = (char) ch; 249 } 250done: argv[argc] = (char *)NULL; 251 *store_argc = argc; 252 return(argv); 253} 254 255/*
|
256 * Str_FindSubstring -- See if a string contains a particular substring. 257 * 258 * Results: If string contains substring, the return value is the location of 259 * the first matching instance of substring in string. If string doesn't 260 * contain substring, the return value is NULL. Matching is done on an exact 261 * character-for-character basis with no wildcards or special characters. 262 * 263 * Side effects: None. 264 * 265 * XXX should be strstr(3). 266 */ 267char * 268Str_FindSubstring(char *string, char *substring) 269{ 270 char *a, *b; 271 272 /* 273 * First scan quickly through the two strings looking for a single- 274 * character match. When it's found, then compare the rest of the 275 * substring. 276 */ 277 278 for (b = substring; *string != 0; string += 1) { 279 if (*string != *b) 280 continue; 281 a = string; 282 for (;;) { 283 if (*b == 0) 284 return(string); 285 if (*a++ != *b++) 286 break; 287 } 288 b = substring; 289 } 290 return((char *) NULL); 291} 292 293/*
| |
294 * Str_Match -- 295 * 296 * See if a particular string matches a particular pattern. 297 * 298 * Results: Non-zero is returned if string matches pattern, 0 otherwise. The 299 * matching operation permits the following special characters in the 300 * pattern: *?\[] (see the man page for details on what these mean). 301 * 302 * Side effects: None. 303 */ 304int
| 256 * Str_Match -- 257 * 258 * See if a particular string matches a particular pattern. 259 * 260 * Results: Non-zero is returned if string matches pattern, 0 otherwise. The 261 * matching operation permits the following special characters in the 262 * pattern: *?\[] (see the man page for details on what these mean). 263 * 264 * Side effects: None. 265 */ 266int
|
305Str_Match(char *string, char *pattern)
| 267Str_Match(const char *string, const char *pattern)
|
306{ 307 char c2; 308 309 for (;;) { 310 /* 311 * See if we're at the end of both the pattern and the 312 * string. If, we succeeded. If we're at the end of the 313 * pattern but not at the end of the string, we failed. 314 */ 315 if (*pattern == 0) 316 return(!*string); 317 if (*string == 0 && *pattern != '*') 318 return(0); 319 /* 320 * Check for a "*" as the next pattern character. It matches 321 * any substring. We handle this by calling ourselves 322 * recursively for each postfix of string, until either we 323 * match or we reach the end of the string. 324 */ 325 if (*pattern == '*') { 326 pattern += 1; 327 if (*pattern == 0) 328 return(1); 329 while (*string != 0) { 330 if (Str_Match(string, pattern)) 331 return(1); 332 ++string; 333 } 334 return(0); 335 } 336 /* 337 * Check for a "?" as the next pattern character. It matches 338 * any single character. 339 */ 340 if (*pattern == '?') 341 goto thisCharOK; 342 /* 343 * Check for a "[" as the next pattern character. It is 344 * followed by a list of characters that are acceptable, or 345 * by a range (two characters separated by "-"). 346 */ 347 if (*pattern == '[') { 348 ++pattern; 349 for (;;) { 350 if ((*pattern == ']') || (*pattern == 0)) 351 return(0); 352 if (*pattern == *string) 353 break; 354 if (pattern[1] == '-') { 355 c2 = pattern[2]; 356 if (c2 == 0) 357 return(0); 358 if ((*pattern <= *string) && 359 (c2 >= *string)) 360 break; 361 if ((*pattern >= *string) && 362 (c2 <= *string)) 363 break; 364 pattern += 2; 365 } 366 ++pattern; 367 } 368 while ((*pattern != ']') && (*pattern != 0)) 369 ++pattern; 370 goto thisCharOK; 371 } 372 /* 373 * If the next pattern character is '/', just strip off the 374 * '/' so we do exact matching on the character that follows. 375 */ 376 if (*pattern == '\\') { 377 ++pattern; 378 if (*pattern == 0) 379 return(0); 380 } 381 /* 382 * There's no special character. Just make sure that the 383 * next characters of each string match. 384 */ 385 if (*pattern != *string) 386 return(0); 387thisCharOK: ++pattern; 388 ++string; 389 } 390} 391 392 393/*- 394 *----------------------------------------------------------------------- 395 * Str_SYSVMatch -- 396 * Check word against pattern for a match (% is wild), 397 * 398 * Results: 399 * Returns the beginning position of a match or null. The number 400 * of characters matched is returned in len. 401 * 402 * Side Effects: 403 * None 404 * 405 *----------------------------------------------------------------------- 406 */
| 268{ 269 char c2; 270 271 for (;;) { 272 /* 273 * See if we're at the end of both the pattern and the 274 * string. If, we succeeded. If we're at the end of the 275 * pattern but not at the end of the string, we failed. 276 */ 277 if (*pattern == 0) 278 return(!*string); 279 if (*string == 0 && *pattern != '*') 280 return(0); 281 /* 282 * Check for a "*" as the next pattern character. It matches 283 * any substring. We handle this by calling ourselves 284 * recursively for each postfix of string, until either we 285 * match or we reach the end of the string. 286 */ 287 if (*pattern == '*') { 288 pattern += 1; 289 if (*pattern == 0) 290 return(1); 291 while (*string != 0) { 292 if (Str_Match(string, pattern)) 293 return(1); 294 ++string; 295 } 296 return(0); 297 } 298 /* 299 * Check for a "?" as the next pattern character. It matches 300 * any single character. 301 */ 302 if (*pattern == '?') 303 goto thisCharOK; 304 /* 305 * Check for a "[" as the next pattern character. It is 306 * followed by a list of characters that are acceptable, or 307 * by a range (two characters separated by "-"). 308 */ 309 if (*pattern == '[') { 310 ++pattern; 311 for (;;) { 312 if ((*pattern == ']') || (*pattern == 0)) 313 return(0); 314 if (*pattern == *string) 315 break; 316 if (pattern[1] == '-') { 317 c2 = pattern[2]; 318 if (c2 == 0) 319 return(0); 320 if ((*pattern <= *string) && 321 (c2 >= *string)) 322 break; 323 if ((*pattern >= *string) && 324 (c2 <= *string)) 325 break; 326 pattern += 2; 327 } 328 ++pattern; 329 } 330 while ((*pattern != ']') && (*pattern != 0)) 331 ++pattern; 332 goto thisCharOK; 333 } 334 /* 335 * If the next pattern character is '/', just strip off the 336 * '/' so we do exact matching on the character that follows. 337 */ 338 if (*pattern == '\\') { 339 ++pattern; 340 if (*pattern == 0) 341 return(0); 342 } 343 /* 344 * There's no special character. Just make sure that the 345 * next characters of each string match. 346 */ 347 if (*pattern != *string) 348 return(0); 349thisCharOK: ++pattern; 350 ++string; 351 } 352} 353 354 355/*- 356 *----------------------------------------------------------------------- 357 * Str_SYSVMatch -- 358 * Check word against pattern for a match (% is wild), 359 * 360 * Results: 361 * Returns the beginning position of a match or null. The number 362 * of characters matched is returned in len. 363 * 364 * Side Effects: 365 * None 366 * 367 *----------------------------------------------------------------------- 368 */
|
407char * 408Str_SYSVMatch(char *word, char *pattern, int *len)
| 369const char * 370Str_SYSVMatch(const char *word, const char *pattern, int *len)
|
409{
| 371{
|
410 char *p = pattern; 411 char *w = word; 412 char *m;
| 372 const char *m, *p, *w;
|
413
| 373
|
| 374 p = pattern; 375 w = word; 376
|
414 if (*w == '\0') { 415 /* Zero-length word cannot be matched against */ 416 *len = 0; 417 return NULL; 418 } 419 420 if (*p == '\0') { 421 /* Null pattern is the whole string */ 422 *len = strlen(w); 423 return w; 424 } 425 426 if ((m = strchr(p, '%')) != NULL) { 427 /* check that the prefix matches */ 428 for (; p != m && *w && *w == *p; w++, p++) 429 continue; 430 431 if (p != m) 432 return NULL; /* No match */ 433 434 if (*++p == '\0') { 435 /* No more pattern, return the rest of the string */ 436 *len = strlen(w); 437 return w; 438 } 439 } 440 441 m = w; 442 443 /* Find a matching tail */ 444 do 445 if (strcmp(p, w) == 0) { 446 *len = w - m; 447 return m; 448 } 449 while (*w++ != '\0'); 450 451 return NULL; 452} 453 454 455/*- 456 *----------------------------------------------------------------------- 457 * Str_SYSVSubst -- 458 * Substitute '%' on the pattern with len characters from src. 459 * If the pattern does not contain a '%' prepend len characters 460 * from src. 461 * 462 * Results: 463 * None 464 * 465 * Side Effects: 466 * Places result on buf 467 * 468 *----------------------------------------------------------------------- 469 */ 470void
| 377 if (*w == '\0') { 378 /* Zero-length word cannot be matched against */ 379 *len = 0; 380 return NULL; 381 } 382 383 if (*p == '\0') { 384 /* Null pattern is the whole string */ 385 *len = strlen(w); 386 return w; 387 } 388 389 if ((m = strchr(p, '%')) != NULL) { 390 /* check that the prefix matches */ 391 for (; p != m && *w && *w == *p; w++, p++) 392 continue; 393 394 if (p != m) 395 return NULL; /* No match */ 396 397 if (*++p == '\0') { 398 /* No more pattern, return the rest of the string */ 399 *len = strlen(w); 400 return w; 401 } 402 } 403 404 m = w; 405 406 /* Find a matching tail */ 407 do 408 if (strcmp(p, w) == 0) { 409 *len = w - m; 410 return m; 411 } 412 while (*w++ != '\0'); 413 414 return NULL; 415} 416 417 418/*- 419 *----------------------------------------------------------------------- 420 * Str_SYSVSubst -- 421 * Substitute '%' on the pattern with len characters from src. 422 * If the pattern does not contain a '%' prepend len characters 423 * from src. 424 * 425 * Results: 426 * None 427 * 428 * Side Effects: 429 * Places result on buf 430 * 431 *----------------------------------------------------------------------- 432 */ 433void
|
471Str_SYSVSubst(Buffer buf, char *pat, char *src, int len)
| 434Str_SYSVSubst(Buffer buf, const char *pat, const char *src, int len)
|
472{
| 435{
|
473 char *m;
| 436 const char *m;
|
474 475 if ((m = strchr(pat, '%')) != NULL) { 476 /* Copy the prefix */ 477 Buf_AddBytes(buf, m - pat, (Byte *) pat); 478 /* skip the % */ 479 pat = m + 1; 480 } 481 482 /* Copy the pattern */ 483 Buf_AddBytes(buf, len, (Byte *) src); 484 485 /* append the rest */ 486 Buf_AddBytes(buf, strlen(pat), (Byte *) pat); 487}
| 437 438 if ((m = strchr(pat, '%')) != NULL) { 439 /* Copy the prefix */ 440 Buf_AddBytes(buf, m - pat, (Byte *) pat); 441 /* skip the % */ 442 pat = m + 1; 443 } 444 445 /* Copy the pattern */ 446 Buf_AddBytes(buf, len, (Byte *) src); 447 448 /* append the rest */ 449 Buf_AddBytes(buf, strlen(pat), (Byte *) pat); 450}
|