VirtualBox

source: kBuild/trunk/src/kmk/misc.c@ 2554

Last change on this file since 2554 was 2548, checked in by bird, 13 years ago

kmk: hacking on a new kmk/kBuild language extension.

  • Property svn:eol-style set to native
File size: 33.2 KB
Line 
1/* Miscellaneous generic support functions for GNU Make.
2Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
31998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 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 3 of the License, or (at your option) any later
10version.
11
12GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License along with
17this program. If not, see <http://www.gnu.org/licenses/>. */
18
19#include "make.h"
20#include "dep.h"
21#include "debug.h"
22#if defined (CONFIG_WITH_VALUE_LENGTH) || defined (CONFIG_WITH_ALLOC_CACHES)
23# include <assert.h>
24#endif
25#ifdef CONFIG_WITH_PRINT_STATS_SWITCH
26# ifdef __APPLE__
27# include <malloc/malloc.h>
28# endif
29# if defined(__GLIBC__) || defined(HAVE_MALLINFO)
30# include <malloc.h>
31# endif
32#endif
33
34#if defined (CONFIG_WITH_NANOTS) || defined (CONFIG_WITH_PRINT_TIME_SWITCH)
35# ifdef WINDOWS32
36# include <Windows.h>
37# endif
38#endif
39
40/* All bcopy calls in this file can be replaced by memcpy and save a tick or two. */
41#ifdef CONFIG_WITH_OPTIMIZATION_HACKS
42# undef bcopy
43# if defined(__GNUC__) && defined(CONFIG_WITH_OPTIMIZATION_HACKS)
44# define bcopy(src, dst, size) __builtin_memcpy ((dst), (src), (size))
45# else
46# define bcopy(src, dst, size) memcpy ((dst), (src), (size))
47# endif
48#endif
49
50/* Variadic functions. We go through contortions to allow proper function
51 prototypes for both ANSI and pre-ANSI C compilers, and also for those
52 which support stdarg.h vs. varargs.h, and finally those which have
53 vfprintf(), etc. and those who have _doprnt... or nothing.
54
55 This fancy stuff all came from GNU fileutils, except for the VA_PRINTF and
56 VA_END macros used here since we have multiple print functions. */
57
58#if USE_VARIADIC
59# if HAVE_STDARG_H
60# include <stdarg.h>
61# define VA_START(args, lastarg) va_start(args, lastarg)
62# else
63# include <varargs.h>
64# define VA_START(args, lastarg) va_start(args)
65# endif
66# if HAVE_VPRINTF
67# define VA_PRINTF(fp, lastarg, args) vfprintf((fp), (lastarg), (args))
68# else
69# define VA_PRINTF(fp, lastarg, args) _doprnt((lastarg), (args), (fp))
70# endif
71# define VA_END(args) va_end(args)
72#else
73/* We can't use any variadic interface! */
74# define va_alist a1, a2, a3, a4, a5, a6, a7, a8
75# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
76# define VA_START(args, lastarg)
77# define VA_PRINTF(fp, lastarg, args) fprintf((fp), (lastarg), va_alist)
78# define VA_END(args)
79#endif
80
81
82/* Compare strings *S1 and *S2.
83 Return negative if the first is less, positive if it is greater,
84 zero if they are equal. */
85
86int
87alpha_compare (const void *v1, const void *v2)
88{
89 const char *s1 = *((char **)v1);
90 const char *s2 = *((char **)v2);
91
92 if (*s1 != *s2)
93 return *s1 - *s2;
94 return strcmp (s1, s2);
95}
96
97
98/* Discard each backslash-newline combination from LINE.
99 Backslash-backslash-newline combinations become backslash-newlines.
100 This is done by copying the text at LINE into itself. */
101
102#ifndef CONFIG_WITH_VALUE_LENGTH
103void
104collapse_continuations (char *line)
105#else
106char *
107collapse_continuations (char *line, unsigned int linelen)
108#endif
109{
110 register char *in, *out, *p;
111 register int backslash;
112 register unsigned int bs_write;
113
114#ifndef CONFIG_WITH_VALUE_LENGTH
115 in = strchr (line, '\n');
116 if (in == 0)
117 return;
118#else
119 assert (strlen (line) == linelen);
120 in = memchr (line, '\n', linelen);
121 if (in == 0)
122 return line + linelen;
123 if (in == line || in[-1] != '\\')
124 {
125 do
126 {
127 unsigned int off_in = in - line;
128 if (off_in == linelen)
129 return in;
130 in = memchr (in + 1, '\n', linelen - off_in - 1);
131 if (in == 0)
132 return line + linelen;
133 }
134 while (in[-1] != '\\');
135 }
136#endif
137
138 out = in;
139 while (out > line && out[-1] == '\\')
140 --out;
141
142 while (*in != '\0')
143 {
144 /* BS_WRITE gets the number of quoted backslashes at
145 the end just before IN, and BACKSLASH gets nonzero
146 if the next character is quoted. */
147 backslash = 0;
148 bs_write = 0;
149 for (p = in - 1; p >= line && *p == '\\'; --p)
150 {
151 if (backslash)
152 ++bs_write;
153 backslash = !backslash;
154
155 /* It should be impossible to go back this far without exiting,
156 but if we do, we can't get the right answer. */
157 if (in == out - 1)
158 abort ();
159 }
160
161 /* Output the appropriate number of backslashes. */
162 while (bs_write-- > 0)
163 *out++ = '\\';
164
165 /* Skip the newline. */
166 ++in;
167
168 /* If the newline is quoted, discard following whitespace
169 and any preceding whitespace; leave just one space. */
170 if (backslash)
171 {
172 in = next_token (in);
173 while (out > line && isblank ((unsigned char)out[-1]))
174 --out;
175 *out++ = ' ';
176 }
177 else
178 /* If the newline isn't quoted, put it in the output. */
179 *out++ = '\n';
180
181 /* Now copy the following line to the output.
182 Stop when we find backslashes followed by a newline. */
183 while (*in != '\0')
184 if (*in == '\\')
185 {
186 p = in + 1;
187 while (*p == '\\')
188 ++p;
189 if (*p == '\n')
190 {
191 in = p;
192 break;
193 }
194 while (in < p)
195 *out++ = *in++;
196 }
197 else
198 *out++ = *in++;
199 }
200
201 *out = '\0';
202#ifdef CONFIG_WITH_VALUE_LENGTH
203 assert (strchr (line, '\0') == out);
204 return out;
205#endif
206}
207
208
209/* Print N spaces (used in debug for target-depth). */
210
211void
212print_spaces (unsigned int n)
213{
214 while (n-- > 0)
215 putchar (' ');
216}
217
218
219
220/* Return a string whose contents concatenate those of s1, s2, s3.
221 This string lives in static, re-used memory. */
222
223char *
224concat (const char *s1, const char *s2, const char *s3)
225{
226 unsigned int len1, len2, len3;
227 static unsigned int rlen = 0;
228 static char *result = NULL;
229
230 len1 = (s1 && *s1 != '\0') ? strlen (s1) : 0;
231 len2 = (s2 && *s2 != '\0') ? strlen (s2) : 0;
232 len3 = (s3 && *s3 != '\0') ? strlen (s3) : 0;
233
234 if (len1 + len2 + len3 + 1 > rlen)
235 result = xrealloc (result, (rlen = len1 + len2 + len3 + 10));
236
237 if (len1)
238 memcpy (result, s1, len1);
239 if (len2)
240 memcpy (result + len1, s2, len2);
241 if (len3)
242 memcpy (result + len1 + len2, s3, len3);
243
244 result[len1+len2+len3] = '\0';
245
246 return result;
247}
248
249
250/* Print a message on stdout. */
251
252void
253#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
254message (int prefix, const char *fmt, ...)
255#else
256message (prefix, fmt, va_alist)
257 int prefix;
258 const char *fmt;
259 va_dcl
260#endif
261{
262#if USE_VARIADIC
263 va_list args;
264#endif
265
266 log_working_directory (1);
267
268 if (fmt != 0)
269 {
270 if (prefix)
271 {
272 if (makelevel == 0)
273 printf ("%s: ", program);
274 else
275 printf ("%s[%u]: ", program, makelevel);
276 }
277 VA_START (args, fmt);
278 VA_PRINTF (stdout, fmt, args);
279 VA_END (args);
280 putchar ('\n');
281 }
282
283 fflush (stdout);
284}
285
286/* Print an error message. */
287
288void
289#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
290error (const struct floc *flocp, const char *fmt, ...)
291#else
292error (flocp, fmt, va_alist)
293 const struct floc *flocp;
294 const char *fmt;
295 va_dcl
296#endif
297{
298#if USE_VARIADIC
299 va_list args;
300#endif
301
302 log_working_directory (1);
303
304 if (flocp && flocp->filenm)
305 fprintf (stderr, "%s:%lu: ", flocp->filenm, flocp->lineno);
306 else if (makelevel == 0)
307 fprintf (stderr, "%s: ", program);
308 else
309 fprintf (stderr, "%s[%u]: ", program, makelevel);
310
311 VA_START(args, fmt);
312 VA_PRINTF (stderr, fmt, args);
313 VA_END (args);
314
315 putc ('\n', stderr);
316 fflush (stderr);
317}
318
319/* Print an error message and exit. */
320
321void
322#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
323fatal (const struct floc *flocp, const char *fmt, ...)
324#else
325fatal (flocp, fmt, va_alist)
326 const struct floc *flocp;
327 const char *fmt;
328 va_dcl
329#endif
330{
331#if USE_VARIADIC
332 va_list args;
333#endif
334
335 log_working_directory (1);
336
337 if (flocp && flocp->filenm)
338 fprintf (stderr, "%s:%lu: *** ", flocp->filenm, flocp->lineno);
339 else if (makelevel == 0)
340 fprintf (stderr, "%s: *** ", program);
341 else
342 fprintf (stderr, "%s[%u]: *** ", program, makelevel);
343
344 VA_START(args, fmt);
345 VA_PRINTF (stderr, fmt, args);
346 VA_END (args);
347
348 fputs (_(". Stop.\n"), stderr);
349
350 die (2);
351}
352
353#ifndef HAVE_STRERROR
354
355#undef strerror
356
357char *
358strerror (int errnum)
359{
360 extern int errno, sys_nerr;
361#ifndef __DECC
362 extern char *sys_errlist[];
363#endif
364 static char buf[] = "Unknown error 12345678901234567890";
365
366 if (errno < sys_nerr)
367 return sys_errlist[errnum];
368
369 sprintf (buf, _("Unknown error %d"), errnum);
370 return buf;
371}
372#endif
373
374/* Print an error message from errno. */
375
376void
377perror_with_name (const char *str, const char *name)
378{
379 error (NILF, _("%s%s: %s"), str, name, strerror (errno));
380}
381
382/* Print an error message from errno and exit. */
383
384void
385pfatal_with_name (const char *name)
386{
387 fatal (NILF, _("%s: %s"), name, strerror (errno));
388
389 /* NOTREACHED */
390}
391
392
393/* Like malloc but get fatal error if memory is exhausted. */
394/* Don't bother if we're using dmalloc; it provides these for us. */
395
396#if !defined(HAVE_DMALLOC_H) && !defined(ELECTRIC_HEAP) /* bird */
397
398#undef xmalloc
399#undef xrealloc
400#undef xstrdup
401
402void *
403xmalloc (unsigned int size)
404{
405 /* Make sure we don't allocate 0, for pre-ANSI libraries. */
406 void *result = malloc (size ? size : 1);
407 if (result == 0)
408 fatal (NILF, _("virtual memory exhausted"));
409
410#ifdef CONFIG_WITH_MAKE_STATS
411 make_stats_allocations++;
412 if (make_expensive_statistics)
413 make_stats_allocated += SIZE_OF_HEAP_BLOCK (result);
414 else
415 make_stats_allocated += size;
416#endif
417 return result;
418}
419
420
421void *
422xrealloc (void *ptr, unsigned int size)
423{
424 void *result;
425#ifdef CONFIG_WITH_MAKE_STATS
426 if (make_expensive_statistics && ptr != NULL)
427 make_stats_allocated -= SIZE_OF_HEAP_BLOCK (ptr);
428 if (ptr)
429 make_stats_reallocations++;
430 else
431 make_stats_allocations++;
432#endif
433
434 /* Some older implementations of realloc() don't conform to ANSI. */
435 if (! size)
436 size = 1;
437 result = ptr ? realloc (ptr, size) : malloc (size);
438 if (result == 0)
439 fatal (NILF, _("virtual memory exhausted"));
440
441#ifdef CONFIG_WITH_MAKE_STATS
442 if (make_expensive_statistics)
443 make_stats_allocated += SIZE_OF_HEAP_BLOCK (result);
444 else
445 make_stats_allocated += size;
446#endif
447 return result;
448}
449
450
451char *
452xstrdup (const char *ptr)
453{
454 char *result;
455
456#ifdef HAVE_STRDUP
457 result = strdup (ptr);
458#else
459 result = malloc (strlen (ptr) + 1);
460#endif
461
462 if (result == 0)
463 fatal (NILF, _("virtual memory exhausted"));
464
465#ifdef CONFIG_WITH_MAKE_STATS
466 make_stats_allocations++;
467 if (make_expensive_statistics)
468 make_stats_allocated += SIZE_OF_HEAP_BLOCK (result);
469 else
470 make_stats_allocated += strlen (ptr) + 1;
471#endif
472#ifdef HAVE_STRDUP
473 return result;
474#else
475 return strcpy (result, ptr);
476#endif
477}
478
479#endif /* HAVE_DMALLOC_H */
480
481char *
482savestring (const char *str, unsigned int length)
483{
484 char *out = xmalloc (length + 1);
485 if (length > 0)
486 memcpy (out, str, length);
487 out[length] = '\0';
488 return out;
489}
490
491
492
493#ifndef CONFIG_WITH_OPTIMIZATION_HACKS /* This is really a reimplemntation of
494 memchr, only slower. It's been replaced by a macro in the header file. */
495
496/* Limited INDEX:
497 Search through the string STRING, which ends at LIMIT, for the character C.
498 Returns a pointer to the first occurrence, or nil if none is found.
499 Like INDEX except that the string searched ends where specified
500 instead of at the first null. */
501
502char *
503lindex (const char *s, const char *limit, int c)
504{
505 while (s < limit)
506 if (*s++ == c)
507 return (char *)(s - 1);
508
509 return 0;
510}
511#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
512
513
514/* Return the address of the first whitespace or null in the string S. */
515
516char *
517end_of_token (const char *s)
518{
519#ifdef KMK
520 for (;;)
521 {
522 unsigned char ch0, ch1, ch2, ch3;
523
524 ch0 = *s;
525 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch0)))
526 return (char *)s;
527 ch1 = s[1];
528 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch1)))
529 return (char *)s + 1;
530 ch2 = s[2];
531 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch2)))
532 return (char *)s + 2;
533 ch3 = s[3];
534 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch3)))
535 return (char *)s + 3;
536
537 s += 4;
538 }
539
540#else
541 while (*s != '\0' && !isblank ((unsigned char)*s))
542 ++s;
543 return (char *)s;
544#endif
545}
546
547#ifdef WINDOWS32
548/*
549 * Same as end_of_token, but take into account a stop character
550 */
551char *
552end_of_token_w32 (const char *s, char stopchar)
553{
554 const char *p = s;
555 int backslash = 0;
556
557 while (*p != '\0' && *p != stopchar
558 && (backslash || !isblank ((unsigned char)*p)))
559 {
560 if (*p++ == '\\')
561 {
562 backslash = !backslash;
563 while (*p == '\\')
564 {
565 backslash = !backslash;
566 ++p;
567 }
568 }
569 else
570 backslash = 0;
571 }
572
573 return (char *)p;
574}
575#endif
576
577/* Return the address of the first nonwhitespace or null in the string S. */
578
579char *
580next_token (const char *s)
581{
582#ifdef KMK
583 for (;;)
584 {
585 unsigned char ch0, ch1, ch2, ch3;
586
587 ch0 = *s;
588 if (MY_PREDICT_FALSE(!MY_IS_BLANK(ch0)))
589 return (char *)s;
590 ch1 = s[1];
591 if (MY_PREDICT_TRUE(!MY_IS_BLANK(ch1)))
592 return (char *)s + 1;
593 ch2 = s[2];
594 if (MY_PREDICT_FALSE(!MY_IS_BLANK(ch2)))
595 return (char *)s + 2;
596 ch3 = s[3];
597 if (MY_PREDICT_TRUE(!MY_IS_BLANK(ch3)))
598 return (char *)s + 3;
599
600 s += 4;
601 }
602
603#else /* !KMK */
604 while (isblank ((unsigned char)*s))
605 ++s;
606 return (char *)s;
607#endif /* !KMK */
608}
609
610/* Find the next token in PTR; return the address of it, and store the length
611 of the token into *LENGTHPTR if LENGTHPTR is not nil. Set *PTR to the end
612 of the token, so this function can be called repeatedly in a loop. */
613
614char *
615find_next_token (const char **ptr, unsigned int *lengthptr)
616{
617#ifdef KMK
618 const char *p = *ptr;
619 const char *e;
620
621 /* skip blanks */
622# if 0 /* a moderate version */
623 for (;; p++)
624 {
625 unsigned char ch = *p;
626 if (!MY_IS_BLANK(ch))
627 {
628 if (!ch)
629 return NULL;
630 break;
631 }
632 }
633
634# else /* (too) big unroll */
635 for (;; p += 4)
636 {
637 unsigned char ch0, ch1, ch2, ch3;
638
639 ch0 = *p;
640 if (MY_PREDICT_FALSE(!MY_IS_BLANK(ch0)))
641 {
642 if (!ch0)
643 return NULL;
644 break;
645 }
646 ch1 = p[1];
647 if (MY_PREDICT_TRUE(!MY_IS_BLANK(ch1)))
648 {
649 if (!ch1)
650 return NULL;
651 p += 1;
652 break;
653 }
654 ch2 = p[2];
655 if (MY_PREDICT_FALSE(!MY_IS_BLANK(ch2)))
656 {
657 if (!ch2)
658 return NULL;
659 p += 2;
660 break;
661 }
662 ch3 = p[3];
663 if (MY_PREDICT_TRUE(!MY_IS_BLANK(ch3)))
664 {
665 if (!ch3)
666 return NULL;
667 p += 3;
668 break;
669 }
670 }
671# endif
672
673 /* skip ahead until EOS or blanks. */
674# if 0 /* a moderate version */
675 for (e = p + 1; ; e++)
676 {
677 unsigned char ch = *e;
678 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch)))
679 break;
680 }
681# else /* (too) big unroll */
682 for (e = p + 1; ; e += 4)
683 {
684 unsigned char ch0, ch1, ch2, ch3;
685
686 ch0 = *e;
687 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch0)))
688 break;
689 ch1 = e[1];
690 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch1)))
691 {
692 e += 1;
693 break;
694 }
695 ch2 = e[2];
696 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch2)))
697 {
698 e += 2;
699 break;
700 }
701 ch3 = e[3];
702 if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch3)))
703 {
704 e += 3;
705 break;
706 }
707 }
708# endif
709 *ptr = e;
710
711 if (lengthptr != 0)
712 *lengthptr = e - p;
713
714 return (char *)p;
715
716#else
717 const char *p = next_token (*ptr);
718
719 if (*p == '\0')
720 return 0;
721
722 *ptr = end_of_token (p);
723 if (lengthptr != 0)
724 *lengthptr = *ptr - p;
725
726 return (char *)p;
727#endif
728}
729#ifdef KMK
730
731/* Same as find_next_token with two exception:
732 - The string ends at EOS or '\0'.
733 - We keep track of $() and ${}, allowing functions to be used. */
734
735char *
736find_next_token_eos (const char **ptr, const char *eos, unsigned int *lengthptr)
737{
738 const char *p = *ptr;
739 const char *e;
740 int level = 0;
741
742 /* skip blanks */
743 for (; p != eos; p++)
744 {
745 unsigned char ch = *p;
746 if (!MY_IS_BLANK(ch))
747 {
748 if (!ch)
749 return NULL;
750 break;
751 }
752 }
753 if (p == eos)
754 return NULL;
755
756 /* skip ahead until EOS or blanks. */
757 for (e = p; e != eos; e++)
758 {
759 unsigned char ch = *e;
760 if (MY_IS_BLANK_OR_EOS(ch))
761 {
762 if (!ch || level == 0)
763 break;
764 }
765 else if (ch == '$')
766 {
767 if (&e[1] != eos && (e[1] == '(' || e[1] == '{'))
768 {
769 level++;
770 e++;
771 }
772 }
773 else if ((ch == ')' || ch == '}') && level > 0)
774 level--;
775 }
776
777 *ptr = e;
778 if (lengthptr != 0)
779 *lengthptr = e - p;
780
781 return (char *)p;
782}
783
784#endif /* KMK */
785
786
787
788/* Allocate a new `struct dep' with all fields initialized to 0. */
789
790struct dep *
791alloc_dep ()
792{
793#ifndef CONFIG_WITH_ALLOC_CACHES
794 struct dep *d = xmalloc (sizeof (struct dep));
795 memset (d, '\0', sizeof (struct dep));
796 return d;
797#else
798 return (struct dep *) alloccache_calloc (&dep_cache);
799#endif
800}
801
802
803/* Free `struct dep' along with `name' and `stem'. */
804
805void
806free_dep (struct dep *d)
807{
808#ifndef CONFIG_WITH_ALLOC_CACHES
809 free (d);
810#else
811 alloccache_free (&dep_cache, d);
812#endif
813}
814
815/* Copy a chain of `struct dep', making a new chain
816 with the same contents as the old one. */
817
818struct dep *
819copy_dep_chain (const struct dep *d)
820{
821 struct dep *firstnew = 0;
822 struct dep *lastnew = 0;
823
824 while (d != 0)
825 {
826#ifndef CONFIG_WITH_ALLOC_CACHES
827 struct dep *c = xmalloc (sizeof (struct dep));
828#else
829 struct dep *c = (struct dep *) alloccache_alloc (&dep_cache);
830#endif
831 memcpy (c, d, sizeof (struct dep));
832
833 c->next = 0;
834 if (firstnew == 0)
835 firstnew = lastnew = c;
836 else
837 lastnew = lastnew->next = c;
838
839 d = d->next;
840 }
841
842 return firstnew;
843}
844
845/* Free a chain of 'struct dep'. */
846
847void
848free_dep_chain (struct dep *d)
849{
850 while (d != 0)
851 {
852 struct dep *df = d;
853 d = d->next;
854#ifndef CONFIG_WITH_ALLOC_CACHES
855 free_dep (df);
856#else
857 alloccache_free (&dep_cache, df);
858#endif
859 }
860}
861
862/* Free a chain of struct nameseq.
863 For struct dep chains use free_dep_chain. */
864
865void
866free_ns_chain (struct nameseq *ns)
867{
868 while (ns != 0)
869 {
870 struct nameseq *t = ns;
871 ns = ns->next;
872#ifndef CONFIG_WITH_ALLOC_CACHES
873 free (t);
874#else
875 alloccache_free (&nameseq_cache, t);
876#endif
877 }
878}
879
880
881
882#if !HAVE_STRCASECMP && !HAVE_STRICMP && !HAVE_STRCMPI
883
884/* If we don't have strcasecmp() (from POSIX), or anything that can substitute
885 for it, define our own version. */
886
887int
888strcasecmp (const char *s1, const char *s2)
889{
890 while (1)
891 {
892 int c1 = (int) *(s1++);
893 int c2 = (int) *(s2++);
894
895 if (isalpha (c1))
896 c1 = tolower (c1);
897 if (isalpha (c2))
898 c2 = tolower (c2);
899
900 if (c1 != '\0' && c1 == c2)
901 continue;
902
903 return (c1 - c2);
904 }
905}
906#endif
907
908
909#ifdef GETLOADAVG_PRIVILEGED
910
911#ifdef POSIX
912
913/* Hopefully if a system says it's POSIX.1 and has the setuid and setgid
914 functions, they work as POSIX.1 says. Some systems (Alpha OSF/1 1.2,
915 for example) which claim to be POSIX.1 also have the BSD setreuid and
916 setregid functions, but they don't work as in BSD and only the POSIX.1
917 way works. */
918
919#undef HAVE_SETREUID
920#undef HAVE_SETREGID
921
922#else /* Not POSIX. */
923
924/* Some POSIX.1 systems have the seteuid and setegid functions. In a
925 POSIX-like system, they are the best thing to use. However, some
926 non-POSIX systems have them too but they do not work in the POSIX style
927 and we must use setreuid and setregid instead. */
928
929#undef HAVE_SETEUID
930#undef HAVE_SETEGID
931
932#endif /* POSIX. */
933
934#ifndef HAVE_UNISTD_H
935extern int getuid (), getgid (), geteuid (), getegid ();
936extern int setuid (), setgid ();
937#ifdef HAVE_SETEUID
938extern int seteuid ();
939#else
940#ifdef HAVE_SETREUID
941extern int setreuid ();
942#endif /* Have setreuid. */
943#endif /* Have seteuid. */
944#ifdef HAVE_SETEGID
945extern int setegid ();
946#else
947#ifdef HAVE_SETREGID
948extern int setregid ();
949#endif /* Have setregid. */
950#endif /* Have setegid. */
951#endif /* No <unistd.h>. */
952
953/* Keep track of the user and group IDs for user- and make- access. */
954static int user_uid = -1, user_gid = -1, make_uid = -1, make_gid = -1;
955#define access_inited (user_uid != -1)
956static enum { make, user } current_access;
957
958
959/* Under -d, write a message describing the current IDs. */
960
961static void
962log_access (const char *flavor)
963{
964 if (! ISDB (DB_JOBS))
965 return;
966
967 /* All the other debugging messages go to stdout,
968 but we write this one to stderr because it might be
969 run in a child fork whose stdout is piped. */
970
971 fprintf (stderr, _("%s: user %lu (real %lu), group %lu (real %lu)\n"),
972 flavor, (unsigned long) geteuid (), (unsigned long) getuid (),
973 (unsigned long) getegid (), (unsigned long) getgid ());
974 fflush (stderr);
975}
976
977
978static void
979init_access (void)
980{
981#ifndef VMS
982 user_uid = getuid ();
983 user_gid = getgid ();
984
985 make_uid = geteuid ();
986 make_gid = getegid ();
987
988 /* Do these ever fail? */
989 if (user_uid == -1 || user_gid == -1 || make_uid == -1 || make_gid == -1)
990 pfatal_with_name ("get{e}[gu]id");
991
992 log_access (_("Initialized access"));
993
994 current_access = make;
995#endif
996}
997
998#endif /* GETLOADAVG_PRIVILEGED */
999
1000/* Give the process appropriate permissions for access to
1001 user data (i.e., to stat files, or to spawn a child process). */
1002void
1003user_access (void)
1004{
1005#ifdef GETLOADAVG_PRIVILEGED
1006
1007 if (!access_inited)
1008 init_access ();
1009
1010 if (current_access == user)
1011 return;
1012
1013 /* We are in "make access" mode. This means that the effective user and
1014 group IDs are those of make (if it was installed setuid or setgid).
1015 We now want to set the effective user and group IDs to the real IDs,
1016 which are the IDs of the process that exec'd make. */
1017
1018#ifdef HAVE_SETEUID
1019
1020 /* Modern systems have the seteuid/setegid calls which set only the
1021 effective IDs, which is ideal. */
1022
1023 if (seteuid (user_uid) < 0)
1024 pfatal_with_name ("user_access: seteuid");
1025
1026#else /* Not HAVE_SETEUID. */
1027
1028#ifndef HAVE_SETREUID
1029
1030 /* System V has only the setuid/setgid calls to set user/group IDs.
1031 There is an effective ID, which can be set by setuid/setgid.
1032 It can be set (unless you are root) only to either what it already is
1033 (returned by geteuid/getegid, now in make_uid/make_gid),
1034 the real ID (return by getuid/getgid, now in user_uid/user_gid),
1035 or the saved set ID (what the effective ID was before this set-ID
1036 executable (make) was exec'd). */
1037
1038 if (setuid (user_uid) < 0)
1039 pfatal_with_name ("user_access: setuid");
1040
1041#else /* HAVE_SETREUID. */
1042
1043 /* In 4BSD, the setreuid/setregid calls set both the real and effective IDs.
1044 They may be set to themselves or each other. So you have two alternatives
1045 at any one time. If you use setuid/setgid, the effective will be set to
1046 the real, leaving only one alternative. Using setreuid/setregid, however,
1047 you can toggle between your two alternatives by swapping the values in a
1048 single setreuid or setregid call. */
1049
1050 if (setreuid (make_uid, user_uid) < 0)
1051 pfatal_with_name ("user_access: setreuid");
1052
1053#endif /* Not HAVE_SETREUID. */
1054#endif /* HAVE_SETEUID. */
1055
1056#ifdef HAVE_SETEGID
1057 if (setegid (user_gid) < 0)
1058 pfatal_with_name ("user_access: setegid");
1059#else
1060#ifndef HAVE_SETREGID
1061 if (setgid (user_gid) < 0)
1062 pfatal_with_name ("user_access: setgid");
1063#else
1064 if (setregid (make_gid, user_gid) < 0)
1065 pfatal_with_name ("user_access: setregid");
1066#endif
1067#endif
1068
1069 current_access = user;
1070
1071 log_access (_("User access"));
1072
1073#endif /* GETLOADAVG_PRIVILEGED */
1074}
1075
1076/* Give the process appropriate permissions for access to
1077 make data (i.e., the load average). */
1078void
1079make_access (void)
1080{
1081#ifdef GETLOADAVG_PRIVILEGED
1082
1083 if (!access_inited)
1084 init_access ();
1085
1086 if (current_access == make)
1087 return;
1088
1089 /* See comments in user_access, above. */
1090
1091#ifdef HAVE_SETEUID
1092 if (seteuid (make_uid) < 0)
1093 pfatal_with_name ("make_access: seteuid");
1094#else
1095#ifndef HAVE_SETREUID
1096 if (setuid (make_uid) < 0)
1097 pfatal_with_name ("make_access: setuid");
1098#else
1099 if (setreuid (user_uid, make_uid) < 0)
1100 pfatal_with_name ("make_access: setreuid");
1101#endif
1102#endif
1103
1104#ifdef HAVE_SETEGID
1105 if (setegid (make_gid) < 0)
1106 pfatal_with_name ("make_access: setegid");
1107#else
1108#ifndef HAVE_SETREGID
1109 if (setgid (make_gid) < 0)
1110 pfatal_with_name ("make_access: setgid");
1111#else
1112 if (setregid (user_gid, make_gid) < 0)
1113 pfatal_with_name ("make_access: setregid");
1114#endif
1115#endif
1116
1117 current_access = make;
1118
1119 log_access (_("Make access"));
1120
1121#endif /* GETLOADAVG_PRIVILEGED */
1122}
1123
1124/* Give the process appropriate permissions for a child process.
1125 This is like user_access, but you can't get back to make_access. */
1126void
1127child_access (void)
1128{
1129#ifdef GETLOADAVG_PRIVILEGED
1130
1131 if (!access_inited)
1132 abort ();
1133
1134 /* Set both the real and effective UID and GID to the user's.
1135 They cannot be changed back to make's. */
1136
1137#ifndef HAVE_SETREUID
1138 if (setuid (user_uid) < 0)
1139 pfatal_with_name ("child_access: setuid");
1140#else
1141 if (setreuid (user_uid, user_uid) < 0)
1142 pfatal_with_name ("child_access: setreuid");
1143#endif
1144
1145#ifndef HAVE_SETREGID
1146 if (setgid (user_gid) < 0)
1147 pfatal_with_name ("child_access: setgid");
1148#else
1149 if (setregid (user_gid, user_gid) < 0)
1150 pfatal_with_name ("child_access: setregid");
1151#endif
1152
1153 log_access (_("Child access"));
1154
1155#endif /* GETLOADAVG_PRIVILEGED */
1156}
1157
1158
1159#ifdef NEED_GET_PATH_MAX
1160unsigned int
1161get_path_max (void)
1162{
1163 static unsigned int value;
1164
1165 if (value == 0)
1166 {
1167 long int x = pathconf ("/", _PC_PATH_MAX);
1168 if (x > 0)
1169 value = x;
1170 else
1171 return MAXPATHLEN;
1172 }
1173
1174 return value;
1175}
1176#endif
1177
1178
1179
1180/* This code is stolen from gnulib.
1181 If/when we abandon the requirement to work with K&R compilers, we can
1182 remove this (and perhaps other parts of GNU make!) and migrate to using
1183 gnulib directly.
1184
1185 This is called only through atexit(), which means die() has already been
1186 invoked. So, call exit() here directly. Apparently that works...?
1187*/
1188
1189/* Close standard output, exiting with status 'exit_failure' on failure.
1190 If a program writes *anything* to stdout, that program should close
1191 stdout and make sure that it succeeds before exiting. Otherwise,
1192 suppose that you go to the extreme of checking the return status
1193 of every function that does an explicit write to stdout. The last
1194 printf can succeed in writing to the internal stream buffer, and yet
1195 the fclose(stdout) could still fail (due e.g., to a disk full error)
1196 when it tries to write out that buffered data. Thus, you would be
1197 left with an incomplete output file and the offending program would
1198 exit successfully. Even calling fflush is not always sufficient,
1199 since some file systems (NFS and CODA) buffer written/flushed data
1200 until an actual close call.
1201
1202 Besides, it's wasteful to check the return value from every call
1203 that writes to stdout -- just let the internal stream state record
1204 the failure. That's what the ferror test is checking below.
1205
1206 It's important to detect such failures and exit nonzero because many
1207 tools (most notably `make' and other build-management systems) depend
1208 on being able to detect failure in other tools via their exit status. */
1209
1210void
1211close_stdout (void)
1212{
1213 int prev_fail = ferror (stdout);
1214 int fclose_fail = fclose (stdout);
1215
1216 if (prev_fail || fclose_fail)
1217 {
1218 if (fclose_fail)
1219 error (NILF, _("write error: %s"), strerror (errno));
1220 else
1221 error (NILF, _("write error"));
1222 exit (EXIT_FAILURE);
1223 }
1224}
1225
1226#ifdef CONFIG_WITH_PRINT_STATS_SWITCH
1227/* Print heap statistics if supported by the platform. */
1228void
1229print_heap_stats (void)
1230{
1231 /* Darwin / Mac OS X */
1232# ifdef __APPLE__
1233 malloc_statistics_t s;
1234
1235 malloc_zone_statistics (NULL, &s);
1236 printf (_("\n# CRT Heap: %zu bytes in use, in %u blocks, avg %zu bytes/block\n"),
1237 s.size_in_use, s.blocks_in_use, s.size_in_use / s.blocks_in_use);
1238 printf (_("# %zu bytes max in use (high water mark)\n"),
1239 s.max_size_in_use);
1240 printf (_("# %zu bytes reserved, %zu bytes free (estimate)\n"),
1241 s.size_allocated, s.size_allocated - s.size_in_use);
1242# endif /* __APPLE__ */
1243
1244 /* MSC / Windows */
1245# ifdef _MSC_VER
1246 unsigned int blocks_used = 0;
1247 unsigned int bytes_used = 0;
1248 unsigned int blocks_avail = 0;
1249 unsigned int bytes_avail = 0;
1250 _HEAPINFO hinfo;
1251
1252 memset (&hinfo, '\0', sizeof (hinfo));
1253 while (_heapwalk(&hinfo) == _HEAPOK)
1254 {
1255 if (hinfo._useflag == _USEDENTRY)
1256 {
1257 blocks_used++;
1258 bytes_used += hinfo._size;
1259 }
1260 else
1261 {
1262 blocks_avail++;
1263 bytes_avail += hinfo._size;
1264 }
1265 }
1266
1267 printf (_("\n# CRT Heap: %u bytes in use, in %u blocks, avg %u bytes/block\n"),
1268 bytes_used, blocks_used, bytes_used / blocks_used);
1269 printf (_("# %u bytes avail, in %u blocks, avg %u bytes/block\n"),
1270 bytes_avail, blocks_avail, bytes_avail / blocks_avail);
1271# endif /* _MSC_VER */
1272
1273 /* Darwin Libc sources indicates that something like this may be
1274 found in GLIBC, however, it's not in any current one... */
1275# if 0 /* ??? */
1276 struct mstats m;
1277
1278 m = mstats();
1279 printf (_("\n# CRT Heap: %zu blocks / %zu bytes in use, %zu blocks / %zu bytes free\n"),
1280 m.chunks_used, m.bytes_used, m.chunks_free, m.bytes_free);
1281 printf (_("# %zu bytes reserved\n"),
1282 m.bytes_total);
1283# endif /* ??? */
1284
1285 /* XVID2/XPG mallinfo (displayed per GLIBC documentation). */
1286# if defined(__GLIBC__) || defined(HAVE_MALLINFO)
1287 struct mallinfo m;
1288
1289 m = mallinfo();
1290 printf (_("\n# CRT Heap: %d bytes in use, %d bytes free\n"),
1291 m.uordblks, m.fordblks);
1292
1293 printf (_("# # free chunks=%d, # fastbin blocks=%d\n"),
1294 m.ordblks, m.smblks);
1295 printf (_("# # mapped regions=%d, space in mapped regions=%d\n"),
1296 m.hblks, m.hblkhd);
1297 printf (_("# non-mapped space allocated from system=%d\n"),
1298 m.arena);
1299 printf (_("# maximum total allocated space=%d\n"),
1300 m.usmblks);
1301 printf (_("# top-most releasable space=%d\n"),
1302 m.keepcost);
1303# endif /* __GLIBC__ || HAVE_MALLINFO */
1304
1305# ifdef CONFIG_WITH_MAKE_STATS
1306 printf(_("# %lu malloc calls, %lu realloc calls\n"),
1307 make_stats_allocations, make_stats_reallocations);
1308 printf(_("# %lu MBs alloc sum, not counting freed, add pinch of salt\n"), /* XXX: better wording */
1309 make_stats_allocated / (1024*1024));
1310# endif
1311
1312 /* XXX: windows */
1313}
1314#endif /* CONFIG_WITH_PRINT_STATS_SWITCH */
1315
1316#ifdef CONFIG_WITH_PRINT_TIME_SWITCH
1317/* Get a nanosecond timestamp, from a monotonic time source if
1318 possible. Returns -1 after calling error() on failure. */
1319
1320big_int
1321nano_timestamp (void)
1322{
1323 big_int ts;
1324#if defined (WINDOWS32)
1325 static int s_state = -1;
1326 static LARGE_INTEGER s_freq;
1327
1328 if (s_state == -1)
1329 s_state = QueryPerformanceFrequency (&s_freq);
1330 if (s_state)
1331 {
1332 LARGE_INTEGER pc;
1333 if (!QueryPerformanceCounter (&pc))
1334 {
1335 s_state = 0;
1336 return nano_timestamp ();
1337 }
1338 ts = (big_int)((long double)pc.QuadPart / (long double)s_freq.QuadPart * 1000000000);
1339 }
1340 else
1341 {
1342 /* fall back to low resolution system time. */
1343 LARGE_INTEGER bigint;
1344 FILETIME ft = {0,0};
1345 GetSystemTimeAsFileTime (&ft);
1346 bigint.u.LowPart = ft.dwLowDateTime;
1347 bigint.u.HighPart = ft.dwLowDateTime;
1348 ts = bigint.QuadPart * 100;
1349 }
1350
1351#elif HAVE_GETTIMEOFDAY
1352/* FIXME: Linux and others have the realtime clock_* api, detect and use it. */
1353 struct timeval tv;
1354 if (!gettimeofday (&tv, NULL))
1355 ts = (big_int)tv.tv_sec * 1000000000
1356 + tv.tv_usec * 1000;
1357 else
1358 {
1359 error (NILF, _("gettimeofday failed"));
1360 ts = -1;
1361 }
1362
1363#else
1364# error "PORTME"
1365#endif
1366
1367 return ts;
1368}
1369
1370/* Formats the elapsed time (nano seconds) in the manner easiest
1371 to read, with millisecond percision for larger numbers. */
1372
1373int
1374format_elapsed_nano (char *buf, size_t size, big_int ts)
1375{
1376 int sz;
1377 if (ts < 1000)
1378 sz = sprintf (buf, "%uns", (unsigned)ts);
1379 else if (ts < 100000)
1380 sz = sprintf (buf, "%u.%03uus",
1381 (unsigned)(ts / 1000),
1382 (unsigned)(ts % 1000));
1383 else
1384 {
1385 ts /= 1000;
1386 if (ts < 1000)
1387 sz = sprintf (buf, "%uus", (unsigned)ts);
1388 else if (ts < 100000)
1389 sz = sprintf (buf, "%u.%03ums",
1390 (unsigned)(ts / 1000),
1391 (unsigned)(ts % 1000));
1392 else
1393 {
1394 ts /= 1000;
1395 if (ts < BIG_INT_C(60000))
1396 sz = sprintf (buf,
1397 "%u.%03us",
1398 (unsigned)(ts / 1000),
1399 (unsigned)(ts % 1000));
1400 else
1401 sz = sprintf (buf,
1402 "%um%u.%03us",
1403 (unsigned)( ts / BIG_INT_C(60000)),
1404 (unsigned)((ts % BIG_INT_C(60000)) / 1000),
1405 (unsigned)((ts % BIG_INT_C(60000)) % 1000));
1406 }
1407 }
1408 if (sz >= size)
1409 fatal (NILF, _("format_elapsed_nano buffer overflow: %d written, %d buffer"),
1410 sz, size);
1411 return sz;
1412}
1413#endif /* CONFIG_WITH_PRINT_TIME_SWITCH */
Note: See TracBrowser for help on using the repository browser.

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