[53] | 1 | /* Builtin function expansion for GNU Make.
|
---|
[3138] | 2 | Copyright (C) 1988-2016 Free Software Foundation, Inc.
|
---|
[53] | 3 | This file is part of GNU Make.
|
---|
| 4 |
|
---|
[501] | 5 | GNU Make is free software; you can redistribute it and/or modify it under the
|
---|
| 6 | terms of the GNU General Public License as published by the Free Software
|
---|
[1989] | 7 | Foundation; either version 3 of the License, or (at your option) any later
|
---|
| 8 | version.
|
---|
[53] | 9 |
|
---|
[501] | 10 | GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
|
---|
| 11 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
---|
| 12 | A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
---|
[53] | 13 |
|
---|
[501] | 14 | You should have received a copy of the GNU General Public License along with
|
---|
[1989] | 15 | this program. If not, see <http://www.gnu.org/licenses/>. */
|
---|
[53] | 16 |
|
---|
[3138] | 17 | #include "makeint.h"
|
---|
[53] | 18 | #include "filedef.h"
|
---|
| 19 | #include "variable.h"
|
---|
| 20 | #include "dep.h"
|
---|
| 21 | #include "job.h"
|
---|
| 22 | #include "commands.h"
|
---|
| 23 | #include "debug.h"
|
---|
| 24 |
|
---|
| 25 | #ifdef _AMIGA
|
---|
| 26 | #include "amiga.h"
|
---|
| 27 | #endif
|
---|
| 28 |
|
---|
| 29 |
|
---|
| 30 | struct function_table_entry
|
---|
| 31 | {
|
---|
[3138] | 32 | union {
|
---|
| 33 | char *(*func_ptr) (char *output, char **argv, const char *fname);
|
---|
| 34 | gmk_func_ptr alloc_func_ptr;
|
---|
| 35 | } fptr;
|
---|
[53] | 36 | const char *name;
|
---|
| 37 | unsigned char len;
|
---|
| 38 | unsigned char minimum_args;
|
---|
| 39 | unsigned char maximum_args;
|
---|
[3138] | 40 | unsigned char expand_args:1;
|
---|
| 41 | unsigned char alloc_fn:1;
|
---|
[53] | 42 | };
|
---|
| 43 |
|
---|
| 44 | static unsigned long
|
---|
| 45 | function_table_entry_hash_1 (const void *keyv)
|
---|
| 46 | {
|
---|
[900] | 47 | const struct function_table_entry *key = keyv;
|
---|
[53] | 48 | return_STRING_N_HASH_1 (key->name, key->len);
|
---|
| 49 | }
|
---|
| 50 |
|
---|
| 51 | static unsigned long
|
---|
| 52 | function_table_entry_hash_2 (const void *keyv)
|
---|
| 53 | {
|
---|
[900] | 54 | const struct function_table_entry *key = keyv;
|
---|
[53] | 55 | return_STRING_N_HASH_2 (key->name, key->len);
|
---|
| 56 | }
|
---|
| 57 |
|
---|
| 58 | static int
|
---|
| 59 | function_table_entry_hash_cmp (const void *xv, const void *yv)
|
---|
| 60 | {
|
---|
[900] | 61 | const struct function_table_entry *x = xv;
|
---|
| 62 | const struct function_table_entry *y = yv;
|
---|
[53] | 63 | int result = x->len - y->len;
|
---|
| 64 | if (result)
|
---|
| 65 | return result;
|
---|
| 66 | return_STRING_N_COMPARE (x->name, y->name, x->len);
|
---|
| 67 | }
|
---|
| 68 |
|
---|
| 69 | static struct hash_table function_table;
|
---|
| 70 | |
---|
| 71 |
|
---|
| 72 |
|
---|
| 73 | /* Store into VARIABLE_BUFFER at O the result of scanning TEXT and replacing
|
---|
| 74 | each occurrence of SUBST with REPLACE. TEXT is null-terminated. SLEN is
|
---|
| 75 | the length of SUBST and RLEN is the length of REPLACE. If BY_WORD is
|
---|
[280] | 76 | nonzero, substitutions are done only on matches which are complete
|
---|
[53] | 77 | whitespace-delimited words. */
|
---|
| 78 |
|
---|
[900] | 79 | char *
|
---|
[280] | 80 | subst_expand (char *o, const char *text, const char *subst, const char *replace,
|
---|
[53] | 81 | unsigned int slen, unsigned int rlen, int by_word)
|
---|
[900] | 82 | {
|
---|
| 83 | const char *t = text;
|
---|
[53] | 84 | const char *p;
|
---|
[280] | 85 |
|
---|
[53] | 86 | if (slen == 0 && !by_word)
|
---|
| 87 | {
|
---|
[280] | 88 | /* The first occurrence of "" in any string is its end. */
|
---|
[53] | 89 | o = variable_buffer_output (o, t, strlen (t));
|
---|
[3138] | 90 | if (rlen > 0)
|
---|
[53] | 91 | o = variable_buffer_output (o, replace, rlen);
|
---|
| 92 | return o;
|
---|
| 93 | }
|
---|
| 94 |
|
---|
| 95 | do
|
---|
[280] | 96 | {
|
---|
[3138] | 97 | if (by_word && slen == 0)
|
---|
| 98 | /* When matching by words, the empty string should match
|
---|
| 99 | the end of each word, rather than the end of the whole text. */
|
---|
[53] | 100 | p = end_of_token (next_token (t));
|
---|
[3138] | 101 | else
|
---|
| 102 | {
|
---|
| 103 | p = strstr (t, subst);
|
---|
| 104 | if (p == 0)
|
---|
| 105 | {
|
---|
| 106 | /* No more matches. Output everything left on the end. */
|
---|
| 107 | o = variable_buffer_output (o, t, strlen (t));
|
---|
| 108 | return o;
|
---|
| 109 | }
|
---|
[53] | 110 | }
|
---|
| 111 |
|
---|
| 112 | /* Output everything before this occurrence of the string to replace. */
|
---|
[3138] | 113 | if (p > t)
|
---|
[53] | 114 | o = variable_buffer_output (o, t, p - t);
|
---|
| 115 |
|
---|
[3138] | 116 | /* If we're substituting only by fully matched words,
|
---|
[280] | 117 | or only at the ends of words, check that this case qualifies. */
|
---|
[3138] | 118 | if (by_word
|
---|
| 119 | && ((p > text && !ISSPACE (p[-1]))
|
---|
| 120 | || ! STOP_SET (p[slen], MAP_SPACE|MAP_NUL)))
|
---|
| 121 | /* Struck out. Output the rest of the string that is
|
---|
| 122 | no longer to be replaced. */
|
---|
[53] | 123 | o = variable_buffer_output (o, subst, slen);
|
---|
[3138] | 124 | else if (rlen > 0)
|
---|
| 125 | /* Output the replacement string. */
|
---|
[53] | 126 | o = variable_buffer_output (o, replace, rlen);
|
---|
[280] | 127 |
|
---|
[900] | 128 | /* Advance T past the string to be replaced. */
|
---|
[53] | 129 | t = p + slen;
|
---|
| 130 | } while (*t != '\0');
|
---|
| 131 |
|
---|
| 132 | return o;
|
---|
[280] | 133 | }
|
---|
[53] | 134 | |
---|
| 135 |
|
---|
| 136 |
|
---|
| 137 | /* Store into VARIABLE_BUFFER at O the result of scanning TEXT
|
---|
| 138 | and replacing strings matching PATTERN with REPLACE.
|
---|
| 139 | If PATTERN_PERCENT is not nil, PATTERN has already been
|
---|
[280] | 140 | run through find_percent, and PATTERN_PERCENT is the result.
|
---|
| 141 | If REPLACE_PERCENT is not nil, REPLACE has already been
|
---|
| 142 | run through find_percent, and REPLACE_PERCENT is the result.
|
---|
| 143 | Note that we expect PATTERN_PERCENT and REPLACE_PERCENT to point to the
|
---|
[53] | 144 | character _AFTER_ the %, not to the % itself.
|
---|
| 145 | */
|
---|
[900] | 146 |
|
---|
| 147 | char *
|
---|
| 148 | patsubst_expand_pat (char *o, const char *text,
|
---|
[53] | 149 | const char *pattern, const char *replace,
|
---|
| 150 | const char *pattern_percent, const char *replace_percent)
|
---|
[280] | 151 | {
|
---|
[900] | 152 | unsigned int pattern_prepercent_len, pattern_postpercent_len;
|
---|
[53] | 153 | unsigned int replace_prepercent_len, replace_postpercent_len;
|
---|
| 154 | const char *t;
|
---|
| 155 | unsigned int len;
|
---|
[280] | 156 | int doneany = 0;
|
---|
| 157 |
|
---|
| 158 | /* Record the length of REPLACE before and after the % so we don't have to
|
---|
| 159 | compute these lengths more than once. */
|
---|
| 160 | if (replace_percent)
|
---|
| 161 | {
|
---|
| 162 | replace_prepercent_len = replace_percent - replace - 1;
|
---|
[53] | 163 | replace_postpercent_len = strlen (replace_percent);
|
---|
[280] | 164 | }
|
---|
| 165 | else
|
---|
| 166 | {
|
---|
| 167 | replace_prepercent_len = strlen (replace);
|
---|
[53] | 168 | replace_postpercent_len = 0;
|
---|
[280] | 169 | }
|
---|
[53] | 170 |
|
---|
| 171 | if (!pattern_percent)
|
---|
[3138] | 172 | /* With no % in the pattern, this is just a simple substitution. */
|
---|
[53] | 173 | return subst_expand (o, text, pattern, replace,
|
---|
| 174 | strlen (pattern), strlen (replace), 1);
|
---|
| 175 |
|
---|
[280] | 176 | /* Record the length of PATTERN before and after the %
|
---|
| 177 | so we don't have to compute it more than once. */
|
---|
[53] | 178 | pattern_prepercent_len = pattern_percent - pattern - 1;
|
---|
| 179 | pattern_postpercent_len = strlen (pattern_percent);
|
---|
| 180 |
|
---|
| 181 | while ((t = find_next_token (&text, &len)) != 0)
|
---|
| 182 | {
|
---|
| 183 | int fail = 0;
|
---|
| 184 |
|
---|
[3138] | 185 | /* Is it big enough to match? */
|
---|
[53] | 186 | if (len < pattern_prepercent_len + pattern_postpercent_len)
|
---|
| 187 | fail = 1;
|
---|
| 188 |
|
---|
[3138] | 189 | /* Does the prefix match? */
|
---|
| 190 | if (!fail && pattern_prepercent_len > 0
|
---|
| 191 | && (*t != *pattern
|
---|
| 192 | || t[pattern_prepercent_len - 1] != pattern_percent[-2]
|
---|
[53] | 193 | || !strneq (t + 1, pattern + 1, pattern_prepercent_len - 1)))
|
---|
| 194 | fail = 1;
|
---|
| 195 |
|
---|
[3138] | 196 | /* Does the suffix match? */
|
---|
| 197 | if (!fail && pattern_postpercent_len > 0
|
---|
| 198 | && (t[len - 1] != pattern_percent[pattern_postpercent_len - 1]
|
---|
| 199 | || t[len - pattern_postpercent_len] != *pattern_percent
|
---|
| 200 | || !strneq (&t[len - pattern_postpercent_len],
|
---|
[53] | 201 | pattern_percent, pattern_postpercent_len - 1)))
|
---|
| 202 | fail = 1;
|
---|
[3138] | 203 |
|
---|
| 204 | if (fail)
|
---|
[53] | 205 | /* It didn't match. Output the string. */
|
---|
[3138] | 206 | o = variable_buffer_output (o, t, len);
|
---|
| 207 | else
|
---|
[53] | 208 | {
|
---|
[3138] | 209 | /* It matched. Output the replacement. */
|
---|
| 210 |
|
---|
[53] | 211 | /* Output the part of the replacement before the %. */
|
---|
[3138] | 212 | o = variable_buffer_output (o, replace, replace_prepercent_len);
|
---|
| 213 |
|
---|
| 214 | if (replace_percent != 0)
|
---|
| 215 | {
|
---|
| 216 | /* Output the part of the matched string that
|
---|
| 217 | matched the % in the pattern. */
|
---|
| 218 | o = variable_buffer_output (o, t + pattern_prepercent_len,
|
---|
| 219 | len - (pattern_prepercent_len
|
---|
| 220 | + pattern_postpercent_len));
|
---|
| 221 | /* Output the part of the replacement after the %. */
|
---|
| 222 | o = variable_buffer_output (o, replace_percent,
|
---|
| 223 | replace_postpercent_len);
|
---|
[53] | 224 | }
|
---|
| 225 | }
|
---|
| 226 |
|
---|
[3138] | 227 | /* Output a space, but not if the replacement is "". */
|
---|
| 228 | if (fail || replace_prepercent_len > 0
|
---|
| 229 | || (replace_percent != 0 && len + replace_postpercent_len > 0))
|
---|
| 230 | {
|
---|
| 231 | o = variable_buffer_output (o, " ", 1);
|
---|
[53] | 232 | doneany = 1;
|
---|
| 233 | }
|
---|
| 234 | }
|
---|
| 235 | if (doneany)
|
---|
| 236 | /* Kill the last space. */
|
---|
| 237 | --o;
|
---|
| 238 |
|
---|
[900] | 239 | return o;
|
---|
| 240 | }
|
---|
| 241 |
|
---|
| 242 | /* Store into VARIABLE_BUFFER at O the result of scanning TEXT
|
---|
| 243 | and replacing strings matching PATTERN with REPLACE.
|
---|
| 244 | If PATTERN_PERCENT is not nil, PATTERN has already been
|
---|
| 245 | run through find_percent, and PATTERN_PERCENT is the result.
|
---|
| 246 | If REPLACE_PERCENT is not nil, REPLACE has already been
|
---|
| 247 | run through find_percent, and REPLACE_PERCENT is the result.
|
---|
| 248 | Note that we expect PATTERN_PERCENT and REPLACE_PERCENT to point to the
|
---|
| 249 | character _AFTER_ the %, not to the % itself.
|
---|
| 250 | */
|
---|
| 251 |
|
---|
| 252 | char *
|
---|
| 253 | patsubst_expand (char *o, const char *text, char *pattern, char *replace)
|
---|
| 254 | {
|
---|
| 255 | const char *pattern_percent = find_percent (pattern);
|
---|
| 256 | const char *replace_percent = find_percent (replace);
|
---|
| 257 |
|
---|
| 258 | /* If there's a percent in the pattern or replacement skip it. */
|
---|
| 259 | if (replace_percent)
|
---|
| 260 | ++replace_percent;
|
---|
| 261 | if (pattern_percent)
|
---|
| 262 | ++pattern_percent;
|
---|
| 263 |
|
---|
| 264 | return patsubst_expand_pat (o, text, pattern, replace,
|
---|
[53] | 265 | pattern_percent, replace_percent);
|
---|
| 266 | }
|
---|
| 267 | |
---|
| 268 |
|
---|
| 269 |
|
---|
| 270 | /* Look up a function by name. */
|
---|
| 271 |
|
---|
[3138] | 272 | static const struct function_table_entry *
|
---|
[53] | 273 | lookup_function (const char *s)
|
---|
| 274 | {
|
---|
[3138] | 275 | struct function_table_entry function_table_entry_key;
|
---|
[53] | 276 | const char *e = s;
|
---|
| 277 |
|
---|
[3138] | 278 | while (STOP_SET (*e, MAP_USERFUNC))
|
---|
| 279 | e++;
|
---|
| 280 |
|
---|
| 281 | if (e == s || !STOP_SET(*e, MAP_NUL|MAP_SPACE))
|
---|
| 282 | return NULL;
|
---|
| 283 |
|
---|
| 284 | function_table_entry_key.name = s;
|
---|
[53] | 285 | function_table_entry_key.len = e - s;
|
---|
| 286 |
|
---|
| 287 | return hash_find_item (&function_table, &function_table_entry_key);
|
---|
| 288 | }
|
---|
| 289 | |
---|
| 290 |
|
---|
[900] | 291 |
|
---|
[53] | 292 | /* Return 1 if PATTERN matches STR, 0 if not. */
|
---|
| 293 |
|
---|
| 294 | int
|
---|
| 295 | pattern_matches (const char *pattern, const char *percent, const char *str)
|
---|
| 296 | {
|
---|
| 297 | unsigned int sfxlen, strlength;
|
---|
[900] | 298 |
|
---|
| 299 | if (percent == 0)
|
---|
| 300 | {
|
---|
| 301 | unsigned int len = strlen (pattern) + 1;
|
---|
[3138] | 302 | char *new_chars = alloca (len);
|
---|
[53] | 303 | memcpy (new_chars, pattern, len);
|
---|
| 304 | percent = find_percent (new_chars);
|
---|
| 305 | if (percent == 0)
|
---|
| 306 | return streq (new_chars, str);
|
---|
| 307 | pattern = new_chars;
|
---|
| 308 | }
|
---|
| 309 |
|
---|
| 310 | sfxlen = strlen (percent + 1);
|
---|
| 311 | strlength = strlen (str);
|
---|
| 312 |
|
---|
| 313 | if (strlength < (percent - pattern) + sfxlen
|
---|
| 314 | || !strneq (pattern, str, percent - pattern))
|
---|
| 315 | return 0;
|
---|
| 316 |
|
---|
| 317 | return !strcmp (percent + 1, str + (strlength - sfxlen));
|
---|
| 318 | }
|
---|
| 319 | |
---|
| 320 |
|
---|
| 321 |
|
---|
| 322 | /* Find the next comma or ENDPAREN (counting nested STARTPAREN and
|
---|
| 323 | ENDPARENtheses), starting at PTR before END. Return a pointer to
|
---|
| 324 | next character.
|
---|
| 325 |
|
---|
| 326 | If no next argument is found, return NULL.
|
---|
| 327 | */
|
---|
| 328 |
|
---|
| 329 | static char *
|
---|
| 330 | find_next_argument (char startparen, char endparen,
|
---|
| 331 | const char *ptr, const char *end)
|
---|
| 332 | {
|
---|
| 333 | int count = 0;
|
---|
| 334 |
|
---|
| 335 | for (; ptr < end; ++ptr)
|
---|
[3138] | 336 | if (*ptr == startparen)
|
---|
| 337 | ++count;
|
---|
| 338 |
|
---|
[53] | 339 | else if (*ptr == endparen)
|
---|
| 340 | {
|
---|
| 341 | --count;
|
---|
| 342 | if (count < 0)
|
---|
| 343 | return NULL;
|
---|
| 344 | }
|
---|
| 345 |
|
---|
| 346 | else if (*ptr == ',' && !count)
|
---|
| 347 | return (char *)ptr;
|
---|
| 348 |
|
---|
| 349 | /* We didn't find anything. */
|
---|
| 350 | return NULL;
|
---|
| 351 | }
|
---|
| 352 | |
---|
| 353 |
|
---|
| 354 |
|
---|
| 355 | /* Glob-expand LINE. The returned pointer is
|
---|
| 356 | only good until the next call to string_glob. */
|
---|
[900] | 357 |
|
---|
| 358 | static char *
|
---|
[53] | 359 | string_glob (char *line)
|
---|
[3138] | 360 | {
|
---|
| 361 | static char *result = 0;
|
---|
[2596] | 362 | static unsigned int length;
|
---|
| 363 | struct nameseq *chain;
|
---|
| 364 | unsigned int idx;
|
---|
[53] | 365 |
|
---|
| 366 | chain = PARSE_FILE_SEQ (&line, struct nameseq, MAP_NUL, NULL,
|
---|
| 367 | /* We do not want parse_file_seq to strip './'s.
|
---|
| 368 | That would break examples like:
|
---|
[900] | 369 | $(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)). */
|
---|
[53] | 370 | PARSEFS_NOSTRIP|PARSEFS_NOCACHE|PARSEFS_EXISTS);
|
---|
| 371 |
|
---|
| 372 | if (result == 0)
|
---|
| 373 | {
|
---|
| 374 | length = 100;
|
---|
[2596] | 375 | result = xmalloc (100);
|
---|
| 376 | }
|
---|
[53] | 377 |
|
---|
[2596] | 378 | idx = 0;
|
---|
| 379 | while (chain != 0)
|
---|
| 380 | {
|
---|
| 381 | struct nameseq *next = chain->next;
|
---|
| 382 | unsigned int len = strlen (chain->name);
|
---|
| 383 |
|
---|
| 384 | if (idx + len + 1 > length)
|
---|
| 385 | {
|
---|
| 386 | length += (len + 1) * 2;
|
---|
| 387 | result = xrealloc (result, length);
|
---|
| 388 | }
|
---|
[900] | 389 | memcpy (&result[idx], chain->name, len);
|
---|
[53] | 390 | idx += len;
|
---|
| 391 | result[idx++] = ' ';
|
---|
| 392 |
|
---|
| 393 | /* Because we used PARSEFS_NOCACHE above, we have to free() NAME. */
|
---|
| 394 | free ((char *)chain->name);
|
---|
| 395 | free (chain);
|
---|
| 396 | chain = next;
|
---|
| 397 | }
|
---|
| 398 |
|
---|
| 399 | /* Kill the last space and terminate the string. */
|
---|
| 400 | if (idx == 0)
|
---|
| 401 | result[0] = '\0';
|
---|
| 402 | else
|
---|
| 403 | result[idx - 1] = '\0';
|
---|
| 404 |
|
---|
| 405 | return result;
|
---|
| 406 | }
|
---|
[153] | 407 | |
---|
[53] | 408 |
|
---|
[900] | 409 | /*
|
---|
[53] | 410 | Builtin functions
|
---|
| 411 | */
|
---|
| 412 |
|
---|
| 413 | static char *
|
---|
| 414 | func_patsubst (char *o, char **argv, const char *funcname UNUSED)
|
---|
[153] | 415 | {
|
---|
[53] | 416 | o = patsubst_expand (o, argv[2], argv[0], argv[1]);
|
---|
| 417 | return o;
|
---|
| 418 | }
|
---|
| 419 |
|
---|
| 420 |
|
---|
| 421 | static char *
|
---|
| 422 | func_join (char *o, char **argv, const char *funcname UNUSED)
|
---|
[900] | 423 | {
|
---|
| 424 | int doneany = 0;
|
---|
| 425 |
|
---|
| 426 | /* Write each word of the first argument directly followed
|
---|
[53] | 427 | by the corresponding word of the second argument.
|
---|
| 428 | If the two arguments have a different number of words,
|
---|
| 429 | the excess words are just output separated by blanks. */
|
---|
| 430 | const char *tp;
|
---|
| 431 | const char *pp;
|
---|
| 432 | const char *list1_iterator = argv[0];
|
---|
[3138] | 433 | const char *list2_iterator = argv[1];
|
---|
[53] | 434 | do
|
---|
| 435 | {
|
---|
| 436 | unsigned int len1, len2;
|
---|
[3138] | 437 |
|
---|
[53] | 438 | tp = find_next_token (&list1_iterator, &len1);
|
---|
| 439 | if (tp != 0)
|
---|
[3138] | 440 | o = variable_buffer_output (o, tp, len1);
|
---|
| 441 |
|
---|
| 442 | pp = find_next_token (&list2_iterator, &len2);
|
---|
| 443 | if (pp != 0)
|
---|
[53] | 444 | o = variable_buffer_output (o, pp, len2);
|
---|
| 445 |
|
---|
| 446 | if (tp != 0 || pp != 0)
|
---|
| 447 | {
|
---|
| 448 | o = variable_buffer_output (o, " ", 1);
|
---|
| 449 | doneany = 1;
|
---|
| 450 | }
|
---|
| 451 | }
|
---|
| 452 | while (tp != 0 || pp != 0);
|
---|
| 453 | if (doneany)
|
---|
| 454 | /* Kill the last blank. */
|
---|
[153] | 455 | --o;
|
---|
[53] | 456 |
|
---|
| 457 | return o;
|
---|
[900] | 458 | }
|
---|
[53] | 459 |
|
---|
| 460 |
|
---|
| 461 | static char *
|
---|
| 462 | func_origin (char *o, char **argv, const char *funcname UNUSED)
|
---|
| 463 | {
|
---|
| 464 | /* Expand the argument. */
|
---|
| 465 | struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
|
---|
[3138] | 466 | if (v == 0)
|
---|
| 467 | o = variable_buffer_output (o, "undefined", 9);
|
---|
[53] | 468 | else
|
---|
[3138] | 469 | switch (v->origin)
|
---|
| 470 | {
|
---|
[53] | 471 | default:
|
---|
[3138] | 472 | case o_invalid:
|
---|
| 473 | abort ();
|
---|
[53] | 474 | break;
|
---|
[3138] | 475 | case o_default:
|
---|
| 476 | o = variable_buffer_output (o, "default", 7);
|
---|
[53] | 477 | break;
|
---|
[3138] | 478 | case o_env:
|
---|
| 479 | o = variable_buffer_output (o, "environment", 11);
|
---|
[53] | 480 | break;
|
---|
[3138] | 481 | case o_file:
|
---|
| 482 | o = variable_buffer_output (o, "file", 4);
|
---|
[53] | 483 | break;
|
---|
[3138] | 484 | case o_env_override:
|
---|
| 485 | o = variable_buffer_output (o, "environment override", 20);
|
---|
[53] | 486 | break;
|
---|
[3138] | 487 | case o_command:
|
---|
| 488 | o = variable_buffer_output (o, "command line", 12);
|
---|
[53] | 489 | break;
|
---|
| 490 | case o_override:
|
---|
| 491 | o = variable_buffer_output (o, "override", 8);
|
---|
| 492 | break;
|
---|
| 493 | case o_automatic:
|
---|
[501] | 494 | o = variable_buffer_output (o, "automatic", 9);
|
---|
| 495 | break;
|
---|
| 496 | }
|
---|
[900] | 497 |
|
---|
[501] | 498 | return o;
|
---|
| 499 | }
|
---|
| 500 |
|
---|
| 501 | static char *
|
---|
| 502 | func_flavor (char *o, char **argv, const char *funcname UNUSED)
|
---|
| 503 | {
|
---|
| 504 | struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
|
---|
| 505 |
|
---|
| 506 | if (v == 0)
|
---|
| 507 | o = variable_buffer_output (o, "undefined", 9);
|
---|
| 508 | else
|
---|
| 509 | if (v->recursive)
|
---|
[53] | 510 | o = variable_buffer_output (o, "recursive", 9);
|
---|
| 511 | else
|
---|
| 512 | o = variable_buffer_output (o, "simple", 6);
|
---|
| 513 |
|
---|
| 514 | return o;
|
---|
[900] | 515 | }
|
---|
| 516 |
|
---|
[53] | 517 |
|
---|
| 518 | static char *
|
---|
| 519 | func_notdir_suffix (char *o, char **argv, const char *funcname)
|
---|
[3138] | 520 | {
|
---|
[53] | 521 | /* Expand the argument. */
|
---|
[3138] | 522 | const char *list_iterator = argv[0];
|
---|
| 523 | const char *p2;
|
---|
| 524 | int doneany =0;
|
---|
| 525 | unsigned int len=0;
|
---|
| 526 |
|
---|
| 527 | int is_suffix = funcname[0] == 's';
|
---|
| 528 | int is_notdir = !is_suffix;
|
---|
| 529 | int stop = MAP_DIRSEP | (is_suffix ? MAP_DOT : 0);
|
---|
| 530 | #ifdef VMS
|
---|
| 531 | /* For VMS list_iterator points to a comma separated list. To use the common
|
---|
| 532 | [find_]next_token, create a local copy and replace the commas with
|
---|
| 533 | spaces. Obviously, there is a problem if there is a ',' in the VMS filename
|
---|
| 534 | (can only happen on ODS5), the same problem as with spaces in filenames,
|
---|
| 535 | which seems to be present in make on all platforms. */
|
---|
| 536 | char *vms_list_iterator = alloca(strlen(list_iterator) + 1);
|
---|
| 537 | int i;
|
---|
| 538 | for (i = 0; list_iterator[i]; i++)
|
---|
[53] | 539 | if (list_iterator[i] == ',')
|
---|
[3138] | 540 | vms_list_iterator[i] = ' ';
|
---|
[53] | 541 | else
|
---|
[3138] | 542 | vms_list_iterator[i] = list_iterator[i];
|
---|
[53] | 543 | vms_list_iterator[i] = list_iterator[i];
|
---|
[3138] | 544 | while ((p2 = find_next_token((const char**) &vms_list_iterator, &len)) != 0)
|
---|
| 545 | #else
|
---|
[53] | 546 | while ((p2 = find_next_token (&list_iterator, &len)) != 0)
|
---|
| 547 | #endif
|
---|
[3138] | 548 | {
|
---|
| 549 | const char *p = p2 + len - 1;
|
---|
| 550 |
|
---|
| 551 | while (p >= p2 && ! STOP_SET (*p, stop))
|
---|
| 552 | --p;
|
---|
| 553 |
|
---|
| 554 | if (p >= p2)
|
---|
[53] | 555 | {
|
---|
| 556 | if (is_notdir)
|
---|
[3138] | 557 | ++p;
|
---|
| 558 | else if (*p != '.')
|
---|
| 559 | continue;
|
---|
| 560 | o = variable_buffer_output (o, p, len - (p - p2));
|
---|
| 561 | }
|
---|
[53] | 562 | #ifdef HAVE_DOS_PATHS
|
---|
| 563 | /* Handle the case of "d:foo/bar". */
|
---|
[3138] | 564 | else if (is_notdir && p2[0] && p2[1] == ':')
|
---|
[53] | 565 | {
|
---|
| 566 | p = p2 + 2;
|
---|
[3138] | 567 | o = variable_buffer_output (o, p, len - (p - p2));
|
---|
| 568 | }
|
---|
| 569 | #endif
|
---|
| 570 | else if (is_notdir)
|
---|
| 571 | o = variable_buffer_output (o, p2, len);
|
---|
| 572 |
|
---|
| 573 | if (is_notdir || p >= p2)
|
---|
| 574 | {
|
---|
| 575 | #ifdef VMS
|
---|
| 576 | if (vms_comma_separator)
|
---|
[53] | 577 | o = variable_buffer_output (o, ",", 1);
|
---|
[900] | 578 | else
|
---|
[53] | 579 | #endif
|
---|
| 580 | o = variable_buffer_output (o, " ", 1);
|
---|
| 581 |
|
---|
| 582 | doneany = 1;
|
---|
| 583 | }
|
---|
| 584 | }
|
---|
| 585 |
|
---|
| 586 | if (doneany)
|
---|
| 587 | /* Kill last space. */
|
---|
| 588 | --o;
|
---|
| 589 |
|
---|
| 590 | return o;
|
---|
[900] | 591 | }
|
---|
| 592 |
|
---|
[3138] | 593 |
|
---|
| 594 | static char *
|
---|
[900] | 595 | func_basename_dir (char *o, char **argv, const char *funcname)
|
---|
[3138] | 596 | {
|
---|
| 597 | /* Expand the argument. */
|
---|
| 598 | const char *p3 = argv[0];
|
---|
| 599 | const char *p2;
|
---|
| 600 | int doneany = 0;
|
---|
| 601 | unsigned int len = 0;
|
---|
| 602 |
|
---|
| 603 | int is_basename = funcname[0] == 'b';
|
---|
| 604 | int is_dir = !is_basename;
|
---|
| 605 | int stop = MAP_DIRSEP | (is_basename ? MAP_DOT : 0) | MAP_NUL;
|
---|
| 606 | #ifdef VMS
|
---|
| 607 | /* As in func_notdir_suffix ... */
|
---|
| 608 | char *vms_p3 = alloca (strlen(p3) + 1);
|
---|
| 609 | int i;
|
---|
| 610 | for (i = 0; p3[i]; i++)
|
---|
[53] | 611 | if (p3[i] == ',')
|
---|
[3138] | 612 | vms_p3[i] = ' ';
|
---|
[900] | 613 | else
|
---|
[3138] | 614 | vms_p3[i] = p3[i];
|
---|
| 615 | vms_p3[i] = p3[i];
|
---|
| 616 | while ((p2 = find_next_token((const char**) &vms_p3, &len)) != 0)
|
---|
[53] | 617 | #else
|
---|
[900] | 618 | while ((p2 = find_next_token (&p3, &len)) != 0)
|
---|
| 619 | #endif
|
---|
| 620 | {
|
---|
| 621 | const char *p = p2 + len - 1;
|
---|
[53] | 622 | while (p >= p2 && ! STOP_SET (*p, stop))
|
---|
[900] | 623 | --p;
|
---|
| 624 |
|
---|
| 625 | if (p >= p2 && (is_dir))
|
---|
[53] | 626 | o = variable_buffer_output (o, p2, ++p - p2);
|
---|
[900] | 627 | else if (p >= p2 && (*p == '.'))
|
---|
[53] | 628 | o = variable_buffer_output (o, p2, p - p2);
|
---|
[3138] | 629 | #ifdef HAVE_DOS_PATHS
|
---|
| 630 | /* Handle the "d:foobar" case */
|
---|
| 631 | else if (p2[0] && p2[1] == ':' && is_dir)
|
---|
| 632 | o = variable_buffer_output (o, p2, 2);
|
---|
| 633 | #endif
|
---|
| 634 | else if (is_dir)
|
---|
| 635 | #ifdef VMS
|
---|
[53] | 636 | {
|
---|
| 637 | extern int vms_report_unix_paths;
|
---|
[900] | 638 | if (vms_report_unix_paths)
|
---|
[53] | 639 | o = variable_buffer_output (o, "./", 2);
|
---|
[900] | 640 | else
|
---|
[53] | 641 | o = variable_buffer_output (o, "[]", 2);
|
---|
| 642 | }
|
---|
[900] | 643 | #else
|
---|
| 644 | #ifndef _AMIGA
|
---|
| 645 | o = variable_buffer_output (o, "./", 2);
|
---|
[53] | 646 | #else
|
---|
[3138] | 647 | ; /* Just a nop... */
|
---|
| 648 | #endif /* AMIGA */
|
---|
| 649 | #endif /* !VMS */
|
---|
| 650 | else
|
---|
| 651 | /* The entire name is the basename. */
|
---|
| 652 | o = variable_buffer_output (o, p2, len);
|
---|
| 653 |
|
---|
[900] | 654 | #ifdef VMS
|
---|
| 655 | if (vms_comma_separator)
|
---|
[53] | 656 | o = variable_buffer_output (o, ",", 1);
|
---|
[900] | 657 | else
|
---|
| 658 | #endif
|
---|
| 659 | o = variable_buffer_output (o, " ", 1);
|
---|
[53] | 660 |
|
---|
[900] | 661 | doneany = 1;
|
---|
[53] | 662 | }
|
---|
| 663 |
|
---|
| 664 | if (doneany)
|
---|
| 665 | /* Kill last space. */
|
---|
| 666 | --o;
|
---|
| 667 |
|
---|
[900] | 668 | return o;
|
---|
[3138] | 669 | }
|
---|
[53] | 670 |
|
---|
| 671 | static char *
|
---|
| 672 | func_addsuffix_addprefix (char *o, char **argv, const char *funcname)
|
---|
[900] | 673 | {
|
---|
[53] | 674 | int fixlen = strlen (argv[0]);
|
---|
| 675 | const char *list_iterator = argv[1];
|
---|
| 676 | int is_addprefix = funcname[3] == 'p';
|
---|
| 677 | int is_addsuffix = !is_addprefix;
|
---|
| 678 |
|
---|
[3138] | 679 | int doneany = 0;
|
---|
[53] | 680 | const char *p;
|
---|
| 681 | unsigned int len;
|
---|
[3138] | 682 |
|
---|
[53] | 683 | while ((p = find_next_token (&list_iterator, &len)) != 0)
|
---|
| 684 | {
|
---|
| 685 | if (is_addprefix)
|
---|
| 686 | o = variable_buffer_output (o, argv[0], fixlen);
|
---|
| 687 | o = variable_buffer_output (o, p, len);
|
---|
| 688 | if (is_addsuffix)
|
---|
| 689 | o = variable_buffer_output (o, argv[0], fixlen);
|
---|
| 690 | o = variable_buffer_output (o, " ", 1);
|
---|
| 691 | doneany = 1;
|
---|
| 692 | }
|
---|
| 693 |
|
---|
| 694 | if (doneany)
|
---|
[153] | 695 | /* Kill last space. */
|
---|
[53] | 696 | --o;
|
---|
| 697 |
|
---|
[3138] | 698 | return o;
|
---|
[53] | 699 | }
|
---|
| 700 |
|
---|
| 701 | static char *
|
---|
| 702 | func_subst (char *o, char **argv, const char *funcname UNUSED)
|
---|
| 703 | {
|
---|
| 704 | o = subst_expand (o, argv[2], argv[0], argv[1], strlen (argv[0]),
|
---|
[153] | 705 | strlen (argv[1]), 0);
|
---|
[53] | 706 |
|
---|
| 707 | return o;
|
---|
[900] | 708 | }
|
---|
| 709 |
|
---|
[53] | 710 |
|
---|
| 711 | static char *
|
---|
| 712 | func_firstword (char *o, char **argv, const char *funcname UNUSED)
|
---|
| 713 | {
|
---|
| 714 | unsigned int i;
|
---|
| 715 | const char *words = argv[0]; /* Use a temp variable for find_next_token */
|
---|
| 716 | const char *p = find_next_token (&words, &i);
|
---|
[280] | 717 |
|
---|
| 718 | if (p != 0)
|
---|
| 719 | o = variable_buffer_output (o, p, i);
|
---|
| 720 |
|
---|
[900] | 721 | return o;
|
---|
| 722 | }
|
---|
| 723 |
|
---|
[53] | 724 | static char *
|
---|
[280] | 725 | func_lastword (char *o, char **argv, const char *funcname UNUSED)
|
---|
| 726 | {
|
---|
| 727 | unsigned int i;
|
---|
| 728 | const char *words = argv[0]; /* Use a temp variable for find_next_token */
|
---|
| 729 | const char *p = NULL;
|
---|
| 730 | const char *t;
|
---|
| 731 |
|
---|
| 732 | while ((t = find_next_token (&words, &i)))
|
---|
| 733 | p = t;
|
---|
[53] | 734 |
|
---|
[153] | 735 | if (p != 0)
|
---|
[53] | 736 | o = variable_buffer_output (o, p, i);
|
---|
| 737 |
|
---|
[900] | 738 | return o;
|
---|
[53] | 739 | }
|
---|
| 740 |
|
---|
[3138] | 741 | static char *
|
---|
[53] | 742 | func_words (char *o, char **argv, const char *funcname UNUSED)
|
---|
| 743 | {
|
---|
| 744 | int i = 0;
|
---|
| 745 | const char *word_iterator = argv[0];
|
---|
| 746 | char buf[20];
|
---|
| 747 |
|
---|
| 748 | while (find_next_token (&word_iterator, NULL) != 0)
|
---|
| 749 | ++i;
|
---|
| 750 |
|
---|
| 751 | sprintf (buf, "%d", i);
|
---|
| 752 | o = variable_buffer_output (o, buf, strlen (buf));
|
---|
| 753 |
|
---|
| 754 | return o;
|
---|
[280] | 755 | }
|
---|
[53] | 756 |
|
---|
| 757 | /* Set begpp to point to the first non-whitespace character of the string,
|
---|
[3138] | 758 | * and endpp to point to the last non-whitespace character of the string.
|
---|
[53] | 759 | * If the string is empty or contains nothing but whitespace, endpp will be
|
---|
[3138] | 760 | * begpp-1.
|
---|
[53] | 761 | */
|
---|
| 762 | char *
|
---|
| 763 | strip_whitespace (const char **begpp, const char **endpp)
|
---|
| 764 | {
|
---|
| 765 | while (*begpp <= *endpp && ISSPACE (**begpp))
|
---|
[900] | 766 | (*begpp) ++;
|
---|
[53] | 767 | while (*endpp >= *begpp && ISSPACE (**endpp))
|
---|
| 768 | (*endpp) --;
|
---|
| 769 | return (char *)*begpp;
|
---|
| 770 | }
|
---|
| 771 |
|
---|
| 772 | static void
|
---|
[3138] | 773 | check_numeric (const char *s, const char *msg)
|
---|
[53] | 774 | {
|
---|
| 775 | const char *end = s + strlen (s) - 1;
|
---|
| 776 | const char *beg = s;
|
---|
[3138] | 777 | strip_whitespace (&s, &end);
|
---|
[53] | 778 |
|
---|
| 779 | for (; s <= end; ++s)
|
---|
| 780 | if (!ISDIGIT (*s)) /* ISDIGIT only evals its arg once: see makeint.h. */
|
---|
| 781 | break;
|
---|
| 782 |
|
---|
[153] | 783 | if (s <= end || end - beg < 0)
|
---|
[53] | 784 | OSS (fatal, *expanding_var, "%s: '%s'", msg, beg);
|
---|
[900] | 785 | }
|
---|
| 786 |
|
---|
| 787 |
|
---|
[53] | 788 |
|
---|
| 789 | static char *
|
---|
[3138] | 790 | func_word (char *o, char **argv, const char *funcname UNUSED)
|
---|
[900] | 791 | {
|
---|
[53] | 792 | const char *end_p;
|
---|
| 793 | const char *p;
|
---|
[3138] | 794 | int i;
|
---|
| 795 |
|
---|
[53] | 796 | /* Check the first argument. */
|
---|
| 797 | check_numeric (argv[0], _("non-numeric first argument to 'word' function"));
|
---|
| 798 | i = atoi (argv[0]);
|
---|
| 799 |
|
---|
| 800 | if (i == 0)
|
---|
| 801 | O (fatal, *expanding_var,
|
---|
| 802 | _("first argument to 'word' function must be greater than 0"));
|
---|
| 803 |
|
---|
| 804 | end_p = argv[1];
|
---|
| 805 | while ((p = find_next_token (&end_p, 0)) != 0)
|
---|
| 806 | if (--i == 0)
|
---|
| 807 | break;
|
---|
| 808 |
|
---|
[153] | 809 | if (i == 0)
|
---|
[53] | 810 | o = variable_buffer_output (o, p, end_p - p);
|
---|
| 811 |
|
---|
| 812 | return o;
|
---|
| 813 | }
|
---|
| 814 |
|
---|
[3138] | 815 | static char *
|
---|
[53] | 816 | func_wordlist (char *o, char **argv, const char *funcname UNUSED)
|
---|
[3138] | 817 | {
|
---|
[53] | 818 | int start, count;
|
---|
| 819 |
|
---|
[280] | 820 | /* Check the arguments. */
|
---|
[3138] | 821 | check_numeric (argv[0],
|
---|
| 822 | _("non-numeric first argument to 'wordlist' function"));
|
---|
[280] | 823 | check_numeric (argv[1],
|
---|
[53] | 824 | _("non-numeric second argument to 'wordlist' function"));
|
---|
| 825 |
|
---|
| 826 | start = atoi (argv[0]);
|
---|
| 827 | if (start < 1)
|
---|
[900] | 828 | ON (fatal, *expanding_var,
|
---|
| 829 | "invalid first argument to 'wordlist' function: '%d'", start);
|
---|
[53] | 830 |
|
---|
| 831 | count = atoi (argv[1]) - start + 1;
|
---|
| 832 |
|
---|
| 833 | if (count > 0)
|
---|
| 834 | {
|
---|
| 835 | const char *p;
|
---|
| 836 | const char *end_p = argv[2];
|
---|
| 837 |
|
---|
| 838 | /* Find the beginning of the "start"th word. */
|
---|
| 839 | while (((p = find_next_token (&end_p, 0)) != 0) && --start)
|
---|
| 840 | ;
|
---|
| 841 |
|
---|
| 842 | if (p)
|
---|
| 843 | {
|
---|
| 844 | /* Find the end of the "count"th word from start. */
|
---|
| 845 | while (--count && (find_next_token (&end_p, 0) != 0))
|
---|
| 846 | ;
|
---|
| 847 |
|
---|
| 848 | /* Return the stuff in the middle. */
|
---|
[900] | 849 | o = variable_buffer_output (o, p, end_p - p);
|
---|
[153] | 850 | }
|
---|
[53] | 851 | }
|
---|
| 852 |
|
---|
[280] | 853 | return o;
|
---|
| 854 | }
|
---|
[53] | 855 |
|
---|
| 856 | static char *
|
---|
| 857 | func_findstring (char *o, char **argv, const char *funcname UNUSED)
|
---|
| 858 | {
|
---|
| 859 | /* Find the first occurrence of the first string in the second. */
|
---|
[153] | 860 | if (strstr (argv[1], argv[0]) != 0)
|
---|
[53] | 861 | o = variable_buffer_output (o, argv[0], strlen (argv[0]));
|
---|
| 862 |
|
---|
| 863 | return o;
|
---|
| 864 | }
|
---|
[900] | 865 |
|
---|
[53] | 866 | static char *
|
---|
| 867 | func_foreach (char *o, char **argv, const char *funcname UNUSED)
|
---|
[900] | 868 | {
|
---|
| 869 | /* expand only the first two. */
|
---|
[53] | 870 | char *varname = expand_argument (argv[0], NULL);
|
---|
[900] | 871 | char *list = expand_argument (argv[1], NULL);
|
---|
[53] | 872 | const char *body = argv[2];
|
---|
[3138] | 873 |
|
---|
| 874 | int doneany = 0;
|
---|
| 875 | const char *list_iterator = list;
|
---|
| 876 | const char *p;
|
---|
[53] | 877 | unsigned int len;
|
---|
[3138] | 878 | struct variable *var;
|
---|
[53] | 879 |
|
---|
| 880 | /* Clean up the variable name by removing whitespace. */
|
---|
| 881 | char *vp = next_token (varname);
|
---|
| 882 | end_of_token (vp)[0] = '\0';
|
---|
| 883 |
|
---|
| 884 | push_new_variable_scope ();
|
---|
[900] | 885 | var = define_variable (vp, strlen (vp), "", o_automatic, 0);
|
---|
[2596] | 886 |
|
---|
[53] | 887 | /* loop through LIST, put the value in VAR and expand BODY */
|
---|
| 888 | while ((p = find_next_token (&list_iterator, &len)) != 0)
|
---|
| 889 | {
|
---|
| 890 | char *result = 0;
|
---|
| 891 |
|
---|
| 892 | free (var->value);
|
---|
| 893 | var->value = xstrndup (p, len);
|
---|
| 894 |
|
---|
| 895 | result = allocated_variable_expand (body);
|
---|
| 896 |
|
---|
| 897 | o = variable_buffer_output (o, result, strlen (result));
|
---|
| 898 | o = variable_buffer_output (o, " ", 1);
|
---|
| 899 | doneany = 1;
|
---|
| 900 | free (result);
|
---|
| 901 | }
|
---|
| 902 |
|
---|
| 903 | if (doneany)
|
---|
| 904 | /* Kill the last space. */
|
---|
| 905 | --o;
|
---|
| 906 |
|
---|
| 907 | pop_variable_scope ();
|
---|
| 908 | free (varname);
|
---|
| 909 | free (list);
|
---|
| 910 |
|
---|
| 911 | return o;
|
---|
| 912 | }
|
---|
| 913 |
|
---|
| 914 | struct a_word
|
---|
| 915 | {
|
---|
| 916 | struct a_word *next;
|
---|
| 917 | struct a_word *chain;
|
---|
| 918 | char *str;
|
---|
| 919 | int length;
|
---|
| 920 | int matched;
|
---|
| 921 | };
|
---|
| 922 |
|
---|
| 923 | static unsigned long
|
---|
| 924 | a_word_hash_1 (const void *key)
|
---|
| 925 | {
|
---|
| 926 | return_STRING_HASH_1 (((struct a_word const *) key)->str);
|
---|
| 927 | }
|
---|
| 928 |
|
---|
| 929 | static unsigned long
|
---|
| 930 | a_word_hash_2 (const void *key)
|
---|
| 931 | {
|
---|
| 932 | return_STRING_HASH_2 (((struct a_word const *) key)->str);
|
---|
| 933 | }
|
---|
| 934 |
|
---|
[3138] | 935 | static int
|
---|
[53] | 936 | a_word_hash_cmp (const void *x, const void *y)
|
---|
| 937 | {
|
---|
| 938 | int result = ((struct a_word const *) x)->length - ((struct a_word const *) y)->length;
|
---|
| 939 | if (result)
|
---|
| 940 | return result;
|
---|
| 941 | return_STRING_COMPARE (((struct a_word const *) x)->str,
|
---|
| 942 | ((struct a_word const *) y)->str);
|
---|
| 943 | }
|
---|
| 944 |
|
---|
| 945 | struct a_pattern
|
---|
| 946 | {
|
---|
| 947 | struct a_pattern *next;
|
---|
| 948 | char *str;
|
---|
| 949 | char *percent;
|
---|
| 950 | int length;
|
---|
| 951 | };
|
---|
| 952 |
|
---|
| 953 | static char *
|
---|
| 954 | func_filter_filterout (char *o, char **argv, const char *funcname)
|
---|
| 955 | {
|
---|
| 956 | struct a_word *wordhead;
|
---|
[3138] | 957 | struct a_word **wordtail;
|
---|
[900] | 958 | struct a_word *wp;
|
---|
| 959 | struct a_pattern *pathead;
|
---|
[53] | 960 | struct a_pattern **pattail;
|
---|
| 961 | struct a_pattern *pp;
|
---|
| 962 |
|
---|
| 963 | struct hash_table a_word_table;
|
---|
| 964 | int is_filter = funcname[CSTRLEN ("filter")] == '\0';
|
---|
| 965 | const char *pat_iterator = argv[0];
|
---|
[3138] | 966 | const char *word_iterator = argv[1];
|
---|
| 967 | int literals = 0;
|
---|
| 968 | int words = 0;
|
---|
[53] | 969 | int hashing = 0;
|
---|
| 970 | char *p;
|
---|
| 971 | unsigned int len;
|
---|
| 972 |
|
---|
[900] | 973 | /* Chop ARGV[0] up into patterns to match against the words.
|
---|
[53] | 974 | We don't need to preserve it because our caller frees all the
|
---|
| 975 | argument memory anyway. */
|
---|
| 976 |
|
---|
| 977 | pattail = &pathead;
|
---|
| 978 | while ((p = find_next_token (&pat_iterator, &len)) != 0)
|
---|
[3138] | 979 | {
|
---|
[53] | 980 | struct a_pattern *pat = alloca (sizeof (struct a_pattern));
|
---|
| 981 |
|
---|
| 982 | *pattail = pat;
|
---|
| 983 | pattail = &pat->next;
|
---|
| 984 |
|
---|
[3138] | 985 | if (*pat_iterator != '\0')
|
---|
| 986 | ++pat_iterator;
|
---|
| 987 |
|
---|
| 988 | pat->str = p;
|
---|
[53] | 989 | p[len] = '\0';
|
---|
| 990 | pat->percent = find_percent (p);
|
---|
| 991 | if (pat->percent == 0)
|
---|
| 992 | literals++;
|
---|
| 993 |
|
---|
| 994 | /* find_percent() might shorten the string so LEN is wrong. */
|
---|
| 995 | pat->length = strlen (pat->str);
|
---|
| 996 | }
|
---|
[900] | 997 | *pattail = 0;
|
---|
[53] | 998 |
|
---|
| 999 | /* Chop ARGV[1] up into words to match against the patterns. */
|
---|
| 1000 |
|
---|
| 1001 | wordtail = &wordhead;
|
---|
| 1002 | while ((p = find_next_token (&word_iterator, &len)) != 0)
|
---|
[3138] | 1003 | {
|
---|
[53] | 1004 | struct a_word *word = alloca (sizeof (struct a_word));
|
---|
| 1005 |
|
---|
| 1006 | *wordtail = word;
|
---|
| 1007 | wordtail = &word->next;
|
---|
| 1008 |
|
---|
| 1009 | if (*word_iterator != '\0')
|
---|
| 1010 | ++word_iterator;
|
---|
| 1011 |
|
---|
| 1012 | p[len] = '\0';
|
---|
| 1013 | word->str = p;
|
---|
| 1014 | word->length = len;
|
---|
| 1015 | word->matched = 0;
|
---|
| 1016 | word->chain = 0;
|
---|
| 1017 | words++;
|
---|
[900] | 1018 | }
|
---|
| 1019 | *wordtail = 0;
|
---|
[53] | 1020 |
|
---|
[3138] | 1021 | /* Only use a hash table if arg list lengths justifies the cost. */
|
---|
| 1022 | hashing = (literals >= 2 && (literals * words) >= 10);
|
---|
| 1023 | if (hashing)
|
---|
| 1024 | {
|
---|
| 1025 | hash_init (&a_word_table, words, a_word_hash_1, a_word_hash_2,
|
---|
[53] | 1026 | a_word_hash_cmp);
|
---|
| 1027 | for (wp = wordhead; wp != 0; wp = wp->next)
|
---|
| 1028 | {
|
---|
| 1029 | struct a_word *owp = hash_insert (&a_word_table, wp);
|
---|
| 1030 | if (owp)
|
---|
| 1031 | wp->chain = owp;
|
---|
| 1032 | }
|
---|
| 1033 | }
|
---|
[3138] | 1034 |
|
---|
| 1035 | if (words)
|
---|
| 1036 | {
|
---|
| 1037 | int doneany = 0;
|
---|
| 1038 |
|
---|
| 1039 | /* Run each pattern through the words, killing words. */
|
---|
| 1040 | for (pp = pathead; pp != 0; pp = pp->next)
|
---|
| 1041 | {
|
---|
| 1042 | if (pp->percent)
|
---|
| 1043 | for (wp = wordhead; wp != 0; wp = wp->next)
|
---|
| 1044 | wp->matched |= pattern_matches (pp->str, pp->percent, wp->str);
|
---|
| 1045 | else if (hashing)
|
---|
| 1046 | {
|
---|
| 1047 | struct a_word a_word_key;
|
---|
| 1048 | a_word_key.str = pp->str;
|
---|
| 1049 | a_word_key.length = pp->length;
|
---|
| 1050 | wp = hash_find_item (&a_word_table, &a_word_key);
|
---|
| 1051 | while (wp)
|
---|
| 1052 | {
|
---|
| 1053 | wp->matched |= 1;
|
---|
| 1054 | wp = wp->chain;
|
---|
[53] | 1055 | }
|
---|
| 1056 | }
|
---|
| 1057 | else
|
---|
[3138] | 1058 | for (wp = wordhead; wp != 0; wp = wp->next)
|
---|
| 1059 | wp->matched |= (wp->length == pp->length
|
---|
| 1060 | && strneq (pp->str, wp->str, wp->length));
|
---|
| 1061 | }
|
---|
| 1062 |
|
---|
| 1063 | /* Output the words that matched (or didn't, for filter-out). */
|
---|
[53] | 1064 | for (wp = wordhead; wp != 0; wp = wp->next)
|
---|
| 1065 | if (is_filter ? wp->matched : !wp->matched)
|
---|
[3138] | 1066 | {
|
---|
| 1067 | o = variable_buffer_output (o, wp->str, strlen (wp->str));
|
---|
[53] | 1068 | o = variable_buffer_output (o, " ", 1);
|
---|
| 1069 | doneany = 1;
|
---|
| 1070 | }
|
---|
| 1071 |
|
---|
| 1072 | if (doneany)
|
---|
| 1073 | /* Kill the last space. */
|
---|
| 1074 | --o;
|
---|
| 1075 | }
|
---|
| 1076 |
|
---|
| 1077 | if (hashing)
|
---|
[153] | 1078 | hash_free (&a_word_table, 0);
|
---|
[53] | 1079 |
|
---|
[900] | 1080 | return o;
|
---|
| 1081 | }
|
---|
[53] | 1082 |
|
---|
| 1083 |
|
---|
| 1084 | static char *
|
---|
| 1085 | func_strip (char *o, char **argv, const char *funcname UNUSED)
|
---|
[900] | 1086 | {
|
---|
[53] | 1087 | const char *p = argv[0];
|
---|
[3138] | 1088 | int doneany = 0;
|
---|
[53] | 1089 |
|
---|
[3138] | 1090 | while (*p != '\0')
|
---|
| 1091 | {
|
---|
[53] | 1092 | int i=0;
|
---|
[3138] | 1093 | const char *word_start;
|
---|
[53] | 1094 |
|
---|
| 1095 | NEXT_TOKEN (p);
|
---|
| 1096 | word_start = p;
|
---|
| 1097 | for (i=0; *p != '\0' && !ISSPACE (*p); ++p, ++i)
|
---|
| 1098 | {}
|
---|
| 1099 | if (!i)
|
---|
| 1100 | break;
|
---|
| 1101 | o = variable_buffer_output (o, word_start, i);
|
---|
[900] | 1102 | o = variable_buffer_output (o, " ", 1);
|
---|
[53] | 1103 | doneany = 1;
|
---|
| 1104 | }
|
---|
| 1105 |
|
---|
| 1106 | if (doneany)
|
---|
| 1107 | /* Kill the last space. */
|
---|
| 1108 | --o;
|
---|
| 1109 |
|
---|
| 1110 | return o;
|
---|
| 1111 | }
|
---|
| 1112 |
|
---|
| 1113 | /*
|
---|
| 1114 | Print a warning or fatal message.
|
---|
| 1115 | */
|
---|
| 1116 | static char *
|
---|
| 1117 | func_error (char *o, char **argv, const char *funcname)
|
---|
| 1118 | {
|
---|
| 1119 | char **argvp;
|
---|
| 1120 | char *msg, *p;
|
---|
| 1121 | int len;
|
---|
[900] | 1122 |
|
---|
[53] | 1123 | /* The arguments will be broken on commas. Rather than create yet
|
---|
| 1124 | another special case where function arguments aren't broken up,
|
---|
| 1125 | just create a format string that puts them back together. */
|
---|
| 1126 | for (len=0, argvp=argv; *argvp != 0; ++argvp)
|
---|
| 1127 | len += strlen (*argvp) + 2;
|
---|
| 1128 |
|
---|
| 1129 | p = msg = alloca (len + 1);
|
---|
| 1130 |
|
---|
| 1131 | for (argvp=argv; argvp[1] != 0; ++argvp)
|
---|
| 1132 | {
|
---|
[3138] | 1133 | strcpy (p, *argvp);
|
---|
| 1134 | p += strlen (*argvp);
|
---|
[280] | 1135 | *(p++) = ',';
|
---|
[3138] | 1136 | *(p++) = ' ';
|
---|
[53] | 1137 | }
|
---|
[280] | 1138 | strcpy (p, *argvp);
|
---|
[3138] | 1139 |
|
---|
[280] | 1140 | switch (*funcname)
|
---|
| 1141 | {
|
---|
| 1142 | case 'e':
|
---|
[3138] | 1143 | OS (fatal, reading_file, "%s", msg);
|
---|
| 1144 |
|
---|
[280] | 1145 | case 'w':
|
---|
| 1146 | OS (error, reading_file, "%s", msg);
|
---|
| 1147 | break;
|
---|
[3138] | 1148 |
|
---|
| 1149 | case 'i':
|
---|
[280] | 1150 | outputs (0, msg);
|
---|
[53] | 1151 | outputs (0, "\n");
|
---|
| 1152 | break;
|
---|
| 1153 |
|
---|
| 1154 | default:
|
---|
| 1155 | OS (fatal, *expanding_var, "Internal error: func_error: '%s'", funcname);
|
---|
| 1156 | }
|
---|
| 1157 |
|
---|
| 1158 | /* The warning function expands to the empty string. */
|
---|
| 1159 | return o;
|
---|
[153] | 1160 | }
|
---|
[53] | 1161 |
|
---|
[900] | 1162 |
|
---|
| 1163 | /*
|
---|
| 1164 | chop argv[0] into words, and sort them.
|
---|
[53] | 1165 | */
|
---|
| 1166 | static char *
|
---|
| 1167 | func_sort (char *o, char **argv, const char *funcname UNUSED)
|
---|
[900] | 1168 | {
|
---|
| 1169 | const char *t;
|
---|
[3138] | 1170 | char **words;
|
---|
| 1171 | int wordi;
|
---|
[53] | 1172 | char *p;
|
---|
[3138] | 1173 | unsigned int len;
|
---|
[900] | 1174 |
|
---|
[53] | 1175 | /* Find the maximum number of words we'll have. */
|
---|
| 1176 | t = argv[0];
|
---|
[3138] | 1177 | wordi = 0;
|
---|
[53] | 1178 | while ((p = find_next_token (&t, NULL)) != 0)
|
---|
[900] | 1179 | {
|
---|
| 1180 | ++t;
|
---|
| 1181 | ++wordi;
|
---|
| 1182 | }
|
---|
| 1183 |
|
---|
| 1184 | words = xmalloc ((wordi == 0 ? 1 : wordi) * sizeof (char *));
|
---|
| 1185 |
|
---|
| 1186 | /* Now assign pointers to each string in the array. */
|
---|
| 1187 | t = argv[0];
|
---|
[53] | 1188 | wordi = 0;
|
---|
[900] | 1189 | while ((p = find_next_token (&t, &len)) != 0)
|
---|
[53] | 1190 | {
|
---|
[3138] | 1191 | ++t;
|
---|
| 1192 | p[len] = '\0';
|
---|
[900] | 1193 | words[wordi++] = p;
|
---|
| 1194 | }
|
---|
| 1195 |
|
---|
| 1196 | if (wordi)
|
---|
| 1197 | {
|
---|
[53] | 1198 | int i;
|
---|
[900] | 1199 |
|
---|
| 1200 | /* Now sort the list of words. */
|
---|
| 1201 | qsort (words, wordi, sizeof (char *), alpha_compare);
|
---|
| 1202 |
|
---|
| 1203 | /* Now write the sorted list, uniquified. */
|
---|
| 1204 | for (i = 0; i < wordi; ++i)
|
---|
| 1205 | {
|
---|
[53] | 1206 | len = strlen (words[i]);
|
---|
[900] | 1207 | if (i == wordi - 1 || strlen (words[i + 1]) != len
|
---|
| 1208 | || strcmp (words[i], words[i + 1]))
|
---|
| 1209 | {
|
---|
[53] | 1210 | o = variable_buffer_output (o, words[i], len);
|
---|
| 1211 | o = variable_buffer_output (o, " ", 1);
|
---|
| 1212 | }
|
---|
| 1213 | }
|
---|
| 1214 |
|
---|
| 1215 | /* Kill the last space. */
|
---|
| 1216 | --o;
|
---|
| 1217 | }
|
---|
| 1218 |
|
---|
| 1219 | free (words);
|
---|
| 1220 |
|
---|
| 1221 | return o;
|
---|
| 1222 | }
|
---|
| 1223 |
|
---|
| 1224 | /*
|
---|
| 1225 | $(if condition,true-part[,false-part])
|
---|
| 1226 |
|
---|
| 1227 | CONDITION is false iff it evaluates to an empty string. White
|
---|
| 1228 | space before and after condition are stripped before evaluation.
|
---|
| 1229 |
|
---|
[153] | 1230 | If CONDITION is true, then TRUE-PART is evaluated, otherwise FALSE-PART is
|
---|
[53] | 1231 | evaluated (if it exists). Because only one of the two PARTs is evaluated,
|
---|
| 1232 | you can use $(if ...) to create side-effects (with $(shell ...), for
|
---|
| 1233 | example).
|
---|
| 1234 | */
|
---|
| 1235 |
|
---|
| 1236 | static char *
|
---|
| 1237 | func_if (char *o, char **argv, const char *funcname UNUSED)
|
---|
| 1238 | {
|
---|
| 1239 | const char *begp = argv[0];
|
---|
| 1240 | const char *endp = begp + strlen (argv[0]) - 1;
|
---|
| 1241 | int result = 0;
|
---|
| 1242 |
|
---|
| 1243 | /* Find the result of the condition: if we have a value, and it's not
|
---|
| 1244 | empty, the condition is true. If we don't have a value, or it's the
|
---|
| 1245 | empty string, then it's false. */
|
---|
| 1246 |
|
---|
| 1247 | strip_whitespace (&begp, &endp);
|
---|
| 1248 |
|
---|
| 1249 | if (begp <= endp)
|
---|
| 1250 | {
|
---|
| 1251 | char *expansion = expand_argument (begp, endp+1);
|
---|
| 1252 |
|
---|
| 1253 | result = strlen (expansion);
|
---|
| 1254 | free (expansion);
|
---|
| 1255 | }
|
---|
[900] | 1256 |
|
---|
[53] | 1257 | /* If the result is true (1) we want to eval the first argument, and if
|
---|
[900] | 1258 | it's false (0) we want to eval the second. If the argument doesn't
|
---|
[53] | 1259 | exist we do nothing, otherwise expand it and add to the buffer. */
|
---|
| 1260 |
|
---|
| 1261 | argv += 1 + !result;
|
---|
| 1262 |
|
---|
| 1263 | if (*argv)
|
---|
| 1264 | {
|
---|
| 1265 | char *expansion = expand_argument (*argv, NULL);
|
---|
| 1266 |
|
---|
| 1267 | o = variable_buffer_output (o, expansion, strlen (expansion));
|
---|
[501] | 1268 |
|
---|
| 1269 | free (expansion);
|
---|
| 1270 | }
|
---|
| 1271 |
|
---|
| 1272 | return o;
|
---|
| 1273 | }
|
---|
| 1274 |
|
---|
| 1275 | /*
|
---|
| 1276 | $(or condition1[,condition2[,condition3[...]]])
|
---|
| 1277 |
|
---|
| 1278 | A CONDITION is false iff it evaluates to an empty string. White
|
---|
| 1279 | space before and after CONDITION are stripped before evaluation.
|
---|
| 1280 |
|
---|
| 1281 | CONDITION1 is evaluated. If it's true, then this is the result of
|
---|
[53] | 1282 | expansion. If it's false, CONDITION2 is evaluated, and so on. If none of
|
---|
[501] | 1283 | the conditions are true, the expansion is the empty string.
|
---|
| 1284 |
|
---|
| 1285 | Once a CONDITION is true no further conditions are evaluated
|
---|
| 1286 | (short-circuiting).
|
---|
| 1287 | */
|
---|
| 1288 |
|
---|
| 1289 | static char *
|
---|
| 1290 | func_or (char *o, char **argv, const char *funcname UNUSED)
|
---|
| 1291 | {
|
---|
| 1292 | for ( ; *argv ; ++argv)
|
---|
| 1293 | {
|
---|
| 1294 | const char *begp = *argv;
|
---|
| 1295 | const char *endp = begp + strlen (*argv) - 1;
|
---|
| 1296 | char *expansion;
|
---|
| 1297 | int result = 0;
|
---|
| 1298 |
|
---|
| 1299 | /* Find the result of the condition: if it's false keep going. */
|
---|
| 1300 |
|
---|
| 1301 | strip_whitespace (&begp, &endp);
|
---|
| 1302 |
|
---|
| 1303 | if (begp > endp)
|
---|
| 1304 | continue;
|
---|
| 1305 |
|
---|
| 1306 | expansion = expand_argument (begp, endp+1);
|
---|
| 1307 | result = strlen (expansion);
|
---|
| 1308 |
|
---|
| 1309 | /* If the result is false keep going. */
|
---|
| 1310 | if (!result)
|
---|
| 1311 | {
|
---|
| 1312 | free (expansion);
|
---|
| 1313 | continue;
|
---|
| 1314 | }
|
---|
| 1315 |
|
---|
| 1316 | /* It's true! Keep this result and return. */
|
---|
| 1317 | o = variable_buffer_output (o, expansion, result);
|
---|
| 1318 | free (expansion);
|
---|
| 1319 | break;
|
---|
| 1320 | }
|
---|
| 1321 |
|
---|
| 1322 | return o;
|
---|
| 1323 | }
|
---|
| 1324 |
|
---|
| 1325 | /*
|
---|
| 1326 | $(and condition1[,condition2[,condition3[...]]])
|
---|
| 1327 |
|
---|
| 1328 | A CONDITION is false iff it evaluates to an empty string. White
|
---|
| 1329 | space before and after CONDITION are stripped before evaluation.
|
---|
| 1330 |
|
---|
| 1331 | CONDITION1 is evaluated. If it's false, then this is the result of
|
---|
| 1332 | expansion. If it's true, CONDITION2 is evaluated, and so on. If all of
|
---|
| 1333 | the conditions are true, the expansion is the result of the last condition.
|
---|
| 1334 |
|
---|
| 1335 | Once a CONDITION is false no further conditions are evaluated
|
---|
| 1336 | (short-circuiting).
|
---|
| 1337 | */
|
---|
| 1338 |
|
---|
| 1339 | static char *
|
---|
| 1340 | func_and (char *o, char **argv, const char *funcname UNUSED)
|
---|
[3138] | 1341 | {
|
---|
[501] | 1342 | char *expansion;
|
---|
| 1343 |
|
---|
| 1344 | while (1)
|
---|
| 1345 | {
|
---|
| 1346 | const char *begp = *argv;
|
---|
| 1347 | const char *endp = begp + strlen (*argv) - 1;
|
---|
| 1348 | int result;
|
---|
| 1349 |
|
---|
| 1350 | /* An empty condition is always false. */
|
---|
| 1351 | strip_whitespace (&begp, &endp);
|
---|
| 1352 | if (begp > endp)
|
---|
| 1353 | return o;
|
---|
| 1354 |
|
---|
| 1355 | expansion = expand_argument (begp, endp+1);
|
---|
| 1356 | result = strlen (expansion);
|
---|
| 1357 |
|
---|
| 1358 | /* If the result is false, stop here: we're done. */
|
---|
| 1359 | if (!result)
|
---|
| 1360 | break;
|
---|
| 1361 |
|
---|
| 1362 | /* Otherwise the result is true. If this is the last one, keep this
|
---|
| 1363 | result and quit. Otherwise go on to the next one! */
|
---|
| 1364 |
|
---|
| 1365 | if (*(++argv))
|
---|
| 1366 | free (expansion);
|
---|
| 1367 | else
|
---|
| 1368 | {
|
---|
| 1369 | o = variable_buffer_output (o, expansion, result);
|
---|
| 1370 | break;
|
---|
| 1371 | }
|
---|
| 1372 | }
|
---|
[153] | 1373 |
|
---|
[53] | 1374 | free (expansion);
|
---|
| 1375 |
|
---|
| 1376 | return o;
|
---|
| 1377 | }
|
---|
| 1378 |
|
---|
| 1379 | static char *
|
---|
| 1380 | func_wildcard (char *o, char **argv, const char *funcname UNUSED)
|
---|
| 1381 | {
|
---|
| 1382 | #ifdef _AMIGA
|
---|
| 1383 | o = wildcard_expansion (argv[0], o);
|
---|
| 1384 | #else
|
---|
| 1385 | char *p = string_glob (argv[0]);
|
---|
| 1386 | o = variable_buffer_output (o, p, strlen (p));
|
---|
| 1387 | #endif
|
---|
| 1388 | return o;
|
---|
| 1389 | }
|
---|
| 1390 |
|
---|
| 1391 | /*
|
---|
| 1392 | $(eval <makefile string>)
|
---|
[153] | 1393 |
|
---|
[53] | 1394 | Always resolves to the empty string.
|
---|
| 1395 |
|
---|
| 1396 | Treat the arguments as a segment of makefile, and parse them.
|
---|
| 1397 | */
|
---|
| 1398 |
|
---|
| 1399 | static char *
|
---|
| 1400 | func_eval (char *o, char **argv, const char *funcname UNUSED)
|
---|
| 1401 | {
|
---|
| 1402 | char *buf;
|
---|
[3138] | 1403 | unsigned int len;
|
---|
[53] | 1404 |
|
---|
| 1405 | /* Eval the buffer. Pop the current variable buffer setting so that the
|
---|
| 1406 | eval'd code can use its own without conflicting. */
|
---|
| 1407 |
|
---|
| 1408 | install_variable_buffer (&buf, &len);
|
---|
| 1409 |
|
---|
| 1410 | eval_buffer (argv[0], NULL);
|
---|
| 1411 |
|
---|
[153] | 1412 | restore_variable_buffer (buf, len);
|
---|
[53] | 1413 |
|
---|
| 1414 | return o;
|
---|
| 1415 | }
|
---|
| 1416 |
|
---|
| 1417 |
|
---|
| 1418 | static char *
|
---|
[3138] | 1419 | func_value (char *o, char **argv, const char *funcname UNUSED)
|
---|
[53] | 1420 | {
|
---|
| 1421 | /* Look up the variable. */
|
---|
| 1422 | struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
|
---|
| 1423 |
|
---|
| 1424 | /* Copy its value into the output buffer without expanding it. */
|
---|
[3138] | 1425 | if (v)
|
---|
[53] | 1426 | o = variable_buffer_output (o, v->value, strlen (v->value));
|
---|
[501] | 1427 |
|
---|
[3138] | 1428 | return o;
|
---|
[53] | 1429 | }
|
---|
| 1430 |
|
---|
| 1431 | /*
|
---|
[3138] | 1432 | \r is replaced on UNIX as well. Is this desirable?
|
---|
[53] | 1433 | */
|
---|
| 1434 | static void
|
---|
| 1435 | fold_newlines (char *buffer, unsigned int *length, int trim_newlines)
|
---|
| 1436 | {
|
---|
[3138] | 1437 | char *dst = buffer;
|
---|
[53] | 1438 | char *src = buffer;
|
---|
[3138] | 1439 | char *last_nonnl = buffer - 1;
|
---|
| 1440 | src[*length] = 0;
|
---|
| 1441 | for (; *src != '\0'; ++src)
|
---|
[53] | 1442 | {
|
---|
[3138] | 1443 | if (src[0] == '\r' && src[1] == '\n')
|
---|
| 1444 | continue;
|
---|
| 1445 | if (*src == '\n')
|
---|
| 1446 | {
|
---|
[53] | 1447 | *dst++ = ' ';
|
---|
[3138] | 1448 | }
|
---|
| 1449 | else
|
---|
| 1450 | {
|
---|
| 1451 | last_nonnl = dst;
|
---|
[53] | 1452 | *dst++ = *src;
|
---|
| 1453 | }
|
---|
| 1454 | }
|
---|
| 1455 |
|
---|
[3138] | 1456 | if (!trim_newlines && (last_nonnl < (dst - 2)))
|
---|
| 1457 | last_nonnl = dst - 2;
|
---|
[53] | 1458 |
|
---|
[3138] | 1459 | *(++last_nonnl) = '\0';
|
---|
| 1460 | *length = last_nonnl - buffer;
|
---|
| 1461 | }
|
---|
| 1462 |
|
---|
[53] | 1463 | pid_t shell_function_pid = 0;
|
---|
[3138] | 1464 | static int shell_function_completed;
|
---|
| 1465 |
|
---|
| 1466 | void
|
---|
| 1467 | shell_completed (int exit_code, int exit_sig)
|
---|
| 1468 | {
|
---|
[53] | 1469 | char buf[256];
|
---|
[3138] | 1470 |
|
---|
| 1471 | shell_function_pid = 0;
|
---|
| 1472 | if (exit_sig == 0 && exit_code == 127)
|
---|
[53] | 1473 | shell_function_completed = -1;
|
---|
| 1474 | else
|
---|
| 1475 | shell_function_completed = 1;
|
---|
| 1476 |
|
---|
| 1477 | sprintf (buf, "%d", exit_code);
|
---|
| 1478 | define_variable_cname (".SHELLSTATUS", buf, o_override, 0);
|
---|
| 1479 | }
|
---|
| 1480 |
|
---|
| 1481 | #ifdef WINDOWS32
|
---|
[3138] | 1482 | /*untested*/
|
---|
| 1483 |
|
---|
[53] | 1484 | #include <windows.h>
|
---|
| 1485 | #include <io.h>
|
---|
[3138] | 1486 | #include "sub_proc.h"
|
---|
| 1487 |
|
---|
[53] | 1488 |
|
---|
| 1489 | int
|
---|
[3138] | 1490 | windows32_openpipe (int *pipedes, int errfd, pid_t *pid_p, char **command_argv, char **envp)
|
---|
| 1491 | {
|
---|
[53] | 1492 | SECURITY_ATTRIBUTES saAttr;
|
---|
[3138] | 1493 | HANDLE hIn = INVALID_HANDLE_VALUE;
|
---|
| 1494 | HANDLE hErr = INVALID_HANDLE_VALUE;
|
---|
| 1495 | HANDLE hChildOutRd;
|
---|
[53] | 1496 | HANDLE hChildOutWr;
|
---|
| 1497 | HANDLE hProcess, tmpIn, tmpErr;
|
---|
| 1498 | DWORD e;
|
---|
| 1499 |
|
---|
| 1500 | /* Set status for return. */
|
---|
[3138] | 1501 | pipedes[0] = pipedes[1] = -1;
|
---|
| 1502 | *pid_p = (pid_t)-1;
|
---|
| 1503 |
|
---|
| 1504 | saAttr.nLength = sizeof (SECURITY_ATTRIBUTES);
|
---|
| 1505 | saAttr.bInheritHandle = TRUE;
|
---|
| 1506 | saAttr.lpSecurityDescriptor = NULL;
|
---|
| 1507 |
|
---|
| 1508 | /* Standard handles returned by GetStdHandle can be NULL or
|
---|
| 1509 | INVALID_HANDLE_VALUE if the parent process closed them. If that
|
---|
| 1510 | happens, we open the null device and pass its handle to
|
---|
| 1511 | process_begin below as the corresponding handle to inherit. */
|
---|
| 1512 | tmpIn = GetStdHandle (STD_INPUT_HANDLE);
|
---|
| 1513 | if (DuplicateHandle (GetCurrentProcess (), tmpIn,
|
---|
| 1514 | GetCurrentProcess (), &hIn,
|
---|
| 1515 | 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE)
|
---|
| 1516 | {
|
---|
| 1517 | e = GetLastError ();
|
---|
| 1518 | if (e == ERROR_INVALID_HANDLE)
|
---|
| 1519 | {
|
---|
| 1520 | tmpIn = CreateFile ("NUL", GENERIC_READ,
|
---|
| 1521 | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
---|
| 1522 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
---|
| 1523 | if (tmpIn != INVALID_HANDLE_VALUE
|
---|
| 1524 | && DuplicateHandle (GetCurrentProcess (), tmpIn,
|
---|
| 1525 | GetCurrentProcess (), &hIn,
|
---|
| 1526 | 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE)
|
---|
| 1527 | CloseHandle (tmpIn);
|
---|
| 1528 | }
|
---|
| 1529 | if (hIn == INVALID_HANDLE_VALUE)
|
---|
| 1530 | {
|
---|
| 1531 | ON (error, NILF,
|
---|
| 1532 | _("windows32_openpipe: DuplicateHandle(In) failed (e=%ld)\n"), e);
|
---|
| 1533 | return -1;
|
---|
| 1534 | }
|
---|
| 1535 | }
|
---|
| 1536 | tmpErr = (HANDLE)_get_osfhandle (errfd);
|
---|
| 1537 | if (DuplicateHandle (GetCurrentProcess (), tmpErr,
|
---|
| 1538 | GetCurrentProcess (), &hErr,
|
---|
| 1539 | 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE)
|
---|
| 1540 | {
|
---|
| 1541 | e = GetLastError ();
|
---|
| 1542 | if (e == ERROR_INVALID_HANDLE)
|
---|
| 1543 | {
|
---|
| 1544 | tmpErr = CreateFile ("NUL", GENERIC_WRITE,
|
---|
| 1545 | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
---|
| 1546 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
---|
| 1547 | if (tmpErr != INVALID_HANDLE_VALUE
|
---|
| 1548 | && DuplicateHandle (GetCurrentProcess (), tmpErr,
|
---|
| 1549 | GetCurrentProcess (), &hErr,
|
---|
| 1550 | 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE)
|
---|
| 1551 | CloseHandle (tmpErr);
|
---|
| 1552 | }
|
---|
[53] | 1553 | if (hErr == INVALID_HANDLE_VALUE)
|
---|
[3138] | 1554 | {
|
---|
| 1555 | ON (error, NILF,
|
---|
| 1556 | _("windows32_openpipe: DuplicateHandle(Err) failed (e=%ld)\n"), e);
|
---|
| 1557 | return -1;
|
---|
| 1558 | }
|
---|
[53] | 1559 | }
|
---|
[3138] | 1560 |
|
---|
[53] | 1561 | if (! CreatePipe (&hChildOutRd, &hChildOutWr, &saAttr, 0))
|
---|
| 1562 | {
|
---|
[3138] | 1563 | ON (error, NILF, _("CreatePipe() failed (e=%ld)\n"), GetLastError());
|
---|
| 1564 | return -1;
|
---|
| 1565 | }
|
---|
| 1566 |
|
---|
[53] | 1567 | hProcess = process_init_fd (hIn, hChildOutWr, hErr);
|
---|
| 1568 |
|
---|
[3138] | 1569 | if (!hProcess)
|
---|
| 1570 | {
|
---|
[2596] | 1571 | O (error, NILF, _("windows32_openpipe(): process_init_fd() failed\n"));
|
---|
| 1572 | return -1;
|
---|
[53] | 1573 | }
|
---|
[3138] | 1574 |
|
---|
| 1575 | /* make sure that CreateProcess() has Path it needs */
|
---|
| 1576 | sync_Path_environment ();
|
---|
| 1577 | /* 'sync_Path_environment' may realloc 'environ', so take note of
|
---|
[53] | 1578 | the new value. */
|
---|
[3138] | 1579 | envp = environ;
|
---|
| 1580 |
|
---|
[53] | 1581 | if (! process_begin (hProcess, command_argv, envp, command_argv[0], NULL))
|
---|
[3138] | 1582 | {
|
---|
| 1583 | /* register process for wait */
|
---|
[53] | 1584 | process_register (hProcess);
|
---|
[3138] | 1585 |
|
---|
| 1586 | /* set the pid for returning to caller */
|
---|
| 1587 | *pid_p = (pid_t) hProcess;
|
---|
| 1588 |
|
---|
| 1589 | /* set up to read data from child */
|
---|
| 1590 | pipedes[0] = _open_osfhandle ((intptr_t) hChildOutRd, O_RDONLY);
|
---|
| 1591 |
|
---|
| 1592 | /* this will be closed almost right away */
|
---|
[53] | 1593 | pipedes[1] = _open_osfhandle ((intptr_t) hChildOutWr, O_APPEND);
|
---|
[3138] | 1594 | return 0;
|
---|
| 1595 | }
|
---|
| 1596 | else
|
---|
| 1597 | {
|
---|
| 1598 | /* reap/cleanup the failed process */
|
---|
[53] | 1599 | process_cleanup (hProcess);
|
---|
[3138] | 1600 |
|
---|
| 1601 | /* close handles which were duplicated, they weren't used */
|
---|
| 1602 | if (hIn != INVALID_HANDLE_VALUE)
|
---|
[53] | 1603 | CloseHandle (hIn);
|
---|
[3138] | 1604 | if (hErr != INVALID_HANDLE_VALUE)
|
---|
| 1605 | CloseHandle (hErr);
|
---|
[53] | 1606 |
|
---|
| 1607 | /* close pipe handles, they won't be used */
|
---|
| 1608 | CloseHandle (hChildOutRd);
|
---|
| 1609 | CloseHandle (hChildOutWr);
|
---|
| 1610 |
|
---|
| 1611 | return -1;
|
---|
| 1612 | }
|
---|
| 1613 | }
|
---|
| 1614 | #endif
|
---|
[3138] | 1615 |
|
---|
[53] | 1616 |
|
---|
| 1617 | #ifdef __MSDOS__
|
---|
| 1618 | FILE *
|
---|
| 1619 | msdos_openpipe (int* pipedes, int *pidp, char *text)
|
---|
| 1620 | {
|
---|
[3138] | 1621 | FILE *fpipe=0;
|
---|
[53] | 1622 | /* MSDOS can't fork, but it has 'popen'. */
|
---|
| 1623 | struct variable *sh = lookup_variable ("SHELL", 5);
|
---|
| 1624 | int e;
|
---|
| 1625 | extern int dos_command_running, dos_status;
|
---|
| 1626 |
|
---|
| 1627 | /* Make sure not to bother processing an empty line. */
|
---|
| 1628 | NEXT_TOKEN (text);
|
---|
[3138] | 1629 | if (*text == '\0')
|
---|
[53] | 1630 | return 0;
|
---|
| 1631 |
|
---|
| 1632 | if (sh)
|
---|
| 1633 | {
|
---|
| 1634 | char buf[PATH_MAX + 7];
|
---|
| 1635 | /* This makes sure $SHELL value is used by $(shell), even
|
---|
| 1636 | though the target environment is not passed to it. */
|
---|
| 1637 | sprintf (buf, "SHELL=%s", sh->value);
|
---|
| 1638 | putenv (buf);
|
---|
| 1639 | }
|
---|
| 1640 |
|
---|
| 1641 | e = errno;
|
---|
| 1642 | errno = 0;
|
---|
| 1643 | dos_command_running = 1;
|
---|
| 1644 | dos_status = 0;
|
---|
| 1645 | /* If dos_status becomes non-zero, it means the child process
|
---|
| 1646 | was interrupted by a signal, like SIGINT or SIGQUIT. See
|
---|
| 1647 | fatal_error_signal in commands.c. */
|
---|
[3138] | 1648 | fpipe = popen (text, "rt");
|
---|
[53] | 1649 | dos_command_running = 0;
|
---|
[3138] | 1650 | if (!fpipe || dos_status)
|
---|
| 1651 | {
|
---|
| 1652 | pipedes[0] = -1;
|
---|
| 1653 | *pidp = -1;
|
---|
[53] | 1654 | if (dos_status)
|
---|
| 1655 | errno = EINTR;
|
---|
| 1656 | else if (errno == 0)
|
---|
| 1657 | errno = ENOMEM;
|
---|
| 1658 | if (fpipe)
|
---|
| 1659 | pclose (fpipe);
|
---|
| 1660 | shell_completed (127, 0);
|
---|
| 1661 | }
|
---|
| 1662 | else
|
---|
| 1663 | {
|
---|
| 1664 | pipedes[0] = fileno (fpipe);
|
---|
| 1665 | *pidp = 42; /* Yes, the Meaning of Life, the Universe, and Everything! */
|
---|
| 1666 | errno = e;
|
---|
| 1667 | }
|
---|
| 1668 | return fpipe;
|
---|
| 1669 | }
|
---|
| 1670 | #endif
|
---|
| 1671 |
|
---|
[3138] | 1672 | /*
|
---|
| 1673 | Do shell spawning, with the naughty bits for different OSes.
|
---|
| 1674 | */
|
---|
| 1675 |
|
---|
| 1676 | #ifdef VMS
|
---|
| 1677 |
|
---|
| 1678 | /* VMS can't do $(shell ...) */
|
---|
| 1679 |
|
---|
| 1680 | char *
|
---|
[53] | 1681 | func_shell_base (char *o, char **argv, int trim_newlines)
|
---|
| 1682 | {
|
---|
| 1683 | fprintf (stderr, "This platform does not support shell\n");
|
---|
| 1684 | die (MAKE_TROUBLE);
|
---|
[3138] | 1685 | return NULL;
|
---|
| 1686 | }
|
---|
[53] | 1687 |
|
---|
[900] | 1688 | #define func_shell 0
|
---|
[3138] | 1689 |
|
---|
[53] | 1690 | #else
|
---|
| 1691 | #ifndef _AMIGA
|
---|
| 1692 | char *
|
---|
| 1693 | func_shell_base (char *o, char **argv, int trim_newlines)
|
---|
[900] | 1694 | {
|
---|
[53] | 1695 | char *batch_filename = NULL;
|
---|
| 1696 | int errfd;
|
---|
[2596] | 1697 | #ifdef __MSDOS__
|
---|
[53] | 1698 | FILE *fpipe;
|
---|
| 1699 | #endif
|
---|
[3138] | 1700 | char **command_argv;
|
---|
| 1701 | const char *error_prefix;
|
---|
| 1702 | char **envp;
|
---|
| 1703 | int pipedes[2];
|
---|
| 1704 | pid_t pid;
|
---|
| 1705 |
|
---|
| 1706 | #ifndef __MSDOS__
|
---|
| 1707 | #ifdef WINDOWS32
|
---|
[53] | 1708 | /* Reset just_print_flag. This is needed on Windows when batch files
|
---|
[1989] | 1709 | are used to run the commands, because we normally refrain from
|
---|
| 1710 | creating batch files under -n. */
|
---|
[53] | 1711 | int j_p_f = just_print_flag;
|
---|
[3138] | 1712 | just_print_flag = 0;
|
---|
| 1713 | #endif
|
---|
| 1714 |
|
---|
[53] | 1715 | /* Construct the argument list. */
|
---|
[3138] | 1716 | command_argv = construct_command_argv (argv[0], NULL, NULL, 0,
|
---|
| 1717 | &batch_filename);
|
---|
| 1718 | if (command_argv == 0)
|
---|
[53] | 1719 | {
|
---|
[3138] | 1720 | #ifdef WINDOWS32
|
---|
| 1721 | just_print_flag = j_p_f;
|
---|
| 1722 | #endif
|
---|
| 1723 | return o;
|
---|
| 1724 | }
|
---|
| 1725 | #endif /* !__MSDOS__ */
|
---|
[53] | 1726 |
|
---|
[900] | 1727 | /* Using a target environment for 'shell' loses in cases like:
|
---|
| 1728 | export var = $(shell echo foobie)
|
---|
[3138] | 1729 | bad := $(var)
|
---|
[501] | 1730 | because target_environment hits a loop trying to expand $(var) to put it
|
---|
| 1731 | in the environment. This is even more confusing when 'var' was not
|
---|
[53] | 1732 | explicitly exported, but just appeared in the calling environment.
|
---|
| 1733 |
|
---|
| 1734 | See Savannah bug #10593.
|
---|
[280] | 1735 |
|
---|
[53] | 1736 | envp = target_environment (NULL);
|
---|
[900] | 1737 | */
|
---|
[3138] | 1738 |
|
---|
| 1739 | envp = environ;
|
---|
[900] | 1740 |
|
---|
[53] | 1741 | /* For error messages. */
|
---|
| 1742 | if (reading_file && reading_file->filenm)
|
---|
| 1743 | {
|
---|
| 1744 | char *p = alloca (strlen (reading_file->filenm)+11+4);
|
---|
[3138] | 1745 | sprintf (p, "%s:%lu: ", reading_file->filenm,
|
---|
| 1746 | reading_file->lineno + reading_file->offset);
|
---|
| 1747 | error_prefix = p;
|
---|
| 1748 | }
|
---|
| 1749 | else
|
---|
| 1750 | error_prefix = "";
|
---|
[900] | 1751 |
|
---|
[53] | 1752 | /* Set up the output in case the shell writes something. */
|
---|
| 1753 | output_start ();
|
---|
| 1754 |
|
---|
| 1755 | errfd = (output_context && output_context->err >= 0
|
---|
| 1756 | ? output_context->err : FD_STDERR);
|
---|
| 1757 |
|
---|
[3138] | 1758 | #if defined(__MSDOS__)
|
---|
[900] | 1759 | fpipe = msdos_openpipe (pipedes, &pid, argv[0]);
|
---|
[3138] | 1760 | if (pipedes[0] < 0)
|
---|
| 1761 | {
|
---|
| 1762 | perror_with_name (error_prefix, "pipe");
|
---|
| 1763 | return o;
|
---|
[900] | 1764 | }
|
---|
| 1765 |
|
---|
[3138] | 1766 | #elif defined(WINDOWS32)
|
---|
| 1767 | windows32_openpipe (pipedes, errfd, &pid, command_argv, envp);
|
---|
| 1768 | /* Restore the value of just_print_flag. */
|
---|
[900] | 1769 | just_print_flag = j_p_f;
|
---|
| 1770 |
|
---|
[3138] | 1771 | if (pipedes[0] < 0)
|
---|
[53] | 1772 | {
|
---|
| 1773 | /* Open of the pipe failed, mark as failed execution. */
|
---|
| 1774 | shell_completed (127, 0);
|
---|
| 1775 | perror_with_name (error_prefix, "pipe");
|
---|
| 1776 | return o;
|
---|
| 1777 | }
|
---|
| 1778 |
|
---|
[3138] | 1779 | #else
|
---|
[53] | 1780 | if (pipe (pipedes) < 0)
|
---|
| 1781 | {
|
---|
[3138] | 1782 | perror_with_name (error_prefix, "pipe");
|
---|
| 1783 | return o;
|
---|
| 1784 | }
|
---|
| 1785 |
|
---|
| 1786 | /* Close handles that are unnecessary for the child process. */
|
---|
| 1787 | CLOSE_ON_EXEC(pipedes[1]);
|
---|
| 1788 | CLOSE_ON_EXEC(pipedes[0]);
|
---|
| 1789 |
|
---|
| 1790 | {
|
---|
| 1791 | struct output out;
|
---|
[53] | 1792 | out.syncout = 1;
|
---|
[3138] | 1793 | out.out = pipedes[1];
|
---|
| 1794 | out.err = errfd;
|
---|
| 1795 |
|
---|
| 1796 | pid = child_execute_job (&out, 1, command_argv, envp);
|
---|
[53] | 1797 | }
|
---|
| 1798 |
|
---|
[3138] | 1799 | if (pid < 0)
|
---|
| 1800 | {
|
---|
| 1801 | perror_with_name (error_prefix, "fork");
|
---|
| 1802 | return o;
|
---|
| 1803 | }
|
---|
| 1804 | #endif
|
---|
| 1805 |
|
---|
[53] | 1806 | {
|
---|
[3138] | 1807 | char *buffer;
|
---|
[53] | 1808 | unsigned int maxlen, i;
|
---|
[3138] | 1809 | int cc;
|
---|
| 1810 |
|
---|
| 1811 | /* Record the PID for reap_children. */
|
---|
[53] | 1812 | shell_function_pid = pid;
|
---|
[3138] | 1813 | #ifndef __MSDOS__
|
---|
| 1814 | shell_function_completed = 0;
|
---|
| 1815 |
|
---|
| 1816 | /* Free the storage only the child needed. */
|
---|
| 1817 | free (command_argv[0]);
|
---|
[53] | 1818 | free (command_argv);
|
---|
| 1819 |
|
---|
[3138] | 1820 | /* Close the write side of the pipe. We test for -1, since
|
---|
[53] | 1821 | pipedes[1] is -1 on MS-Windows, and some versions of MS
|
---|
[3138] | 1822 | libraries barf when 'close' is called with -1. */
|
---|
| 1823 | if (pipedes[1] >= 0)
|
---|
[53] | 1824 | close (pipedes[1]);
|
---|
[3138] | 1825 | #endif
|
---|
| 1826 |
|
---|
| 1827 | /* Set up and read from the pipe. */
|
---|
| 1828 |
|
---|
| 1829 | maxlen = 200;
|
---|
| 1830 | buffer = xmalloc (maxlen + 1);
|
---|
| 1831 |
|
---|
| 1832 | /* Read from the pipe until it gets EOF. */
|
---|
[53] | 1833 | for (i = 0; ; i += cc)
|
---|
[3138] | 1834 | {
|
---|
| 1835 | if (i == maxlen)
|
---|
| 1836 | {
|
---|
| 1837 | maxlen += 512;
|
---|
| 1838 | buffer = xrealloc (buffer, maxlen + 1);
|
---|
[53] | 1839 | }
|
---|
[3138] | 1840 |
|
---|
[53] | 1841 | EINTRLOOP (cc, read (pipedes[0], &buffer[i], maxlen - i));
|
---|
[3138] | 1842 | if (cc <= 0)
|
---|
| 1843 | break;
|
---|
| 1844 | }
|
---|
| 1845 | buffer[i] = '\0';
|
---|
| 1846 |
|
---|
[53] | 1847 | /* Close the read side of the pipe. */
|
---|
[3138] | 1848 | #ifdef __MSDOS__
|
---|
[53] | 1849 | if (fpipe)
|
---|
| 1850 | {
|
---|
[3138] | 1851 | int st = pclose (fpipe);
|
---|
| 1852 | shell_completed (st, 0);
|
---|
| 1853 | }
|
---|
| 1854 | #else
|
---|
[53] | 1855 | (void) close (pipedes[0]);
|
---|
[3138] | 1856 | #endif
|
---|
| 1857 |
|
---|
| 1858 | /* Loop until child_handler or reap_children() sets
|
---|
| 1859 | shell_function_completed to the status of our child shell. */
|
---|
| 1860 | while (shell_function_completed == 0)
|
---|
| 1861 | reap_children (1, 0);
|
---|
[53] | 1862 |
|
---|
[3138] | 1863 | if (batch_filename)
|
---|
[53] | 1864 | {
|
---|
[3138] | 1865 | DB (DB_VERBOSE, (_("Cleaning up temporary batch file %s\n"),
|
---|
| 1866 | batch_filename));
|
---|
| 1867 | remove (batch_filename);
|
---|
[53] | 1868 | free (batch_filename);
|
---|
[3138] | 1869 | }
|
---|
| 1870 | shell_function_pid = 0;
|
---|
| 1871 |
|
---|
| 1872 | /* shell_completed() will set shell_function_completed to 1 when the
|
---|
| 1873 | child dies normally, or to -1 if it dies with status 127, which is
|
---|
| 1874 | most likely an exec fail. */
|
---|
| 1875 |
|
---|
| 1876 | if (shell_function_completed == -1)
|
---|
| 1877 | {
|
---|
| 1878 | /* This likely means that the execvp failed, so we should just
|
---|
| 1879 | write the error message in the pipe from the child. */
|
---|
| 1880 | fputs (buffer, stderr);
|
---|
| 1881 | fflush (stderr);
|
---|
| 1882 | }
|
---|
[53] | 1883 | else
|
---|
[3138] | 1884 | {
|
---|
| 1885 | /* The child finished normally. Replace all newlines in its output
|
---|
[53] | 1886 | with spaces, and put that in the variable output buffer. */
|
---|
| 1887 | fold_newlines (buffer, &i, trim_newlines);
|
---|
| 1888 | o = variable_buffer_output (o, buffer, i);
|
---|
| 1889 | }
|
---|
[3138] | 1890 |
|
---|
[53] | 1891 | free (buffer);
|
---|
| 1892 | }
|
---|
| 1893 |
|
---|
[3138] | 1894 | return o;
|
---|
| 1895 | }
|
---|
[53] | 1896 |
|
---|
| 1897 | #else /* _AMIGA */
|
---|
| 1898 |
|
---|
| 1899 | /* Do the Amiga version of func_shell. */
|
---|
| 1900 |
|
---|
| 1901 | char *
|
---|
| 1902 | func_shell_base (char *o, char **argv, int trim_newlines)
|
---|
| 1903 | {
|
---|
| 1904 | /* Amiga can't fork nor spawn, but I can start a program with
|
---|
| 1905 | redirection of my choice. However, this means that we
|
---|
| 1906 | don't have an opportunity to reopen stdout to trap it. Thus,
|
---|
| 1907 | we save our own stdout onto a new descriptor and dup a temp
|
---|
| 1908 | file's descriptor onto our stdout temporarily. After we
|
---|
| 1909 | spawn the shell program, we dup our own stdout back to the
|
---|
| 1910 | stdout descriptor. The buffer reading is the same as above,
|
---|
[501] | 1911 | except that we're now reading from a file. */
|
---|
| 1912 |
|
---|
[53] | 1913 | #include <dos/dos.h>
|
---|
| 1914 | #include <proto/dos.h>
|
---|
| 1915 |
|
---|
| 1916 | BPTR child_stdout;
|
---|
| 1917 | char tmp_output[FILENAME_MAX];
|
---|
| 1918 | unsigned int maxlen = 200, i;
|
---|
[1989] | 1919 | int cc;
|
---|
| 1920 | char * buffer, * ptr;
|
---|
[53] | 1921 | char ** aptr;
|
---|
| 1922 | int len = 0;
|
---|
| 1923 | char* batch_filename = NULL;
|
---|
| 1924 |
|
---|
[3138] | 1925 | /* Construct the argument list. */
|
---|
[53] | 1926 | command_argv = construct_command_argv (argv[0], NULL, NULL, 0,
|
---|
| 1927 | &batch_filename);
|
---|
| 1928 | if (command_argv == 0)
|
---|
| 1929 | return o;
|
---|
| 1930 |
|
---|
| 1931 | /* Note the mktemp() is a security hole, but this only runs on Amiga.
|
---|
| 1932 | Ideally we would use output_tmpfile(), but this uses a special
|
---|
| 1933 | Open(), not fopen(), and I'm not familiar enough with the code to mess
|
---|
| 1934 | with it. */
|
---|
| 1935 | strcpy (tmp_output, "t:MakeshXXXXXXXX");
|
---|
| 1936 | mktemp (tmp_output);
|
---|
| 1937 | child_stdout = Open (tmp_output, MODE_NEWFILE);
|
---|
| 1938 |
|
---|
| 1939 | for (aptr=command_argv; *aptr; aptr++)
|
---|
| 1940 | len += strlen (*aptr) + 1;
|
---|
| 1941 |
|
---|
| 1942 | buffer = xmalloc (len + 1);
|
---|
| 1943 | ptr = buffer;
|
---|
| 1944 |
|
---|
| 1945 | for (aptr=command_argv; *aptr; aptr++)
|
---|
| 1946 | {
|
---|
| 1947 | strcpy (ptr, *aptr);
|
---|
| 1948 | ptr += strlen (ptr) + 1;
|
---|
| 1949 | *ptr ++ = ' ';
|
---|
| 1950 | *ptr = 0;
|
---|
| 1951 | }
|
---|
| 1952 |
|
---|
| 1953 | ptr[-1] = '\n';
|
---|
| 1954 |
|
---|
| 1955 | Execute (buffer, NULL, child_stdout);
|
---|
| 1956 | free (buffer);
|
---|
| 1957 |
|
---|
| 1958 | Close (child_stdout);
|
---|
| 1959 |
|
---|
[3138] | 1960 | child_stdout = Open (tmp_output, MODE_OLDFILE);
|
---|
| 1961 |
|
---|
| 1962 | buffer = xmalloc (maxlen);
|
---|
| 1963 | i = 0;
|
---|
[53] | 1964 | do
|
---|
| 1965 | {
|
---|
| 1966 | if (i == maxlen)
|
---|
[3138] | 1967 | {
|
---|
[53] | 1968 | maxlen += 512;
|
---|
| 1969 | buffer = xrealloc (buffer, maxlen + 1);
|
---|
| 1970 | }
|
---|
| 1971 |
|
---|
[3138] | 1972 | cc = Read (child_stdout, &buffer[i], maxlen - i);
|
---|
[53] | 1973 | if (cc > 0)
|
---|
| 1974 | i += cc;
|
---|
| 1975 | } while (cc > 0);
|
---|
| 1976 |
|
---|
| 1977 | Close (child_stdout);
|
---|
[3138] | 1978 |
|
---|
| 1979 | fold_newlines (buffer, &i, trim_newlines);
|
---|
| 1980 | o = variable_buffer_output (o, buffer, i);
|
---|
| 1981 | free (buffer);
|
---|
| 1982 | return o;
|
---|
| 1983 | }
|
---|
[53] | 1984 | #endif /* _AMIGA */
|
---|
| 1985 |
|
---|
| 1986 | static char *
|
---|
| 1987 | func_shell (char *o, char **argv, const char *funcname UNUSED)
|
---|
| 1988 | {
|
---|
[3138] | 1989 | return func_shell_base (o, argv, 1);
|
---|
[53] | 1990 | }
|
---|
| 1991 | #endif /* !VMS */
|
---|
[3138] | 1992 |
|
---|
[53] | 1993 | #ifdef EXPERIMENTAL
|
---|
| 1994 |
|
---|
| 1995 | /*
|
---|
| 1996 | equality. Return is string-boolean, i.e., the empty string is false.
|
---|
| 1997 | */
|
---|
| 1998 | static char *
|
---|
| 1999 | func_eq (char *o, char **argv, char *funcname UNUSED)
|
---|
| 2000 | {
|
---|
| 2001 | int result = ! strcmp (argv[0], argv[1]);
|
---|
| 2002 | o = variable_buffer_output (o, result ? "1" : "", result);
|
---|
| 2003 | return o;
|
---|
[3138] | 2004 | }
|
---|
[53] | 2005 |
|
---|
[900] | 2006 |
|
---|
[53] | 2007 | /*
|
---|
[3138] | 2008 | string-boolean not operator.
|
---|
[53] | 2009 | */
|
---|
| 2010 | static char *
|
---|
| 2011 | func_not (char *o, char **argv, char *funcname UNUSED)
|
---|
| 2012 | {
|
---|
| 2013 | const char *s = argv[0];
|
---|
| 2014 | int result = 0;
|
---|
| 2015 | NEXT_TOKEN (s);
|
---|
[2596] | 2016 | result = ! (*s);
|
---|
[3138] | 2017 | o = variable_buffer_output (o, result ? "1" : "", result);
|
---|
| 2018 | return o;
|
---|
| 2019 | }
|
---|
| 2020 | #endif
|
---|
| 2021 | |
---|
| 2022 |
|
---|
[2596] | 2023 |
|
---|
| 2024 | #ifdef HAVE_DOS_PATHS
|
---|
| 2025 | # ifdef __CYGWIN__
|
---|
| 2026 | # define IS_ABSOLUTE(n) ((n[0] && n[1] == ':') || STOP_SET (n[0], MAP_DIRSEP))
|
---|
| 2027 | # else
|
---|
[3138] | 2028 | # define IS_ABSOLUTE(n) (n[0] && n[1] == ':')
|
---|
| 2029 | # endif
|
---|
[280] | 2030 | # define ROOT_LEN 3
|
---|
| 2031 | #else
|
---|
| 2032 | #define IS_ABSOLUTE(n) (n[0] == '/')
|
---|
| 2033 | #define ROOT_LEN 1
|
---|
| 2034 | #endif
|
---|
| 2035 |
|
---|
[2596] | 2036 | /* Return the absolute name of file NAME which does not contain any '.',
|
---|
[280] | 2037 | '..' components nor any repeated path separators ('/'). */
|
---|
| 2038 |
|
---|
| 2039 | static char *
|
---|
| 2040 | abspath (const char *name, char *apath)
|
---|
| 2041 | {
|
---|
| 2042 | char *dest;
|
---|
[2596] | 2043 | const char *start, *end, *apath_limit;
|
---|
[280] | 2044 | unsigned long root_len = ROOT_LEN;
|
---|
| 2045 |
|
---|
| 2046 | if (name[0] == '\0' || apath == NULL)
|
---|
[3138] | 2047 | return NULL;
|
---|
[280] | 2048 |
|
---|
| 2049 | apath_limit = apath + GET_PATH_MAX;
|
---|
| 2050 |
|
---|
[2596] | 2051 | if (!IS_ABSOLUTE(name))
|
---|
[3138] | 2052 | {
|
---|
| 2053 | /* It is unlikely we would make it until here but just to make sure. */
|
---|
| 2054 | if (!starting_directory)
|
---|
| 2055 | return NULL;
|
---|
| 2056 |
|
---|
| 2057 | strcpy (apath, starting_directory);
|
---|
| 2058 |
|
---|
| 2059 | #ifdef HAVE_DOS_PATHS
|
---|
| 2060 | if (STOP_SET (name[0], MAP_DIRSEP))
|
---|
| 2061 | {
|
---|
| 2062 | if (STOP_SET (name[1], MAP_DIRSEP))
|
---|
| 2063 | {
|
---|
| 2064 | /* A UNC. Don't prepend a drive letter. */
|
---|
| 2065 | apath[0] = name[0];
|
---|
| 2066 | apath[1] = name[1];
|
---|
[2596] | 2067 | root_len = 2;
|
---|
| 2068 | }
|
---|
[280] | 2069 | /* We have /foo, an absolute file name except for the drive
|
---|
| 2070 | letter. Assume the missing drive letter is the current
|
---|
| 2071 | drive, which we can get if we remove from starting_directory
|
---|
| 2072 | everything past the root directory. */
|
---|
[3138] | 2073 | apath[root_len] = '\0';
|
---|
| 2074 | }
|
---|
| 2075 | #endif
|
---|
| 2076 |
|
---|
[2596] | 2077 | dest = strchr (apath, '\0');
|
---|
| 2078 | }
|
---|
| 2079 | else
|
---|
| 2080 | {
|
---|
| 2081 | #if defined(__CYGWIN__) && defined(HAVE_DOS_PATHS)
|
---|
| 2082 | if (STOP_SET (name[0], MAP_DIRSEP))
|
---|
[3138] | 2083 | root_len = 1;
|
---|
| 2084 | #endif
|
---|
| 2085 | strncpy (apath, name, root_len);
|
---|
| 2086 | apath[root_len] = '\0';
|
---|
| 2087 | dest = apath + root_len;
|
---|
| 2088 | /* Get past the root, since we already copied it. */
|
---|
| 2089 | name += root_len;
|
---|
| 2090 | #ifdef HAVE_DOS_PATHS
|
---|
| 2091 | if (! STOP_SET (apath[root_len - 1], MAP_DIRSEP))
|
---|
| 2092 | {
|
---|
[2596] | 2093 | /* Convert d:foo into d:./foo and increase root_len. */
|
---|
[3138] | 2094 | apath[2] = '.';
|
---|
[2596] | 2095 | apath[3] = '/';
|
---|
[280] | 2096 | dest++;
|
---|
| 2097 | root_len++;
|
---|
| 2098 | /* strncpy above copied one character too many. */
|
---|
| 2099 | name--;
|
---|
| 2100 | }
|
---|
| 2101 | else
|
---|
| 2102 | apath[root_len - 1] = '/'; /* make sure it's a forward slash */
|
---|
[3138] | 2103 | #endif
|
---|
| 2104 | }
|
---|
[280] | 2105 |
|
---|
| 2106 | for (start = end = name; *start != '\0'; start = end)
|
---|
[3138] | 2107 | {
|
---|
[280] | 2108 | unsigned long len;
|
---|
| 2109 |
|
---|
| 2110 | /* Skip sequence of multiple path-separators. */
|
---|
| 2111 | while (STOP_SET (*start, MAP_DIRSEP))
|
---|
| 2112 | ++start;
|
---|
[3138] | 2113 |
|
---|
[280] | 2114 | /* Find end of path component. */
|
---|
[3138] | 2115 | for (end = start; ! STOP_SET (*end, MAP_DIRSEP|MAP_NUL); ++end)
|
---|
[280] | 2116 | ;
|
---|
[3138] | 2117 |
|
---|
| 2118 | len = end - start;
|
---|
| 2119 |
|
---|
| 2120 | if (len == 0)
|
---|
| 2121 | break;
|
---|
| 2122 | else if (len == 1 && start[0] == '.')
|
---|
[280] | 2123 | /* nothing */;
|
---|
[3138] | 2124 | else if (len == 2 && start[0] == '.' && start[1] == '.')
|
---|
| 2125 | {
|
---|
[280] | 2126 | /* Back up to previous component, ignore if at root already. */
|
---|
| 2127 | if (dest > apath + root_len)
|
---|
[3138] | 2128 | for (--dest; ! STOP_SET (dest[-1], MAP_DIRSEP); --dest)
|
---|
[280] | 2129 | ;
|
---|
| 2130 | }
|
---|
[3138] | 2131 | else
|
---|
[280] | 2132 | {
|
---|
[3138] | 2133 | if (! STOP_SET (dest[-1], MAP_DIRSEP))
|
---|
| 2134 | *dest++ = '/';
|
---|
[280] | 2135 |
|
---|
| 2136 | if (dest + len >= apath_limit)
|
---|
| 2137 | return NULL;
|
---|
[3138] | 2138 |
|
---|
[280] | 2139 | dest = memcpy (dest, start, len);
|
---|
| 2140 | dest += len;
|
---|
| 2141 | *dest = '\0';
|
---|
| 2142 | }
|
---|
| 2143 | }
|
---|
| 2144 |
|
---|
| 2145 | /* Unless it is root strip trailing separator. */
|
---|
| 2146 | if (dest > apath + root_len && STOP_SET (dest[-1], MAP_DIRSEP))
|
---|
| 2147 | --dest;
|
---|
| 2148 |
|
---|
| 2149 | *dest = '\0';
|
---|
| 2150 |
|
---|
[900] | 2151 | return apath;
|
---|
| 2152 | }
|
---|
[280] | 2153 |
|
---|
| 2154 |
|
---|
| 2155 | static char *
|
---|
| 2156 | func_realpath (char *o, char **argv, const char *funcname UNUSED)
|
---|
| 2157 | {
|
---|
| 2158 | /* Expand the argument. */
|
---|
| 2159 | const char *p = argv[0];
|
---|
[3138] | 2160 | const char *path = 0;
|
---|
| 2161 | int doneany = 0;
|
---|
| 2162 | unsigned int len = 0;
|
---|
| 2163 |
|
---|
| 2164 | while ((path = find_next_token (&p, &len)) != 0)
|
---|
[280] | 2165 | {
|
---|
| 2166 | if (len < GET_PATH_MAX)
|
---|
| 2167 | {
|
---|
| 2168 | char *rp;
|
---|
[3138] | 2169 | struct stat st;
|
---|
[280] | 2170 | PATH_VAR (in);
|
---|
[3138] | 2171 | PATH_VAR (out);
|
---|
[280] | 2172 |
|
---|
[3138] | 2173 | strncpy (in, path, len);
|
---|
| 2174 | in[len] = '\0';
|
---|
[280] | 2175 |
|
---|
[3138] | 2176 | #ifdef HAVE_REALPATH
|
---|
| 2177 | ENULLLOOP (rp, realpath (in, out));
|
---|
| 2178 | #else
|
---|
| 2179 | rp = abspath (in, out);
|
---|
| 2180 | #endif
|
---|
| 2181 |
|
---|
| 2182 | if (rp)
|
---|
| 2183 | {
|
---|
[280] | 2184 | int r;
|
---|
| 2185 | EINTRLOOP (r, stat (out, &st));
|
---|
| 2186 | if (r == 0)
|
---|
| 2187 | {
|
---|
| 2188 | o = variable_buffer_output (o, out, strlen (out));
|
---|
| 2189 | o = variable_buffer_output (o, " ", 1);
|
---|
| 2190 | doneany = 1;
|
---|
| 2191 | }
|
---|
[900] | 2192 | }
|
---|
[280] | 2193 | }
|
---|
| 2194 | }
|
---|
| 2195 |
|
---|
[3138] | 2196 | /* Kill last space. */
|
---|
| 2197 | if (doneany)
|
---|
| 2198 | --o;
|
---|
| 2199 |
|
---|
| 2200 | return o;
|
---|
| 2201 | }
|
---|
| 2202 |
|
---|
| 2203 | static char *
|
---|
| 2204 | func_file (char *o, char **argv, const char *funcname UNUSED)
|
---|
| 2205 | {
|
---|
| 2206 | char *fn = argv[0];
|
---|
| 2207 |
|
---|
| 2208 | if (fn[0] == '>')
|
---|
| 2209 | {
|
---|
| 2210 | FILE *fp;
|
---|
| 2211 | const char *mode = "w";
|
---|
| 2212 |
|
---|
| 2213 | /* We are writing a file. */
|
---|
| 2214 | ++fn;
|
---|
| 2215 | if (fn[0] == '>')
|
---|
| 2216 | {
|
---|
| 2217 | mode = "a";
|
---|
| 2218 | ++fn;
|
---|
| 2219 | }
|
---|
| 2220 | NEXT_TOKEN (fn);
|
---|
| 2221 |
|
---|
| 2222 | if (fn[0] == '\0')
|
---|
| 2223 | O (fatal, *expanding_var, _("file: missing filename"));
|
---|
| 2224 |
|
---|
| 2225 | ENULLLOOP (fp, fopen (fn, mode));
|
---|
| 2226 | if (fp == NULL)
|
---|
| 2227 | OSS (fatal, reading_file, _("open: %s: %s"), fn, strerror (errno));
|
---|
| 2228 |
|
---|
| 2229 | if (argv[1])
|
---|
| 2230 | {
|
---|
| 2231 | int l = strlen (argv[1]);
|
---|
| 2232 | int nl = l == 0 || argv[1][l-1] != '\n';
|
---|
| 2233 |
|
---|
| 2234 | if (fputs (argv[1], fp) == EOF || (nl && fputc ('\n', fp) == EOF))
|
---|
| 2235 | OSS (fatal, reading_file, _("write: %s: %s"), fn, strerror (errno));
|
---|
| 2236 | }
|
---|
| 2237 | if (fclose (fp))
|
---|
| 2238 | OSS (fatal, reading_file, _("close: %s: %s"), fn, strerror (errno));
|
---|
| 2239 | }
|
---|
| 2240 | else if (fn[0] == '<')
|
---|
| 2241 | {
|
---|
| 2242 | char *preo = o;
|
---|
| 2243 | FILE *fp;
|
---|
| 2244 |
|
---|
| 2245 | ++fn;
|
---|
| 2246 | NEXT_TOKEN (fn);
|
---|
| 2247 | if (fn[0] == '\0')
|
---|
| 2248 | O (fatal, *expanding_var, _("file: missing filename"));
|
---|
| 2249 |
|
---|
| 2250 | if (argv[1])
|
---|
| 2251 | O (fatal, *expanding_var, _("file: too many arguments"));
|
---|
| 2252 |
|
---|
| 2253 | ENULLLOOP (fp, fopen (fn, "r"));
|
---|
| 2254 | if (fp == NULL)
|
---|
| 2255 | {
|
---|
| 2256 | if (errno == ENOENT)
|
---|
| 2257 | return o;
|
---|
| 2258 | OSS (fatal, reading_file, _("open: %s: %s"), fn, strerror (errno));
|
---|
| 2259 | }
|
---|
| 2260 |
|
---|
| 2261 | while (1)
|
---|
| 2262 | {
|
---|
| 2263 | char buf[1024];
|
---|
| 2264 | size_t l = fread (buf, 1, sizeof (buf), fp);
|
---|
| 2265 | if (l > 0)
|
---|
| 2266 | o = variable_buffer_output (o, buf, l);
|
---|
| 2267 |
|
---|
| 2268 | if (ferror (fp))
|
---|
| 2269 | if (errno != EINTR)
|
---|
| 2270 | OSS (fatal, reading_file, _("read: %s: %s"), fn, strerror (errno));
|
---|
| 2271 | if (feof (fp))
|
---|
| 2272 | break;
|
---|
| 2273 | }
|
---|
| 2274 | if (fclose (fp))
|
---|
| 2275 | OSS (fatal, reading_file, _("close: %s: %s"), fn, strerror (errno));
|
---|
| 2276 |
|
---|
| 2277 | /* Remove trailing newline. */
|
---|
| 2278 | if (o > preo && o[-1] == '\n')
|
---|
| 2279 | if (--o > preo && o[-1] == '\r')
|
---|
| 2280 | --o;
|
---|
[280] | 2281 | }
|
---|
| 2282 | else
|
---|
| 2283 | OS (fatal, *expanding_var, _("file: invalid file operation: %s"), fn);
|
---|
[900] | 2284 |
|
---|
| 2285 | return o;
|
---|
[280] | 2286 | }
|
---|
| 2287 |
|
---|
| 2288 | static char *
|
---|
| 2289 | func_abspath (char *o, char **argv, const char *funcname UNUSED)
|
---|
| 2290 | {
|
---|
| 2291 | /* Expand the argument. */
|
---|
| 2292 | const char *p = argv[0];
|
---|
[3138] | 2293 | const char *path = 0;
|
---|
| 2294 | int doneany = 0;
|
---|
| 2295 | unsigned int len = 0;
|
---|
[280] | 2296 |
|
---|
| 2297 | while ((path = find_next_token (&p, &len)) != 0)
|
---|
| 2298 | {
|
---|
| 2299 | if (len < GET_PATH_MAX)
|
---|
| 2300 | {
|
---|
| 2301 | PATH_VAR (in);
|
---|
| 2302 | PATH_VAR (out);
|
---|
| 2303 |
|
---|
| 2304 | strncpy (in, path, len);
|
---|
| 2305 | in[len] = '\0';
|
---|
| 2306 |
|
---|
| 2307 | if (abspath (in, out))
|
---|
| 2308 | {
|
---|
| 2309 | o = variable_buffer_output (o, out, strlen (out));
|
---|
| 2310 | o = variable_buffer_output (o, " ", 1);
|
---|
| 2311 | doneany = 1;
|
---|
[900] | 2312 | }
|
---|
[280] | 2313 | }
|
---|
| 2314 | }
|
---|
[53] | 2315 |
|
---|
| 2316 | /* Kill last space. */
|
---|
| 2317 | if (doneany)
|
---|
| 2318 | --o;
|
---|
| 2319 |
|
---|
| 2320 | return o;
|
---|
| 2321 | }
|
---|
| 2322 |
|
---|
| 2323 | /* Lookup table for builtin functions.
|
---|
| 2324 |
|
---|
| 2325 | This doesn't have to be sorted; we use a straight lookup. We might gain
|
---|
| 2326 | some efficiency by moving most often used functions to the start of the
|
---|
[900] | 2327 | table.
|
---|
[53] | 2328 |
|
---|
[3138] | 2329 | If MAXIMUM_ARGS is 0, that means there is no maximum and all
|
---|
| 2330 | comma-separated values are treated as arguments.
|
---|
[53] | 2331 |
|
---|
| 2332 | EXPAND_ARGS means that all arguments should be expanded before invocation.
|
---|
| 2333 | Functions that do namespace tricks (foreach) don't automatically expand. */
|
---|
[3138] | 2334 |
|
---|
| 2335 | static char *func_call (char *o, char **argv, const char *funcname);
|
---|
| 2336 |
|
---|
| 2337 | #define FT_ENTRY(_name, _min, _max, _exp, _func) \
|
---|
| 2338 | { { (_func) }, STRING_SIZE_TUPLE(_name), (_min), (_max), (_exp), 0 }
|
---|
| 2339 |
|
---|
| 2340 | static struct function_table_entry function_table_init[] =
|
---|
| 2341 | {
|
---|
| 2342 | /* Name MIN MAX EXP? Function */
|
---|
| 2343 | FT_ENTRY ("abspath", 0, 1, 1, func_abspath),
|
---|
| 2344 | FT_ENTRY ("addprefix", 2, 2, 1, func_addsuffix_addprefix),
|
---|
| 2345 | FT_ENTRY ("addsuffix", 2, 2, 1, func_addsuffix_addprefix),
|
---|
| 2346 | FT_ENTRY ("basename", 0, 1, 1, func_basename_dir),
|
---|
| 2347 | FT_ENTRY ("dir", 0, 1, 1, func_basename_dir),
|
---|
| 2348 | FT_ENTRY ("notdir", 0, 1, 1, func_notdir_suffix),
|
---|
| 2349 | FT_ENTRY ("subst", 3, 3, 1, func_subst),
|
---|
| 2350 | FT_ENTRY ("suffix", 0, 1, 1, func_notdir_suffix),
|
---|
| 2351 | FT_ENTRY ("filter", 2, 2, 1, func_filter_filterout),
|
---|
| 2352 | FT_ENTRY ("filter-out", 2, 2, 1, func_filter_filterout),
|
---|
| 2353 | FT_ENTRY ("findstring", 2, 2, 1, func_findstring),
|
---|
| 2354 | FT_ENTRY ("firstword", 0, 1, 1, func_firstword),
|
---|
| 2355 | FT_ENTRY ("flavor", 0, 1, 1, func_flavor),
|
---|
| 2356 | FT_ENTRY ("join", 2, 2, 1, func_join),
|
---|
| 2357 | FT_ENTRY ("lastword", 0, 1, 1, func_lastword),
|
---|
| 2358 | FT_ENTRY ("patsubst", 3, 3, 1, func_patsubst),
|
---|
| 2359 | FT_ENTRY ("realpath", 0, 1, 1, func_realpath),
|
---|
| 2360 | FT_ENTRY ("shell", 0, 1, 1, func_shell),
|
---|
| 2361 | FT_ENTRY ("sort", 0, 1, 1, func_sort),
|
---|
| 2362 | FT_ENTRY ("strip", 0, 1, 1, func_strip),
|
---|
| 2363 | FT_ENTRY ("wildcard", 0, 1, 1, func_wildcard),
|
---|
| 2364 | FT_ENTRY ("word", 2, 2, 1, func_word),
|
---|
| 2365 | FT_ENTRY ("wordlist", 3, 3, 1, func_wordlist),
|
---|
| 2366 | FT_ENTRY ("words", 0, 1, 1, func_words),
|
---|
| 2367 | FT_ENTRY ("origin", 0, 1, 1, func_origin),
|
---|
| 2368 | FT_ENTRY ("foreach", 3, 3, 0, func_foreach),
|
---|
| 2369 | FT_ENTRY ("call", 1, 0, 1, func_call),
|
---|
| 2370 | FT_ENTRY ("info", 0, 1, 1, func_error),
|
---|
[53] | 2371 | FT_ENTRY ("error", 0, 1, 1, func_error),
|
---|
[3138] | 2372 | FT_ENTRY ("warning", 0, 1, 1, func_error),
|
---|
| 2373 | FT_ENTRY ("if", 2, 3, 0, func_if),
|
---|
[53] | 2374 | FT_ENTRY ("or", 1, 0, 0, func_or),
|
---|
| 2375 | FT_ENTRY ("and", 1, 0, 0, func_and),
|
---|
| 2376 | FT_ENTRY ("value", 0, 1, 1, func_value),
|
---|
| 2377 | FT_ENTRY ("eval", 0, 1, 1, func_eval),
|
---|
| 2378 | FT_ENTRY ("file", 1, 2, 1, func_file),
|
---|
| 2379 | #ifdef EXPERIMENTAL
|
---|
| 2380 | FT_ENTRY ("eq", 2, 2, 1, func_eq),
|
---|
| 2381 | FT_ENTRY ("not", 0, 1, 1, func_not),
|
---|
| 2382 | #endif
|
---|
| 2383 | };
|
---|
| 2384 |
|
---|
| 2385 | #define FUNCTION_TABLE_ENTRIES (sizeof (function_table_init) / sizeof (struct function_table_entry))
|
---|
[3138] | 2386 | |
---|
| 2387 |
|
---|
[53] | 2388 |
|
---|
[3138] | 2389 | /* These must come after the definition of function_table. */
|
---|
| 2390 |
|
---|
[53] | 2391 | static char *
|
---|
| 2392 | expand_builtin_function (char *o, int argc, char **argv,
|
---|
[3138] | 2393 | const struct function_table_entry *entry_p)
|
---|
| 2394 | {
|
---|
[53] | 2395 | char *p;
|
---|
| 2396 |
|
---|
[3138] | 2397 | if (argc < (int)entry_p->minimum_args)
|
---|
[53] | 2398 | fatal (*expanding_var, strlen (entry_p->name),
|
---|
| 2399 | _("insufficient number of arguments (%d) to function '%s'"),
|
---|
[3138] | 2400 | argc, entry_p->name);
|
---|
| 2401 |
|
---|
| 2402 | /* I suppose technically some function could do something with no arguments,
|
---|
[53] | 2403 | but so far no internal ones do, so just test it for all functions here
|
---|
[3138] | 2404 | rather than in each one. We can change it later if necessary. */
|
---|
| 2405 |
|
---|
| 2406 | if (!argc && !entry_p->alloc_fn)
|
---|
| 2407 | return o;
|
---|
| 2408 |
|
---|
| 2409 | if (!entry_p->fptr.func_ptr)
|
---|
| 2410 | OS (fatal, *expanding_var,
|
---|
| 2411 | _("unimplemented on this platform: function '%s'"), entry_p->name);
|
---|
| 2412 |
|
---|
| 2413 | if (!entry_p->alloc_fn)
|
---|
| 2414 | return entry_p->fptr.func_ptr (o, argv, entry_p->name);
|
---|
| 2415 |
|
---|
| 2416 | /* This function allocates memory and returns it to us.
|
---|
| 2417 | Write it to the variable buffer, then free it. */
|
---|
[53] | 2418 |
|
---|
| 2419 | p = entry_p->fptr.alloc_func_ptr (entry_p->name, argc, argv);
|
---|
| 2420 | if (p)
|
---|
| 2421 | {
|
---|
| 2422 | o = variable_buffer_output (o, p, strlen (p));
|
---|
| 2423 | free (p);
|
---|
| 2424 | }
|
---|
| 2425 |
|
---|
[900] | 2426 | return o;
|
---|
[53] | 2427 | }
|
---|
| 2428 |
|
---|
| 2429 | /* Check for a function invocation in *STRINGP. *STRINGP points at the
|
---|
| 2430 | opening ( or { and is not null-terminated. If a function invocation
|
---|
[900] | 2431 | is found, expand it into the buffer at *OP, updating *OP, incrementing
|
---|
| 2432 | *STRINGP past the reference and returning nonzero. If not, return zero. */
|
---|
[53] | 2433 |
|
---|
[900] | 2434 | int
|
---|
[53] | 2435 | handle_function (char **op, const char **stringp)
|
---|
| 2436 | {
|
---|
| 2437 | const struct function_table_entry *entry_p;
|
---|
| 2438 | char openparen = (*stringp)[0];
|
---|
| 2439 | char closeparen = openparen == '(' ? ')' : '}';
|
---|
| 2440 | const char *beg;
|
---|
| 2441 | const char *end;
|
---|
| 2442 | int count = 0;
|
---|
| 2443 | char *abeg = NULL;
|
---|
| 2444 | char **argv, **argvp;
|
---|
| 2445 | int nargs;
|
---|
| 2446 |
|
---|
| 2447 | beg = *stringp + 1;
|
---|
[3138] | 2448 |
|
---|
| 2449 | entry_p = lookup_function (beg);
|
---|
[53] | 2450 |
|
---|
| 2451 | if (!entry_p)
|
---|
| 2452 | return 0;
|
---|
| 2453 |
|
---|
| 2454 | /* We found a builtin function. Find the beginning of its arguments (skip
|
---|
| 2455 | whitespace after the name). */
|
---|
| 2456 |
|
---|
| 2457 | beg += entry_p->len;
|
---|
| 2458 | NEXT_TOKEN (beg);
|
---|
| 2459 |
|
---|
| 2460 | /* Find the end of the function invocation, counting nested use of
|
---|
| 2461 | whichever kind of parens we use. Since we're looking, count commas
|
---|
| 2462 | to get a rough estimate of how many arguments we might have. The
|
---|
| 2463 | count might be high, but it'll never be low. */
|
---|
| 2464 |
|
---|
[3138] | 2465 | for (nargs=1, end=beg; *end != '\0'; ++end)
|
---|
| 2466 | if (*end == ',')
|
---|
| 2467 | ++nargs;
|
---|
[53] | 2468 | else if (*end == openparen)
|
---|
| 2469 | ++count;
|
---|
| 2470 | else if (*end == closeparen && --count < 0)
|
---|
| 2471 | break;
|
---|
[900] | 2472 |
|
---|
[53] | 2473 | if (count >= 0)
|
---|
| 2474 | fatal (*expanding_var, strlen (entry_p->name),
|
---|
| 2475 | _("unterminated call to function '%s': missing '%c'"),
|
---|
| 2476 | entry_p->name, closeparen);
|
---|
| 2477 |
|
---|
| 2478 | *stringp = end;
|
---|
| 2479 |
|
---|
| 2480 | /* Get some memory to store the arg pointers. */
|
---|
| 2481 | argvp = argv = alloca (sizeof (char *) * (nargs + 2));
|
---|
[900] | 2482 |
|
---|
[53] | 2483 | /* Chop the string into arguments, then a nul. As soon as we hit
|
---|
[900] | 2484 | MAXIMUM_ARGS (if it's >0) assume the rest of the string is part of the
|
---|
| 2485 | last argument.
|
---|
| 2486 |
|
---|
| 2487 | If we're expanding, store pointers to the expansion of each one. If
|
---|
[53] | 2488 | not, make a duplicate of the string and point into that, nul-terminating
|
---|
[900] | 2489 | each argument. */
|
---|
| 2490 |
|
---|
| 2491 | if (entry_p->expand_args)
|
---|
| 2492 | {
|
---|
| 2493 | const char *p;
|
---|
| 2494 | for (p=beg, nargs=0; p <= end; ++argvp)
|
---|
| 2495 | {
|
---|
| 2496 | const char *next;
|
---|
| 2497 |
|
---|
[53] | 2498 | ++nargs;
|
---|
[900] | 2499 |
|
---|
[53] | 2500 | if (nargs == entry_p->maximum_args
|
---|
[900] | 2501 | || (! (next = find_next_argument (openparen, closeparen, p, end))))
|
---|
| 2502 | next = end;
|
---|
[53] | 2503 |
|
---|
[900] | 2504 | *argvp = expand_argument (p, next);
|
---|
| 2505 | p = next + 1;
|
---|
| 2506 | }
|
---|
| 2507 | }
|
---|
[53] | 2508 | else
|
---|
[900] | 2509 | {
|
---|
| 2510 | int len = end - beg;
|
---|
| 2511 | char *p, *aend;
|
---|
[53] | 2512 |
|
---|
[900] | 2513 | abeg = xmalloc (len+1);
|
---|
| 2514 | memcpy (abeg, beg, len);
|
---|
| 2515 | abeg[len] = '\0';
|
---|
| 2516 | aend = abeg + len;
|
---|
| 2517 |
|
---|
| 2518 | for (p=abeg, nargs=0; p <= aend; ++argvp)
|
---|
[53] | 2519 | {
|
---|
| 2520 | char *next;
|
---|
[900] | 2521 |
|
---|
[53] | 2522 | ++nargs;
|
---|
| 2523 |
|
---|
| 2524 | if (nargs == entry_p->maximum_args
|
---|
| 2525 | || (! (next = find_next_argument (openparen, closeparen, p, aend))))
|
---|
| 2526 | next = aend;
|
---|
| 2527 |
|
---|
| 2528 | *argvp = p;
|
---|
| 2529 | *next = '\0';
|
---|
| 2530 | p = next + 1;
|
---|
| 2531 | }
|
---|
| 2532 | }
|
---|
[3138] | 2533 | *argvp = NULL;
|
---|
[900] | 2534 |
|
---|
[53] | 2535 | /* Finally! Run the function... */
|
---|
| 2536 | *op = expand_builtin_function (*op, nargs, argv, entry_p);
|
---|
| 2537 |
|
---|
| 2538 | /* Free memory. */
|
---|
| 2539 | if (entry_p->expand_args)
|
---|
| 2540 | for (argvp=argv; *argvp != 0; ++argvp)
|
---|
| 2541 | free (*argvp);
|
---|
| 2542 | else
|
---|
| 2543 | free (abeg);
|
---|
| 2544 |
|
---|
[153] | 2545 | return 1;
|
---|
[53] | 2546 | }
|
---|
| 2547 | |
---|
| 2548 |
|
---|
| 2549 |
|
---|
| 2550 | /* User-defined functions. Expand the first argument as either a builtin
|
---|
| 2551 | function or a make variable, in the context of the rest of the arguments
|
---|
| 2552 | assigned to $1, $2, ... $N. $0 is the name of the function. */
|
---|
| 2553 |
|
---|
| 2554 | static char *
|
---|
| 2555 | func_call (char *o, char **argv, const char *funcname UNUSED)
|
---|
[3138] | 2556 | {
|
---|
| 2557 | static int max_args = 0;
|
---|
| 2558 | char *fname;
|
---|
[53] | 2559 | char *body;
|
---|
| 2560 | int flen;
|
---|
| 2561 | int i;
|
---|
| 2562 | int saved_args;
|
---|
| 2563 | const struct function_table_entry *entry_p;
|
---|
| 2564 | struct variable *v;
|
---|
| 2565 |
|
---|
| 2566 | /* Clean up the name of the variable to be invoked. */
|
---|
| 2567 | fname = next_token (argv[0]);
|
---|
| 2568 | end_of_token (fname)[0] = '\0';
|
---|
| 2569 |
|
---|
| 2570 | /* Calling nothing is a no-op */
|
---|
[900] | 2571 | if (*fname == '\0')
|
---|
[53] | 2572 | return o;
|
---|
| 2573 |
|
---|
| 2574 | /* Are we invoking a builtin function? */
|
---|
| 2575 |
|
---|
| 2576 | entry_p = lookup_function (fname);
|
---|
| 2577 | if (entry_p)
|
---|
| 2578 | {
|
---|
| 2579 | /* How many arguments do we have? */
|
---|
| 2580 | for (i=0; argv[i+1]; ++i)
|
---|
| 2581 | ;
|
---|
| 2582 | return expand_builtin_function (o, i, argv+1, entry_p);
|
---|
| 2583 | }
|
---|
| 2584 |
|
---|
| 2585 | /* Not a builtin, so the first argument is the name of a variable to be
|
---|
| 2586 | expanded and interpreted as a function. Find it. */
|
---|
[900] | 2587 | flen = strlen (fname);
|
---|
[53] | 2588 |
|
---|
| 2589 | v = lookup_variable (fname, flen);
|
---|
| 2590 |
|
---|
| 2591 | if (v == 0)
|
---|
| 2592 | warn_undefined (fname, flen);
|
---|
| 2593 |
|
---|
| 2594 | if (v == 0 || *v->value == '\0')
|
---|
| 2595 | return o;
|
---|
| 2596 |
|
---|
| 2597 | body = alloca (flen + 4);
|
---|
| 2598 | body[0] = '$';
|
---|
| 2599 | body[1] = '(';
|
---|
| 2600 | memcpy (body + 2, fname, flen);
|
---|
| 2601 | body[flen+2] = ')';
|
---|
| 2602 | body[flen+3] = '\0';
|
---|
| 2603 |
|
---|
| 2604 | /* Set up arguments $(1) .. $(N). $(0) is the function name. */
|
---|
| 2605 |
|
---|
| 2606 | push_new_variable_scope ();
|
---|
| 2607 |
|
---|
| 2608 | for (i=0; *argv; ++i, ++argv)
|
---|
| 2609 | {
|
---|
| 2610 | char num[11];
|
---|
| 2611 |
|
---|
| 2612 | sprintf (num, "%d", i);
|
---|
| 2613 | define_variable (num, strlen (num), *argv, o_automatic, 0);
|
---|
| 2614 | }
|
---|
| 2615 |
|
---|
| 2616 | /* If the number of arguments we have is < max_args, it means we're inside
|
---|
| 2617 | a recursive invocation of $(call ...). Fill in the remaining arguments
|
---|
| 2618 | in the new scope with the empty value, to hide them from this
|
---|
| 2619 | invocation. */
|
---|
| 2620 |
|
---|
| 2621 | for (; i < max_args; ++i)
|
---|
| 2622 | {
|
---|
| 2623 | char num[11];
|
---|
| 2624 |
|
---|
| 2625 | sprintf (num, "%d", i);
|
---|
| 2626 | define_variable (num, strlen (num), "", o_automatic, 0);
|
---|
| 2627 | }
|
---|
| 2628 |
|
---|
| 2629 | /* Expand the body in the context of the arguments, adding the result to
|
---|
| 2630 | the variable buffer. */
|
---|
| 2631 |
|
---|
| 2632 | v->exp_count = EXP_COUNT_MAX;
|
---|
| 2633 |
|
---|
| 2634 | saved_args = max_args;
|
---|
| 2635 | max_args = i;
|
---|
| 2636 | o = variable_expand_string (o, body, flen+3);
|
---|
[3138] | 2637 | max_args = saved_args;
|
---|
| 2638 |
|
---|
| 2639 | v->exp_count = 0;
|
---|
| 2640 |
|
---|
| 2641 | pop_variable_scope ();
|
---|
| 2642 |
|
---|
| 2643 | return o + strlen (o);
|
---|
| 2644 | }
|
---|
| 2645 |
|
---|
| 2646 | void
|
---|
| 2647 | define_new_function (const floc *flocp, const char *name,
|
---|
| 2648 | unsigned int min, unsigned int max, unsigned int flags,
|
---|
| 2649 | gmk_func_ptr func)
|
---|
| 2650 | {
|
---|
| 2651 | const char *e = name;
|
---|
| 2652 | struct function_table_entry *ent;
|
---|
| 2653 | size_t len;
|
---|
| 2654 |
|
---|
| 2655 | while (STOP_SET (*e, MAP_USERFUNC))
|
---|
| 2656 | e++;
|
---|
| 2657 | len = e - name;
|
---|
| 2658 |
|
---|
| 2659 | if (len == 0)
|
---|
| 2660 | O (fatal, flocp, _("Empty function name"));
|
---|
| 2661 | if (*name == '.' || *e != '\0')
|
---|
| 2662 | OS (fatal, flocp, _("Invalid function name: %s"), name);
|
---|
| 2663 | if (len > 255)
|
---|
| 2664 | OS (fatal, flocp, _("Function name too long: %s"), name);
|
---|
| 2665 | if (min > 255)
|
---|
| 2666 | ONS (fatal, flocp,
|
---|
| 2667 | _("Invalid minimum argument count (%u) for function %s"), min, name);
|
---|
| 2668 | if (max > 255 || (max && max < min))
|
---|
| 2669 | ONS (fatal, flocp,
|
---|
| 2670 | _("Invalid maximum argument count (%u) for function %s"), max, name);
|
---|
| 2671 |
|
---|
| 2672 | ent = xmalloc (sizeof (struct function_table_entry));
|
---|
| 2673 | ent->name = name;
|
---|
| 2674 | ent->len = len;
|
---|
[53] | 2675 | ent->minimum_args = min;
|
---|
| 2676 | ent->maximum_args = max;
|
---|
| 2677 | ent->expand_args = ANY_SET(flags, GMK_FUNC_NOEXPAND) ? 0 : 1;
|
---|
[3138] | 2678 | ent->alloc_fn = 1;
|
---|
| 2679 | ent->fptr.alloc_func_ptr = func;
|
---|
[53] | 2680 |
|
---|
[3138] | 2681 | hash_insert (&function_table, ent);
|
---|
[53] | 2682 | }
|
---|
| 2683 |
|
---|
| 2684 | void
|
---|
| 2685 | hash_init_function_table (void)
|
---|
| 2686 | {
|
---|
| 2687 | hash_init (&function_table, FUNCTION_TABLE_ENTRIES * 2,
|
---|
| 2688 | function_table_entry_hash_1, function_table_entry_hash_2,
|
---|
| 2689 | function_table_entry_hash_cmp);
|
---|
| 2690 | hash_load (&function_table, function_table_init,
|
---|
| 2691 | FUNCTION_TABLE_ENTRIES, sizeof (struct function_table_entry));
|
---|
| 2692 | }
|
---|