VirtualBox

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

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

kmk: build fixes

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

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