source: trunk/src/kmk/function.c@ 1387

Last change on this file since 1387 was 1387, checked in by bird, 17 years ago

Fixed typo in $(libpath).

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