VirtualBox

source: kBuild/trunk/src/kmk/output.c@ 3229

最後變更 在這個檔案從3229是 3229,由 bird 提交於 7 年 前

kmk: build fixes

  • 屬性 svn:eol-style 設為 native
檔案大小: 34.4 KB
 
1/* Output to stdout / stderr for GNU make
2Copyright (C) 2013-2016 Free Software Foundation, Inc.
3This file is part of GNU Make.
4
5GNU Make is free software; you can redistribute it and/or modify it under the
6terms of the GNU General Public License as published by the Free Software
7Foundation; either version 3 of the License, or (at your option) any later
8version.
9
10GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
11WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License along with
15this program. If not, see <http://www.gnu.org/licenses/>. */
16
17#include "makeint.h"
18#include "job.h"
19
20/* GNU make no longer supports pre-ANSI89 environments. */
21
22#include <assert.h>
23#include <stdio.h>
24#include <stdarg.h>
25
26#ifdef HAVE_UNISTD_H
27# include <unistd.h>
28#endif
29
30#ifdef HAVE_FCNTL_H
31# include <fcntl.h>
32#else
33# include <sys/file.h>
34#endif
35
36#ifdef WINDOWS32
37# include <windows.h>
38# include <io.h>
39# ifndef CONFIG_NEW_WIN_CHILDREN
40# include "sub_proc.h"
41# else
42# include "w32/winchildren.h"
43# endif
44#endif /* WINDOWS32 */
45#ifdef KBUILD_OS_WINDOWS
46# include "console.h"
47#endif
48
49struct output *output_context = NULL;
50unsigned int stdio_traced = 0;
51
52#define OUTPUT_NONE (-1)
53
54#define OUTPUT_ISSET(_out) ((_out)->out >= 0 || (_out)->err >= 0)
55
56#ifdef HAVE_FCNTL_H
57# define STREAM_OK(_s) ((fcntl (fileno (_s), F_GETFD) != -1) || (errno != EBADF))
58#else
59# define STREAM_OK(_s) 1
60#endif
61
62
63#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
64# define MEMBUF_MIN_SEG_SIZE 4096
65# define MEMBUF_MAX_SEG_SIZE (512*1024)
66# define MEMBUF_MAX_MOVE_LEN ( MEMBUF_MIN_SEG_SIZE \
67 - offsetof (struct output_segment, runs) \
68 - sizeof (struct output_run))
69# define MEMBUF_MAX_TOTAL ( sizeof (void *) <= 4 \
70 ? (size_t)512*1024 : (size_t)16*1024*1024 )
71
72static void *acquire_semaphore (void);
73static void release_semaphore (void *);
74static int log_working_directory (int);
75
76/* Is make's stdout going to the same place as stderr?
77 Also, did we already sync_init (== -1)? */
78static int combined_output = -1;
79
80/* Internal worker for output_dump and membuf_dump_most. */
81static void membuf_dump (struct output *out)
82{
83 if (out->out.total || out->err.total)
84 {
85 int traced = 0;
86 struct output_run *err_run;
87 struct output_run *out_run;
88 struct output_segment *seg;
89 FILE *prevdst;
90
91 /* Try to acquire the semaphore. If it fails, dump the output
92 unsynchronized; still better than silently discarding it.
93 We want to keep this lock for as little time as possible. */
94 void *sem = acquire_semaphore ();
95# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
96 int prev_mode_out = _setmode (fileno (stdout), _O_BINARY);
97 int prev_mode_err = _setmode (fileno (stderr), _O_BINARY);
98# endif
99
100# ifndef KMK /* this drives me bananas. */
101 /* Log the working directory for this dump. */
102 if (print_directory_flag && output_sync != OUTPUT_SYNC_RECURSE)
103 traced = log_working_directory (1);
104# endif
105
106 /* Work the out and err sequences in parallel. */
107 out_run = out->out.head_run;
108 err_run = out->err.head_run;
109 prevdst = NULL;
110 while (err_run || out_run)
111 {
112 FILE *dst;
113 const void *src;
114 size_t len;
115 if (out_run && (!err_run || out_run->seqno <= err_run->seqno))
116 {
117 src = out_run + 1;
118 len = out_run->len;
119 dst = stdout;
120 out_run = out_run->next;
121 }
122 else
123 {
124 src = err_run + 1;
125 len = err_run->len;
126 dst = stderr;
127 err_run = err_run->next;
128 }
129 if (dst != prevdst)
130 fflush(prevdst);
131 prevdst = dst;
132# if 0 /* for debugging */
133 while (len > 0)
134 {
135 const char *nl = (const char *)memchr (src, '\n', len);
136 size_t line_len = nl ? nl - (const char *)src + 1 : len;
137 char *tmp = (char *)xmalloc (1 + line_len + 1 + 1);
138 tmp[0] = '{';
139 memcpy (&tmp[1], src, line_len);
140 tmp[1 + line_len] = '}';
141# ifdef KBUILD_OS_WINDOWS
142 maybe_con_fwrite (tmp, 1 + line_len + 1, 1, dst);
143# else
144 fwrite (tmp, 1 + line_len + 1, 1, dst);
145# endif
146 free (tmp);
147 src = (const char *)src + line_len;
148 len -= line_len;
149 }
150#else
151# ifdef KBUILD_OS_WINDOWS
152 maybe_con_fwrite (src, len, 1, dst);
153# else
154 fwrite (src, len, 1, dst);
155# endif
156# endif
157 }
158 if (prevdst)
159 fflush (prevdst);
160
161# ifndef KMK /* this drives me bananas. */
162 if (traced)
163 log_working_directory (0);
164# endif
165
166 /* Exit the critical section. */
167# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
168 _setmode (fileno (stdout), prev_mode_out);
169 _setmode (fileno (stderr), prev_mode_err);
170# endif
171 if (sem)
172 release_semaphore (sem);
173
174 /* Free the segments and reset the state. */
175 while ((seg = out->out.head_seg))
176 {
177 out->out.head_seg = seg->next;
178 free (seg);
179 }
180 out->out.tail_seg = NULL;
181 out->out.tail_run = NULL;
182 out->out.head_run = NULL;
183 out->out.left = 0;
184 out->out.total = 0;
185
186 while ((seg = out->err.head_seg))
187 {
188 out->err.head_seg = seg->next;
189 free (seg);
190 }
191 out->err.tail_seg = NULL;
192 out->err.tail_run = NULL;
193 out->err.head_run = NULL;
194 out->err.left = 0;
195 out->err.total = 0;
196
197 out->seqno = 0;
198 }
199 else
200 assert (out->out.head_seg == NULL && out->err.head_seg == NULL);
201}
202
203/* Writes up to LEN bytes to the given segment.
204 Returns how much was actually written. */
205static size_t
206membuf_write_segment (struct output_membuf *membuf, struct output_segment *seg,
207 const char *src, size_t len, unsigned int *pseqno)
208{
209 size_t written = 0;
210 if (seg && membuf->left > 0)
211 {
212 struct output_run *run = membuf->tail_run;
213 char *dst = (char *)(run + 1) + run->len;
214 assert ((uintptr_t)run - (uintptr_t)seg < seg->size);
215
216 /* If the sequence number didn't change, then we can append
217 to the current run without further considerations. */
218 if (run->seqno == *pseqno)
219 written = len;
220 /* If the current run does not end with a newline, don't start a new
221 run till we encounter one. */
222 else if (dst[-1] != '\n')
223 {
224 char const *srcnl = (const char *)memchr (src, '\n', len);
225 written = srcnl ? srcnl - src + 1 : len;
226 }
227 /* Try create a new empty run and append to it. */
228 else
229 {
230 size_t const offnextrun = ( (uintptr_t)dst - (uintptr_t)(seg)
231 + sizeof(void *) - 1)
232 & ~(sizeof(void *) - 1);
233 if (offnextrun > seg->size - sizeof (struct output_run) * 2)
234 return 0; /* need new segment */
235
236 run = run->next = (struct output_run *)((char *)seg + offnextrun);
237 run->next = NULL;
238 run->seqno = ++(*pseqno);
239 run->len = 0;
240 membuf->tail_run = run;
241 membuf->left = seg->size - (offnextrun + sizeof (*run));
242 dst = (char *)(run + 1);
243 written = len;
244 }
245
246 /* Append to the current run. */
247 if (written > membuf->left)
248 written = membuf->left;
249 memcpy (dst, src, written);
250 run->len += written;
251 membuf->left -= written;
252 }
253 return written;
254}
255
256/* Helper for membuf_write_new_segment and membuf_dump_most that figures out
257 now much data needs to be moved from the previous run in order to make it
258 end with a newline. */
259static size_t membuf_calc_move_len (struct output_run *tail_run)
260{
261 size_t to_move = 0;
262 if (tail_run)
263 {
264 const char *data = (const char *)(tail_run + 1);
265 size_t off = tail_run->len;
266 while (off > 0 && data[off - 1] != '\n')
267 off--;
268 to_move = tail_run->len - off;
269 if (to_move >= MEMBUF_MAX_MOVE_LEN)
270 to_move = 0;
271 }
272 return to_move;
273}
274
275/* Allocates a new segment and writes to it.
276 This will take care to make sure the previous run terminates with
277 a newline so that we pass whole lines to fwrite when dumping. */
278static size_t
279membuf_write_new_segment (struct output_membuf *membuf, const char *src,
280 size_t len, unsigned int *pseqno)
281{
282 struct output_run *prev_run = membuf->tail_run;
283 struct output_segment *prev_seg = membuf->tail_seg;
284 size_t const to_move = membuf_calc_move_len (prev_run);
285 struct output_segment *new_seg;
286 size_t written;
287 char *dst;
288
289 /* Figure the the segment size. We start with MEMBUF_MIN_SEG_SIZE and double
290 it each time till we reach MEMBUF_MAX_SEG_SIZE. */
291 size_t const offset_runs = offsetof (struct output_segment, runs);
292 size_t segsize = !prev_seg ? MEMBUF_MIN_SEG_SIZE
293 : prev_seg->size >= MEMBUF_MAX_SEG_SIZE ? MEMBUF_MAX_SEG_SIZE
294 : prev_seg->size * 2;
295 while ( segsize < to_move + len + offset_runs + sizeof (struct output_run) * 2
296 && segsize < MEMBUF_MAX_SEG_SIZE)
297 segsize *= 2;
298
299 /* Allocate the segment and link it and the first run. */
300 new_seg = (struct output_segment *)xmalloc (segsize);
301 new_seg->size = segsize;
302 new_seg->next = NULL;
303 new_seg->runs[0].next = NULL;
304 if (!prev_seg)
305 {
306 membuf->head_seg = new_seg;
307 membuf->head_run = &new_seg->runs[0];
308 }
309 else
310 {
311 prev_seg->next = new_seg;
312 prev_run->next = &new_seg->runs[0];
313 }
314 membuf->tail_seg = new_seg;
315 membuf->tail_run = &new_seg->runs[0];
316 membuf->total += segsize;
317 membuf->left = segsize - sizeof (struct output_run) - offset_runs;
318
319 /* Initialize and write data to the first run. */
320 dst = (char *)&new_seg->runs[0]; /* Try bypass gcc array size cleverness. */
321 dst += sizeof (struct output_run);
322 assert (MEMBUF_MAX_MOVE_LEN < MEMBUF_MIN_SEG_SIZE);
323 if (to_move > 0)
324 {
325 /* Move to_move bytes from the previous run in hope that we'll get a
326 newline to soon. Afterwards call membuf_segment_write to work SRC. */
327 assert (prev_run != NULL);
328 assert (membuf->left >= to_move);
329 prev_run->len -= to_move;
330 new_seg->runs[0].len = to_move;
331 new_seg->runs[0].seqno = prev_run->seqno;
332 memcpy (dst, (const char *)(prev_run + 1) + prev_run->len, to_move);
333 membuf->left -= to_move;
334
335 written = membuf_write_segment (membuf, new_seg, src, len, pseqno);
336 }
337 else
338 {
339 /* Create a run with up to LEN from SRC. */
340 written = len;
341 if (written > membuf->left)
342 written = membuf->left;
343 new_seg->runs[0].len = written;
344 new_seg->runs[0].seqno = ++(*pseqno);
345 memcpy (dst, src, written);
346 membuf->left -= written;
347 }
348 return written;
349}
350
351/* Worker for output_write that will dump most of the output when we hit
352 MEMBUF_MAX_TOTAL on either of the two membuf structures, then free all the
353 output segments. Incomplete lines will be held over to the next buffers
354 and copied into new segments. */
355static void
356membuf_dump_most (struct output *out)
357{
358 size_t out_to_move = membuf_calc_move_len (out->out.tail_run);
359 size_t err_to_move = membuf_calc_move_len (out->err.tail_run);
360 if (!out_to_move && !err_to_move)
361 membuf_dump (out);
362 else
363 {
364 /* Allocate a stack buffer for holding incomplete lines. This should be
365 fine since we're only talking about max 2 * MEMBUF_MAX_MOVE_LEN.
366 The -1 on the sequence numbers, ise because membuf_write_new_segment
367 will increment them before use. */
368 unsigned int out_seqno = out_to_move ? out->out.tail_run->seqno - 1 : 0;
369 unsigned int err_seqno = err_to_move ? out->err.tail_run->seqno - 1 : 0;
370 char *tmp = alloca (out_to_move + err_to_move);
371 if (out_to_move)
372 {
373 out->out.tail_run->len -= out_to_move;
374 memcpy (tmp,
375 (char *)(out->out.tail_run + 1) + out->out.tail_run->len,
376 out_to_move);
377 }
378 if (err_to_move)
379 {
380 out->err.tail_run->len -= err_to_move;
381 memcpy (tmp + out_to_move,
382 (char *)(out->err.tail_run + 1) + out->err.tail_run->len,
383 err_to_move);
384 }
385
386 membuf_dump (out);
387
388 if (out_to_move)
389 {
390 size_t written = membuf_write_new_segment (&out->out, tmp,
391 out_to_move, &out_seqno);
392 assert (written == out_to_move); (void)written;
393 }
394 if (err_to_move)
395 {
396 size_t written = membuf_write_new_segment (&out->err,
397 tmp + out_to_move,
398 err_to_move, &err_seqno);
399 assert (written == err_to_move); (void)written;
400 }
401 }
402}
403
404
405
406/* write/fwrite like function, binary mode. */
407ssize_t
408output_write_bin (struct output *out, int is_err, const char *src, size_t len)
409{
410 size_t ret = len;
411 if (!out || !out->syncout)
412 {
413 FILE *f = is_err ? stderr : stdout;
414# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
415 /* On DOS platforms we need to disable \n -> \r\n converts that is common on
416 standard output/error. Also optimize for console output. */
417 int saved_errno;
418 int fd = fileno (f);
419 int prev_mode = _setmode (fd, _O_BINARY);
420 maybe_con_fwrite (src, len, 1, f);
421 if (fflush (f) == EOF)
422 ret = -1;
423 saved_errno = errno;
424 _setmode (fd, prev_mode);
425 errno = saved_errno;
426# else
427 fwrite (src, len, 1, f);
428 if (fflush (f) == EOF)
429 ret = -1;
430# endif
431 }
432 else
433 {
434 struct output_membuf *membuf = is_err ? &out->err : &out->out;
435 while (len > 0)
436 {
437 size_t runlen = membuf_write_segment (membuf, membuf->tail_seg, src, len, &out->seqno);
438 if (!runlen)
439 {
440 if (membuf->total < MEMBUF_MAX_TOTAL)
441 runlen = membuf_write_new_segment (membuf, src, len, &out->seqno);
442 else
443 membuf_dump_most (out);
444 }
445 /* advance */
446 len -= runlen;
447 src += runlen;
448 }
449 }
450 return ret;
451}
452
453#endif /* CONFIG_WITH_OUTPUT_IN_MEMORY */
454
455/* write/fwrite like function, text mode. */
456ssize_t
457output_write_text (struct output *out, int is_err, const char *src, size_t len)
458{
459#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
460# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
461 ssize_t ret = len;
462 if (!out || !out->syncout)
463 {
464 /* ASSUME fwrite does the desired conversion. */
465 FILE *f = is_err ? stderr : stdout;
466# ifdef KBUILD_OS_WINDOWS
467 if (maybe_con_fwrite (src, len, 1, f) < 0)
468 ret = -1;
469# else
470 fwrite (src, len, 1, f);
471# endif
472 if (fflush (f) == EOF)
473 ret = -1;
474 }
475 else
476 {
477 /* Work the buffer line by line, replacing each \n with \r\n. */
478 while (len > 0)
479 {
480 const char *nl = memchr ( src, '\n', len);
481 size_t line_len = nl ? nl - src : len;
482 output_write_bin (out, is_err, src, line_len);
483 if (!nl)
484 break;
485 output_write_bin (out, is_err, "\r\n", 2);
486 len -= line_len + 1;
487 src += line_len + 1;
488 }
489 }
490 return ret;
491# else
492 return output_write_bin (out, is_err, src, len);
493# endif
494#else
495 ssize_t ret = len;
496 if (! out || ! out->syncout)
497 {
498 FILE *f = is_err ? stderr : stdout;
499# ifdef KBUILD_OS_WINDOWS
500 maybe_con_fwrite(src, len, 1, f);
501# else
502 fwrite (src, len, 1, f);
503# endif
504 fflush (f);
505 }
506 else
507 {
508 int fd = is_err ? out->err : out->out;
509 int r;
510
511 EINTRLOOP (r, lseek (fd, 0, SEEK_END));
512 while (1)
513 {
514 EINTRLOOP (r, write (fd, src, len));
515 if (r == len || r <= 0)
516 break;
517 len -= r;
518 src += r;
519 }
520 }
521 return ret;
522#endif
523}
524
525
526
527/* Write a string to the current STDOUT or STDERR. */
528static void
529_outputs (struct output *out, int is_err, const char *msg)
530{
531#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
532 output_write_text (out, is_err, msg, strlen (msg));
533#else /* !CONFIG_WITH_OUTPUT_IN_MEMORY */
534 if (! out || ! out->syncout)
535 {
536 FILE *f = is_err ? stderr : stdout;
537# ifdef KBUILD_OS_WINDOWS
538 maybe_con_fwrite(msg, strlen(msg), 1, f);
539# else
540 fputs (msg, f);
541# endif
542 fflush (f);
543 }
544 else
545 {
546 int fd = is_err ? out->err : out->out;
547 int len = strlen (msg);
548 int r;
549
550 EINTRLOOP (r, lseek (fd, 0, SEEK_END));
551 while (1)
552 {
553 EINTRLOOP (r, write (fd, msg, len));
554 if (r == len || r <= 0)
555 break;
556 len -= r;
557 msg += r;
558 }
559 }
560#endif /* !CONFIG_WITH_OUTPUT_IN_MEMORY */
561}
562
563
564/* Write a message indicating that we've just entered or
565 left (according to ENTERING) the current directory. */
566
567static int
568log_working_directory (int entering)
569{
570 static char *buf = NULL;
571 static unsigned int len = 0;
572 unsigned int need;
573 const char *fmt;
574 char *p;
575
576 /* Get enough space for the longest possible output. */
577 need = strlen (program) + INTSTR_LENGTH + 2 + 1;
578 if (starting_directory)
579 need += strlen (starting_directory);
580
581 /* Use entire sentences to give the translators a fighting chance. */
582 if (makelevel == 0)
583 if (starting_directory == 0)
584 if (entering)
585 fmt = _("%s: Entering an unknown directory\n");
586 else
587 fmt = _("%s: Leaving an unknown directory\n");
588 else
589 if (entering)
590 fmt = _("%s: Entering directory '%s'\n");
591 else
592 fmt = _("%s: Leaving directory '%s'\n");
593 else
594 if (starting_directory == 0)
595 if (entering)
596 fmt = _("%s[%u]: Entering an unknown directory\n");
597 else
598 fmt = _("%s[%u]: Leaving an unknown directory\n");
599 else
600 if (entering)
601 fmt = _("%s[%u]: Entering directory '%s'\n");
602 else
603 fmt = _("%s[%u]: Leaving directory '%s'\n");
604
605 need += strlen (fmt);
606
607 if (need > len)
608 {
609 buf = xrealloc (buf, need);
610 len = need;
611 }
612
613 p = buf;
614 if (print_data_base_flag)
615 {
616 *(p++) = '#';
617 *(p++) = ' ';
618 }
619
620 if (makelevel == 0)
621 if (starting_directory == 0)
622 sprintf (p, fmt , program);
623 else
624 sprintf (p, fmt, program, starting_directory);
625 else if (starting_directory == 0)
626 sprintf (p, fmt, program, makelevel);
627 else
628 sprintf (p, fmt, program, makelevel, starting_directory);
629
630 _outputs (NULL, 0, buf);
631
632 return 1;
633}
634
635/* Set a file descriptor to be in O_APPEND mode.
636 If it fails, just ignore it. */
637
638static void
639set_append_mode (int fd)
640{
641#if defined(F_GETFL) && defined(F_SETFL) && defined(O_APPEND)
642 int flags = fcntl (fd, F_GETFL, 0);
643 if (flags >= 0)
644 fcntl (fd, F_SETFL, flags | O_APPEND);
645#endif
646}
647
648
649
650#ifndef NO_OUTPUT_SYNC
651
652/* Semaphore for use in -j mode with output_sync. */
653static sync_handle_t sync_handle = -1;
654
655#define FD_NOT_EMPTY(_f) ((_f) != OUTPUT_NONE && lseek ((_f), 0, SEEK_END) > 0)
656
657/* Set up the sync handle. Disables output_sync on error. */
658static int
659sync_init (void)
660{
661 int combined_output = 0;
662
663#ifdef WINDOWS32
664# ifdef CONFIG_NEW_WIN_CHILDREN
665 if (STREAM_OK (stdout))
666 {
667 if (STREAM_OK (stderr))
668 {
669 char mtxname[256];
670 sync_handle = create_mutex (mtxname, sizeof (mtxname));
671 if (sync_handle != -1)
672 {
673 prepare_mutex_handle_string (mtxname);
674 return same_stream (stdout, stderr);
675 }
676 perror_with_name ("output-sync suppressed: ", "create_mutex");
677 }
678 else
679 perror_with_name ("output-sync suppressed: ", "stderr");
680 }
681 else
682 perror_with_name ("output-sync suppressed: ", "stdout");
683 output_sync = OUTPUT_SYNC_NONE;
684
685# else /* !CONFIG_NEW_WIN_CHILDREN */
686 if ((!STREAM_OK (stdout) && !STREAM_OK (stderr))
687 || (sync_handle = create_mutex ()) == -1)
688 {
689 perror_with_name ("output-sync suppressed: ", "stderr");
690 output_sync = 0;
691 }
692 else
693 {
694 combined_output = same_stream (stdout, stderr);
695 prepare_mutex_handle_string (sync_handle);
696 }
697# endif /* !CONFIG_NEW_WIN_CHILDREN */
698
699#else
700 if (STREAM_OK (stdout))
701 {
702 struct stat stbuf_o, stbuf_e;
703
704 sync_handle = fileno (stdout);
705 combined_output = (fstat (fileno (stdout), &stbuf_o) == 0
706 && fstat (fileno (stderr), &stbuf_e) == 0
707 && stbuf_o.st_dev == stbuf_e.st_dev
708 && stbuf_o.st_ino == stbuf_e.st_ino);
709 }
710 else if (STREAM_OK (stderr))
711 sync_handle = fileno (stderr);
712 else
713 {
714 perror_with_name ("output-sync suppressed: ", "stderr");
715 output_sync = 0;
716 }
717#endif
718
719 return combined_output;
720}
721
722#ifndef CONFIG_WITH_OUTPUT_IN_MEMORY
723/* Support routine for output_sync() */
724static void
725pump_from_tmp (int from, FILE *to)
726{
727# ifdef KMK
728 char buffer[8192];
729# else
730 static char buffer[8192];
731#endif
732
733# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
734 int prev_mode;
735
736 /* "from" is opened by open_tmpfd, which does it in binary mode, so
737 we need the mode of "to" to match that. */
738 prev_mode = _setmode (fileno (to), _O_BINARY);
739#endif
740
741 if (lseek (from, 0, SEEK_SET) == -1)
742 perror ("lseek()");
743
744 while (1)
745 {
746 int len;
747 EINTRLOOP (len, read (from, buffer, sizeof (buffer)));
748 if (len < 0)
749 perror ("read()");
750 if (len <= 0)
751 break;
752 if (fwrite (buffer, len, 1, to) < 1)
753 {
754 perror ("fwrite()");
755 break;
756 }
757 fflush (to);
758 }
759
760# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
761 /* Switch "to" back to its original mode, so that log messages by
762 Make have the same EOL format as without --output-sync. */
763 _setmode (fileno (to), prev_mode);
764#endif
765}
766#endif /* CONFIG_WITH_OUTPUT_IN_MEMORY */
767
768/* Obtain the lock for writing output. */
769static void *
770acquire_semaphore (void)
771{
772 static struct flock fl;
773
774 fl.l_type = F_WRLCK;
775 fl.l_whence = SEEK_SET;
776 fl.l_start = 0;
777 fl.l_len = 1;
778 if (fcntl (sync_handle, F_SETLKW, &fl) != -1)
779 return &fl;
780 perror ("fcntl()");
781 return NULL;
782}
783
784/* Release the lock for writing output. */
785static void
786release_semaphore (void *sem)
787{
788 struct flock *flp = (struct flock *)sem;
789 flp->l_type = F_UNLCK;
790 if (fcntl (sync_handle, F_SETLKW, flp) == -1)
791 perror ("fcntl()");
792}
793
794#ifndef CONFIG_WITH_OUTPUT_IN_MEMORY
795
796/* Returns a file descriptor to a temporary file. The file is automatically
797 closed/deleted on exit. Don't use a FILE* stream. */
798int
799output_tmpfd (void)
800{
801 int fd = -1;
802 FILE *tfile = tmpfile ();
803
804 if (! tfile)
805 pfatal_with_name ("tmpfile");
806
807 /* Create a duplicate so we can close the stream. */
808 fd = dup (fileno (tfile));
809 if (fd < 0)
810 pfatal_with_name ("dup");
811
812 fclose (tfile);
813
814 set_append_mode (fd);
815
816 return fd;
817}
818
819/* Adds file descriptors to the child structure to support output_sync; one
820 for stdout and one for stderr as long as they are open. If stdout and
821 stderr share a device they can share a temp file too.
822 Will reset output_sync on error. */
823static void
824setup_tmpfile (struct output *out)
825{
826 /* Is make's stdout going to the same place as stderr? */
827 static int combined_output = -1;
828
829 if (combined_output < 0)
830 combined_output = sync_init ();
831
832 if (STREAM_OK (stdout))
833 {
834 int fd = output_tmpfd ();
835 if (fd < 0)
836 goto error;
837 CLOSE_ON_EXEC (fd);
838 out->out = fd;
839 }
840
841 if (STREAM_OK (stderr))
842 {
843 if (out->out != OUTPUT_NONE && combined_output)
844 out->err = out->out;
845 else
846 {
847 int fd = output_tmpfd ();
848 if (fd < 0)
849 goto error;
850 CLOSE_ON_EXEC (fd);
851 out->err = fd;
852 }
853 }
854
855 return;
856
857 /* If we failed to create a temp file, disable output sync going forward. */
858 error:
859 output_close (out);
860 output_sync = OUTPUT_SYNC_NONE;
861}
862
863#endif /* CONFIG_WITH_OUTPUT_IN_MEMORY */
864
865/* Synchronize the output of jobs in -j mode to keep the results of
866 each job together. This is done by holding the results in temp files,
867 one for stdout and potentially another for stderr, and only releasing
868 them to "real" stdout/stderr when a semaphore can be obtained. */
869
870void
871output_dump (struct output *out)
872{
873#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
874 membuf_dump (out);
875#else
876 int outfd_not_empty = FD_NOT_EMPTY (out->out);
877 int errfd_not_empty = FD_NOT_EMPTY (out->err);
878
879 if (outfd_not_empty || errfd_not_empty)
880 {
881 int traced = 0;
882
883 /* Try to acquire the semaphore. If it fails, dump the output
884 unsynchronized; still better than silently discarding it.
885 We want to keep this lock for as little time as possible. */
886 void *sem = acquire_semaphore ();
887
888 /* Log the working directory for this dump. */
889 if (print_directory_flag && output_sync != OUTPUT_SYNC_RECURSE)
890 traced = log_working_directory (1);
891
892 if (outfd_not_empty)
893 pump_from_tmp (out->out, stdout);
894 if (errfd_not_empty && out->err != out->out)
895 pump_from_tmp (out->err, stderr);
896
897 if (traced)
898 log_working_directory (0);
899
900 /* Exit the critical section. */
901 if (sem)
902 release_semaphore (sem);
903
904 /* Truncate and reset the output, in case we use it again. */
905 if (out->out != OUTPUT_NONE)
906 {
907 int e;
908 lseek (out->out, 0, SEEK_SET);
909 EINTRLOOP (e, ftruncate (out->out, 0));
910 }
911 if (out->err != OUTPUT_NONE && out->err != out->out)
912 {
913 int e;
914 lseek (out->err, 0, SEEK_SET);
915 EINTRLOOP (e, ftruncate (out->err, 0));
916 }
917 }
918#endif
919}
920#endif /* NO_OUTPUT_SYNC */
921
922
923
924/* Provide support for temporary files. */
925
926#ifndef HAVE_STDLIB_H
927# ifdef HAVE_MKSTEMP
928int mkstemp (char *template);
929# else
930char *mktemp (char *template);
931# endif
932#endif
933
934FILE *
935output_tmpfile (char **name, const char *template)
936{
937#ifdef HAVE_FDOPEN
938 int fd;
939#endif
940
941#if defined HAVE_MKSTEMP || defined HAVE_MKTEMP
942# define TEMPLATE_LEN strlen (template)
943#else
944# define TEMPLATE_LEN L_tmpnam
945#endif
946 *name = xmalloc (TEMPLATE_LEN + 1);
947 strcpy (*name, template);
948
949#if defined HAVE_MKSTEMP && defined HAVE_FDOPEN
950 /* It's safest to use mkstemp(), if we can. */
951 fd = mkstemp (*name);
952 if (fd == -1)
953 return 0;
954 return fdopen (fd, "w");
955#else
956# ifdef HAVE_MKTEMP
957 (void) mktemp (*name);
958# else
959 (void) tmpnam (*name);
960# endif
961
962# ifdef HAVE_FDOPEN
963 /* Can't use mkstemp(), but guard against a race condition. */
964 EINTRLOOP (fd, open (*name, O_CREAT|O_EXCL|O_WRONLY, 0600));
965 if (fd == -1)
966 return 0;
967 return fdopen (fd, "w");
968# else
969 /* Not secure, but what can we do? */
970 return fopen (*name, "w");
971# endif
972#endif
973}
974
975
976
977/* This code is stolen from gnulib.
978 If/when we abandon the requirement to work with K&R compilers, we can
979 remove this (and perhaps other parts of GNU make!) and migrate to using
980 gnulib directly.
981
982 This is called only through atexit(), which means die() has already been
983 invoked. So, call exit() here directly. Apparently that works...?
984*/
985
986/* Close standard output, exiting with status 'exit_failure' on failure.
987 If a program writes *anything* to stdout, that program should close
988 stdout and make sure that it succeeds before exiting. Otherwise,
989 suppose that you go to the extreme of checking the return status
990 of every function that does an explicit write to stdout. The last
991 printf can succeed in writing to the internal stream buffer, and yet
992 the fclose(stdout) could still fail (due e.g., to a disk full error)
993 when it tries to write out that buffered data. Thus, you would be
994 left with an incomplete output file and the offending program would
995 exit successfully. Even calling fflush is not always sufficient,
996 since some file systems (NFS and CODA) buffer written/flushed data
997 until an actual close call.
998
999 Besides, it's wasteful to check the return value from every call
1000 that writes to stdout -- just let the internal stream state record
1001 the failure. That's what the ferror test is checking below.
1002
1003 It's important to detect such failures and exit nonzero because many
1004 tools (most notably 'make' and other build-management systems) depend
1005 on being able to detect failure in other tools via their exit status. */
1006
1007static void
1008close_stdout (void)
1009{
1010 int prev_fail = ferror (stdout);
1011 int fclose_fail = fclose (stdout);
1012
1013 if (prev_fail || fclose_fail)
1014 {
1015 if (fclose_fail)
1016 perror_with_name (_("write error: stdout"), "");
1017 else
1018 O (error, NILF, _("write error: stdout"));
1019 exit (MAKE_TROUBLE);
1020 }
1021}
1022
1023
1024
1025void
1026output_init (struct output *out)
1027{
1028 if (out)
1029 {
1030#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
1031 out->out.head_seg = NULL;
1032 out->out.tail_seg = NULL;
1033 out->out.head_run = NULL;
1034 out->out.tail_run = NULL;
1035 out->err.head_seg = NULL;
1036 out->err.tail_seg = NULL;
1037 out->err.head_run = NULL;
1038 out->err.tail_run = NULL;
1039 out->err.total = 0;
1040 out->out.total = 0;
1041 out->seqno = 0;
1042#else
1043 out->out = out->err = OUTPUT_NONE;
1044#endif
1045 out->syncout = !!output_sync;
1046 return;
1047 }
1048
1049 /* Configure this instance of make. Be sure stdout is line-buffered. */
1050
1051#ifdef HAVE_SETVBUF
1052# ifdef SETVBUF_REVERSED
1053 setvbuf (stdout, _IOLBF, xmalloc (BUFSIZ), BUFSIZ);
1054# else /* setvbuf not reversed. */
1055 /* Some buggy systems lose if we pass 0 instead of allocating ourselves. */
1056 setvbuf (stdout, 0, _IOLBF, BUFSIZ);
1057# endif /* setvbuf reversed. */
1058#elif HAVE_SETLINEBUF
1059 setlinebuf (stdout);
1060#endif /* setlinebuf missing. */
1061
1062 /* Force stdout/stderr into append mode. This ensures parallel jobs won't
1063 lose output due to overlapping writes. */
1064 set_append_mode (fileno (stdout));
1065 set_append_mode (fileno (stderr));
1066
1067#ifdef HAVE_ATEXIT
1068 if (STREAM_OK (stdout))
1069 atexit (close_stdout);
1070#endif
1071}
1072
1073void
1074output_close (struct output *out)
1075{
1076 if (! out)
1077 {
1078 if (stdio_traced)
1079 log_working_directory (0);
1080 return;
1081 }
1082
1083#ifndef NO_OUTPUT_SYNC
1084 output_dump (out);
1085#endif
1086
1087#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
1088 assert (out->out.total == 0);
1089 assert (out->out.head_seg == NULL);
1090 assert (out->err.total == 0);
1091 assert (out->err.head_seg == NULL);
1092#else
1093 if (out->out >= 0)
1094 close (out->out);
1095 if (out->err >= 0 && out->err != out->out)
1096 close (out->err);
1097#endif
1098
1099 output_init (out);
1100}
1101
1102/* We're about to generate output: be sure it's set up. */
1103void
1104output_start (void)
1105{
1106#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
1107 /* If we're syncing output make sure the sempahore (win) is set up. */
1108 if (output_context && output_context->syncout)
1109 if (combined_output < 0)
1110 combined_output = sync_init ();
1111#else
1112#ifndef NO_OUTPUT_SYNC
1113 /* If we're syncing output make sure the temporary file is set up. */
1114 if (output_context && output_context->syncout)
1115 if (! OUTPUT_ISSET(output_context))
1116 setup_tmpfile (output_context);
1117#endif
1118#endif
1119
1120#ifndef KMK
1121 /* If we're not syncing this output per-line or per-target, make sure we emit
1122 the "Entering..." message where appropriate. */
1123 if (output_sync == OUTPUT_SYNC_NONE || output_sync == OUTPUT_SYNC_RECURSE)
1124#else
1125 /* Indiscriminately output "Entering..." and "Leaving..." message for each
1126 command line or target is plain annoying! And when there is no recursion
1127 it's actually inappropriate. Haven't got a simple way of detecting that,
1128 so back to the old behavior for now. [bird] */
1129#endif
1130 if (! stdio_traced && print_directory_flag)
1131 stdio_traced = log_working_directory (1);
1132}
1133
1134void
1135outputs (int is_err, const char *msg)
1136{
1137 if (! msg || *msg == '\0')
1138 return;
1139
1140 output_start ();
1141
1142 _outputs (output_context, is_err, msg);
1143}
1144
1145
1146
1147static struct fmtstring
1148 {
1149 char *buffer;
1150 size_t size;
1151 } fmtbuf = { NULL, 0 };
1152
1153static char *
1154get_buffer (size_t need)
1155{
1156 /* Make sure we have room. NEED includes space for \0. */
1157 if (need > fmtbuf.size)
1158 {
1159 fmtbuf.size += need * 2;
1160 fmtbuf.buffer = xrealloc (fmtbuf.buffer, fmtbuf.size);
1161 }
1162
1163 fmtbuf.buffer[need-1] = '\0';
1164
1165 return fmtbuf.buffer;
1166}
1167
1168/* Print a message on stdout. */
1169
1170void
1171message (int prefix, size_t len, const char *fmt, ...)
1172{
1173 va_list args;
1174 char *p;
1175
1176 len += strlen (fmt) + strlen (program) + INTSTR_LENGTH + 4 + 1 + 1;
1177 p = get_buffer (len);
1178
1179 if (prefix)
1180 {
1181 if (makelevel == 0)
1182 sprintf (p, "%s: ", program);
1183 else
1184 sprintf (p, "%s[%u]: ", program, makelevel);
1185 p += strlen (p);
1186 }
1187
1188 va_start (args, fmt);
1189 vsprintf (p, fmt, args);
1190 va_end (args);
1191
1192 strcat (p, "\n");
1193
1194 assert (fmtbuf.buffer[len-1] == '\0');
1195 outputs (0, fmtbuf.buffer);
1196}
1197
1198/* Print an error message. */
1199
1200void
1201error (const floc *flocp, size_t len, const char *fmt, ...)
1202{
1203 va_list args;
1204 char *p;
1205
1206 len += (strlen (fmt) + strlen (program)
1207 + (flocp && flocp->filenm ? strlen (flocp->filenm) : 0)
1208 + INTSTR_LENGTH + 4 + 1 + 1);
1209 p = get_buffer (len);
1210
1211 if (flocp && flocp->filenm)
1212 sprintf (p, "%s:%lu: ", flocp->filenm, flocp->lineno + flocp->offset);
1213 else if (makelevel == 0)
1214 sprintf (p, "%s: ", program);
1215 else
1216 sprintf (p, "%s[%u]: ", program, makelevel);
1217 p += strlen (p);
1218
1219 va_start (args, fmt);
1220 vsprintf (p, fmt, args);
1221 va_end (args);
1222
1223 strcat (p, "\n");
1224
1225 assert (fmtbuf.buffer[len-1] == '\0');
1226 outputs (1, fmtbuf.buffer);
1227}
1228
1229/* Print an error message and exit. */
1230
1231void
1232fatal (const floc *flocp, size_t len, const char *fmt, ...)
1233{
1234 va_list args;
1235 const char *stop = _(". Stop.\n");
1236 char *p;
1237
1238 len += (strlen (fmt) + strlen (program)
1239 + (flocp && flocp->filenm ? strlen (flocp->filenm) : 0)
1240 + INTSTR_LENGTH + 8 + strlen (stop) + 1);
1241 p = get_buffer (len);
1242
1243 if (flocp && flocp->filenm)
1244 sprintf (p, "%s:%lu: *** ", flocp->filenm, flocp->lineno + flocp->offset);
1245 else if (makelevel == 0)
1246 sprintf (p, "%s: *** ", program);
1247 else
1248 sprintf (p, "%s[%u]: *** ", program, makelevel);
1249 p += strlen (p);
1250
1251 va_start (args, fmt);
1252 vsprintf (p, fmt, args);
1253 va_end (args);
1254
1255 strcat (p, stop);
1256
1257 assert (fmtbuf.buffer[len-1] == '\0');
1258 outputs (1, fmtbuf.buffer);
1259
1260 die (MAKE_FAILURE);
1261}
1262
1263/* Print an error message from errno. */
1264
1265void
1266perror_with_name (const char *str, const char *name)
1267{
1268 const char *err = strerror (errno);
1269 OSSS (error, NILF, _("%s%s: %s"), str, name, err);
1270}
1271
1272/* Print an error message from errno and exit. */
1273
1274void
1275pfatal_with_name (const char *name)
1276{
1277 const char *err = strerror (errno);
1278 OSS (fatal, NILF, _("%s: %s"), name, err);
1279
1280 /* NOTREACHED */
1281}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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