VirtualBox

source: kBuild/trunk/src/kmk/str.c@ 30

Last change on this file since 30 was 25, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r24,
which included commits to RCS files with non-trunk default branches.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.3 KB
Line 
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
39#ifndef lint
40#if 0
41static char sccsid[] = "@(#)str.c 5.8 (Berkeley) 6/1/90";
42#else
43static const char rcsid[] =
44 "$FreeBSD: src/usr.bin/make/str.c,v 1.12.2.1 2002/06/17 04:30:48 jmallett Exp $";
45#endif
46#endif /* not lint */
47
48#include "make.h"
49
50static char **argv, *buffer;
51static int argmax, curlen;
52
53/*
54 * str_init --
55 * Initialize the strings package
56 *
57 */
58void
59str_init()
60{
61 char *p1;
62 argv = (char **)emalloc(((argmax = 50) + 1) * sizeof(char *));
63 argv[0] = Var_Value(".MAKE", VAR_GLOBAL, &p1);
64}
65
66
67/*
68 * str_end --
69 * Cleanup the strings package
70 *
71 */
72void
73str_end()
74{
75 if (argv) {
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 */
92char *
93str_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 */
140char **
141brk_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 }
255done: 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 */
270char *
271Str_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 */
309int
310Str_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);
394thisCharOK: ++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 */
414char *
415Str_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 (*w == '\0') {
425 /* Zero-length word cannot be matched against */
426 *len = 0;
427 return NULL;
428 }
429
430 if (*p == '\0') {
431 /* Null pattern is the whole string */
432 *len = strlen(w);
433 return w;
434 }
435
436 if ((m = strchr(p, '%')) != NULL) {
437 /* check that the prefix matches */
438 for (; p != m && *w && *w == *p; w++, p++)
439 continue;
440
441 if (p != m)
442 return NULL; /* No match */
443
444 if (*++p == '\0') {
445 /* No more pattern, return the rest of the string */
446 *len = strlen(w);
447 return w;
448 }
449 }
450
451 m = w;
452
453 /* Find a matching tail */
454 do
455 if (strcmp(p, w) == 0) {
456 *len = w - m;
457 return m;
458 }
459 while (*w++ != '\0');
460
461 return NULL;
462}
463
464
465/*-
466 *-----------------------------------------------------------------------
467 * Str_SYSVSubst --
468 * Substitute '%' on the pattern with len characters from src.
469 * If the pattern does not contain a '%' prepend len characters
470 * from src.
471 *
472 * Results:
473 * None
474 *
475 * Side Effects:
476 * Places result on buf
477 *
478 *-----------------------------------------------------------------------
479 */
480void
481Str_SYSVSubst(buf, pat, src, len)
482 Buffer buf;
483 char *pat;
484 char *src;
485 int len;
486{
487 char *m;
488
489 if ((m = strchr(pat, '%')) != NULL) {
490 /* Copy the prefix */
491 Buf_AddBytes(buf, m - pat, (Byte *) pat);
492 /* skip the % */
493 pat = m + 1;
494 }
495
496 /* Copy the pattern */
497 Buf_AddBytes(buf, len, (Byte *) src);
498
499 /* append the rest */
500 Buf_AddBytes(buf, strlen(pat), (Byte *) pat);
501}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette