VirtualBox

source: kBuild/trunk/src/kmk/function.c@ 3548

Last change on this file since 3548 was 3545, checked in by bird, 3 years ago

kmk: Use 'error' instead of 'message' for reporting attempts and quoting empty strings so we get the caller location. (probably thought error implied kmk would eventually exit with non-zero status code)

  • Property svn:eol-style set to native
File size: 232.2 KB
Line 
1/* Builtin function expansion for GNU Make.
2Copyright (C) 1988-2016 Free Software Foundation, Inc.
3This file is part of GNU Make.
4
5GNU Make is free software; you can redistribute it and/or modify it under the
6terms of the GNU General Public License as published by the Free Software
7Foundation; either version 3 of the License, or (at your option) any later
8version.
9
10GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
11WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License along with
15this program. If not, see <http://www.gnu.org/licenses/>. */
16
17#include "makeint.h"
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#ifdef WINDOWS32 /* bird */
30# include "pathstuff.h"
31# ifdef CONFIG_NEW_WIN_CHILDREN
32# include "w32/winchildren.h"
33# endif
34#endif
35
36#ifdef KMK_HELPERS
37# include "kbuild.h"
38#endif
39#ifdef CONFIG_WITH_PRINTF
40# include "kmkbuiltin.h"
41#endif
42#ifdef CONFIG_WITH_XARGS /* bird */
43# ifdef HAVE_LIMITS_H
44# include <limits.h>
45# endif
46#endif
47#ifdef CONFIG_WITH_COMPILER
48# include "kmk_cc_exec.h"
49#endif
50#include <assert.h> /* bird */
51
52#if defined (CONFIG_WITH_MATH) || defined (CONFIG_WITH_NANOTS) || defined (CONFIG_WITH_FILE_SIZE) /* bird */
53# include <ctype.h>
54typedef big_int math_int;
55static char *math_int_to_variable_buffer (char *, math_int);
56static math_int math_int_from_string (const char *str);
57#endif
58
59#ifdef CONFIG_WITH_NANOTS /* bird */
60# ifdef WINDOWS32
61# include <Windows.h>
62# endif
63#endif
64
65#ifdef __OS2__
66# define CONFIG_WITH_OS2_LIBPATH 1
67#endif
68#ifdef CONFIG_WITH_OS2_LIBPATH
69# define INCL_BASE
70# define INCL_ERRROS
71# include <os2.h>
72
73# define QHINF_EXEINFO 1 /* NE exeinfo. */
74# define QHINF_READRSRCTBL 2 /* Reads from the resource table. */
75# define QHINF_READFILE 3 /* Reads from the executable file. */
76# define QHINF_LIBPATHLENGTH 4 /* Gets the libpath length. */
77# define QHINF_LIBPATH 5 /* Gets the entire libpath. */
78# define QHINF_FIXENTRY 6 /* NE only */
79# define QHINF_STE 7 /* NE only */
80# define QHINF_MAPSEL 8 /* NE only */
81 extern APIRET APIENTRY DosQueryHeaderInfo(HMODULE hmod, ULONG ulIndex, PVOID pvBuffer, ULONG cbBuffer, ULONG ulSubFunction);
82#endif /* CONFIG_WITH_OS2_LIBPATH */
83
84#ifdef KMK
85/** Checks if the @a_cch characters (bytes) in @a a_psz equals @a a_szConst. */
86# define STR_N_EQUALS(a_psz, a_cch, a_szConst) \
87 ( (a_cch) == sizeof (a_szConst) - 1 && !strncmp ((a_psz), (a_szConst), sizeof (a_szConst) - 1) )
88
89# ifdef _MSC_VER
90# include "kmkbuiltin/mscfakes.h"
91# endif
92# include "version_compare.h"
93#endif
94
95
96struct function_table_entry
97 {
98 union {
99 char *(*func_ptr) (char *output, char **argv, const char *fname);
100 gmk_func_ptr alloc_func_ptr;
101 } fptr;
102 const char *name;
103 unsigned char len;
104 unsigned char minimum_args;
105 unsigned char maximum_args;
106 unsigned char expand_args:1;
107 unsigned char alloc_fn:1;
108 };
109
110static unsigned long
111function_table_entry_hash_1 (const void *keyv)
112{
113 const struct function_table_entry *key = keyv;
114 return_STRING_N_HASH_1 (key->name, key->len);
115}
116
117static unsigned long
118function_table_entry_hash_2 (const void *keyv)
119{
120 const struct function_table_entry *key = keyv;
121 return_STRING_N_HASH_2 (key->name, key->len);
122}
123
124static int
125function_table_entry_hash_cmp (const void *xv, const void *yv)
126{
127 const struct function_table_entry *x = xv;
128 const struct function_table_entry *y = yv;
129 int result = x->len - y->len;
130 if (result)
131 return result;
132 return_STRING_N_COMPARE (x->name, y->name, x->len);
133}
134
135static struct hash_table function_table;
136
137#ifdef CONFIG_WITH_MAKE_STATS
138long make_stats_allocations = 0;
139long make_stats_reallocations = 0;
140unsigned long make_stats_allocated = 0;
141unsigned long make_stats_ht_lookups = 0;
142unsigned long make_stats_ht_collisions = 0;
143#endif
144
145
146
147/* Store into VARIABLE_BUFFER at O the result of scanning TEXT and replacing
148 each occurrence of SUBST with REPLACE. TEXT is null-terminated. SLEN is
149 the length of SUBST and RLEN is the length of REPLACE. If BY_WORD is
150 nonzero, substitutions are done only on matches which are complete
151 whitespace-delimited words. */
152
153char *
154subst_expand (char *o, const char *text, const char *subst, const char *replace,
155 unsigned int slen, unsigned int rlen, int by_word)
156{
157 const char *t = text;
158 const char *p;
159
160 if (slen == 0 && !by_word)
161 {
162 /* The first occurrence of "" in any string is its end. */
163 o = variable_buffer_output (o, t, strlen (t));
164 if (rlen > 0)
165 o = variable_buffer_output (o, replace, rlen);
166 return o;
167 }
168
169 do
170 {
171 if (by_word && slen == 0)
172 /* When matching by words, the empty string should match
173 the end of each word, rather than the end of the whole text. */
174 p = end_of_token (next_token (t));
175 else
176 {
177 p = strstr (t, subst);
178 if (p == 0)
179 {
180 /* No more matches. Output everything left on the end. */
181 o = variable_buffer_output (o, t, strlen (t));
182 return o;
183 }
184 }
185
186 /* Output everything before this occurrence of the string to replace. */
187 if (p > t)
188 o = variable_buffer_output (o, t, p - t);
189
190 /* If we're substituting only by fully matched words,
191 or only at the ends of words, check that this case qualifies. */
192 if (by_word
193 && ((p > text && !ISSPACE (p[-1]))
194 || ! STOP_SET (p[slen], MAP_SPACE|MAP_NUL)))
195 /* Struck out. Output the rest of the string that is
196 no longer to be replaced. */
197 o = variable_buffer_output (o, subst, slen);
198 else if (rlen > 0)
199 /* Output the replacement string. */
200 o = variable_buffer_output (o, replace, rlen);
201
202 /* Advance T past the string to be replaced. */
203 t = p + slen;
204 } while (*t != '\0');
205
206 return o;
207}
208
209
210
211/* Store into VARIABLE_BUFFER at O the result of scanning TEXT
212 and replacing strings matching PATTERN with REPLACE.
213 If PATTERN_PERCENT is not nil, PATTERN has already been
214 run through find_percent, and PATTERN_PERCENT is the result.
215 If REPLACE_PERCENT is not nil, REPLACE has already been
216 run through find_percent, and REPLACE_PERCENT is the result.
217 Note that we expect PATTERN_PERCENT and REPLACE_PERCENT to point to the
218 character _AFTER_ the %, not to the % itself.
219*/
220
221char *
222patsubst_expand_pat (char *o, const char *text,
223 const char *pattern, const char *replace,
224 const char *pattern_percent, const char *replace_percent)
225{
226 unsigned int pattern_prepercent_len, pattern_postpercent_len;
227 unsigned int replace_prepercent_len, replace_postpercent_len;
228 const char *t;
229 unsigned int len;
230 int doneany = 0;
231
232 /* Record the length of REPLACE before and after the % so we don't have to
233 compute these lengths more than once. */
234 if (replace_percent)
235 {
236 replace_prepercent_len = replace_percent - replace - 1;
237 replace_postpercent_len = strlen (replace_percent);
238 }
239 else
240 {
241 replace_prepercent_len = strlen (replace);
242 replace_postpercent_len = 0;
243 }
244
245 if (!pattern_percent)
246 /* With no % in the pattern, this is just a simple substitution. */
247 return subst_expand (o, text, pattern, replace,
248 strlen (pattern), strlen (replace), 1);
249
250 /* Record the length of PATTERN before and after the %
251 so we don't have to compute it more than once. */
252 pattern_prepercent_len = pattern_percent - pattern - 1;
253 pattern_postpercent_len = strlen (pattern_percent);
254
255 while ((t = find_next_token (&text, &len)) != 0)
256 {
257 int fail = 0;
258
259 /* Is it big enough to match? */
260 if (len < pattern_prepercent_len + pattern_postpercent_len)
261 fail = 1;
262
263 /* Does the prefix match? */
264 if (!fail && pattern_prepercent_len > 0
265 && (*t != *pattern
266 || t[pattern_prepercent_len - 1] != pattern_percent[-2]
267 || !strneq (t + 1, pattern + 1, pattern_prepercent_len - 1)))
268 fail = 1;
269
270 /* Does the suffix match? */
271 if (!fail && pattern_postpercent_len > 0
272 && (t[len - 1] != pattern_percent[pattern_postpercent_len - 1]
273 || t[len - pattern_postpercent_len] != *pattern_percent
274 || !strneq (&t[len - pattern_postpercent_len],
275 pattern_percent, pattern_postpercent_len - 1)))
276 fail = 1;
277
278 if (fail)
279 /* It didn't match. Output the string. */
280 o = variable_buffer_output (o, t, len);
281 else
282 {
283 /* It matched. Output the replacement. */
284
285 /* Output the part of the replacement before the %. */
286 o = variable_buffer_output (o, replace, replace_prepercent_len);
287
288 if (replace_percent != 0)
289 {
290 /* Output the part of the matched string that
291 matched the % in the pattern. */
292 o = variable_buffer_output (o, t + pattern_prepercent_len,
293 len - (pattern_prepercent_len
294 + pattern_postpercent_len));
295 /* Output the part of the replacement after the %. */
296 o = variable_buffer_output (o, replace_percent,
297 replace_postpercent_len);
298 }
299 }
300
301 /* Output a space, but not if the replacement is "". */
302 if (fail || replace_prepercent_len > 0
303 || (replace_percent != 0 && len + replace_postpercent_len > 0))
304 {
305 o = variable_buffer_output (o, " ", 1);
306 doneany = 1;
307 }
308 }
309#ifndef CONFIG_WITH_VALUE_LENGTH
310 if (doneany)
311 /* Kill the last space. */
312 --o;
313#else
314 /* Kill the last space and make sure there is a terminator there
315 so that strcache_add_len doesn't have to do a lot of exacty work
316 when expand_deps sends the output its way. */
317 if (doneany)
318 *--o = '\0';
319 else
320 o = variable_buffer_output (o, "\0", 1) - 1;
321#endif
322
323 return o;
324}
325
326/* Store into VARIABLE_BUFFER at O the result of scanning TEXT
327 and replacing strings matching PATTERN with REPLACE.
328 If PATTERN_PERCENT is not nil, PATTERN has already been
329 run through find_percent, and PATTERN_PERCENT is the result.
330 If REPLACE_PERCENT is not nil, REPLACE has already been
331 run through find_percent, and REPLACE_PERCENT is the result.
332 Note that we expect PATTERN_PERCENT and REPLACE_PERCENT to point to the
333 character _AFTER_ the %, not to the % itself.
334*/
335
336char *
337patsubst_expand (char *o, const char *text, char *pattern, char *replace)
338{
339 const char *pattern_percent = find_percent (pattern);
340 const char *replace_percent = find_percent (replace);
341
342 /* If there's a percent in the pattern or replacement skip it. */
343 if (replace_percent)
344 ++replace_percent;
345 if (pattern_percent)
346 ++pattern_percent;
347
348 return patsubst_expand_pat (o, text, pattern, replace,
349 pattern_percent, replace_percent);
350}
351
352
353#if defined (CONFIG_WITH_OPTIMIZATION_HACKS) || defined (CONFIG_WITH_VALUE_LENGTH)
354
355/* Char map containing the valid function name characters. */
356char func_char_map[256];
357
358/* Do the hash table lookup. */
359
360MY_INLINE const struct function_table_entry *
361lookup_function_in_hash_tab (const char *s, unsigned char len)
362{
363 struct function_table_entry function_table_entry_key;
364 function_table_entry_key.name = s;
365 function_table_entry_key.len = len;
366
367 return hash_find_item (&function_table, &function_table_entry_key);
368}
369
370/* Look up a function by name. */
371
372MY_INLINE const struct function_table_entry *
373lookup_function (const char *s, unsigned int len)
374{
375 unsigned char ch;
376# if 0 /* insane loop unroll */
377
378 if (len > MAX_FUNCTION_LENGTH)
379 len = MAX_FUNCTION_LENGTH + 1;
380
381# define X(idx) \
382 if (!func_char_map[ch = s[idx]]) \
383 { \
384 if (ISBLANK (ch)) \
385 return lookup_function_in_hash_tab (s, idx); \
386 return 0; \
387 }
388# define Z(idx) \
389 return lookup_function_in_hash_tab (s, idx);
390
391 switch (len)
392 {
393 default:
394 assert (0);
395 case 0: return 0;
396 case 1: return 0;
397 case 2: X(0); X(1); Z(2);
398 case 3: X(0); X(1); X(2); Z(3);
399 case 4: X(0); X(1); X(2); X(3); Z(4);
400 case 5: X(0); X(1); X(2); X(3); X(4); Z(5);
401 case 6: X(0); X(1); X(2); X(3); X(4); X(5); Z(6);
402 case 7: X(0); X(1); X(2); X(3); X(4); X(5); X(6); Z(7);
403 case 8: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); Z(8);
404 case 9: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); X(8); Z(9);
405 case 10: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); X(8); X(9); Z(10);
406 case 11: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); X(8); X(9); X(10); Z(11);
407 case 12: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); X(8); X(9); X(10); X(11); Z(12);
408 case 13: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); X(8); X(9); X(10); X(11); X(12);
409 if ((ch = s[12]) == '\0' || ISBLANK (ch))
410 return lookup_function_in_hash_tab (s, 12);
411 return 0;
412 }
413# undef Z
414# undef X
415
416# else /* normal loop */
417 const char *e = s;
418 if (len > MAX_FUNCTION_LENGTH)
419 len = MAX_FUNCTION_LENGTH;
420 while (func_char_map[ch = *e])
421 {
422 if (!len--)
423 return 0;
424 e++;
425 }
426 if (ch == '\0' || ISBLANK (ch))
427 return lookup_function_in_hash_tab (s, e - s);
428 return 0;
429# endif /* normal loop */
430}
431
432#else /* original code */
433/* Look up a function by name. */
434
435static const struct function_table_entry *
436lookup_function (const char *s)
437{
438 struct function_table_entry function_table_entry_key;
439 const char *e = s;
440 while (STOP_SET (*e, MAP_USERFUNC))
441 e++;
442
443 if (e == s || !STOP_SET(*e, MAP_NUL|MAP_SPACE))
444 return NULL;
445
446 function_table_entry_key.name = s;
447 function_table_entry_key.len = e - s;
448
449 return hash_find_item (&function_table, &function_table_entry_key);
450}
451#endif /* original code */
452
453
454
455/* Return 1 if PATTERN matches STR, 0 if not. */
456
457int
458pattern_matches (const char *pattern, const char *percent, const char *str)
459{
460 unsigned int sfxlen, strlength;
461
462 if (percent == 0)
463 {
464 unsigned int len = strlen (pattern) + 1;
465 char *new_chars = alloca (len);
466 memcpy (new_chars, pattern, len);
467 percent = find_percent (new_chars);
468 if (percent == 0)
469 return streq (new_chars, str);
470 pattern = new_chars;
471 }
472
473 sfxlen = strlen (percent + 1);
474 strlength = strlen (str);
475
476 if (strlength < (percent - pattern) + sfxlen
477 || !strneq (pattern, str, percent - pattern))
478 return 0;
479
480 return !strcmp (percent + 1, str + (strlength - sfxlen));
481}
482
483#ifdef KMK
484/* Return 1 if PATTERN matches STR, 0 if not.
485
486 PATTERN is the pattern to match against. PERCENT points to the '%' wildcard
487 inside PATTERN. SFXLEN is the length of pattern following PERCENT. */
488
489static int
490pattern_matches_ex (const char *pattern, const char *percent,
491 unsigned int sfxlen,
492 const char *str, unsigned int strlength)
493{
494 if (strlength < (percent - pattern) + sfxlen
495 || !strneq (pattern, str, percent - pattern)
496 || strcmp (percent + 1, str + (strlength - sfxlen)))
497 return 0;
498 return 1;
499}
500#endif
501
502
503
504/* Find the next comma or ENDPAREN (counting nested STARTPAREN and
505 ENDPARENtheses), starting at PTR before END. Return a pointer to
506 next character.
507
508 If no next argument is found, return NULL.
509*/
510
511static char *
512find_next_argument (char startparen, char endparen,
513 const char *ptr, const char *end)
514{
515 int count = 0;
516
517 for (; ptr < end; ++ptr)
518 if (*ptr == startparen)
519 ++count;
520
521 else if (*ptr == endparen)
522 {
523 --count;
524 if (count < 0)
525 return NULL;
526 }
527
528 else if (*ptr == ',' && !count)
529 return (char *)ptr;
530
531 /* We didn't find anything. */
532 return NULL;
533}
534
535
536
537/* Glob-expand LINE. The returned pointer is
538 only good until the next call to string_glob. */
539
540static char *
541string_glob (char *line)
542{
543 static char *result = 0;
544 static unsigned int length;
545 struct nameseq *chain;
546 unsigned int idx;
547
548 chain = PARSE_FILE_SEQ (&line, struct nameseq, MAP_NUL, NULL,
549 /* We do not want parse_file_seq to strip './'s.
550 That would break examples like:
551 $(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)). */
552 PARSEFS_NOSTRIP|PARSEFS_NOCACHE|PARSEFS_EXISTS);
553
554 if (result == 0)
555 {
556 length = 100;
557 result = xmalloc (100);
558 }
559
560 idx = 0;
561 while (chain != 0)
562 {
563 struct nameseq *next = chain->next;
564 unsigned int len = strlen (chain->name);
565
566 if (idx + len + 1 > length)
567 {
568 length += (len + 1) * 2;
569 result = xrealloc (result, length);
570 }
571 memcpy (&result[idx], chain->name, len);
572 idx += len;
573 result[idx++] = ' ';
574
575 /* Because we used PARSEFS_NOCACHE above, we have to free() NAME. */
576 free ((char *)chain->name);
577#ifndef CONFIG_WITH_ALLOC_CACHES
578 free (chain);
579#else
580 alloccache_free (&nameseq_cache, chain);
581#endif
582 chain = next;
583 }
584
585 /* Kill the last space and terminate the string. */
586 if (idx == 0)
587 result[0] = '\0';
588 else
589 result[idx - 1] = '\0';
590
591 return result;
592}
593
594
595/*
596 Builtin functions
597 */
598
599static char *
600func_patsubst (char *o, char **argv, const char *funcname UNUSED)
601{
602 o = patsubst_expand (o, argv[2], argv[0], argv[1]);
603 return o;
604}
605
606
607static char *
608func_join (char *o, char **argv, const char *funcname UNUSED)
609{
610 int doneany = 0;
611
612 /* Write each word of the first argument directly followed
613 by the corresponding word of the second argument.
614 If the two arguments have a different number of words,
615 the excess words are just output separated by blanks. */
616 const char *tp;
617 const char *pp;
618 const char *list1_iterator = argv[0];
619 const char *list2_iterator = argv[1];
620 do
621 {
622 unsigned int len1, len2;
623
624 tp = find_next_token (&list1_iterator, &len1);
625 if (tp != 0)
626 o = variable_buffer_output (o, tp, len1);
627
628 pp = find_next_token (&list2_iterator, &len2);
629 if (pp != 0)
630 o = variable_buffer_output (o, pp, len2);
631
632 if (tp != 0 || pp != 0)
633 {
634 o = variable_buffer_output (o, " ", 1);
635 doneany = 1;
636 }
637 }
638 while (tp != 0 || pp != 0);
639 if (doneany)
640 /* Kill the last blank. */
641 --o;
642
643 return o;
644}
645
646
647static char *
648func_origin (char *o, char **argv, const char *funcname UNUSED)
649{
650 /* Expand the argument. */
651 struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
652 if (v == 0)
653 o = variable_buffer_output (o, "undefined", 9);
654 else
655 switch (v->origin)
656 {
657 default:
658 case o_invalid:
659 abort ();
660 break;
661 case o_default:
662 o = variable_buffer_output (o, "default", 7);
663 break;
664 case o_env:
665 o = variable_buffer_output (o, "environment", 11);
666 break;
667 case o_file:
668 o = variable_buffer_output (o, "file", 4);
669 break;
670 case o_env_override:
671 o = variable_buffer_output (o, "environment override", 20);
672 break;
673 case o_command:
674 o = variable_buffer_output (o, "command line", 12);
675 break;
676 case o_override:
677 o = variable_buffer_output (o, "override", 8);
678 break;
679 case o_automatic:
680 o = variable_buffer_output (o, "automatic", 9);
681 break;
682#ifdef CONFIG_WITH_LOCAL_VARIABLES
683 case o_local:
684 o = variable_buffer_output (o, "local", 5);
685 break;
686#endif
687 }
688
689 return o;
690}
691
692static char *
693func_flavor (char *o, char **argv, const char *funcname UNUSED)
694{
695 struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
696
697 if (v == 0)
698 o = variable_buffer_output (o, "undefined", 9);
699 else
700 if (v->recursive)
701 o = variable_buffer_output (o, "recursive", 9);
702 else
703 o = variable_buffer_output (o, "simple", 6);
704
705 return o;
706}
707
708#ifdef CONFIG_WITH_WHERE_FUNCTION
709static char *
710func_where (char *o, char **argv, const char *funcname UNUSED)
711{
712 struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
713 char buf[64];
714
715 if (v == 0)
716 o = variable_buffer_output (o, "undefined", 9);
717 else
718 if (v->fileinfo.filenm)
719 {
720 o = variable_buffer_output (o, v->fileinfo.filenm, strlen(v->fileinfo.filenm));
721 sprintf (buf, ":%lu", v->fileinfo.lineno);
722 o = variable_buffer_output (o, buf, strlen(buf));
723 }
724 else
725 o = variable_buffer_output (o, "no-location", 11);
726
727 return o;
728}
729#endif /* CONFIG_WITH_WHERE_FUNCTION */
730
731static char *
732func_notdir_suffix (char *o, char **argv, const char *funcname)
733{
734 /* Expand the argument. */
735 const char *list_iterator = argv[0];
736 const char *p2;
737 int doneany =0;
738 unsigned int len=0;
739
740 int is_suffix = funcname[0] == 's';
741 int is_notdir = !is_suffix;
742 int stop = MAP_DIRSEP | (is_suffix ? MAP_DOT : 0);
743#ifdef VMS
744 /* For VMS list_iterator points to a comma separated list. To use the common
745 [find_]next_token, create a local copy and replace the commas with
746 spaces. Obviously, there is a problem if there is a ',' in the VMS filename
747 (can only happen on ODS5), the same problem as with spaces in filenames,
748 which seems to be present in make on all platforms. */
749 char *vms_list_iterator = alloca(strlen(list_iterator) + 1);
750 int i;
751 for (i = 0; list_iterator[i]; i++)
752 if (list_iterator[i] == ',')
753 vms_list_iterator[i] = ' ';
754 else
755 vms_list_iterator[i] = list_iterator[i];
756 vms_list_iterator[i] = list_iterator[i];
757 while ((p2 = find_next_token((const char**) &vms_list_iterator, &len)) != 0)
758#else
759 while ((p2 = find_next_token (&list_iterator, &len)) != 0)
760#endif
761 {
762 const char *p = p2 + len - 1;
763
764 while (p >= p2 && ! STOP_SET (*p, stop))
765 --p;
766
767 if (p >= p2)
768 {
769 if (is_notdir)
770 ++p;
771 else if (*p != '.')
772 continue;
773 o = variable_buffer_output (o, p, len - (p - p2));
774 }
775#ifdef HAVE_DOS_PATHS
776 /* Handle the case of "d:foo/bar". */
777 else if (is_notdir && p2[0] && p2[1] == ':')
778 {
779 p = p2 + 2;
780 o = variable_buffer_output (o, p, len - (p - p2));
781 }
782#endif
783 else if (is_notdir)
784 o = variable_buffer_output (o, p2, len);
785
786 if (is_notdir || p >= p2)
787 {
788#ifdef VMS
789 if (vms_comma_separator)
790 o = variable_buffer_output (o, ",", 1);
791 else
792#endif
793 o = variable_buffer_output (o, " ", 1);
794
795 doneany = 1;
796 }
797 }
798
799 if (doneany)
800 /* Kill last space. */
801 --o;
802
803 return o;
804}
805
806
807static char *
808func_basename_dir (char *o, char **argv, const char *funcname)
809{
810 /* Expand the argument. */
811 const char *p3 = argv[0];
812 const char *p2;
813 int doneany = 0;
814 unsigned int len = 0;
815
816 int is_basename = funcname[0] == 'b';
817 int is_dir = !is_basename;
818 int stop = MAP_DIRSEP | (is_basename ? MAP_DOT : 0) | MAP_NUL;
819#ifdef VMS
820 /* As in func_notdir_suffix ... */
821 char *vms_p3 = alloca (strlen(p3) + 1);
822 int i;
823 for (i = 0; p3[i]; i++)
824 if (p3[i] == ',')
825 vms_p3[i] = ' ';
826 else
827 vms_p3[i] = p3[i];
828 vms_p3[i] = p3[i];
829 while ((p2 = find_next_token((const char**) &vms_p3, &len)) != 0)
830#else
831 while ((p2 = find_next_token (&p3, &len)) != 0)
832#endif
833 {
834 const char *p = p2 + len - 1;
835 while (p >= p2 && ! STOP_SET (*p, stop))
836 --p;
837
838 if (p >= p2 && (is_dir))
839 o = variable_buffer_output (o, p2, ++p - p2);
840 else if (p >= p2 && (*p == '.'))
841 o = variable_buffer_output (o, p2, p - p2);
842#ifdef HAVE_DOS_PATHS
843 /* Handle the "d:foobar" case */
844 else if (p2[0] && p2[1] == ':' && is_dir)
845 o = variable_buffer_output (o, p2, 2);
846#endif
847 else if (is_dir)
848#ifdef VMS
849 {
850 extern int vms_report_unix_paths;
851 if (vms_report_unix_paths)
852 o = variable_buffer_output (o, "./", 2);
853 else
854 o = variable_buffer_output (o, "[]", 2);
855 }
856#else
857#ifndef _AMIGA
858 o = variable_buffer_output (o, "./", 2);
859#else
860 ; /* Just a nop... */
861#endif /* AMIGA */
862#endif /* !VMS */
863 else
864 /* The entire name is the basename. */
865 o = variable_buffer_output (o, p2, len);
866
867#ifdef VMS
868 if (vms_comma_separator)
869 o = variable_buffer_output (o, ",", 1);
870 else
871#endif
872 o = variable_buffer_output (o, " ", 1);
873 doneany = 1;
874 }
875
876 if (doneany)
877 /* Kill last space. */
878 --o;
879
880 return o;
881}
882
883#if 1 /* rewrite to new MAP stuff? */
884# ifdef VMS
885# define IS_PATHSEP(c) ((c) == ']')
886# else
887# ifdef HAVE_DOS_PATHS
888# define IS_PATHSEP(c) ((c) == '/' || (c) == '\\')
889# else
890# define IS_PATHSEP(c) ((c) == '/')
891# endif
892# endif
893#endif
894
895#ifdef CONFIG_WITH_ROOT_FUNC
896
897/*
898 $(root path)
899
900 This is mainly for dealing with drive letters and UNC paths on Windows
901 and OS/2.
902 */
903static char *
904func_root (char *o, char **argv, const char *funcname UNUSED)
905{
906 const char *paths = argv[0] ? argv[0] : "";
907 int doneany = 0;
908 const char *p;
909 unsigned int len;
910
911 while ((p = find_next_token (&paths, &len)) != 0)
912 {
913 const char *p2 = p;
914
915# ifdef HAVE_DOS_PATHS
916 if ( len >= 2
917 && p2[1] == ':'
918 && ( (p2[0] >= 'A' && p2[0] <= 'Z')
919 || (p2[0] >= 'a' && p2[0] <= 'z')))
920 {
921 p2 += 2;
922 len -= 2;
923 }
924 else if (len >= 4 && IS_PATHSEP(p2[0]) && IS_PATHSEP(p2[1])
925 && !IS_PATHSEP(p2[2]))
926 {
927 /* Min recognized UNC: "//./" - find the next slash
928 Typical root: "//srv/shr/" */
929 /* XXX: Check if //./ needs special handling. */
930
931 p2 += 3;
932 len -= 3;
933 while (len > 0 && !IS_PATHSEP(*p2))
934 p2++, len--;
935
936 if (len && IS_PATHSEP(p2[0]) && (len == 1 || !IS_PATHSEP(p2[1])))
937 {
938 p2++;
939 len--;
940
941 if (len) /* optional share */
942 while (len > 0 && !IS_PATHSEP(*p2))
943 p2++, len--;
944 }
945 else
946 p2 = NULL;
947 }
948 else if (IS_PATHSEP(*p2))
949 {
950 p2++;
951 len--;
952 }
953 else
954 p2 = NULL;
955
956# elif defined (VMS) || defined (AMGIA)
957 /* XXX: VMS and AMGIA */
958 O (fatal, NILF, _("$(root ) is not implemented on this platform"));
959# else
960 if (IS_PATHSEP(*p2))
961 {
962 p2++;
963 len--;
964 }
965 else
966 p2 = NULL;
967# endif
968 if (p2 != NULL)
969 {
970 /* Include all subsequent path separators. */
971
972 while (len > 0 && IS_PATHSEP(*p2))
973 p2++, len--;
974 o = variable_buffer_output (o, p, p2 - p);
975 o = variable_buffer_output (o, " ", 1);
976 doneany = 1;
977 }
978 }
979
980 if (doneany)
981 /* Kill last space. */
982 --o;
983
984 return o;
985}
986
987/*
988 $(notroot path)
989
990 This is mainly for dealing with drive letters and UNC paths on Windows
991 and OS/2.
992 */
993static char *
994func_notroot (char *o, char **argv, const char *funcname UNUSED)
995{
996 const char *paths = argv[0] ? argv[0] : "";
997 int doneany = 0;
998 const char *p;
999 unsigned int len;
1000
1001 while ((p = find_next_token (&paths, &len)) != 0)
1002 {
1003 const char *p2 = p;
1004
1005# ifdef HAVE_DOS_PATHS
1006 if ( len >= 2
1007 && p2[1] == ':'
1008 && ( (p2[0] >= 'A' && p2[0] <= 'Z')
1009 || (p2[0] >= 'a' && p2[0] <= 'z')))
1010 {
1011 p2 += 2;
1012 len -= 2;
1013 }
1014 else if (len >= 4 && IS_PATHSEP(p2[0]) && IS_PATHSEP(p2[1])
1015 && !IS_PATHSEP(p2[2]))
1016 {
1017 /* Min recognized UNC: "//./" - find the next slash
1018 Typical root: "//srv/shr/" */
1019 /* XXX: Check if //./ needs special handling. */
1020 unsigned int saved_len = len;
1021
1022 p2 += 3;
1023 len -= 3;
1024 while (len > 0 && !IS_PATHSEP(*p2))
1025 p2++, len--;
1026
1027 if (len && IS_PATHSEP(p2[0]) && (len == 1 || !IS_PATHSEP(p2[1])))
1028 {
1029 p2++;
1030 len--;
1031
1032 if (len) /* optional share */
1033 while (len > 0 && !IS_PATHSEP(*p2))
1034 p2++, len--;
1035 }
1036 else
1037 {
1038 p2 = p;
1039 len = saved_len;
1040 }
1041 }
1042
1043# elif defined (VMS) || defined (AMGIA)
1044 /* XXX: VMS and AMGIA */
1045 O (fatal, NILF, _("$(root ) is not implemented on this platform"));
1046# endif
1047
1048 /* Exclude all subsequent / leading path separators. */
1049
1050 while (len > 0 && IS_PATHSEP(*p2))
1051 p2++, len--;
1052 if (len > 0)
1053 o = variable_buffer_output (o, p2, len);
1054 else
1055 o = variable_buffer_output (o, ".", 1);
1056 o = variable_buffer_output (o, " ", 1);
1057 doneany = 1;
1058 }
1059
1060 if (doneany)
1061 /* Kill last space. */
1062 --o;
1063
1064 return o;
1065}
1066
1067#endif /* CONFIG_WITH_ROOT_FUNC */
1068
1069static char *
1070func_addsuffix_addprefix (char *o, char **argv, const char *funcname)
1071{
1072 int fixlen = strlen (argv[0]);
1073 const char *list_iterator = argv[1];
1074 int is_addprefix = funcname[3] == 'p';
1075 int is_addsuffix = !is_addprefix;
1076
1077 int doneany = 0;
1078 const char *p;
1079 unsigned int len;
1080
1081 while ((p = find_next_token (&list_iterator, &len)) != 0)
1082 {
1083 if (is_addprefix)
1084 o = variable_buffer_output (o, argv[0], fixlen);
1085 o = variable_buffer_output (o, p, len);
1086 if (is_addsuffix)
1087 o = variable_buffer_output (o, argv[0], fixlen);
1088 o = variable_buffer_output (o, " ", 1);
1089 doneany = 1;
1090 }
1091
1092 if (doneany)
1093 /* Kill last space. */
1094 --o;
1095
1096 return o;
1097}
1098
1099static char *
1100func_subst (char *o, char **argv, const char *funcname UNUSED)
1101{
1102 o = subst_expand (o, argv[2], argv[0], argv[1], strlen (argv[0]),
1103 strlen (argv[1]), 0);
1104
1105 return o;
1106}
1107
1108#ifdef CONFIG_WITH_DEFINED_FUNCTIONS
1109
1110/* Used by func_firstdefined and func_lastdefined to parse the optional last
1111 argument. Returns 0 if the variable name is to be returned and 1 if it's
1112 the variable value value. */
1113static int
1114parse_value_name_argument (const char *arg1, const char *funcname)
1115{
1116 const char *end;
1117 int rc;
1118
1119 if (arg1 == NULL)
1120 return 0;
1121
1122 end = strchr (arg1, '\0');
1123 strip_whitespace (&arg1, &end);
1124
1125 if (!strncmp (arg1, "name", end - arg1))
1126 rc = 0;
1127 else if (!strncmp (arg1, "value", end - arg1))
1128 rc = 1;
1129 else
1130# if 1 /* FIXME: later */
1131 OSS (fatal, *expanding_var,
1132 _("second argument to `%s' function must be `name' or `value', not `%s'"),
1133 funcname, arg1);
1134# else
1135 {
1136 /* check the expanded form */
1137 char *exp = expand_argument (arg1, strchr (arg1, '\0'));
1138 arg1 = exp;
1139 end = strchr (arg1, '\0');
1140 strip_whitespace (&arg1, &end);
1141
1142 if (!strncmp (arg1, "name", end - arg1))
1143 rc = 0;
1144 else if (!strncmp (arg1, "value", end - arg1))
1145 rc = 1;
1146 else
1147 OSS (fatal, *expanding_var,
1148 _("second argument to `%s' function must be `name' or `value', not `%s'"),
1149 funcname, exp);
1150 free (exp);
1151 }
1152# endif
1153
1154 return rc;
1155}
1156
1157/* Given a list of variable names (ARGV[0]), returned the first variable which
1158 is defined (i.e. value is not empty). ARGV[1] indicates whether to return
1159 the variable name or its value. */
1160static char *
1161func_firstdefined (char *o, char **argv, const char *funcname)
1162{
1163 unsigned int i;
1164 const char *words = argv[0]; /* Use a temp variable for find_next_token */
1165 const char *p;
1166 int ret_value = parse_value_name_argument (argv[1], funcname);
1167
1168 /* FIXME: Optimize by not expanding the arguments, but instead expand them
1169 one by one here. This will require a find_next_token variant which
1170 takes `$(' and `)' into account. */
1171 while ((p = find_next_token (&words, &i)) != NULL)
1172 {
1173 struct variable *v = lookup_variable (p, i);
1174 if (v && v->value_length)
1175 {
1176 if (ret_value)
1177 variable_expand_string_2 (o, v->value, v->value_length, &o);
1178 else
1179 o = variable_buffer_output (o, p, i);
1180 break;
1181 }
1182 }
1183
1184 return o;
1185}
1186
1187/* Given a list of variable names (ARGV[0]), returned the last variable which
1188 is defined (i.e. value is not empty). ARGV[1] indicates whether to return
1189 the variable name or its value. */
1190static char *
1191func_lastdefined (char *o, char **argv, const char *funcname)
1192{
1193 struct variable *last_v = NULL;
1194 unsigned int i;
1195 const char *words = argv[0]; /* Use a temp variable for find_next_token */
1196 const char *p;
1197 int ret_value = parse_value_name_argument (argv[1], funcname);
1198
1199 /* FIXME: Optimize this. Walk from the end on unexpanded arguments. */
1200 while ((p = find_next_token (&words, &i)) != NULL)
1201 {
1202 struct variable *v = lookup_variable (p, i);
1203 if (v && v->value_length)
1204 {
1205 last_v = v;
1206 break;
1207 }
1208 }
1209
1210 if (last_v != NULL)
1211 {
1212 if (ret_value)
1213 variable_expand_string_2 (o, last_v->value, last_v->value_length, &o);
1214 else
1215 o = variable_buffer_output (o, last_v->name, last_v->length);
1216 }
1217 return o;
1218}
1219
1220#endif /* CONFIG_WITH_DEFINED_FUNCTIONS */
1221
1222static char *
1223func_firstword (char *o, char **argv, const char *funcname UNUSED)
1224{
1225 unsigned int i;
1226 const char *words = argv[0]; /* Use a temp variable for find_next_token */
1227 const char *p = find_next_token (&words, &i);
1228
1229 if (p != 0)
1230 o = variable_buffer_output (o, p, i);
1231
1232 return o;
1233}
1234
1235static char *
1236func_lastword (char *o, char **argv, const char *funcname UNUSED)
1237{
1238 unsigned int i;
1239 const char *words = argv[0]; /* Use a temp variable for find_next_token */
1240 const char *p = NULL;
1241 const char *t;
1242
1243 while ((t = find_next_token (&words, &i)))
1244 p = t;
1245
1246 if (p != 0)
1247 o = variable_buffer_output (o, p, i);
1248
1249 return o;
1250}
1251
1252static char *
1253func_words (char *o, char **argv, const char *funcname UNUSED)
1254{
1255 int i = 0;
1256 const char *word_iterator = argv[0];
1257 char buf[20];
1258
1259 while (find_next_token (&word_iterator, NULL) != 0)
1260 ++i;
1261
1262 sprintf (buf, "%d", i);
1263 o = variable_buffer_output (o, buf, strlen (buf));
1264
1265 return o;
1266}
1267
1268/* Set begpp to point to the first non-whitespace character of the string,
1269 * and endpp to point to the last non-whitespace character of the string.
1270 * If the string is empty or contains nothing but whitespace, endpp will be
1271 * begpp-1.
1272 */
1273char *
1274strip_whitespace (const char **begpp, const char **endpp)
1275{
1276 while (*begpp <= *endpp && ISSPACE (**begpp))
1277 (*begpp) ++;
1278 while (*endpp >= *begpp && ISSPACE (**endpp))
1279 (*endpp) --;
1280 return (char *)*begpp;
1281}
1282
1283static void
1284check_numeric (const char *s, const char *msg)
1285{
1286 const char *end = s + strlen (s) - 1;
1287 const char *beg = s;
1288 strip_whitespace (&s, &end);
1289
1290 for (; s <= end; ++s)
1291 if (!ISDIGIT (*s)) /* ISDIGIT only evals its arg once: see makeint.h. */
1292 break;
1293
1294 if (s <= end || end - beg < 0)
1295 OSS (fatal, *expanding_var, "%s: '%s'", msg, beg);
1296}
1297
1298
1299
1300static char *
1301func_word (char *o, char **argv, const char *funcname UNUSED)
1302{
1303 const char *end_p;
1304 const char *p;
1305 int i;
1306
1307 /* Check the first argument. */
1308 check_numeric (argv[0], _("non-numeric first argument to 'word' function"));
1309 i = atoi (argv[0]);
1310
1311 if (i == 0)
1312 O (fatal, *expanding_var,
1313 _("first argument to 'word' function must be greater than 0"));
1314
1315 end_p = argv[1];
1316 while ((p = find_next_token (&end_p, 0)) != 0)
1317 if (--i == 0)
1318 break;
1319
1320 if (i == 0)
1321 o = variable_buffer_output (o, p, end_p - p);
1322
1323 return o;
1324}
1325
1326static char *
1327func_wordlist (char *o, char **argv, const char *funcname UNUSED)
1328{
1329 int start, count;
1330
1331 /* Check the arguments. */
1332 check_numeric (argv[0],
1333 _("non-numeric first argument to 'wordlist' function"));
1334 check_numeric (argv[1],
1335 _("non-numeric second argument to 'wordlist' function"));
1336
1337 start = atoi (argv[0]);
1338 if (start < 1)
1339 ON (fatal, *expanding_var,
1340 "invalid first argument to 'wordlist' function: '%d'", start);
1341
1342 count = atoi (argv[1]) - start + 1;
1343
1344 if (count > 0)
1345 {
1346 const char *p;
1347 const char *end_p = argv[2];
1348
1349 /* Find the beginning of the "start"th word. */
1350 while (((p = find_next_token (&end_p, 0)) != 0) && --start)
1351 ;
1352
1353 if (p)
1354 {
1355 /* Find the end of the "count"th word from start. */
1356 while (--count && (find_next_token (&end_p, 0) != 0))
1357 ;
1358
1359 /* Return the stuff in the middle. */
1360 o = variable_buffer_output (o, p, end_p - p);
1361 }
1362 }
1363
1364 return o;
1365}
1366
1367static char *
1368func_findstring (char *o, char **argv, const char *funcname UNUSED)
1369{
1370 /* Find the first occurrence of the first string in the second. */
1371 if (strstr (argv[1], argv[0]) != 0)
1372 o = variable_buffer_output (o, argv[0], strlen (argv[0]));
1373
1374 return o;
1375}
1376
1377static char *
1378func_foreach (char *o, char **argv, const char *funcname UNUSED)
1379{
1380 /* expand only the first two. */
1381 char *varname = expand_argument (argv[0], NULL);
1382 char *list = expand_argument (argv[1], NULL);
1383 const char *body = argv[2];
1384#ifdef CONFIG_WITH_VALUE_LENGTH
1385 long body_len = strlen (body);
1386#endif
1387
1388 int doneany = 0;
1389 const char *list_iterator = list;
1390 const char *p;
1391 unsigned int len;
1392 struct variable *var;
1393
1394 /* Clean up the variable name by removing whitespace. */
1395 char *vp = next_token (varname);
1396 end_of_token (vp)[0] = '\0';
1397
1398 push_new_variable_scope ();
1399 var = define_variable (vp, strlen (vp), "", o_automatic, 0);
1400
1401 /* loop through LIST, put the value in VAR and expand BODY */
1402 while ((p = find_next_token (&list_iterator, &len)) != 0)
1403 {
1404#ifndef CONFIG_WITH_VALUE_LENGTH
1405 char *result = 0;
1406
1407 free (var->value);
1408 var->value = xstrndup (p, len);
1409
1410 result = allocated_variable_expand (body);
1411
1412 o = variable_buffer_output (o, result, strlen (result));
1413 o = variable_buffer_output (o, " ", 1);
1414 doneany = 1;
1415 free (result);
1416#else /* CONFIG_WITH_VALUE_LENGTH */
1417 if (len >= var->value_alloc_len)
1418 {
1419# ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE
1420 if (var->rdonly_val)
1421 var->rdonly_val = 0;
1422 else
1423# endif
1424 free (var->value);
1425 var->value_alloc_len = VAR_ALIGN_VALUE_ALLOC (len + 1);
1426 var->value = xmalloc (var->value_alloc_len);
1427 }
1428 memcpy (var->value, p, len);
1429 var->value[len] = '\0';
1430 var->value_length = len;
1431 VARIABLE_CHANGED (var);
1432
1433 variable_expand_string_2 (o, body, body_len, &o);
1434 o = variable_buffer_output (o, " ", 1);
1435 doneany = 1;
1436#endif /* CONFIG_WITH_VALUE_LENGTH */
1437 }
1438
1439 if (doneany)
1440 /* Kill the last space. */
1441 --o;
1442
1443 pop_variable_scope ();
1444 free (varname);
1445 free (list);
1446
1447 return o;
1448}
1449
1450#ifdef CONFIG_WITH_LOOP_FUNCTIONS
1451
1452
1453/* Helper for func_for that evaluates the INIT and NEXT parts. */
1454static void
1455helper_eval (char *text, size_t text_len)
1456{
1457 unsigned int buf_len;
1458 char *buf;
1459
1460 install_variable_buffer (&buf, &buf_len);
1461 eval_buffer (text, NULL, text + text_len);
1462 restore_variable_buffer (buf, buf_len);
1463}
1464
1465/*
1466 $(for init,condition,next,body)
1467 */
1468static char *
1469func_for (char *o, char **argv, const char *funcname UNUSED)
1470{
1471 char *init = argv[0];
1472 const char *cond = argv[1];
1473 const char *next = argv[2];
1474 size_t next_len = strlen (next);
1475 char *next_buf = xmalloc (next_len + 1);
1476 const char *body = argv[3];
1477 size_t body_len = strlen (body);
1478 unsigned int doneany = 0;
1479
1480 push_new_variable_scope ();
1481
1482 /* Evaluate INIT. */
1483
1484 helper_eval (init, strlen (init));
1485
1486 /* Loop till COND is false. */
1487
1488 while (expr_eval_if_conditionals (cond, NULL) == 0 /* true */)
1489 {
1490 /* Expand BODY. */
1491
1492 if (!doneany)
1493 doneany = 1;
1494 else
1495 o = variable_buffer_output (o, " ", 1);
1496 variable_expand_string_2 (o, body, body_len, &o);
1497
1498 /* Evaluate NEXT. */
1499
1500 memcpy (next_buf, next, next_len + 1);
1501 helper_eval (next_buf, next_len);
1502 }
1503
1504 pop_variable_scope ();
1505 free (next_buf);
1506
1507 return o;
1508}
1509
1510/*
1511 $(while condition,body)
1512 */
1513static char *
1514func_while (char *o, char **argv, const char *funcname UNUSED)
1515{
1516 const char *cond = argv[0];
1517 const char *body = argv[1];
1518 size_t body_len = strlen (body);
1519 unsigned int doneany = 0;
1520
1521 push_new_variable_scope ();
1522
1523 while (expr_eval_if_conditionals (cond, NULL) == 0 /* true */)
1524 {
1525 if (!doneany)
1526 doneany = 1;
1527 else
1528 o = variable_buffer_output (o, " ", 1);
1529 variable_expand_string_2 (o, body, body_len, &o);
1530 }
1531
1532 pop_variable_scope ();
1533
1534 return o;
1535}
1536
1537
1538#endif /* CONFIG_WITH_LOOP_FUNCTIONS */
1539
1540struct a_word
1541{
1542 struct a_word *next;
1543 struct a_word *chain;
1544 char *str;
1545 int length;
1546 int matched;
1547};
1548
1549static unsigned long
1550a_word_hash_1 (const void *key)
1551{
1552 return_STRING_HASH_1 (((struct a_word const *) key)->str);
1553}
1554
1555static unsigned long
1556a_word_hash_2 (const void *key)
1557{
1558 return_STRING_HASH_2 (((struct a_word const *) key)->str);
1559}
1560
1561static int
1562a_word_hash_cmp (const void *x, const void *y)
1563{
1564 int result = ((struct a_word const *) x)->length - ((struct a_word const *) y)->length;
1565 if (result)
1566 return result;
1567 return_STRING_COMPARE (((struct a_word const *) x)->str,
1568 ((struct a_word const *) y)->str);
1569}
1570
1571struct a_pattern
1572{
1573 struct a_pattern *next;
1574 char *str;
1575 char *percent;
1576 int length;
1577#ifdef KMK
1578 unsigned int sfxlen;
1579#endif
1580};
1581
1582static char *
1583func_filter_filterout (char *o, char **argv, const char *funcname)
1584{
1585 struct a_word *wordhead;
1586 struct a_word **wordtail;
1587 struct a_word *wp;
1588 struct a_pattern *pathead;
1589 struct a_pattern **pattail;
1590 struct a_pattern *pp;
1591
1592 struct hash_table a_word_table;
1593 int is_filter = funcname[CSTRLEN ("filter")] == '\0';
1594 const char *pat_iterator = argv[0];
1595 const char *word_iterator = argv[1];
1596 int literals = 0;
1597 int words = 0;
1598 int hashing = 0;
1599 char *p;
1600 unsigned int len;
1601
1602 /* Chop ARGV[0] up into patterns to match against the words.
1603 We don't need to preserve it because our caller frees all the
1604 argument memory anyway. */
1605
1606 pattail = &pathead;
1607 while ((p = find_next_token (&pat_iterator, &len)) != 0)
1608 {
1609 struct a_pattern *pat = alloca (sizeof (struct a_pattern));
1610
1611 *pattail = pat;
1612 pattail = &pat->next;
1613
1614 if (*pat_iterator != '\0')
1615 ++pat_iterator;
1616
1617 pat->str = p;
1618 p[len] = '\0';
1619 pat->percent = find_percent (p);
1620 if (pat->percent == 0)
1621 literals++;
1622#ifdef KMK
1623 pat->sfxlen = pat->percent ? strlen(pat->percent + 1) : 0;
1624#endif
1625
1626 /* find_percent() might shorten the string so LEN is wrong. */
1627 pat->length = strlen (pat->str);
1628 }
1629 *pattail = 0;
1630
1631 /* Chop ARGV[1] up into words to match against the patterns. */
1632
1633 wordtail = &wordhead;
1634 while ((p = find_next_token (&word_iterator, &len)) != 0)
1635 {
1636 struct a_word *word = alloca (sizeof (struct a_word));
1637
1638 *wordtail = word;
1639 wordtail = &word->next;
1640
1641 if (*word_iterator != '\0')
1642 ++word_iterator;
1643
1644 p[len] = '\0';
1645 word->str = p;
1646 word->length = len;
1647 word->matched = 0;
1648 word->chain = 0;
1649 words++;
1650 }
1651 *wordtail = 0;
1652
1653 /* Only use a hash table if arg list lengths justifies the cost. */
1654 hashing = (literals >= 2 && (literals * words) >= 10);
1655 if (hashing)
1656 {
1657 hash_init (&a_word_table, words, a_word_hash_1, a_word_hash_2,
1658 a_word_hash_cmp);
1659 for (wp = wordhead; wp != 0; wp = wp->next)
1660 {
1661 struct a_word *owp = hash_insert (&a_word_table, wp);
1662 if (owp)
1663 wp->chain = owp;
1664 }
1665 }
1666
1667 if (words)
1668 {
1669 int doneany = 0;
1670
1671 /* Run each pattern through the words, killing words. */
1672 for (pp = pathead; pp != 0; pp = pp->next)
1673 {
1674 if (pp->percent)
1675 for (wp = wordhead; wp != 0; wp = wp->next)
1676#ifdef KMK
1677 wp->matched |= pattern_matches_ex (pp->str, pp->percent, pp->sfxlen,
1678 wp->str, wp->length);
1679#else
1680 wp->matched |= pattern_matches (pp->str, pp->percent, wp->str);
1681#endif
1682 else if (hashing)
1683 {
1684 struct a_word a_word_key;
1685 a_word_key.str = pp->str;
1686 a_word_key.length = pp->length;
1687 wp = hash_find_item (&a_word_table, &a_word_key);
1688 while (wp)
1689 {
1690 wp->matched |= 1;
1691 wp = wp->chain;
1692 }
1693 }
1694 else
1695 for (wp = wordhead; wp != 0; wp = wp->next)
1696 wp->matched |= (wp->length == pp->length
1697 && strneq (pp->str, wp->str, wp->length));
1698 }
1699
1700 /* Output the words that matched (or didn't, for filter-out). */
1701 for (wp = wordhead; wp != 0; wp = wp->next)
1702 if (is_filter ? wp->matched : !wp->matched)
1703 {
1704 o = variable_buffer_output (o, wp->str, strlen (wp->str));
1705 o = variable_buffer_output (o, " ", 1);
1706 doneany = 1;
1707 }
1708
1709 if (doneany)
1710 /* Kill the last space. */
1711 --o;
1712 }
1713
1714 if (hashing)
1715 hash_free (&a_word_table, 0);
1716
1717 return o;
1718}
1719
1720
1721static char *
1722func_strip (char *o, char **argv, const char *funcname UNUSED)
1723{
1724 const char *p = argv[0];
1725 int doneany = 0;
1726
1727 while (*p != '\0')
1728 {
1729 int i=0;
1730 const char *word_start;
1731
1732 NEXT_TOKEN (p);
1733 word_start = p;
1734 for (i=0; *p != '\0' && !ISSPACE (*p); ++p, ++i)
1735 {}
1736 if (!i)
1737 break;
1738 o = variable_buffer_output (o, word_start, i);
1739 o = variable_buffer_output (o, " ", 1);
1740 doneany = 1;
1741 }
1742
1743 if (doneany)
1744 /* Kill the last space. */
1745 --o;
1746
1747 return o;
1748}
1749
1750/*
1751 Print a warning or fatal message.
1752*/
1753static char *
1754func_error (char *o, char **argv, const char *funcname)
1755{
1756 char **argvp;
1757 char *msg, *p;
1758 int len;
1759
1760 /* The arguments will be broken on commas. Rather than create yet
1761 another special case where function arguments aren't broken up,
1762 just create a format string that puts them back together. */
1763 for (len=0, argvp=argv; *argvp != 0; ++argvp)
1764 len += strlen (*argvp) + 2;
1765
1766 p = msg = alloca (len + 1);
1767
1768 for (argvp=argv; argvp[1] != 0; ++argvp)
1769 {
1770 strcpy (p, *argvp);
1771 p += strlen (*argvp);
1772 *(p++) = ',';
1773 *(p++) = ' ';
1774 }
1775 strcpy (p, *argvp);
1776
1777 switch (*funcname)
1778 {
1779 case 'e':
1780 OS (fatal, reading_file, "%s", msg);
1781
1782 case 'w':
1783 OS (error, reading_file, "%s", msg);
1784 break;
1785
1786 case 'i':
1787 outputs (0, msg);
1788 outputs (0, "\n");
1789 break;
1790
1791 default:
1792 OS (fatal, *expanding_var, "Internal error: func_error: '%s'", funcname);
1793 }
1794
1795 /* The warning function expands to the empty string. */
1796 return o;
1797}
1798
1799#ifdef KMK
1800/* Compare strings *S1 and *S2.
1801 Return negative if the first is less, positive if it is greater,
1802 zero if they are equal. */
1803
1804static int
1805version_compare_wrapper (const void *v1, const void *v2)
1806{
1807 const char *s1 = *((char **)v1);
1808 const char *s2 = *((char **)v2);
1809 return version_compare (s1, s2);
1810}
1811#endif /* KMK */
1812
1813/*
1814 chop argv[0] into words, and sort them.
1815 */
1816static char *
1817func_sort (char *o, char **argv, const char *funcname UNUSED)
1818{
1819 const char *t;
1820 char **words;
1821 int wordi;
1822 char *p;
1823 unsigned int len;
1824
1825 /* Find the maximum number of words we'll have. */
1826 t = argv[0];
1827 wordi = 0;
1828 while ((p = find_next_token (&t, NULL)) != 0)
1829 {
1830 ++t;
1831 ++wordi;
1832 }
1833
1834 words = xmalloc ((wordi == 0 ? 1 : wordi) * sizeof (char *));
1835
1836 /* Now assign pointers to each string in the array. */
1837 t = argv[0];
1838 wordi = 0;
1839 while ((p = find_next_token (&t, &len)) != 0)
1840 {
1841 if (*t != '\0') /* bird: Fixes access beyond end of string and overflowing words array. */
1842 ++t;
1843 p[len] = '\0';
1844 words[wordi++] = p;
1845 }
1846
1847 if (wordi)
1848 {
1849 int i;
1850
1851 /* Now sort the list of words. */
1852#ifdef KMK
1853 if (funcname[0] == 'v' || funcname[1] == 'v')
1854 qsort (words, wordi, sizeof (char *), version_compare_wrapper);
1855 else
1856 qsort (words, wordi, sizeof (char *), alpha_compare);
1857#else
1858 qsort (words, wordi, sizeof (char *), alpha_compare);
1859#endif
1860
1861 /* Now write the sorted list, uniquified. */
1862#ifdef CONFIG_WITH_RSORT
1863 if (*funcname != 'r')
1864 {
1865 /* sort */
1866#endif
1867 for (i = 0; i < wordi; ++i)
1868 {
1869 len = strlen (words[i]);
1870 if (i == wordi - 1 || strlen (words[i + 1]) != len
1871 || strcmp (words[i], words[i + 1]))
1872 {
1873 o = variable_buffer_output (o, words[i], len);
1874 o = variable_buffer_output (o, " ", 1);
1875 }
1876 }
1877#ifdef CONFIG_WITH_RSORT
1878 }
1879 else
1880 {
1881 /* rsort - reverse the result */
1882 i = wordi;
1883 while (i-- > 0)
1884 {
1885 len = strlen (words[i]);
1886 if (i == 0 || strlen (words[i - 1]) != len
1887 || strcmp (words[i], words[i - 1]))
1888 {
1889 o = variable_buffer_output (o, words[i], len);
1890 o = variable_buffer_output (o, " ", 1);
1891 }
1892 }
1893 }
1894#endif
1895
1896 /* Kill the last space. */
1897 --o;
1898 }
1899
1900 free (words);
1901
1902 return o;
1903}
1904
1905/*
1906 $(if condition,true-part[,false-part])
1907
1908 CONDITION is false iff it evaluates to an empty string. White
1909 space before and after condition are stripped before evaluation.
1910
1911 If CONDITION is true, then TRUE-PART is evaluated, otherwise FALSE-PART is
1912 evaluated (if it exists). Because only one of the two PARTs is evaluated,
1913 you can use $(if ...) to create side-effects (with $(shell ...), for
1914 example).
1915*/
1916
1917static char *
1918func_if (char *o, char **argv, const char *funcname UNUSED)
1919{
1920 const char *begp = argv[0];
1921 const char *endp = begp + strlen (argv[0]) - 1;
1922 int result = 0;
1923
1924 /* Find the result of the condition: if we have a value, and it's not
1925 empty, the condition is true. If we don't have a value, or it's the
1926 empty string, then it's false. */
1927
1928 strip_whitespace (&begp, &endp);
1929
1930 if (begp <= endp)
1931 {
1932 char *expansion = expand_argument (begp, endp+1);
1933
1934 result = strlen (expansion);
1935 free (expansion);
1936 }
1937
1938 /* If the result is true (1) we want to eval the first argument, and if
1939 it's false (0) we want to eval the second. If the argument doesn't
1940 exist we do nothing, otherwise expand it and add to the buffer. */
1941
1942 argv += 1 + !result;
1943
1944 if (*argv)
1945 {
1946 char *expansion = expand_argument (*argv, NULL);
1947
1948 o = variable_buffer_output (o, expansion, strlen (expansion));
1949
1950 free (expansion);
1951 }
1952
1953 return o;
1954}
1955
1956/*
1957 $(or condition1[,condition2[,condition3[...]]])
1958
1959 A CONDITION is false iff it evaluates to an empty string. White
1960 space before and after CONDITION are stripped before evaluation.
1961
1962 CONDITION1 is evaluated. If it's true, then this is the result of
1963 expansion. If it's false, CONDITION2 is evaluated, and so on. If none of
1964 the conditions are true, the expansion is the empty string.
1965
1966 Once a CONDITION is true no further conditions are evaluated
1967 (short-circuiting).
1968*/
1969
1970static char *
1971func_or (char *o, char **argv, const char *funcname UNUSED)
1972{
1973 for ( ; *argv ; ++argv)
1974 {
1975 const char *begp = *argv;
1976 const char *endp = begp + strlen (*argv) - 1;
1977 char *expansion;
1978 int result = 0;
1979
1980 /* Find the result of the condition: if it's false keep going. */
1981
1982 strip_whitespace (&begp, &endp);
1983
1984 if (begp > endp)
1985 continue;
1986
1987 expansion = expand_argument (begp, endp+1);
1988 result = strlen (expansion);
1989
1990 /* If the result is false keep going. */
1991 if (!result)
1992 {
1993 free (expansion);
1994 continue;
1995 }
1996
1997 /* It's true! Keep this result and return. */
1998 o = variable_buffer_output (o, expansion, result);
1999 free (expansion);
2000 break;
2001 }
2002
2003 return o;
2004}
2005
2006/*
2007 $(and condition1[,condition2[,condition3[...]]])
2008
2009 A CONDITION is false iff it evaluates to an empty string. White
2010 space before and after CONDITION are stripped before evaluation.
2011
2012 CONDITION1 is evaluated. If it's false, then this is the result of
2013 expansion. If it's true, CONDITION2 is evaluated, and so on. If all of
2014 the conditions are true, the expansion is the result of the last condition.
2015
2016 Once a CONDITION is false no further conditions are evaluated
2017 (short-circuiting).
2018*/
2019
2020static char *
2021func_and (char *o, char **argv, const char *funcname UNUSED)
2022{
2023 char *expansion;
2024
2025 while (1)
2026 {
2027 const char *begp = *argv;
2028 const char *endp = begp + strlen (*argv) - 1;
2029 int result;
2030
2031 /* An empty condition is always false. */
2032 strip_whitespace (&begp, &endp);
2033 if (begp > endp)
2034 return o;
2035
2036 expansion = expand_argument (begp, endp+1);
2037 result = strlen (expansion);
2038
2039 /* If the result is false, stop here: we're done. */
2040 if (!result)
2041 break;
2042
2043 /* Otherwise the result is true. If this is the last one, keep this
2044 result and quit. Otherwise go on to the next one! */
2045
2046 if (*(++argv))
2047 free (expansion);
2048 else
2049 {
2050 o = variable_buffer_output (o, expansion, result);
2051 break;
2052 }
2053 }
2054
2055 free (expansion);
2056
2057 return o;
2058}
2059
2060static char *
2061func_wildcard (char *o, char **argv, const char *funcname UNUSED)
2062{
2063#ifdef _AMIGA
2064 o = wildcard_expansion (argv[0], o);
2065#else
2066 char *p = string_glob (argv[0]);
2067 o = variable_buffer_output (o, p, strlen (p));
2068#endif
2069 return o;
2070}
2071
2072/*
2073 $(eval <makefile string>)
2074
2075 Always resolves to the empty string.
2076
2077 Treat the arguments as a segment of makefile, and parse them.
2078*/
2079
2080static char *
2081func_eval (char *o, char **argv, const char *funcname UNUSED)
2082{
2083 char *buf;
2084 unsigned int len;
2085
2086 /* Eval the buffer. Pop the current variable buffer setting so that the
2087 eval'd code can use its own without conflicting. */
2088
2089 install_variable_buffer (&buf, &len);
2090
2091#ifndef CONFIG_WITH_VALUE_LENGTH
2092 eval_buffer (argv[0], NULL);
2093#else
2094 eval_buffer (argv[0], NULL, strchr (argv[0], '\0'));
2095#endif
2096
2097 restore_variable_buffer (buf, len);
2098
2099 return o;
2100}
2101
2102
2103#ifdef CONFIG_WITH_EVALPLUS
2104/* Same as func_eval except that we push and pop the local variable
2105 context before evaluating the buffer. */
2106static char *
2107func_evalctx (char *o, char **argv, const char *funcname UNUSED)
2108{
2109 char *buf;
2110 unsigned int len;
2111
2112 /* Eval the buffer. Pop the current variable buffer setting so that the
2113 eval'd code can use its own without conflicting. */
2114
2115 install_variable_buffer (&buf, &len);
2116
2117 push_new_variable_scope ();
2118
2119 eval_buffer (argv[0], NULL, strchr (argv[0], '\0'));
2120
2121 pop_variable_scope ();
2122
2123 restore_variable_buffer (buf, len);
2124
2125 return o;
2126}
2127
2128/* A mix of func_eval and func_value, saves memory for the expansion.
2129 This implements both evalval and evalvalctx, the latter has its own
2130 variable context just like evalctx. */
2131static char *
2132func_evalval (char *o, char **argv, const char *funcname)
2133{
2134 /* Look up the variable. */
2135 struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
2136 if (v)
2137 {
2138 char *buf;
2139 unsigned int len;
2140 int var_ctx;
2141 size_t off;
2142 const floc *reading_file_saved = reading_file;
2143# ifdef CONFIG_WITH_MAKE_STATS
2144 unsigned long long uStartTick = CURRENT_CLOCK_TICK();
2145# ifndef CONFIG_WITH_COMPILER
2146 MAKE_STATS_2(v->evalval_count++);
2147# endif
2148# endif
2149
2150 var_ctx = !strcmp (funcname, "evalvalctx");
2151 if (var_ctx)
2152 push_new_variable_scope ();
2153 if (v->fileinfo.filenm)
2154 reading_file = &v->fileinfo;
2155
2156# ifdef CONFIG_WITH_COMPILER
2157 /* If this variable has been evaluated more than a few times, it make
2158 sense to compile it to speed up the processing. */
2159
2160 v->evalval_count++;
2161 if ( v->evalprog
2162 || (v->evalval_count == 3 && kmk_cc_compile_variable_for_eval (v)))
2163 {
2164 install_variable_buffer (&buf, &len); /* Really necessary? */
2165 kmk_exec_eval_variable (v);
2166 restore_variable_buffer (buf, len);
2167 }
2168 else
2169# endif
2170 {
2171 /* Make a copy of the value to the variable buffer first since
2172 eval_buffer will make changes to its input. */
2173
2174 off = o - variable_buffer;
2175 variable_buffer_output (o, v->value, v->value_length + 1);
2176 o = variable_buffer + off;
2177 assert (!o[v->value_length]);
2178
2179 install_variable_buffer (&buf, &len); /* Really necessary? */
2180 eval_buffer (o, NULL, o + v->value_length);
2181 restore_variable_buffer (buf, len);
2182 }
2183
2184 reading_file = reading_file_saved;
2185 if (var_ctx)
2186 pop_variable_scope ();
2187
2188 MAKE_STATS_2(v->cTicksEvalVal += CURRENT_CLOCK_TICK() - uStartTick);
2189 }
2190
2191 return o;
2192}
2193
2194/* Optimizes the content of one or more variables to save time in
2195 the eval functions. This function will collapse line continuations
2196 and remove comments. */
2197static char *
2198func_eval_optimize_variable (char *o, char **argv, const char *funcname)
2199{
2200 unsigned int i;
2201
2202 for (i = 0; argv[i]; i++)
2203 {
2204 struct variable *v = lookup_variable (argv[i], strlen (argv[i]));
2205# ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE
2206 if (v && v->origin != o_automatic && !v->rdonly_val)
2207# else
2208 if (v && v->origin != o_automatic)
2209# endif
2210 {
2211 char *eos, *src;
2212
2213 eos = collapse_continuations (v->value, v->value_length);
2214 v->value_length = eos - v->value;
2215
2216 /* remove comments */
2217
2218 src = memchr (v->value, '#', v->value_length);
2219 if (src)
2220 {
2221 unsigned char ch = '\0';
2222 char *dst = src;
2223 do
2224 {
2225 /* drop blanks preceeding the comment */
2226 while (dst > v->value)
2227 {
2228 ch = (unsigned char)dst[-1];
2229 if (!ISBLANK (ch))
2230 break;
2231 dst--;
2232 }
2233
2234 /* advance SRC to eol / eos. */
2235 src = memchr (src, '\n', eos - src);
2236 if (!src)
2237 break;
2238
2239 /* drop a preceeding newline if possible (full line comment) */
2240 if (dst > v->value && dst[-1] == '\n')
2241 dst--;
2242
2243 /* copy till next comment or eol. */
2244 while (src < eos)
2245 {
2246 ch = *src++;
2247 if (ch == '#')
2248 break;
2249 *dst++ = ch;
2250 }
2251 }
2252 while (ch == '#' && src < eos);
2253
2254 *dst = '\0';
2255 v->value_length = dst - v->value;
2256 }
2257
2258 VARIABLE_CHANGED (v);
2259
2260# ifdef CONFIG_WITH_COMPILER
2261 /* Compile the variable for evalval, evalctx and expansion. */
2262
2263 if ( v->recursive
2264 && !IS_VARIABLE_RECURSIVE_WITHOUT_DOLLAR (v))
2265 kmk_cc_compile_variable_for_expand (v);
2266 kmk_cc_compile_variable_for_eval (v);
2267# endif
2268 }
2269 else if (v)
2270 OSS (error, NILF, _("$(%s ): variable `%s' is of the wrong type\n"), funcname, v->name);
2271 }
2272
2273 return o;
2274}
2275
2276#endif /* CONFIG_WITH_EVALPLUS */
2277
2278static char *
2279func_value (char *o, char **argv, const char *funcname UNUSED)
2280{
2281 /* Look up the variable. */
2282 struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
2283
2284 /* Copy its value into the output buffer without expanding it. */
2285 if (v)
2286#ifdef CONFIG_WITH_VALUE_LENGTH
2287 {
2288 assert (v->value_length == strlen (v->value));
2289 o = variable_buffer_output (o, v->value, v->value_length);
2290 }
2291#else
2292 o = variable_buffer_output (o, v->value, strlen (v->value));
2293#endif
2294
2295 return o;
2296}
2297
2298/*
2299 \r is replaced on UNIX as well. Is this desirable?
2300 */
2301static void
2302fold_newlines (char *buffer, unsigned int *length, int trim_newlines)
2303{
2304 char *dst = buffer;
2305 char *src = buffer;
2306 char *last_nonnl = buffer - 1;
2307 src[*length] = 0;
2308 for (; *src != '\0'; ++src)
2309 {
2310 if (src[0] == '\r' && src[1] == '\n')
2311 continue;
2312 if (*src == '\n')
2313 {
2314 *dst++ = ' ';
2315 }
2316 else
2317 {
2318 last_nonnl = dst;
2319 *dst++ = *src;
2320 }
2321 }
2322
2323 if (!trim_newlines && (last_nonnl < (dst - 2)))
2324 last_nonnl = dst - 2;
2325
2326 *(++last_nonnl) = '\0';
2327 *length = last_nonnl - buffer;
2328}
2329
2330pid_t shell_function_pid = 0;
2331static int shell_function_completed;
2332
2333void
2334shell_completed (int exit_code, int exit_sig)
2335{
2336 char buf[256];
2337
2338 shell_function_pid = 0;
2339 if (exit_sig == 0 && exit_code == 127)
2340 shell_function_completed = -1;
2341 else
2342 shell_function_completed = 1;
2343
2344 sprintf (buf, "%d", exit_code);
2345 define_variable_cname (".SHELLSTATUS", buf, o_override, 0);
2346}
2347
2348#ifdef WINDOWS32
2349/*untested*/
2350
2351# ifndef CONFIG_NEW_WIN_CHILDREN
2352#include <windows.h>
2353#include <io.h>
2354#include "sub_proc.h"
2355
2356int
2357windows32_openpipe (int *pipedes, int errfd, pid_t *pid_p, char **command_argv, char **envp)
2358{
2359 SECURITY_ATTRIBUTES saAttr;
2360 HANDLE hIn = INVALID_HANDLE_VALUE;
2361 HANDLE hErr = INVALID_HANDLE_VALUE;
2362 HANDLE hChildOutRd;
2363 HANDLE hChildOutWr;
2364 HANDLE hProcess, tmpIn, tmpErr;
2365 DWORD e;
2366
2367 /* Set status for return. */
2368 pipedes[0] = pipedes[1] = -1;
2369 *pid_p = (pid_t)-1;
2370
2371 saAttr.nLength = sizeof (SECURITY_ATTRIBUTES);
2372 saAttr.bInheritHandle = TRUE;
2373 saAttr.lpSecurityDescriptor = NULL;
2374
2375 /* Standard handles returned by GetStdHandle can be NULL or
2376 INVALID_HANDLE_VALUE if the parent process closed them. If that
2377 happens, we open the null device and pass its handle to
2378 process_begin below as the corresponding handle to inherit. */
2379 tmpIn = GetStdHandle (STD_INPUT_HANDLE);
2380 if (DuplicateHandle (GetCurrentProcess (), tmpIn,
2381 GetCurrentProcess (), &hIn,
2382 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE)
2383 {
2384 e = GetLastError ();
2385 if (e == ERROR_INVALID_HANDLE)
2386 {
2387 tmpIn = CreateFile ("NUL", GENERIC_READ,
2388 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
2389 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2390 if (tmpIn != INVALID_HANDLE_VALUE
2391 && DuplicateHandle (GetCurrentProcess (), tmpIn,
2392 GetCurrentProcess (), &hIn,
2393 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE)
2394 CloseHandle (tmpIn);
2395 }
2396 if (hIn == INVALID_HANDLE_VALUE)
2397 {
2398 ON (error, NILF,
2399 _("windows32_openpipe: DuplicateHandle(In) failed (e=%ld)\n"), e);
2400 return -1;
2401 }
2402 }
2403 tmpErr = (HANDLE)_get_osfhandle (errfd);
2404 if (DuplicateHandle (GetCurrentProcess (), tmpErr,
2405 GetCurrentProcess (), &hErr,
2406 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE)
2407 {
2408 e = GetLastError ();
2409 if (e == ERROR_INVALID_HANDLE)
2410 {
2411 tmpErr = CreateFile ("NUL", GENERIC_WRITE,
2412 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
2413 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2414 if (tmpErr != INVALID_HANDLE_VALUE
2415 && DuplicateHandle (GetCurrentProcess (), tmpErr,
2416 GetCurrentProcess (), &hErr,
2417 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE)
2418 CloseHandle (tmpErr);
2419 }
2420 if (hErr == INVALID_HANDLE_VALUE)
2421 {
2422 ON (error, NILF,
2423 _("windows32_openpipe: DuplicateHandle(Err) failed (e=%ld)\n"), e);
2424 return -1;
2425 }
2426 }
2427
2428 if (! CreatePipe (&hChildOutRd, &hChildOutWr, &saAttr, 0))
2429 {
2430 ON (error, NILF, _("CreatePipe() failed (e=%ld)\n"), GetLastError());
2431 return -1;
2432 }
2433
2434 hProcess = process_init_fd (hIn, hChildOutWr, hErr);
2435
2436 if (!hProcess)
2437 {
2438 O (error, NILF, _("windows32_openpipe(): process_init_fd() failed\n"));
2439 return -1;
2440 }
2441
2442 /* make sure that CreateProcess() has Path it needs */
2443 sync_Path_environment ();
2444 /* 'sync_Path_environment' may realloc 'environ', so take note of
2445 the new value. */
2446 envp = environ;
2447
2448 if (! process_begin (hProcess, command_argv, envp, command_argv[0], NULL))
2449 {
2450 /* register process for wait */
2451 process_register (hProcess);
2452
2453 /* set the pid for returning to caller */
2454 *pid_p = (pid_t) hProcess;
2455
2456 /* set up to read data from child */
2457 pipedes[0] = _open_osfhandle ((intptr_t) hChildOutRd, O_RDONLY);
2458
2459 /* this will be closed almost right away */
2460 pipedes[1] = _open_osfhandle ((intptr_t) hChildOutWr, O_APPEND);
2461 return 0;
2462 }
2463 else
2464 {
2465 /* reap/cleanup the failed process */
2466 process_cleanup (hProcess);
2467
2468 /* close handles which were duplicated, they weren't used */
2469 if (hIn != INVALID_HANDLE_VALUE)
2470 CloseHandle (hIn);
2471 if (hErr != INVALID_HANDLE_VALUE)
2472 CloseHandle (hErr);
2473
2474 /* close pipe handles, they won't be used */
2475 CloseHandle (hChildOutRd);
2476 CloseHandle (hChildOutWr);
2477
2478 return -1;
2479 }
2480}
2481# endif /* !CONFIG_NEW_WIN_CHILDREN */
2482#endif
2483
2484
2485#ifdef __MSDOS__
2486FILE *
2487msdos_openpipe (int* pipedes, int *pidp, char *text)
2488{
2489 FILE *fpipe=0;
2490 /* MSDOS can't fork, but it has 'popen'. */
2491 struct variable *sh = lookup_variable ("SHELL", 5);
2492 int e;
2493 extern int dos_command_running, dos_status;
2494
2495 /* Make sure not to bother processing an empty line. */
2496 NEXT_TOKEN (text);
2497 if (*text == '\0')
2498 return 0;
2499
2500 if (sh)
2501 {
2502 char buf[PATH_MAX + 7];
2503 /* This makes sure $SHELL value is used by $(shell), even
2504 though the target environment is not passed to it. */
2505 sprintf (buf, "SHELL=%s", sh->value);
2506 putenv (buf);
2507 }
2508
2509 e = errno;
2510 errno = 0;
2511 dos_command_running = 1;
2512 dos_status = 0;
2513 /* If dos_status becomes non-zero, it means the child process
2514 was interrupted by a signal, like SIGINT or SIGQUIT. See
2515 fatal_error_signal in commands.c. */
2516 fpipe = popen (text, "rt");
2517 dos_command_running = 0;
2518 if (!fpipe || dos_status)
2519 {
2520 pipedes[0] = -1;
2521 *pidp = -1;
2522 if (dos_status)
2523 errno = EINTR;
2524 else if (errno == 0)
2525 errno = ENOMEM;
2526 if (fpipe)
2527 pclose (fpipe);
2528 shell_completed (127, 0);
2529 }
2530 else
2531 {
2532 pipedes[0] = fileno (fpipe);
2533 *pidp = 42; /* Yes, the Meaning of Life, the Universe, and Everything! */
2534 errno = e;
2535 }
2536 return fpipe;
2537}
2538#endif
2539
2540/*
2541 Do shell spawning, with the naughty bits for different OSes.
2542 */
2543
2544#ifdef VMS
2545
2546/* VMS can't do $(shell ...) */
2547
2548char *
2549func_shell_base (char *o, char **argv, int trim_newlines)
2550{
2551 fprintf (stderr, "This platform does not support shell\n");
2552 die (MAKE_TROUBLE);
2553 return NULL;
2554}
2555
2556#define func_shell 0
2557
2558#else
2559#ifndef _AMIGA
2560char *
2561func_shell_base (char *o, char **argv, int trim_newlines)
2562{
2563 char *batch_filename = NULL;
2564 int errfd;
2565#ifdef __MSDOS__
2566 FILE *fpipe;
2567#endif
2568 char **command_argv;
2569 const char * volatile error_prefix; /* bird: this volatile ~~and the 'o' one~~, is for shutting up gcc warnings */
2570 char **envp;
2571 int pipedes[2];
2572 pid_t pid;
2573
2574#ifndef __MSDOS__
2575#ifdef WINDOWS32
2576 /* Reset just_print_flag. This is needed on Windows when batch files
2577 are used to run the commands, because we normally refrain from
2578 creating batch files under -n. */
2579 int j_p_f = just_print_flag;
2580 just_print_flag = 0;
2581#endif
2582
2583 /* Construct the argument list. */
2584 command_argv = construct_command_argv (argv[0], NULL, NULL, 0,
2585 &batch_filename);
2586 if (command_argv == 0)
2587 {
2588#ifdef WINDOWS32
2589 just_print_flag = j_p_f;
2590#endif
2591 return o;
2592 }
2593#endif /* !__MSDOS__ */
2594
2595 /* Using a target environment for 'shell' loses in cases like:
2596 export var = $(shell echo foobie)
2597 bad := $(var)
2598 because target_environment hits a loop trying to expand $(var) to put it
2599 in the environment. This is even more confusing when 'var' was not
2600 explicitly exported, but just appeared in the calling environment.
2601
2602 See Savannah bug #10593.
2603
2604 envp = target_environment (NULL);
2605 */
2606
2607 envp = environ;
2608
2609 /* For error messages. */
2610 if (reading_file && reading_file->filenm)
2611 {
2612 char *p = alloca (strlen (reading_file->filenm)+11+4);
2613 sprintf (p, "%s:%lu: ", reading_file->filenm,
2614 reading_file->lineno + reading_file->offset);
2615 error_prefix = p;
2616 }
2617 else
2618 error_prefix = "";
2619
2620 /* Set up the output in case the shell writes something. */
2621 output_start ();
2622
2623#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
2624 errfd = -1; /** @todo fixme */
2625#else
2626 errfd = (output_context && output_context->err >= 0
2627 ? output_context->err : FD_STDERR);
2628#endif
2629
2630#if defined(__MSDOS__)
2631 fpipe = msdos_openpipe (pipedes, &pid, argv[0]);
2632 if (pipedes[0] < 0)
2633 {
2634 perror_with_name (error_prefix, "pipe");
2635 return o;
2636 }
2637
2638#elif defined(WINDOWS32)
2639# ifdef CONFIG_NEW_WIN_CHILDREN
2640 pipedes[1] = -1;
2641 MkWinChildCreateWithStdOutPipe (command_argv, envp, errfd, &pid, &pipedes[0]);
2642# else
2643 windows32_openpipe (pipedes, errfd, &pid, command_argv, envp);
2644# endif
2645 /* Restore the value of just_print_flag. */
2646 just_print_flag = j_p_f;
2647
2648 if (pipedes[0] < 0)
2649 {
2650 /* Open of the pipe failed, mark as failed execution. */
2651 shell_completed (127, 0);
2652 perror_with_name (error_prefix, "pipe");
2653 return o;
2654 }
2655
2656#else
2657 if (pipe (pipedes) < 0)
2658 {
2659 perror_with_name (error_prefix, "pipe");
2660 return o;
2661 }
2662
2663 /* Close handles that are unnecessary for the child process. */
2664 CLOSE_ON_EXEC(pipedes[1]);
2665 CLOSE_ON_EXEC(pipedes[0]);
2666
2667 {
2668 struct output out;
2669 out.syncout = 1;
2670 out.out = pipedes[1];
2671 out.err = errfd;
2672
2673 pid = child_execute_job (&out, 1, command_argv, envp);
2674 }
2675
2676 if (pid < 0)
2677 {
2678 perror_with_name (error_prefix, "fork");
2679 return o;
2680 }
2681#endif
2682
2683 {
2684 char *buffer;
2685 unsigned int maxlen, i;
2686 int cc;
2687
2688 /* Record the PID for reap_children. */
2689 shell_function_pid = pid;
2690#ifndef __MSDOS__
2691 shell_function_completed = 0;
2692
2693 /* Free the storage only the child needed. */
2694 free (command_argv[0]);
2695 free (command_argv);
2696
2697 /* Close the write side of the pipe. We test for -1, since
2698 pipedes[1] is -1 on MS-Windows, and some versions of MS
2699 libraries barf when 'close' is called with -1. */
2700 if (pipedes[1] >= 0)
2701 close (pipedes[1]);
2702#endif
2703
2704 /* Set up and read from the pipe. */
2705
2706 maxlen = 200;
2707 buffer = xmalloc (maxlen + 1);
2708
2709 /* Read from the pipe until it gets EOF. */
2710 for (i = 0; ; i += cc)
2711 {
2712 if (i == maxlen)
2713 {
2714 maxlen += 512;
2715 buffer = xrealloc (buffer, maxlen + 1);
2716 }
2717
2718 EINTRLOOP (cc, read (pipedes[0], &buffer[i], maxlen - i));
2719 if (cc <= 0)
2720 break;
2721 }
2722 buffer[i] = '\0';
2723
2724 /* Close the read side of the pipe. */
2725#ifdef __MSDOS__
2726 if (fpipe)
2727 {
2728 int st = pclose (fpipe);
2729 shell_completed (st, 0);
2730 }
2731#else
2732# ifdef _MSC_VER /* Avoid annoying msvcrt when debugging. (bird) */
2733 if (pipedes[0] != -1)
2734# endif
2735 (void) close (pipedes[0]);
2736#endif
2737
2738 /* Loop until child_handler or reap_children() sets
2739 shell_function_completed to the status of our child shell. */
2740 while (shell_function_completed == 0)
2741 reap_children (1, 0);
2742
2743 if (batch_filename)
2744 {
2745 DB (DB_VERBOSE, (_("Cleaning up temporary batch file %s\n"),
2746 batch_filename));
2747 remove (batch_filename);
2748 free (batch_filename);
2749 }
2750 shell_function_pid = 0;
2751
2752 /* shell_completed() will set shell_function_completed to 1 when the
2753 child dies normally, or to -1 if it dies with status 127, which is
2754 most likely an exec fail. */
2755
2756 if (shell_function_completed == -1)
2757 {
2758 /* This likely means that the execvp failed, so we should just
2759 write the error message in the pipe from the child. */
2760 fputs (buffer, stderr);
2761 fflush (stderr);
2762 }
2763 else
2764 {
2765 /* The child finished normally. Replace all newlines in its output
2766 with spaces, and put that in the variable output buffer. */
2767 fold_newlines (buffer, &i, trim_newlines);
2768 o = variable_buffer_output (o, buffer, i);
2769 }
2770
2771 free (buffer);
2772 }
2773
2774 return o;
2775}
2776
2777#else /* _AMIGA */
2778
2779/* Do the Amiga version of func_shell. */
2780
2781char *
2782func_shell_base (char *o, char **argv, int trim_newlines)
2783{
2784 /* Amiga can't fork nor spawn, but I can start a program with
2785 redirection of my choice. However, this means that we
2786 don't have an opportunity to reopen stdout to trap it. Thus,
2787 we save our own stdout onto a new descriptor and dup a temp
2788 file's descriptor onto our stdout temporarily. After we
2789 spawn the shell program, we dup our own stdout back to the
2790 stdout descriptor. The buffer reading is the same as above,
2791 except that we're now reading from a file. */
2792
2793#include <dos/dos.h>
2794#include <proto/dos.h>
2795
2796 BPTR child_stdout;
2797 char tmp_output[FILENAME_MAX];
2798 unsigned int maxlen = 200, i;
2799 int cc;
2800 char * buffer, * ptr;
2801 char ** aptr;
2802 int len = 0;
2803 char* batch_filename = NULL;
2804
2805 /* Construct the argument list. */
2806 command_argv = construct_command_argv (argv[0], NULL, NULL, 0,
2807 &batch_filename);
2808 if (command_argv == 0)
2809 return o;
2810
2811 /* Note the mktemp() is a security hole, but this only runs on Amiga.
2812 Ideally we would use output_tmpfile(), but this uses a special
2813 Open(), not fopen(), and I'm not familiar enough with the code to mess
2814 with it. */
2815 strcpy (tmp_output, "t:MakeshXXXXXXXX");
2816 mktemp (tmp_output);
2817 child_stdout = Open (tmp_output, MODE_NEWFILE);
2818
2819 for (aptr=command_argv; *aptr; aptr++)
2820 len += strlen (*aptr) + 1;
2821
2822 buffer = xmalloc (len + 1);
2823 ptr = buffer;
2824
2825 for (aptr=command_argv; *aptr; aptr++)
2826 {
2827 strcpy (ptr, *aptr);
2828 ptr += strlen (ptr) + 1;
2829 *ptr ++ = ' ';
2830 *ptr = 0;
2831 }
2832
2833 ptr[-1] = '\n';
2834
2835 Execute (buffer, NULL, child_stdout);
2836 free (buffer);
2837
2838 Close (child_stdout);
2839
2840 child_stdout = Open (tmp_output, MODE_OLDFILE);
2841
2842 buffer = xmalloc (maxlen);
2843 i = 0;
2844 do
2845 {
2846 if (i == maxlen)
2847 {
2848 maxlen += 512;
2849 buffer = xrealloc (buffer, maxlen + 1);
2850 }
2851
2852 cc = Read (child_stdout, &buffer[i], maxlen - i);
2853 if (cc > 0)
2854 i += cc;
2855 } while (cc > 0);
2856
2857 Close (child_stdout);
2858
2859 fold_newlines (buffer, &i, trim_newlines);
2860 o = variable_buffer_output (o, buffer, i);
2861 free (buffer);
2862 return o;
2863}
2864#endif /* _AMIGA */
2865
2866static char *
2867func_shell (char *o, char **argv, const char *funcname UNUSED)
2868{
2869 return func_shell_base (o, argv, 1);
2870}
2871#endif /* !VMS */
2872
2873#ifdef EXPERIMENTAL
2874
2875/*
2876 equality. Return is string-boolean, i.e., the empty string is false.
2877 */
2878static char *
2879func_eq (char *o, char **argv, const char *funcname UNUSED)
2880{
2881 int result = ! strcmp (argv[0], argv[1]);
2882 o = variable_buffer_output (o, result ? "1" : "", result);
2883 return o;
2884}
2885
2886
2887/*
2888 string-boolean not operator.
2889 */
2890static char *
2891func_not (char *o, char **argv, const char *funcname UNUSED)
2892{
2893 const char *s = argv[0];
2894 int result = 0;
2895 NEXT_TOKEN (s);
2896 result = ! (*s);
2897 o = variable_buffer_output (o, result ? "1" : "", result);
2898 return o;
2899}
2900#endif
2901
2902
2903
2904#ifdef HAVE_DOS_PATHS
2905# ifdef __CYGWIN__
2906# define IS_ABSOLUTE(n) ((n[0] && n[1] == ':') || STOP_SET (n[0], MAP_DIRSEP))
2907# else
2908# define IS_ABSOLUTE(n) (n[0] && n[1] == ':')
2909# endif
2910# define ROOT_LEN 3
2911#else
2912#define IS_ABSOLUTE(n) (n[0] == '/')
2913#define ROOT_LEN 1
2914#endif
2915
2916/* Return the absolute name of file NAME which does not contain any '.',
2917 '..' components nor any repeated path separators ('/'). */
2918#ifdef KMK
2919char *
2920#else
2921static char *
2922#endif
2923abspath (const char *name, char *apath)
2924{
2925 char *dest;
2926 const char *start, *end, *apath_limit;
2927 unsigned long root_len = ROOT_LEN;
2928
2929 if (name[0] == '\0' || apath == NULL)
2930 return NULL;
2931
2932#ifdef WINDOWS32 /* bird */
2933 dest = unix_slashes_resolved (name, apath, GET_PATH_MAX);
2934 if (!dest)
2935 return NULL;
2936 dest = strchr(apath, '\0');
2937
2938 (void)end; (void)start; (void)apath_limit;
2939
2940#elif defined __OS2__ /* bird */
2941 if (_abspath(apath, name, GET_PATH_MAX))
2942 return NULL;
2943 dest = strchr(apath, '\0');
2944
2945 (void)end; (void)start; (void)apath_limit; (void)dest;
2946
2947#else /* !WINDOWS32 && !__OS2__ */
2948 apath_limit = apath + GET_PATH_MAX;
2949
2950 if (!IS_ABSOLUTE(name))
2951 {
2952 /* It is unlikely we would make it until here but just to make sure. */
2953 if (!starting_directory)
2954 return NULL;
2955
2956 strcpy (apath, starting_directory);
2957
2958#ifdef HAVE_DOS_PATHS
2959 if (STOP_SET (name[0], MAP_DIRSEP))
2960 {
2961 if (STOP_SET (name[1], MAP_DIRSEP))
2962 {
2963 /* A UNC. Don't prepend a drive letter. */
2964 apath[0] = name[0];
2965 apath[1] = name[1];
2966 root_len = 2;
2967 }
2968 /* We have /foo, an absolute file name except for the drive
2969 letter. Assume the missing drive letter is the current
2970 drive, which we can get if we remove from starting_directory
2971 everything past the root directory. */
2972 apath[root_len] = '\0';
2973 }
2974#endif
2975
2976 dest = strchr (apath, '\0');
2977 }
2978 else
2979 {
2980#if defined(__CYGWIN__) && defined(HAVE_DOS_PATHS)
2981 if (STOP_SET (name[0], MAP_DIRSEP))
2982 root_len = 1;
2983#endif
2984#ifdef KMK
2985 memcpy (apath, name, root_len);
2986 apath[root_len] = '\0';
2987 assert (strlen (apath) == root_len);
2988#else
2989 strncpy (apath, name, root_len);
2990 apath[root_len] = '\0';
2991#endif
2992 dest = apath + root_len;
2993 /* Get past the root, since we already copied it. */
2994 name += root_len;
2995#ifdef HAVE_DOS_PATHS
2996 if (! STOP_SET (apath[root_len - 1], MAP_DIRSEP))
2997 {
2998 /* Convert d:foo into d:./foo and increase root_len. */
2999 apath[2] = '.';
3000 apath[3] = '/';
3001 dest++;
3002 root_len++;
3003 /* strncpy above copied one character too many. */
3004 name--;
3005 }
3006 else
3007 apath[root_len - 1] = '/'; /* make sure it's a forward slash */
3008#endif
3009 }
3010
3011 for (start = end = name; *start != '\0'; start = end)
3012 {
3013 unsigned long len;
3014
3015 /* Skip sequence of multiple path-separators. */
3016 while (STOP_SET (*start, MAP_DIRSEP))
3017 ++start;
3018
3019 /* Find end of path component. */
3020 for (end = start; ! STOP_SET (*end, MAP_DIRSEP|MAP_NUL); ++end)
3021 ;
3022
3023 len = end - start;
3024
3025 if (len == 0)
3026 break;
3027 else if (len == 1 && start[0] == '.')
3028 /* nothing */;
3029 else if (len == 2 && start[0] == '.' && start[1] == '.')
3030 {
3031 /* Back up to previous component, ignore if at root already. */
3032 if (dest > apath + root_len)
3033 for (--dest; ! STOP_SET (dest[-1], MAP_DIRSEP); --dest)
3034 ;
3035 }
3036 else
3037 {
3038 if (! STOP_SET (dest[-1], MAP_DIRSEP))
3039 *dest++ = '/';
3040
3041 if (dest + len >= apath_limit)
3042 return NULL;
3043
3044 dest = memcpy (dest, start, len);
3045 dest += len;
3046 *dest = '\0';
3047 }
3048 }
3049#endif /* !WINDOWS32 && !__OS2__ */
3050
3051 /* Unless it is root strip trailing separator. */
3052 if (dest > apath + root_len && STOP_SET (dest[-1], MAP_DIRSEP))
3053 --dest;
3054
3055 *dest = '\0';
3056
3057 return apath;
3058}
3059
3060
3061static char *
3062func_realpath (char *o, char **argv, const char *funcname UNUSED)
3063{
3064 /* Expand the argument. */
3065 const char *p = argv[0];
3066 const char *path = 0;
3067 int doneany = 0;
3068 unsigned int len = 0;
3069
3070 while ((path = find_next_token (&p, &len)) != 0)
3071 {
3072 if (len < GET_PATH_MAX)
3073 {
3074 char *rp;
3075 struct stat st;
3076 PATH_VAR (in);
3077 PATH_VAR (out);
3078
3079 strncpy (in, path, len);
3080 in[len] = '\0';
3081
3082#ifdef HAVE_REALPATH
3083 ENULLLOOP (rp, realpath (in, out));
3084#else
3085 rp = abspath (in, out);
3086#endif
3087
3088 if (rp)
3089 {
3090 int r;
3091 EINTRLOOP (r, stat (out, &st));
3092 if (r == 0)
3093 {
3094 o = variable_buffer_output (o, out, strlen (out));
3095 o = variable_buffer_output (o, " ", 1);
3096 doneany = 1;
3097 }
3098 }
3099 }
3100 }
3101
3102 /* Kill last space. */
3103 if (doneany)
3104 --o;
3105
3106 return o;
3107}
3108
3109static char *
3110func_file (char *o, char **argv, const char *funcname UNUSED)
3111{
3112 char *fn = argv[0];
3113
3114 if (fn[0] == '>')
3115 {
3116 FILE *fp;
3117#ifdef KMK_FOPEN_NO_INHERIT_MODE
3118 const char *mode = "w" KMK_FOPEN_NO_INHERIT_MODE;
3119#else
3120 const char *mode = "w";
3121#endif
3122
3123 /* We are writing a file. */
3124 ++fn;
3125 if (fn[0] == '>')
3126 {
3127#ifdef KMK_FOPEN_NO_INHERIT_MODE
3128 mode = "a" KMK_FOPEN_NO_INHERIT_MODE;
3129#else
3130 mode = "a";
3131#endif
3132 ++fn;
3133 }
3134 NEXT_TOKEN (fn);
3135
3136 if (fn[0] == '\0')
3137 O (fatal, *expanding_var, _("file: missing filename"));
3138
3139 ENULLLOOP (fp, fopen (fn, mode));
3140 if (fp == NULL)
3141 OSS (fatal, reading_file, _("open: %s: %s"), fn, strerror (errno));
3142
3143 if (argv[1])
3144 {
3145 int l = strlen (argv[1]);
3146 int nl = l == 0 || argv[1][l-1] != '\n';
3147
3148 if (fputs (argv[1], fp) == EOF || (nl && fputc ('\n', fp) == EOF))
3149 OSS (fatal, reading_file, _("write: %s: %s"), fn, strerror (errno));
3150 }
3151 if (fclose (fp))
3152 OSS (fatal, reading_file, _("close: %s: %s"), fn, strerror (errno));
3153 }
3154 else if (fn[0] == '<')
3155 {
3156 char *preo = o;
3157 FILE *fp;
3158
3159 ++fn;
3160 NEXT_TOKEN (fn);
3161 if (fn[0] == '\0')
3162 O (fatal, *expanding_var, _("file: missing filename"));
3163
3164 if (argv[1])
3165 O (fatal, *expanding_var, _("file: too many arguments"));
3166
3167#ifdef KMK_FOPEN_NO_INHERIT_MODE
3168 ENULLLOOP (fp, fopen (fn, "r" KMK_FOPEN_NO_INHERIT_MODE));
3169#else
3170 ENULLLOOP (fp, fopen (fn, "r"));
3171#endif
3172 if (fp == NULL)
3173 {
3174 if (errno == ENOENT)
3175 return o;
3176 OSS (fatal, reading_file, _("open: %s: %s"), fn, strerror (errno));
3177 }
3178
3179 while (1)
3180 {
3181 char buf[1024];
3182 size_t l = fread (buf, 1, sizeof (buf), fp);
3183 if (l > 0)
3184 o = variable_buffer_output (o, buf, l);
3185
3186 if (ferror (fp))
3187 if (errno != EINTR)
3188 OSS (fatal, reading_file, _("read: %s: %s"), fn, strerror (errno));
3189 if (feof (fp))
3190 break;
3191 }
3192 if (fclose (fp))
3193 OSS (fatal, reading_file, _("close: %s: %s"), fn, strerror (errno));
3194
3195 /* Remove trailing newline. */
3196 if (o > preo && o[-1] == '\n')
3197 if (--o > preo && o[-1] == '\r')
3198 --o;
3199 }
3200 else
3201 OS (fatal, *expanding_var, _("file: invalid file operation: %s"), fn);
3202
3203 return o;
3204}
3205
3206static char *
3207func_abspath (char *o, char **argv, const char *funcname UNUSED)
3208{
3209 /* Expand the argument. */
3210 const char *p = argv[0];
3211 const char *path = 0;
3212 int doneany = 0;
3213 unsigned int len = 0;
3214
3215 while ((path = find_next_token (&p, &len)) != 0)
3216 {
3217 if (len < GET_PATH_MAX)
3218 {
3219 PATH_VAR (in);
3220 PATH_VAR (out);
3221
3222 strncpy (in, path, len);
3223 in[len] = '\0';
3224
3225 if (abspath (in, out))
3226 {
3227 o = variable_buffer_output (o, out, strlen (out));
3228 o = variable_buffer_output (o, " ", 1);
3229 doneany = 1;
3230 }
3231 }
3232 }
3233
3234 /* Kill last space. */
3235 if (doneany)
3236 --o;
3237
3238 return o;
3239}
3240
3241#ifdef CONFIG_WITH_ABSPATHEX
3242/* Same as abspath except that the current path may be given as the
3243 2nd argument. */
3244static char *
3245func_abspathex (char *o, char **argv, const char *funcname UNUSED)
3246{
3247 char *cwd = argv[1];
3248
3249 /* cwd needs leading spaces chopped and may be optional,
3250 in which case we're exactly like $(abspath ). */
3251 if (cwd)
3252 while (ISBLANK (*cwd))
3253 cwd++;
3254 if (!cwd || !*cwd)
3255 o = func_abspath (o, argv, funcname);
3256 else
3257 {
3258 /* Expand the argument. */
3259 const char *p = argv[0];
3260 unsigned int cwd_len = ~0U;
3261 char *path = 0;
3262 int doneany = 0;
3263 unsigned int len = 0;
3264 PATH_VAR (in);
3265 PATH_VAR (out);
3266
3267 while ((path = find_next_token (&p, &len)) != 0)
3268 {
3269 if (len < GET_PATH_MAX)
3270 {
3271#ifdef HAVE_DOS_PATHS
3272 if (path[0] != '/' && path[0] != '\\' && (len < 2 || path[1] != ':') && cwd)
3273#else
3274 if (path[0] != '/' && cwd)
3275#endif
3276 {
3277 /* relative path, prefix with cwd. */
3278 if (cwd_len == ~0U)
3279 cwd_len = strlen (cwd);
3280 if (cwd_len + len + 1 >= GET_PATH_MAX)
3281 continue;
3282 memcpy (in, cwd, cwd_len);
3283 in[cwd_len] = '/';
3284 memcpy (in + cwd_len + 1, path, len);
3285 in[cwd_len + len + 1] = '\0';
3286 }
3287 else
3288 {
3289 /* absolute path pass it as-is. */
3290 memcpy (in, path, len);
3291 in[len] = '\0';
3292 }
3293
3294 if (abspath (in, out))
3295 {
3296 o = variable_buffer_output (o, out, strlen (out));
3297 o = variable_buffer_output (o, " ", 1);
3298 doneany = 1;
3299 }
3300 }
3301 }
3302
3303 /* Kill last space. */
3304 if (doneany)
3305 --o;
3306 }
3307
3308 return o;
3309}
3310#endif
3311
3312#ifdef CONFIG_WITH_XARGS
3313/* Create one or more command lines avoiding the max argument
3314 length restriction of the host OS.
3315
3316 The last argument is the list of arguments that the normal
3317 xargs command would be fed from stdin.
3318
3319 The first argument is initial command and it's arguments.
3320
3321 If there are three or more arguments, the 2nd argument is
3322 the command and arguments to be used on subsequent
3323 command lines. Defaults to the initial command.
3324
3325 If there are four or more arguments, the 3rd argument is
3326 the command to be used at the final command line. Defaults
3327 to the sub sequent or initial command .
3328
3329 A future version of this function may define more arguments
3330 and therefor anyone specifying six or more arguments will
3331 cause fatal errors.
3332
3333 Typical usage is:
3334 $(xargs ar cas mylib.a,$(objects))
3335 or
3336 $(xargs ar cas mylib.a,ar as mylib.a,$(objects))
3337
3338 It will then create one or more "ar mylib.a ..." command
3339 lines with proper \n\t separation so it can be used when
3340 writing rules. */
3341static char *
3342func_xargs (char *o, char **argv, const char *funcname UNUSED)
3343{
3344 int argc;
3345 const char *initial_cmd;
3346 size_t initial_cmd_len;
3347 const char *subsequent_cmd;
3348 size_t subsequent_cmd_len;
3349 const char *final_cmd;
3350 size_t final_cmd_len;
3351 const char *args;
3352 size_t max_args;
3353 int i;
3354
3355#ifdef ARG_MAX
3356 /* ARG_MAX is a bit unreliable (environment), so drop 25% of the max. */
3357# define XARGS_MAX (ARG_MAX - (ARG_MAX / 4))
3358#else /* FIXME: update configure with a command line length test. */
3359# define XARGS_MAX 10240
3360#endif
3361
3362 argc = 0;
3363 while (argv[argc])
3364 argc++;
3365 if (argc > 4)
3366 O (fatal, NILF, _("Too many arguments for $(xargs)!\n"));
3367
3368 /* first: the initial / default command.*/
3369 initial_cmd = argv[0];
3370 while (ISSPACE (*initial_cmd))
3371 initial_cmd++;
3372 max_args = initial_cmd_len = strlen (initial_cmd);
3373
3374 /* second: the command for the subsequent command lines. defaults to the initial cmd. */
3375 subsequent_cmd = argc > 2 && argv[1][0] != '\0' ? argv[1] : "\0";
3376 while (ISSPACE (*subsequent_cmd))
3377 subsequent_cmd++; /* gcc 7.3.0 complains "offset ‘1’ outside bounds of constant string" if constant is "" rather than "\0". */
3378 if (*subsequent_cmd)
3379 {
3380 subsequent_cmd_len = strlen (subsequent_cmd);
3381 if (subsequent_cmd_len > max_args)
3382 max_args = subsequent_cmd_len;
3383 }
3384 else
3385 {
3386 subsequent_cmd = initial_cmd;
3387 subsequent_cmd_len = initial_cmd_len;
3388 }
3389
3390 /* third: the final command. defaults to the subseq cmd. */
3391 final_cmd = argc > 3 && argv[2][0] != '\0' ? argv[2] : "\0";
3392 while (ISSPACE (*final_cmd))
3393 final_cmd++; /* gcc 7.3.0: same complaint as for subsequent_cmd++ */
3394 if (*final_cmd)
3395 {
3396 final_cmd_len = strlen (final_cmd);
3397 if (final_cmd_len > max_args)
3398 max_args = final_cmd_len;
3399 }
3400 else
3401 {
3402 final_cmd = subsequent_cmd;
3403 final_cmd_len = subsequent_cmd_len;
3404 }
3405
3406 /* last: the arguments to split up into sensible portions. */
3407 args = argv[argc - 1];
3408
3409 /* calc the max argument length. */
3410 if (XARGS_MAX <= max_args + 2)
3411 ONN (fatal, NILF, _("$(xargs): the commands are longer than the max exec argument length. (%lu <= %lu)\n"),
3412 (unsigned long)XARGS_MAX, (unsigned long)max_args + 2);
3413 max_args = XARGS_MAX - max_args - 1;
3414
3415 /* generate the commands. */
3416 i = 0;
3417 for (i = 0; ; i++)
3418 {
3419 unsigned int len;
3420 const char *iterator = args;
3421 const char *end = args;
3422 const char *cur;
3423 const char *tmp;
3424
3425 /* scan the arguments till we reach the end or the max length. */
3426 while ((cur = find_next_token(&iterator, &len))
3427 && (size_t)((cur + len) - args) < max_args)
3428 end = cur + len;
3429 if (cur && end == args)
3430 O (fatal, NILF, _("$(xargs): command + one single arg is too much. giving up.\n"));
3431
3432 /* emit the command. */
3433 if (i == 0)
3434 {
3435 o = variable_buffer_output (o, (char *)initial_cmd, initial_cmd_len);
3436 o = variable_buffer_output (o, " ", 1);
3437 }
3438 else if (cur)
3439 {
3440 o = variable_buffer_output (o, "\n\t", 2);
3441 o = variable_buffer_output (o, (char *)subsequent_cmd, subsequent_cmd_len);
3442 o = variable_buffer_output (o, " ", 1);
3443 }
3444 else
3445 {
3446 o = variable_buffer_output (o, "\n\t", 2);
3447 o = variable_buffer_output (o, (char *)final_cmd, final_cmd_len);
3448 o = variable_buffer_output (o, " ", 1);
3449 }
3450
3451 tmp = end;
3452 while (tmp > args && ISSPACE (tmp[-1])) /* drop trailing spaces. */
3453 tmp--;
3454 o = variable_buffer_output (o, (char *)args, tmp - args);
3455
3456
3457 /* next */
3458 if (!cur)
3459 break;
3460 args = end;
3461 while (ISSPACE (*args))
3462 args++;
3463 }
3464
3465 return o;
3466}
3467#endif
3468
3469
3470#ifdef CONFIG_WITH_STRING_FUNCTIONS
3471/*
3472 $(length string)
3473
3474 XXX: This doesn't take multibyte locales into account.
3475 */
3476static char *
3477func_length (char *o, char **argv, const char *funcname UNUSED)
3478{
3479 size_t len = strlen (argv[0]);
3480 return math_int_to_variable_buffer (o, len);
3481}
3482
3483/*
3484 $(length-var var)
3485
3486 XXX: This doesn't take multibyte locales into account.
3487 */
3488static char *
3489func_length_var (char *o, char **argv, const char *funcname UNUSED)
3490{
3491 struct variable *var = lookup_variable (argv[0], strlen (argv[0]));
3492 return math_int_to_variable_buffer (o, var ? var->value_length : 0);
3493}
3494
3495
3496/* func_insert and func_substr helper. */
3497static char *
3498helper_pad (char *o, size_t to_add, const char *pad, size_t pad_len)
3499{
3500 while (to_add > 0)
3501 {
3502 size_t size = to_add > pad_len ? pad_len : to_add;
3503 o = variable_buffer_output (o, pad, size);
3504 to_add -= size;
3505 }
3506 return o;
3507}
3508
3509/*
3510 $(insert in, str[, n[, length[, pad]]])
3511
3512 XXX: This doesn't take multibyte locales into account.
3513 */
3514static char *
3515func_insert (char *o, char **argv, const char *funcname UNUSED)
3516{
3517 const char *in = argv[0];
3518 math_int in_len = (math_int)strlen (in);
3519 const char *str = argv[1];
3520 math_int str_len = (math_int)strlen (str);
3521 math_int n = 0;
3522 math_int length = str_len;
3523 const char *pad = " ";
3524 size_t pad_len = 16;
3525 size_t i;
3526
3527 if (argv[2] != NULL)
3528 {
3529 n = math_int_from_string (argv[2]);
3530 if (n > 0)
3531 n--; /* one-origin */
3532 else if (n == 0)
3533 n = str_len; /* append */
3534 else
3535 { /* n < 0: from the end */
3536 n = str_len + n;
3537 if (n < 0)
3538 n = 0;
3539 }
3540 if (n > 16*1024*1024) /* 16MB */
3541 OS (fatal, NILF, _("$(insert ): n=%s is out of bounds\n"), argv[2]);
3542
3543 if (argv[3] != NULL)
3544 {
3545 length = math_int_from_string (argv[3]);
3546 if (length < 0 || length > 16*1024*1024 /* 16MB */)
3547 OS (fatal, NILF, _("$(insert ): length=%s is out of bounds\n"), argv[3]);
3548
3549 if (argv[4] != NULL)
3550 {
3551 const char *tmp = argv[4];
3552 for (i = 0; tmp[i] == ' '; i++)
3553 /* nothing */;
3554 if (tmp[i] != '\0')
3555 {
3556 pad = argv[4];
3557 pad_len = strlen (pad);
3558 }
3559 /* else: it was all default spaces. */
3560 }
3561 }
3562 }
3563
3564 /* the head of the original string */
3565 if (n > 0)
3566 {
3567 if (n <= str_len)
3568 o = variable_buffer_output (o, str, n);
3569 else
3570 {
3571 o = variable_buffer_output (o, str, str_len);
3572 o = helper_pad (o, n - str_len, pad, pad_len);
3573 }
3574 }
3575
3576 /* insert the string */
3577 if (length <= in_len)
3578 o = variable_buffer_output (o, in, length);
3579 else
3580 {
3581 o = variable_buffer_output (o, in, in_len);
3582 o = helper_pad (o, length - in_len, pad, pad_len);
3583 }
3584
3585 /* the tail of the original string */
3586 if (n < str_len)
3587 o = variable_buffer_output (o, str + n, str_len - n);
3588
3589 return o;
3590}
3591
3592
3593/*
3594 $(pos needle, haystack[, start])
3595 $(lastpos needle, haystack[, start])
3596
3597 XXX: This doesn't take multibyte locales into account.
3598 */
3599static char *
3600func_pos (char *o, char **argv, const char *funcname UNUSED)
3601{
3602 const char *needle = *argv[0] ? argv[0] : " ";
3603 size_t needle_len = strlen (needle);
3604 const char *haystack = argv[1];
3605 size_t haystack_len = strlen (haystack);
3606 math_int start = 0;
3607 const char *hit;
3608
3609 if (argv[2] != NULL)
3610 {
3611 start = math_int_from_string (argv[2]);
3612 if (start > 0)
3613 start--; /* one-origin */
3614 else if (start < 0)
3615 start = haystack_len + start; /* from the end */
3616 if (start < 0 || start + needle_len > haystack_len)
3617 return math_int_to_variable_buffer (o, 0);
3618 }
3619 else if (funcname[0] == 'l')
3620 start = haystack_len - 1;
3621
3622 /* do the searching */
3623 if (funcname[0] != 'l')
3624 { /* pos */
3625 if (needle_len == 1)
3626 hit = strchr (haystack + start, *needle);
3627 else
3628 hit = strstr (haystack + start, needle);
3629 }
3630 else
3631 { /* last pos */
3632 int ch = *needle;
3633 size_t off = start + 1;
3634
3635 hit = NULL;
3636 while (off-- > 0)
3637 {
3638 if ( haystack[off] == ch
3639 && ( needle_len == 1
3640 || strncmp (&haystack[off], needle, needle_len) == 0))
3641 {
3642 hit = haystack + off;
3643 break;
3644 }
3645 }
3646 }
3647
3648 return math_int_to_variable_buffer (o, hit ? hit - haystack + 1 : 0);
3649}
3650
3651
3652/*
3653 $(substr str, start[, length[, pad]])
3654
3655 XXX: This doesn't take multibyte locales into account.
3656 */
3657static char *
3658func_substr (char *o, char **argv, const char *funcname UNUSED)
3659{
3660 const char *str = argv[0];
3661 math_int str_len = (math_int)strlen (str);
3662 math_int start = math_int_from_string (argv[1]);
3663 math_int length = 0;
3664 const char *pad = NULL;
3665 size_t pad_len = 0;
3666
3667 if (argv[2] != NULL)
3668 {
3669 if (argv[3] != NULL)
3670 {
3671 pad = argv[3];
3672 for (pad_len = 0; pad[pad_len] == ' '; pad_len++)
3673 /* nothing */;
3674 if (pad[pad_len] != '\0')
3675 pad_len = strlen (pad);
3676 else
3677 {
3678 pad = " ";
3679 pad_len = 16;
3680 }
3681 }
3682 length = math_int_from_string (argv[2]);
3683 if (pad != NULL && length > 16*1024*1024 /* 16MB */)
3684 OS (fatal, NILF, _("$(substr ): length=%s is out of bounds\n"), argv[2]);
3685 if (pad != NULL && length < 0)
3686 OS (fatal, NILF, _("$(substr ): negative length (%s) and padding doesn't mix.\n"), argv[2]);
3687 if (length == 0)
3688 return o;
3689 }
3690
3691 /* Note that negative start and length are used for referencing from the
3692 end of the string. */
3693 if (pad == NULL)
3694 {
3695 if (start > 0)
3696 start--; /* one-origin */
3697 else
3698 {
3699 start = str_len + start;
3700 if (start <= 0)
3701 {
3702 if (length < 0)
3703 return o;
3704 start += length;
3705 if (start <= 0)
3706 return o;
3707 length = start;
3708 start = 0;
3709 }
3710 }
3711
3712 if (start >= str_len)
3713 return o;
3714 if (length == 0)
3715 length = str_len - start;
3716 else if (length < 0)
3717 {
3718 if (str_len <= -length)
3719 return o;
3720 length += str_len;
3721 if (length <= start)
3722 return o;
3723 length -= start;
3724 }
3725 else if (start + length > str_len)
3726 length = str_len - start;
3727
3728 o = variable_buffer_output (o, str + start, length);
3729 }
3730 else
3731 {
3732 if (start > 0)
3733 {
3734 start--; /* one-origin */
3735 if (start >= str_len)
3736 return length ? helper_pad (o, length, pad, pad_len) : o;
3737 if (length == 0)
3738 length = str_len - start;
3739 }
3740 else
3741 {
3742 start = str_len + start;
3743 if (start <= 0)
3744 {
3745 if (start + length <= 0)
3746 return length ? helper_pad (o, length, pad, pad_len) : o;
3747 o = helper_pad (o, -start, pad, pad_len);
3748 return variable_buffer_output (o, str, length + start);
3749 }
3750 if (length == 0)
3751 length = str_len - start;
3752 }
3753 if (start + length <= str_len)
3754 o = variable_buffer_output (o, str + start, length);
3755 else
3756 {
3757 o = variable_buffer_output (o, str + start, str_len - start);
3758 o = helper_pad (o, start + length - str_len, pad, pad_len);
3759 }
3760 }
3761
3762 return o;
3763}
3764
3765
3766/*
3767 $(translate string, from-set[, to-set[, pad-char]])
3768
3769 XXX: This doesn't take multibyte locales into account.
3770 */
3771static char *
3772func_translate (char *o, char **argv, const char *funcname UNUSED)
3773{
3774 const unsigned char *str = (const unsigned char *)argv[0];
3775 const unsigned char *from_set = (const unsigned char *)argv[1];
3776 const char *to_set = argv[2] != NULL ? argv[2] : "";
3777 char trans_tab[1 << CHAR_BIT];
3778 int i;
3779 char ch;
3780
3781 /* init the array. */
3782 for (i = 0; i < (1 << CHAR_BIT); i++)
3783 trans_tab[i] = i;
3784
3785 while ( (i = *from_set) != '\0'
3786 && (ch = *to_set) != '\0')
3787 {
3788 trans_tab[i] = ch;
3789 from_set++;
3790 to_set++;
3791 }
3792
3793 if (i != '\0')
3794 {
3795 ch = '\0'; /* no padding == remove char */
3796 if (argv[2] != NULL && argv[3] != NULL)
3797 {
3798 ch = argv[3][0];
3799 if (ch && argv[3][1])
3800 OS (fatal, NILF, _("$(translate ): pad=`%s' expected a single char\n"), argv[3]);
3801 if (ch == '\0') /* no char == space */
3802 ch = ' ';
3803 }
3804 while ((i = *from_set++) != '\0')
3805 trans_tab[i] = ch;
3806 }
3807
3808 /* do the translation */
3809 while ((i = *str++) != '\0')
3810 {
3811 ch = trans_tab[i];
3812 if (ch)
3813 o = variable_buffer_output (o, &ch, 1);
3814 }
3815
3816 return o;
3817}
3818#endif /* CONFIG_WITH_STRING_FUNCTIONS */
3819
3820
3821#ifdef CONFIG_WITH_DEFINED
3822/* Similar to ifdef. */
3823static char *
3824func_defined (char *o, char **argv, const char *funcname UNUSED)
3825{
3826 struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
3827 int result = v != NULL && *v->value != '\0';
3828 o = variable_buffer_output (o, result ? "1" : "", result);
3829 return o;
3830}
3831#endif /* CONFIG_WITH_DEFINED*/
3832
3833#ifdef CONFIG_WITH_TOUPPER_TOLOWER
3834static char *
3835func_toupper_tolower (char *o, char **argv, const char *funcname)
3836{
3837 /* Expand the argument. */
3838 const char *p = argv[0];
3839 while (*p)
3840 {
3841 /* convert to temporary buffer */
3842 char tmp[256];
3843 unsigned int i;
3844 if (!strcmp(funcname, "toupper"))
3845 for (i = 0; i < sizeof(tmp) && *p; i++, p++)
3846 tmp[i] = toupper(*p);
3847 else
3848 for (i = 0; i < sizeof(tmp) && *p; i++, p++)
3849 tmp[i] = tolower(*p);
3850 o = variable_buffer_output (o, tmp, i);
3851 }
3852
3853 return o;
3854}
3855#endif /* CONFIG_WITH_TOUPPER_TOLOWER */
3856
3857#if defined(CONFIG_WITH_VALUE_LENGTH) && defined(CONFIG_WITH_COMPARE)
3858
3859/* Strip leading spaces and other things off a command. */
3860static const char *
3861comp_cmds_strip_leading (const char *s, const char *e)
3862{
3863 while (s < e)
3864 {
3865 const char ch = *s;
3866 if (!ISBLANK (ch)
3867 && ch != '@'
3868#ifdef CONFIG_WITH_COMMANDS_FUNC
3869 && ch != '%'
3870#endif
3871 && ch != '+'
3872 && ch != '-')
3873 break;
3874 s++;
3875 }
3876 return s;
3877}
3878
3879/* Worker for func_comp_vars() which is called if the comparision failed.
3880 It will do the slow command by command comparision of the commands
3881 when there invoked as comp-cmds. */
3882static char *
3883comp_vars_ne (char *o, const char *s1, const char *e1, const char *s2, const char *e2,
3884 char *ne_retval, const char *funcname)
3885{
3886 /* give up at once if not comp-cmds or comp-cmds-ex. */
3887 if (strcmp (funcname, "comp-cmds") != 0
3888 && strcmp (funcname, "comp-cmds-ex") != 0)
3889 o = variable_buffer_output (o, ne_retval, strlen (ne_retval));
3890 else
3891 {
3892 const char * const s1_start = s1;
3893 int new_cmd = 1;
3894 int diff;
3895 for (;;)
3896 {
3897 /* if it's a new command, strip leading stuff. */
3898 if (new_cmd)
3899 {
3900 s1 = comp_cmds_strip_leading (s1, e1);
3901 s2 = comp_cmds_strip_leading (s2, e2);
3902 new_cmd = 0;
3903 }
3904 if (s1 >= e1 || s2 >= e2)
3905 break;
3906
3907 /*
3908 * Inner compare loop which compares one line.
3909 * FIXME: parse quoting!
3910 */
3911 for (;;)
3912 {
3913 const char ch1 = *s1;
3914 const char ch2 = *s2;
3915 diff = ch1 - ch2;
3916 if (diff)
3917 break;
3918 if (ch1 == '\n')
3919 break;
3920 assert (ch1 != '\r');
3921
3922 /* next */
3923 s1++;
3924 s2++;
3925 if (s1 >= e1 || s2 >= e2)
3926 break;
3927 }
3928
3929 /*
3930 * If we exited because of a difference try to end-of-command
3931 * comparision, e.g. ignore trailing spaces.
3932 */
3933 if (diff)
3934 {
3935 /* strip */
3936 while (s1 < e1 && ISBLANK (*s1))
3937 s1++;
3938 while (s2 < e2 && ISBLANK (*s2))
3939 s2++;
3940 if (s1 >= e1 || s2 >= e2)
3941 break;
3942
3943 /* compare again and check that it's a newline. */
3944 if (*s2 != '\n' || *s1 != '\n')
3945 break;
3946 }
3947 /* Break out if we exited because of EOS. */
3948 else if (s1 >= e1 || s2 >= e2)
3949 break;
3950
3951 /*
3952 * Detect the end of command lines.
3953 */
3954 if (*s1 == '\n')
3955 new_cmd = s1 == s1_start || s1[-1] != '\\';
3956 s1++;
3957 s2++;
3958 }
3959
3960 /*
3961 * Ignore trailing empty lines.
3962 */
3963 if (s1 < e1 || s2 < e2)
3964 {
3965 while (s1 < e1 && (ISBLANK (*s1) || *s1 == '\n'))
3966 if (*s1++ == '\n')
3967 s1 = comp_cmds_strip_leading (s1, e1);
3968 while (s2 < e2 && (ISBLANK (*s2) || *s2 == '\n'))
3969 if (*s2++ == '\n')
3970 s2 = comp_cmds_strip_leading (s2, e2);
3971 }
3972
3973 /* emit the result. */
3974 if (s1 == e1 && s2 == e2)
3975 o = variable_buffer_output (o, "", 1) - 1; /** @todo check why this was necessary back the... */
3976 else
3977 o = variable_buffer_output (o, ne_retval, strlen (ne_retval));
3978 }
3979 return o;
3980}
3981
3982/*
3983 $(comp-vars var1,var2,not-equal-return)
3984 or
3985 $(comp-cmds cmd-var1,cmd-var2,not-equal-return)
3986
3987 Compares the two variables (that's given by name to avoid unnecessary
3988 expanding) and return the string in the third argument if not equal.
3989 If equal, nothing is returned.
3990
3991 comp-vars will to an exact comparision only stripping leading and
3992 trailing spaces.
3993
3994 comp-cmds will compare command by command, ignoring not only leading
3995 and trailing spaces on each line but also leading one leading '@',
3996 '-', '+' and '%'
3997*/
3998static char *
3999func_comp_vars (char *o, char **argv, const char *funcname)
4000{
4001 const char *s1, *e1, *x1, *s2, *e2, *x2;
4002 char *a1 = NULL, *a2 = NULL;
4003 size_t l, l1, l2;
4004 struct variable *var1 = lookup_variable (argv[0], strlen (argv[0]));
4005 struct variable *var2 = lookup_variable (argv[1], strlen (argv[1]));
4006
4007 /* the simple cases */
4008 if (var1 == var2)
4009 return variable_buffer_output (o, "", 0); /* eq */
4010 if (!var1 || !var2)
4011 return variable_buffer_output (o, argv[2], strlen(argv[2]));
4012 if (var1->value == var2->value)
4013 return variable_buffer_output (o, "", 0); /* eq */
4014 if ( (!var1->recursive || IS_VARIABLE_RECURSIVE_WITHOUT_DOLLAR (var1))
4015 && (!var2->recursive || IS_VARIABLE_RECURSIVE_WITHOUT_DOLLAR (var2)) )
4016 {
4017 if ( var1->value_length == var2->value_length
4018 && !memcmp (var1->value, var2->value, var1->value_length))
4019 return variable_buffer_output (o, "", 0); /* eq */
4020
4021 /* ignore trailing and leading blanks */
4022 s1 = var1->value;
4023 e1 = s1 + var1->value_length;
4024 while (ISBLANK (*s1))
4025 s1++;
4026 while (e1 > s1 && ISBLANK (e1[-1]))
4027 e1--;
4028
4029 s2 = var2->value;
4030 e2 = s2 + var2->value_length;
4031 while (ISBLANK (*s2))
4032 s2++;
4033 while (e2 > s2 && ISBLANK (e2[-1]))
4034 e2--;
4035
4036 if (e1 - s1 != e2 - s2)
4037 return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
4038 if (!memcmp (s1, s2, e1 - s1))
4039 return variable_buffer_output (o, "", 0); /* eq */
4040 return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
4041 }
4042
4043 /* ignore trailing and leading blanks */
4044 s1 = var1->value;
4045 e1 = s1 + var1->value_length;
4046 while (ISBLANK (*s1))
4047 s1++;
4048 while (e1 > s1 && ISBLANK (e1[-1]))
4049 e1--;
4050
4051 s2 = var2->value;
4052 e2 = s2 + var2->value_length;
4053 while (ISBLANK (*s2))
4054 s2++;
4055 while (e2 > s2 && ISBLANK (e2[-1]))
4056 e2--;
4057
4058 /* both empty after stripping? */
4059 if (s1 == e1 && s2 == e2)
4060 return variable_buffer_output (o, "", 0); /* eq */
4061
4062 /* optimist. */
4063 if ( e1 - s1 == e2 - s2
4064 && !memcmp(s1, s2, e1 - s1))
4065 return variable_buffer_output (o, "", 0); /* eq */
4066
4067 /* compare up to the first '$' or the end. */
4068 x1 = var1->recursive ? memchr (s1, '$', e1 - s1) : NULL;
4069 x2 = var2->recursive ? memchr (s2, '$', e2 - s2) : NULL;
4070 if (!x1 && !x2)
4071 return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
4072
4073 l1 = x1 ? x1 - s1 : e1 - s1;
4074 l2 = x2 ? x2 - s2 : e2 - s2;
4075 l = l1 <= l2 ? l1 : l2;
4076 if (l && memcmp (s1, s2, l))
4077 return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
4078
4079 /* one or both buffers now require expanding. */
4080 if (!x1)
4081 s1 += l;
4082 else
4083 {
4084 s1 = a1 = allocated_variable_expand ((char *)s1 + l);
4085 if (!l)
4086 while (ISBLANK (*s1))
4087 s1++;
4088 e1 = strchr (s1, '\0');
4089 while (e1 > s1 && ISBLANK (e1[-1]))
4090 e1--;
4091 }
4092
4093 if (!x2)
4094 s2 += l;
4095 else
4096 {
4097 s2 = a2 = allocated_variable_expand ((char *)s2 + l);
4098 if (!l)
4099 while (ISBLANK (*s2))
4100 s2++;
4101 e2 = strchr (s2, '\0');
4102 while (e2 > s2 && ISBLANK (e2[-1]))
4103 e2--;
4104 }
4105
4106 /* the final compare */
4107 if ( e1 - s1 != e2 - s2
4108 || memcmp (s1, s2, e1 - s1))
4109 o = comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
4110 else
4111 o = variable_buffer_output (o, "", 1) - 1; /* eq */ /** @todo check why this was necessary back the... */
4112 if (a1)
4113 free (a1);
4114 if (a2)
4115 free (a2);
4116 return o;
4117}
4118
4119/*
4120 $(comp-cmds-ex cmds1,cmds2,not-equal-return)
4121
4122 Compares the two strings and return the string in the third argument
4123 if not equal. If equal, nothing is returned.
4124
4125 The comparision will be performed command by command, ignoring not
4126 only leading and trailing spaces on each line but also leading one
4127 leading '@', '-', '+' and '%'.
4128*/
4129static char *
4130func_comp_cmds_ex (char *o, char **argv, const char *funcname)
4131{
4132 const char *s1, *e1, *s2, *e2;
4133 size_t l1, l2;
4134
4135 /* the simple cases */
4136 s1 = argv[0];
4137 s2 = argv[1];
4138 if (s1 == s2)
4139 return variable_buffer_output (o, "", 0); /* eq */
4140 l1 = strlen (argv[0]);
4141 l2 = strlen (argv[1]);
4142
4143 if ( l1 == l2
4144 && !memcmp (s1, s2, l1))
4145 return variable_buffer_output (o, "", 0); /* eq */
4146
4147 /* ignore trailing and leading blanks */
4148 e1 = s1 + l1;
4149 s1 = comp_cmds_strip_leading (s1, e1);
4150
4151 e2 = s2 + l2;
4152 s2 = comp_cmds_strip_leading (s2, e2);
4153
4154 if (e1 - s1 != e2 - s2)
4155 return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
4156 if (!memcmp (s1, s2, e1 - s1))
4157 return variable_buffer_output (o, "", 0); /* eq */
4158 return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
4159}
4160#endif
4161
4162#ifdef CONFIG_WITH_DATE
4163# if defined (_MSC_VER) /* FIXME: !defined (HAVE_STRPTIME) */
4164char *strptime(const char *s, const char *format, struct tm *tm)
4165{
4166 return (char *)"strptime is not implemented";
4167}
4168# endif
4169/* Check if the string is all blanks or not. */
4170static int
4171all_blanks (const char *s)
4172{
4173 if (!s)
4174 return 1;
4175 while (ISSPACE (*s))
4176 s++;
4177 return *s == '\0';
4178}
4179
4180/* The first argument is the strftime format string, a iso
4181 timestamp is the default if nothing is given.
4182
4183 The second argument is a time value if given. The format
4184 is either the format from the first argument or given as
4185 an additional third argument. */
4186static char *
4187func_date (char *o, char **argv, const char *funcname)
4188{
4189 char *p;
4190 char *buf;
4191 size_t buf_size;
4192 struct tm t;
4193 const char *format;
4194
4195 /* determin the format - use a single word as the default. */
4196 format = !strcmp (funcname, "date-utc")
4197 ? "%Y-%m-%dT%H:%M:%SZ"
4198 : "%Y-%m-%dT%H:%M:%S";
4199 if (!all_blanks (argv[0]))
4200 format = argv[0];
4201
4202 /* get the time. */
4203 memset (&t, 0, sizeof(t));
4204 if (argv[0] && !all_blanks (argv[1]))
4205 {
4206 const char *input_format = !all_blanks (argv[2]) ? argv[2] : format;
4207 p = strptime (argv[1], input_format, &t);
4208 if (!p || *p != '\0')
4209 {
4210 OSSSS (error, NILF, _("$(%s): strptime(%s,%s,) -> %s\n"), funcname,
4211 argv[1], input_format, p ? p : "<null>");
4212 return variable_buffer_output (o, "", 0);
4213 }
4214 }
4215 else
4216 {
4217 time_t tval;
4218 time (&tval);
4219 if (!strcmp (funcname, "date-utc"))
4220 t = *gmtime (&tval);
4221 else
4222 t = *localtime (&tval);
4223 }
4224
4225 /* format it. note that zero isn't necessarily an error, so we'll
4226 have to keep shut about failures. */
4227 buf_size = 64;
4228 buf = xmalloc (buf_size);
4229 while (strftime (buf, buf_size, format, &t) == 0)
4230 {
4231 if (buf_size >= 4096)
4232 {
4233 *buf = '\0';
4234 break;
4235 }
4236 buf = xrealloc (buf, buf_size <<= 1);
4237 }
4238 o = variable_buffer_output (o, buf, strlen (buf));
4239 free (buf);
4240 return o;
4241}
4242#endif
4243
4244#ifdef CONFIG_WITH_FILE_SIZE
4245/* Prints the size of the specified file. Only one file is
4246 permitted, notthing is stripped. -1 is returned if stat
4247 fails. */
4248static char *
4249func_file_size (char *o, char **argv, const char *funcname UNUSED)
4250{
4251 struct stat st;
4252 if (stat (argv[0], &st))
4253 return variable_buffer_output (o, "-1", 2);
4254 return math_int_to_variable_buffer (o, st.st_size);
4255}
4256#endif
4257
4258#ifdef CONFIG_WITH_WHICH
4259/* Checks if the specified file exists an is executable.
4260 On systems employing executable extensions, the name may
4261 be modified to include the extension. */
4262static int func_which_test_x (char *file)
4263{
4264 struct stat st;
4265# if defined(WINDOWS32) || defined(__OS2__)
4266 char *ext;
4267 char *slash;
4268
4269 /* fix slashes first. */
4270 slash = file;
4271 while ((slash = strchr (slash, '\\')) != NULL)
4272 *slash++ = '/';
4273
4274 /* straight */
4275 if (stat (file, &st) == 0
4276 && S_ISREG (st.st_mode))
4277 return 1;
4278
4279 /* don't try add an extension if there already is one */
4280 ext = strchr (file, '\0');
4281 if (ext - file >= 4
4282 && ( !stricmp (ext - 4, ".exe")
4283 || !stricmp (ext - 4, ".cmd")
4284 || !stricmp (ext - 4, ".bat")
4285 || !stricmp (ext - 4, ".com")))
4286 return 0;
4287
4288 /* try the extensions. */
4289 strcpy (ext, ".exe");
4290 if (stat (file, &st) == 0
4291 && S_ISREG (st.st_mode))
4292 return 1;
4293
4294 strcpy (ext, ".cmd");
4295 if (stat (file, &st) == 0
4296 && S_ISREG (st.st_mode))
4297 return 1;
4298
4299 strcpy (ext, ".bat");
4300 if (stat (file, &st) == 0
4301 && S_ISREG (st.st_mode))
4302 return 1;
4303
4304 strcpy (ext, ".com");
4305 if (stat (file, &st) == 0
4306 && S_ISREG (st.st_mode))
4307 return 1;
4308
4309 return 0;
4310
4311# else
4312
4313 return access (file, X_OK) == 0
4314 && stat (file, &st) == 0
4315 && S_ISREG (st.st_mode);
4316# endif
4317}
4318
4319/* Searches for the specified programs in the PATH and print
4320 their full location if found. Prints nothing if not found. */
4321static char *
4322func_which (char *o, char **argv, const char *funcname UNUSED)
4323{
4324 const char *path;
4325 struct variable *path_var;
4326 unsigned i;
4327 int first = 1;
4328 PATH_VAR (buf);
4329
4330 path_var = lookup_variable ("PATH", 4);
4331 if (path_var)
4332 path = path_var->value;
4333 else
4334 path = ".";
4335
4336 /* iterate input */
4337 for (i = 0; argv[i]; i++)
4338 {
4339 unsigned int len;
4340 const char *iterator = argv[i];
4341 char *cur;
4342
4343 while ((cur = find_next_token (&iterator, &len)))
4344 {
4345 /* if there is a separator, don't walk the path. */
4346 if (memchr (cur, '/', len)
4347#ifdef HAVE_DOS_PATHS
4348 || memchr (cur, '\\', len)
4349 || memchr (cur, ':', len)
4350#endif
4351 )
4352 {
4353 if (len + 1 + 4 < GET_PATH_MAX) /* +4 for .exe */
4354 {
4355 memcpy (buf, cur, len);
4356 buf[len] = '\0';
4357 if (func_which_test_x (buf))
4358 o = variable_buffer_output (o, buf, strlen (buf));
4359 }
4360 }
4361 else
4362 {
4363 const char *comp = path;
4364 for (;;)
4365 {
4366 const char *src = comp;
4367 const char *end = strchr (comp, PATH_SEPARATOR_CHAR);
4368 size_t src_len = end ? (size_t)(end - comp) : strlen (comp);
4369 if (!src_len)
4370 {
4371 src_len = 1;
4372 src = ".";
4373 }
4374 if (len + src_len + 2 + 4 < GET_PATH_MAX) /* +4 for .exe */
4375 {
4376 memcpy (buf, src, src_len);
4377 buf [src_len] = '/';
4378 memcpy (&buf[src_len + 1], cur, len);
4379 buf[src_len + 1 + len] = '\0';
4380
4381 if (func_which_test_x (buf))
4382 {
4383 if (!first)
4384 o = variable_buffer_output (o, " ", 1);
4385 o = variable_buffer_output (o, buf, strlen (buf));
4386 first = 0;
4387 break;
4388 }
4389 }
4390
4391 /* next */
4392 if (!end)
4393 break;
4394 comp = end + 1;
4395 }
4396 }
4397 }
4398 }
4399
4400 return variable_buffer_output (o, "", 0);
4401}
4402#endif /* CONFIG_WITH_WHICH */
4403
4404#ifdef CONFIG_WITH_IF_CONDITIONALS
4405
4406/* Evaluates the expression given in the argument using the
4407 same evaluator as for the new 'if' statements, except now
4408 we don't force the result into a boolean like for 'if' and
4409 '$(if-expr ,,)'. */
4410static char *
4411func_expr (char *o, char **argv, const char *funcname UNUSED)
4412{
4413 o = expr_eval_to_string (o, argv[0]);
4414 return o;
4415}
4416
4417/* Same as '$(if ,,)' except the first argument is evaluated
4418 using the same evaluator as for the new 'if' statements. */
4419static char *
4420func_if_expr (char *o, char **argv, const char *funcname UNUSED)
4421{
4422 int rc;
4423 char *to_expand;
4424
4425 /* Evaluate the condition in argv[0] and expand the 2nd or
4426 3rd (optional) argument according to the result. */
4427 rc = expr_eval_if_conditionals (argv[0], NULL);
4428 to_expand = rc == 0 ? argv[1] : argv[2];
4429 if (to_expand && *to_expand)
4430 variable_expand_string_2 (o, to_expand, -1, &o);
4431
4432 return o;
4433}
4434
4435/*
4436 $(select when1-cond, when1-body[,whenN-cond, whenN-body]).
4437 */
4438static char *
4439func_select (char *o, char **argv, const char *funcname UNUSED)
4440{
4441 int i;
4442
4443 /* Test WHEN-CONDs until one matches. The check for 'otherwise[:]'
4444 and 'default[:]' make this a bit more fun... */
4445
4446 for (i = 0; argv[i] != NULL; i += 2)
4447 {
4448 const char *cond = argv[i];
4449 int is_otherwise = 0;
4450
4451 if (argv[i + 1] == NULL)
4452 O (fatal, NILF, _("$(select ): not an even argument count\n"));
4453
4454 while (ISSPACE (*cond))
4455 cond++;
4456 if ( (*cond == 'o' && strncmp (cond, "otherwise", 9) == 0)
4457 || (*cond == 'd' && strncmp (cond, "default", 7) == 0))
4458 {
4459 const char *end = cond + (*cond == 'o' ? 9 : 7);
4460 while (ISSPACE (*end))
4461 end++;
4462 if (*end == ':')
4463 do end++;
4464 while (ISSPACE (*end));
4465 is_otherwise = *end == '\0';
4466 }
4467
4468 if ( is_otherwise
4469 || expr_eval_if_conditionals (cond, NULL) == 0 /* true */)
4470 {
4471 variable_expand_string_2 (o, argv[i + 1], -1, &o);
4472 break;
4473 }
4474 }
4475
4476 return o;
4477}
4478
4479#endif /* CONFIG_WITH_IF_CONDITIONALS */
4480
4481#ifdef CONFIG_WITH_SET_CONDITIONALS
4482static char *
4483func_set_intersects (char *o, char **argv, const char *funcname UNUSED)
4484{
4485 const char *s1_cur;
4486 unsigned int s1_len;
4487 const char *s1_iterator = argv[0];
4488
4489 while ((s1_cur = find_next_token (&s1_iterator, &s1_len)) != 0)
4490 {
4491 const char *s2_cur;
4492 unsigned int s2_len;
4493 const char *s2_iterator = argv[1];
4494 while ((s2_cur = find_next_token (&s2_iterator, &s2_len)) != 0)
4495 if (s2_len == s1_len
4496 && strneq (s2_cur, s1_cur, s1_len) )
4497 return variable_buffer_output (o, "1", 1); /* found intersection */
4498 }
4499
4500 return o; /* no intersection */
4501}
4502#endif /* CONFIG_WITH_SET_CONDITIONALS */
4503
4504#ifdef CONFIG_WITH_STACK
4505
4506/* Push an item (string without spaces). */
4507static char *
4508func_stack_push (char *o, char **argv, const char *funcname UNUSED)
4509{
4510 do_variable_definition(NILF, argv[0], argv[1], o_file, f_append, 0 /* !target_var */);
4511 return o;
4512}
4513
4514/* Pops an item off the stack / get the top stack element.
4515 (This is what's tricky to do in pure GNU make syntax.) */
4516static char *
4517func_stack_pop_top (char *o, char **argv, const char *funcname)
4518{
4519 struct variable *stack_var;
4520 const char *stack = argv[0];
4521
4522 stack_var = lookup_variable (stack, strlen (stack) );
4523 if (stack_var)
4524 {
4525 unsigned int len;
4526 const char *iterator = stack_var->value;
4527 char *lastitem = NULL;
4528 char *cur;
4529
4530 while ((cur = find_next_token (&iterator, &len)))
4531 lastitem = cur;
4532
4533 if (lastitem != NULL)
4534 {
4535 if (strcmp (funcname, "stack-popv") != 0)
4536 o = variable_buffer_output (o, lastitem, len);
4537 if (strcmp (funcname, "stack-top") != 0)
4538 {
4539 *lastitem = '\0';
4540 while (lastitem > stack_var->value && ISSPACE (lastitem[-1]))
4541 *--lastitem = '\0';
4542#ifdef CONFIG_WITH_VALUE_LENGTH
4543 stack_var->value_length = lastitem - stack_var->value;
4544#endif
4545 VARIABLE_CHANGED (stack_var);
4546 }
4547 }
4548 }
4549 return o;
4550}
4551#endif /* CONFIG_WITH_STACK */
4552
4553#if defined (CONFIG_WITH_MATH) || defined (CONFIG_WITH_NANOTS) || defined (CONFIG_WITH_FILE_SIZE)
4554/* outputs the number (as a string) into the variable buffer. */
4555static char *
4556math_int_to_variable_buffer (char *o, math_int num)
4557{
4558 static const char xdigits[17] = "0123456789abcdef";
4559 int negative;
4560 char strbuf[24]; /* 16 hex + 2 prefix + sign + term => 20
4561 or 20 dec + sign + term => 22 */
4562 char *str = &strbuf[sizeof (strbuf) - 1];
4563
4564 negative = num < 0;
4565 if (negative)
4566 num = -num;
4567
4568 *str = '\0';
4569
4570 do
4571 {
4572#ifdef HEX_MATH_NUMBERS
4573 *--str = xdigits[num & 0xf];
4574 num >>= 4;
4575#else
4576 *--str = xdigits[num % 10];
4577 num /= 10;
4578#endif
4579 }
4580 while (num);
4581
4582#ifdef HEX_MATH_NUMBERS
4583 *--str = 'x';
4584 *--str = '0';
4585#endif
4586
4587 if (negative)
4588 *--str = '-';
4589
4590 return variable_buffer_output (o, str, &strbuf[sizeof (strbuf) - 1] - str);
4591}
4592#endif /* CONFIG_WITH_MATH || CONFIG_WITH_NANOTS */
4593
4594#ifdef CONFIG_WITH_MATH
4595
4596/* Converts a string to an integer, causes an error if the format is invalid. */
4597static math_int
4598math_int_from_string (const char *str)
4599{
4600 const char *start;
4601 unsigned base = 0;
4602 int negative = 0;
4603 math_int num = 0;
4604
4605 /* strip spaces */
4606 while (ISSPACE (*str))
4607 str++;
4608 if (!*str)
4609 {
4610 O (error, NILF, _("bad number: empty\n"));
4611 return 0;
4612 }
4613 start = str;
4614
4615 /* check for +/- */
4616 while (*str == '+' || *str == '-' || ISSPACE (*str))
4617 if (*str++ == '-')
4618 negative = !negative;
4619
4620 /* check for prefix - we do not accept octal numbers, sorry. */
4621 if (*str == '0' && (str[1] == 'x' || str[1] == 'X'))
4622 {
4623 base = 16;
4624 str += 2;
4625 }
4626 else
4627 {
4628 /* look for a hex digit, if not found treat it as decimal */
4629 const char *p2 = str;
4630 for ( ; *p2; p2++)
4631 if (isxdigit (*p2) && !isdigit (*p2) && isascii (*p2) )
4632 {
4633 base = 16;
4634 break;
4635 }
4636 if (base == 0)
4637 base = 10;
4638 }
4639
4640 /* must have at least one digit! */
4641 if ( !isascii (*str)
4642 || !(base == 16 ? isxdigit (*str) : isdigit (*str)) )
4643 {
4644 OS (error, NILF, _("bad number: '%s'\n"), start);
4645 return 0;
4646 }
4647
4648 /* convert it! */
4649 while (*str && !ISSPACE (*str))
4650 {
4651 int ch = *str++;
4652 if (ch >= '0' && ch <= '9')
4653 ch -= '0';
4654 else if (base == 16 && ch >= 'a' && ch <= 'f')
4655 ch -= 'a' - 10;
4656 else if (base == 16 && ch >= 'A' && ch <= 'F')
4657 ch -= 'A' - 10;
4658 else
4659 {
4660 OSNN (error, NILF, _("bad number: '%s' (base=%u, pos=%lu)\n"), start, base, (unsigned long)(str - start));
4661 return 0;
4662 }
4663 num *= base;
4664 num += ch;
4665 }
4666
4667 /* check trailing spaces. */
4668 while (ISSPACE (*str))
4669 str++;
4670 if (*str)
4671 {
4672 OS (error, NILF, _("bad number: '%s'\n"), start);
4673 return 0;
4674 }
4675
4676 return negative ? -num : num;
4677}
4678
4679/* Add two or more integer numbers. */
4680static char *
4681func_int_add (char *o, char **argv, const char *funcname UNUSED)
4682{
4683 math_int num;
4684 int i;
4685
4686 num = math_int_from_string (argv[0]);
4687 for (i = 1; argv[i]; i++)
4688 num += math_int_from_string (argv[i]);
4689
4690 return math_int_to_variable_buffer (o, num);
4691}
4692
4693/* Subtract two or more integer numbers. */
4694static char *
4695func_int_sub (char *o, char **argv, const char *funcname UNUSED)
4696{
4697 math_int num;
4698 int i;
4699
4700 num = math_int_from_string (argv[0]);
4701 for (i = 1; argv[i]; i++)
4702 num -= math_int_from_string (argv[i]);
4703
4704 return math_int_to_variable_buffer (o, num);
4705}
4706
4707/* Multiply two or more integer numbers. */
4708static char *
4709func_int_mul (char *o, char **argv, const char *funcname UNUSED)
4710{
4711 math_int num;
4712 int i;
4713
4714 num = math_int_from_string (argv[0]);
4715 for (i = 1; argv[i]; i++)
4716 num *= math_int_from_string (argv[i]);
4717
4718 return math_int_to_variable_buffer (o, num);
4719}
4720
4721/* Divide an integer number by one or more divisors. */
4722static char *
4723func_int_div (char *o, char **argv, const char *funcname UNUSED)
4724{
4725 math_int num;
4726 math_int divisor;
4727 int i;
4728
4729 num = math_int_from_string (argv[0]);
4730 for (i = 1; argv[i]; i++)
4731 {
4732 divisor = math_int_from_string (argv[i]);
4733 if (!divisor)
4734 {
4735 OS (error, NILF, _("divide by zero ('%s')\n"), argv[i]);
4736 return math_int_to_variable_buffer (o, 0);
4737 }
4738 num /= divisor;
4739 }
4740
4741 return math_int_to_variable_buffer (o, num);
4742}
4743
4744
4745/* Divide and return the remainder. */
4746static char *
4747func_int_mod (char *o, char **argv, const char *funcname UNUSED)
4748{
4749 math_int num;
4750 math_int divisor;
4751
4752 num = math_int_from_string (argv[0]);
4753 divisor = math_int_from_string (argv[1]);
4754 if (!divisor)
4755 {
4756 OS (error, NILF, _("divide by zero ('%s')\n"), argv[1]);
4757 return math_int_to_variable_buffer (o, 0);
4758 }
4759 num %= divisor;
4760
4761 return math_int_to_variable_buffer (o, num);
4762}
4763
4764/* 2-complement. */
4765static char *
4766func_int_not (char *o, char **argv, const char *funcname UNUSED)
4767{
4768 math_int num;
4769
4770 num = math_int_from_string (argv[0]);
4771 num = ~num;
4772
4773 return math_int_to_variable_buffer (o, num);
4774}
4775
4776/* Bitwise AND (two or more numbers). */
4777static char *
4778func_int_and (char *o, char **argv, const char *funcname UNUSED)
4779{
4780 math_int num;
4781 int i;
4782
4783 num = math_int_from_string (argv[0]);
4784 for (i = 1; argv[i]; i++)
4785 num &= math_int_from_string (argv[i]);
4786
4787 return math_int_to_variable_buffer (o, num);
4788}
4789
4790/* Bitwise OR (two or more numbers). */
4791static char *
4792func_int_or (char *o, char **argv, const char *funcname UNUSED)
4793{
4794 math_int num;
4795 int i;
4796
4797 num = math_int_from_string (argv[0]);
4798 for (i = 1; argv[i]; i++)
4799 num |= math_int_from_string (argv[i]);
4800
4801 return math_int_to_variable_buffer (o, num);
4802}
4803
4804/* Bitwise XOR (two or more numbers). */
4805static char *
4806func_int_xor (char *o, char **argv, const char *funcname UNUSED)
4807{
4808 math_int num;
4809 int i;
4810
4811 num = math_int_from_string (argv[0]);
4812 for (i = 1; argv[i]; i++)
4813 num ^= math_int_from_string (argv[i]);
4814
4815 return math_int_to_variable_buffer (o, num);
4816}
4817
4818/* Compare two integer numbers. Returns make boolean (true="1"; false=""). */
4819static char *
4820func_int_cmp (char *o, char **argv, const char *funcname)
4821{
4822 math_int num1;
4823 math_int num2;
4824 int rc;
4825
4826 num1 = math_int_from_string (argv[0]);
4827 num2 = math_int_from_string (argv[1]);
4828
4829 funcname += sizeof ("int-") - 1;
4830 if (!strcmp (funcname, "eq"))
4831 rc = num1 == num2;
4832 else if (!strcmp (funcname, "ne"))
4833 rc = num1 != num2;
4834 else if (!strcmp (funcname, "gt"))
4835 rc = num1 > num2;
4836 else if (!strcmp (funcname, "ge"))
4837 rc = num1 >= num2;
4838 else if (!strcmp (funcname, "lt"))
4839 rc = num1 < num2;
4840 else /*if (!strcmp (funcname, "le"))*/
4841 rc = num1 <= num2;
4842
4843 return variable_buffer_output (o, rc ? "1" : "", rc);
4844}
4845
4846#endif /* CONFIG_WITH_MATH */
4847
4848#ifdef CONFIG_WITH_NANOTS
4849/* Returns the current timestamp as nano seconds. The time
4850 source is a high res monotone one if the platform provides
4851 this (and we know about it).
4852
4853 Tip. Use this with int-sub to profile makefile reading
4854 and similar. */
4855static char *
4856func_nanots (char *o, char **argv UNUSED, const char *funcname UNUSED)
4857{
4858 return math_int_to_variable_buffer (o, nano_timestamp ());
4859}
4860#endif
4861
4862#ifdef CONFIG_WITH_OS2_LIBPATH
4863/* Sets or gets the OS/2 libpath variables.
4864
4865 The first argument indicates which variable - BEGINLIBPATH,
4866 ENDLIBPATH, LIBPATHSTRICT or LIBPATH.
4867
4868 The second indicates whether this is a get (not present) or
4869 set (present) operation. When present it is the new value for
4870 the variable. */
4871static char *
4872func_os2_libpath (char *o, char **argv, const char *funcname UNUSED)
4873{
4874 char buf[4096];
4875 ULONG fVar;
4876 APIRET rc;
4877
4878 /* translate variable name (first arg) */
4879 if (!strcmp (argv[0], "BEGINLIBPATH"))
4880 fVar = BEGIN_LIBPATH;
4881 else if (!strcmp (argv[0], "ENDLIBPATH"))
4882 fVar = END_LIBPATH;
4883 else if (!strcmp (argv[0], "LIBPATHSTRICT"))
4884 fVar = LIBPATHSTRICT;
4885 else if (!strcmp (argv[0], "LIBPATH"))
4886 fVar = 0;
4887 else
4888 {
4889 OS (error, NILF, _("$(libpath): unknown variable `%s'"), argv[0]);
4890 return variable_buffer_output (o, "", 0);
4891 }
4892
4893 if (!argv[1])
4894 {
4895 /* get the variable value. */
4896 if (fVar != 0)
4897 {
4898 buf[0] = buf[1] = buf[2] = buf[3] = '\0';
4899 rc = DosQueryExtLIBPATH (buf, fVar);
4900 }
4901 else
4902 rc = DosQueryHeaderInfo (NULLHANDLE, 0, buf, sizeof(buf), QHINF_LIBPATH);
4903 if (rc != NO_ERROR)
4904 {
4905 OSN (error, NILF, _("$(libpath): failed to query `%s', rc=%d"), argv[0], rc);
4906 return variable_buffer_output (o, "", 0);
4907 }
4908 o = variable_buffer_output (o, buf, strlen (buf));
4909 }
4910 else
4911 {
4912 /* set the variable value. */
4913 size_t len;
4914 size_t len_max = sizeof (buf) < 2048 ? sizeof (buf) : 2048;
4915 const char *val;
4916 const char *end;
4917
4918 if (fVar == 0)
4919 {
4920 O (error, NILF, _("$(libpath): LIBPATH is read-only"));
4921 return variable_buffer_output (o, "", 0);
4922 }
4923
4924 /* strip leading and trailing spaces and check for max length. */
4925 val = argv[1];
4926 while (ISSPACE (*val))
4927 val++;
4928 end = strchr (val, '\0');
4929 while (end > val && ISSPACE (end[-1]))
4930 end--;
4931
4932 len = end - val;
4933 if (len >= len_max)
4934 {
4935 OSNN (error, NILF, _("$(libpath): The new `%s' value is too long (%d bytes, max %d)"),
4936 argv[0], len, len_max);
4937 return variable_buffer_output (o, "", 0);
4938 }
4939
4940 /* make a stripped copy in low memory and try set it. */
4941 memcpy (buf, val, len);
4942 buf[len] = '\0';
4943 rc = DosSetExtLIBPATH (buf, fVar);
4944 if (rc != NO_ERROR)
4945 {
4946 OSSN (error, NILF, _("$(libpath): failed to set `%s' to `%s', rc=%d"), argv[0], buf, rc);
4947 return variable_buffer_output (o, "", 0);
4948 }
4949
4950 o = variable_buffer_output (o, "", 0);
4951 }
4952 return o;
4953}
4954#endif /* CONFIG_WITH_OS2_LIBPATH */
4955
4956#if defined (CONFIG_WITH_MAKE_STATS) || defined (CONFIG_WITH_MINIMAL_STATS)
4957/* Retrieve make statistics. */
4958static char *
4959func_make_stats (char *o, char **argv, const char *funcname UNUSED)
4960{
4961 char buf[512];
4962 int len;
4963
4964 if (!argv[0] || (!argv[0][0] && !argv[1]))
4965 {
4966# ifdef CONFIG_WITH_MAKE_STATS
4967 len = sprintf (buf, "alloc-cur: %5ld/%3ld %3luMB hash: %5lu %2lu%%",
4968 make_stats_allocations,
4969 make_stats_reallocations,
4970 make_stats_allocated / (1024*1024),
4971 make_stats_ht_lookups,
4972 (make_stats_ht_collisions * 100) / make_stats_ht_lookups);
4973 o = variable_buffer_output (o, buf, len);
4974#endif
4975 }
4976 else
4977 {
4978 /* selective */
4979 int i;
4980 for (i = 0; argv[i]; i++)
4981 {
4982 unsigned long val;
4983 if (i != 0)
4984 o = variable_buffer_output (o, " ", 1);
4985 if (0)
4986 continue;
4987# ifdef CONFIG_WITH_MAKE_STATS
4988 else if (!strcmp(argv[i], "allocations"))
4989 val = make_stats_allocations;
4990 else if (!strcmp(argv[i], "reallocations"))
4991 val = make_stats_reallocations;
4992 else if (!strcmp(argv[i], "allocated"))
4993 val = make_stats_allocated;
4994 else if (!strcmp(argv[i], "ht_lookups"))
4995 val = make_stats_ht_lookups;
4996 else if (!strcmp(argv[i], "ht_collisions"))
4997 val = make_stats_ht_collisions;
4998 else if (!strcmp(argv[i], "ht_collisions_pct"))
4999 val = (make_stats_ht_collisions * 100) / make_stats_ht_lookups;
5000#endif
5001 else
5002 {
5003 o = variable_buffer_output (o, argv[i], strlen (argv[i]));
5004 continue;
5005 }
5006
5007 len = sprintf (buf, "%ld", val);
5008 o = variable_buffer_output (o, buf, len);
5009 }
5010 }
5011
5012 return o;
5013}
5014#endif /* CONFIG_WITH_MAKE_STATS */
5015
5016#ifdef CONFIG_WITH_COMMANDS_FUNC
5017/* Gets all the commands for a target, separated by newlines.
5018
5019 This is useful when creating and checking target dependencies since
5020 it reduces the amount of work and the memory consuption. A new prefix
5021 character '%' has been introduced for skipping certain lines, like
5022 for instance the one calling this function and pushing to a dep file.
5023 Blank lines are also skipped.
5024
5025 The commands function takes exactly one argument, which is the name of
5026 the target which commands should be returned.
5027
5028 The commands-sc is identical to commands except that it uses a ';' to
5029 separate the commands.
5030
5031 The commands-usr is similar to commands except that it takes a 2nd
5032 argument that is used to separate the commands. */
5033char *
5034func_commands (char *o, char **argv, const char *funcname)
5035{
5036 struct file *file;
5037 static int recursive = 0;
5038
5039 if (recursive)
5040 {
5041 OS (error, reading_file, _("$(%s ) was invoked recursivly"), funcname);
5042 return variable_buffer_output (o, "recursive", sizeof ("recursive") - 1);
5043 }
5044 if (*argv[0] == '\0')
5045 {
5046 OS (error, reading_file, _("$(%s ) was invoked with an empty target name"), funcname);
5047 return o;
5048 }
5049 recursive = 1;
5050
5051 file = lookup_file (argv[0]);
5052 if (file && file->cmds)
5053 {
5054 unsigned int i;
5055 int cmd_sep_len;
5056 struct commands *cmds = file->cmds;
5057 const char *cmd_sep;
5058
5059 if (!strcmp (funcname, "commands"))
5060 {
5061 cmd_sep = "\n";
5062 cmd_sep_len = 1;
5063 }
5064 else if (!strcmp (funcname, "commands-sc"))
5065 {
5066 cmd_sep = ";";
5067 cmd_sep_len = 1;
5068 }
5069 else /*if (!strcmp (funcname, "commands-usr"))*/
5070 {
5071 cmd_sep = argv[1];
5072 cmd_sep_len = strlen (cmd_sep);
5073 }
5074
5075 initialize_file_variables (file, 1 /* don't search for pattern vars */);
5076 set_file_variables (file, 1 /* early call */);
5077 chop_commands (cmds);
5078
5079 for (i = 0; i < cmds->ncommand_lines; i++)
5080 {
5081 char *p;
5082 char *in, *out, *ref;
5083
5084 /* Skip it if it has a '%' prefix or is blank. */
5085 if (cmds->lines_flags[i] & COMMAND_GETTER_SKIP_IT)
5086 continue;
5087 p = cmds->command_lines[i];
5088 while (ISBLANK (*p))
5089 p++;
5090 if (*p == '\0')
5091 continue;
5092
5093 /* --- copied from new_job() in job.c --- */
5094
5095 /* Collapse backslash-newline combinations that are inside variable
5096 or function references. These are left alone by the parser so
5097 that they will appear in the echoing of commands (where they look
5098 nice); and collapsed by construct_command_argv when it tokenizes.
5099 But letting them survive inside function invocations loses because
5100 we don't want the functions to see them as part of the text. */
5101
5102 /* IN points to where in the line we are scanning.
5103 OUT points to where in the line we are writing.
5104 When we collapse a backslash-newline combination,
5105 IN gets ahead of OUT. */
5106
5107 in = out = p;
5108 while ((ref = strchr (in, '$')) != 0)
5109 {
5110 ++ref; /* Move past the $. */
5111
5112 if (out != in)
5113 /* Copy the text between the end of the last chunk
5114 we processed (where IN points) and the new chunk
5115 we are about to process (where REF points). */
5116 memmove (out, in, ref - in);
5117
5118 /* Move both pointers past the boring stuff. */
5119 out += ref - in;
5120 in = ref;
5121
5122 if (*ref == '(' || *ref == '{')
5123 {
5124 char openparen = *ref;
5125 char closeparen = openparen == '(' ? ')' : '}';
5126 int count;
5127 char *p2;
5128
5129 *out++ = *in++; /* Copy OPENPAREN. */
5130 /* IN now points past the opening paren or brace.
5131 Count parens or braces until it is matched. */
5132 count = 0;
5133 while (*in != '\0')
5134 {
5135 if (*in == closeparen && --count < 0)
5136 break;
5137 else if (*in == '\\' && in[1] == '\n')
5138 {
5139 /* We have found a backslash-newline inside a
5140 variable or function reference. Eat it and
5141 any following whitespace. */
5142
5143 int quoted = 0;
5144 for (p2 = in - 1; p2 > ref && *p2 == '\\'; --p2)
5145 quoted = !quoted;
5146
5147 if (quoted)
5148 /* There were two or more backslashes, so this is
5149 not really a continuation line. We don't collapse
5150 the quoting backslashes here as is done in
5151 collapse_continuations, because the line will
5152 be collapsed again after expansion. */
5153 *out++ = *in++;
5154 else
5155 {
5156 /* Skip the backslash, newline and
5157 any following whitespace. */
5158 in = next_token (in + 2);
5159
5160 /* Discard any preceding whitespace that has
5161 already been written to the output. */
5162 while (out > ref
5163 && ISBLANK (out[-1]))
5164 --out;
5165
5166 /* Replace it all with a single space. */
5167 *out++ = ' ';
5168 }
5169 }
5170 else
5171 {
5172 if (*in == openparen)
5173 ++count;
5174
5175 *out++ = *in++;
5176 }
5177 }
5178 }
5179 /* Some of these can be amended ($< perhaps), but we're likely to be called while the
5180 dep expansion happens, so it would have to be on a hackish basis. sad... */
5181 else if (*ref == '<' || *ref == '*' || *ref == '%' || *ref == '^' || *ref == '+')
5182 OSN (error, reading_file, _("$(%s ) does not work reliably with $%c in all cases"), funcname, *ref);
5183 }
5184
5185 /* There are no more references in this line to worry about.
5186 Copy the remaining uninteresting text to the output. */
5187 if (out != in)
5188 strcpy (out, in);
5189
5190 /* --- copied from new_job() in job.c --- */
5191
5192 /* Finally, expand the line. */
5193 if (i)
5194 o = variable_buffer_output (o, cmd_sep, cmd_sep_len);
5195 o = variable_expand_for_file_2 (o, cmds->command_lines[i], ~0U, file, NULL);
5196
5197 /* Skip it if it has a '%' prefix or is blank. */
5198 p = o;
5199 while (ISBLANK (*o)
5200 || *o == '@'
5201 || *o == '-'
5202 || *o == '+')
5203 o++;
5204 if (*o != '\0' && *o != '%')
5205 o = strchr (o, '\0');
5206 else if (i)
5207 o = p - cmd_sep_len;
5208 else
5209 o = p;
5210 } /* for each command line */
5211 }
5212 /* else FIXME: bitch about it? */
5213
5214 recursive = 0;
5215 return o;
5216}
5217#endif /* CONFIG_WITH_COMMANDS_FUNC */
5218#ifdef KMK
5219
5220/* Useful when debugging kmk and/or makefiles. */
5221char *
5222func_breakpoint (char *o, char **argv UNUSED, const char *funcname UNUSED)
5223{
5224#ifdef _MSC_VER
5225 __debugbreak();
5226#elif defined(__i386__) || defined(__x86__) || defined(__X86__) || defined(_M_IX86) || defined(__i386) \
5227 || defined(__amd64__) || defined(__x86_64__) || defined(__AMD64__) || defined(_M_X64) || defined(__amd64)
5228# ifdef __sun__
5229 __asm__ __volatile__ ("int $3\n\t");
5230# else
5231 __asm__ __volatile__ ("int3\n\t");
5232# endif
5233#else
5234 char *p = (char *)0;
5235 *p = '\0';
5236#endif
5237 return o;
5238}
5239
5240/* umask | umask -S. */
5241char *
5242func_get_umask (char *o, char **argv UNUSED, const char *funcname UNUSED)
5243{
5244 char sz[80];
5245 int off;
5246 mode_t u;
5247 int symbolic = 0;
5248 const char *psz = argv[0];
5249
5250 if (psz)
5251 {
5252 const char *pszEnd = strchr (psz, '\0');
5253 strip_whitespace (&psz, &pszEnd);
5254
5255 if (pszEnd != psz)
5256 {
5257 if ( STR_N_EQUALS (psz, pszEnd - pszEnd, "S")
5258 || STR_N_EQUALS (psz, pszEnd - pszEnd, "-S")
5259 || STR_N_EQUALS (psz, pszEnd - pszEnd, "symbolic") )
5260 symbolic = 1;
5261 else
5262 OSS (error, reading_file, _("$(%s ) invalid argument `%s'"),
5263 funcname, argv[0]);
5264 }
5265 }
5266
5267 u = g_fUMask;
5268 assert (u == umask (g_fUMask));
5269
5270 if (symbolic)
5271 {
5272 off = 0;
5273 sz[off++] = 'u';
5274 sz[off++] = '=';
5275 if ((u & S_IRUSR) == 0)
5276 sz[off++] = 'r';
5277 if ((u & S_IWUSR) == 0)
5278 sz[off++] = 'w';
5279 if ((u & S_IXUSR) == 0)
5280 sz[off++] = 'x';
5281 sz[off++] = ',';
5282 sz[off++] = 'g';
5283 sz[off++] = '=';
5284 if ((u & S_IRGRP) == 0)
5285 sz[off++] = 'r';
5286 if ((u & S_IWGRP) == 0)
5287 sz[off++] = 'w';
5288 if ((u & S_IXGRP) == 0)
5289 sz[off++] = 'x';
5290 sz[off++] = ',';
5291 sz[off++] = 'o';
5292 sz[off++] = '=';
5293 if ((u & S_IROTH) == 0)
5294 sz[off++] = 'r';
5295 if ((u & S_IWOTH) == 0)
5296 sz[off++] = 'w';
5297 if ((u & S_IXOTH) == 0)
5298 sz[off++] = 'x';
5299 }
5300 else
5301 off = sprintf (sz, "%.4o", u);
5302
5303 return variable_buffer_output (o, sz, off);
5304}
5305
5306
5307/* umask 0002 | umask u=rwx,g=rwx,o=rx. */
5308char *
5309func_set_umask (char *o, char **argv UNUSED, const char *funcname UNUSED)
5310{
5311 mode_t u;
5312 const char *psz;
5313
5314 /* Figure what kind of input this is. */
5315 psz = argv[0];
5316 while (ISBLANK (*psz))
5317 psz++;
5318
5319 if (isdigit ((unsigned char)*psz))
5320 {
5321 u = 0;
5322 while (*psz)
5323 {
5324 u <<= 3;
5325 if (*psz < '0' || *psz >= '8')
5326 {
5327 OSS (error, reading_file, _("$(%s ) illegal number `%s'"), funcname, argv[0]);
5328 break;
5329 }
5330 u += *psz - '0';
5331 psz++;
5332 }
5333
5334 if (argv[1] != NULL)
5335 OS (error, reading_file, _("$(%s ) too many arguments for octal mode"), funcname);
5336
5337 umask (u);
5338 g_fUMask = u;
5339 }
5340 else
5341 {
5342 OS (error, reading_file, _("$(%s ) symbol mode is not implemented"), funcname);
5343 }
5344
5345 return o;
5346}
5347
5348
5349/* Controls the cache in dir-bird-nt.c. */
5350
5351char *
5352func_dircache_ctl (char *o, char **argv UNUSED, const char *funcname UNUSED)
5353{
5354# ifdef KBUILD_OS_WINDOWS
5355 const char *cmd = argv[0];
5356 while (ISBLANK (*cmd))
5357 cmd++;
5358 if (strcmp (cmd, "invalidate") == 0)
5359 {
5360 if (argv[1] != NULL)
5361 O (error, reading_file, "$(dircache-ctl invalidate) takes no parameters");
5362 dir_cache_invalid_all ();
5363 }
5364 else if (strcmp (cmd, "invalidate-and-close-dirs") == 0)
5365 {
5366 if (argv[1] != NULL)
5367 O (error, reading_file, "$(dircache-ctl invalidate) takes no parameters");
5368 dir_cache_invalid_all_and_close_dirs (0 /*including_root*/);
5369 }
5370 else if (strcmp (cmd, "invalidate-missing") == 0)
5371 {
5372 if (argv[1] != NULL)
5373 O (error, reading_file, "$(dircache-ctl invalidate-missing) takes no parameters");
5374 dir_cache_invalid_missing ();
5375 }
5376 else if (strcmp (cmd, "volatile") == 0)
5377 {
5378 size_t i;
5379 for (i = 1; argv[i] != NULL; i++)
5380 {
5381 const char *dir = argv[i];
5382 while (ISBLANK (*dir))
5383 dir++;
5384 if (*dir)
5385 dir_cache_volatile_dir (dir);
5386 }
5387 }
5388 else if (strcmp (cmd, "deleted") == 0)
5389 {
5390 size_t i;
5391 for (i = 1; argv[i] != NULL; i++)
5392 {
5393 const char *dir = argv[i];
5394 while (ISBLANK (*dir))
5395 dir++;
5396 if (*dir)
5397 dir_cache_deleted_directory (dir);
5398 }
5399 }
5400 else
5401 OS (error, reading_file, "Unknown $(dircache-ctl ) command: '%s'", cmd);
5402# endif
5403 return o;
5404}
5405
5406/* Helper for performer GNU make style quoting of one filename. */
5407
5408static char *
5409helper_quote_make (char *o, const char *name, size_t len, int is_dep,
5410 int is_tgt, int quote_trailing_slashes,
5411 const char *funcname)
5412{
5413 unsigned const map_flags = MAP_BLANK
5414 | MAP_NEWLINE
5415 | MAP_COMMENT
5416 | MAP_VARIABLE
5417 | MAP_SEMI
5418 | MAP_EQUALS
5419 | (is_dep ? MAP_PIPE :
5420 is_tgt ? MAP_COLON : 0);
5421 const char *cur = name;
5422 assert (memchr (name, '\0', len) == NULL);
5423 if (len > 0)
5424 {
5425 const char * const end = &name[len];
5426 unsigned long len_out = 0;
5427 const char *prev = cur;
5428 do
5429 {
5430 char ch = *cur;
5431 unsigned int flags = stopchar_map[(unsigned int)ch] & map_flags;
5432 if (!flags)
5433 cur++; /* likely */
5434 else
5435 {
5436 /* Flush pending output. */
5437 if (prev != cur)
5438 {
5439 o = variable_buffer_output (o, prev, cur - prev);
5440 len_out += cur - prev;
5441 }
5442
5443 /* Dollar is quoted by duplicating the dollar: */
5444 if (flags & MAP_VARIABLE)
5445 {
5446 o = variable_buffer_output (o, "$", 1);
5447 prev = cur++;
5448 }
5449 /* The rest is quoted by '\': */
5450 else
5451 {
5452 size_t const max_slashes = cur - prev;
5453 size_t slashes = 0;
5454 while (slashes < max_slashes && cur[1 - slashes] == '\\')
5455 slashes++;
5456 if (slashes)
5457 {
5458 o = variable_buffer_output (o, &cur[0 - slashes], slashes);
5459 len_out += slashes;
5460 }
5461 o = variable_buffer_output (o, "\\", 1);
5462 prev = cur++;
5463 }
5464 }
5465 }
5466 while ((uintptr_t)cur < (uintptr_t)end);
5467
5468 /* Flush pending output. */
5469 if (prev != cur)
5470 {
5471 o = variable_buffer_output (o, prev, cur - prev);
5472 len_out += cur - prev;
5473 }
5474
5475 /* Escape trailing slashes when needed. */
5476 if ( o[-1] == '\\'
5477 && quote_trailing_slashes)
5478 {
5479 size_t slashes = 1;
5480 while (slashes < len_out && o[-1 - slashes] == '\\')
5481 slashes++;
5482 while (slashes-- > 0)
5483 o = variable_buffer_output (o, "\\", 1);
5484 }
5485 }
5486 else
5487 OS (error, reading_file, "%s: cannot quote empty string", funcname);
5488 return o;
5489}
5490
5491/* Helper for func_quote_make that checks if there are more arguments
5492 that produces output or not. */
5493
5494static int func_quote_make_has_more_non_empty_args (char **argv)
5495{
5496 for (;;)
5497 {
5498 char *arg = *argv;
5499 if (!arg)
5500 return 0;
5501 if (*arg)
5502 return 1;
5503 argv++;
5504 }
5505}
5506
5507/* Takes zero or more plain strings and escapes (quotes) spaces and other
5508 problematic characters, GNU make style.
5509
5510 There is one slightly problematic aspect of using this, if the input ends
5511 with backslashes whether or not they will be reduced or taken as-is depends
5512 on whether they appear at the end of a line or not. They are taken as-is
5513 when at the end of a line, otherwise they'll be subject to unescaping
5514 (unquoting) and reduced by half.
5515
5516 In addition, the quoting style differs for files on the left side and
5517 right side of the recipe colon. Colons aren't escaped are only escaped
5518 on the left side (target), and the pipe character is only escaped on the
5519 right side (deps).
5520
5521 For this reason there are four variants of this function. */
5522
5523static char *func_quote_make (char *o, char **argv, const char *funcname)
5524{
5525 int const is_dep = funcname[5] == '-' && funcname[6] == 'd';
5526 int const is_tgt = funcname[5] == '-' && funcname[6] == 't';
5527 int const quote_trailing_slashes = funcname[5] == '\0' || funcname[9] == '\0';
5528 char * const o_initial = o;
5529 int i;
5530
5531 assert ( quote_trailing_slashes
5532 == (!strcmp (funcname, "quote") || !strcmp (funcname, "quote-dep") || !strcmp (funcname, "quote-tgt")));
5533 assert (is_dep == !strncmp (funcname, "quote-dep", sizeof ("quote-dep") - 1));
5534 assert (is_tgt == !strncmp (funcname, "quote-tgt", sizeof ("quote-tgt") - 1));
5535
5536 for (i = 0; argv[i]; i++)
5537 {
5538 char *arg = argv[i];
5539 if (*arg)
5540 {
5541 /* Add space separator. */
5542 if (o != o_initial)
5543 o = variable_buffer_output (o, " ", 1);
5544
5545 /* Output the quoted argument: */
5546 if (quote_trailing_slashes)
5547 o = helper_quote_make (o, arg, strlen (arg), is_dep, is_tgt,
5548 quote_trailing_slashes, funcname);
5549 else
5550 {
5551 char *end = strchr (arg, '\0');
5552 int qts = end != arg && end[-1] == '\\'
5553 && func_quote_make_has_more_non_empty_args (&argv[i + 1]);
5554 o = helper_quote_make (o, arg, strlen (arg), is_dep, is_tgt,
5555 qts, funcname);
5556 }
5557 }
5558 else
5559 OS (error, reading_file, "%s: cannot munge empty string", funcname);
5560 }
5561
5562 return o;
5563}
5564
5565/* Worker for func_quote_shell() for escaping a string that's inside
5566 double quotes. */
5567
5568static char *func_escape_shell_in_dq (char *o, const char *arg, size_t len)
5569{
5570 const char *prev = arg;
5571 while (len-- > 0)
5572 {
5573 char const ch = *arg;
5574 switch (ch)
5575 {
5576 default:
5577 arg++;
5578 break;
5579 case '!':
5580 case '$':
5581 case '`':
5582 case '"':
5583 case '\\':
5584 case '\n':
5585 if (prev != arg)
5586 o = variable_buffer_output (o, prev, arg - prev);
5587 o = variable_buffer_output (o, "\\", 1);
5588 prev = arg;
5589 arg++;
5590 break;
5591 }
5592 }
5593 if (prev != arg)
5594 o = variable_buffer_output (o, prev, arg - prev);
5595 return o;
5596}
5597
5598/* quote-sh-dq */
5599
5600static char *func_quote_shell_dq (char *o, char **argv, const char *funcname UNUSED)
5601{
5602 return func_escape_shell_in_dq (o, argv[0], strlen (argv[0]));
5603}
5604
5605
5606/* Worker for func_quote_shell() for escaping a string that's inside
5607 single quotes. */
5608
5609static char *func_escape_shell_in_sq (char *o, const char *arg, size_t len)
5610{
5611 while (len > 0)
5612 {
5613 char *sq = memchr (arg, '\'', len);
5614 if (!sq)
5615 return variable_buffer_output (o, arg, len);
5616 if (sq != arg)
5617 o = variable_buffer_output (o, arg, sq - arg);
5618 o = variable_buffer_output (o, "'\\''", 4);
5619
5620 /* advance */
5621 sq++;
5622 len -= sq - arg;
5623 arg = sq;
5624 }
5625 return o;
5626}
5627
5628/* quote-sh-dq */
5629
5630static char *func_quote_shell_sq (char *o, char **argv, const char *funcname UNUSED)
5631{
5632 return func_escape_shell_in_sq (o, argv[0], strlen (argv[0]));
5633}
5634
5635/* Output a shell argument with quoting as needed. */
5636static char *helper_quote_shell (char *o, const char *arg, size_t len,
5637 int leading_space)
5638{
5639 if ( memchr (arg, '$', len) != NULL
5640 || memchr (arg, '*', len) != NULL
5641 || memchr (arg, '?', len) != NULL
5642 || memchr (arg, '[', len) != NULL)
5643 {
5644 if (leading_space)
5645 o = variable_buffer_output (o, " '", 2);
5646 else
5647 o = variable_buffer_output (o, "'", 1);
5648 o = func_escape_shell_in_sq (o, arg, len);
5649 o = variable_buffer_output (o, "'", 1);
5650 }
5651 else if ( memchr (arg, ' ', len) != NULL
5652 || memchr (arg, '\t', len) != NULL
5653 || memchr (arg, '\\', len) != NULL
5654 || memchr (arg, '"', len) != NULL
5655 || memchr (arg, '`', len) != NULL
5656 || memchr (arg, '!', len) != NULL
5657 || memchr (arg, '|', len) != NULL
5658 || memchr (arg, '<', len) != NULL
5659 || memchr (arg, '>', len) != NULL
5660 || memchr (arg, '&', len) != NULL
5661 || memchr (arg, ';', len) != NULL
5662 || memchr (arg, '(', len) != NULL
5663 || memchr (arg, ')', len) != NULL
5664 || memchr (arg, '\n', len) != NULL)
5665 {
5666 if (leading_space)
5667 o = variable_buffer_output (o, " \"", 2);
5668 else
5669 o = variable_buffer_output (o, "\"", 1);
5670 o = func_escape_shell_in_dq (o, arg, len);
5671 o = variable_buffer_output (o, "\"", 1);
5672 }
5673 else
5674 {
5675 if (leading_space)
5676 o = variable_buffer_output (o, " ", 1);
5677 o = variable_buffer_output (o, arg, len);
5678 }
5679 return o;
5680}
5681
5682/* Takes zero or more plain strings and escapes/quotes spaces and other
5683 problematic characters, bourne make style.
5684
5685 The quote-sh-dq and quote-sh-sq variants is for escaping strings that
5686 going to be put into double quotes and single quotes respectively.
5687
5688 The normal quote-sh variant assumes it's free to do open and close
5689 quotes as it pleases. */
5690
5691static char *func_quote_shell (char *o, char **argv, const char *funcname UNUSED)
5692{
5693 int i;
5694 for (i = 0; argv[i]; i++)
5695 o = helper_quote_shell (o, argv[i], strlen (argv[i]),
5696 i > 0 /*need_leading_space*/);
5697 return o;
5698}
5699
5700/* Unlinks CUR from *CHAINP and frees it, returning the next element. */
5701
5702static struct nameseq *
5703helper_unlink_and_free_ns (struct nameseq *cur, struct nameseq *prev,
5704 struct nameseq **chainp)
5705{
5706 struct nameseq *freeit = cur; \
5707 free ((char *)cur->name);
5708 if (prev)
5709 prev->next = cur = cur->next;
5710 else
5711 *chainp = cur = cur->next;
5712 free_ns (freeit);
5713 return cur;
5714}
5715
5716/* Frees a chain returned by helper_parse_file_list. */
5717
5718static void free_ns_chain_no_strcache (struct nameseq *ns)
5719{
5720 while (ns != 0)
5721 {
5722 struct nameseq *t = ns;
5723 free ((char *)ns->name);
5724 ns = ns->next;
5725 free_ns (t);
5726 }
5727}
5728
5729/* Decoded style options for the $(q* ) and $(*file* ) functions. */
5730#define Q_RET_MASK 0x000f
5731#define Q_RET_QUOTED 0x0000
5732#define Q_RET_QUOTED_DEP 0x0001
5733#define Q_RET_QUOTED_DEP_END 0x0002
5734#define Q_RET_QUOTED_TGT 0x0003
5735#define Q_RET_QUOTED_TGT_END 0x0004
5736#define Q_RET_UNQUOTED 0x0005
5737#define Q_RET_SHELL 0x0006
5738#define Q_RET_SHELL_IN_DQ 0x0007
5739#define Q_RET_SHELL_IN_SQ 0x0008
5740
5741#define Q_IN_MASK 0x0070
5742#define Q_IN_QUOTED 0x0000
5743#define Q_IN_UNQUOTED 0x0010
5744#define Q_IN_QUOTED_DEP 0x0020 /** @todo needed? */
5745#define Q_IN_QUOTED_TGT 0x0030 /** @todo needed? */
5746#define Q_IN_UNQUOTED_SINGLE 0x0040
5747#define Q_IN_SEP_COMMA 0x0080 /* for VMS hacks, file lists only */
5748
5749#define Q_SEP_MASK 0x0700
5750#define Q_SEP_SHIFT 8
5751#define Q_SEP_SPACE 0x0000
5752#define Q_SEP_TAB 0x0100
5753#define Q_SEP_NL 0x0200
5754#define Q_SEP_NL_TAB 0x0300
5755#define Q_SEP_COMMA 0x0400 /* for VMS, output only */
5756
5757#define Q_QDEFAULT (Q_IN_QUOTED | Q_RET_QUOTED | Q_SEP_SPACE)
5758#ifndef VMS
5759# define Q_QDEFAULT_VMS_TRICKS Q_QDEFAULT
5760#else /* VMS: Treat ',' as file separators in input, maybe output too. */
5761# define Q_QDEFAULT_VMS_TRICKS (Q_IN_SEP_COMMA | \
5762 (!vms_comma_separator ? Q_QDEFAULT \
5763 : (Q_QDEFAULT & ~Q_SEP_MASK) | Q_SEP_COMMA)
5764#endif
5765
5766
5767/* Decodes the optional style argument. This is chiefly for the return
5768 style, but can also pick the input and space styles (just because we can). */
5769
5770static unsigned int helper_file_quoting_style (char *style, unsigned int intstyle)
5771{
5772 if (style != NULL)
5773 {
5774 for (;;)
5775 {
5776 /* Skip blanks: */
5777 while (ISBLANK (*style))
5778 style++;
5779 if (*style != '\0')
5780 {
5781 /* Find the end of the current word: */
5782 char * const start = style;
5783 size_t len;
5784 char ch;
5785 while (!ISBLANK ((ch = *style)) && ch != '\0')
5786 style++;
5787 len = style - start;
5788
5789 /* String "switch" to decode the word: */
5790
5791#define MATCH(a_str) (len == sizeof (a_str) - 1 && memcmp (start, a_str, sizeof (a_str)) == 0)
5792 /* return styles: */
5793 if (MATCH ("quoted") || MATCH ("q"))
5794 intstyle = (intstyle & ~Q_RET_MASK) | Q_RET_QUOTED;
5795 else if (MATCH ("unquoted") || MATCH ("unq") || MATCH ("u"))
5796 intstyle = (intstyle & ~Q_RET_MASK) | Q_RET_UNQUOTED;
5797 else if (MATCH ("quoted-dep") || MATCH ("q-dep") || MATCH ("q-d"))
5798 intstyle = (intstyle & ~Q_RET_MASK) | Q_RET_QUOTED_DEP;
5799 else if (MATCH ("quoted-dep-end") || MATCH ("q-dep-end") || MATCH ("q-d-e"))
5800 intstyle = (intstyle & ~Q_RET_MASK) | Q_RET_QUOTED_DEP_END;
5801 else if (MATCH ("quoted-tgt") || MATCH ("q-tgt") || MATCH ("q-t"))
5802 intstyle = (intstyle & ~Q_RET_MASK) | Q_RET_QUOTED_TGT;
5803 else if (MATCH ("quoted-tgt-end") || MATCH ("q-tgt-end") || MATCH ("q-t-e"))
5804 intstyle = (intstyle & ~Q_RET_MASK) | Q_RET_QUOTED_TGT_END;
5805 else if (MATCH ("shell") || MATCH ("sh"))
5806 intstyle = (intstyle & ~Q_RET_MASK) | Q_RET_SHELL;
5807 else if (MATCH ("shell-in-dq") || MATCH ("sh-i-d"))
5808 intstyle = (intstyle & ~Q_RET_MASK) | Q_RET_SHELL_IN_DQ; /* returned string is used inside double shell quotes */
5809 else if (MATCH ("shell-in-sq") || MATCH ("sh-i-s"))
5810 intstyle = (intstyle & ~Q_RET_MASK) | Q_RET_SHELL_IN_SQ; /* returned string is used inside single shell quotes */
5811 /* input styles: */
5812 else if (MATCH ("in-quoted") || MATCH ("i-q"))
5813 intstyle = (intstyle & ~Q_IN_MASK) | Q_IN_QUOTED;
5814 else if (MATCH ("in-unquoted") || MATCH ("i-unq") || MATCH ("i-u"))
5815 intstyle = (intstyle & ~Q_IN_MASK) | Q_IN_UNQUOTED;
5816 else if (MATCH ("in-unquoted-single")|| MATCH ("i-unq-s") || MATCH ("i-u-s")
5817 || MATCH ("in-unquoted-file") || MATCH ("i-unq-f") || MATCH ("i-u-f"))
5818 intstyle = (intstyle & ~Q_IN_MASK) | Q_IN_UNQUOTED_SINGLE;
5819 else if (MATCH ("in-quoted-dep") || MATCH ("i-q-dep") || MATCH ("i-q-d"))
5820 intstyle = (intstyle & ~Q_IN_MASK) | Q_IN_QUOTED_DEP;
5821 else if (MATCH ("in-quoted-tgt") || MATCH ("i-q-tgt") || MATCH ("i-q-t"))
5822 intstyle = (intstyle & ~Q_IN_MASK) | Q_IN_QUOTED_TGT;
5823 else if (MATCH ("in-sep-comma") || MATCH ("i-s-com") || MATCH ("i-s-c"))
5824 intstyle |= Q_IN_SEP_COMMA; /*?*/
5825 /* separator styles (output): */
5826 else if (MATCH ("sep-space") || MATCH ("s-space") || MATCH ("s-s"))
5827 intstyle = (intstyle & ~Q_SEP_MASK) | Q_SEP_SPACE;
5828 else if (MATCH ("sep-tab") || MATCH ("s-tab") || MATCH ("s-t"))
5829 intstyle = (intstyle & ~Q_SEP_MASK) | Q_SEP_TAB;
5830 else if (MATCH ("sep-nl") || MATCH ("s-nl") || MATCH ("s-n"))
5831 intstyle = (intstyle & ~Q_SEP_MASK) | Q_SEP_NL;
5832 else if (MATCH ("sep-nl-tab") || MATCH ("s-nl-tab") || MATCH ("s-n-t"))
5833 intstyle = (intstyle & ~Q_SEP_MASK) | Q_SEP_NL_TAB;
5834 else if (MATCH ("sep-comma") || MATCH ("s-comma") || MATCH ("s-c"))
5835 intstyle = (intstyle & ~Q_SEP_MASK) | Q_SEP_COMMA;
5836 else
5837 {
5838 char savedch = *style;
5839 *style = '\0';
5840 OS (error, reading_file, "Unknown file style: %s", start);
5841 *style = savedch;
5842 }
5843#undef MATCH
5844 }
5845 else
5846 break;
5847 }
5848 }
5849 return intstyle;
5850}
5851
5852/* Output (returns) a separator according to STYLE. */
5853
5854static char *helper_return_sep (char *o, unsigned int style)
5855{
5856 /* Note! Must match Q_SEP_MASK! */
5857 static struct
5858 {
5859 const char *sep;
5860 size_t len;
5861 } const seps[8] =
5862 {
5863 { " ", 1 },
5864 { "\t", 1 },
5865 { "\n", 1 },
5866 { "\n\t", 2 },
5867 { ",", 1 },
5868 { " ", 1 },
5869 { " ", 1 },
5870 { " ", 1 }
5871 };
5872
5873 return variable_buffer_output(o,
5874 seps[(style & Q_SEP_MASK) >> Q_SEP_SHIFT].sep,
5875 seps[(style & Q_SEP_MASK) >> Q_SEP_SHIFT].len);
5876}
5877
5878/* Removes one separator from the output.
5879
5880This is typically used when outputting lists where there is no simple way of
5881telling whether an entry is the last one or not. So, is_last is always false
5882and the last separator is removed afterwards by this function. */
5883
5884MY_INLINE char *helper_drop_separator (char *o, unsigned int style)
5885{
5886 o -= (style & Q_SEP_MASK) != Q_SEP_NL_TAB ? 1 : 2;
5887 *o = '\0'; /* not strictly necessary */
5888 return o;
5889}
5890
5891
5892/* Outputs (returns) the given file. */
5893
5894static char *helper_return_file_len (char *o, const char *file, size_t len,
5895 unsigned int style, int is_last)
5896{
5897 assert (memchr (file, '\0', len) == NULL);
5898 switch (style & Q_RET_MASK)
5899 {
5900 case Q_RET_UNQUOTED:
5901 o = variable_buffer_output (o, file, len);
5902 break;
5903 case Q_RET_QUOTED:
5904 o = helper_quote_make (o, file, len, 0 /*is_dep*/, 0 /*is_tgt*/,
5905 !is_last /*quote_trailing_slashes*/, NULL);
5906 break;
5907 case Q_RET_QUOTED_DEP:
5908 o = helper_quote_make (o, file, len, 1 /*is_dep*/, 0 /*is_tgt*/,
5909 !is_last /*quote_trailing_slashes*/, NULL);
5910 break;
5911 case Q_RET_QUOTED_DEP_END:
5912 o = helper_quote_make (o, file, len, 1 /*is_dep*/, 0 /*is_tgt*/,
5913 0 /*quote_trailing_slashes*/, NULL);
5914 break;
5915 case Q_RET_QUOTED_TGT:
5916 o = helper_quote_make (o, file, len, 0 /*is_dep*/, 1 /*is_tgt*/,
5917 !is_last /*quote_trailing_slashes*/, NULL);
5918 break;
5919 case Q_RET_QUOTED_TGT_END:
5920 o = helper_quote_make (o, file, len, 0 /*is_dep*/, 1 /*is_tgt*/,
5921 0 /*quote_trailing_slashes*/, NULL);
5922 break;
5923 case Q_RET_SHELL:
5924 o = helper_quote_shell (o, file, len, 0 /*need_leading_space*/);
5925 break;
5926 case Q_RET_SHELL_IN_DQ:
5927 o = func_escape_shell_in_dq (o, file, len);
5928 break;
5929 case Q_RET_SHELL_IN_SQ:
5930 o = func_escape_shell_in_sq (o, file, len);
5931 break;
5932 default:
5933 assert (0);
5934 }
5935
5936 /* Add separator space if not last. */
5937 if (!is_last)
5938 o = helper_return_sep (o, style);
5939 return o;
5940}
5941
5942/* Outputs (returns) the given file. */
5943
5944static char *helper_return_file (char *o, const char *file,
5945 unsigned int style, int is_last)
5946{
5947 return helper_return_file_len (o,file, strlen (file), style, is_last);
5948}
5949
5950/* Outputs (returns) the given CHAIN and frees it. */
5951
5952static char *helper_return_and_free_chain (char *o, struct nameseq *chain, unsigned int style)
5953{
5954 struct nameseq *cur;
5955 for (cur = chain; cur; cur = cur->next)
5956 o = helper_return_file (o, cur->name, style, cur->next == NULL);
5957 free_ns_chain_no_strcache (chain);
5958 return o;
5959}
5960
5961
5962/* Helper for helper_parse_file_list that globs a name sequence. */
5963static struct nameseq *
5964helper_glob_chain (struct nameseq *chain)
5965{
5966 struct nameseq *prev = NULL;
5967 struct nameseq *cur = chain;
5968 glob_t gl;
5969 dir_setup_glob (&gl);
5970
5971 /** @todo XXX: !NO_ARCHIVES */
5972 while (cur)
5973 {
5974 switch (glob (cur->name, GLOB_NOSORT | GLOB_ALTDIRFUNC, NULL, &gl))
5975 {
5976 case 0: /* Replace CUR with the names found. */
5977 {
5978 struct nameseq *subchain = NULL;
5979 struct nameseq **ppnext = &subchain;
5980 const char ** const names = (const char **)gl.gl_pathv;
5981 size_t const num_names = gl.gl_pathc;
5982 size_t idx;
5983
5984 cur = helper_unlink_and_free_ns (cur, prev, &chain);
5985
5986 for (idx = 0; idx < num_names; idx++)
5987 {
5988#ifndef CONFIG_WITH_ALLOC_CACHES
5989 struct nameseq *newp = xcalloc (sizeof (*newp));
5990#else
5991 struct nameseq *newp = alloccache_calloc (&nameseq_cache);
5992#endif
5993 newp->name = xstrdup (names[idx]);
5994 newp->next = NULL;
5995 *ppnext = newp;
5996 ppnext = &newp->next;
5997 }
5998
5999 if (subchain) /* parnaoia */
6000 {
6001 *ppnext = cur;
6002 if (prev)
6003 prev->next = subchain;
6004 else
6005 chain = subchain;
6006 }
6007 break;
6008 }
6009
6010 case GLOB_NOMATCH: /* doesn't exist, remove */
6011 cur = helper_unlink_and_free_ns (cur, prev, &chain);
6012 break;
6013
6014 default: /* Keep it. */
6015 prev = cur;
6016 cur = cur->next;
6017 break;
6018
6019 case GLOB_NOSPACE:
6020 OUT_OF_MEM();
6021 }
6022 globfree (&gl);
6023 }
6024 return chain;
6025}
6026
6027/* Parses a file/word list according to STYLE and returns a name list.
6028
6029 The FILELIST parameter may be modified!
6030
6031 The GLOB param is for wildcard/qwildcard.
6032
6033 TODO/XXX: Unquote and split up the FILELIST directly. All function
6034 arguments are heap copies already, so we are free to modify
6035 them. Would be nice to ditch the nameseq in favor of something
6036 which also includes the length. */
6037
6038static struct nameseq *
6039helper_parse_file_list (char *filelist, unsigned int style, int glob)
6040{
6041 if (filelist && *filelist != '\0')
6042 {
6043 /* Q_IN_SEP_COMMA: VMS tricks for qbasename, qdir, qnotdir and qsuffix
6044 where commas are treated as separtors in FILELIST. We simply
6045 replace commas in the FILELIST before doing the regular parsing. */
6046 if (!(style & Q_IN_SEP_COMMA))
6047 { /* typical */ }
6048 else
6049 {
6050 size_t len = strlen (filelist);
6051 char *start = filelist;
6052 char *comma = (char *)memchr (filelist, ',', len);
6053 while (comma)
6054 {
6055 *comma = ' ';
6056 len -= comma - start - 1;
6057 if (len)
6058 {
6059 start = comma + 1;
6060 comma = (char *)memchr (start, ',', len);
6061 }
6062 else
6063 break;
6064 }
6065 }
6066
6067 switch (style & Q_IN_MASK)
6068 {
6069 case Q_IN_QUOTED:
6070 case Q_IN_QUOTED_DEP: /** @todo ?? */
6071 case Q_IN_QUOTED_TGT: /** @todo ?? */
6072 return PARSE_FILE_SEQ(&filelist, struct nameseq, MAP_NUL, NULL,
6073 !glob
6074 ? PARSEFS_NOGLOB | PARSEFS_NOSTRIP | PARSEFS_NOCACHE
6075 : PARSEFS_NOSTRIP | PARSEFS_NOCACHE | PARSEFS_EXISTS);
6076
6077 case Q_IN_UNQUOTED:
6078 {
6079 struct nameseq *chain = NULL;
6080 struct nameseq **ppnext = &chain;
6081 const char *it = filelist;
6082 const char *cur;
6083 unsigned int curlen;
6084 while ((cur = find_next_token (&it, &curlen)) != NULL)
6085 {
6086#ifndef CONFIG_WITH_ALLOC_CACHES
6087 struct nameseq *newp = xcalloc (sizeof (*newp));
6088#else
6089 struct nameseq *newp = alloccache_calloc (&nameseq_cache);
6090#endif
6091 newp->name = xstrndup (cur, curlen);
6092 newp->next = NULL;
6093 *ppnext = newp;
6094 ppnext = &newp->next;
6095 }
6096 if (!glob)
6097 return chain;
6098 return helper_glob_chain (chain);
6099 }
6100
6101 case Q_IN_UNQUOTED_SINGLE:
6102 if (*filelist != '\0')
6103 {
6104#ifndef CONFIG_WITH_ALLOC_CACHES
6105 struct nameseq *newp = xcalloc (sizeof (*newp));
6106#else
6107 struct nameseq *newp = alloccache_calloc (&nameseq_cache);
6108#endif
6109 newp->name = xstrdup (filelist);
6110 newp->next = NULL;
6111 if (!glob)
6112 return newp;
6113 return helper_glob_chain (newp);
6114 }
6115 return NULL;
6116
6117 default:
6118 assert (0);
6119 return NULL;
6120 }
6121 }
6122 return NULL;
6123}
6124
6125/* $(requote style, file1 file2 ... fileN). */
6126
6127static char *func_requote (char *o, char **argv, const char *funcname UNUSED)
6128{
6129 unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
6130 struct nameseq *chain = helper_parse_file_list (argv[1], style, 0);
6131 return helper_return_and_free_chain (o, chain, style);
6132}
6133
6134
6135/* Common worker for func_firstfile() and func_qfirstfile(). */
6136
6137static char *common_firstfile (char *o, char **argv, unsigned int style)
6138{
6139 struct nameseq *chain = helper_parse_file_list (argv[0], style, 0);
6140 if (chain)
6141 {
6142 o = helper_return_file (o, chain->name, style, 1);
6143 free_ns_chain_no_strcache (chain);
6144 }
6145 return o;
6146}
6147
6148/* $(firstfile file1 file2 ... fileN) - same as $(firstfile ), except
6149 for files rather than word tokens. See func_firstword(). */
6150
6151static char *func_firstfile (char *o, char **argv, const char *funcname UNUSED)
6152{
6153 return common_firstfile(o, argv, Q_IN_QUOTED | Q_RET_QUOTED | Q_SEP_SPACE);
6154}
6155
6156/* $(qfirstfile style, file1 file2 ... fileN) - same as $(firstfile ), except
6157 for files rather than word tokens. See func_firstword(). */
6158
6159static char *func_q_firstfile (char *o, char **argv, const char *funcname UNUSED)
6160{
6161 unsigned int style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
6162 return common_firstfile(o, &argv[1], style);
6163}
6164
6165
6166/* Common worker for func_lastfile() and func_q_lastfile(). */
6167
6168static char *common_lastfile (char *o, char **argv, unsigned int style)
6169{
6170 struct nameseq *chain = helper_parse_file_list (argv[0], style, 0);
6171 if (chain)
6172 {
6173 struct nameseq *last = chain;
6174 while (last->next)
6175 last = last->next;
6176 o = helper_return_file (o, last->name, style, 1);
6177 free_ns_chain_no_strcache (chain);
6178 }
6179 return o;
6180}
6181
6182/* $(lastfile file1 file2 ... fileN) - same as $(lastfile ), except
6183 for files rather than word tokens. See func_lastword(). */
6184
6185static char *func_lastfile (char *o, char **argv, const char *funcname UNUSED)
6186{
6187 return common_lastfile (o, argv, Q_IN_QUOTED | Q_RET_QUOTED | Q_SEP_SPACE);
6188}
6189
6190/* $(qlastfile style, file1 file2 ... fileN) - same as $(lastfile ), except
6191 for files rather than word tokens. See func_lastword(). */
6192
6193static char *func_q_lastfile (char *o, char **argv, const char *funcname UNUSED)
6194{
6195 unsigned int style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
6196 return common_lastfile (o, &argv[1], style);
6197}
6198
6199
6200/* Common worker for func_filelist() and func_q_filelist(). */
6201
6202static char *common_filelist (char *o, char **argv, unsigned int style)
6203{
6204 int start;
6205 int count;
6206
6207 /* Check the arguments. */
6208 check_numeric (argv[0],
6209 _("non-numeric first argument to 'filelist' function"));
6210 check_numeric (argv[1],
6211 _("non-numeric second argument to 'filelist' function"));
6212
6213 start = atoi (argv[0]);
6214 if (start < 1)
6215 ON (fatal, *expanding_var,
6216 "invalid first argument to 'filelist' function: '%d'", start);
6217 start--; /* make zero based */
6218
6219 count = atoi (argv[1]) - start;
6220
6221 if (count > 0)
6222 {
6223 char *line = argv[2];
6224 struct nameseq *cur;
6225 struct nameseq *chain;
6226 chain = helper_parse_file_list (line, style, 0);
6227
6228 /* Find the beginning of the "start"th word (1-based). */
6229 for (cur = chain; cur && start > 1; cur = cur->next)
6230 start--;
6231
6232 /* Output the requested count */
6233 while (cur && count-- > 0)
6234 o = helper_return_file (o, cur->name, style, count > 0 && cur->next);
6235
6236 free_ns_chain_no_strcache (chain);
6237 }
6238
6239 return o;
6240}
6241
6242/* $(filelist start, end, file1..fileN) - same as $(wordlist),
6243 except for files rather than word tokens. See func_wordlist(). */
6244
6245static char *func_filelist (char *o, char **argv, const char *funcname UNUSED)
6246{
6247 return common_filelist (o, argv, Q_IN_QUOTED | Q_RET_QUOTED | Q_SEP_SPACE);
6248}
6249
6250/* $(qfilelist style, start, end, file1..fileN) - same as $(wordlist),
6251 except for files rather than word tokens. See func_wordlist(). */
6252
6253static char *func_q_filelist (char *o, char **argv, const char *funcname UNUSED)
6254{
6255 unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
6256 return common_filelist (o, &argv[1], style);
6257}
6258
6259
6260/* Common worker for func_countfiles() and func_q_countfiles(). */
6261
6262static char *common_countfiles (char *o, char **argv, unsigned int style)
6263{
6264 struct nameseq *chain = helper_parse_file_list (argv[0], style, 0);
6265 struct nameseq *cur;
6266 unsigned int files = 0;
6267 char retval[32];
6268
6269 for (cur = chain; cur; cur = cur->next)
6270 files++;
6271 free_ns_chain_no_strcache (chain);
6272
6273 return variable_buffer_output (o, retval, sprintf (retval, "%u", files));
6274}
6275
6276/* $(countfiles file1 file2 ... fileN) - same as $(words ), except for
6277 files rather than word tokens. See func_words(). */
6278
6279static char *func_countfiles (char *o, char **argv, const char *funcname UNUSED)
6280{
6281 return common_countfiles (o, argv, Q_IN_QUOTED | Q_RET_QUOTED | Q_SEP_SPACE);
6282}
6283
6284/* $(qcountfiles style, file1 file2 ... fileN) - same as $(words ), except for
6285 files rather than word tokens and the STYLE argument. See func_words(). */
6286
6287static char *func_q_countfiles (char *o, char **argv, const char *funcname UNUSED)
6288{
6289 unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
6290 return common_countfiles (o, &argv[1], style);
6291}
6292
6293
6294/* Helper that sets the variable value. */
6295
6296static void
6297helper_set_var_value (struct variable *var, const char *value, size_t len)
6298{
6299#ifndef CONFIG_WITH_VALUE_LENGTH
6300 free (var->value);
6301 var->value = xstrndup (value, len);
6302#else
6303 if (len >= var->value_alloc_len)
6304 {
6305# ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE
6306 if (var->rdonly_val)
6307 var->rdonly_val = 0;
6308 else
6309# endif
6310 free (var->value);
6311 var->value_alloc_len = VAR_ALIGN_VALUE_ALLOC (len + 1);
6312 var->value = xmalloc (var->value_alloc_len);
6313 }
6314 memcpy (var->value, value, len);
6315 var->value[len] = '\0';
6316 var->value_length = len;
6317 VARIABLE_CHANGED (var);
6318#endif
6319}
6320
6321/* Common worker for func_foreachfile and func_qforeachfile. */
6322
6323static char *
6324common_foreachfile (char *o, char **argv, unsigned int style)
6325{
6326 /* expand only the first two. */
6327 char *varname = expand_argument (argv[0], NULL);
6328 char *list = expand_argument (argv[1], NULL);
6329 const char *body = argv[2];
6330#ifdef CONFIG_WITH_VALUE_LENGTH
6331 long body_len = strlen (body);
6332#endif
6333
6334 struct nameseq *chain = helper_parse_file_list (list, style, 0);
6335 struct nameseq *cur;
6336
6337 /* Clean up the variable name by removing whitespace. */
6338 struct variable *var;
6339 char *vp = next_token (varname);
6340 char *vp_end = end_of_token (vp);
6341 vp_end[0] = '\0';
6342
6343 push_new_variable_scope ();
6344 var = define_variable (vp, vp_end - vp, "", o_automatic, 0);
6345
6346 /* Don't need the list any more. */
6347 free (list);
6348 list = NULL;
6349
6350 /* Loop through the chain. */
6351 for (cur = chain; cur; cur = cur->next)
6352 {
6353 /* Update the variable value: */
6354 unsigned int const len = strlen (cur->name);
6355 switch (style & Q_RET_MASK)
6356 {
6357 case Q_RET_UNQUOTED:
6358 helper_set_var_value (var, cur->name, len);
6359 break;
6360 default:
6361 { /* Use the output buffer as temporary storage. */
6362 size_t const saved_off = o - variable_buffer;
6363 size_t quoted_len;
6364 char *quoted;
6365 o = helper_return_file_len (o, cur->name, len, style, 1 /*is_last*/);
6366 quoted = &variable_buffer[saved_off];
6367 quoted_len = o - quoted;
6368 helper_set_var_value (var, quoted, quoted_len);
6369 o = quoted;
6370 break;
6371 }
6372 }
6373
6374 /* Expand the body: */
6375#ifndef CONFIG_WITH_VALUE_LENGTH
6376 {
6377 char *result = allocated_variable_expand (body);
6378 o = variable_buffer_output (o, result, strlen (result));
6379 free (result);
6380 }
6381#else
6382 variable_expand_string_2 (o, body, body_len, &o);
6383#endif
6384
6385 /* Add separator: */
6386 if (cur->next)
6387 o = helper_return_sep (o, style);
6388 }
6389
6390 pop_variable_scope ();
6391 free (varname);
6392
6393 return o;
6394}
6395
6396/* $(foreachfile var, filelist, body) - same as $(foreach ), except
6397 for file rather than word tokens.
6398 See also func_foreach(). */
6399
6400static char *
6401func_foreachfile (char *o, char **argv, const char *funcname UNUSED)
6402{
6403 return common_foreachfile (o, argv, Q_IN_QUOTED | Q_RET_QUOTED | Q_SEP_SPACE);
6404}
6405
6406/* $(qforeachfile style, var, filelist, body) - same as $(foreach ), except
6407 for file rather than word tokens and flexible variable value encoding.
6408 See also func_foreach(). */
6409
6410static char *
6411func_q_foreachfile (char *o, char **argv, const char *funcname UNUSED)
6412{
6413 unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
6414 return common_foreachfile (o, &argv[1], style);
6415}
6416
6417
6418/* Common worker for func_sortfiles() and func_q_sortfiles(). */
6419
6420static char *common_sortfiles (char *o, char **argv, unsigned int style,
6421 int ascending, int version)
6422{
6423 struct nameseq *chain = helper_parse_file_list (argv[0], style, 0);
6424
6425 /* Count the number of files to determin the array size and whether we've
6426 got anything to sort. */
6427 struct nameseq *cur;
6428 unsigned int num_files = 0;
6429 for (cur = chain; cur; cur = cur->next)
6430 num_files++;
6431
6432 if (num_files <= 1)
6433 o = helper_return_and_free_chain (o, chain, style);
6434 else
6435 {
6436 /* Create array of string pointers from the chain. */
6437 char **files = (char **)xmalloc (num_files * sizeof (char *));
6438 unsigned int idx = 0;
6439 for (cur = chain; cur; cur = cur->next)
6440 files[idx++] = (char *)cur->name;
6441
6442 /* Sort it. */
6443 if (version)
6444 qsort(files, num_files, sizeof(files[0]), version_compare_wrapper);
6445 else
6446 qsort(files, num_files, sizeof(files[0]), alpha_compare);
6447
6448 /* Output. We skip equal files. */
6449 if (ascending)
6450 for (idx = 0; idx < num_files; idx++)
6451 {
6452 const char *curfile = files[idx];
6453 while (idx + 1 < num_files && strcmp(files[idx + 1], curfile) == 0)
6454 idx++;
6455 o = helper_return_file(o, files[idx], style, idx + 1 >= num_files);
6456 }
6457 else
6458 {
6459 idx = num_files;
6460 while (idx-- > 0)
6461 {
6462 const char *curfile = files[idx];
6463 while (idx > 0 && strcmp(files[idx - 1], curfile) == 0)
6464 idx--;
6465 o = helper_return_file (o, curfile, style, idx == 0);
6466 }
6467 }
6468
6469 free (files);
6470 free_ns_chain_no_strcache (chain);
6471 }
6472 return o;
6473}
6474
6475/* $(sortfiles file1 ... fileN) and
6476 $(rsortfiles file1 ... fileN) - same as $(sort ) and $(rsort ),
6477 except for files rather than word tokens. See func_sort(). */
6478
6479static char *func_sortfiles (char *o, char **argv, const char *funcname)
6480{
6481 return common_sortfiles (o, argv, Q_IN_QUOTED | Q_RET_QUOTED | Q_SEP_SPACE,
6482 funcname[0] != 'r',
6483 funcname[0] == 'v' || funcname[1] == 'v');
6484}
6485
6486/* $(qsortfiles style, file1 ... fileN) and
6487 $(qrsortfiles style, file1 ... fileN) - same as $(sort ) and $(rsort ),
6488 except for files rather than word tokens and the flexible style.
6489 See func_sort(). */
6490
6491static char *func_q_sortfiles (char *o, char **argv, const char *funcname)
6492{
6493 unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
6494 return common_sortfiles (o, &argv[1], style, funcname[1] != 'r',
6495 funcname[1] == 'v' || funcname[2] == 'v');
6496}
6497
6498
6499/* Helper for determining whether the given path is absolute or not. */
6500
6501static int helper_is_abs (const char *path)
6502{
6503#ifdef HAVE_DOS_PATHS
6504 return path[0] == '/'
6505 || path[0] == '\\'
6506 || (isalpha(path[0]) && path[1] == ':');
6507#else
6508 return path[0] == '/';
6509#endif
6510}
6511
6512/* Worker for func_q_abspath and func_q_abspath_ex. */
6513
6514static char *worker_abspath (char *o, char *line, const char *cwd,
6515 size_t cwd_len, unsigned int style)
6516{
6517 if (line && *line != '\0')
6518 {
6519 PATH_VAR (outbuf);
6520 struct nameseq *chain = helper_parse_file_list (line, style, 0);
6521
6522 /* Special case: single path, no cwd - no is_last path trouble */
6523 if (chain && !chain->next && !cwd)
6524 {
6525 if (abspath (chain->name, outbuf))
6526 o = helper_return_file(o, outbuf, style, 1);
6527 free_ns_chain_no_strcache (chain);
6528 }
6529 else if (chain)
6530 {
6531 /* Pass one: replace names by absolute names */
6532 struct nameseq *prev = NULL;
6533 struct nameseq *cur = chain;
6534 while (cur)
6535 {
6536 /* If relative path and we've got cwd, join cwd and it. */
6537 if (cwd && !helper_is_abs (cur->name))
6538 {
6539 size_t len_name = strlen (cur->name);
6540 char *name = xrealloc ((char *)cur->name, cwd_len + 1 + len_name + 1);
6541 memmove (&name[cwd_len + 1], &name[0], len_name);
6542 memcpy (name, cwd, cwd_len);
6543 name[cwd_len] = '/';
6544 name[cwd_len + 1 + len_name] = '\0';
6545 cur->name = name;
6546 }
6547
6548 if (abspath (cur->name, outbuf))
6549 {
6550 free ((char *)cur->name);
6551 cur->name = xstrdup (outbuf);
6552 prev = cur;
6553 cur = cur->next;
6554 }
6555 else /* remove it */
6556 cur = helper_unlink_and_free_ns (cur, prev, &chain);
6557 }
6558
6559 /* Pass two: output */
6560 o = helper_return_and_free_chain (o, chain, style);
6561 }
6562 }
6563 return o;
6564}
6565
6566/* $(qabspath style, file1 file2 ... fileN) - same as $(abspath ), except
6567 for files rather than word tokens. See func_abspath(). */
6568
6569static char *func_q_abspath (char *o, char **argv, const char *funcname UNUSED)
6570{
6571 return worker_abspath (o, argv[1], NULL, 0,
6572 helper_file_quoting_style (argv[0], Q_QDEFAULT));
6573}
6574
6575# ifdef CONFIG_WITH_ABSPATHEX
6576/* $(qabspathex style, file1 file2 ... fileN [,cwd]) - same as $(abspathex ),
6577 except for files rather than word tokens. See func_abspath_ex(). */
6578
6579static char *
6580func_q_abspathex (char *o, char **argv, const char *funcname UNUSED)
6581{
6582 /* cwd needs leading spaces chopped and may be optional,
6583 in which case we're exactly like $(abspath ). */
6584 char *cwd = argv[2];
6585 if (cwd)
6586 {
6587 while (ISBLANK (*cwd))
6588 cwd++;
6589 if (*cwd == '\0')
6590 cwd = NULL;
6591 }
6592
6593 return worker_abspath (o, argv[1], cwd, cwd ? strlen (cwd) : 0,
6594 helper_file_quoting_style (argv[0], Q_QDEFAULT));
6595}
6596# endif
6597
6598/* $(qaddprefix style, prefix, file1 ... fileN) and
6599 $(qaddsuffix style, prefix, file1 ... fileN) - same as $(addprefix )
6600 and $(addsuffix ) except for files rather than word tokens.
6601 The suffix/prefix is unquoted on input and subjected to the same quoting
6602 styling as the file names.
6603 See func_addsuffix_addprefix(). */
6604
6605static char *func_q_addsuffix_addprefix (char *o, char **argv, const char *funcname UNUSED)
6606{
6607 unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
6608 const char * const fix = argv[1];
6609 size_t const fixlen = strlen (fix);
6610 struct nameseq *chain = helper_parse_file_list (argv[2], style, 0);
6611 if (chain)
6612 {
6613 size_t tmpsize = (fixlen + 512) & ~(size_t)63;
6614 char *tmp = (char *)xmalloc (tmpsize);
6615 struct nameseq *cur;
6616
6617 if (funcname[4] == 'p')
6618 {
6619 memcpy (tmp, fix, fixlen);
6620 for (cur = chain; cur; cur = cur->next)
6621 {
6622 size_t curlen = strlen (cur->name);
6623 if (fixlen + curlen + 1 <= tmpsize)
6624 { /* likely */ }
6625 else
6626 {
6627 tmpsize = (fixlen + curlen + 63) & ~(size_t)63;
6628 tmp = (char *)xrealloc (tmp, tmpsize);
6629 }
6630 memcpy (&tmp[fixlen], cur->name, curlen + 1);
6631 o = helper_return_file_len (o, tmp, fixlen + curlen,
6632 style, cur->next == NULL);
6633 }
6634 }
6635 else
6636 for (cur = chain; cur; cur = cur->next)
6637 {
6638 size_t curlen = strlen (cur->name);
6639 if (fixlen + curlen + 1 <= tmpsize)
6640 { /* likely */ }
6641 else
6642 {
6643 tmpsize = (fixlen + curlen + 63) & ~(size_t)63;
6644 tmp = (char *)xrealloc (tmp, tmpsize);
6645 }
6646 memcpy (tmp, cur->name, curlen);
6647 memcpy (&tmp[curlen], fix, fixlen + 1);
6648
6649 o = helper_return_file_len (o, tmp, fixlen + curlen,
6650 style, cur->next == NULL);
6651 }
6652 free_ns_chain_no_strcache (chain);
6653 }
6654 return o;
6655}
6656
6657/* $(qbasename style, path1 .. pathN) and $(qdir style, path1 .. pathN)
6658 - same as $(basename ) and $(dir ), except for files rather than word tokens.
6659 See func_basename_dir(). */
6660
6661static char *
6662func_q_basename_dir (char *o, char **argv, const char *funcname)
6663{
6664 unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT_VMS_TRICKS);
6665 struct nameseq *chain = helper_parse_file_list (argv[1], style, 0);
6666 struct nameseq *cur;
6667
6668 int const is_basename = funcname[1] == 'b';
6669 int const is_dir = !is_basename;
6670 int const stop = MAP_DIRSEP | (is_basename ? MAP_DOT : 0) | MAP_NUL;
6671
6672 for (cur = chain; cur; cur = cur->next)
6673 {
6674 int const is_last = cur->next == NULL;
6675 const char * const path = cur->name;
6676 const char * const end = strchr (path, '\0');
6677
6678 /* Locate the last dot or path separator (P): */
6679 const char *p = path != end ? end - 1 : end;
6680 while (p >= path && !STOP_SET (*p, stop))
6681 --p;
6682
6683 /* Do the outputting: */
6684 if (p >= path && (is_dir))
6685 o = helper_return_file_len (o, path, ++p - path, style, is_last);
6686 else if (p >= path && *p == '.')
6687 o = helper_return_file_len (o, path, p - path, style, is_last);
6688#ifdef HAVE_DOS_PATHS
6689 /* Handle the "d:foobar" case */
6690 else if (path[0] && path[1] == ':' && is_dir)
6691 o = helper_return_file_len (o, path, 2, style, is_last);
6692#endif
6693 else if (is_dir)
6694#ifdef VMS
6695 {
6696 extern int vms_report_unix_paths;
6697 o = helper_return_file_len (o, vms_report_unix_paths ? "./" : "[]",
6698 2, style, is_last);
6699 }
6700#else
6701# ifndef _AMIGA
6702 o = helper_return_file_len (o, "./", 2, style, is_last);
6703# else
6704 ; /* Just a nop... */
6705# endif /* AMIGA */
6706#endif /* !VMS */
6707 else
6708 /* The entire name is the basename. */
6709 o = helper_return_file_len (o, path, end - path, style, is_last);
6710 }
6711
6712 free_ns_chain_no_strcache (chain);
6713 return o;
6714}
6715
6716/* $(qnotdir style, path1 ... pathN) - same as $(notdir ), except for
6717 files rather than word tokens. See func_notdir_suffix(). */
6718
6719static char *
6720func_q_notdir (char *o, char **argv, const char *funcname)
6721{
6722 unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT_VMS_TRICKS);
6723 struct nameseq *chain = helper_parse_file_list (argv[1], style, 0);
6724 struct nameseq *cur;
6725 int const stop = MAP_DIRSEP;
6726 (void)funcname;
6727
6728 for (cur = chain; cur; cur = cur->next)
6729 {
6730 int const is_last = cur->next == NULL;
6731 const char * const path = cur->name;
6732 const char * const end = strchr(path, '\0');
6733
6734 /* Locate the last dot or path separator (P): */
6735 const char *p = path != end ? end - 1 : end;
6736 while (p >= path && ! STOP_SET (*p, stop))
6737 --p;
6738
6739 if ((uintptr_t)p >= (uintptr_t)path)
6740 o = helper_return_file_len (o, p + 1, end - p - 1, style, is_last);
6741#ifdef HAVE_DOS_PATHS
6742 else if (path[0] && path[1] == ':') /* "d:foo/bar" -> "foo/bar" */
6743 o = helper_return_file_len (o, path + 2, end - path - 2, style, is_last);
6744#endif
6745 else
6746 o = helper_return_file_len (o, path, end - path, style, is_last);
6747 }
6748
6749 free_ns_chain_no_strcache (chain);
6750 return o;
6751}
6752
6753/* $(qsuffix style, path1 ... pathN) - same as $(suffix ), except for
6754 files rather than word tokens. See func_notdir_suffix(). */
6755
6756static char *
6757func_q_suffix (char *o, char **argv, const char *funcname)
6758{
6759 unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT_VMS_TRICKS);
6760 struct nameseq *chain = helper_parse_file_list (argv[1], style, 0);
6761 struct nameseq *prev;
6762 struct nameseq *cur;
6763 int const stop = MAP_DIRSEP | MAP_DOT;
6764 (void)funcname;
6765
6766 /* For suffixes we do a pre-pass that removes elements without suffixes.
6767 This simplifies the handling of end-quoting. */
6768 prev = NULL;
6769 cur = chain;
6770 while (cur)
6771 {
6772 const char * const path = cur->name;
6773 if (strchr (path, '.') != NULL)
6774 {
6775 const char * const end = strchr (path, '\0');
6776 const char *p = end - 1;
6777 while ((uintptr_t)p >= (uintptr_t)path && ! STOP_SET (*p, stop))
6778 --p;
6779 if ((uintptr_t)p >= (uintptr_t)path && *p == '.')
6780 {
6781 if (p != path)
6782 memmove ((char *)path, p, end - p + 1);
6783 prev = cur;
6784 cur = cur->next;
6785 }
6786 else /* remove it */
6787 cur = helper_unlink_and_free_ns (cur, prev, &chain);
6788 }
6789 else /* remove it */
6790 cur = helper_unlink_and_free_ns (cur, prev, &chain);
6791 }
6792
6793 /* Output pass: */
6794 return helper_return_and_free_chain (o, chain, style);
6795}
6796
6797# ifdef CONFIG_WITH_ROOT_FUNC
6798/*
6799 $(qroot style, path...pathN) - same as $(root ), except files rather
6800 than space delimited word tokens. See func_root().
6801
6802 This is mainly for dealing with drive letters and UNC paths on Windows
6803 and OS/2.
6804 */
6805static char *
6806func_q_root (char *o, char **argv, const char *funcname UNUSED)
6807{
6808 unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
6809 struct nameseq *chain = helper_parse_file_list (argv[1], style, 0);
6810 struct nameseq *prev;
6811 struct nameseq *cur;
6812
6813 /* First pass: Strip non-root components and remove rootless elements. */
6814 prev = NULL;
6815 cur = chain;
6816 while (cur)
6817 {
6818 const char *path = cur->name;
6819 const char *end = NULL;
6820 char ch;
6821
6822# ifdef HAVE_DOS_PATHS
6823 if (isalpha(path[0]) && path[1] == ':')
6824 end = path + 2;
6825 else if ( IS_PATHSEP(path[0])
6826 && IS_PATHSEP(path[1])
6827 && !IS_PATHSEP(path[2]) && path[2]
6828 && path[3])
6829 {
6830 /* Min recognized UNC: "//./" - find the next slash
6831 Typical root: "//srv/shr/" */
6832 /* XXX: Check if //./ needs special handling. */
6833 end = path + 3;
6834 while ((ch = *end) != '\0' && !IS_PATHSEP(ch))
6835 end++;
6836
6837 if (IS_PATHSEP(ch) && !IS_PATHSEP(end[1]))
6838 {
6839 end++;
6840 while ((ch = *end) != '\0' && !IS_PATHSEP(ch))
6841 end++;
6842 }
6843 else
6844 end = NULL; /* invalid */
6845 }
6846 else if (IS_PATHSEP(*end))
6847 end = path + 1;
6848 else
6849 end = NULL;
6850
6851# elif defined (VMS) || defined (AMGIA)
6852 /* XXX: VMS and AMGIA */
6853 OS (fatal, NILF, _("$(%s ) is not implemented on this platform"), funcname);
6854# else
6855 if (IS_PATHSEP(*path))
6856 end = path + 1;
6857# endif
6858 if (end != NULL)
6859 {
6860 /* Include all subsequent path separators. */
6861
6862 while ((ch = *end) != '\0' && IS_PATHSEP(ch))
6863 end++;
6864 *(char *)end = '\0';
6865
6866 prev = cur;
6867 cur = cur->next;
6868 }
6869 else
6870 cur = helper_unlink_and_free_ns(cur, prev, &chain);
6871 }
6872
6873 /* Second pass: Output */
6874 return helper_return_and_free_chain (o, chain, style);
6875}
6876
6877/*
6878 $(qnotroot style, path1 .. pathN) - same as $(notroot ), except files
6879 rather than space delimited word tokens. See func_notroot().
6880
6881 This is mainly for dealing with drive letters and UNC paths on Windows
6882 and OS/2.
6883 */
6884static char *
6885func_q_notroot (char *o, char **argv, const char *funcname UNUSED)
6886{
6887 unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
6888 struct nameseq *chain = helper_parse_file_list (argv[1], style, 0);
6889 struct nameseq *cur;
6890
6891 for (cur = chain; cur; cur = cur->next)
6892 {
6893 const char *start = cur->name;
6894 char ch;
6895
6896# ifdef HAVE_DOS_PATHS
6897 if (isalpha(start[0]) && start[1] == ':')
6898 start += 2;
6899 else if ( IS_PATHSEP(start[0])
6900 && IS_PATHSEP(start[1])
6901 && !IS_PATHSEP(start[2]) && start[2] != '\0'
6902 && start[3] != '\0')
6903 {
6904 /* Min recognized UNC: "//./" - find the next slash
6905 Typical root: "//srv/shr/" */
6906 /* XXX: Check if //./ needs special handling. */
6907 start += 3;
6908 while ((ch = *start) != '\0' && !IS_PATHSEP(ch))
6909 start++;
6910
6911 if (IS_PATHSEP(ch) && !IS_PATHSEP(start[1]))
6912 {
6913 start++;
6914 while ((ch = *start) != '\0' && !IS_PATHSEP(ch))
6915 start++;
6916 }
6917 else
6918 start = cur->name; /* invalid UNC, pretend it's a couple unixy root slashes. */
6919 }
6920
6921# elif defined (VMS) || defined (AMGIA)
6922 /* XXX: VMS and AMGIA */
6923 OS (fatal, NILF, _("$(%s) is not implemented on this platform"), funcname);
6924# endif
6925
6926 /* Exclude all subsequent / leading path separators. */
6927 while ((ch = *start) != '\0' && IS_PATHSEP(ch))
6928 start++;
6929
6930 if (ch != '\0')
6931 o = helper_return_file(o, start, style, cur->next == NULL);
6932 else
6933 o = helper_return_file_len (o, ".", 1, style, cur->next == NULL);
6934 }
6935
6936 free_ns_chain_no_strcache (chain);
6937 return o;
6938}
6939
6940# endif
6941
6942/* $(qrealpath style, path1 .. pathN) - same as $(realpath ), except files
6943 rather than space delimited word tokens. See func_realpath(). */
6944
6945static char *
6946func_q_realpath (char *o, char **argv, const char *funcname UNUSED)
6947{
6948 PATH_VAR (outbuf);
6949 unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
6950 struct nameseq *chain = helper_parse_file_list (argv[1], style, 0);
6951
6952 /* Pass one: Do the realpath/abspath thing and remove anything that fails
6953 or doesn't exists. */
6954 struct nameseq *cur = chain;
6955 struct nameseq *prev = NULL;
6956 while (cur)
6957 {
6958 char *result;
6959#ifdef HAVE_REALPATH
6960 ENULLLOOP (result, realpath (cur->name, outbuf));
6961#else
6962 result = abspath (cur->name, outbuf);
6963#endif
6964 if (result)
6965 {
6966 struct stat st;
6967 int r;
6968 EINTRLOOP (r, stat (outbuf, &st));
6969 if (r == 0)
6970 {
6971 free ((char *)cur->name);
6972 cur->name = xstrdup (result);
6973 prev = cur;
6974 cur = cur->next;
6975 }
6976 else
6977 cur = helper_unlink_and_free_ns(cur, prev, &chain);
6978 }
6979 else
6980 cur = helper_unlink_and_free_ns(cur, prev, &chain);
6981 }
6982
6983 /* Pass two: Output. */
6984 return helper_return_and_free_chain (o, chain, style);
6985}
6986
6987/* $(qwildcard path1 .. pathN [, style]) - same as $(wildcard ), except files
6988 rather than space delimited word tokens. See func_wildcard(). */
6989
6990static char *
6991func_q_wildcard (char *o, char **argv, const char *funcname UNUSED)
6992{
6993 unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
6994 struct nameseq *chain = helper_parse_file_list (argv[1], style, 1 /*glob*/);
6995#ifdef _AMIGA
6996 OS (fatal, NILF, _("$(%s ) is not implemented on this platform"), funcname);
6997#endif
6998 return helper_return_and_free_chain (o, chain, style);
6999}
7000
7001static char *
7002worker_filter_filterout (char *o, char **argv, unsigned style, int is_filter)
7003{
7004 struct nameseq *wordchain;
7005 struct a_word *wordhead;
7006 struct a_word **wordtail;
7007 struct a_word *wp;
7008 struct nameseq *patchain;
7009 struct a_pattern *pathead;
7010 struct a_pattern **pattail;
7011 struct a_pattern *pp;
7012 struct nameseq *cur;
7013 struct hash_table a_word_table;
7014 int literals;
7015 int words;
7016 int hashing;
7017 unsigned int words_len; /* for output estimation */
7018
7019 /* Chop ARGV[0] up into patterns to match against the words. */
7020 /** @todo this very inefficient as we convert between two list format and
7021 * duplicates the patterns on the heap. We could just modify argv[0]
7022 * directly. */
7023 patchain = helper_parse_file_list (argv[0], style, 0 /*glob*/);
7024 pattail = &pathead;
7025 for (cur = patchain, literals = 0; cur; cur = cur->next)
7026 {
7027 struct a_pattern *pat = alloca (sizeof (struct a_pattern));
7028
7029 *pattail = pat;
7030 pattail = &pat->next;
7031
7032 pat->str = (char *)cur->name; /* (safe - PARSEFS_NOCACHE) */
7033 pat->percent = find_percent (pat->str); /* may modify name */
7034 if (pat->percent == 0)
7035 literals++;
7036 pat->sfxlen = pat->percent ? strlen(pat->percent + 1) : 0;
7037 pat->length = strlen (pat->str);
7038 }
7039 *pattail = NULL;
7040
7041 /* Chop ARGV[1] up into words to match against the patterns. */
7042 /** @todo this very inefficient as we convert between two list format and
7043 * duplicates the words on the heap. We could just modify argv[1]
7044 * directly. */
7045 wordchain = helper_parse_file_list (argv[1], style, 0 /*glob*/);
7046 wordtail = &wordhead;
7047 for (cur = wordchain, words = 0, words_len = 0; cur; cur = cur->next)
7048 {
7049 struct a_word *word = alloca (sizeof (struct a_word));
7050
7051 *wordtail = word;
7052 wordtail = &word->next;
7053
7054 word->str = (char *)cur->name; /* (safe - PARSEFS_NOCACHE) */
7055 word->length = strlen (cur->name);
7056 words_len += word->length + 1;
7057 word->matched = 0;
7058 word->chain = NULL;
7059 words++;
7060 }
7061 *wordtail = NULL;
7062
7063 /* Only use a hash table if arg list lengths justifies the cost. */
7064 hashing = (literals >= 2 && (literals * words) >= 10);
7065 if (hashing)
7066 {
7067 hash_init (&a_word_table, words, a_word_hash_1, a_word_hash_2,
7068 a_word_hash_cmp);
7069 for (wp = wordhead; wp != 0; wp = wp->next)
7070 {
7071 struct a_word *owp = hash_insert (&a_word_table, wp);
7072 if (owp)
7073 wp->chain = owp;
7074 }
7075 }
7076
7077 if (words)
7078 {
7079 int doneany = 0;
7080
7081 if (is_filter)
7082 words_len = 0;
7083
7084 /* Run each pattern through the words, killing words. */
7085 for (pp = pathead; pp != 0; pp = pp->next)
7086 {
7087 if (pp->percent)
7088 for (wp = wordhead; wp != 0; wp = wp->next)
7089 if (!wp->matched
7090 && pattern_matches_ex (pp->str, pp->percent, pp->sfxlen,
7091 wp->str, wp->length))
7092 {
7093 wp->matched = 1;
7094 if (is_filter)
7095 words_len += wp->length + 1;
7096 else
7097 words_len -= wp->length + 1;
7098 }
7099 else if (hashing)
7100 {
7101 struct a_word a_word_key;
7102 a_word_key.str = pp->str;
7103 a_word_key.length = pp->length;
7104 wp = hash_find_item (&a_word_table, &a_word_key);
7105 while (wp)
7106 {
7107 if (!wp->matched)
7108 {
7109 wp->matched = 1;
7110 if (is_filter)
7111 words_len += wp->length + 1;
7112 else
7113 words_len -= wp->length + 1;
7114 }
7115 wp = wp->chain;
7116 }
7117 }
7118 else
7119 for (wp = wordhead; wp != 0; wp = wp->next)
7120 if (!wp->matched
7121 && wp->length == pp->length
7122 && strneq (pp->str, wp->str, wp->length))
7123 {
7124 wp->matched = 1;
7125 if (is_filter)
7126 words_len += wp->length + 1;
7127 else
7128 words_len -= wp->length + 1;
7129 }
7130 }
7131
7132 /* Output the words that matched (or didn't, for filter-out). */
7133 o = ensure_variable_buffer_space (o, words_len);
7134
7135 for (wp = wordhead; wp != 0; wp = wp->next)
7136 if (wp->matched == is_filter)
7137 {
7138 o = helper_return_file_len (o, wp->str, wp->length,
7139 style, 0 /*is_last*/);
7140 doneany = 1;
7141 }
7142
7143 /* Kill the last separator. */
7144 if (doneany)
7145 o = helper_drop_separator (o, style);
7146 }
7147
7148 /* Clean up. */
7149 if (hashing)
7150 hash_free (&a_word_table, 0);
7151 free_ns_chain_no_strcache (wordchain);
7152 free_ns_chain_no_strcache (patchain);
7153
7154 return o;
7155}
7156
7157/* Implements $(qfilter ) and $(qfilter-out ). */
7158static char *
7159func_q_filter_filterout (char *o, char **argv, const char *funcname)
7160{
7161 unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
7162 return worker_filter_filterout (o, &argv[1], style, funcname[7] == '\0');
7163}
7164
7165#endif /* KMK */
7166
7167
7168#ifdef CONFIG_WITH_LAZY_DEPS_VARS
7169
7170/* Helper that parses the index argument for the $(deps* ) and $(qdeps* )
7171 functions. */
7172static unsigned int parse_dep_index (const char *index, const char *funcname)
7173{
7174 unsigned int idx = 0;
7175 if (index)
7176 {
7177 while (ISSPACE (*index))
7178 index++;
7179 if (*index != '\0')
7180 {
7181 char *next = (char *)index;
7182 long l = strtol (index, &next, 0);
7183 while (ISSPACE (*next))
7184 next++;
7185 idx = (unsigned int)l;
7186 if (*next != '\0' || l < 0 || (long)idx != l)
7187 OSS (fatal, NILF, _("%s: invalid index value: `%s'\n"), funcname, index);
7188 }
7189 }
7190 return idx;
7191}
7192
7193/* Helper that calculates the output length for a dependency */
7194
7195MY_INLINE unsigned int helper_dep_output_len (struct dep *d)
7196{
7197 const char *c = dep_name (d);
7198#ifndef NO_ARCHIVES
7199 if (ar_name (c))
7200 return strlen (strchr (c, '(') + 1);
7201#endif
7202#ifdef CONFIG_WITH_STRCACHE2
7203 if (!d->need_2nd_expansion)
7204 return strcache2_get_len (&file_strcache, c) + 1;
7205#endif
7206 return strlen (c) + 1;
7207}
7208
7209/* Helper that outputs a depndency. */
7210
7211MY_INLINE char *helper_dep_output_one (char *o, struct dep *d,
7212 unsigned int style, int is_last)
7213{
7214 const char *c = dep_name (d);
7215#ifndef NO_ARCHIVES
7216 if (ar_name (c))
7217 {
7218 c = strchr(c, '(') + 1;
7219 o = helper_return_file_len (o, c, strlen(c) - 1, style, is_last);
7220 }
7221 else
7222#endif
7223#ifdef CONFIG_WITH_STRCACHE2
7224 if (!d->need_2nd_expansion)
7225 {
7226 unsigned int len = strcache2_get_len (&file_strcache, c);
7227 o = helper_return_file_len (o, c, len, style, is_last);
7228 }
7229 else
7230#endif
7231 o = helper_return_file (o, c, style, is_last);
7232 return o;
7233}
7234
7235/* Implements $^/$(deps )/$(qdeps ) and $+/$(deps-all )/$(qdeps-all ).
7236
7237 If no second argument is given, or if it's empty, or if it's zero,
7238 all dependencies will be returned. If the second argument is non-zero
7239 the dependency at that position will be returned. If the argument is
7240 negative a fatal error is thrown. */
7241static char *
7242worker_deps (char *o, char **argv, const char *funcname, unsigned int style,
7243 int all_deps)
7244{
7245 unsigned int idx = parse_dep_index (argv[1], funcname);
7246 struct file *file;
7247
7248 /* Find the file and select the list corresponding to FUNCNAME. */
7249
7250 file = lookup_file (argv[0]);
7251 if (file)
7252 {
7253 struct dep *deps;
7254 struct dep *d;
7255 if (!all_deps)
7256 {
7257 deps = file->deps_no_dupes;
7258 if (!deps && file->deps)
7259 deps = file->deps_no_dupes = create_uniqute_deps_chain (file->deps);
7260 }
7261 else
7262 deps = file->deps;
7263
7264 if ( file->double_colon
7265 && ( file->double_colon != file
7266 || file->last != file))
7267 OSS (error, NILF, _("$(%s ) cannot be used on files with multiple double colon rules like `%s'\n"),
7268 funcname, file->name);
7269
7270 if (idx == 0 /* all */)
7271 {
7272 /* Since this may be a long list, calculate the output space needed if
7273 no quoting takes place and no multichar separators are used. */
7274
7275 unsigned int total_len = 0;
7276 for (d = deps; d; d = d->next)
7277 if (!d->ignore_mtime)
7278 total_len += helper_dep_output_len (d);
7279 if (total_len > 0)
7280 {
7281 o = ensure_variable_buffer_space (o, total_len);
7282
7283 for (d = deps; d; d = d->next)
7284 if (!d->ignore_mtime)
7285 o = helper_dep_output_one (o, d, style, 0 /*is_last*/);
7286
7287 /* nuke the last list separator */
7288 o = helper_drop_separator (o, style);
7289 }
7290 }
7291 else
7292 {
7293 /* Dependency given by index. */
7294
7295 for (d = deps; d; d = d->next)
7296 if (!d->ignore_mtime)
7297 if (--idx == 0) /* 1 based indexing */
7298 return helper_dep_output_one (o, d, style, 1 /*is_last*/);
7299 }
7300 }
7301
7302 return o;
7303}
7304
7305/* Implements $? / $(deps-newer ) / $(qdeps-newer ).
7306
7307 If no second argument is given, or if it's empty, or if it's zero,
7308 all dependencies will be returned. If the second argument is non-zero
7309 the dependency at that position will be returned. If the argument is
7310 negative a fatal error is thrown. */
7311static char *
7312worker_deps_newer (char *o, char **argv, const char *funcname, unsigned int style)
7313{
7314 unsigned int idx = parse_dep_index (argv[1], funcname);
7315 struct file *file;
7316
7317 /* Find the file. */
7318
7319 file = lookup_file (argv[0]);
7320 if (file)
7321 {
7322 struct dep *deps = file->deps;
7323 struct dep *d;
7324
7325 if ( file->double_colon
7326 && ( file->double_colon != file
7327 || file->last != file))
7328 OSS (error, NILF, _("$(%s ) cannot be used on files with multiple double colon rules like `%s'\n"),
7329 funcname, file->name);
7330
7331 if (idx == 0 /* all */)
7332 {
7333 unsigned int total_len = 0;
7334
7335 /* calc the result length. */
7336
7337 for (d = deps; d; d = d->next)
7338 if (!d->ignore_mtime && d->changed)
7339 total_len += helper_dep_output_len (d);
7340 if (total_len)
7341 {
7342 o = ensure_variable_buffer_space (o, total_len);
7343
7344 for (d = deps; d; d = d->next)
7345 if (!d->ignore_mtime && d->changed)
7346 o = helper_dep_output_one (o, d, style, 0 /*is_last*/);
7347
7348 /* nuke the last list separator */
7349 o = helper_drop_separator (o, style);
7350 }
7351 }
7352 else
7353 {
7354 /* Dependency given by index. */
7355
7356 for (d = deps; d; d = d->next)
7357 if (!d->ignore_mtime && d->changed)
7358 if (--idx == 0) /* 1 based indexing */
7359 return helper_dep_output_one (o, d, style, 1 /*is_last*/);
7360 }
7361 }
7362
7363 return o;
7364}
7365
7366/* Implements $|, the order only dependency list.
7367
7368 If no second argument is given, or if it's empty, or if it's zero,
7369 all dependencies will be returned. If the second argument is non-zero
7370 the dependency at that position will be returned. If the argument is
7371 negative a fatal error is thrown. */
7372static char *
7373worker_deps_order_only (char *o, char **argv, const char *funcname, unsigned int style)
7374{
7375 unsigned int idx = parse_dep_index (argv[1], funcname);
7376 struct file *file;
7377
7378 /* Find the file. */
7379
7380 file = lookup_file (argv[0]);
7381 if (file)
7382 {
7383 struct dep *deps = file->deps;
7384 struct dep *d;
7385
7386 if ( file->double_colon
7387 && ( file->double_colon != file
7388 || file->last != file))
7389 OSS (error, NILF, _("$(%s ) cannot be used on files with multiple double colon rules like `%s'\n"),
7390 funcname, file->name);
7391
7392 if (idx == 0 /* all */)
7393 {
7394 unsigned int total_len = 0;
7395
7396 /* calc the result length. */
7397
7398 for (d = deps; d; d = d->next)
7399 if (d->ignore_mtime)
7400 total_len += helper_dep_output_len (d);
7401 if (total_len)
7402 {
7403 o = ensure_variable_buffer_space (o, total_len);
7404
7405 for (d = deps; d; d = d->next)
7406 if (d->ignore_mtime)
7407 o = helper_dep_output_one (o, d, style, 0 /*is_last*/);
7408
7409 /* nuke the last list separator */
7410 o = helper_drop_separator (o, style);
7411 }
7412 }
7413 else
7414 {
7415 /* Dependency given by index. */
7416
7417 for (d = deps; d; d = d->next)
7418 if (d->ignore_mtime)
7419 if (--idx == 0) /* 1 based indexing */
7420 return helper_dep_output_one (o, d, style, 1 /*is_last*/);
7421 }
7422 }
7423
7424 return o;
7425}
7426
7427/* Implements $^ and $+.
7428
7429 The first comes with FUNCNAME 'deps', the second as 'deps-all'.
7430
7431 If no second argument is given, or if it's empty, or if it's zero,
7432 all dependencies will be returned. If the second argument is non-zero
7433 the dependency at that position will be returned. If the argument is
7434 negative a fatal error is thrown. */
7435static char *
7436func_deps (char *o, char **argv, const char *funcname)
7437{
7438# ifdef VMS
7439 return worker_deps (o, argv, funcname, Q_RET_UNQUOTED | Q_SEP_COMMA,
7440# else
7441 return worker_deps (o, argv, funcname, Q_RET_UNQUOTED | Q_SEP_SPACE,
7442# endif
7443 funcname[4] != '\0');
7444}
7445
7446/* Implements $?.
7447
7448 If no second argument is given, or if it's empty, or if it's zero,
7449 all dependencies will be returned. If the second argument is non-zero
7450 the dependency at that position will be returned. If the argument is
7451 negative a fatal error is thrown. */
7452static char *
7453func_deps_newer (char *o, char **argv, const char *funcname)
7454{
7455# ifdef VMS
7456 return worker_deps_newer (o, argv, funcname, Q_RET_UNQUOTED | Q_SEP_COMMA);
7457# else
7458 return worker_deps_newer (o, argv, funcname, Q_RET_UNQUOTED | Q_SEP_SPACE);
7459# endif
7460}
7461
7462/* Implements $|, the order only dependency list.
7463
7464 If no second argument is given, or if it's empty, or if it's zero,
7465 all dependencies will be returned. If the second argument is non-zero
7466 the dependency at that position will be returned. If the argument is
7467 negative a fatal error is thrown. */
7468static char *
7469func_deps_order_only (char *o, char **argv, const char *funcname)
7470{
7471# ifdef VMS
7472 return worker_deps_order_only (o, argv, funcname, Q_RET_UNQUOTED | Q_SEP_COMMA);
7473# else
7474 return worker_deps_order_only (o, argv, funcname, Q_RET_UNQUOTED | Q_SEP_SPACE);
7475# endif
7476}
7477
7478#endif /* CONFIG_WITH_LAZY_DEPS_VARS */
7479#ifdef KMK
7480
7481/* Implements $(qdeps ) and $(qdeps-all )
7482
7483 If no third argument is given, or if it's empty, or if it's zero,
7484 all dependencies will be returned. If the third argument is non-zero
7485 the dependency at that position will be returned. If the argument is
7486 negative a fatal error is thrown. */
7487static char *
7488func_q_deps (char *o, char **argv, const char *funcname)
7489{
7490 unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
7491 return worker_deps (o, &argv[1], funcname, style, funcname[5] != '\0');
7492}
7493
7494/* Implements $(qdeps-newer ).
7495
7496 If no third argument is given, or if it's empty, or if it's zero,
7497 all dependencies will be returned. If the third argument is non-zero
7498 the dependency at that position will be returned. If the argument is
7499 negative a fatal error is thrown. */
7500static char *
7501func_q_deps_newer (char *o, char **argv, const char *funcname)
7502{
7503 unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
7504 return worker_deps_newer (o, &argv[1], funcname, style);
7505}
7506
7507/* Implements $(qdeps-oo ), the order only dependency list.
7508
7509 If no third argument is given, or if it's empty, or if it's zero,
7510 all dependencies will be returned. If the third argument is non-zero
7511 the dependency at that position will be returned. If the argument is
7512 negative a fatal error is thrown. */
7513static char *
7514func_q_deps_order_only (char *o, char **argv, const char *funcname)
7515{
7516 unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
7517 return worker_deps_order_only (o, &argv[1], funcname, style);
7518}
7519
7520/* Implements $(qtarget ), converting a single unquoted file to the given
7521 quoting style.
7522
7523 Typically used like this:
7524 $(qtarget sh,$@)
7525 $(qone-unquoted sh,$@) */
7526static char *
7527func_q_one_unquoted (char *o, char **argv, const char *funcname)
7528{
7529 unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
7530 return helper_return_file (o, argv[1], style, 1 /*is_last*/);
7531}
7532
7533#endif /* KMK */
7534
7535/* Lookup table for builtin functions.
7536
7537 This doesn't have to be sorted; we use a straight lookup. We might gain
7538 some efficiency by moving most often used functions to the start of the
7539 table.
7540
7541 If MAXIMUM_ARGS is 0, that means there is no maximum and all
7542 comma-separated values are treated as arguments.
7543
7544 EXPAND_ARGS means that all arguments should be expanded before invocation.
7545 Functions that do namespace tricks (foreach) don't automatically expand. */
7546
7547static char *func_call (char *o, char **argv, const char *funcname);
7548
7549#define FT_ENTRY(_name, _min, _max, _exp, _func) \
7550 { { (_func) }, STRING_SIZE_TUPLE(_name), (_min), (_max), (_exp), 0 }
7551
7552static struct function_table_entry function_table_init[] =
7553{
7554 /* Name MIN MAX EXP? Function */
7555 FT_ENTRY ("abspath", 0, 1, 1, func_abspath),
7556 FT_ENTRY ("addprefix", 2, 2, 1, func_addsuffix_addprefix),
7557 FT_ENTRY ("addsuffix", 2, 2, 1, func_addsuffix_addprefix),
7558 FT_ENTRY ("basename", 0, 1, 1, func_basename_dir),
7559 FT_ENTRY ("dir", 0, 1, 1, func_basename_dir),
7560 FT_ENTRY ("notdir", 0, 1, 1, func_notdir_suffix),
7561#ifdef CONFIG_WITH_ROOT_FUNC
7562 FT_ENTRY ("root", 0, 1, 1, func_root),
7563 FT_ENTRY ("notroot", 0, 1, 1, func_notroot),
7564#endif
7565 FT_ENTRY ("subst", 3, 3, 1, func_subst),
7566 FT_ENTRY ("suffix", 0, 1, 1, func_notdir_suffix),
7567 FT_ENTRY ("filter", 2, 2, 1, func_filter_filterout),
7568 FT_ENTRY ("filter-out", 2, 2, 1, func_filter_filterout),
7569 FT_ENTRY ("findstring", 2, 2, 1, func_findstring),
7570#ifdef CONFIG_WITH_DEFINED_FUNCTIONS
7571 FT_ENTRY ("firstdefined", 0, 2, 1, func_firstdefined),
7572#endif
7573 FT_ENTRY ("firstword", 0, 1, 1, func_firstword),
7574 FT_ENTRY ("flavor", 0, 1, 1, func_flavor),
7575 FT_ENTRY ("join", 2, 2, 1, func_join),
7576#ifdef CONFIG_WITH_DEFINED_FUNCTIONS
7577 FT_ENTRY ("lastdefined", 0, 2, 1, func_lastdefined),
7578#endif
7579 FT_ENTRY ("lastword", 0, 1, 1, func_lastword),
7580 FT_ENTRY ("patsubst", 3, 3, 1, func_patsubst),
7581 FT_ENTRY ("realpath", 0, 1, 1, func_realpath),
7582#ifdef CONFIG_WITH_RSORT
7583 FT_ENTRY ("rsort", 0, 1, 1, func_sort),
7584# ifdef KMK
7585 FT_ENTRY ("rversort", 0, 1, 1, func_sort),
7586# endif
7587#endif
7588 FT_ENTRY ("shell", 0, 1, 1, func_shell),
7589 FT_ENTRY ("sort", 0, 1, 1, func_sort),
7590# ifdef KMK
7591 FT_ENTRY ("versort", 0, 1, 1, func_sort),
7592# endif
7593 FT_ENTRY ("strip", 0, 1, 1, func_strip),
7594#ifdef CONFIG_WITH_WHERE_FUNCTION
7595 FT_ENTRY ("where", 0, 1, 1, func_where),
7596#endif
7597 FT_ENTRY ("wildcard", 0, 1, 1, func_wildcard),
7598 FT_ENTRY ("word", 2, 2, 1, func_word),
7599 FT_ENTRY ("wordlist", 3, 3, 1, func_wordlist),
7600 FT_ENTRY ("words", 0, 1, 1, func_words),
7601 FT_ENTRY ("origin", 0, 1, 1, func_origin),
7602 FT_ENTRY ("foreach", 3, 3, 0, func_foreach),
7603#ifdef CONFIG_WITH_LOOP_FUNCTIONS
7604 FT_ENTRY ("for", 4, 4, 0, func_for),
7605 FT_ENTRY ("while", 2, 2, 0, func_while),
7606#endif
7607 FT_ENTRY ("call", 1, 0, 1, func_call),
7608 FT_ENTRY ("info", 0, 1, 1, func_error),
7609 FT_ENTRY ("error", 0, 1, 1, func_error),
7610 FT_ENTRY ("warning", 0, 1, 1, func_error),
7611 FT_ENTRY ("if", 2, 3, 0, func_if),
7612 FT_ENTRY ("or", 1, 0, 0, func_or),
7613 FT_ENTRY ("and", 1, 0, 0, func_and),
7614 FT_ENTRY ("value", 0, 1, 1, func_value),
7615#ifdef EXPERIMENTAL
7616 FT_ENTRY ("eq", 2, 2, 1, func_eq),
7617 FT_ENTRY ("not", 0, 1, 1, func_not),
7618#endif
7619 FT_ENTRY ("eval", 0, 1, 1, func_eval),
7620#ifdef CONFIG_WITH_EVALPLUS
7621 FT_ENTRY ("evalctx", 0, 1, 1, func_evalctx),
7622 FT_ENTRY ("evalval", 1, 1, 1, func_evalval),
7623 FT_ENTRY ("evalvalctx", 1, 1, 1, func_evalval),
7624 FT_ENTRY ("evalcall", 1, 0, 1, func_call),
7625 FT_ENTRY ("evalcall2", 1, 0, 1, func_call),
7626 FT_ENTRY ("eval-opt-var", 1, 0, 1, func_eval_optimize_variable),
7627#endif
7628 FT_ENTRY ("file", 1, 2, 1, func_file),
7629#ifdef CONFIG_WITH_STRING_FUNCTIONS
7630 FT_ENTRY ("length", 1, 1, 1, func_length),
7631 FT_ENTRY ("length-var", 1, 1, 1, func_length_var),
7632 FT_ENTRY ("insert", 2, 5, 1, func_insert),
7633 FT_ENTRY ("pos", 2, 3, 1, func_pos),
7634 FT_ENTRY ("lastpos", 2, 3, 1, func_pos),
7635 FT_ENTRY ("substr", 2, 4, 1, func_substr),
7636 FT_ENTRY ("translate", 2, 4, 1, func_translate),
7637#endif
7638#ifdef CONFIG_WITH_PRINTF
7639 FT_ENTRY ("printf", 1, 0, 1, kmk_builtin_func_printf),
7640#endif
7641#ifdef CONFIG_WITH_LAZY_DEPS_VARS
7642 FT_ENTRY ("deps", 1, 2, 1, func_deps),
7643 FT_ENTRY ("deps-all", 1, 2, 1, func_deps),
7644 FT_ENTRY ("deps-newer", 1, 2, 1, func_deps_newer),
7645 FT_ENTRY ("deps-oo", 1, 2, 1, func_deps_order_only),
7646#endif
7647#ifdef CONFIG_WITH_DEFINED
7648 FT_ENTRY ("defined", 1, 1, 1, func_defined),
7649#endif
7650#ifdef CONFIG_WITH_TOUPPER_TOLOWER
7651 FT_ENTRY ("toupper", 0, 1, 1, func_toupper_tolower),
7652 FT_ENTRY ("tolower", 0, 1, 1, func_toupper_tolower),
7653#endif
7654#ifdef CONFIG_WITH_ABSPATHEX
7655 FT_ENTRY ("abspathex", 0, 2, 1, func_abspathex),
7656#endif
7657#ifdef CONFIG_WITH_XARGS
7658 FT_ENTRY ("xargs", 2, 0, 1, func_xargs),
7659#endif
7660#if defined(CONFIG_WITH_VALUE_LENGTH) && defined(CONFIG_WITH_COMPARE)
7661 FT_ENTRY ("comp-vars", 3, 3, 1, func_comp_vars),
7662 FT_ENTRY ("comp-cmds", 3, 3, 1, func_comp_vars),
7663 FT_ENTRY ("comp-cmds-ex", 3, 3, 1, func_comp_cmds_ex),
7664#endif
7665#ifdef CONFIG_WITH_DATE
7666 FT_ENTRY ("date", 0, 1, 1, func_date),
7667 FT_ENTRY ("date-utc", 0, 3, 1, func_date),
7668#endif
7669#ifdef CONFIG_WITH_FILE_SIZE
7670 FT_ENTRY ("file-size", 1, 1, 1, func_file_size),
7671#endif
7672#ifdef CONFIG_WITH_WHICH
7673 FT_ENTRY ("which", 0, 0, 1, func_which),
7674#endif
7675#ifdef CONFIG_WITH_IF_CONDITIONALS
7676 FT_ENTRY ("expr", 1, 1, 0, func_expr),
7677 FT_ENTRY ("if-expr", 2, 3, 0, func_if_expr),
7678 FT_ENTRY ("select", 2, 0, 0, func_select),
7679#endif
7680#ifdef CONFIG_WITH_SET_CONDITIONALS
7681 FT_ENTRY ("intersects", 2, 2, 1, func_set_intersects),
7682#endif
7683#ifdef CONFIG_WITH_STACK
7684 FT_ENTRY ("stack-push", 2, 2, 1, func_stack_push),
7685 FT_ENTRY ("stack-pop", 1, 1, 1, func_stack_pop_top),
7686 FT_ENTRY ("stack-popv", 1, 1, 1, func_stack_pop_top),
7687 FT_ENTRY ("stack-top", 1, 1, 1, func_stack_pop_top),
7688#endif
7689#ifdef CONFIG_WITH_MATH
7690 FT_ENTRY ("int-add", 2, 0, 1, func_int_add),
7691 FT_ENTRY ("int-sub", 2, 0, 1, func_int_sub),
7692 FT_ENTRY ("int-mul", 2, 0, 1, func_int_mul),
7693 FT_ENTRY ("int-div", 2, 0, 1, func_int_div),
7694 FT_ENTRY ("int-mod", 2, 2, 1, func_int_mod),
7695 FT_ENTRY ("int-not", 1, 1, 1, func_int_not),
7696 FT_ENTRY ("int-and", 2, 0, 1, func_int_and),
7697 FT_ENTRY ("int-or", 2, 0, 1, func_int_or),
7698 FT_ENTRY ("int-xor", 2, 0, 1, func_int_xor),
7699 FT_ENTRY ("int-eq", 2, 2, 1, func_int_cmp),
7700 FT_ENTRY ("int-ne", 2, 2, 1, func_int_cmp),
7701 FT_ENTRY ("int-gt", 2, 2, 1, func_int_cmp),
7702 FT_ENTRY ("int-ge", 2, 2, 1, func_int_cmp),
7703 FT_ENTRY ("int-lt", 2, 2, 1, func_int_cmp),
7704 FT_ENTRY ("int-le", 2, 2, 1, func_int_cmp),
7705#endif
7706#ifdef CONFIG_WITH_NANOTS
7707 FT_ENTRY ("nanots", 0, 0, 0, func_nanots),
7708#endif
7709#ifdef CONFIG_WITH_OS2_LIBPATH
7710 FT_ENTRY ("libpath", 1, 2, 1, func_os2_libpath),
7711#endif
7712#if defined (CONFIG_WITH_MAKE_STATS) || defined (CONFIG_WITH_MINIMAL_STATS)
7713 FT_ENTRY ("make-stats", 0, 0, 0, func_make_stats),
7714#endif
7715#ifdef CONFIG_WITH_COMMANDS_FUNC
7716 FT_ENTRY ("commands", 1, 1, 1, func_commands),
7717 FT_ENTRY ("commands-sc", 1, 1, 1, func_commands),
7718 FT_ENTRY ("commands-usr", 2, 2, 1, func_commands),
7719#endif
7720#ifdef KMK_HELPERS
7721 FT_ENTRY ("kb-src-tool", 1, 2, 0, func_kbuild_source_tool),
7722 FT_ENTRY ("kb-obj-base", 1, 2, 0, func_kbuild_object_base),
7723 FT_ENTRY ("kb-obj-suff", 1, 2, 0, func_kbuild_object_suffix),
7724 FT_ENTRY ("kb-src-prop", 3, 4, 0, func_kbuild_source_prop),
7725 FT_ENTRY ("kb-src-one", 0, 1, 0, func_kbuild_source_one),
7726 FT_ENTRY ("kb-exp-tmpl", 6, 6, 1, func_kbuild_expand_template),
7727#endif
7728#ifdef KMK
7729 FT_ENTRY ("dircache-ctl", 1, 0, 1, func_dircache_ctl),
7730 FT_ENTRY ("breakpoint", 0, 0, 0, func_breakpoint),
7731 FT_ENTRY ("set-umask", 1, 3, 1, func_set_umask),
7732 FT_ENTRY ("get-umask", 0, 0, 0, func_get_umask),
7733#endif
7734#ifdef KMK
7735 FT_ENTRY ("quote", 1, 0, 1, func_quote_make),
7736 FT_ENTRY ("quote-dep", 1, 0, 1, func_quote_make),
7737 FT_ENTRY ("quote-tgt", 1, 0, 1, func_quote_make),
7738 FT_ENTRY ("quote-depend", 1, 0, 1, func_quote_make),
7739 FT_ENTRY ("quote-tgtend", 1, 0, 1, func_quote_make),
7740 FT_ENTRY ("quote-sh", 1, 0, 1, func_quote_shell),
7741 FT_ENTRY ("quote-sh-dq", 1, 1, 1, func_quote_shell_dq),
7742 FT_ENTRY ("quote-sh-sq", 1, 1, 1, func_quote_shell_sq),
7743 FT_ENTRY ("requote", 1, 0, 1, func_requote),
7744 /* Quoted input and maybe output variants of functions typically
7745 working with files: */
7746 FT_ENTRY ("firstfile", 0, 1, 1, func_firstfile),
7747 FT_ENTRY ("lastfile", 0, 1, 1, func_lastfile),
7748 FT_ENTRY ("filelist", 3, 3, 1, func_filelist),
7749 FT_ENTRY ("countfiles", 0, 1, 1, func_countfiles),
7750 FT_ENTRY ("foreachfile", 3, 3, 0, func_foreachfile),
7751 FT_ENTRY ("sortfiles", 0, 1, 1, func_sortfiles),
7752 FT_ENTRY ("versortfiles", 0, 1, 1, func_sortfiles),
7753# ifdef CONFIG_WITH_RSORT
7754 FT_ENTRY ("rsortfiles", 0, 1, 1, func_sortfiles),
7755 FT_ENTRY ("rversortfiles", 0, 1, 1, func_sortfiles),
7756# endif
7757 /* Function variants with preceding style argument and quoting by default. */
7758 FT_ENTRY ("qfirstfile", 1+0, 1+1, 1, func_q_firstfile),
7759 FT_ENTRY ("qlastfile", 1+0, 1+1, 1, func_q_lastfile),
7760 FT_ENTRY ("qfilelist", 1+3, 1+3, 1, func_q_filelist),
7761 FT_ENTRY ("qcountfiles", 1+0, 1+1, 1, func_q_countfiles),
7762 FT_ENTRY ("qforeachfile", 1+3, 1+3, 0, func_q_foreachfile),
7763 FT_ENTRY ("qsortfiles", 1+0, 1+1, 1, func_q_sortfiles),
7764 FT_ENTRY ("qversortfiles",1+0, 1+1, 1, func_q_sortfiles),
7765# ifdef CONFIG_WITH_RSORT
7766 FT_ENTRY ("qrsortfiles", 1+0, 1+1, 1, func_q_sortfiles),
7767 FT_ENTRY ("qrversortfiles",1+0,1+1, 1, func_q_sortfiles),
7768# endif
7769 FT_ENTRY ("qabspath", 1+0, 1+1, 1, func_q_abspath),
7770 FT_ENTRY ("qaddprefix", 1+2, 1+2, 1, func_q_addsuffix_addprefix),
7771 FT_ENTRY ("qaddsuffix", 1+2, 1+2, 1, func_q_addsuffix_addprefix),
7772 FT_ENTRY ("qbasename", 1+0, 1+1, 1, func_q_basename_dir),
7773 FT_ENTRY ("qdir", 1+0, 1+1, 1, func_q_basename_dir),
7774 FT_ENTRY ("qnotdir", 1+0, 1+1, 1, func_q_notdir),
7775# ifdef CONFIG_WITH_ROOT_FUNC
7776 FT_ENTRY ("qroot", 1+0, 1+1, 1, func_q_root),
7777 FT_ENTRY ("qnotroot", 1+0, 1+1, 1, func_q_notroot),
7778# endif
7779 FT_ENTRY ("qsuffix", 1+0, 1+1, 1, func_q_suffix),
7780 FT_ENTRY ("qrealpath", 1+0, 1+1, 1, func_q_realpath),
7781# ifdef CONFIG_WITH_ABSPATHEX
7782 FT_ENTRY ("qabspathex", 1+0, 1+2, 1, func_q_abspathex),
7783# endif
7784 FT_ENTRY ("qwildcard", 1+0, 1+1, 1, func_q_wildcard),
7785 FT_ENTRY ("qone-unquoted",1+1, 1+1, 1, func_q_one_unquoted),
7786 FT_ENTRY ("qtarget", 1+1, 1+1, 1, func_q_one_unquoted), /* For requoting plain $@ to given style. */
7787 FT_ENTRY ("qdeps", 1+1, 1+2, 1, func_q_deps), /* $^ with quoting style */
7788 FT_ENTRY ("qdeps-all", 1+1, 1+2, 1, func_q_deps), /* $+ with quoting style */
7789 FT_ENTRY ("qdeps-newer", 1+1, 1+2, 1, func_q_deps_newer), /* $? with quoting style */
7790 FT_ENTRY ("qdeps-oo", 1+1, 1+2, 1, func_q_deps_order_only), /* $| with quoting style */
7791 FT_ENTRY ("qfilter", 1+2, 1+2, 1, func_q_filter_filterout),
7792 FT_ENTRY ("qfilter-out", 1+2, 1+2, 1, func_q_filter_filterout),
7793 /** @todo XXX: Add more qxxxx variants. */
7794#endif
7795};
7796
7797#define FUNCTION_TABLE_ENTRIES (sizeof (function_table_init) / sizeof (struct function_table_entry))
7798
7799
7800
7801/* These must come after the definition of function_table. */
7802
7803static char *
7804expand_builtin_function (char *o, int argc, char **argv,
7805 const struct function_table_entry *entry_p)
7806{
7807 char *p;
7808
7809 if (argc < (int)entry_p->minimum_args)
7810 fatal (*expanding_var, strlen (entry_p->name),
7811 _("insufficient number of arguments (%d) to function '%s'"),
7812 argc, entry_p->name);
7813
7814 /* I suppose technically some function could do something with no arguments,
7815 but so far no internal ones do, so just test it for all functions here
7816 rather than in each one. We can change it later if necessary. */
7817
7818 if (!argc && !entry_p->alloc_fn)
7819 return o;
7820
7821 if (!entry_p->fptr.func_ptr)
7822 OS (fatal, *expanding_var,
7823 _("unimplemented on this platform: function '%s'"), entry_p->name);
7824
7825 if (!entry_p->alloc_fn)
7826 return entry_p->fptr.func_ptr (o, argv, entry_p->name);
7827
7828 /* This function allocates memory and returns it to us.
7829 Write it to the variable buffer, then free it. */
7830
7831 p = entry_p->fptr.alloc_func_ptr (entry_p->name, argc, argv);
7832 if (p)
7833 {
7834 o = variable_buffer_output (o, p, strlen (p));
7835 free (p);
7836 }
7837
7838 return o;
7839}
7840
7841/* Check for a function invocation in *STRINGP. *STRINGP points at the
7842 opening ( or { and is not null-terminated. If a function invocation
7843 is found, expand it into the buffer at *OP, updating *OP, incrementing
7844 *STRINGP past the reference and returning nonzero. If not, return zero. */
7845
7846static int
7847handle_function2 (const struct function_table_entry *entry_p, char **op, const char **stringp) /* bird split it up. */
7848{
7849 char openparen = (*stringp)[0];
7850 char closeparen = openparen == '(' ? ')' : '}';
7851 const char *beg;
7852 const char *end;
7853 int count = 0;
7854 char *abeg = NULL;
7855 char **argv, **argvp;
7856 int nargs;
7857
7858 beg = *stringp + 1;
7859
7860 /* We found a builtin function. Find the beginning of its arguments (skip
7861 whitespace after the name). */
7862
7863 beg += entry_p->len;
7864 NEXT_TOKEN (beg);
7865
7866 /* Find the end of the function invocation, counting nested use of
7867 whichever kind of parens we use. Since we're looking, count commas
7868 to get a rough estimate of how many arguments we might have. The
7869 count might be high, but it'll never be low. */
7870
7871 for (nargs=1, end=beg; *end != '\0'; ++end)
7872 if (*end == ',')
7873 ++nargs;
7874 else if (*end == openparen)
7875 ++count;
7876 else if (*end == closeparen && --count < 0)
7877 break;
7878
7879 if (count >= 0)
7880 fatal (*expanding_var, strlen (entry_p->name),
7881 _("unterminated call to function '%s': missing '%c'"),
7882 entry_p->name, closeparen);
7883
7884 *stringp = end;
7885
7886 /* Get some memory to store the arg pointers. */
7887 argvp = argv = alloca (sizeof (char *) * (nargs + 2));
7888
7889 /* Chop the string into arguments, then a nul. As soon as we hit
7890 MAXIMUM_ARGS (if it's >0) assume the rest of the string is part of the
7891 last argument.
7892
7893 If we're expanding, store pointers to the expansion of each one. If
7894 not, make a duplicate of the string and point into that, nul-terminating
7895 each argument. */
7896
7897 if (entry_p->expand_args)
7898 {
7899 const char *p;
7900 for (p=beg, nargs=0; p <= end; ++argvp)
7901 {
7902 const char *next;
7903
7904 ++nargs;
7905
7906 if (nargs == entry_p->maximum_args
7907 || (! (next = find_next_argument (openparen, closeparen, p, end))))
7908 next = end;
7909
7910 *argvp = expand_argument (p, next);
7911 p = next + 1;
7912 }
7913 }
7914 else
7915 {
7916 int len = end - beg;
7917 char *p, *aend;
7918
7919 abeg = xmalloc (len+1);
7920 memcpy (abeg, beg, len);
7921 abeg[len] = '\0';
7922 aend = abeg + len;
7923
7924 for (p=abeg, nargs=0; p <= aend; ++argvp)
7925 {
7926 char *next;
7927
7928 ++nargs;
7929
7930 if (nargs == entry_p->maximum_args
7931 || (! (next = find_next_argument (openparen, closeparen, p, aend))))
7932 next = aend;
7933
7934 *argvp = p;
7935 *next = '\0';
7936 p = next + 1;
7937 }
7938 }
7939 *argvp = NULL;
7940
7941 /* Finally! Run the function... */
7942 *op = expand_builtin_function (*op, nargs, argv, entry_p);
7943
7944 /* Free memory. */
7945 if (entry_p->expand_args)
7946 for (argvp=argv; *argvp != 0; ++argvp)
7947 free (*argvp);
7948 else
7949 free (abeg);
7950
7951 return 1;
7952}
7953
7954
7955int /* bird split it up and hacked it. */
7956#ifndef CONFIG_WITH_VALUE_LENGTH
7957handle_function (char **op, const char **stringp)
7958{
7959 const struct function_table_entry *entry_p = lookup_function (*stringp + 1);
7960 if (!entry_p)
7961 return 0;
7962 return handle_function2 (entry_p, op, stringp);
7963}
7964#else /* CONFIG_WITH_VALUE_LENGTH */
7965handle_function (char **op, const char **stringp, const char *nameend, const char *eol UNUSED)
7966{
7967 const char *fname = *stringp + 1;
7968 const struct function_table_entry *entry_p =
7969 lookup_function_in_hash_tab (fname, nameend - fname);
7970 if (!entry_p)
7971 return 0;
7972 return handle_function2 (entry_p, op, stringp);
7973}
7974#endif /* CONFIG_WITH_VALUE_LENGTH */
7975
7976#ifdef CONFIG_WITH_COMPILER
7977/* Used by the "compiler" to get all info about potential functions. */
7978make_function_ptr_t
7979lookup_function_for_compiler (const char *name, unsigned int len,
7980 unsigned char *minargsp, unsigned char *maxargsp,
7981 char *expargsp, const char **funcnamep)
7982{
7983 const struct function_table_entry *entry_p = lookup_function (name, len);
7984 if (!entry_p)
7985 return 0;
7986 *minargsp = entry_p->minimum_args;
7987 *maxargsp = entry_p->maximum_args;
7988 *expargsp = entry_p->expand_args;
7989 *funcnamep = entry_p->name;
7990 return entry_p->func_ptr;
7991}
7992#endif /* CONFIG_WITH_COMPILER */
7993
7994
7995
7996/* User-defined functions. Expand the first argument as either a builtin
7997 function or a make variable, in the context of the rest of the arguments
7998 assigned to $1, $2, ... $N. $0 is the name of the function. */
7999
8000static char *
8001func_call (char *o, char **argv, const char *funcname UNUSED)
8002{
8003 static int max_args = 0;
8004 char *fname;
8005 char *body;
8006 int flen;
8007 int i;
8008 int saved_args;
8009 const struct function_table_entry *entry_p;
8010 struct variable *v;
8011#ifdef CONFIG_WITH_EVALPLUS
8012 char *buf;
8013 unsigned int len;
8014#endif
8015#ifdef CONFIG_WITH_VALUE_LENGTH
8016 char *fname_end;
8017#endif
8018#if defined (CONFIG_WITH_EVALPLUS) || defined (CONFIG_WITH_VALUE_LENGTH)
8019 char num[11];
8020#endif
8021
8022 /* Clean up the name of the variable to be invoked. */
8023 fname = next_token (argv[0]);
8024#ifndef CONFIG_WITH_VALUE_LENGTH
8025 end_of_token (fname)[0] = '\0';
8026#else
8027 fname_end = end_of_token (fname);
8028 *fname_end = '\0';
8029#endif
8030
8031 /* Calling nothing is a no-op */
8032#ifndef CONFIG_WITH_VALUE_LENGTH
8033 if (*fname == '\0')
8034#else
8035 if (fname == fname_end)
8036#endif
8037 return o;
8038
8039 /* Are we invoking a builtin function? */
8040
8041#ifndef CONFIG_WITH_VALUE_LENGTH
8042 entry_p = lookup_function (fname);
8043#else
8044 entry_p = lookup_function (fname, fname_end - fname);
8045#endif
8046 if (entry_p)
8047 {
8048 /* How many arguments do we have? */
8049 for (i=0; argv[i+1]; ++i)
8050 ;
8051 return expand_builtin_function (o, i, argv+1, entry_p);
8052 }
8053
8054 /* Not a builtin, so the first argument is the name of a variable to be
8055 expanded and interpreted as a function. Find it. */
8056 flen = strlen (fname);
8057
8058 v = lookup_variable (fname, flen);
8059
8060 if (v == 0)
8061 warn_undefined (fname, flen);
8062
8063 if (v == 0 || *v->value == '\0')
8064 return o;
8065
8066 body = alloca (flen + 4);
8067 body[0] = '$';
8068 body[1] = '(';
8069 memcpy (body + 2, fname, flen);
8070 body[flen+2] = ')';
8071 body[flen+3] = '\0';
8072
8073 /* Set up arguments $(1) .. $(N). $(0) is the function name. */
8074
8075 push_new_variable_scope ();
8076
8077 for (i=0; *argv; ++i, ++argv)
8078#ifdef CONFIG_WITH_VALUE_LENGTH
8079 define_variable (num, sprintf (num, "%d", i), *argv, o_automatic, 0);
8080#else
8081 {
8082 char num[11];
8083
8084 sprintf (num, "%d", i);
8085 define_variable (num, strlen (num), *argv, o_automatic, 0);
8086 }
8087#endif
8088
8089#ifdef CONFIG_WITH_EVALPLUS
8090 /* $(.ARGC) is the argument count. */
8091
8092 len = sprintf (num, "%d", i - 1);
8093 define_variable_vl (".ARGC", sizeof (".ARGC") - 1, num, len,
8094 1 /* dup val */, o_automatic, 0);
8095#endif
8096
8097 /* If the number of arguments we have is < max_args, it means we're inside
8098 a recursive invocation of $(call ...). Fill in the remaining arguments
8099 in the new scope with the empty value, to hide them from this
8100 invocation. */
8101
8102 for (; i < max_args; ++i)
8103#ifdef CONFIG_WITH_VALUE_LENGTH
8104 define_variable (num, sprintf (num, "%d", i), "", o_automatic, 0);
8105#else
8106 {
8107 char num[11];
8108
8109 sprintf (num, "%d", i);
8110 define_variable (num, strlen (num), "", o_automatic, 0);
8111 }
8112#endif
8113
8114 saved_args = max_args;
8115 max_args = i;
8116
8117#ifdef CONFIG_WITH_EVALPLUS
8118 if (!strcmp (funcname, "call"))
8119 {
8120#endif
8121 /* Expand the body in the context of the arguments, adding the result to
8122 the variable buffer. */
8123
8124 v->exp_count = EXP_COUNT_MAX;
8125#ifndef CONFIG_WITH_VALUE_LENGTH
8126 o = variable_expand_string (o, body, flen+3);
8127 v->exp_count = 0;
8128
8129 o += strlen (o);
8130#else /* CONFIG_WITH_VALUE_LENGTH */
8131 variable_expand_string_2 (o, body, flen+3, &o);
8132 v->exp_count = 0;
8133#endif /* CONFIG_WITH_VALUE_LENGTH */
8134#ifdef CONFIG_WITH_EVALPLUS
8135 }
8136 else
8137 {
8138 const floc *reading_file_saved = reading_file;
8139 char *eos;
8140
8141 if (!strcmp (funcname, "evalcall"))
8142 {
8143 /* Evaluate the variable value without expanding it. We
8144 need a copy since eval_buffer is destructive. */
8145
8146 size_t off = o - variable_buffer;
8147 eos = variable_buffer_output (o, v->value, v->value_length + 1) - 1;
8148 o = variable_buffer + off;
8149 if (v->fileinfo.filenm)
8150 reading_file = &v->fileinfo;
8151 }
8152 else
8153 {
8154 /* Expand the body first and then evaluate the output. */
8155
8156 v->exp_count = EXP_COUNT_MAX;
8157 o = variable_expand_string_2 (o, body, flen+3, &eos);
8158 v->exp_count = 0;
8159 }
8160
8161 install_variable_buffer (&buf, &len);
8162 eval_buffer (o, NULL, eos);
8163 restore_variable_buffer (buf, len);
8164 reading_file = reading_file_saved;
8165
8166 /* Deal with the .RETURN value if present. */
8167
8168 v = lookup_variable_in_set (".RETURN", sizeof (".RETURN") - 1,
8169 current_variable_set_list->set);
8170 if (v && v->value_length)
8171 {
8172 if (v->recursive && !IS_VARIABLE_RECURSIVE_WITHOUT_DOLLAR (v))
8173 {
8174 v->exp_count = EXP_COUNT_MAX;
8175 variable_expand_string_2 (o, v->value, v->value_length, &o);
8176 v->exp_count = 0;
8177 }
8178 else
8179 o = variable_buffer_output (o, v->value, v->value_length);
8180 }
8181 }
8182#endif /* CONFIG_WITH_EVALPLUS */
8183
8184 max_args = saved_args;
8185
8186 pop_variable_scope ();
8187
8188 return o;
8189}
8190
8191void
8192define_new_function (const floc *flocp, const char *name,
8193 unsigned int min, unsigned int max, unsigned int flags,
8194 gmk_func_ptr func)
8195{
8196 const char *e = name;
8197 struct function_table_entry *ent;
8198 size_t len;
8199
8200 while (STOP_SET (*e, MAP_USERFUNC))
8201 e++;
8202 len = e - name;
8203
8204 if (len == 0)
8205 O (fatal, flocp, _("Empty function name"));
8206 if (*name == '.' || *e != '\0')
8207 OS (fatal, flocp, _("Invalid function name: %s"), name);
8208 if (len > 255)
8209 OS (fatal, flocp, _("Function name too long: %s"), name);
8210 if (min > 255)
8211 ONS (fatal, flocp,
8212 _("Invalid minimum argument count (%u) for function %s"), min, name);
8213 if (max > 255 || (max && max < min))
8214 ONS (fatal, flocp,
8215 _("Invalid maximum argument count (%u) for function %s"), max, name);
8216
8217 ent = xmalloc (sizeof (struct function_table_entry));
8218 ent->name = name;
8219 ent->len = len;
8220 ent->minimum_args = min;
8221 ent->maximum_args = max;
8222 ent->expand_args = ANY_SET(flags, GMK_FUNC_NOEXPAND) ? 0 : 1;
8223 ent->alloc_fn = 1;
8224 ent->fptr.alloc_func_ptr = func;
8225
8226 hash_insert (&function_table, ent);
8227}
8228
8229void
8230hash_init_function_table (void)
8231{
8232 hash_init (&function_table, FUNCTION_TABLE_ENTRIES * 2,
8233 function_table_entry_hash_1, function_table_entry_hash_2,
8234 function_table_entry_hash_cmp);
8235 hash_load (&function_table, function_table_init,
8236 FUNCTION_TABLE_ENTRIES, sizeof (struct function_table_entry));
8237#if defined (CONFIG_WITH_OPTIMIZATION_HACKS) || defined (CONFIG_WITH_VALUE_LENGTH)
8238 {
8239 unsigned int i;
8240 for (i = 0; i < FUNCTION_TABLE_ENTRIES; i++)
8241 {
8242 const char *fn = function_table_init[i].name;
8243 while (*fn)
8244 {
8245 func_char_map[(int)*fn] = 1;
8246 fn++;
8247 }
8248 assert (function_table_init[i].len <= MAX_FUNCTION_LENGTH);
8249 assert (function_table_init[i].len >= MIN_FUNCTION_LENGTH);
8250 }
8251 }
8252#endif
8253}
Note: See TracBrowser for help on using the repository browser.

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