VirtualBox

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

Last change on this file since 3273 was 3273, checked in by bird, 6 years ago

kmk: OS/2 build fixes

  • Property svn:eol-style set to native
File size: 34.6 KB
Line 
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 ((size_t)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#ifdef KBUILD_OS_DARWIN /* F_SETLKW isn't supported on pipes */
781 if (errno != EBADF)
782#endif
783 perror ("fcntl()");
784 return NULL;
785}
786
787/* Release the lock for writing output. */
788static void
789release_semaphore (void *sem)
790{
791 struct flock *flp = (struct flock *)sem;
792 flp->l_type = F_UNLCK;
793 if (fcntl (sync_handle, F_SETLKW, flp) == -1)
794 perror ("fcntl()");
795}
796
797#ifndef CONFIG_WITH_OUTPUT_IN_MEMORY
798
799/* Returns a file descriptor to a temporary file. The file is automatically
800 closed/deleted on exit. Don't use a FILE* stream. */
801int
802output_tmpfd (void)
803{
804 int fd = -1;
805 FILE *tfile = tmpfile ();
806
807 if (! tfile)
808 pfatal_with_name ("tmpfile");
809
810 /* Create a duplicate so we can close the stream. */
811 fd = dup (fileno (tfile));
812 if (fd < 0)
813 pfatal_with_name ("dup");
814
815 fclose (tfile);
816
817 set_append_mode (fd);
818
819 return fd;
820}
821
822/* Adds file descriptors to the child structure to support output_sync; one
823 for stdout and one for stderr as long as they are open. If stdout and
824 stderr share a device they can share a temp file too.
825 Will reset output_sync on error. */
826static void
827setup_tmpfile (struct output *out)
828{
829 /* Is make's stdout going to the same place as stderr? */
830 static int combined_output = -1;
831
832 if (combined_output < 0)
833 combined_output = sync_init ();
834
835 if (STREAM_OK (stdout))
836 {
837 int fd = output_tmpfd ();
838 if (fd < 0)
839 goto error;
840 CLOSE_ON_EXEC (fd);
841 out->out = fd;
842 }
843
844 if (STREAM_OK (stderr))
845 {
846 if (out->out != OUTPUT_NONE && combined_output)
847 out->err = out->out;
848 else
849 {
850 int fd = output_tmpfd ();
851 if (fd < 0)
852 goto error;
853 CLOSE_ON_EXEC (fd);
854 out->err = fd;
855 }
856 }
857
858 return;
859
860 /* If we failed to create a temp file, disable output sync going forward. */
861 error:
862 output_close (out);
863 output_sync = OUTPUT_SYNC_NONE;
864}
865
866#endif /* CONFIG_WITH_OUTPUT_IN_MEMORY */
867
868/* Synchronize the output of jobs in -j mode to keep the results of
869 each job together. This is done by holding the results in temp files,
870 one for stdout and potentially another for stderr, and only releasing
871 them to "real" stdout/stderr when a semaphore can be obtained. */
872
873void
874output_dump (struct output *out)
875{
876#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
877 membuf_dump (out);
878#else
879 int outfd_not_empty = FD_NOT_EMPTY (out->out);
880 int errfd_not_empty = FD_NOT_EMPTY (out->err);
881
882 if (outfd_not_empty || errfd_not_empty)
883 {
884 int traced = 0;
885
886 /* Try to acquire the semaphore. If it fails, dump the output
887 unsynchronized; still better than silently discarding it.
888 We want to keep this lock for as little time as possible. */
889 void *sem = acquire_semaphore ();
890
891# ifndef KMK /* this drives me bananas. */
892 /* Log the working directory for this dump. */
893 if (print_directory_flag && output_sync != OUTPUT_SYNC_RECURSE)
894 traced = log_working_directory (1);
895# endif
896
897 if (outfd_not_empty)
898 pump_from_tmp (out->out, stdout);
899 if (errfd_not_empty && out->err != out->out)
900 pump_from_tmp (out->err, stderr);
901
902# ifndef KMK /* this drives me bananas. */
903 if (traced)
904 log_working_directory (0);
905# endif
906
907 /* Exit the critical section. */
908 if (sem)
909 release_semaphore (sem);
910
911 /* Truncate and reset the output, in case we use it again. */
912 if (out->out != OUTPUT_NONE)
913 {
914 int e;
915 lseek (out->out, 0, SEEK_SET);
916 EINTRLOOP (e, ftruncate (out->out, 0));
917 }
918 if (out->err != OUTPUT_NONE && out->err != out->out)
919 {
920 int e;
921 lseek (out->err, 0, SEEK_SET);
922 EINTRLOOP (e, ftruncate (out->err, 0));
923 }
924 }
925#endif
926}
927#endif /* NO_OUTPUT_SYNC */
928
929
930
931/* Provide support for temporary files. */
932
933#ifndef HAVE_STDLIB_H
934# ifdef HAVE_MKSTEMP
935int mkstemp (char *template);
936# else
937char *mktemp (char *template);
938# endif
939#endif
940
941FILE *
942output_tmpfile (char **name, const char *template)
943{
944#ifdef HAVE_FDOPEN
945 int fd;
946#endif
947
948#if defined HAVE_MKSTEMP || defined HAVE_MKTEMP
949# define TEMPLATE_LEN strlen (template)
950#else
951# define TEMPLATE_LEN L_tmpnam
952#endif
953 *name = xmalloc (TEMPLATE_LEN + 1);
954 strcpy (*name, template);
955
956#if defined HAVE_MKSTEMP && defined HAVE_FDOPEN
957 /* It's safest to use mkstemp(), if we can. */
958 fd = mkstemp (*name);
959 if (fd == -1)
960 return 0;
961 return fdopen (fd, "w");
962#else
963# ifdef HAVE_MKTEMP
964 (void) mktemp (*name);
965# else
966 (void) tmpnam (*name);
967# endif
968
969# ifdef HAVE_FDOPEN
970 /* Can't use mkstemp(), but guard against a race condition. */
971 EINTRLOOP (fd, open (*name, O_CREAT|O_EXCL|O_WRONLY, 0600));
972 if (fd == -1)
973 return 0;
974 return fdopen (fd, "w");
975# else
976 /* Not secure, but what can we do? */
977 return fopen (*name, "w");
978# endif
979#endif
980}
981
982
983
984/* This code is stolen from gnulib.
985 If/when we abandon the requirement to work with K&R compilers, we can
986 remove this (and perhaps other parts of GNU make!) and migrate to using
987 gnulib directly.
988
989 This is called only through atexit(), which means die() has already been
990 invoked. So, call exit() here directly. Apparently that works...?
991*/
992
993/* Close standard output, exiting with status 'exit_failure' on failure.
994 If a program writes *anything* to stdout, that program should close
995 stdout and make sure that it succeeds before exiting. Otherwise,
996 suppose that you go to the extreme of checking the return status
997 of every function that does an explicit write to stdout. The last
998 printf can succeed in writing to the internal stream buffer, and yet
999 the fclose(stdout) could still fail (due e.g., to a disk full error)
1000 when it tries to write out that buffered data. Thus, you would be
1001 left with an incomplete output file and the offending program would
1002 exit successfully. Even calling fflush is not always sufficient,
1003 since some file systems (NFS and CODA) buffer written/flushed data
1004 until an actual close call.
1005
1006 Besides, it's wasteful to check the return value from every call
1007 that writes to stdout -- just let the internal stream state record
1008 the failure. That's what the ferror test is checking below.
1009
1010 It's important to detect such failures and exit nonzero because many
1011 tools (most notably 'make' and other build-management systems) depend
1012 on being able to detect failure in other tools via their exit status. */
1013
1014static void
1015close_stdout (void)
1016{
1017 int prev_fail = ferror (stdout);
1018 int fclose_fail = fclose (stdout);
1019
1020 if (prev_fail || fclose_fail)
1021 {
1022 if (fclose_fail)
1023 perror_with_name (_("write error: stdout"), "");
1024 else
1025 O (error, NILF, _("write error: stdout"));
1026 exit (MAKE_TROUBLE);
1027 }
1028}
1029
1030
1031
1032void
1033output_init (struct output *out)
1034{
1035 if (out)
1036 {
1037#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
1038 out->out.head_seg = NULL;
1039 out->out.tail_seg = NULL;
1040 out->out.head_run = NULL;
1041 out->out.tail_run = NULL;
1042 out->err.head_seg = NULL;
1043 out->err.tail_seg = NULL;
1044 out->err.head_run = NULL;
1045 out->err.tail_run = NULL;
1046 out->err.total = 0;
1047 out->out.total = 0;
1048 out->seqno = 0;
1049#else
1050 out->out = out->err = OUTPUT_NONE;
1051#endif
1052 out->syncout = !!output_sync;
1053 return;
1054 }
1055
1056 /* Configure this instance of make. Be sure stdout is line-buffered. */
1057
1058#ifdef HAVE_SETVBUF
1059# ifdef SETVBUF_REVERSED
1060 setvbuf (stdout, _IOLBF, xmalloc (BUFSIZ), BUFSIZ);
1061# else /* setvbuf not reversed. */
1062 /* Some buggy systems lose if we pass 0 instead of allocating ourselves. */
1063 setvbuf (stdout, 0, _IOLBF, BUFSIZ);
1064# endif /* setvbuf reversed. */
1065#elif HAVE_SETLINEBUF
1066 setlinebuf (stdout);
1067#endif /* setlinebuf missing. */
1068
1069 /* Force stdout/stderr into append mode. This ensures parallel jobs won't
1070 lose output due to overlapping writes. */
1071 set_append_mode (fileno (stdout));
1072 set_append_mode (fileno (stderr));
1073
1074#ifdef HAVE_ATEXIT
1075 if (STREAM_OK (stdout))
1076 atexit (close_stdout);
1077#endif
1078}
1079
1080void
1081output_close (struct output *out)
1082{
1083 if (! out)
1084 {
1085 if (stdio_traced)
1086 log_working_directory (0);
1087 return;
1088 }
1089
1090#ifndef NO_OUTPUT_SYNC
1091 output_dump (out);
1092#endif
1093
1094#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
1095 assert (out->out.total == 0);
1096 assert (out->out.head_seg == NULL);
1097 assert (out->err.total == 0);
1098 assert (out->err.head_seg == NULL);
1099#else
1100 if (out->out >= 0)
1101 close (out->out);
1102 if (out->err >= 0 && out->err != out->out)
1103 close (out->err);
1104#endif
1105
1106 output_init (out);
1107}
1108
1109/* We're about to generate output: be sure it's set up. */
1110void
1111output_start (void)
1112{
1113#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
1114 /* If we're syncing output make sure the sempahore (win) is set up. */
1115 if (output_context && output_context->syncout)
1116 if (combined_output < 0)
1117 combined_output = sync_init ();
1118#else
1119#ifndef NO_OUTPUT_SYNC
1120 /* If we're syncing output make sure the temporary file is set up. */
1121 if (output_context && output_context->syncout)
1122 if (! OUTPUT_ISSET(output_context))
1123 setup_tmpfile (output_context);
1124#endif
1125#endif
1126
1127#ifndef KMK
1128 /* If we're not syncing this output per-line or per-target, make sure we emit
1129 the "Entering..." message where appropriate. */
1130 if (output_sync == OUTPUT_SYNC_NONE || output_sync == OUTPUT_SYNC_RECURSE)
1131#else
1132 /* Indiscriminately output "Entering..." and "Leaving..." message for each
1133 command line or target is plain annoying! And when there is no recursion
1134 it's actually inappropriate. Haven't got a simple way of detecting that,
1135 so back to the old behavior for now. [bird] */
1136#endif
1137 if (! stdio_traced && print_directory_flag)
1138 stdio_traced = log_working_directory (1);
1139}
1140
1141void
1142outputs (int is_err, const char *msg)
1143{
1144 if (! msg || *msg == '\0')
1145 return;
1146
1147 output_start ();
1148
1149 _outputs (output_context, is_err, msg);
1150}
1151
1152
1153
1154static struct fmtstring
1155 {
1156 char *buffer;
1157 size_t size;
1158 } fmtbuf = { NULL, 0 };
1159
1160static char *
1161get_buffer (size_t need)
1162{
1163 /* Make sure we have room. NEED includes space for \0. */
1164 if (need > fmtbuf.size)
1165 {
1166 fmtbuf.size += need * 2;
1167 fmtbuf.buffer = xrealloc (fmtbuf.buffer, fmtbuf.size);
1168 }
1169
1170 fmtbuf.buffer[need-1] = '\0';
1171
1172 return fmtbuf.buffer;
1173}
1174
1175/* Print a message on stdout. */
1176
1177void
1178message (int prefix, size_t len, const char *fmt, ...)
1179{
1180 va_list args;
1181 char *p;
1182
1183 len += strlen (fmt) + strlen (program) + INTSTR_LENGTH + 4 + 1 + 1;
1184 p = get_buffer (len);
1185
1186 if (prefix)
1187 {
1188 if (makelevel == 0)
1189 sprintf (p, "%s: ", program);
1190 else
1191 sprintf (p, "%s[%u]: ", program, makelevel);
1192 p += strlen (p);
1193 }
1194
1195 va_start (args, fmt);
1196 vsprintf (p, fmt, args);
1197 va_end (args);
1198
1199 strcat (p, "\n");
1200
1201 assert (fmtbuf.buffer[len-1] == '\0');
1202 outputs (0, fmtbuf.buffer);
1203}
1204
1205/* Print an error message. */
1206
1207void
1208error (const floc *flocp, size_t len, const char *fmt, ...)
1209{
1210 va_list args;
1211 char *p;
1212
1213 len += (strlen (fmt) + strlen (program)
1214 + (flocp && flocp->filenm ? strlen (flocp->filenm) : 0)
1215 + INTSTR_LENGTH + 4 + 1 + 1);
1216 p = get_buffer (len);
1217
1218 if (flocp && flocp->filenm)
1219 sprintf (p, "%s:%lu: ", flocp->filenm, flocp->lineno + flocp->offset);
1220 else if (makelevel == 0)
1221 sprintf (p, "%s: ", program);
1222 else
1223 sprintf (p, "%s[%u]: ", program, makelevel);
1224 p += strlen (p);
1225
1226 va_start (args, fmt);
1227 vsprintf (p, fmt, args);
1228 va_end (args);
1229
1230 strcat (p, "\n");
1231
1232 assert (fmtbuf.buffer[len-1] == '\0');
1233 outputs (1, fmtbuf.buffer);
1234}
1235
1236/* Print an error message and exit. */
1237
1238void
1239fatal (const floc *flocp, size_t len, const char *fmt, ...)
1240{
1241 va_list args;
1242 const char *stop = _(". Stop.\n");
1243 char *p;
1244
1245 len += (strlen (fmt) + strlen (program)
1246 + (flocp && flocp->filenm ? strlen (flocp->filenm) : 0)
1247 + INTSTR_LENGTH + 8 + strlen (stop) + 1);
1248 p = get_buffer (len);
1249
1250 if (flocp && flocp->filenm)
1251 sprintf (p, "%s:%lu: *** ", flocp->filenm, flocp->lineno + flocp->offset);
1252 else if (makelevel == 0)
1253 sprintf (p, "%s: *** ", program);
1254 else
1255 sprintf (p, "%s[%u]: *** ", program, makelevel);
1256 p += strlen (p);
1257
1258 va_start (args, fmt);
1259 vsprintf (p, fmt, args);
1260 va_end (args);
1261
1262 strcat (p, stop);
1263
1264 assert (fmtbuf.buffer[len-1] == '\0');
1265 outputs (1, fmtbuf.buffer);
1266
1267 die (MAKE_FAILURE);
1268}
1269
1270/* Print an error message from errno. */
1271
1272void
1273perror_with_name (const char *str, const char *name)
1274{
1275 const char *err = strerror (errno);
1276 OSSS (error, NILF, _("%s%s: %s"), str, name, err);
1277}
1278
1279/* Print an error message from errno and exit. */
1280
1281void
1282pfatal_with_name (const char *name)
1283{
1284 const char *err = strerror (errno);
1285 OSS (fatal, NILF, _("%s: %s"), name, err);
1286
1287 /* NOTREACHED */
1288}
Note: See TracBrowser for help on using the repository browser.

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