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