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