VirtualBox

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

Last change on this file since 1836 was 1836, checked in by bird, 16 years ago

kmk: don't return '\0'.

  • Property svn:eol-style set to native
File size: 118.0 KB
Line 
1/* Builtin function expansion for GNU Make.
2Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
31998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
4Foundation, Inc.
5This file is part of GNU Make.
6
7GNU Make is free software; you can redistribute it and/or modify it under the
8terms of the GNU General Public License as published by the Free Software
9Foundation; either version 2, or (at your option) any later version.
10
11GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License along with
16GNU Make; see the file COPYING. If not, write to the Free Software
17Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */
18
19#include "make.h"
20#include "filedef.h"
21#include "variable.h"
22#include "dep.h"
23#include "job.h"
24#include "commands.h"
25#include "debug.h"
26
27#ifdef _AMIGA
28#include "amiga.h"
29#endif
30
31#ifdef WINDOWS32 /* bird */
32# include "pathstuff.h"
33#endif
34
35#ifdef KMK_HELPERS
36# include "kbuild.h"
37#endif
38#ifdef CONFIG_WITH_XARGS /* bird */
39# ifdef HAVE_LIMITS_H
40# include <limits.h>
41# endif
42#endif
43#include <assert.h> /* bird */
44
45#if defined (CONFIG_WITH_MATH) || defined (CONFIG_WITH_NANOTS) || defined (CONFIG_WITH_FILE_SIZE) /* bird */
46# include <ctype.h>
47# ifdef _MSC_VER
48typedef __int64 math_int;
49# else
50# include <stdint.h>
51typedef int64_t math_int;
52# endif
53static char *math_int_to_variable_buffer (char *, math_int);
54#endif
55
56#ifdef CONFIG_WITH_NANOTS /* bird */
57# ifdef WINDOWS32
58# include <Windows.h>
59# endif
60#endif
61
62#ifdef __OS2__
63# define CONFIG_WITH_OS2_LIBPATH 1
64#endif
65#ifdef CONFIG_WITH_OS2_LIBPATH
66# define INCL_BASE
67# define INCL_ERRROS
68# include <os2.h>
69
70# define QHINF_EXEINFO 1 /* NE exeinfo. */
71# define QHINF_READRSRCTBL 2 /* Reads from the resource table. */
72# define QHINF_READFILE 3 /* Reads from the executable file. */
73# define QHINF_LIBPATHLENGTH 4 /* Gets the libpath length. */
74# define QHINF_LIBPATH 5 /* Gets the entire libpath. */
75# define QHINF_FIXENTRY 6 /* NE only */
76# define QHINF_STE 7 /* NE only */
77# define QHINF_MAPSEL 8 /* NE only */
78 extern APIRET APIENTRY DosQueryHeaderInfo(HMODULE hmod, ULONG ulIndex, PVOID pvBuffer, ULONG cbBuffer, ULONG ulSubFunction);
79#endif /* CONFIG_WITH_OS2_LIBPATH */
80
81
82struct function_table_entry
83 {
84 const char *name;
85 unsigned char len;
86 unsigned char minimum_args;
87 unsigned char maximum_args;
88 char expand_args;
89 char *(*func_ptr) (char *output, char **argv, const char *fname);
90 };
91
92static unsigned long
93function_table_entry_hash_1 (const void *keyv)
94{
95 const struct function_table_entry *key = keyv;
96 return_STRING_N_HASH_1 (key->name, key->len);
97}
98
99static unsigned long
100function_table_entry_hash_2 (const void *keyv)
101{
102 const struct function_table_entry *key = keyv;
103 return_STRING_N_HASH_2 (key->name, key->len);
104}
105
106static int
107function_table_entry_hash_cmp (const void *xv, const void *yv)
108{
109 const struct function_table_entry *x = xv;
110 const struct function_table_entry *y = yv;
111 int result = x->len - y->len;
112 if (result)
113 return result;
114 return_STRING_N_COMPARE (x->name, y->name, x->len);
115}
116
117static struct hash_table function_table;
118
119#ifdef CONFIG_WITH_MAKE_STATS
120long make_stats_allocations = 0;
121unsigned long make_stats_allocated = 0;
122unsigned long make_stats_allocated_sum = 0;
123unsigned long make_stats_ht_lookups = 0;
124unsigned long make_stats_ht_collisions = 0;
125#endif
126
127
128
129/* Store into VARIABLE_BUFFER at O the result of scanning TEXT and replacing
130 each occurrence of SUBST with REPLACE. TEXT is null-terminated. SLEN is
131 the length of SUBST and RLEN is the length of REPLACE. If BY_WORD is
132 nonzero, substitutions are done only on matches which are complete
133 whitespace-delimited words. */
134
135char *
136subst_expand (char *o, const char *text, const char *subst, const char *replace,
137 unsigned int slen, unsigned int rlen, int by_word)
138{
139 const char *t = text;
140 const char *p;
141
142 if (slen == 0 && !by_word)
143 {
144 /* The first occurrence of "" in any string is its end. */
145 o = variable_buffer_output (o, t, strlen (t));
146 if (rlen > 0)
147 o = variable_buffer_output (o, replace, rlen);
148 return o;
149 }
150
151 do
152 {
153 if (by_word && slen == 0)
154 /* When matching by words, the empty string should match
155 the end of each word, rather than the end of the whole text. */
156 p = end_of_token (next_token (t));
157 else
158 {
159 p = strstr (t, subst);
160 if (p == 0)
161 {
162 /* No more matches. Output everything left on the end. */
163 o = variable_buffer_output (o, t, strlen (t));
164 return o;
165 }
166 }
167
168 /* Output everything before this occurrence of the string to replace. */
169 if (p > t)
170 o = variable_buffer_output (o, t, p - t);
171
172 /* If we're substituting only by fully matched words,
173 or only at the ends of words, check that this case qualifies. */
174 if (by_word
175 && ((p > text && !isblank ((unsigned char)p[-1]))
176 || (p[slen] != '\0' && !isblank ((unsigned char)p[slen]))))
177 /* Struck out. Output the rest of the string that is
178 no longer to be replaced. */
179 o = variable_buffer_output (o, subst, slen);
180 else if (rlen > 0)
181 /* Output the replacement string. */
182 o = variable_buffer_output (o, replace, rlen);
183
184 /* Advance T past the string to be replaced. */
185 t = p + slen;
186 } while (*t != '\0');
187
188 return o;
189}
190
191
192
193/* Store into VARIABLE_BUFFER at O the result of scanning TEXT
194 and replacing strings matching PATTERN with REPLACE.
195 If PATTERN_PERCENT is not nil, PATTERN has already been
196 run through find_percent, and PATTERN_PERCENT is the result.
197 If REPLACE_PERCENT is not nil, REPLACE has already been
198 run through find_percent, and REPLACE_PERCENT is the result.
199 Note that we expect PATTERN_PERCENT and REPLACE_PERCENT to point to the
200 character _AFTER_ the %, not to the % itself.
201*/
202
203char *
204patsubst_expand_pat (char *o, const char *text,
205 const char *pattern, const char *replace,
206 const char *pattern_percent, const char *replace_percent)
207{
208 unsigned int pattern_prepercent_len, pattern_postpercent_len;
209 unsigned int replace_prepercent_len, replace_postpercent_len;
210 const char *t;
211 unsigned int len;
212 int doneany = 0;
213
214 /* Record the length of REPLACE before and after the % so we don't have to
215 compute these lengths more than once. */
216 if (replace_percent)
217 {
218 replace_prepercent_len = replace_percent - replace - 1;
219 replace_postpercent_len = strlen (replace_percent);
220 }
221 else
222 {
223 replace_prepercent_len = strlen (replace);
224 replace_postpercent_len = 0;
225 }
226
227 if (!pattern_percent)
228 /* With no % in the pattern, this is just a simple substitution. */
229 return subst_expand (o, text, pattern, replace,
230 strlen (pattern), strlen (replace), 1);
231
232 /* Record the length of PATTERN before and after the %
233 so we don't have to compute it more than once. */
234 pattern_prepercent_len = pattern_percent - pattern - 1;
235 pattern_postpercent_len = strlen (pattern_percent);
236
237 while ((t = find_next_token (&text, &len)) != 0)
238 {
239 int fail = 0;
240
241 /* Is it big enough to match? */
242 if (len < pattern_prepercent_len + pattern_postpercent_len)
243 fail = 1;
244
245 /* Does the prefix match? */
246 if (!fail && pattern_prepercent_len > 0
247 && (*t != *pattern
248 || t[pattern_prepercent_len - 1] != pattern_percent[-2]
249 || !strneq (t + 1, pattern + 1, pattern_prepercent_len - 1)))
250 fail = 1;
251
252 /* Does the suffix match? */
253 if (!fail && pattern_postpercent_len > 0
254 && (t[len - 1] != pattern_percent[pattern_postpercent_len - 1]
255 || t[len - pattern_postpercent_len] != *pattern_percent
256 || !strneq (&t[len - pattern_postpercent_len],
257 pattern_percent, pattern_postpercent_len - 1)))
258 fail = 1;
259
260 if (fail)
261 /* It didn't match. Output the string. */
262 o = variable_buffer_output (o, t, len);
263 else
264 {
265 /* It matched. Output the replacement. */
266
267 /* Output the part of the replacement before the %. */
268 o = variable_buffer_output (o, replace, replace_prepercent_len);
269
270 if (replace_percent != 0)
271 {
272 /* Output the part of the matched string that
273 matched the % in the pattern. */
274 o = variable_buffer_output (o, t + pattern_prepercent_len,
275 len - (pattern_prepercent_len
276 + pattern_postpercent_len));
277 /* Output the part of the replacement after the %. */
278 o = variable_buffer_output (o, replace_percent,
279 replace_postpercent_len);
280 }
281 }
282
283 /* Output a space, but not if the replacement is "". */
284 if (fail || replace_prepercent_len > 0
285 || (replace_percent != 0 && len + replace_postpercent_len > 0))
286 {
287 o = variable_buffer_output (o, " ", 1);
288 doneany = 1;
289 }
290 }
291 if (doneany)
292 /* Kill the last space. */
293 --o;
294
295 return o;
296}
297
298/* Store into VARIABLE_BUFFER at O the result of scanning TEXT
299 and replacing strings matching PATTERN with REPLACE.
300 If PATTERN_PERCENT is not nil, PATTERN has already been
301 run through find_percent, and PATTERN_PERCENT is the result.
302 If REPLACE_PERCENT is not nil, REPLACE has already been
303 run through find_percent, and REPLACE_PERCENT is the result.
304 Note that we expect PATTERN_PERCENT and REPLACE_PERCENT to point to the
305 character _AFTER_ the %, not to the % itself.
306*/
307
308char *
309patsubst_expand (char *o, const char *text, char *pattern, char *replace)
310{
311 const char *pattern_percent = find_percent (pattern);
312 const char *replace_percent = find_percent (replace);
313
314 /* If there's a percent in the pattern or replacement skip it. */
315 if (replace_percent)
316 ++replace_percent;
317 if (pattern_percent)
318 ++pattern_percent;
319
320 return patsubst_expand_pat (o, text, pattern, replace,
321 pattern_percent, replace_percent);
322}
323
324
325#if defined (CONFIG_WITH_OPTIMIZATION_HACKS) || defined (CONFIG_WITH_VALUE_LENGTH)
326/* The maximum length of a function, once reached there is
327 it can't be function and we can skip the hash lookup drop out. */
328
329# define MAX_FUNCTION_LENGTH 12
330# define MIN_FUNCTION_LENGTH 2
331
332/* char map containing the valid function name characters. */
333static char func_char_map[256];
334
335/* Do the hash table lookup. */
336
337__inline static const struct function_table_entry *
338lookup_function_in_hash_tab (const char *s, unsigned char len)
339{
340 struct function_table_entry function_table_entry_key;
341 function_table_entry_key.name = s;
342 function_table_entry_key.len = len;
343
344 return hash_find_item (&function_table, &function_table_entry_key);
345}
346
347/* Look up a function by name. */
348
349__inline static const struct function_table_entry *
350lookup_function (const char *s, unsigned int len)
351{
352 unsigned char ch;
353# if 0 /* insane loop unroll */
354
355 if (len > MAX_FUNCTION_LENGTH)
356 len = MAX_FUNCTION_LENGTH + 1;
357
358# define X(idx) \
359 if (!func_char_map[ch = s[idx]]) \
360 { \
361 if (isblank (ch)) \
362 return lookup_function_in_hash_tab (s, idx); \
363 return 0; \
364 }
365# define Z(idx) \
366 return lookup_function_in_hash_tab (s, idx);
367
368 switch (len)
369 {
370 default:
371 assert (0);
372 case 0: return 0;
373 case 1: return 0;
374 case 2: X(0); X(1); Z(2);
375 case 3: X(0); X(1); X(2); Z(3);
376 case 4: X(0); X(1); X(2); X(3); Z(4);
377 case 5: X(0); X(1); X(2); X(3); X(4); Z(5);
378 case 6: X(0); X(1); X(2); X(3); X(4); X(5); Z(6);
379 case 7: X(0); X(1); X(2); X(3); X(4); X(5); X(6); Z(7);
380 case 8: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); Z(8);
381 case 9: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); X(8); Z(9);
382 case 10: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); X(8); X(9); Z(10);
383 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);
384 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);
385 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);
386 if ((ch = s[12]) == '\0' || isblank (ch))
387 return lookup_function_in_hash_tab (s, 12);
388 return 0;
389 }
390# undef Z
391# undef X
392
393# else /* normal loop */
394 const char *e = s;
395 if (len > MAX_FUNCTION_LENGTH)
396 len = MAX_FUNCTION_LENGTH;
397 while (func_char_map[ch = *e])
398 {
399 if (!len--)
400 return 0;
401 e++;
402 }
403 if (ch == '\0' || isblank ((unsigned char) ch))
404 return lookup_function_in_hash_tab (s, e - s);
405 return 0;
406# endif /* normal loop */
407}
408
409#else /* original code */
410/* Look up a function by name. */
411
412static const struct function_table_entry *
413lookup_function (const char *s)
414{
415 const char *e = s;
416 while (*e && ( (*e >= 'a' && *e <= 'z') || *e == '-'))
417 e++;
418 if (*e == '\0' || isblank ((unsigned char) *e))
419 {
420 struct function_table_entry function_table_entry_key;
421 function_table_entry_key.name = s;
422 function_table_entry_key.len = e - s;
423
424 return hash_find_item (&function_table, &function_table_entry_key);
425 }
426 return 0;
427}
428#endif /* original code */
429
430
431
432/* Return 1 if PATTERN matches STR, 0 if not. */
433
434int
435pattern_matches (const char *pattern, const char *percent, const char *str)
436{
437 unsigned int sfxlen, strlength;
438
439 if (percent == 0)
440 {
441 unsigned int len = strlen (pattern) + 1;
442 char *new_chars = alloca (len);
443 memcpy (new_chars, pattern, len);
444 percent = find_percent (new_chars);
445 if (percent == 0)
446 return streq (new_chars, str);
447 pattern = new_chars;
448 }
449
450 sfxlen = strlen (percent + 1);
451 strlength = strlen (str);
452
453 if (strlength < (percent - pattern) + sfxlen
454 || !strneq (pattern, str, percent - pattern))
455 return 0;
456
457 return !strcmp (percent + 1, str + (strlength - sfxlen));
458}
459
460
461
462/* Find the next comma or ENDPAREN (counting nested STARTPAREN and
463 ENDPARENtheses), starting at PTR before END. Return a pointer to
464 next character.
465
466 If no next argument is found, return NULL.
467*/
468
469static char *
470find_next_argument (char startparen, char endparen,
471 const char *ptr, const char *end)
472{
473 int count = 0;
474
475 for (; ptr < end; ++ptr)
476 if (*ptr == startparen)
477 ++count;
478
479 else if (*ptr == endparen)
480 {
481 --count;
482 if (count < 0)
483 return NULL;
484 }
485
486 else if (*ptr == ',' && !count)
487 return (char *)ptr;
488
489 /* We didn't find anything. */
490 return NULL;
491}
492
493
494
495/* Glob-expand LINE. The returned pointer is
496 only good until the next call to string_glob. */
497
498static char *
499string_glob (char *line)
500{
501 static char *result = 0;
502 static unsigned int length;
503 struct nameseq *chain;
504 unsigned int idx;
505
506 chain = multi_glob (parse_file_seq
507 (&line, '\0', sizeof (struct nameseq),
508 /* We do not want parse_file_seq to strip `./'s.
509 That would break examples like:
510 $(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)). */
511 0),
512 sizeof (struct nameseq));
513
514 if (result == 0)
515 {
516 length = 100;
517 result = xmalloc (100);
518 }
519
520 idx = 0;
521 while (chain != 0)
522 {
523 const char *name = chain->name;
524 unsigned int len = strlen (name);
525
526 struct nameseq *next = chain->next;
527 free (chain);
528 chain = next;
529
530 /* multi_glob will pass names without globbing metacharacters
531 through as is, but we want only files that actually exist. */
532 if (file_exists_p (name))
533 {
534 if (idx + len + 1 > length)
535 {
536 length += (len + 1) * 2;
537 result = xrealloc (result, length);
538 }
539 memcpy (&result[idx], name, len);
540 idx += len;
541 result[idx++] = ' ';
542 }
543 }
544
545 /* Kill the last space and terminate the string. */
546 if (idx == 0)
547 result[0] = '\0';
548 else
549 result[idx - 1] = '\0';
550
551 return result;
552}
553
554
555/*
556 Builtin functions
557 */
558
559static char *
560func_patsubst (char *o, char **argv, const char *funcname UNUSED)
561{
562 o = patsubst_expand (o, argv[2], argv[0], argv[1]);
563 return o;
564}
565
566
567static char *
568func_join (char *o, char **argv, const char *funcname UNUSED)
569{
570 int doneany = 0;
571
572 /* Write each word of the first argument directly followed
573 by the corresponding word of the second argument.
574 If the two arguments have a different number of words,
575 the excess words are just output separated by blanks. */
576 const char *tp;
577 const char *pp;
578 const char *list1_iterator = argv[0];
579 const char *list2_iterator = argv[1];
580 do
581 {
582 unsigned int len1, len2;
583
584 tp = find_next_token (&list1_iterator, &len1);
585 if (tp != 0)
586 o = variable_buffer_output (o, tp, len1);
587
588 pp = find_next_token (&list2_iterator, &len2);
589 if (pp != 0)
590 o = variable_buffer_output (o, pp, len2);
591
592 if (tp != 0 || pp != 0)
593 {
594 o = variable_buffer_output (o, " ", 1);
595 doneany = 1;
596 }
597 }
598 while (tp != 0 || pp != 0);
599 if (doneany)
600 /* Kill the last blank. */
601 --o;
602
603 return o;
604}
605
606
607static char *
608func_origin (char *o, char **argv, const char *funcname UNUSED)
609{
610 /* Expand the argument. */
611 struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
612 if (v == 0)
613 o = variable_buffer_output (o, "undefined", 9);
614 else
615 switch (v->origin)
616 {
617 default:
618 case o_invalid:
619 abort ();
620 break;
621 case o_default:
622 o = variable_buffer_output (o, "default", 7);
623 break;
624 case o_env:
625 o = variable_buffer_output (o, "environment", 11);
626 break;
627 case o_file:
628 o = variable_buffer_output (o, "file", 4);
629 break;
630 case o_env_override:
631 o = variable_buffer_output (o, "environment override", 20);
632 break;
633 case o_command:
634 o = variable_buffer_output (o, "command line", 12);
635 break;
636 case o_override:
637 o = variable_buffer_output (o, "override", 8);
638 break;
639 case o_automatic:
640 o = variable_buffer_output (o, "automatic", 9);
641 break;
642#ifdef CONFIG_WITH_LOCAL_VARIABLES
643 case o_local:
644 o = variable_buffer_output (o, "local", 5);
645 break;
646#endif
647 }
648
649 return o;
650}
651
652static char *
653func_flavor (char *o, char **argv, const char *funcname UNUSED)
654{
655 struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
656
657 if (v == 0)
658 o = variable_buffer_output (o, "undefined", 9);
659 else
660 if (v->recursive)
661 o = variable_buffer_output (o, "recursive", 9);
662 else
663 o = variable_buffer_output (o, "simple", 6);
664
665 return o;
666}
667
668#ifdef VMS
669# define IS_PATHSEP(c) ((c) == ']')
670#else
671# ifdef HAVE_DOS_PATHS
672# define IS_PATHSEP(c) ((c) == '/' || (c) == '\\')
673# else
674# define IS_PATHSEP(c) ((c) == '/')
675# endif
676#endif
677
678
679static char *
680func_notdir_suffix (char *o, char **argv, const char *funcname)
681{
682 /* Expand the argument. */
683 const char *list_iterator = argv[0];
684 const char *p2;
685 int doneany =0;
686 unsigned int len=0;
687
688 int is_suffix = streq (funcname, "suffix");
689 int is_notdir = !is_suffix;
690 while ((p2 = find_next_token (&list_iterator, &len)) != 0)
691 {
692 const char *p = p2 + len;
693
694
695 while (p >= p2 && (!is_suffix || *p != '.'))
696 {
697 if (IS_PATHSEP (*p))
698 break;
699 --p;
700 }
701
702 if (p >= p2)
703 {
704 if (is_notdir)
705 ++p;
706 else if (*p != '.')
707 continue;
708 o = variable_buffer_output (o, p, len - (p - p2));
709 }
710#ifdef HAVE_DOS_PATHS
711 /* Handle the case of "d:foo/bar". */
712 else if (streq (funcname, "notdir") && p2[0] && p2[1] == ':')
713 {
714 p = p2 + 2;
715 o = variable_buffer_output (o, p, len - (p - p2));
716 }
717#endif
718 else if (is_notdir)
719 o = variable_buffer_output (o, p2, len);
720
721 if (is_notdir || p >= p2)
722 {
723 o = variable_buffer_output (o, " ", 1);
724 doneany = 1;
725 }
726 }
727
728 if (doneany)
729 /* Kill last space. */
730 --o;
731
732 return o;
733}
734
735
736static char *
737func_basename_dir (char *o, char **argv, const char *funcname)
738{
739 /* Expand the argument. */
740 const char *p3 = argv[0];
741 const char *p2;
742 int doneany=0;
743 unsigned int len=0;
744
745 int is_basename= streq (funcname, "basename");
746 int is_dir= !is_basename;
747
748 while ((p2 = find_next_token (&p3, &len)) != 0)
749 {
750 const char *p = p2 + len;
751 while (p >= p2 && (!is_basename || *p != '.'))
752 {
753 if (IS_PATHSEP (*p))
754 break;
755 --p;
756 }
757
758 if (p >= p2 && (is_dir))
759 o = variable_buffer_output (o, p2, ++p - p2);
760 else if (p >= p2 && (*p == '.'))
761 o = variable_buffer_output (o, p2, p - p2);
762#ifdef HAVE_DOS_PATHS
763 /* Handle the "d:foobar" case */
764 else if (p2[0] && p2[1] == ':' && is_dir)
765 o = variable_buffer_output (o, p2, 2);
766#endif
767 else if (is_dir)
768#ifdef VMS
769 o = variable_buffer_output (o, "[]", 2);
770#else
771#ifndef _AMIGA
772 o = variable_buffer_output (o, "./", 2);
773#else
774 ; /* Just a nop... */
775#endif /* AMIGA */
776#endif /* !VMS */
777 else
778 /* The entire name is the basename. */
779 o = variable_buffer_output (o, p2, len);
780
781 o = variable_buffer_output (o, " ", 1);
782 doneany = 1;
783 }
784
785 if (doneany)
786 /* Kill last space. */
787 --o;
788
789 return o;
790}
791
792static char *
793func_addsuffix_addprefix (char *o, char **argv, const char *funcname)
794{
795 int fixlen = strlen (argv[0]);
796 const char *list_iterator = argv[1];
797 int is_addprefix = streq (funcname, "addprefix");
798 int is_addsuffix = !is_addprefix;
799
800 int doneany = 0;
801 const char *p;
802 unsigned int len;
803
804 while ((p = find_next_token (&list_iterator, &len)) != 0)
805 {
806 if (is_addprefix)
807 o = variable_buffer_output (o, argv[0], fixlen);
808 o = variable_buffer_output (o, p, len);
809 if (is_addsuffix)
810 o = variable_buffer_output (o, argv[0], fixlen);
811 o = variable_buffer_output (o, " ", 1);
812 doneany = 1;
813 }
814
815 if (doneany)
816 /* Kill last space. */
817 --o;
818
819 return o;
820}
821
822static char *
823func_subst (char *o, char **argv, const char *funcname UNUSED)
824{
825 o = subst_expand (o, argv[2], argv[0], argv[1], strlen (argv[0]),
826 strlen (argv[1]), 0);
827
828 return o;
829}
830
831
832static char *
833func_firstword (char *o, char **argv, const char *funcname UNUSED)
834{
835 unsigned int i;
836 const char *words = argv[0]; /* Use a temp variable for find_next_token */
837 const char *p = find_next_token (&words, &i);
838
839 if (p != 0)
840 o = variable_buffer_output (o, p, i);
841
842 return o;
843}
844
845static char *
846func_lastword (char *o, char **argv, const char *funcname UNUSED)
847{
848 unsigned int i;
849 const char *words = argv[0]; /* Use a temp variable for find_next_token */
850 const char *p = NULL;
851 const char *t;
852
853 while ((t = find_next_token (&words, &i)))
854 p = t;
855
856 if (p != 0)
857 o = variable_buffer_output (o, p, i);
858
859 return o;
860}
861
862static char *
863func_words (char *o, char **argv, const char *funcname UNUSED)
864{
865 int i = 0;
866 const char *word_iterator = argv[0];
867 char buf[20];
868
869 while (find_next_token (&word_iterator, (unsigned int *) 0) != 0)
870 ++i;
871
872 sprintf (buf, "%d", i);
873 o = variable_buffer_output (o, buf, strlen (buf));
874
875 return o;
876}
877
878/* Set begpp to point to the first non-whitespace character of the string,
879 * and endpp to point to the last non-whitespace character of the string.
880 * If the string is empty or contains nothing but whitespace, endpp will be
881 * begpp-1.
882 */
883char *
884strip_whitespace (const char **begpp, const char **endpp)
885{
886 while (*begpp <= *endpp && isspace ((unsigned char)**begpp))
887 (*begpp) ++;
888 while (*endpp >= *begpp && isspace ((unsigned char)**endpp))
889 (*endpp) --;
890 return (char *)*begpp;
891}
892
893static void
894check_numeric (const char *s, const char *msg)
895{
896 const char *end = s + strlen (s) - 1;
897 const char *beg = s;
898 strip_whitespace (&s, &end);
899
900 for (; s <= end; ++s)
901 if (!ISDIGIT (*s)) /* ISDIGIT only evals its arg once: see make.h. */
902 break;
903
904 if (s <= end || end - beg < 0)
905 fatal (*expanding_var, "%s: '%s'", msg, beg);
906}
907
908
909
910static char *
911func_word (char *o, char **argv, const char *funcname UNUSED)
912{
913 const char *end_p;
914 const char *p;
915 int i;
916
917 /* Check the first argument. */
918 check_numeric (argv[0], _("non-numeric first argument to `word' function"));
919 i = atoi (argv[0]);
920
921 if (i == 0)
922 fatal (*expanding_var,
923 _("first argument to `word' function must be greater than 0"));
924
925 end_p = argv[1];
926 while ((p = find_next_token (&end_p, 0)) != 0)
927 if (--i == 0)
928 break;
929
930 if (i == 0)
931 o = variable_buffer_output (o, p, end_p - p);
932
933 return o;
934}
935
936static char *
937func_wordlist (char *o, char **argv, const char *funcname UNUSED)
938{
939 int start, count;
940
941 /* Check the arguments. */
942 check_numeric (argv[0],
943 _("non-numeric first argument to `wordlist' function"));
944 check_numeric (argv[1],
945 _("non-numeric second argument to `wordlist' function"));
946
947 start = atoi (argv[0]);
948 if (start < 1)
949 fatal (*expanding_var,
950 "invalid first argument to `wordlist' function: `%d'", start);
951
952 count = atoi (argv[1]) - start + 1;
953
954 if (count > 0)
955 {
956 const char *p;
957 const char *end_p = argv[2];
958
959 /* Find the beginning of the "start"th word. */
960 while (((p = find_next_token (&end_p, 0)) != 0) && --start)
961 ;
962
963 if (p)
964 {
965 /* Find the end of the "count"th word from start. */
966 while (--count && (find_next_token (&end_p, 0) != 0))
967 ;
968
969 /* Return the stuff in the middle. */
970 o = variable_buffer_output (o, p, end_p - p);
971 }
972 }
973
974 return o;
975}
976
977static char *
978func_findstring (char *o, char **argv, const char *funcname UNUSED)
979{
980 /* Find the first occurrence of the first string in the second. */
981 if (strstr (argv[1], argv[0]) != 0)
982 o = variable_buffer_output (o, argv[0], strlen (argv[0]));
983
984 return o;
985}
986
987static char *
988func_foreach (char *o, char **argv, const char *funcname UNUSED)
989{
990 /* expand only the first two. */
991 char *varname = expand_argument (argv[0], NULL);
992 char *list = expand_argument (argv[1], NULL);
993 const char *body = argv[2];
994#ifdef CONFIG_WITH_VALUE_LENGTH
995 long body_len = strlen (body);
996#endif
997
998 int doneany = 0;
999 const char *list_iterator = list;
1000 const char *p;
1001 unsigned int len;
1002 struct variable *var;
1003
1004 push_new_variable_scope ();
1005 var = define_variable (varname, strlen (varname), "", o_automatic, 0);
1006
1007 /* loop through LIST, put the value in VAR and expand BODY */
1008 while ((p = find_next_token (&list_iterator, &len)) != 0)
1009 {
1010#ifndef CONFIG_WITH_VALUE_LENGTH
1011 char *result = 0;
1012
1013 free (var->value);
1014 var->value = savestring (p, len);
1015 result = allocated_variable_expand (body);
1016
1017 o = variable_buffer_output (o, result, strlen (result));
1018 o = variable_buffer_output (o, " ", 1);
1019 doneany = 1;
1020 free (result);
1021#else /* CONFIG_WITH_VALUE_LENGTH */
1022 if (len >= (unsigned int)var->value_alloc_len)
1023 {
1024 free (var->value);
1025 var->value_alloc_len = (len + 32) & ~31;
1026 var->value = xmalloc (var->value_alloc_len);
1027 }
1028 memcpy (var->value, p, len);
1029 var->value[len] = '\0';
1030 var->value_length = len;
1031
1032 variable_expand_string_2 (o, body, body_len, &o);
1033 o = variable_buffer_output (o, " ", 1);
1034 doneany = 1;
1035#endif /* CONFIG_WITH_VALUE_LENGTH */
1036 }
1037
1038 if (doneany)
1039 /* Kill the last space. */
1040 --o;
1041
1042 pop_variable_scope ();
1043 free (varname);
1044 free (list);
1045
1046 return o;
1047}
1048
1049struct a_word
1050{
1051 struct a_word *next;
1052 struct a_word *chain;
1053 char *str;
1054 int length;
1055 int matched;
1056};
1057
1058static unsigned long
1059a_word_hash_1 (const void *key)
1060{
1061 return_STRING_HASH_1 (((struct a_word const *) key)->str);
1062}
1063
1064static unsigned long
1065a_word_hash_2 (const void *key)
1066{
1067 return_STRING_HASH_2 (((struct a_word const *) key)->str);
1068}
1069
1070static int
1071a_word_hash_cmp (const void *x, const void *y)
1072{
1073 int result = ((struct a_word const *) x)->length - ((struct a_word const *) y)->length;
1074 if (result)
1075 return result;
1076 return_STRING_COMPARE (((struct a_word const *) x)->str,
1077 ((struct a_word const *) y)->str);
1078}
1079
1080struct a_pattern
1081{
1082 struct a_pattern *next;
1083 char *str;
1084 char *percent;
1085 int length;
1086 int save_c;
1087};
1088
1089static char *
1090func_filter_filterout (char *o, char **argv, const char *funcname)
1091{
1092 struct a_word *wordhead;
1093 struct a_word **wordtail;
1094 struct a_word *wp;
1095 struct a_pattern *pathead;
1096 struct a_pattern **pattail;
1097 struct a_pattern *pp;
1098
1099 struct hash_table a_word_table;
1100 int is_filter = streq (funcname, "filter");
1101 const char *pat_iterator = argv[0];
1102 const char *word_iterator = argv[1];
1103 int literals = 0;
1104 int words = 0;
1105 int hashing = 0;
1106 char *p;
1107 unsigned int len;
1108
1109 /* Chop ARGV[0] up into patterns to match against the words. */
1110
1111 pattail = &pathead;
1112 while ((p = find_next_token (&pat_iterator, &len)) != 0)
1113 {
1114 struct a_pattern *pat = alloca (sizeof (struct a_pattern));
1115
1116 *pattail = pat;
1117 pattail = &pat->next;
1118
1119 if (*pat_iterator != '\0')
1120 ++pat_iterator;
1121
1122 pat->str = p;
1123 pat->length = len;
1124 pat->save_c = p[len];
1125 p[len] = '\0';
1126 pat->percent = find_percent (p);
1127 if (pat->percent == 0)
1128 literals++;
1129 }
1130 *pattail = 0;
1131
1132 /* Chop ARGV[1] up into words to match against the patterns. */
1133
1134 wordtail = &wordhead;
1135 while ((p = find_next_token (&word_iterator, &len)) != 0)
1136 {
1137 struct a_word *word = alloca (sizeof (struct a_word));
1138
1139 *wordtail = word;
1140 wordtail = &word->next;
1141
1142 if (*word_iterator != '\0')
1143 ++word_iterator;
1144
1145 p[len] = '\0';
1146 word->str = p;
1147 word->length = len;
1148 word->matched = 0;
1149 word->chain = 0;
1150 words++;
1151 }
1152 *wordtail = 0;
1153
1154 /* Only use a hash table if arg list lengths justifies the cost. */
1155 hashing = (literals >= 2 && (literals * words) >= 10);
1156 if (hashing)
1157 {
1158 hash_init (&a_word_table, words, a_word_hash_1, a_word_hash_2,
1159 a_word_hash_cmp);
1160 for (wp = wordhead; wp != 0; wp = wp->next)
1161 {
1162 struct a_word *owp = hash_insert (&a_word_table, wp);
1163 if (owp)
1164 wp->chain = owp;
1165 }
1166 }
1167
1168 if (words)
1169 {
1170 int doneany = 0;
1171
1172 /* Run each pattern through the words, killing words. */
1173 for (pp = pathead; pp != 0; pp = pp->next)
1174 {
1175 if (pp->percent)
1176 for (wp = wordhead; wp != 0; wp = wp->next)
1177 wp->matched |= pattern_matches (pp->str, pp->percent, wp->str);
1178 else if (hashing)
1179 {
1180 struct a_word a_word_key;
1181 a_word_key.str = pp->str;
1182 a_word_key.length = pp->length;
1183 wp = hash_find_item (&a_word_table, &a_word_key);
1184 while (wp)
1185 {
1186 wp->matched |= 1;
1187 wp = wp->chain;
1188 }
1189 }
1190 else
1191 for (wp = wordhead; wp != 0; wp = wp->next)
1192 wp->matched |= (wp->length == pp->length
1193 && strneq (pp->str, wp->str, wp->length));
1194 }
1195
1196 /* Output the words that matched (or didn't, for filter-out). */
1197 for (wp = wordhead; wp != 0; wp = wp->next)
1198 if (is_filter ? wp->matched : !wp->matched)
1199 {
1200 o = variable_buffer_output (o, wp->str, strlen (wp->str));
1201 o = variable_buffer_output (o, " ", 1);
1202 doneany = 1;
1203 }
1204
1205 if (doneany)
1206 /* Kill the last space. */
1207 --o;
1208 }
1209
1210 for (pp = pathead; pp != 0; pp = pp->next)
1211 pp->str[pp->length] = pp->save_c;
1212
1213 if (hashing)
1214 hash_free (&a_word_table, 0);
1215
1216 return o;
1217}
1218
1219
1220static char *
1221func_strip (char *o, char **argv, const char *funcname UNUSED)
1222{
1223 const char *p = argv[0];
1224 int doneany = 0;
1225
1226 while (*p != '\0')
1227 {
1228 int i=0;
1229 const char *word_start;
1230
1231 while (isspace ((unsigned char)*p))
1232 ++p;
1233 word_start = p;
1234 for (i=0; *p != '\0' && !isspace ((unsigned char)*p); ++p, ++i)
1235 {}
1236 if (!i)
1237 break;
1238 o = variable_buffer_output (o, word_start, i);
1239 o = variable_buffer_output (o, " ", 1);
1240 doneany = 1;
1241 }
1242
1243 if (doneany)
1244 /* Kill the last space. */
1245 --o;
1246
1247 return o;
1248}
1249
1250/*
1251 Print a warning or fatal message.
1252*/
1253static char *
1254func_error (char *o, char **argv, const char *funcname)
1255{
1256 char **argvp;
1257 char *msg, *p;
1258 int len;
1259
1260 /* The arguments will be broken on commas. Rather than create yet
1261 another special case where function arguments aren't broken up,
1262 just create a format string that puts them back together. */
1263 for (len=0, argvp=argv; *argvp != 0; ++argvp)
1264 len += strlen (*argvp) + 2;
1265
1266 p = msg = alloca (len + 1);
1267
1268 for (argvp=argv; argvp[1] != 0; ++argvp)
1269 {
1270 strcpy (p, *argvp);
1271 p += strlen (*argvp);
1272 *(p++) = ',';
1273 *(p++) = ' ';
1274 }
1275 strcpy (p, *argvp);
1276
1277 switch (*funcname) {
1278 case 'e':
1279 fatal (reading_file, "%s", msg);
1280
1281 case 'w':
1282 error (reading_file, "%s", msg);
1283 break;
1284
1285 case 'i':
1286 printf ("%s\n", msg);
1287 fflush(stdout);
1288 break;
1289
1290 default:
1291 fatal (*expanding_var, "Internal error: func_error: '%s'", funcname);
1292 }
1293
1294 /* The warning function expands to the empty string. */
1295 return o;
1296}
1297
1298
1299/*
1300 chop argv[0] into words, and sort them.
1301 */
1302static char *
1303func_sort (char *o, char **argv, const char *funcname UNUSED)
1304{
1305 const char *t;
1306 char **words;
1307 int wordi;
1308 char *p;
1309 unsigned int len;
1310 int i;
1311
1312 /* Find the maximum number of words we'll have. */
1313 t = argv[0];
1314 wordi = 1;
1315 while (*t != '\0')
1316 {
1317 char c = *(t++);
1318
1319 if (! isspace ((unsigned char)c))
1320 continue;
1321
1322 ++wordi;
1323
1324 while (isspace ((unsigned char)*t))
1325 ++t;
1326 }
1327
1328 words = xmalloc (wordi * sizeof (char *));
1329
1330 /* Now assign pointers to each string in the array. */
1331 t = argv[0];
1332 wordi = 0;
1333 while ((p = find_next_token (&t, &len)) != 0)
1334 {
1335 ++t;
1336 p[len] = '\0';
1337 words[wordi++] = p;
1338 }
1339
1340 if (wordi)
1341 {
1342 /* Now sort the list of words. */
1343 qsort (words, wordi, sizeof (char *), alpha_compare);
1344
1345 /* Now write the sorted list, uniquified. */
1346#ifdef CONFIG_WITH_RSORT
1347 if (strcmp (funcname, "rsort"))
1348 {
1349 /* sort */
1350#endif
1351 for (i = 0; i < wordi; ++i)
1352 {
1353 len = strlen (words[i]);
1354 if (i == wordi - 1 || strlen (words[i + 1]) != len
1355 || strcmp (words[i], words[i + 1]))
1356 {
1357 o = variable_buffer_output (o, words[i], len);
1358 o = variable_buffer_output (o, " ", 1);
1359 }
1360 }
1361#ifdef CONFIG_WITH_RSORT
1362 }
1363 else
1364 {
1365 /* rsort - reverse the result */
1366 i = wordi;
1367 while (i-- > 0)
1368 {
1369 len = strlen (words[i]);
1370 if (i == 0 || strlen (words[i - 1]) != len
1371 || strcmp (words[i], words[i - 1]))
1372 {
1373 o = variable_buffer_output (o, words[i], len);
1374 o = variable_buffer_output (o, " ", 1);
1375 }
1376 }
1377 }
1378#endif
1379
1380 /* Kill the last space. */
1381 --o;
1382 }
1383
1384 free (words);
1385
1386 return o;
1387}
1388
1389/*
1390 $(if condition,true-part[,false-part])
1391
1392 CONDITION is false iff it evaluates to an empty string. White
1393 space before and after condition are stripped before evaluation.
1394
1395 If CONDITION is true, then TRUE-PART is evaluated, otherwise FALSE-PART is
1396 evaluated (if it exists). Because only one of the two PARTs is evaluated,
1397 you can use $(if ...) to create side-effects (with $(shell ...), for
1398 example).
1399*/
1400
1401static char *
1402func_if (char *o, char **argv, const char *funcname UNUSED)
1403{
1404 const char *begp = argv[0];
1405 const char *endp = begp + strlen (argv[0]) - 1;
1406 int result = 0;
1407
1408 /* Find the result of the condition: if we have a value, and it's not
1409 empty, the condition is true. If we don't have a value, or it's the
1410 empty string, then it's false. */
1411
1412 strip_whitespace (&begp, &endp);
1413
1414 if (begp <= endp)
1415 {
1416 char *expansion = expand_argument (begp, endp+1);
1417
1418 result = strlen (expansion);
1419 free (expansion);
1420 }
1421
1422 /* If the result is true (1) we want to eval the first argument, and if
1423 it's false (0) we want to eval the second. If the argument doesn't
1424 exist we do nothing, otherwise expand it and add to the buffer. */
1425
1426 argv += 1 + !result;
1427
1428 if (*argv)
1429 {
1430 char *expansion = expand_argument (*argv, NULL);
1431
1432 o = variable_buffer_output (o, expansion, strlen (expansion));
1433
1434 free (expansion);
1435 }
1436
1437 return o;
1438}
1439
1440/*
1441 $(or condition1[,condition2[,condition3[...]]])
1442
1443 A CONDITION is false iff it evaluates to an empty string. White
1444 space before and after CONDITION are stripped before evaluation.
1445
1446 CONDITION1 is evaluated. If it's true, then this is the result of
1447 expansion. If it's false, CONDITION2 is evaluated, and so on. If none of
1448 the conditions are true, the expansion is the empty string.
1449
1450 Once a CONDITION is true no further conditions are evaluated
1451 (short-circuiting).
1452*/
1453
1454static char *
1455func_or (char *o, char **argv, const char *funcname UNUSED)
1456{
1457 for ( ; *argv ; ++argv)
1458 {
1459 const char *begp = *argv;
1460 const char *endp = begp + strlen (*argv) - 1;
1461 char *expansion;
1462 int result = 0;
1463
1464 /* Find the result of the condition: if it's false keep going. */
1465
1466 strip_whitespace (&begp, &endp);
1467
1468 if (begp > endp)
1469 continue;
1470
1471 expansion = expand_argument (begp, endp+1);
1472 result = strlen (expansion);
1473
1474 /* If the result is false keep going. */
1475 if (!result)
1476 {
1477 free (expansion);
1478 continue;
1479 }
1480
1481 /* It's true! Keep this result and return. */
1482 o = variable_buffer_output (o, expansion, result);
1483 free (expansion);
1484 break;
1485 }
1486
1487 return o;
1488}
1489
1490/*
1491 $(and condition1[,condition2[,condition3[...]]])
1492
1493 A CONDITION is false iff it evaluates to an empty string. White
1494 space before and after CONDITION are stripped before evaluation.
1495
1496 CONDITION1 is evaluated. If it's false, then this is the result of
1497 expansion. If it's true, CONDITION2 is evaluated, and so on. If all of
1498 the conditions are true, the expansion is the result of the last condition.
1499
1500 Once a CONDITION is false no further conditions are evaluated
1501 (short-circuiting).
1502*/
1503
1504static char *
1505func_and (char *o, char **argv, const char *funcname UNUSED)
1506{
1507 char *expansion;
1508 int result;
1509
1510 while (1)
1511 {
1512 const char *begp = *argv;
1513 const char *endp = begp + strlen (*argv) - 1;
1514
1515 /* An empty condition is always false. */
1516 strip_whitespace (&begp, &endp);
1517 if (begp > endp)
1518 return o;
1519
1520 expansion = expand_argument (begp, endp+1);
1521 result = strlen (expansion);
1522
1523 /* If the result is false, stop here: we're done. */
1524 if (!result)
1525 break;
1526
1527 /* Otherwise the result is true. If this is the last one, keep this
1528 result and quit. Otherwise go on to the next one! */
1529
1530 if (*(++argv))
1531 free (expansion);
1532 else
1533 {
1534 o = variable_buffer_output (o, expansion, result);
1535 break;
1536 }
1537 }
1538
1539 free (expansion);
1540
1541 return o;
1542}
1543
1544static char *
1545func_wildcard (char *o, char **argv, const char *funcname UNUSED)
1546{
1547#ifdef _AMIGA
1548 o = wildcard_expansion (argv[0], o);
1549#else
1550 char *p = string_glob (argv[0]);
1551 o = variable_buffer_output (o, p, strlen (p));
1552#endif
1553 return o;
1554}
1555
1556/*
1557 $(eval <makefile string>)
1558
1559 Always resolves to the empty string.
1560
1561 Treat the arguments as a segment of makefile, and parse them.
1562*/
1563
1564static char *
1565func_eval (char *o, char **argv, const char *funcname UNUSED)
1566{
1567 char *buf;
1568 unsigned int len;
1569
1570 /* Eval the buffer. Pop the current variable buffer setting so that the
1571 eval'd code can use its own without conflicting. */
1572
1573 install_variable_buffer (&buf, &len);
1574
1575#ifndef CONFIG_WITH_VALUE_LENGTH
1576 eval_buffer (argv[0]);
1577#else
1578 eval_buffer (argv[0], strchr (argv[0], '\0'));
1579#endif
1580
1581 restore_variable_buffer (buf, len);
1582
1583 return o;
1584}
1585
1586
1587#ifdef CONFIG_WITH_EVALPLUS
1588/* Same as func_eval except that we push and pop the local variable
1589 context before evaluating the buffer. */
1590static char *
1591func_evalctx (char *o, char **argv, const char *funcname UNUSED)
1592{
1593 char *buf;
1594 unsigned int len;
1595
1596 /* Eval the buffer. Pop the current variable buffer setting so that the
1597 eval'd code can use its own without conflicting. */
1598
1599 install_variable_buffer (&buf, &len);
1600
1601 push_new_variable_scope ();
1602
1603 eval_buffer (argv[0], strchr (argv[0], '\0'));
1604
1605 pop_variable_scope ();
1606
1607 restore_variable_buffer (buf, len);
1608
1609 return o;
1610}
1611
1612/* A mix of func_eval and func_value, saves memory for the expansion.
1613 This implements both evalval and evalvalctx, the latter has its own
1614 variable context just like evalctx. */
1615static char *
1616func_evalval (char *o, char **argv, const char *funcname)
1617{
1618 /* Look up the variable. */
1619 struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
1620 if (v)
1621 {
1622 char *buf;
1623 unsigned int len;
1624 int var_ctx;
1625 size_t off;
1626 const struct floc *reading_file_saved = reading_file;
1627
1628 /* Make a copy of the value to the variable buffer since
1629 eval_buffer will make changes to its input. */
1630
1631 off = o - variable_buffer;
1632 variable_buffer_output (o, v->value, v->value_length + 1);
1633 o = variable_buffer + off;
1634
1635 /* Eval the value. Pop the current variable buffer setting so that the
1636 eval'd code can use its own without conflicting. (really necessary?) */
1637
1638 install_variable_buffer (&buf, &len);
1639 var_ctx = !strcmp (funcname, "evalvalctx");
1640 if (var_ctx)
1641 push_new_variable_scope ();
1642 if (v->fileinfo.filenm)
1643 reading_file = &v->fileinfo;
1644
1645 assert (!o[v->value_length]);
1646 eval_buffer (o, o + v->value_length);
1647
1648 reading_file = reading_file_saved;
1649 if (var_ctx)
1650 pop_variable_scope ();
1651 restore_variable_buffer (buf, len);
1652 }
1653
1654 return o;
1655}
1656#endif /* CONFIG_WITH_EVALPLUS */
1657
1658static char *
1659func_value (char *o, char **argv, const char *funcname UNUSED)
1660{
1661 /* Look up the variable. */
1662 struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
1663
1664 /* Copy its value into the output buffer without expanding it. */
1665 if (v)
1666#ifdef CONFIG_WITH_VALUE_LENGTH
1667 o = variable_buffer_output (o, v->value,
1668 v->value_length >= 0
1669 ? (unsigned int)v->value_length /* FIXME */
1670 : strlen(v->value));
1671#else
1672 o = variable_buffer_output (o, v->value, strlen(v->value));
1673#endif
1674
1675 return o;
1676}
1677
1678/*
1679 \r is replaced on UNIX as well. Is this desirable?
1680 */
1681static void
1682fold_newlines (char *buffer, unsigned int *length)
1683{
1684 char *dst = buffer;
1685 char *src = buffer;
1686 char *last_nonnl = buffer -1;
1687 src[*length] = 0;
1688 for (; *src != '\0'; ++src)
1689 {
1690 if (src[0] == '\r' && src[1] == '\n')
1691 continue;
1692 if (*src == '\n')
1693 {
1694 *dst++ = ' ';
1695 }
1696 else
1697 {
1698 last_nonnl = dst;
1699 *dst++ = *src;
1700 }
1701 }
1702 *(++last_nonnl) = '\0';
1703 *length = last_nonnl - buffer;
1704}
1705
1706
1707
1708int shell_function_pid = 0, shell_function_completed;
1709
1710
1711#ifdef WINDOWS32
1712/*untested*/
1713
1714#include <windows.h>
1715#include <io.h>
1716#include "sub_proc.h"
1717
1718
1719void
1720windows32_openpipe (int *pipedes, int *pid_p, char **command_argv, char **envp)
1721{
1722 SECURITY_ATTRIBUTES saAttr;
1723 HANDLE hIn;
1724 HANDLE hErr;
1725 HANDLE hChildOutRd;
1726 HANDLE hChildOutWr;
1727 HANDLE hProcess;
1728
1729
1730 saAttr.nLength = sizeof (SECURITY_ATTRIBUTES);
1731 saAttr.bInheritHandle = TRUE;
1732 saAttr.lpSecurityDescriptor = NULL;
1733
1734 if (DuplicateHandle (GetCurrentProcess(),
1735 GetStdHandle(STD_INPUT_HANDLE),
1736 GetCurrentProcess(),
1737 &hIn,
1738 0,
1739 TRUE,
1740 DUPLICATE_SAME_ACCESS) == FALSE) {
1741 fatal (NILF, _("create_child_process: DuplicateHandle(In) failed (e=%ld)\n"),
1742 GetLastError());
1743
1744 }
1745 if (DuplicateHandle(GetCurrentProcess(),
1746 GetStdHandle(STD_ERROR_HANDLE),
1747 GetCurrentProcess(),
1748 &hErr,
1749 0,
1750 TRUE,
1751 DUPLICATE_SAME_ACCESS) == FALSE) {
1752 fatal (NILF, _("create_child_process: DuplicateHandle(Err) failed (e=%ld)\n"),
1753 GetLastError());
1754 }
1755
1756 if (!CreatePipe(&hChildOutRd, &hChildOutWr, &saAttr, 0))
1757 fatal (NILF, _("CreatePipe() failed (e=%ld)\n"), GetLastError());
1758
1759 hProcess = process_init_fd(hIn, hChildOutWr, hErr);
1760
1761 if (!hProcess)
1762 fatal (NILF, _("windows32_openpipe (): process_init_fd() failed\n"));
1763
1764 /* make sure that CreateProcess() has Path it needs */
1765 sync_Path_environment();
1766
1767 if (!process_begin(hProcess, command_argv, envp, command_argv[0], NULL)) {
1768 /* register process for wait */
1769 process_register(hProcess);
1770
1771 /* set the pid for returning to caller */
1772 *pid_p = (int) hProcess;
1773
1774 /* set up to read data from child */
1775 pipedes[0] = _open_osfhandle((long) hChildOutRd, O_RDONLY);
1776
1777 /* this will be closed almost right away */
1778 pipedes[1] = _open_osfhandle((long) hChildOutWr, O_APPEND);
1779 } else {
1780 /* reap/cleanup the failed process */
1781 process_cleanup(hProcess);
1782
1783 /* close handles which were duplicated, they weren't used */
1784 CloseHandle(hIn);
1785 CloseHandle(hErr);
1786
1787 /* close pipe handles, they won't be used */
1788 CloseHandle(hChildOutRd);
1789 CloseHandle(hChildOutWr);
1790
1791 /* set status for return */
1792 pipedes[0] = pipedes[1] = -1;
1793 *pid_p = -1;
1794 }
1795}
1796#endif
1797
1798
1799#ifdef __MSDOS__
1800FILE *
1801msdos_openpipe (int* pipedes, int *pidp, char *text)
1802{
1803 FILE *fpipe=0;
1804 /* MSDOS can't fork, but it has `popen'. */
1805 struct variable *sh = lookup_variable ("SHELL", 5);
1806 int e;
1807 extern int dos_command_running, dos_status;
1808
1809 /* Make sure not to bother processing an empty line. */
1810 while (isblank ((unsigned char)*text))
1811 ++text;
1812 if (*text == '\0')
1813 return 0;
1814
1815 if (sh)
1816 {
1817 char buf[PATH_MAX + 7];
1818 /* This makes sure $SHELL value is used by $(shell), even
1819 though the target environment is not passed to it. */
1820 sprintf (buf, "SHELL=%s", sh->value);
1821 putenv (buf);
1822 }
1823
1824 e = errno;
1825 errno = 0;
1826 dos_command_running = 1;
1827 dos_status = 0;
1828 /* If dos_status becomes non-zero, it means the child process
1829 was interrupted by a signal, like SIGINT or SIGQUIT. See
1830 fatal_error_signal in commands.c. */
1831 fpipe = popen (text, "rt");
1832 dos_command_running = 0;
1833 if (!fpipe || dos_status)
1834 {
1835 pipedes[0] = -1;
1836 *pidp = -1;
1837 if (dos_status)
1838 errno = EINTR;
1839 else if (errno == 0)
1840 errno = ENOMEM;
1841 shell_function_completed = -1;
1842 }
1843 else
1844 {
1845 pipedes[0] = fileno (fpipe);
1846 *pidp = 42; /* Yes, the Meaning of Life, the Universe, and Everything! */
1847 errno = e;
1848 shell_function_completed = 1;
1849 }
1850 return fpipe;
1851}
1852#endif
1853
1854/*
1855 Do shell spawning, with the naughty bits for different OSes.
1856 */
1857
1858#ifdef VMS
1859
1860/* VMS can't do $(shell ...) */
1861#define func_shell 0
1862
1863#else
1864#ifndef _AMIGA
1865static char *
1866func_shell (char *o, char **argv, const char *funcname UNUSED)
1867{
1868 char *batch_filename = NULL;
1869
1870#ifdef __MSDOS__
1871 FILE *fpipe;
1872#endif
1873 char **command_argv;
1874 const char *error_prefix;
1875 char **envp;
1876 int pipedes[2];
1877 int pid;
1878
1879#ifndef __MSDOS__
1880 /* Construct the argument list. */
1881 command_argv = construct_command_argv (argv[0], NULL, NULL, &batch_filename);
1882 if (command_argv == 0)
1883 return o;
1884#endif
1885
1886 /* Using a target environment for `shell' loses in cases like:
1887 export var = $(shell echo foobie)
1888 because target_environment hits a loop trying to expand $(var)
1889 to put it in the environment. This is even more confusing when
1890 var was not explicitly exported, but just appeared in the
1891 calling environment.
1892
1893 See Savannah bug #10593.
1894
1895 envp = target_environment (NILF);
1896 */
1897
1898 envp = environ;
1899
1900 /* For error messages. */
1901 if (reading_file && reading_file->filenm)
1902 {
1903 char *p = alloca (strlen (reading_file->filenm)+11+4);
1904 sprintf (p, "%s:%lu: ", reading_file->filenm, reading_file->lineno);
1905 error_prefix = p;
1906 }
1907 else
1908 error_prefix = "";
1909
1910#if defined(__MSDOS__)
1911 fpipe = msdos_openpipe (pipedes, &pid, argv[0]);
1912 if (pipedes[0] < 0)
1913 {
1914 perror_with_name (error_prefix, "pipe");
1915 return o;
1916 }
1917#elif defined(WINDOWS32)
1918 windows32_openpipe (pipedes, &pid, command_argv, envp);
1919 if (pipedes[0] < 0)
1920 {
1921 /* open of the pipe failed, mark as failed execution */
1922 shell_function_completed = -1;
1923
1924 return o;
1925 }
1926 else
1927#else
1928 if (pipe (pipedes) < 0)
1929 {
1930 perror_with_name (error_prefix, "pipe");
1931 return o;
1932 }
1933
1934# ifdef __EMX__
1935 /* close some handles that are unnecessary for the child process */
1936 CLOSE_ON_EXEC(pipedes[1]);
1937 CLOSE_ON_EXEC(pipedes[0]);
1938 /* Never use fork()/exec() here! Use spawn() instead in exec_command() */
1939 pid = child_execute_job (0, pipedes[1], command_argv, envp);
1940 if (pid < 0)
1941 perror_with_name (error_prefix, "spawn");
1942# else /* ! __EMX__ */
1943 pid = vfork ();
1944 if (pid < 0)
1945 perror_with_name (error_prefix, "fork");
1946 else if (pid == 0)
1947 child_execute_job (0, pipedes[1], command_argv, envp);
1948 else
1949# endif
1950#endif
1951 {
1952 /* We are the parent. */
1953 char *buffer;
1954 unsigned int maxlen, i;
1955 int cc;
1956
1957 /* Record the PID for reap_children. */
1958 shell_function_pid = pid;
1959#ifndef __MSDOS__
1960 shell_function_completed = 0;
1961
1962 /* Free the storage only the child needed. */
1963 free (command_argv[0]);
1964 free (command_argv);
1965
1966 /* Close the write side of the pipe. */
1967# ifdef _MSC_VER /* Avoid annoying msvcrt when debugging. (bird) */
1968 if (pipedes[1] != -1)
1969# endif
1970 close (pipedes[1]);
1971#endif
1972
1973 /* Set up and read from the pipe. */
1974
1975 maxlen = 200;
1976 buffer = xmalloc (maxlen + 1);
1977
1978 /* Read from the pipe until it gets EOF. */
1979 for (i = 0; ; i += cc)
1980 {
1981 if (i == maxlen)
1982 {
1983 maxlen += 512;
1984 buffer = xrealloc (buffer, maxlen + 1);
1985 }
1986
1987 EINTRLOOP (cc, read (pipedes[0], &buffer[i], maxlen - i));
1988 if (cc <= 0)
1989 break;
1990 }
1991 buffer[i] = '\0';
1992
1993 /* Close the read side of the pipe. */
1994#ifdef __MSDOS__
1995 if (fpipe)
1996 (void) pclose (fpipe);
1997#else
1998# ifdef _MSC_VER /* Avoid annoying msvcrt when debugging. (bird) */
1999 if (pipedes[0] != -1)
2000# endif
2001 (void) close (pipedes[0]);
2002#endif
2003
2004 /* Loop until child_handler or reap_children() sets
2005 shell_function_completed to the status of our child shell. */
2006 while (shell_function_completed == 0)
2007 reap_children (1, 0);
2008
2009 if (batch_filename) {
2010 DB (DB_VERBOSE, (_("Cleaning up temporary batch file %s\n"),
2011 batch_filename));
2012 remove (batch_filename);
2013 free (batch_filename);
2014 }
2015 shell_function_pid = 0;
2016
2017 /* The child_handler function will set shell_function_completed
2018 to 1 when the child dies normally, or to -1 if it
2019 dies with status 127, which is most likely an exec fail. */
2020
2021 if (shell_function_completed == -1)
2022 {
2023 /* This likely means that the execvp failed, so we should just
2024 write the error message in the pipe from the child. */
2025 fputs (buffer, stderr);
2026 fflush (stderr);
2027 }
2028 else
2029 {
2030 /* The child finished normally. Replace all newlines in its output
2031 with spaces, and put that in the variable output buffer. */
2032 fold_newlines (buffer, &i);
2033 o = variable_buffer_output (o, buffer, i);
2034 }
2035
2036 free (buffer);
2037 }
2038
2039 return o;
2040}
2041
2042#else /* _AMIGA */
2043
2044/* Do the Amiga version of func_shell. */
2045
2046static char *
2047func_shell (char *o, char **argv, const char *funcname)
2048{
2049 /* Amiga can't fork nor spawn, but I can start a program with
2050 redirection of my choice. However, this means that we
2051 don't have an opportunity to reopen stdout to trap it. Thus,
2052 we save our own stdout onto a new descriptor and dup a temp
2053 file's descriptor onto our stdout temporarily. After we
2054 spawn the shell program, we dup our own stdout back to the
2055 stdout descriptor. The buffer reading is the same as above,
2056 except that we're now reading from a file. */
2057
2058#include <dos/dos.h>
2059#include <proto/dos.h>
2060
2061 BPTR child_stdout;
2062 char tmp_output[FILENAME_MAX];
2063 unsigned int maxlen = 200, i;
2064 int cc;
2065 char * buffer, * ptr;
2066 char ** aptr;
2067 int len = 0;
2068 char* batch_filename = NULL;
2069
2070 /* Construct the argument list. */
2071 command_argv = construct_command_argv (argv[0], (char **) NULL,
2072 (struct file *) 0, &batch_filename);
2073 if (command_argv == 0)
2074 return o;
2075
2076 /* Note the mktemp() is a security hole, but this only runs on Amiga.
2077 Ideally we would use main.c:open_tmpfile(), but this uses a special
2078 Open(), not fopen(), and I'm not familiar enough with the code to mess
2079 with it. */
2080 strcpy (tmp_output, "t:MakeshXXXXXXXX");
2081 mktemp (tmp_output);
2082 child_stdout = Open (tmp_output, MODE_NEWFILE);
2083
2084 for (aptr=command_argv; *aptr; aptr++)
2085 len += strlen (*aptr) + 1;
2086
2087 buffer = xmalloc (len + 1);
2088 ptr = buffer;
2089
2090 for (aptr=command_argv; *aptr; aptr++)
2091 {
2092 strcpy (ptr, *aptr);
2093 ptr += strlen (ptr) + 1;
2094 *ptr ++ = ' ';
2095 *ptr = 0;
2096 }
2097
2098 ptr[-1] = '\n';
2099
2100 Execute (buffer, NULL, child_stdout);
2101 free (buffer);
2102
2103 Close (child_stdout);
2104
2105 child_stdout = Open (tmp_output, MODE_OLDFILE);
2106
2107 buffer = xmalloc (maxlen);
2108 i = 0;
2109 do
2110 {
2111 if (i == maxlen)
2112 {
2113 maxlen += 512;
2114 buffer = xrealloc (buffer, maxlen + 1);
2115 }
2116
2117 cc = Read (child_stdout, &buffer[i], maxlen - i);
2118 if (cc > 0)
2119 i += cc;
2120 } while (cc > 0);
2121
2122 Close (child_stdout);
2123
2124 fold_newlines (buffer, &i);
2125 o = variable_buffer_output (o, buffer, i);
2126 free (buffer);
2127 return o;
2128}
2129#endif /* _AMIGA */
2130#endif /* !VMS */
2131
2132#ifdef EXPERIMENTAL
2133
2134/*
2135 equality. Return is string-boolean, ie, the empty string is false.
2136 */
2137static char *
2138func_eq (char *o, char **argv, const char *funcname)
2139{
2140 int result = ! strcmp (argv[0], argv[1]);
2141 o = variable_buffer_output (o, result ? "1" : "", result);
2142 return o;
2143}
2144
2145
2146/*
2147 string-boolean not operator.
2148 */
2149static char *
2150func_not (char *o, char **argv, const char *funcname)
2151{
2152 const char *s = argv[0];
2153 int result = 0;
2154 while (isspace ((unsigned char)*s))
2155 s++;
2156 result = ! (*s);
2157 o = variable_buffer_output (o, result ? "1" : "", result);
2158 return o;
2159}
2160#endif
2161
2162
2163
2164#ifdef CONFIG_WITH_DEFINED
2165/* Similar to ifdef. */
2166static char *
2167func_defined (char *o, char **argv, const char *funcname)
2168{
2169 struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
2170 int result = v != NULL && *v->value != '\0';
2171 o = variable_buffer_output (o, result ? "1" : "", result);
2172 return o;
2173}
2174#endif /* CONFIG_WITH_DEFINED*/
2175
2176
2177
2178/* Return the absolute name of file NAME which does not contain any `.',
2179 `..' components nor any repeated path separators ('/'). */
2180#ifdef KMK
2181char *
2182#else
2183static char *
2184#endif
2185abspath (const char *name, char *apath)
2186{
2187 char *dest;
2188 const char *start, *end, *apath_limit;
2189
2190 if (name[0] == '\0' || apath == NULL)
2191 return NULL;
2192
2193#ifdef WINDOWS32 /* bird */
2194 dest = w32ify((char *)name, 1);
2195 if (!dest)
2196 return NULL;
2197 {
2198 size_t len = strlen(dest);
2199 memcpy(apath, dest, len);
2200 dest = apath + len;
2201 }
2202
2203 (void)end; (void)start; (void)apath_limit;
2204
2205#elif defined __OS2__ /* bird */
2206 if (_abspath(apath, name, GET_PATH_MAX))
2207 return NULL;
2208 dest = strchr(apath, '\0');
2209
2210 (void)end; (void)start; (void)apath_limit; (void)dest;
2211
2212#else /* !WINDOWS32 && !__OS2__ */
2213 apath_limit = apath + GET_PATH_MAX;
2214
2215#ifdef HAVE_DOS_PATHS /* bird added this */
2216 if (isalpha(name[0]) && name[1] == ':')
2217 {
2218 /* drive spec */
2219 apath[0] = toupper(name[0]);
2220 apath[1] = ':';
2221 apath[2] = '/';
2222 name += 2;
2223 }
2224 else
2225#endif /* HAVE_DOS_PATHS */
2226 if (name[0] != '/')
2227 {
2228 /* It is unlikely we would make it until here but just to make sure. */
2229 if (!starting_directory)
2230 return NULL;
2231
2232 strcpy (apath, starting_directory);
2233
2234 dest = strchr (apath, '\0');
2235 }
2236 else
2237 {
2238 apath[0] = '/';
2239 dest = apath + 1;
2240 }
2241
2242 for (start = end = name; *start != '\0'; start = end)
2243 {
2244 unsigned long len;
2245
2246 /* Skip sequence of multiple path-separators. */
2247 while (*start == '/')
2248 ++start;
2249
2250 /* Find end of path component. */
2251 for (end = start; *end != '\0' && *end != '/'; ++end)
2252 ;
2253
2254 len = end - start;
2255
2256 if (len == 0)
2257 break;
2258 else if (len == 1 && start[0] == '.')
2259 /* nothing */;
2260 else if (len == 2 && start[0] == '.' && start[1] == '.')
2261 {
2262 /* Back up to previous component, ignore if at root already. */
2263 if (dest > apath + 1)
2264 while ((--dest)[-1] != '/');
2265 }
2266 else
2267 {
2268 if (dest[-1] != '/')
2269 *dest++ = '/';
2270
2271 if (dest + len >= apath_limit)
2272 return NULL;
2273
2274 dest = memcpy (dest, start, len);
2275 dest += len;
2276 *dest = '\0';
2277 }
2278 }
2279#endif /* !WINDOWS32 && !__OS2__ */
2280
2281 /* Unless it is root strip trailing separator. */
2282#ifdef HAVE_DOS_PATHS /* bird (is this correct? what about UNC?) */
2283 if (dest > apath + 1 + (apath[0] != '/') && dest[-1] == '/')
2284#else
2285 if (dest > apath + 1 && dest[-1] == '/')
2286#endif
2287 --dest;
2288
2289 *dest = '\0';
2290
2291 return apath;
2292}
2293
2294
2295static char *
2296func_realpath (char *o, char **argv, const char *funcname UNUSED)
2297{
2298 /* Expand the argument. */
2299 const char *p = argv[0];
2300 const char *path = 0;
2301 int doneany = 0;
2302 unsigned int len = 0;
2303 PATH_VAR (in);
2304 PATH_VAR (out);
2305
2306 while ((path = find_next_token (&p, &len)) != 0)
2307 {
2308 if (len < GET_PATH_MAX)
2309 {
2310 strncpy (in, path, len);
2311 in[len] = '\0';
2312
2313 if (
2314#ifdef HAVE_REALPATH
2315 realpath (in, out)
2316#else
2317 abspath (in, out)
2318#endif
2319 )
2320 {
2321 o = variable_buffer_output (o, out, strlen (out));
2322 o = variable_buffer_output (o, " ", 1);
2323 doneany = 1;
2324 }
2325 }
2326 }
2327
2328 /* Kill last space. */
2329 if (doneany)
2330 --o;
2331
2332 return o;
2333}
2334
2335static char *
2336func_abspath (char *o, char **argv, const char *funcname UNUSED)
2337{
2338 /* Expand the argument. */
2339 const char *p = argv[0];
2340 const char *path = 0;
2341 int doneany = 0;
2342 unsigned int len = 0;
2343 PATH_VAR (in);
2344 PATH_VAR (out);
2345
2346 while ((path = find_next_token (&p, &len)) != 0)
2347 {
2348 if (len < GET_PATH_MAX)
2349 {
2350 strncpy (in, path, len);
2351 in[len] = '\0';
2352
2353 if (abspath (in, out))
2354 {
2355 o = variable_buffer_output (o, out, strlen (out));
2356 o = variable_buffer_output (o, " ", 1);
2357 doneany = 1;
2358 }
2359 }
2360 }
2361
2362 /* Kill last space. */
2363 if (doneany)
2364 --o;
2365
2366 return o;
2367}
2368
2369#ifdef CONFIG_WITH_ABSPATHEX
2370/* Same as abspath except that the current path may be given as the
2371 2nd argument. */
2372static char *
2373func_abspathex (char *o, char **argv, const char *funcname UNUSED)
2374{
2375 char *cwd = argv[1];
2376
2377 /* cwd needs leading spaces chopped and may be optional,
2378 in which case we're exactly like $(abspath ). */
2379 while (isblank(*cwd))
2380 cwd++;
2381 if (!*cwd)
2382 o = func_abspath (o, argv, funcname);
2383 else
2384 {
2385 /* Expand the argument. */
2386 const char *p = argv[0];
2387 unsigned int cwd_len = ~0U;
2388 char *path = 0;
2389 int doneany = 0;
2390 unsigned int len = 0;
2391 PATH_VAR (in);
2392 PATH_VAR (out);
2393
2394 while ((path = find_next_token (&p, &len)) != 0)
2395 {
2396 if (len < GET_PATH_MAX)
2397 {
2398#ifdef HAVE_DOS_PATHS
2399 if (path[0] != '/' && path[0] != '\\' && (len < 2 || path[1] != ':') && cwd)
2400#else
2401 if (path[0] != '/' && cwd)
2402#endif
2403 {
2404 /* relative path, prefix with cwd. */
2405 if (cwd_len == ~0U)
2406 cwd_len = strlen (cwd);
2407 if (cwd_len + len + 1 >= GET_PATH_MAX)
2408 continue;
2409 memcpy (in, cwd, cwd_len);
2410 in[cwd_len] = '/';
2411 memcpy (in + cwd_len + 1, path, len);
2412 in[cwd_len + len + 1] = '\0';
2413 }
2414 else
2415 {
2416 /* absolute path pass it as-is. */
2417 memcpy (in, path, len);
2418 in[len] = '\0';
2419 }
2420
2421 if (abspath (in, out))
2422 {
2423 o = variable_buffer_output (o, out, strlen (out));
2424 o = variable_buffer_output (o, " ", 1);
2425 doneany = 1;
2426 }
2427 }
2428 }
2429
2430 /* Kill last space. */
2431 if (doneany)
2432 --o;
2433 }
2434
2435 return o;
2436}
2437#endif
2438
2439#ifdef CONFIG_WITH_XARGS
2440/* Create one or more command lines avoiding the max argument
2441 lenght restriction of the host OS.
2442
2443 The last argument is the list of arguments that the normal
2444 xargs command would be fed from stdin.
2445
2446 The first argument is initial command and it's arguments.
2447
2448 If there are three or more arguments, the 2nd argument is
2449 the command and arguments to be used on subsequent
2450 command lines. Defaults to the initial command.
2451
2452 If there are four or more arguments, the 3rd argument is
2453 the command to be used at the final command line. Defaults
2454 to the sub sequent or initial command .
2455
2456 A future version of this function may define more arguments
2457 and therefor anyone specifying six or more arguments will
2458 cause fatal errors.
2459
2460 Typical usage is:
2461 $(xargs ar cas mylib.a,$(objects))
2462 or
2463 $(xargs ar cas mylib.a,ar as mylib.a,$(objects))
2464
2465 It will then create one or more "ar mylib.a ..." command
2466 lines with proper \n\t separation so it can be used when
2467 writing rules. */
2468static char *
2469func_xargs (char *o, char **argv, const char *funcname UNUSED)
2470{
2471 int argc;
2472 const char *initial_cmd;
2473 size_t initial_cmd_len;
2474 const char *subsequent_cmd;
2475 size_t subsequent_cmd_len;
2476 const char *final_cmd;
2477 size_t final_cmd_len;
2478 const char *args;
2479 size_t max_args;
2480 int i;
2481
2482#ifdef ARG_MAX
2483 /* ARG_MAX is a bit unreliable (environment), so drop 25% of the max. */
2484# define XARGS_MAX (ARG_MAX - (ARG_MAX / 4))
2485#else /* FIXME: update configure with a command line length test. */
2486# define XARGS_MAX 10240
2487#endif
2488
2489 argc = 0;
2490 while (argv[argc])
2491 argc++;
2492 if (argc > 4)
2493 fatal (NILF, _("Too many arguments for $(xargs)!\n"));
2494
2495 /* first: the initial / default command.*/
2496 initial_cmd = argv[0];
2497 while (isspace ((unsigned char)*initial_cmd))
2498 initial_cmd++;
2499 max_args = initial_cmd_len = strlen (initial_cmd);
2500
2501 /* second: the command for the subsequent command lines. defaults to the initial cmd. */
2502 subsequent_cmd = argc > 2 && argv[1][0] != '\0' ? argv[1] : "";
2503 while (isspace ((unsigned char)*subsequent_cmd))
2504 subsequent_cmd++;
2505 if (*subsequent_cmd)
2506 {
2507 subsequent_cmd_len = strlen (subsequent_cmd);
2508 if (subsequent_cmd_len > max_args)
2509 max_args = subsequent_cmd_len;
2510 }
2511 else
2512 {
2513 subsequent_cmd = initial_cmd;
2514 subsequent_cmd_len = initial_cmd_len;
2515 }
2516
2517 /* third: the final command. defaults to the subseq cmd. */
2518 final_cmd = argc > 3 && argv[2][0] != '\0' ? argv[2] : "";
2519 while (isspace ((unsigned char)*final_cmd))
2520 final_cmd++;
2521 if (*final_cmd)
2522 {
2523 final_cmd_len = strlen (final_cmd);
2524 if (final_cmd_len > max_args)
2525 max_args = final_cmd_len;
2526 }
2527 else
2528 {
2529 final_cmd = subsequent_cmd;
2530 final_cmd_len = subsequent_cmd_len;
2531 }
2532
2533 /* last: the arguments to split up into sensible portions. */
2534 args = argv[argc - 1];
2535
2536 /* calc the max argument length. */
2537 if (XARGS_MAX <= max_args + 2)
2538 fatal (NILF, _("$(xargs): the commands are longer than the max exec argument length. (%lu <= %lu)\n"),
2539 (unsigned long)XARGS_MAX, (unsigned long)max_args + 2);
2540 max_args = XARGS_MAX - max_args - 1;
2541
2542 /* generate the commands. */
2543 i = 0;
2544 for (i = 0; ; i++)
2545 {
2546 unsigned int len;
2547 const char *iterator = args;
2548 const char *end = args;
2549 const char *cur;
2550 const char *tmp;
2551
2552 /* scan the arguments till we reach the end or the max length. */
2553 while ((cur = find_next_token(&iterator, &len))
2554 && (size_t)((cur + len) - args) < max_args)
2555 end = cur + len;
2556 if (cur && end == args)
2557 fatal (NILF, _("$(xargs): command + one single arg is too much. giving up.\n"));
2558
2559 /* emit the command. */
2560 if (i == 0)
2561 {
2562 o = variable_buffer_output (o, (char *)initial_cmd, initial_cmd_len);
2563 o = variable_buffer_output (o, " ", 1);
2564 }
2565 else if (cur)
2566 {
2567 o = variable_buffer_output (o, "\n\t", 2);
2568 o = variable_buffer_output (o, (char *)subsequent_cmd, subsequent_cmd_len);
2569 o = variable_buffer_output (o, " ", 1);
2570 }
2571 else
2572 {
2573 o = variable_buffer_output (o, "\n\t", 2);
2574 o = variable_buffer_output (o, (char *)final_cmd, final_cmd_len);
2575 o = variable_buffer_output (o, " ", 1);
2576 }
2577
2578 tmp = end;
2579 while (tmp > args && isspace ((unsigned char)tmp[-1])) /* drop trailing spaces. */
2580 tmp--;
2581 o = variable_buffer_output (o, (char *)args, tmp - args);
2582
2583
2584 /* next */
2585 if (!cur)
2586 break;
2587 args = end;
2588 while (isspace ((unsigned char)*args))
2589 args++;
2590 }
2591
2592 return o;
2593}
2594#endif
2595
2596#ifdef CONFIG_WITH_TOUPPER_TOLOWER
2597static char *
2598func_toupper_tolower (char *o, char **argv, const char *funcname)
2599{
2600 /* Expand the argument. */
2601 const char *p = argv[0];
2602 while (*p)
2603 {
2604 /* convert to temporary buffer */
2605 char tmp[256];
2606 unsigned int i;
2607 if (!strcmp(funcname, "toupper"))
2608 for (i = 0; i < sizeof(tmp) && *p; i++, p++)
2609 tmp[i] = toupper(*p);
2610 else
2611 for (i = 0; i < sizeof(tmp) && *p; i++, p++)
2612 tmp[i] = tolower(*p);
2613 o = variable_buffer_output (o, tmp, i);
2614 }
2615
2616 return o;
2617}
2618#endif /* CONFIG_WITH_TOUPPER_TOLOWER */
2619
2620#if defined(CONFIG_WITH_VALUE_LENGTH) && defined(CONFIG_WITH_COMPARE)
2621
2622/* Strip leading spaces and other things off a command. */
2623static const char *
2624comp_cmds_strip_leading (const char *s, const char *e)
2625{
2626 while (s < e)
2627 {
2628 const char ch = *s;
2629 if (!isblank (ch)
2630 && ch != '@'
2631#ifdef CONFIG_WITH_COMMANDS_FUNC
2632 && ch != '%'
2633#endif
2634 && ch != '+'
2635 && ch != '-')
2636 break;
2637 s++;
2638 }
2639 return s;
2640}
2641
2642/* Worker for func_comp_vars() which is called if the comparision failed.
2643 It will do the slow command by command comparision of the commands
2644 when there invoked as comp-cmds. */
2645static char *
2646comp_vars_ne (char *o, const char *s1, const char *e1, const char *s2, const char *e2,
2647 char *ne_retval, const char *funcname)
2648{
2649 /* give up at once if not comp-cmds or comp-cmds-ex. */
2650 if (strcmp (funcname, "comp-cmds") != 0
2651 && strcmp (funcname, "comp-cmds-ex") != 0)
2652 o = variable_buffer_output (o, ne_retval, strlen (ne_retval));
2653 else
2654 {
2655 const char * const s1_start = s1;
2656 int new_cmd = 1;
2657 int diff;
2658 for (;;)
2659 {
2660 /* if it's a new command, strip leading stuff. */
2661 if (new_cmd)
2662 {
2663 s1 = comp_cmds_strip_leading (s1, e1);
2664 s2 = comp_cmds_strip_leading (s2, e2);
2665 new_cmd = 0;
2666 }
2667 if (s1 >= e1 || s2 >= e2)
2668 break;
2669
2670 /*
2671 * Inner compare loop which compares one line.
2672 * FIXME: parse quoting!
2673 */
2674 for (;;)
2675 {
2676 const char ch1 = *s1;
2677 const char ch2 = *s2;
2678 diff = ch1 - ch2;
2679 if (diff)
2680 break;
2681 if (ch1 == '\n')
2682 break;
2683 assert (ch1 != '\r');
2684
2685 /* next */
2686 s1++;
2687 s2++;
2688 if (s1 >= e1 || s2 >= e2)
2689 break;
2690 }
2691
2692 /*
2693 * If we exited because of a difference try to end-of-command
2694 * comparision, e.g. ignore trailing spaces.
2695 */
2696 if (diff)
2697 {
2698 /* strip */
2699 while (s1 < e1 && isblank (*s1))
2700 s1++;
2701 while (s2 < e2 && isblank (*s2))
2702 s2++;
2703 if (s1 >= e1 || s2 >= e2)
2704 break;
2705
2706 /* compare again and check that it's a newline. */
2707 if (*s2 != '\n' || *s1 != '\n')
2708 break;
2709 }
2710 /* Break out if we exited because of EOS. */
2711 else if (s1 >= e1 || s2 >= e2)
2712 break;
2713
2714 /*
2715 * Detect the end of command lines.
2716 */
2717 if (*s1 == '\n')
2718 new_cmd = s1 == s1_start || s1[-1] != '\\';
2719 s1++;
2720 s2++;
2721 }
2722
2723 /*
2724 * Ignore trailing empty lines.
2725 */
2726 if (s1 < e1 || s2 < e2)
2727 {
2728 while (s1 < e1 && (isblank (*s1) || *s1 == '\n'))
2729 if (*s1++ == '\n')
2730 s1 = comp_cmds_strip_leading (s1, e1);
2731 while (s2 < e2 && (isblank (*s2) || *s2 == '\n'))
2732 if (*s2++ == '\n')
2733 s2 = comp_cmds_strip_leading (s2, e2);
2734 }
2735
2736 /* emit the result. */
2737 if (s1 == e1 && s2 == e2)
2738 o = variable_buffer_output (o, "", 1) - 1; /** @todo check why this was necessary back the... */
2739 else
2740 o = variable_buffer_output (o, ne_retval, strlen (ne_retval));
2741 }
2742 return o;
2743}
2744
2745/*
2746 $(comp-vars var1,var2,not-equal-return)
2747 or
2748 $(comp-cmds cmd-var1,cmd-var2,not-equal-return)
2749
2750 Compares the two variables (that's given by name to avoid unnecessary
2751 expanding) and return the string in the third argument if not equal.
2752 If equal, nothing is returned.
2753
2754 comp-vars will to an exact comparision only stripping leading and
2755 trailing spaces.
2756
2757 comp-cmds will compare command by command, ignoring not only leading
2758 and trailing spaces on each line but also leading one leading '@',
2759 '-', '+' and '%'
2760*/
2761static char *
2762func_comp_vars (char *o, char **argv, const char *funcname)
2763{
2764 const char *s1, *e1, *x1, *s2, *e2, *x2;
2765 char *a1 = NULL, *a2 = NULL;
2766 size_t l, l1, l2;
2767 struct variable *var1 = lookup_variable (argv[0], strlen (argv[0]));
2768 struct variable *var2 = lookup_variable (argv[1], strlen (argv[1]));
2769
2770 /* the simple cases */
2771 if (var1 == var2)
2772 return variable_buffer_output (o, "", 0); /* eq */
2773 if (!var1 || !var2)
2774 return variable_buffer_output (o, argv[2], strlen(argv[2]));
2775 if (var1->value == var2->value)
2776 return variable_buffer_output (o, "", 0); /* eq */
2777 if (!var1->recursive && !var2->recursive)
2778 {
2779 if ( var1->value_length == var2->value_length
2780 && !memcmp (var1->value, var2->value, var1->value_length))
2781 return variable_buffer_output (o, "", 0); /* eq */
2782
2783 /* ignore trailing and leading blanks */
2784 s1 = var1->value;
2785 e1 = s1 + var1->value_length;
2786 while (isblank ((unsigned char) *s1))
2787 s1++;
2788 while (e1 > s1 && isblank ((unsigned char) e1[-1]))
2789 e1--;
2790
2791 s2 = var2->value;
2792 e2 = s2 + var2->value_length;
2793 while (isblank ((unsigned char) *s2))
2794 s2++;
2795 while (e2 > s2 && isblank ((unsigned char) e2[-1]))
2796 e2--;
2797
2798 if (e1 - s1 != e2 - s2)
2799 return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
2800 if (!memcmp (s1, s2, e1 - s1))
2801 return variable_buffer_output (o, "", 0); /* eq */
2802 return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
2803 }
2804
2805 /* ignore trailing and leading blanks */
2806 s1 = var1->value;
2807 e1 = s1 + var1->value_length;
2808 while (isblank ((unsigned char) *s1))
2809 s1++;
2810 while (e1 > s1 && isblank ((unsigned char) e1[-1]))
2811 e1--;
2812
2813 s2 = var2->value;
2814 e2 = s2 + var2->value_length;
2815 while (isblank((unsigned char)*s2))
2816 s2++;
2817 while (e2 > s2 && isblank ((unsigned char) e2[-1]))
2818 e2--;
2819
2820 /* both empty after stripping? */
2821 if (s1 == e1 && s2 == e2)
2822 return variable_buffer_output (o, "", 0); /* eq */
2823
2824 /* optimist. */
2825 if ( e1 - s1 == e2 - s2
2826 && !memcmp(s1, s2, e1 - s1))
2827 return variable_buffer_output (o, "", 0); /* eq */
2828
2829 /* compare up to the first '$' or the end. */
2830 x1 = var1->recursive ? memchr (s1, '$', e1 - s1) : NULL;
2831 x2 = var2->recursive ? memchr (s2, '$', e2 - s2) : NULL;
2832 if (!x1 && !x2)
2833 return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
2834
2835 l1 = x1 ? x1 - s1 : e1 - s1;
2836 l2 = x2 ? x2 - s2 : e2 - s2;
2837 l = l1 <= l2 ? l1 : l2;
2838 if (l && memcmp (s1, s2, l))
2839 return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
2840
2841 /* one or both buffers now require expanding. */
2842 if (!x1)
2843 s1 += l;
2844 else
2845 {
2846 s1 = a1 = allocated_variable_expand ((char *)s1 + l);
2847 if (!l)
2848 while (isblank ((unsigned char) *s1))
2849 s1++;
2850 e1 = strchr (s1, '\0');
2851 while (e1 > s1 && isblank ((unsigned char) e1[-1]))
2852 e1--;
2853 }
2854
2855 if (!x2)
2856 s2 += l;
2857 else
2858 {
2859 s2 = a2 = allocated_variable_expand ((char *)s2 + l);
2860 if (!l)
2861 while (isblank ((unsigned char) *s2))
2862 s2++;
2863 e2 = strchr (s2, '\0');
2864 while (e2 > s2 && isblank ((unsigned char) e2[-1]))
2865 e2--;
2866 }
2867
2868 /* the final compare */
2869 if ( e1 - s1 != e2 - s2
2870 || memcmp (s1, s2, e1 - s1))
2871 o = comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
2872 else
2873 o = variable_buffer_output (o, "", 1) - 1; /* eq */ /** @todo check why this was necessary back the... */
2874 if (a1)
2875 free (a1);
2876 if (a2)
2877 free (a2);
2878 return o;
2879}
2880
2881/*
2882 $(comp-cmds-ex cmds1,cmds2,not-equal-return)
2883
2884 Compares the two strings and return the string in the third argument
2885 if not equal. If equal, nothing is returned.
2886
2887 The comparision will be performed command by command, ignoring not
2888 only leading and trailing spaces on each line but also leading one
2889 leading '@', '-', '+' and '%'.
2890*/
2891static char *
2892func_comp_cmds_ex (char *o, char **argv, const char *funcname)
2893{
2894 const char *s1, *e1, *s2, *e2;
2895 size_t l1, l2;
2896
2897 /* the simple cases */
2898 s1 = argv[0];
2899 s2 = argv[1];
2900 if (s1 == s2)
2901 return variable_buffer_output (o, "", 0); /* eq */
2902 l1 = strlen (argv[0]);
2903 l2 = strlen (argv[1]);
2904
2905 if ( l1 == l2
2906 && !memcmp (s1, s2, l1))
2907 return variable_buffer_output (o, "", 0); /* eq */
2908
2909 /* ignore trailing and leading blanks */
2910 e1 = s1 + l1;
2911 s1 = comp_cmds_strip_leading (s1, e1);
2912
2913 e2 = s2 + l2;
2914 s2 = comp_cmds_strip_leading (s2, e2);
2915
2916 if (e1 - s1 != e2 - s2)
2917 return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
2918 if (!memcmp (s1, s2, e1 - s1))
2919 return variable_buffer_output (o, "", 0); /* eq */
2920 return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
2921}
2922#endif
2923
2924#ifdef CONFIG_WITH_DATE
2925# if defined (_MSC_VER) /* FIXME: !defined (HAVE_STRPTIME) */
2926char *strptime(const char *s, const char *format, struct tm *tm)
2927{
2928 return (char *)"strptime is not implemented";
2929}
2930# endif
2931/* Check if the string is all blanks or not. */
2932static int
2933all_blanks (const char *s)
2934{
2935 if (!s)
2936 return 1;
2937 while (isspace ((unsigned char)*s))
2938 s++;
2939 return *s == '\0';
2940}
2941
2942/* The first argument is the strftime format string, a iso
2943 timestamp is the default if nothing is given.
2944
2945 The second argument is a time value if given. The format
2946 is either the format from the first argument or given as
2947 an additional third argument. */
2948static char *
2949func_date (char *o, char **argv, const char *funcname)
2950{
2951 char *p;
2952 char *buf;
2953 size_t buf_size;
2954 struct tm t;
2955 const char *format;
2956
2957 /* determin the format - use a single word as the default. */
2958 format = !strcmp (funcname, "date-utc")
2959 ? "%Y-%m-%dT%H:%M:%SZ"
2960 : "%Y-%m-%dT%H:%M:%S";
2961 if (!all_blanks (argv[0]))
2962 format = argv[0];
2963
2964 /* get the time. */
2965 memset (&t, 0, sizeof(t));
2966 if (argv[0] && !all_blanks (argv[1]))
2967 {
2968 const char *input_format = !all_blanks (argv[2]) ? argv[2] : format;
2969 p = strptime (argv[1], input_format, &t);
2970 if (!p || *p != '\0')
2971 {
2972 error (NILF, _("$(%s): strptime(%s,%s,) -> %s\n"), funcname,
2973 argv[1], input_format, p ? p : "<null>");
2974 return variable_buffer_output (o, "", 0);
2975 }
2976 }
2977 else
2978 {
2979 time_t tval;
2980 time (&tval);
2981 if (!strcmp (funcname, "date-utc"))
2982 t = *gmtime (&tval);
2983 else
2984 t = *localtime (&tval);
2985 }
2986
2987 /* format it. note that zero isn't necessarily an error, so we'll
2988 have to keep shut about failures. */
2989 buf_size = 64;
2990 buf = xmalloc (buf_size);
2991 while (strftime (buf, buf_size, format, &t) == 0)
2992 {
2993 if (buf_size >= 4096)
2994 {
2995 *buf = '\0';
2996 break;
2997 }
2998 buf = xrealloc (buf, buf_size <<= 1);
2999 }
3000 o = variable_buffer_output (o, buf, strlen (buf));
3001 free (buf);
3002 return o;
3003}
3004#endif
3005
3006#ifdef CONFIG_WITH_FILE_SIZE
3007/* Prints the size of the specified file. Only one file is
3008 permitted, notthing is stripped. -1 is returned if stat
3009 fails. */
3010static char *
3011func_file_size (char *o, char **argv, const char *funcname UNUSED)
3012{
3013 struct stat st;
3014 if (stat (argv[0], &st))
3015 return variable_buffer_output (o, "-1", 2);
3016 return math_int_to_variable_buffer (o, st.st_size);
3017}
3018#endif
3019
3020#ifdef CONFIG_WITH_WHICH
3021/* Checks if the specified file exists an is executable.
3022 On systems employing executable extensions, the name may
3023 be modified to include the extension. */
3024static int func_which_test_x (char *file)
3025{
3026 struct stat st;
3027# if defined(WINDOWS32) || defined(__OS2__)
3028 char *ext;
3029 char *slash;
3030
3031 /* fix slashes first. */
3032 slash = file;
3033 while ((slash = strchr (slash, '\\')) != NULL)
3034 *slash++ = '/';
3035
3036 /* straight */
3037 if (stat (file, &st) == 0
3038 && S_ISREG (st.st_mode))
3039 return 1;
3040
3041 /* don't try add an extension if there already is one */
3042 ext = strchr (file, '\0');
3043 if (ext - file >= 4
3044 && ( !stricmp (ext - 4, ".exe")
3045 || !stricmp (ext - 4, ".cmd")
3046 || !stricmp (ext - 4, ".bat")
3047 || !stricmp (ext - 4, ".com")))
3048 return 0;
3049
3050 /* try the extensions. */
3051 strcpy (ext, ".exe");
3052 if (stat (file, &st) == 0
3053 && S_ISREG (st.st_mode))
3054 return 1;
3055
3056 strcpy (ext, ".cmd");
3057 if (stat (file, &st) == 0
3058 && S_ISREG (st.st_mode))
3059 return 1;
3060
3061 strcpy (ext, ".bat");
3062 if (stat (file, &st) == 0
3063 && S_ISREG (st.st_mode))
3064 return 1;
3065
3066 strcpy (ext, ".com");
3067 if (stat (file, &st) == 0
3068 && S_ISREG (st.st_mode))
3069 return 1;
3070
3071 return 0;
3072
3073# else
3074
3075 return access (file, X_OK) == 0
3076 && stat (file, &st) == 0
3077 && S_ISREG (st.st_mode);
3078# endif
3079}
3080
3081/* Searches for the specified programs in the PATH and print
3082 their full location if found. Prints nothing if not found. */
3083static char *
3084func_which (char *o, char **argv, const char *funcname UNUSED)
3085{
3086 const char *path;
3087 struct variable *path_var;
3088 unsigned i;
3089 int first = 1;
3090 PATH_VAR (buf);
3091
3092 path_var = lookup_variable ("PATH", 4);
3093 if (path_var)
3094 path = path_var->value;
3095 else
3096 path = ".";
3097
3098 /* iterate input */
3099 for (i = 0; argv[i]; i++)
3100 {
3101 unsigned int len;
3102 const char *iterator = argv[i];
3103 char *cur;
3104
3105 while ((cur = find_next_token (&iterator, &len)))
3106 {
3107 /* if there is a separator, don't walk the path. */
3108 if (memchr (cur, '/', len)
3109#ifdef HAVE_DOS_PATHS
3110 || memchr (cur, '\\', len)
3111 || memchr (cur, ':', len)
3112#endif
3113 )
3114 {
3115 if (len + 1 + 4 < GET_PATH_MAX) /* +4 for .exe */
3116 {
3117 memcpy (buf, cur, len);
3118 buf[len] = '\0';
3119 if (func_which_test_x (buf))
3120 o = variable_buffer_output (o, buf, strlen (buf));
3121 }
3122 }
3123 else
3124 {
3125 const char *comp = path;
3126 for (;;)
3127 {
3128 const char *src = comp;
3129 const char *end = strchr (comp, PATH_SEPARATOR_CHAR);
3130 size_t comp_len = end ? (size_t)(end - comp) : strlen (comp);
3131 if (!comp_len)
3132 {
3133 comp_len = 1;
3134 src = ".";
3135 }
3136 if (len + comp_len + 2 + 4 < GET_PATH_MAX) /* +4 for .exe */
3137 {
3138 memcpy (buf, comp, comp_len);
3139 buf [comp_len] = '/';
3140 memcpy (&buf[comp_len + 1], cur, len);
3141 buf[comp_len + 1 + len] = '\0';
3142
3143 if (func_which_test_x (buf))
3144 {
3145 if (!first)
3146 o = variable_buffer_output (o, " ", 1);
3147 o = variable_buffer_output (o, buf, strlen (buf));
3148 first = 0;
3149 break;
3150 }
3151 }
3152
3153 /* next */
3154 if (!end)
3155 break;
3156 comp = end + 1;
3157 }
3158 }
3159 }
3160 }
3161
3162 return variable_buffer_output (o, "", 0);
3163}
3164#endif /* CONFIG_WITH_WHICH */
3165
3166#ifdef CONFIG_WITH_IF_CONDITIONALS
3167
3168/* Evaluates the expression given in the argument using the
3169 same evaluator as for the new 'if' statements, except now
3170 we don't force the result into a boolean like for 'if' and
3171 '$(if-expr ,,)'. */
3172static char *
3173func_expr (char *o, char **argv, const char *funcname UNUSED)
3174{
3175 o = expr_eval_to_string (o, argv[0]);
3176 return o;
3177}
3178
3179/* Same as '$(if ,,)' except the first argument is evaluated
3180 using the same evaluator as for the new 'if' statements. */
3181static char *
3182func_if_expr (char *o, char **argv, const char *funcname UNUSED)
3183{
3184 int rc;
3185 char *to_expand;
3186
3187 /* Evaluate the condition in argv[0] and expand the 2nd or
3188 3rd argument according to the result. */
3189 rc = expr_eval_if_conditionals (argv[0], NULL);
3190 to_expand = rc == 0 ? argv[1] : argv[2];
3191 if (*to_expand)
3192 {
3193 char *expansion = expand_argument (to_expand, NULL);
3194
3195 o = variable_buffer_output (o, expansion, strlen (expansion));
3196
3197 free (expansion);
3198 }
3199
3200 return o;
3201}
3202
3203#endif /* CONFIG_WITH_IF_CONDITIONALS */
3204
3205#ifdef CONFIG_WITH_STACK
3206
3207/* Push an item (string without spaces). */
3208static char *
3209func_stack_push (char *o, char **argv, const char *funcname UNUSED)
3210{
3211 do_variable_definition(NILF, argv[0], argv[1], o_file, f_append, 0 /* !target_var */);
3212 return o;
3213}
3214
3215/* Pops an item off the stack / get the top stack element.
3216 (This is what's tricky to do in pure GNU make syntax.) */
3217static char *
3218func_stack_pop_top (char *o, char **argv, const char *funcname)
3219{
3220 struct variable *stack_var;
3221 const char *stack = argv[0];
3222
3223 stack_var = lookup_variable (stack, strlen (stack) );
3224 if (stack_var)
3225 {
3226 unsigned int len;
3227 const char *iterator = stack_var->value;
3228 char *lastitem = NULL;
3229 char *cur;
3230
3231 while ((cur = find_next_token (&iterator, &len)))
3232 lastitem = cur;
3233
3234 if (lastitem != NULL)
3235 {
3236 if (strcmp (funcname, "stack-popv") != 0)
3237 o = variable_buffer_output (o, lastitem, len);
3238 if (strcmp (funcname, "stack-top") != 0)
3239 {
3240 *lastitem = '\0';
3241 while (lastitem > stack_var->value && isspace (lastitem[-1]))
3242 *--lastitem = '\0';
3243#ifdef CONFIG_WITH_VALUE_LENGTH
3244 stack_var->value_length = lastitem - stack_var->value;
3245#endif
3246 }
3247 }
3248 }
3249 return o;
3250}
3251#endif /* CONFIG_WITH_STACK */
3252
3253#if defined (CONFIG_WITH_MATH) || defined (CONFIG_WITH_NANOTS) || defined (CONFIG_WITH_FILE_SIZE)
3254/* outputs the number (as a string) into the variable buffer. */
3255static char *
3256math_int_to_variable_buffer (char *o, math_int num)
3257{
3258 static const char xdigits[17] = "0123456789abcdef";
3259 int negative;
3260 char strbuf[24]; /* 16 hex + 2 prefix + sign + term => 20
3261 or 20 dec + sign + term => 22 */
3262 char *str = &strbuf[sizeof (strbuf) - 1];
3263
3264 negative = num < 0;
3265 if (negative)
3266 num = -num;
3267
3268 *str = '\0';
3269
3270 do
3271 {
3272#ifdef HEX_MATH_NUMBERS
3273 *--str = xdigits[num & 0xf];
3274 num >>= 4;
3275#else
3276 *--str = xdigits[num % 10];
3277 num /= 10;
3278#endif
3279 }
3280 while (num);
3281
3282#ifdef HEX_MATH_NUMBERS
3283 *--str = 'x';
3284 *--str = '0';
3285#endif
3286
3287 if (negative)
3288 *--str = '-';
3289
3290 return variable_buffer_output (o, str, &strbuf[sizeof (strbuf) - 1] - str);
3291}
3292#endif /* CONFIG_WITH_MATH || CONFIG_WITH_NANOTS */
3293
3294#ifdef CONFIG_WITH_MATH
3295
3296/* Converts a string to an integer, causes an error if the format is invalid. */
3297static math_int
3298math_int_from_string (const char *str)
3299{
3300 const char *start;
3301 unsigned base = 0;
3302 int negative = 0;
3303 math_int num = 0;
3304
3305 /* strip spaces */
3306 while (isspace (*str))
3307 str++;
3308 if (!*str)
3309 {
3310 error (NILF, _("bad number: empty\n"));
3311 return 0;
3312 }
3313 start = str;
3314
3315 /* check for +/- */
3316 while (*str == '+' || *str == '-' || isspace (*str))
3317 if (*str++ == '-')
3318 negative = !negative;
3319
3320 /* check for prefix - we do not accept octal numbers, sorry. */
3321 if (*str == '0' && (str[1] == 'x' || str[1] == 'X'))
3322 {
3323 base = 16;
3324 str += 2;
3325 }
3326 else
3327 {
3328 /* look for a hex digit, if not found treat it as decimal */
3329 const char *p2 = str;
3330 for ( ; *p2; p2++)
3331 if (isxdigit (*p2) && !isdigit (*p2) && isascii (*p2) )
3332 {
3333 base = 16;
3334 break;
3335 }
3336 if (base == 0)
3337 base = 10;
3338 }
3339
3340 /* must have at least one digit! */
3341 if ( !isascii (*str)
3342 || !(base == 16 ? isxdigit (*str) : isdigit (*str)) )
3343 {
3344 error (NILF, _("bad number: '%s'\n"), start);
3345 return 0;
3346 }
3347
3348 /* convert it! */
3349 while (*str && !isspace (*str))
3350 {
3351 int ch = *str++;
3352 if (ch >= '0' && ch <= '9')
3353 ch -= '0';
3354 else if (base == 16 && ch >= 'a' && ch <= 'f')
3355 ch -= 'a' - 10;
3356 else if (base == 16 && ch >= 'A' && ch <= 'F')
3357 ch -= 'A' - 10;
3358 else
3359 {
3360 error (NILF, _("bad number: '%s' (base=%d, pos=%d)\n"), start, base, str - start);
3361 return 0;
3362 }
3363 num *= base;
3364 num += ch;
3365 }
3366
3367 /* check trailing spaces. */
3368 while (isspace (*str))
3369 str++;
3370 if (*str)
3371 {
3372 error (NILF, _("bad number: '%s'\n"), start);
3373 return 0;
3374 }
3375
3376 return negative ? -num : num;
3377}
3378
3379/* Add two or more integer numbers. */
3380static char *
3381func_int_add (char *o, char **argv, const char *funcname UNUSED)
3382{
3383 math_int num;
3384 int i;
3385
3386 num = math_int_from_string (argv[0]);
3387 for (i = 1; argv[i]; i++)
3388 num += math_int_from_string (argv[i]);
3389
3390 return math_int_to_variable_buffer (o, num);
3391}
3392
3393/* Subtract two or more integer numbers. */
3394static char *
3395func_int_sub (char *o, char **argv, const char *funcname UNUSED)
3396{
3397 math_int num;
3398 int i;
3399
3400 num = math_int_from_string (argv[0]);
3401 for (i = 1; argv[i]; i++)
3402 num -= math_int_from_string (argv[i]);
3403
3404 return math_int_to_variable_buffer (o, num);
3405}
3406
3407/* Multiply two or more integer numbers. */
3408static char *
3409func_int_mul (char *o, char **argv, const char *funcname UNUSED)
3410{
3411 math_int num;
3412 int i;
3413
3414 num = math_int_from_string (argv[0]);
3415 for (i = 1; argv[i]; i++)
3416 num *= math_int_from_string (argv[i]);
3417
3418 return math_int_to_variable_buffer (o, num);
3419}
3420
3421/* Divide an integer number by one or more divisors. */
3422static char *
3423func_int_div (char *o, char **argv, const char *funcname UNUSED)
3424{
3425 math_int num;
3426 math_int divisor;
3427 int i;
3428
3429 num = math_int_from_string (argv[0]);
3430 for (i = 1; argv[i]; i++)
3431 {
3432 divisor = math_int_from_string (argv[i]);
3433 if (!divisor)
3434 {
3435 error (NILF, _("divide by zero ('%s')\n"), argv[i]);
3436 return math_int_to_variable_buffer (o, 0);
3437 }
3438 num /= divisor;
3439 }
3440
3441 return math_int_to_variable_buffer (o, num);
3442}
3443
3444
3445/* Divide and return the remainder. */
3446static char *
3447func_int_mod (char *o, char **argv, const char *funcname UNUSED)
3448{
3449 math_int num;
3450 math_int divisor;
3451
3452 num = math_int_from_string (argv[0]);
3453 divisor = math_int_from_string (argv[1]);
3454 if (!divisor)
3455 {
3456 error (NILF, _("divide by zero ('%s')\n"), argv[1]);
3457 return math_int_to_variable_buffer (o, 0);
3458 }
3459 num %= divisor;
3460
3461 return math_int_to_variable_buffer (o, num);
3462}
3463
3464/* 2-complement. */
3465static char *
3466func_int_not (char *o, char **argv, const char *funcname UNUSED)
3467{
3468 math_int num;
3469
3470 num = math_int_from_string (argv[0]);
3471 num = ~num;
3472
3473 return math_int_to_variable_buffer (o, num);
3474}
3475
3476/* Bitwise AND (two or more numbers). */
3477static char *
3478func_int_and (char *o, char **argv, const char *funcname UNUSED)
3479{
3480 math_int num;
3481 int i;
3482
3483 num = math_int_from_string (argv[0]);
3484 for (i = 1; argv[i]; i++)
3485 num &= math_int_from_string (argv[i]);
3486
3487 return math_int_to_variable_buffer (o, num);
3488}
3489
3490/* Bitwise OR (two or more numbers). */
3491static char *
3492func_int_or (char *o, char **argv, const char *funcname UNUSED)
3493{
3494 math_int num;
3495 int i;
3496
3497 num = math_int_from_string (argv[0]);
3498 for (i = 1; argv[i]; i++)
3499 num |= math_int_from_string (argv[i]);
3500
3501 return math_int_to_variable_buffer (o, num);
3502}
3503
3504/* Bitwise XOR (two or more numbers). */
3505static char *
3506func_int_xor (char *o, char **argv, const char *funcname UNUSED)
3507{
3508 math_int num;
3509 int i;
3510
3511 num = math_int_from_string (argv[0]);
3512 for (i = 1; argv[i]; i++)
3513 num ^= math_int_from_string (argv[i]);
3514
3515 return math_int_to_variable_buffer (o, num);
3516}
3517
3518/* Compare two integer numbers. Returns make boolean (true="1"; false=""). */
3519static char *
3520func_int_cmp (char *o, char **argv, const char *funcname)
3521{
3522 math_int num1;
3523 math_int num2;
3524 int rc;
3525
3526 num1 = math_int_from_string (argv[0]);
3527 num2 = math_int_from_string (argv[1]);
3528
3529 funcname += sizeof ("int-") - 1;
3530 if (!strcmp (funcname, "eq"))
3531 rc = num1 == num2;
3532 else if (!strcmp (funcname, "ne"))
3533 rc = num1 != num2;
3534 else if (!strcmp (funcname, "gt"))
3535 rc = num1 > num2;
3536 else if (!strcmp (funcname, "ge"))
3537 rc = num1 >= num2;
3538 else if (!strcmp (funcname, "lt"))
3539 rc = num1 < num2;
3540 else /*if (!strcmp (funcname, "le"))*/
3541 rc = num1 <= num2;
3542
3543 return variable_buffer_output (o, rc ? "1" : "", rc);
3544}
3545
3546#endif /* CONFIG_WITH_MATH */
3547
3548#ifdef CONFIG_WITH_NANOTS
3549/* Returns the current timestamp as nano seconds. The time
3550 source is a high res monotone one if the platform provides
3551 this (and we know about it).
3552
3553 Tip. Use this with int-sub to profile makefile reading
3554 and similar. */
3555static char *
3556func_nanots (char *o, char **argv, const char *funcname)
3557{
3558 math_int ts;
3559
3560#if defined (WINDOWS32)
3561 static int s_state = -1;
3562 static LARGE_INTEGER s_freq;
3563
3564 if (s_state == -1)
3565 s_state = QueryPerformanceFrequency (&s_freq);
3566 if (s_state)
3567 {
3568 LARGE_INTEGER pc;
3569 if (!QueryPerformanceCounter (&pc))
3570 {
3571 s_state = 0;
3572 return func_nanots (o, argv, funcname);
3573 }
3574 ts = (math_int)((long double)pc.QuadPart / (long double)s_freq.QuadPart * 1000000000);
3575 }
3576 else
3577 {
3578 /* fall back to low resolution system time. */
3579 LARGE_INTEGER bigint;
3580 FILETIME ft = {0,0};
3581 GetSystemTimeAsFileTime (&ft);
3582 bigint.u.LowPart = ft.dwLowDateTime;
3583 bigint.u.HighPart = ft.dwLowDateTime;
3584 ts = bigint.QuadPart * 100;
3585 }
3586
3587/* FIXME: Linux and others have the realtime clock_* api, detect and use it. */
3588
3589#elif HAVE_GETTIMEOFDAY
3590 struct timeval tv;
3591 if (!gettimeofday (&tv, NULL))
3592 ts = (math_int)tv.tv_sec * 1000000000
3593 + tv.tv_usec * 1000;
3594 else
3595 {
3596 error (NILF, _("$(nanots): gettimeofday failed"));
3597 ts = 0;
3598 }
3599
3600#else
3601# error "PORTME"
3602#endif
3603
3604 return math_int_to_variable_buffer (o, ts);
3605}
3606#endif
3607
3608#ifdef CONFIG_WITH_OS2_LIBPATH
3609/* Sets or gets the OS/2 libpath variables.
3610
3611 The first argument indicates which variable - BEGINLIBPATH,
3612 ENDLIBPATH, LIBPATHSTRICT or LIBPATH.
3613
3614 The second indicates whether this is a get (not present) or
3615 set (present) operation. When present it is the new value for
3616 the variable. */
3617static char *
3618func_os2_libpath (char *o, char **argv, const char *funcname UNUSED)
3619{
3620 char buf[4096];
3621 ULONG fVar;
3622 APIRET rc;
3623
3624 /* translate variable name (first arg) */
3625 if (!strcmp (argv[0], "BEGINLIBPATH"))
3626 fVar = BEGIN_LIBPATH;
3627 else if (!strcmp (argv[0], "ENDLIBPATH"))
3628 fVar = END_LIBPATH;
3629 else if (!strcmp (argv[0], "LIBPATHSTRICT"))
3630 fVar = LIBPATHSTRICT;
3631 else if (!strcmp (argv[0], "LIBPATH"))
3632 fVar = 0;
3633 else
3634 {
3635 error (NILF, _("$(libpath): unknown variable `%s'"), argv[0]);
3636 return variable_buffer_output (o, "", 0);
3637 }
3638
3639 if (!argv[1])
3640 {
3641 /* get the variable value. */
3642 if (fVar != 0)
3643 {
3644 buf[0] = buf[1] = buf[2] = buf[3] = '\0';
3645 rc = DosQueryExtLIBPATH (buf, fVar);
3646 }
3647 else
3648 rc = DosQueryHeaderInfo (NULLHANDLE, 0, buf, sizeof(buf), QHINF_LIBPATH);
3649 if (rc != NO_ERROR)
3650 {
3651 error (NILF, _("$(libpath): failed to query `%s', rc=%d"), argv[0], rc);
3652 return variable_buffer_output (o, "", 0);
3653 }
3654 o = variable_buffer_output (o, buf, strlen (buf));
3655 }
3656 else
3657 {
3658 /* set the variable value. */
3659 size_t len;
3660 size_t len_max = sizeof (buf) < 2048 ? sizeof (buf) : 2048;
3661 const char *val;
3662 const char *end;
3663
3664 if (fVar == 0)
3665 {
3666 error (NILF, _("$(libpath): LIBPATH is read-only"));
3667 return variable_buffer_output (o, "", 0);
3668 }
3669
3670 /* strip leading and trailing spaces and check for max length. */
3671 val = argv[1];
3672 while (isspace (*val))
3673 val++;
3674 end = strchr (val, '\0');
3675 while (end > val && isspace (end[-1]))
3676 end--;
3677
3678 len = end - val;
3679 if (len >= len_max)
3680 {
3681 error (NILF, _("$(libpath): The new `%s' value is too long (%d bytes, max %d)"),
3682 argv[0], len, len_max);
3683 return variable_buffer_output (o, "", 0);
3684 }
3685
3686 /* make a stripped copy in low memory and try set it. */
3687 memcpy (buf, val, len);
3688 buf[len] = '\0';
3689 rc = DosSetExtLIBPATH (buf, fVar);
3690 if (rc != NO_ERROR)
3691 {
3692 error (NILF, _("$(libpath): failed to set `%s' to `%s', rc=%d"), argv[0], buf, rc);
3693 return variable_buffer_output (o, "", 0);
3694 }
3695
3696 o = variable_buffer_output (o, "", 0);
3697 }
3698 return o;
3699}
3700#endif /* CONFIG_WITH_OS2_LIBPATH */
3701
3702#ifdef CONFIG_WITH_MAKE_STATS
3703/* Retrieve make statistics. */
3704static char *
3705func_make_stats (char *o, char **argv, const char *funcname UNUSED)
3706{
3707 char buf[512];
3708 int len;
3709
3710 if (!argv[0] || (!argv[0][0] && !argv[1]))
3711 {
3712 len = sprintf (buf, "alloc-cur: %5ld %6luKB (/%3luMB) hash: %5lu %2lu%%",
3713 make_stats_allocations,
3714 make_stats_allocated / 1024,
3715 make_stats_allocated_sum / (1024*1024),
3716 make_stats_ht_lookups,
3717 (make_stats_ht_collisions * 100) / make_stats_ht_lookups);
3718 o = variable_buffer_output (o, buf, len);
3719 }
3720 else
3721 {
3722 /* selective */
3723 int i;
3724 for (i = 0; argv[i]; i++)
3725 {
3726 unsigned long val;
3727 if (i != 0)
3728 o = variable_buffer_output (o, " ", 1);
3729 if (!strcmp(argv[i], "allocations"))
3730 val = make_stats_allocations;
3731 else if (!strcmp(argv[i], "allocated"))
3732 val = make_stats_allocated;
3733 else if (!strcmp(argv[i], "allocated_sum"))
3734 val = make_stats_allocated_sum;
3735 else if (!strcmp(argv[i], "ht_lookups"))
3736 val = make_stats_ht_lookups;
3737 else if (!strcmp(argv[i], "ht_collisions"))
3738 val = make_stats_ht_collisions;
3739 else if (!strcmp(argv[i], "ht_collisions_pct"))
3740 val = (make_stats_ht_collisions * 100) / make_stats_ht_lookups;
3741 else
3742 {
3743 o = variable_buffer_output (o, argv[i], strlen (argv[i]));
3744 continue;
3745 }
3746
3747 len = sprintf (buf, "%ld", val);
3748 o = variable_buffer_output (o, buf, len);
3749 }
3750 }
3751 return o;
3752}
3753#endif /* CONFIG_WITH_MAKE_STATS */
3754
3755#ifdef CONFIG_WITH_COMMANDS_FUNC
3756/* Gets all the commands for a target, separated by newlines.
3757
3758 This is useful when creating and checking target dependencies since
3759 it reduces the amount of work and the memory consuption. A new prefix
3760 character '%' has been introduced for skipping certain lines, like
3761 for instance the one calling this function and pushing to a dep file.
3762 Blank lines are also skipped.
3763
3764 The commands function takes exactly one argument, which is the name of
3765 the target which commands should be returned.
3766
3767 The commands-sc is identical to commands except that it uses a ';' to
3768 separate the commands.
3769
3770 The commands-usr is similar to commands except that it takes a 2nd
3771 argument that is used to separate the commands. */
3772char *
3773func_commands (char *o, char **argv, const char *funcname)
3774{
3775 struct file *file;
3776 static int recursive = 0;
3777
3778 if (recursive)
3779 {
3780 error (reading_file, _("$(%s ) was invoked recursivly"), funcname);
3781 return variable_buffer_output (o, "recursive", sizeof ("recursive") - 1);
3782 }
3783 if (*argv[0] == '\0')
3784 {
3785 error (reading_file, _("$(%s ) was invoked with an empty target name"), funcname);
3786 return o;
3787 }
3788 recursive = 1;
3789
3790 file = lookup_file (argv[0]);
3791 if (file && file->cmds)
3792 {
3793 unsigned int i;
3794 int cmd_sep_len;
3795 struct commands *cmds = file->cmds;
3796 const char *cmd_sep;
3797
3798 if (!strcmp (funcname, "commands"))
3799 {
3800 cmd_sep = "\n";
3801 cmd_sep_len = 1;
3802 }
3803 else if (!strcmp (funcname, "commands-sc"))
3804 {
3805 cmd_sep = ";";
3806 cmd_sep_len = 1;
3807 }
3808 else /*if (!strcmp (funcname, "commands-usr"))*/
3809 {
3810 cmd_sep = argv[1];
3811 cmd_sep_len = strlen (cmd_sep);
3812 }
3813
3814 initialize_file_variables (file, 1 /* reading - FIXME: we don't know? */);
3815 set_file_variables (file);
3816 chop_commands (cmds);
3817
3818 for (i = 0; i < cmds->ncommand_lines; i++)
3819 {
3820 char *p;
3821 char *in, *out, *ref;
3822
3823 /* Skip it if it has a '%' prefix or is blank. */
3824 if (cmds->lines_flags[i] & COMMAND_GETTER_SKIP_IT)
3825 continue;
3826 p = cmds->command_lines[i];
3827 while (isblank ((unsigned char)*p))
3828 p++;
3829 if (*p == '\0')
3830 continue;
3831
3832 /* --- copied from new_job() in job.c --- */
3833
3834 /* Collapse backslash-newline combinations that are inside variable
3835 or function references. These are left alone by the parser so
3836 that they will appear in the echoing of commands (where they look
3837 nice); and collapsed by construct_command_argv when it tokenizes.
3838 But letting them survive inside function invocations loses because
3839 we don't want the functions to see them as part of the text. */
3840
3841 /* IN points to where in the line we are scanning.
3842 OUT points to where in the line we are writing.
3843 When we collapse a backslash-newline combination,
3844 IN gets ahead of OUT. */
3845
3846 in = out = p;
3847 while ((ref = strchr (in, '$')) != 0)
3848 {
3849 ++ref; /* Move past the $. */
3850
3851 if (out != in)
3852 /* Copy the text between the end of the last chunk
3853 we processed (where IN points) and the new chunk
3854 we are about to process (where REF points). */
3855 memmove (out, in, ref - in);
3856
3857 /* Move both pointers past the boring stuff. */
3858 out += ref - in;
3859 in = ref;
3860
3861 if (*ref == '(' || *ref == '{')
3862 {
3863 char openparen = *ref;
3864 char closeparen = openparen == '(' ? ')' : '}';
3865 int count;
3866 char *p;
3867
3868 *out++ = *in++; /* Copy OPENPAREN. */
3869 /* IN now points past the opening paren or brace.
3870 Count parens or braces until it is matched. */
3871 count = 0;
3872 while (*in != '\0')
3873 {
3874 if (*in == closeparen && --count < 0)
3875 break;
3876 else if (*in == '\\' && in[1] == '\n')
3877 {
3878 /* We have found a backslash-newline inside a
3879 variable or function reference. Eat it and
3880 any following whitespace. */
3881
3882 int quoted = 0;
3883 for (p = in - 1; p > ref && *p == '\\'; --p)
3884 quoted = !quoted;
3885
3886 if (quoted)
3887 /* There were two or more backslashes, so this is
3888 not really a continuation line. We don't collapse
3889 the quoting backslashes here as is done in
3890 collapse_continuations, because the line will
3891 be collapsed again after expansion. */
3892 *out++ = *in++;
3893 else
3894 {
3895 /* Skip the backslash, newline and
3896 any following whitespace. */
3897 in = next_token (in + 2);
3898
3899 /* Discard any preceding whitespace that has
3900 already been written to the output. */
3901 while (out > ref
3902 && isblank ((unsigned char)out[-1]))
3903 --out;
3904
3905 /* Replace it all with a single space. */
3906 *out++ = ' ';
3907 }
3908 }
3909 else
3910 {
3911 if (*in == openparen)
3912 ++count;
3913
3914 *out++ = *in++;
3915 }
3916 }
3917 }
3918 /* Some of these can be amended ($< perhaps), but we're likely to be called while the
3919 dep expansion happens, so it would have to be on a hackish basis. sad... */
3920 else if (*ref == '<' || *ref == '*' || *ref == '%' || *ref == '^' || *ref == '+')
3921 error (reading_file, _("$(%s ) does not work reliably with $%c in all cases"), funcname, *ref);
3922 }
3923
3924 /* There are no more references in this line to worry about.
3925 Copy the remaining uninteresting text to the output. */
3926 if (out != in)
3927 strcpy (out, in);
3928
3929 /* --- copied from new_job() in job.c --- */
3930
3931 /* Finally, expand the line. */
3932 if (i)
3933 o = variable_buffer_output (o, cmd_sep, cmd_sep_len);
3934 o = variable_expand_for_file_2 (o, cmds->command_lines[i], file);
3935
3936 /* Skip it if it has a '%' prefix or is blank. */
3937 p = o;
3938 while (isblank ((unsigned char)*o)
3939 || *o == '@'
3940 || *o == '-'
3941 || *o == '+')
3942 o++;
3943 if (*o != '\0' && *o != '%')
3944 o = strchr (o, '\0');
3945 else if (i)
3946 o = p - cmd_sep_len;
3947 else
3948 o = p;
3949 } /* for each command line */
3950 }
3951 /* else FIXME: bitch about it? */
3952
3953 recursive = 0;
3954 return o;
3955}
3956#endif /* CONFIG_WITH_COMMANDS_FUNC */
3957
3958#ifdef KMK
3959/* Useful when debugging kmk and/or makefiles. */
3960char *
3961func_breakpoint (char *o, char **argv, const char *funcname)
3962{
3963#ifdef _MSC_VER
3964 __debugbreak();
3965#elif defined(__i386__) || defined(__x86__) || defined(__X86__) || defined(_M_IX86) || defined(__i386) \
3966 || defined(__amd64__) || defined(__x86_64__) || defined(__AMD64__) || defined(_M_X64) || defined(__amd64)
3967 __asm__ __volatile__ ("int3\n\t");
3968#else
3969 char *p = (char *)0;
3970 *p = '\0';
3971#endif
3972 return o;
3973}
3974#endif /* KMK */
3975
3976
3977/* Lookup table for builtin functions.
3978
3979 This doesn't have to be sorted; we use a straight lookup. We might gain
3980 some efficiency by moving most often used functions to the start of the
3981 table.
3982
3983 If MAXIMUM_ARGS is 0, that means there is no maximum and all
3984 comma-separated values are treated as arguments.
3985
3986 EXPAND_ARGS means that all arguments should be expanded before invocation.
3987 Functions that do namespace tricks (foreach) don't automatically expand. */
3988
3989static char *func_call (char *o, char **argv, const char *funcname);
3990
3991
3992static struct function_table_entry function_table_init[] =
3993{
3994 /* Name/size */ /* MIN MAX EXP? Function */
3995 { STRING_SIZE_TUPLE("abspath"), 0, 1, 1, func_abspath},
3996 { STRING_SIZE_TUPLE("addprefix"), 2, 2, 1, func_addsuffix_addprefix},
3997 { STRING_SIZE_TUPLE("addsuffix"), 2, 2, 1, func_addsuffix_addprefix},
3998 { STRING_SIZE_TUPLE("basename"), 0, 1, 1, func_basename_dir},
3999 { STRING_SIZE_TUPLE("dir"), 0, 1, 1, func_basename_dir},
4000 { STRING_SIZE_TUPLE("notdir"), 0, 1, 1, func_notdir_suffix},
4001 { STRING_SIZE_TUPLE("subst"), 3, 3, 1, func_subst},
4002 { STRING_SIZE_TUPLE("suffix"), 0, 1, 1, func_notdir_suffix},
4003 { STRING_SIZE_TUPLE("filter"), 2, 2, 1, func_filter_filterout},
4004 { STRING_SIZE_TUPLE("filter-out"), 2, 2, 1, func_filter_filterout},
4005 { STRING_SIZE_TUPLE("findstring"), 2, 2, 1, func_findstring},
4006 { STRING_SIZE_TUPLE("firstword"), 0, 1, 1, func_firstword},
4007 { STRING_SIZE_TUPLE("flavor"), 0, 1, 1, func_flavor},
4008 { STRING_SIZE_TUPLE("join"), 2, 2, 1, func_join},
4009 { STRING_SIZE_TUPLE("lastword"), 0, 1, 1, func_lastword},
4010 { STRING_SIZE_TUPLE("patsubst"), 3, 3, 1, func_patsubst},
4011 { STRING_SIZE_TUPLE("realpath"), 0, 1, 1, func_realpath},
4012#ifdef CONFIG_WITH_RSORT
4013 { STRING_SIZE_TUPLE("rsort"), 0, 1, 1, func_sort},
4014#endif
4015 { STRING_SIZE_TUPLE("shell"), 0, 1, 1, func_shell},
4016 { STRING_SIZE_TUPLE("sort"), 0, 1, 1, func_sort},
4017 { STRING_SIZE_TUPLE("strip"), 0, 1, 1, func_strip},
4018 { STRING_SIZE_TUPLE("wildcard"), 0, 1, 1, func_wildcard},
4019 { STRING_SIZE_TUPLE("word"), 2, 2, 1, func_word},
4020 { STRING_SIZE_TUPLE("wordlist"), 3, 3, 1, func_wordlist},
4021 { STRING_SIZE_TUPLE("words"), 0, 1, 1, func_words},
4022 { STRING_SIZE_TUPLE("origin"), 0, 1, 1, func_origin},
4023 { STRING_SIZE_TUPLE("foreach"), 3, 3, 0, func_foreach},
4024 { STRING_SIZE_TUPLE("call"), 1, 0, 1, func_call},
4025 { STRING_SIZE_TUPLE("info"), 0, 1, 1, func_error},
4026 { STRING_SIZE_TUPLE("error"), 0, 1, 1, func_error},
4027 { STRING_SIZE_TUPLE("warning"), 0, 1, 1, func_error},
4028 { STRING_SIZE_TUPLE("if"), 2, 3, 0, func_if},
4029 { STRING_SIZE_TUPLE("or"), 1, 0, 0, func_or},
4030 { STRING_SIZE_TUPLE("and"), 1, 0, 0, func_and},
4031 { STRING_SIZE_TUPLE("value"), 0, 1, 1, func_value},
4032 { STRING_SIZE_TUPLE("eval"), 0, 1, 1, func_eval},
4033#ifdef CONFIG_WITH_EVALPLUS
4034 { STRING_SIZE_TUPLE("evalctx"), 0, 1, 1, func_evalctx},
4035 { STRING_SIZE_TUPLE("evalval"), 1, 1, 1, func_evalval},
4036 { STRING_SIZE_TUPLE("evalvalctx"), 1, 1, 1, func_evalval},
4037 { STRING_SIZE_TUPLE("evalcall"), 1, 0, 1, func_call},
4038 { STRING_SIZE_TUPLE("evalcall2"), 1, 0, 1, func_call},
4039#endif
4040#ifdef EXPERIMENTAL
4041 { STRING_SIZE_TUPLE("eq"), 2, 2, 1, func_eq},
4042 { STRING_SIZE_TUPLE("not"), 0, 1, 1, func_not},
4043#endif
4044#ifdef CONFIG_WITH_DEFINED
4045 { STRING_SIZE_TUPLE("defined"), 1, 1, 1, func_defined},
4046#endif
4047#ifdef CONFIG_WITH_TOUPPER_TOLOWER
4048 { STRING_SIZE_TUPLE("toupper"), 0, 1, 1, func_toupper_tolower},
4049 { STRING_SIZE_TUPLE("tolower"), 0, 1, 1, func_toupper_tolower},
4050#endif
4051#ifdef CONFIG_WITH_ABSPATHEX
4052 { STRING_SIZE_TUPLE("abspathex"), 0, 2, 1, func_abspathex},
4053#endif
4054#ifdef CONFIG_WITH_XARGS
4055 { STRING_SIZE_TUPLE("xargs"), 2, 0, 1, func_xargs},
4056#endif
4057#if defined(CONFIG_WITH_VALUE_LENGTH) && defined(CONFIG_WITH_COMPARE)
4058 { STRING_SIZE_TUPLE("comp-vars"), 3, 3, 1, func_comp_vars},
4059 { STRING_SIZE_TUPLE("comp-cmds"), 3, 3, 1, func_comp_vars},
4060 { STRING_SIZE_TUPLE("comp-cmds-ex"), 3, 3, 1, func_comp_cmds_ex},
4061#endif
4062#ifdef CONFIG_WITH_DATE
4063 { STRING_SIZE_TUPLE("date"), 0, 1, 1, func_date},
4064 { STRING_SIZE_TUPLE("date-utc"), 0, 3, 1, func_date},
4065#endif
4066#ifdef CONFIG_WITH_FILE_SIZE
4067 { STRING_SIZE_TUPLE("file-size"), 1, 1, 1, func_file_size},
4068#endif
4069#ifdef CONFIG_WITH_WHICH
4070 { STRING_SIZE_TUPLE("which"), 0, 0, 1, func_which},
4071#endif
4072#ifdef CONFIG_WITH_IF_CONDITIONALS
4073 { STRING_SIZE_TUPLE("expr"), 1, 1, 0, func_expr},
4074 { STRING_SIZE_TUPLE("if-expr"), 2, 3, 0, func_if_expr},
4075#endif
4076#ifdef CONFIG_WITH_STACK
4077 { STRING_SIZE_TUPLE("stack-push"), 2, 2, 1, func_stack_push},
4078 { STRING_SIZE_TUPLE("stack-pop"), 1, 1, 1, func_stack_pop_top},
4079 { STRING_SIZE_TUPLE("stack-popv"), 1, 1, 1, func_stack_pop_top},
4080 { STRING_SIZE_TUPLE("stack-top"), 1, 1, 1, func_stack_pop_top},
4081#endif
4082#ifdef CONFIG_WITH_MATH
4083 { STRING_SIZE_TUPLE("int-add"), 2, 0, 1, func_int_add},
4084 { STRING_SIZE_TUPLE("int-sub"), 2, 0, 1, func_int_sub},
4085 { STRING_SIZE_TUPLE("int-mul"), 2, 0, 1, func_int_mul},
4086 { STRING_SIZE_TUPLE("int-div"), 2, 0, 1, func_int_div},
4087 { STRING_SIZE_TUPLE("int-mod"), 2, 2, 1, func_int_mod},
4088 { STRING_SIZE_TUPLE("int-not"), 1, 1, 1, func_int_not},
4089 { STRING_SIZE_TUPLE("int-and"), 2, 0, 1, func_int_and},
4090 { STRING_SIZE_TUPLE("int-or"), 2, 0, 1, func_int_or},
4091 { STRING_SIZE_TUPLE("int-xor"), 2, 0, 1, func_int_xor},
4092 { STRING_SIZE_TUPLE("int-eq"), 2, 2, 1, func_int_cmp},
4093 { STRING_SIZE_TUPLE("int-ne"), 2, 2, 1, func_int_cmp},
4094 { STRING_SIZE_TUPLE("int-gt"), 2, 2, 1, func_int_cmp},
4095 { STRING_SIZE_TUPLE("int-ge"), 2, 2, 1, func_int_cmp},
4096 { STRING_SIZE_TUPLE("int-lt"), 2, 2, 1, func_int_cmp},
4097 { STRING_SIZE_TUPLE("int-le"), 2, 2, 1, func_int_cmp},
4098#endif
4099#ifdef CONFIG_WITH_NANOTS
4100 { STRING_SIZE_TUPLE("nanots"), 0, 0, 0, func_nanots},
4101#endif
4102#ifdef CONFIG_WITH_OS2_LIBPATH
4103 { STRING_SIZE_TUPLE("libpath"), 1, 2, 1, func_os2_libpath},
4104#endif
4105#ifdef CONFIG_WITH_MAKE_STATS
4106 { STRING_SIZE_TUPLE("make-stats"), 0, 0, 0, func_make_stats},
4107#endif
4108#ifdef CONFIG_WITH_COMMANDS_FUNC
4109 { STRING_SIZE_TUPLE("commands"), 1, 1, 1, func_commands},
4110 { STRING_SIZE_TUPLE("commands-sc"), 1, 1, 1, func_commands},
4111 { STRING_SIZE_TUPLE("commands-usr"), 2, 2, 1, func_commands},
4112#endif
4113#ifdef KMK_HELPERS
4114 { STRING_SIZE_TUPLE("kb-src-tool"), 1, 1, 0, func_kbuild_source_tool},
4115 { STRING_SIZE_TUPLE("kb-obj-base"), 1, 1, 0, func_kbuild_object_base},
4116 { STRING_SIZE_TUPLE("kb-obj-suff"), 1, 1, 0, func_kbuild_object_suffix},
4117 { STRING_SIZE_TUPLE("kb-src-prop"), 3, 4, 0, func_kbuild_source_prop},
4118 { STRING_SIZE_TUPLE("kb-src-one"), 0, 1, 0, func_kbuild_source_one},
4119#endif
4120#ifdef KMK
4121 { STRING_SIZE_TUPLE("breakpoint"), 0, 0, 0, func_breakpoint},
4122#endif
4123};
4124
4125#define FUNCTION_TABLE_ENTRIES (sizeof (function_table_init) / sizeof (struct function_table_entry))
4126
4127
4128
4129/* These must come after the definition of function_table. */
4130
4131static char *
4132expand_builtin_function (char *o, int argc, char **argv,
4133 const struct function_table_entry *entry_p)
4134{
4135 if (argc < (int)entry_p->minimum_args)
4136 fatal (*expanding_var,
4137 _("insufficient number of arguments (%d) to function `%s'"),
4138 argc, entry_p->name);
4139
4140 /* I suppose technically some function could do something with no
4141 arguments, but so far none do, so just test it for all functions here
4142 rather than in each one. We can change it later if necessary. */
4143
4144 if (!argc)
4145 return o;
4146
4147 if (!entry_p->func_ptr)
4148 fatal (*expanding_var,
4149 _("unimplemented on this platform: function `%s'"), entry_p->name);
4150
4151 return entry_p->func_ptr (o, argv, entry_p->name);
4152}
4153
4154/* Check for a function invocation in *STRINGP. *STRINGP points at the
4155 opening ( or { and is not null-terminated. If a function invocation
4156 is found, expand it into the buffer at *OP, updating *OP, incrementing
4157 *STRINGP past the reference and returning nonzero. If not, return zero. */
4158
4159static int
4160handle_function2 (const struct function_table_entry *entry_p, char **op, const char **stringp) /* bird split it up. */
4161{
4162 char openparen = (*stringp)[0];
4163 char closeparen = openparen == '(' ? ')' : '}';
4164 const char *beg;
4165 const char *end;
4166 int count = 0;
4167 char *abeg = NULL;
4168 char **argv, **argvp;
4169 int nargs;
4170
4171 beg = *stringp + 1;
4172
4173 /* We found a builtin function. Find the beginning of its arguments (skip
4174 whitespace after the name). */
4175
4176 beg = next_token (beg + entry_p->len);
4177
4178 /* Find the end of the function invocation, counting nested use of
4179 whichever kind of parens we use. Since we're looking, count commas
4180 to get a rough estimate of how many arguments we might have. The
4181 count might be high, but it'll never be low. */
4182
4183 for (nargs=1, end=beg; *end != '\0'; ++end)
4184 if (*end == ',')
4185 ++nargs;
4186 else if (*end == openparen)
4187 ++count;
4188 else if (*end == closeparen && --count < 0)
4189 break;
4190
4191 if (count >= 0)
4192 fatal (*expanding_var,
4193 _("unterminated call to function `%s': missing `%c'"),
4194 entry_p->name, closeparen);
4195
4196 *stringp = end;
4197
4198 /* Get some memory to store the arg pointers. */
4199 argvp = argv = alloca (sizeof (char *) * (nargs + 2));
4200
4201 /* Chop the string into arguments, then a nul. As soon as we hit
4202 MAXIMUM_ARGS (if it's >0) assume the rest of the string is part of the
4203 last argument.
4204
4205 If we're expanding, store pointers to the expansion of each one. If
4206 not, make a duplicate of the string and point into that, nul-terminating
4207 each argument. */
4208
4209 if (entry_p->expand_args)
4210 {
4211 const char *p;
4212 for (p=beg, nargs=0; p <= end; ++argvp)
4213 {
4214 const char *next;
4215
4216 ++nargs;
4217
4218 if (nargs == entry_p->maximum_args
4219 || (! (next = find_next_argument (openparen, closeparen, p, end))))
4220 next = end;
4221
4222 *argvp = expand_argument (p, next);
4223 p = next + 1;
4224 }
4225 }
4226 else
4227 {
4228 int len = end - beg;
4229 char *p, *aend;
4230
4231 abeg = xmalloc (len+1);
4232 memcpy (abeg, beg, len);
4233 abeg[len] = '\0';
4234 aend = abeg + len;
4235
4236 for (p=abeg, nargs=0; p <= aend; ++argvp)
4237 {
4238 char *next;
4239
4240 ++nargs;
4241
4242 if (nargs == entry_p->maximum_args
4243 || (! (next = find_next_argument (openparen, closeparen, p, aend))))
4244 next = aend;
4245
4246 *argvp = p;
4247 *next = '\0';
4248 p = next + 1;
4249 }
4250 }
4251 *argvp = NULL;
4252
4253 /* Finally! Run the function... */
4254 *op = expand_builtin_function (*op, nargs, argv, entry_p);
4255
4256 /* Free memory. */
4257 if (entry_p->expand_args)
4258 for (argvp=argv; *argvp != 0; ++argvp)
4259 free (*argvp);
4260 if (abeg)
4261 free (abeg);
4262
4263 return 1;
4264}
4265
4266
4267int /* bird split it up */
4268#ifndef CONFIG_WITH_VALUE_LENGTH
4269handle_function (char **op, const char **stringp)
4270{
4271 const struct function_table_entry *entry_p = lookup_function (*stringp + 1);
4272 if (!entry_p)
4273 return 0;
4274 return handle_function2 (entry_p, op, stringp);
4275}
4276#else /* CONFIG_WITH_VALUE_LENGTH */
4277handle_function (char **op, const char **stringp, const char *eol)
4278{
4279 const char *fname = *stringp + 1;
4280 const struct function_table_entry *entry_p = lookup_function (fname, eol - fname);
4281 if (!entry_p)
4282 return 0;
4283 return handle_function2 (entry_p, op, stringp);
4284}
4285#endif /* CONFIG_WITH_VALUE_LENGTH */
4286
4287
4288
4289/* User-defined functions. Expand the first argument as either a builtin
4290 function or a make variable, in the context of the rest of the arguments
4291 assigned to $1, $2, ... $N. $0 is the name of the function. */
4292
4293static char *
4294func_call (char *o, char **argv, const char *funcname UNUSED)
4295{
4296 static int max_args = 0;
4297 char *fname;
4298 char *cp;
4299 char *body;
4300 int flen;
4301 int i;
4302 int saved_args;
4303 const struct function_table_entry *entry_p;
4304 struct variable *v;
4305#ifdef CONFIG_WITH_EVALPLUS
4306 char *buf;
4307 unsigned int len;
4308#endif
4309
4310 /* There is no way to define a variable with a space in the name, so strip
4311 leading and trailing whitespace as a favor to the user. */
4312 fname = argv[0];
4313 while (*fname != '\0' && isspace ((unsigned char)*fname))
4314 ++fname;
4315
4316 cp = fname + strlen (fname) - 1;
4317 while (cp > fname && isspace ((unsigned char)*cp))
4318 --cp;
4319 cp[1] = '\0';
4320
4321 /* Calling nothing is a no-op */
4322 if (*fname == '\0')
4323 return o;
4324
4325 /* Are we invoking a builtin function? */
4326
4327#ifndef CONFIG_WITH_VALUE_LENGTH
4328 entry_p = lookup_function (fname);
4329#else
4330 entry_p = lookup_function (fname, cp - fname + 1);
4331#endif
4332 if (entry_p)
4333 {
4334 /* How many arguments do we have? */
4335 for (i=0; argv[i+1]; ++i)
4336 ;
4337 return expand_builtin_function (o, i, argv+1, entry_p);
4338 }
4339
4340 /* Not a builtin, so the first argument is the name of a variable to be
4341 expanded and interpreted as a function. Find it. */
4342 flen = strlen (fname);
4343
4344 v = lookup_variable (fname, flen);
4345
4346 if (v == 0)
4347 warn_undefined (fname, flen);
4348
4349 if (v == 0 || *v->value == '\0')
4350 return o;
4351
4352 body = alloca (flen + 4);
4353 body[0] = '$';
4354 body[1] = '(';
4355 memcpy (body + 2, fname, flen);
4356 body[flen+2] = ')';
4357 body[flen+3] = '\0';
4358
4359 /* Set up arguments $(1) .. $(N). $(0) is the function name. */
4360
4361 push_new_variable_scope ();
4362
4363 for (i=0; *argv; ++i, ++argv)
4364 {
4365 char num[11];
4366
4367 sprintf (num, "%d", i);
4368 define_variable (num, strlen (num), *argv, o_automatic, 0);
4369 }
4370
4371 /* If the number of arguments we have is < max_args, it means we're inside
4372 a recursive invocation of $(call ...). Fill in the remaining arguments
4373 in the new scope with the empty value, to hide them from this
4374 invocation. */
4375
4376 for (; i < max_args; ++i)
4377 {
4378 char num[11];
4379
4380#ifndef CONFIG_WITH_VALUE_LENGTH
4381 sprintf (num, "%d", i);
4382 define_variable (num, strlen (num), "", o_automatic, 0);
4383#else
4384 define_variable (num, sprintf (num, "%d", i), "", o_automatic, 0);
4385#endif
4386 }
4387
4388 saved_args = max_args;
4389 max_args = i;
4390
4391#ifdef CONFIG_WITH_EVALPLUS
4392 if (!strcmp (funcname, "call"))
4393 {
4394#endif
4395 /* Expand the body in the context of the arguments, adding the result to
4396 the variable buffer. */
4397
4398 v->exp_count = EXP_COUNT_MAX;
4399#ifndef CONFIG_WITH_VALUE_LENGTH
4400 o = variable_expand_string (o, body, flen+3);
4401 v->exp_count = 0;
4402
4403 o += strlen (o);
4404#else /* CONFIG_WITH_VALUE_LENGTH */
4405 variable_expand_string_2 (o, body, flen+3, &o);
4406 v->exp_count = 0;
4407#endif /* CONFIG_WITH_VALUE_LENGTH */
4408#ifdef CONFIG_WITH_EVALPLUS
4409 }
4410 else
4411 {
4412 const struct floc *reading_file_saved = reading_file;
4413 char *eos;
4414
4415 if (!strcmp (funcname, "evalcall"))
4416 {
4417 /* Evaluate the variable value without expanding it. We
4418 need a copy since eval_buffer is destructive. */
4419
4420 size_t off = o - variable_buffer;
4421 eos = variable_buffer_output (o, v->value, v->value_length + 1) - 1;
4422 o = variable_buffer + off;
4423 if (v->fileinfo.filenm)
4424 reading_file = &v->fileinfo;
4425 }
4426 else
4427 {
4428 /* Expand the body first and then evaluate the output. */
4429
4430 v->exp_count = EXP_COUNT_MAX;
4431 o = variable_expand_string_2 (o, body, flen+3, &eos);
4432 v->exp_count = 0;
4433 }
4434
4435 install_variable_buffer (&buf, &len);
4436 eval_buffer (o, eos);
4437 restore_variable_buffer (buf, len);
4438 reading_file = reading_file_saved;
4439 }
4440#endif /* CONFIG_WITH_EVALPLUS */
4441
4442 max_args = saved_args;
4443
4444 pop_variable_scope ();
4445
4446 return o;
4447}
4448
4449void
4450hash_init_function_table (void)
4451{
4452 hash_init (&function_table, FUNCTION_TABLE_ENTRIES * 2,
4453 function_table_entry_hash_1, function_table_entry_hash_2,
4454 function_table_entry_hash_cmp);
4455 hash_load (&function_table, function_table_init,
4456 FUNCTION_TABLE_ENTRIES, sizeof (struct function_table_entry));
4457#if defined (CONFIG_WITH_OPTIMIZATION_HACKS) || defined (CONFIG_WITH_VALUE_LENGTH)
4458 {
4459 unsigned int i;
4460 for (i = 'a'; i <= 'z'; i++)
4461 func_char_map[i] = 1;
4462 func_char_map[(unsigned int)'-'] = 1;
4463
4464 for (i = 0; i < FUNCTION_TABLE_ENTRIES; i++)
4465 {
4466 assert (function_table_init[i].len <= MAX_FUNCTION_LENGTH);
4467 assert (function_table_init[i].len >= MIN_FUNCTION_LENGTH);
4468 }
4469 }
4470#endif
4471}
Note: See TracBrowser for help on using the repository browser.

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