source: trunk/src/kmk/output.c@ 3669

Last change on this file since 3669 was 3669, checked in by bird, 5 months ago

kmk: More stdout close error debugging

  • Property svn:eol-style set to native
File size: 44.1 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#if defined (DEBUG_STDOUT_CLOSE_ISSUE) && defined (KBUILD_OS_WINDOWS)
18# include "nt/ntstuff.h"
19# include "nt/nthlp.h"
20# include <process.h>
21#endif
22#include "makeint.h"
23#include "job.h"
24
25/* GNU make no longer supports pre-ANSI89 environments. */
26
27#include <assert.h>
28#include <stdio.h>
29#include <stdarg.h>
30
31#ifdef HAVE_UNISTD_H
32# include <unistd.h>
33#endif
34
35#ifdef HAVE_FCNTL_H
36# include <fcntl.h>
37#else
38# include <sys/file.h>
39#endif
40
41#ifdef WINDOWS32
42# include <windows.h>
43# include <io.h>
44# ifndef CONFIG_NEW_WIN_CHILDREN
45# include "sub_proc.h"
46# else
47# include "w32/winchildren.h"
48# endif
49#endif /* WINDOWS32 */
50#ifdef KBUILD_OS_WINDOWS
51# include "console.h"
52#endif
53
54struct output *output_context = NULL;
55unsigned int stdio_traced = 0;
56
57#define OUTPUT_NONE (-1)
58
59#define OUTPUT_ISSET(_out) ((_out)->out >= 0 || (_out)->err >= 0)
60
61#ifdef HAVE_FCNTL_H
62# define STREAM_OK(_s) ((fcntl (fileno (_s), F_GETFD) != -1) || (errno != EBADF))
63#else
64# define STREAM_OK(_s) 1
65#endif
66
67#ifdef DEBUG_STDOUT_CLOSE_ISSUE
68
69/* fflush wrapper w/ error checking + reporting for stdout.
70 This is to debug the mysterious 'kmk: write error: stdout' errors. */
71int g_fStdOutError = 0;
72
73# ifdef KBUILD_OS_WINDOWS
74static void my_output_pipe_info (HANDLE hStdOut, const char *pszWhere)
75{
76 MY_IO_STATUS_BLOCK Ios = {0} ;
77 struct MY_FILE_PIPE_INFORMATION
78 {
79 ULONG ReadMode;
80 ULONG CompletionMode;
81 } Info1 = {0};
82 MY_NTSTATUS rcNt1 = g_pfnNtQueryInformationFile(hStdOut, &Ios, &Info1, sizeof(Info1), MyFilePipeInformation);
83 struct MY_FILE_PIPE_LOCAL_INFORMATION
84 {
85 ULONG NamedPipeType;
86 ULONG NamedPipeConfiguration;
87 ULONG MaximumInstances;
88 ULONG CurrentInstances;
89 ULONG InboundQuota;
90 ULONG ReadDataAvailable;
91 ULONG OutboundQuota;
92 ULONG WriteQuotaAvailable;
93 ULONG NamedPipeState;
94 ULONG NamedPipeEnd;
95 } Info2 = {0};
96 MY_NTSTATUS rcNt2 = g_pfnNtQueryInformationFile(hStdOut, &Ios, &Info2, sizeof(Info2), MyFilePipeLocalInformation);
97 union { BYTE ab[1024]; MY_FILE_NAME_INFORMATION NameInfo; } uBuf = {{0}};
98 MY_NTSTATUS rcNt3 = g_pfnNtQueryInformationFile(hStdOut, &Ios, &uBuf, sizeof(uBuf) - sizeof(WCHAR), MyFileNameInformation);
99 fprintf(stderr, "kmk[%u/%u]: stdout pipeinfo at %s: mode=%#x complmode=%#x type=%#x cfg=%#x instances=%u/%u inquota=%#x readable=%#x outquota=%#x writable=%#x state=%#x end=%#x hStdOut=%p %S rcNt=%#x/%#x/%#x\n",
100 makelevel, _getpid(), pszWhere, Info1.ReadMode, Info1.CompletionMode, Info2.NamedPipeType, Info2.NamedPipeConfiguration,
101 Info2.CurrentInstances, Info2.MaximumInstances, Info2.InboundQuota, Info2.ReadDataAvailable, Info2.OutboundQuota,
102 Info2.WriteQuotaAvailable, Info2.NamedPipeState, Info2.NamedPipeEnd,
103 hStdOut, uBuf.NameInfo.FileName, rcNt1, rcNt2, rcNt3);
104}
105# endif /* KBUILD_OS_WINDOWS */
106
107static void my_stdout_error (const char *pszOperation, const char *pszMessage)
108{
109# ifdef KBUILD_OS_WINDOWS
110 DWORD const dwErr = GetLastError ();
111# endif
112 int const iErrNo = errno;
113 int const fdFile = fileno (stdout);
114# ifdef KBUILD_OS_WINDOWS
115 HANDLE const hNative = (HANDLE)_get_osfhandle (_fileno (stdout));
116 DWORD const dwType = GetFileType (hNative);
117 unsigned int uDosErr = _doserrno;
118 if ((dwType & ~FILE_TYPE_REMOTE) == FILE_TYPE_PIPE)
119 my_output_pipe_info (hNative, "error");
120 fprintf (stderr, "kmk[%u/%u]: stdout error: %s: %s! (lasterr=%u errno=%d fileno=%d uDosErr=%u native=%p type=%#x)\n",
121 makelevel, _getpid(), pszOperation, pszMessage, dwErr, iErrNo, fdFile, uDosErr, hNative, dwType);
122# else
123 fprintf (stderr, "kmk[%u]: stdout error: %s: %s! (lasterr=%u errno=%d fileno=%d)\n",
124 makelevel, pszOperation, pszMessage, dwErr, iErrNo, fdFile);
125# endif
126}
127
128/* Preserves errno and win32 last error. */
129void my_check_stdout (const char *pszWhere)
130{
131 if (!g_fStdOutError)
132 {
133# ifdef KBUILD_OS_WINDOWS
134 DWORD const dwErrSaved = GetLastError();
135# endif
136 int const iErrNoSaved = errno;
137
138 if (ferror (stdout))
139 {
140 my_stdout_error (pszWhere, "error pending!");
141 g_fStdOutError = 1;
142 }
143
144 errno = iErrNoSaved;
145# ifdef KBUILD_OS_WINDOWS
146 SetLastError(dwErrSaved);
147# endif
148 }
149}
150
151# ifdef KBUILD_OS_WINDOWS
152/* generic fwrite wrapper */
153__declspec(dllexport) size_t __cdecl fwrite(void const *pvBuf, size_t cbItem, size_t cItems, FILE *pFile)
154{
155 size_t cbWritten;
156 if (pFile == stdout)
157 my_check_stdout("fwrite/entry");
158 _lock_file(pFile);
159 cbWritten = _fwrite_nolock(pvBuf, cbItem, cItems, pFile);
160 _unlock_file(pFile);
161 if (pFile == stdout)
162 my_check_stdout("fwrite/exit");
163 return cbWritten;
164}
165void * const __imp_fwrite = (void *)(uintptr_t)fwrite;
166
167/* generic fflush wrapper */
168__declspec(dllexport) int __cdecl fflush(FILE *pFile)
169{
170 int rc;
171 if (pFile == stdout || !pFile)
172 my_check_stdout("fflush/entry");
173 if (pFile)
174 {
175 _lock_file(pFile);
176 rc = _fflush_nolock(pFile);
177 _unlock_file(pFile);
178 }
179 if (pFile == stdout || !pFile)
180 my_check_stdout("fflush/exit");
181 return rc;
182}
183void * const __imp_fflush = (void *)(uintptr_t)fflush;
184
185# else
186static int my_fflush (FILE *pFile)
187{
188 if (pFile == stdout && !g_fStdOutError)
189 {
190 if (!ferror (pFile))
191 {
192 int rcRet = fflush (pFile);
193 g_fStdOutError = ferror (pFile);
194 if (rcRet != EOF && !g_fStdOutError)
195 { /* likely */ }
196 else if (rcRet == EOF)
197 my_stdout_error ("fflush(stdout)", "flush failed!");
198 else
199 my_stdout_error ("fflush(stdout)", "error pending after successful flush!");
200
201 return rcRet;
202 }
203 else
204 {
205 my_stdout_error ("fflush(stdout)", "error pending on entry!");
206 g_fStdOutError = 1;
207 }
208
209 }
210 return fflush (pFile);
211}
212
213# undef fflush
214# define fflush(a_pFile) my_fflush(a_pFile)
215# endif
216
217#endif /* DEBUG_STDOUT_CLOSE_ISSUE */
218
219
220#if defined(KMK) && !defined(NO_OUTPUT_SYNC)
221/* Non-negative if we're counting output lines.
222
223 This is used by die_with_job_output to decide whether the initial build
224 error needs to be repeated because there was too much output from parallel
225 jobs between it and the actual make termination. */
226int output_metered = -1;
227
228static void meter_output_block (char const *buffer, size_t len)
229{
230 while (len > 0)
231 {
232 char *nl = (char *)memchr (buffer, '\n', len);
233 size_t linelen;
234 if (nl)
235 {
236 linelen = nl - buffer + 1;
237 output_metered++;
238 }
239 else
240 linelen = len;
241 output_metered += linelen / 132;
242
243 /* advance */
244 buffer += linelen;
245 len -= linelen;
246 }
247}
248#endif
249
250
251#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
252# define MEMBUF_MIN_SEG_SIZE 4096
253# define MEMBUF_MAX_SEG_SIZE (512*1024)
254# define MEMBUF_MAX_MOVE_LEN ( MEMBUF_MIN_SEG_SIZE \
255 - offsetof (struct output_segment, runs) \
256 - sizeof (struct output_run))
257# define MEMBUF_MAX_TOTAL ( sizeof (void *) <= 4 \
258 ? (size_t)512*1024 : (size_t)16*1024*1024 )
259
260static void *acquire_semaphore (void);
261static void release_semaphore (void *);
262static int log_working_directory (int);
263
264/* Is make's stdout going to the same place as stderr?
265 Also, did we already sync_init (== -1)? */
266static int combined_output = -1;
267
268/* Helper for membuf_reset and output_reset */
269static membuf_reset (struct output *out)
270{
271 struct output_segment *seg;
272 while ((seg = out->out.head_seg))
273 {
274 out->out.head_seg = seg->next;
275 free (seg);
276 }
277 out->out.tail_seg = NULL;
278 out->out.tail_run = NULL;
279 out->out.head_run = NULL;
280 out->out.left = 0;
281 out->out.total = 0;
282
283 while ((seg = out->err.head_seg))
284 {
285 out->err.head_seg = seg->next;
286 free (seg);
287 }
288 out->err.tail_seg = NULL;
289 out->err.tail_run = NULL;
290 out->err.head_run = NULL;
291 out->err.left = 0;
292 out->err.total = 0;
293
294 out->seqno = 0;
295}
296
297/* Used by die_with_job_output to suppress output when it shouldn't be repeated. */
298void output_reset (struct output *out)
299{
300 if (out && (out->out.total || out->err.total))
301 membuf_reset (out);
302}
303
304/* Internal worker for output_dump and membuf_dump_most. */
305static void membuf_dump (struct output *out)
306{
307 if (out->out.total || out->err.total)
308 {
309 int traced = 0;
310 struct output_run *err_run;
311 struct output_run *out_run;
312 FILE *prevdst;
313
314 /* Try to acquire the semaphore. If it fails, dump the output
315 unsynchronized; still better than silently discarding it.
316 We want to keep this lock for as little time as possible. */
317 void *sem = acquire_semaphore ();
318# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
319 int prev_mode_out = _setmode (fileno (stdout), _O_BINARY);
320 int prev_mode_err = _setmode (fileno (stderr), _O_BINARY);
321# endif
322
323# ifndef KMK /* this drives me bananas. */
324 /* Log the working directory for this dump. */
325 if (print_directory_flag && output_sync != OUTPUT_SYNC_RECURSE)
326 traced = log_working_directory (1);
327# endif
328
329 /* Work the out and err sequences in parallel. */
330 out_run = out->out.head_run;
331 err_run = out->err.head_run;
332 prevdst = NULL;
333 while (err_run || out_run)
334 {
335 FILE *dst;
336 const void *src;
337 size_t len;
338 if (out_run && (!err_run || out_run->seqno <= err_run->seqno))
339 {
340 src = out_run + 1;
341 len = out_run->len;
342 dst = stdout;
343 out_run = out_run->next;
344 }
345 else
346 {
347 src = err_run + 1;
348 len = err_run->len;
349 dst = stderr;
350 err_run = err_run->next;
351 }
352 if (dst != prevdst)
353 fflush (prevdst);
354 prevdst = dst;
355#ifdef KMK
356 if (output_metered < 0)
357 { /* likely */ }
358 else
359 meter_output_block (src, len);
360#endif
361# if 0 /* for debugging */
362 while (len > 0)
363 {
364 const char *nl = (const char *)memchr (src, '\n', len);
365 size_t line_len = nl ? nl - (const char *)src + 1 : len;
366 char *tmp = (char *)xmalloc (1 + line_len + 1 + 1);
367 tmp[0] = '{';
368 memcpy (&tmp[1], src, line_len);
369 tmp[1 + line_len] = '}';
370# ifdef KBUILD_OS_WINDOWS
371 maybe_con_fwrite (tmp, 1 + line_len + 1, 1, dst);
372# else
373 fwrite (tmp, 1 + line_len + 1, 1, dst);
374# endif
375 free (tmp);
376 src = (const char *)src + line_len;
377 len -= line_len;
378 }
379#else
380# ifdef KBUILD_OS_WINDOWS
381 maybe_con_fwrite (src, len, 1, dst);
382# else
383 fwrite (src, len, 1, dst);
384# endif
385# endif
386 }
387 if (prevdst)
388 fflush (prevdst);
389
390# ifndef KMK /* this drives me bananas. */
391 if (traced)
392 log_working_directory (0);
393# endif
394
395 /* Exit the critical section. */
396# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
397 if (prev_mode_out != -1)
398 _setmode (fileno (stdout), prev_mode_out);
399 if (prev_mode_err != -1)
400 _setmode (fileno (stderr), prev_mode_err);
401# endif
402 if (sem)
403 release_semaphore (sem);
404
405# ifdef KMK
406 if (!out->dont_truncate)
407 { /* likely */ }
408 else return;
409# endif
410
411 /* Free the segments and reset the state. */
412 membuf_reset (out);
413 }
414 else
415 assert (out->out.head_seg == NULL && out->err.head_seg == NULL);
416}
417
418/* Writes up to LEN bytes to the given segment.
419 Returns how much was actually written. */
420static size_t
421membuf_write_segment (struct output_membuf *membuf, struct output_segment *seg,
422 const char *src, size_t len, unsigned int *pseqno)
423{
424 size_t written = 0;
425 if (seg && membuf->left > 0)
426 {
427 struct output_run *run = membuf->tail_run;
428 char *dst = (char *)(run + 1) + run->len;
429 assert ((uintptr_t)run - (uintptr_t)seg < seg->size);
430
431 /* If the sequence number didn't change, then we can append
432 to the current run without further considerations. */
433 if (run->seqno == *pseqno)
434 written = len;
435 /* If the current run does not end with a newline, don't start a new
436 run till we encounter one. */
437 else if (dst[-1] != '\n')
438 {
439 char const *srcnl = (const char *)memchr (src, '\n', len);
440 written = srcnl ? srcnl - src + 1 : len;
441 }
442 /* Try create a new empty run and append to it. */
443 else
444 {
445 size_t const offnextrun = ( (uintptr_t)dst - (uintptr_t)(seg)
446 + sizeof(void *) - 1)
447 & ~(sizeof(void *) - 1);
448 if (offnextrun > seg->size - sizeof (struct output_run) * 2)
449 return 0; /* need new segment */
450
451 run = run->next = (struct output_run *)((char *)seg + offnextrun);
452 run->next = NULL;
453 run->seqno = ++(*pseqno);
454 run->len = 0;
455 membuf->tail_run = run;
456 membuf->left = seg->size - (offnextrun + sizeof (*run));
457 dst = (char *)(run + 1);
458 written = len;
459 }
460
461 /* Append to the current run. */
462 if (written > membuf->left)
463 written = membuf->left;
464 memcpy (dst, src, written);
465 run->len += written;
466 membuf->left -= written;
467 }
468 return written;
469}
470
471/* Helper for membuf_write_new_segment and membuf_dump_most that figures out
472 now much data needs to be moved from the previous run in order to make it
473 end with a newline. */
474static size_t membuf_calc_move_len (struct output_run *tail_run)
475{
476 size_t to_move = 0;
477 if (tail_run)
478 {
479 const char *data = (const char *)(tail_run + 1);
480 size_t off = tail_run->len;
481 while (off > 0 && data[off - 1] != '\n')
482 off--;
483 to_move = tail_run->len - off;
484 if (to_move >= MEMBUF_MAX_MOVE_LEN)
485 to_move = 0;
486 }
487 return to_move;
488}
489
490/* Allocates a new segment and writes to it.
491 This will take care to make sure the previous run terminates with
492 a newline so that we pass whole lines to fwrite when dumping. */
493static size_t
494membuf_write_new_segment (struct output_membuf *membuf, const char *src,
495 size_t len, unsigned int *pseqno)
496{
497 struct output_run *prev_run = membuf->tail_run;
498 struct output_segment *prev_seg = membuf->tail_seg;
499 size_t const to_move = membuf_calc_move_len (prev_run);
500 struct output_segment *new_seg;
501 size_t written;
502 char *dst;
503
504 /* Figure the the segment size. We start with MEMBUF_MIN_SEG_SIZE and double
505 it each time till we reach MEMBUF_MAX_SEG_SIZE. */
506 size_t const offset_runs = offsetof (struct output_segment, runs);
507 size_t segsize = !prev_seg ? MEMBUF_MIN_SEG_SIZE
508 : prev_seg->size >= MEMBUF_MAX_SEG_SIZE ? MEMBUF_MAX_SEG_SIZE
509 : prev_seg->size * 2;
510 while ( segsize < to_move + len + offset_runs + sizeof (struct output_run) * 2
511 && segsize < MEMBUF_MAX_SEG_SIZE)
512 segsize *= 2;
513
514 /* Allocate the segment and link it and the first run. */
515 new_seg = (struct output_segment *)xmalloc (segsize);
516 new_seg->size = segsize;
517 new_seg->next = NULL;
518 new_seg->runs[0].next = NULL;
519 if (!prev_seg)
520 {
521 membuf->head_seg = new_seg;
522 membuf->head_run = &new_seg->runs[0];
523 }
524 else
525 {
526 prev_seg->next = new_seg;
527 prev_run->next = &new_seg->runs[0];
528 }
529 membuf->tail_seg = new_seg;
530 membuf->tail_run = &new_seg->runs[0];
531 membuf->total += segsize;
532 membuf->left = segsize - sizeof (struct output_run) - offset_runs;
533
534 /* Initialize and write data to the first run. */
535 dst = (char *)&new_seg->runs[0]; /* Try bypass gcc array size cleverness. */
536 dst += sizeof (struct output_run);
537 assert (MEMBUF_MAX_MOVE_LEN < MEMBUF_MIN_SEG_SIZE);
538 if (to_move > 0)
539 {
540 /* Move to_move bytes from the previous run in hope that we'll get a
541 newline to soon. Afterwards call membuf_segment_write to work SRC. */
542 assert (prev_run != NULL);
543 assert (membuf->left >= to_move);
544 prev_run->len -= to_move;
545 new_seg->runs[0].len = to_move;
546 new_seg->runs[0].seqno = prev_run->seqno;
547 memcpy (dst, (const char *)(prev_run + 1) + prev_run->len, to_move);
548 membuf->left -= to_move;
549
550 written = membuf_write_segment (membuf, new_seg, src, len, pseqno);
551 }
552 else
553 {
554 /* Create a run with up to LEN from SRC. */
555 written = len;
556 if (written > membuf->left)
557 written = membuf->left;
558 new_seg->runs[0].len = written;
559 new_seg->runs[0].seqno = ++(*pseqno);
560 memcpy (dst, src, written);
561 membuf->left -= written;
562 }
563 return written;
564}
565
566/* Worker for output_write that will dump most of the output when we hit
567 MEMBUF_MAX_TOTAL on either of the two membuf structures, then free all the
568 output segments. Incomplete lines will be held over to the next buffers
569 and copied into new segments. */
570static void
571membuf_dump_most (struct output *out)
572{
573 size_t out_to_move = membuf_calc_move_len (out->out.tail_run);
574 size_t err_to_move = membuf_calc_move_len (out->err.tail_run);
575 if (!out_to_move && !err_to_move)
576 membuf_dump (out);
577 else
578 {
579 /* Allocate a stack buffer for holding incomplete lines. This should be
580 fine since we're only talking about max 2 * MEMBUF_MAX_MOVE_LEN.
581 The -1 on the sequence numbers, ise because membuf_write_new_segment
582 will increment them before use. */
583 unsigned int out_seqno = out_to_move ? out->out.tail_run->seqno - 1 : 0;
584 unsigned int err_seqno = err_to_move ? out->err.tail_run->seqno - 1 : 0;
585 char *tmp = alloca (out_to_move + err_to_move);
586 if (out_to_move)
587 {
588 out->out.tail_run->len -= out_to_move;
589 memcpy (tmp,
590 (char *)(out->out.tail_run + 1) + out->out.tail_run->len,
591 out_to_move);
592 }
593 if (err_to_move)
594 {
595 out->err.tail_run->len -= err_to_move;
596 memcpy (tmp + out_to_move,
597 (char *)(out->err.tail_run + 1) + out->err.tail_run->len,
598 err_to_move);
599 }
600
601 membuf_dump (out);
602
603 if (out_to_move)
604 {
605 size_t written = membuf_write_new_segment (&out->out, tmp,
606 out_to_move, &out_seqno);
607 assert (written == out_to_move); (void)written;
608 }
609 if (err_to_move)
610 {
611 size_t written = membuf_write_new_segment (&out->err,
612 tmp + out_to_move,
613 err_to_move, &err_seqno);
614 assert (written == err_to_move); (void)written;
615 }
616 }
617}
618
619
620
621/* write/fwrite like function, binary mode. */
622ssize_t
623output_write_bin (struct output *out, int is_err, const char *src, size_t len)
624{
625 size_t ret = len;
626 if (!out || !out->syncout)
627 {
628 FILE *f = is_err ? stderr : stdout;
629# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
630 /* On DOS platforms we need to disable \n -> \r\n converts that is common on
631 standard output/error. Also optimize for console output. */
632 int saved_errno;
633 int fd = fileno (f);
634 int prev_mode = _setmode (fd, _O_BINARY);
635 maybe_con_fwrite (src, len, 1, f);
636 if (fflush (f) == EOF)
637 ret = -1;
638 saved_errno = errno;
639 _setmode (fd, prev_mode);
640 errno = saved_errno;
641# else
642 fwrite (src, len, 1, f);
643 if (fflush (f) == EOF)
644 ret = -1;
645# endif
646 }
647 else
648 {
649 struct output_membuf *membuf = is_err ? &out->err : &out->out;
650 while (len > 0)
651 {
652 size_t runlen = membuf_write_segment (membuf, membuf->tail_seg, src, len, &out->seqno);
653 if (!runlen)
654 {
655 if (membuf->total < MEMBUF_MAX_TOTAL)
656 runlen = membuf_write_new_segment (membuf, src, len, &out->seqno);
657 else
658 membuf_dump_most (out);
659 }
660 /* advance */
661 len -= runlen;
662 src += runlen;
663 }
664 }
665 return ret;
666}
667
668#endif /* CONFIG_WITH_OUTPUT_IN_MEMORY */
669
670/* write/fwrite like function, text mode. */
671ssize_t
672output_write_text (struct output *out, int is_err, const char *src, size_t len)
673{
674#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
675# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
676 ssize_t ret = len;
677 if (!out || !out->syncout)
678 {
679 /* ASSUME fwrite does the desired conversion. */
680 FILE *f = is_err ? stderr : stdout;
681# ifdef KBUILD_OS_WINDOWS
682 if (maybe_con_fwrite (src, len, 1, f) < 0)
683 ret = -1;
684# else
685 fwrite (src, len, 1, f);
686# endif
687 if (fflush (f) == EOF)
688 ret = -1;
689 }
690 else
691 {
692 /* Work the buffer line by line, replacing each \n with \r\n. */
693 while (len > 0)
694 {
695 const char *nl = memchr (src, '\n', len);
696 size_t line_len = nl ? nl - src : len;
697 output_write_bin (out, is_err, src, line_len);
698 if (!nl)
699 break;
700 output_write_bin (out, is_err, "\r\n", 2);
701 len -= line_len + 1;
702 src += line_len + 1;
703 }
704 }
705 return ret;
706# else
707 return output_write_bin (out, is_err, src, len);
708# endif
709#else
710 ssize_t ret = len;
711 if (! out || ! out->syncout)
712 {
713 FILE *f = is_err ? stderr : stdout;
714# ifdef KBUILD_OS_WINDOWS
715 maybe_con_fwrite(src, len, 1, f);
716# else
717 fwrite (src, len, 1, f);
718# endif
719 fflush (f);
720 }
721 else
722 {
723 int fd = is_err ? out->err : out->out;
724 int r;
725
726 EINTRLOOP (r, lseek (fd, 0, SEEK_END));
727 while (1)
728 {
729 EINTRLOOP (r, write (fd, src, len));
730 if ((size_t)r == len || r <= 0)
731 break;
732 len -= r;
733 src += r;
734 }
735 }
736 return ret;
737#endif
738}
739
740
741
742/* Write a string to the current STDOUT or STDERR. */
743static void
744_outputs (struct output *out, int is_err, const char *msg)
745{
746#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
747 output_write_text (out, is_err, msg, strlen (msg));
748#else /* !CONFIG_WITH_OUTPUT_IN_MEMORY */
749 if (! out || ! out->syncout)
750 {
751 FILE *f = is_err ? stderr : stdout;
752# ifdef KBUILD_OS_WINDOWS
753 maybe_con_fwrite(msg, strlen(msg), 1, f);
754# else
755 fputs (msg, f);
756# endif
757 fflush (f);
758 }
759 else
760 {
761 int fd = is_err ? out->err : out->out;
762 int len = strlen (msg);
763 int r;
764
765 EINTRLOOP (r, lseek (fd, 0, SEEK_END));
766 while (1)
767 {
768 EINTRLOOP (r, write (fd, msg, len));
769 if (r == len || r <= 0)
770 break;
771 len -= r;
772 msg += r;
773 }
774 }
775#endif /* !CONFIG_WITH_OUTPUT_IN_MEMORY */
776}
777
778
779/* Write a message indicating that we've just entered or
780 left (according to ENTERING) the current directory. */
781
782static int
783log_working_directory (int entering)
784{
785 static char *buf = NULL;
786 static unsigned int len = 0;
787 unsigned int need;
788 const char *fmt;
789 char *p;
790
791 /* Get enough space for the longest possible output. */
792 need = strlen (program) + INTSTR_LENGTH + 2 + 1;
793 if (starting_directory)
794 need += strlen (starting_directory);
795
796 /* Use entire sentences to give the translators a fighting chance. */
797 if (makelevel == 0)
798 if (starting_directory == 0)
799 if (entering)
800 fmt = _("%s: Entering an unknown directory\n");
801 else
802 fmt = _("%s: Leaving an unknown directory\n");
803 else
804 if (entering)
805 fmt = _("%s: Entering directory '%s'\n");
806 else
807 fmt = _("%s: Leaving directory '%s'\n");
808 else
809 if (starting_directory == 0)
810 if (entering)
811 fmt = _("%s[%u]: Entering an unknown directory\n");
812 else
813 fmt = _("%s[%u]: Leaving an unknown directory\n");
814 else
815 if (entering)
816 fmt = _("%s[%u]: Entering directory '%s'\n");
817 else
818 fmt = _("%s[%u]: Leaving directory '%s'\n");
819
820 need += strlen (fmt);
821
822 if (need > len)
823 {
824 buf = xrealloc (buf, need);
825 len = need;
826 }
827
828 p = buf;
829 if (print_data_base_flag)
830 {
831 *(p++) = '#';
832 *(p++) = ' ';
833 }
834
835 if (makelevel == 0)
836 if (starting_directory == 0)
837 sprintf (p, fmt , program);
838 else
839 sprintf (p, fmt, program, starting_directory);
840 else if (starting_directory == 0)
841 sprintf (p, fmt, program, makelevel);
842 else
843 sprintf (p, fmt, program, makelevel, starting_directory);
844
845 _outputs (NULL, 0, buf);
846
847 return 1;
848}
849
850/* Set a file descriptor to be in O_APPEND mode.
851 If it fails, just ignore it. */
852
853static void
854set_append_mode (int fd)
855{
856#if defined(F_GETFL) && defined(F_SETFL) && defined(O_APPEND)
857 int flags = fcntl (fd, F_GETFL, 0);
858 if (flags >= 0)
859 fcntl (fd, F_SETFL, flags | O_APPEND);
860#endif
861}
862
863
864
865#ifndef NO_OUTPUT_SYNC
866
867/* Semaphore for use in -j mode with output_sync. */
868static sync_handle_t sync_handle = -1;
869
870#define FD_NOT_EMPTY(_f) ((_f) != OUTPUT_NONE && lseek ((_f), 0, SEEK_END) > 0)
871
872/* Set up the sync handle. Disables output_sync on error. */
873static int
874sync_init (void)
875{
876 int combined_output = 0;
877
878#ifdef WINDOWS32
879# ifdef CONFIG_NEW_WIN_CHILDREN
880 if (STREAM_OK (stdout))
881 {
882 if (STREAM_OK (stderr))
883 {
884 char mtxname[256];
885 sync_handle = create_mutex (mtxname, sizeof (mtxname));
886 if (sync_handle != -1)
887 {
888 prepare_mutex_handle_string (mtxname);
889 return same_stream (stdout, stderr);
890 }
891 perror_with_name ("output-sync suppressed: ", "create_mutex");
892 }
893 else
894 perror_with_name ("output-sync suppressed: ", "stderr");
895 }
896 else
897 perror_with_name ("output-sync suppressed: ", "stdout");
898 output_sync = OUTPUT_SYNC_NONE;
899
900# else /* !CONFIG_NEW_WIN_CHILDREN */
901 if ((!STREAM_OK (stdout) && !STREAM_OK (stderr))
902 || (sync_handle = create_mutex ()) == -1)
903 {
904 perror_with_name ("output-sync suppressed: ", "stderr");
905 output_sync = 0;
906 }
907 else
908 {
909 combined_output = same_stream (stdout, stderr);
910 prepare_mutex_handle_string (sync_handle);
911 }
912# endif /* !CONFIG_NEW_WIN_CHILDREN */
913
914#else
915 if (STREAM_OK (stdout))
916 {
917 struct stat stbuf_o, stbuf_e;
918
919 sync_handle = fileno (stdout);
920 combined_output = (fstat (fileno (stdout), &stbuf_o) == 0
921 && fstat (fileno (stderr), &stbuf_e) == 0
922 && stbuf_o.st_dev == stbuf_e.st_dev
923 && stbuf_o.st_ino == stbuf_e.st_ino);
924 }
925 else if (STREAM_OK (stderr))
926 sync_handle = fileno (stderr);
927 else
928 {
929 perror_with_name ("output-sync suppressed: ", "stderr");
930 output_sync = 0;
931 }
932#endif
933
934 return combined_output;
935}
936
937#ifndef CONFIG_WITH_OUTPUT_IN_MEMORY
938/* Support routine for output_sync() */
939static void
940pump_from_tmp (int from, FILE *to)
941{
942# ifdef KMK
943 char buffer[8192];
944# else
945 static char buffer[8192];
946#endif
947
948# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
949 int prev_mode;
950
951 /* "from" is opened by open_tmpfd, which does it in binary mode, so
952 we need the mode of "to" to match that. */
953 prev_mode = _setmode (fileno (to), O_BINARY);
954#endif
955
956 if (lseek (from, 0, SEEK_SET) == -1)
957 perror ("lseek()");
958
959 while (1)
960 {
961 int len;
962 EINTRLOOP (len, read (from, buffer, sizeof (buffer)));
963 if (len < 0)
964 perror ("read()");
965 if (len <= 0)
966 break;
967#ifdef KMK
968 if (output_metered < 0)
969 { /* likely */ }
970 else
971 meter_output_block (buffer, len);
972#endif
973 if (fwrite (buffer, len, 1, to) < 1)
974 {
975 perror ("fwrite()");
976 break;
977 }
978 fflush (to);
979 }
980
981# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
982 /* Switch "to" back to its original mode, so that log messages by
983 Make have the same EOL format as without --output-sync. */
984 _setmode (fileno (to), prev_mode);
985#endif
986}
987#endif /* CONFIG_WITH_OUTPUT_IN_MEMORY */
988
989/* Obtain the lock for writing output. */
990static void *
991acquire_semaphore (void)
992{
993 static struct flock fl;
994
995 fl.l_type = F_WRLCK;
996 fl.l_whence = SEEK_SET;
997 fl.l_start = 0;
998 fl.l_len = 1;
999 if (fcntl (sync_handle, F_SETLKW, &fl) != -1)
1000 return &fl;
1001#ifdef KBUILD_OS_DARWIN /* F_SETLKW isn't supported on pipes */
1002 if (errno != EBADF)
1003#endif
1004 perror ("fcntl()");
1005 return NULL;
1006}
1007
1008/* Release the lock for writing output. */
1009static void
1010release_semaphore (void *sem)
1011{
1012 struct flock *flp = (struct flock *)sem;
1013 flp->l_type = F_UNLCK;
1014 if (fcntl (sync_handle, F_SETLKW, flp) == -1)
1015 perror ("fcntl()");
1016}
1017
1018#ifndef CONFIG_WITH_OUTPUT_IN_MEMORY
1019
1020/* Returns a file descriptor to a temporary file. The file is automatically
1021 closed/deleted on exit. Don't use a FILE* stream. */
1022int
1023output_tmpfd (void)
1024{
1025 int fd = -1;
1026 FILE *tfile = tmpfile ();
1027
1028 if (! tfile)
1029 {
1030#ifdef KMK
1031 if (output_context && output_context->syncout)
1032 output_context->syncout = 0; /* Avoid inifinit recursion. */
1033#endif
1034 pfatal_with_name ("tmpfile");
1035 }
1036
1037 /* Create a duplicate so we can close the stream. */
1038 fd = dup (fileno (tfile));
1039 if (fd < 0)
1040 {
1041#ifdef KMK
1042 if (output_context && output_context->syncout)
1043 output_context->syncout = 0; /* Avoid inifinit recursion. */
1044#endif
1045 pfatal_with_name ("dup");
1046 }
1047
1048 fclose (tfile);
1049
1050 set_append_mode (fd);
1051
1052 return fd;
1053}
1054
1055/* Adds file descriptors to the child structure to support output_sync; one
1056 for stdout and one for stderr as long as they are open. If stdout and
1057 stderr share a device they can share a temp file too.
1058 Will reset output_sync on error. */
1059static void
1060setup_tmpfile (struct output *out)
1061{
1062 /* Is make's stdout going to the same place as stderr? */
1063 static int combined_output = -1;
1064
1065 if (combined_output < 0)
1066 {
1067#ifdef KMK /* prevent infinite recursion if sync_init() calls perror_with_name. */
1068 combined_output = 0;
1069#endif
1070 combined_output = sync_init ();
1071 }
1072
1073 if (STREAM_OK (stdout))
1074 {
1075 int fd = output_tmpfd ();
1076 if (fd < 0)
1077 goto error;
1078 CLOSE_ON_EXEC (fd);
1079 out->out = fd;
1080 }
1081
1082 if (STREAM_OK (stderr))
1083 {
1084 if (out->out != OUTPUT_NONE && combined_output)
1085 out->err = out->out;
1086 else
1087 {
1088 int fd = output_tmpfd ();
1089 if (fd < 0)
1090 goto error;
1091 CLOSE_ON_EXEC (fd);
1092 out->err = fd;
1093 }
1094 }
1095
1096 return;
1097
1098 /* If we failed to create a temp file, disable output sync going forward. */
1099 error:
1100 output_close (out);
1101 output_sync = OUTPUT_SYNC_NONE;
1102}
1103
1104#endif /* !CONFIG_WITH_OUTPUT_IN_MEMORY */
1105
1106/* Synchronize the output of jobs in -j mode to keep the results of
1107 each job together. This is done by holding the results in temp files,
1108 one for stdout and potentially another for stderr, and only releasing
1109 them to "real" stdout/stderr when a semaphore can be obtained. */
1110
1111void
1112output_dump (struct output *out)
1113{
1114#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
1115 membuf_dump (out);
1116#else
1117 int outfd_not_empty = FD_NOT_EMPTY (out->out);
1118 int errfd_not_empty = FD_NOT_EMPTY (out->err);
1119
1120 if (outfd_not_empty || errfd_not_empty)
1121 {
1122# ifndef KMK /* this drives me bananas. */
1123 int traced = 0;
1124# endif
1125
1126 /* Try to acquire the semaphore. If it fails, dump the output
1127 unsynchronized; still better than silently discarding it.
1128 We want to keep this lock for as little time as possible. */
1129 void *sem = acquire_semaphore ();
1130
1131# ifndef KMK /* this drives me bananas. */
1132 /* Log the working directory for this dump. */
1133 if (print_directory_flag && output_sync != OUTPUT_SYNC_RECURSE)
1134 traced = log_working_directory (1);
1135# endif
1136
1137 if (outfd_not_empty)
1138 pump_from_tmp (out->out, stdout);
1139 if (errfd_not_empty && out->err != out->out)
1140 pump_from_tmp (out->err, stderr);
1141
1142# ifndef KMK /* this drives me bananas. */
1143 if (traced)
1144 log_working_directory (0);
1145# endif
1146
1147 /* Exit the critical section. */
1148 if (sem)
1149 release_semaphore (sem);
1150
1151# ifdef KMK
1152 if (!out->dont_truncate)
1153 { /* likely */ }
1154 else return;
1155# endif
1156 /* Truncate and reset the output, in case we use it again. */
1157 if (out->out != OUTPUT_NONE)
1158 {
1159 int e;
1160 lseek (out->out, 0, SEEK_SET);
1161 EINTRLOOP (e, ftruncate (out->out, 0));
1162 }
1163 if (out->err != OUTPUT_NONE && out->err != out->out)
1164 {
1165 int e;
1166 lseek (out->err, 0, SEEK_SET);
1167 EINTRLOOP (e, ftruncate (out->err, 0));
1168 }
1169 }
1170#endif
1171}
1172
1173# if defined(KMK) && !defined(CONFIG_WITH_OUTPUT_IN_MEMORY)
1174/* Used by die_with_job_output to suppress output when it shouldn't be repeated. */
1175void output_reset (struct output *out)
1176{
1177 if (out)
1178 {
1179 if (out->out != OUTPUT_NONE)
1180 {
1181 int e;
1182 lseek (out->out, 0, SEEK_SET);
1183 EINTRLOOP (e, ftruncate (out->out, 0));
1184 }
1185 if (out->err != OUTPUT_NONE && out->err != out->out)
1186 {
1187 int e;
1188 lseek (out->err, 0, SEEK_SET);
1189 EINTRLOOP (e, ftruncate (out->err, 0));
1190 }
1191 }
1192}
1193# endif
1194#endif /* NO_OUTPUT_SYNC */
1195
1196
1197
1198/* Provide support for temporary files. */
1199
1200#ifndef HAVE_STDLIB_H
1201# ifdef HAVE_MKSTEMP
1202int mkstemp (char *template);
1203# else
1204char *mktemp (char *template);
1205# endif
1206#endif
1207
1208FILE *
1209output_tmpfile (char **name, const char *template)
1210{
1211#ifdef HAVE_FDOPEN
1212 int fd;
1213#endif
1214
1215#if defined HAVE_MKSTEMP || defined HAVE_MKTEMP
1216# define TEMPLATE_LEN strlen (template)
1217#else
1218# define TEMPLATE_LEN L_tmpnam
1219#endif
1220 *name = xmalloc (TEMPLATE_LEN + 1);
1221 strcpy (*name, template);
1222
1223#if defined HAVE_MKSTEMP && defined HAVE_FDOPEN
1224 /* It's safest to use mkstemp(), if we can. */
1225 fd = mkstemp (*name);
1226 if (fd == -1)
1227 return 0;
1228 return fdopen (fd, "w");
1229#else
1230# ifdef HAVE_MKTEMP
1231 (void) mktemp (*name);
1232# else
1233 (void) tmpnam (*name);
1234# endif
1235
1236# ifdef HAVE_FDOPEN
1237 /* Can't use mkstemp(), but guard against a race condition. */
1238 EINTRLOOP (fd, open (*name, O_CREAT|O_EXCL|O_WRONLY, 0600));
1239 if (fd == -1)
1240 return 0;
1241 return fdopen (fd, "w");
1242# else
1243 /* Not secure, but what can we do? */
1244 return fopen (*name, "w");
1245# endif
1246#endif
1247}
1248
1249
1250
1251/* This code is stolen from gnulib.
1252 If/when we abandon the requirement to work with K&R compilers, we can
1253 remove this (and perhaps other parts of GNU make!) and migrate to using
1254 gnulib directly.
1255
1256 This is called only through atexit(), which means die() has already been
1257 invoked. So, call exit() here directly. Apparently that works...?
1258*/
1259
1260/* Close standard output, exiting with status 'exit_failure' on failure.
1261 If a program writes *anything* to stdout, that program should close
1262 stdout and make sure that it succeeds before exiting. Otherwise,
1263 suppose that you go to the extreme of checking the return status
1264 of every function that does an explicit write to stdout. The last
1265 printf can succeed in writing to the internal stream buffer, and yet
1266 the fclose(stdout) could still fail (due e.g., to a disk full error)
1267 when it tries to write out that buffered data. Thus, you would be
1268 left with an incomplete output file and the offending program would
1269 exit successfully. Even calling fflush is not always sufficient,
1270 since some file systems (NFS and CODA) buffer written/flushed data
1271 until an actual close call.
1272
1273 Besides, it's wasteful to check the return value from every call
1274 that writes to stdout -- just let the internal stream state record
1275 the failure. That's what the ferror test is checking below.
1276
1277 It's important to detect such failures and exit nonzero because many
1278 tools (most notably 'make' and other build-management systems) depend
1279 on being able to detect failure in other tools via their exit status. */
1280
1281static void
1282close_stdout (void)
1283{
1284 int prev_fail = ferror (stdout);
1285#ifdef DEBUG_STDOUT_CLOSE_ISSUE
1286 if (prev_fail)
1287 my_stdout_error ("close_stdout", "error pending on entry!");
1288 errno = 0; SetLastError (0);
1289#endif
1290 int fclose_fail = fclose (stdout);
1291
1292 if (prev_fail || fclose_fail)
1293 {
1294#ifdef DEBUG_STDOUT_CLOSE_ISSUE
1295 if (fclose_fail)
1296 my_stdout_error ("close_stdout", "fclose failed!");
1297#endif
1298 if (fclose_fail)
1299 perror_with_name (_("write error: stdout"), "");
1300 else
1301 O (error, NILF, _("write error: stdout"));
1302 exit (MAKE_TROUBLE);
1303 }
1304}
1305
1306
1307
1308void
1309output_init (struct output *out)
1310{
1311#ifdef DEBUG_STDOUT_CLOSE_ISSUE
1312 if (STREAM_OK (stdout) && ferror (stdout))
1313 my_stdout_error (out ? "output_init(out)" : "output_init(NULL)", "error pending entry!");
1314#endif
1315
1316 if (out)
1317 {
1318#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
1319 out->out.head_seg = NULL;
1320 out->out.tail_seg = NULL;
1321 out->out.head_run = NULL;
1322 out->out.tail_run = NULL;
1323 out->err.head_seg = NULL;
1324 out->err.tail_seg = NULL;
1325 out->err.head_run = NULL;
1326 out->err.tail_run = NULL;
1327 out->err.total = 0;
1328 out->out.total = 0;
1329 out->seqno = 0;
1330#else
1331 out->out = out->err = OUTPUT_NONE;
1332#endif
1333 out->syncout = !!output_sync;
1334#ifdef KMK
1335 out->dont_truncate = 0;
1336#endif
1337 return;
1338 }
1339
1340 /* Configure this instance of make. Be sure stdout is line-buffered. */
1341
1342#ifdef HAVE_SETVBUF
1343# ifdef SETVBUF_REVERSED
1344 setvbuf (stdout, _IOLBF, xmalloc (BUFSIZ), BUFSIZ);
1345# else /* setvbuf not reversed. */
1346 /* Some buggy systems lose if we pass 0 instead of allocating ourselves. */
1347 setvbuf (stdout, 0, _IOLBF, BUFSIZ);
1348# endif /* setvbuf reversed. */
1349#elif HAVE_SETLINEBUF
1350 setlinebuf (stdout);
1351#endif /* setlinebuf missing. */
1352
1353 /* Force stdout/stderr into append mode. This ensures parallel jobs won't
1354 lose output due to overlapping writes. */
1355 set_append_mode (fileno (stdout));
1356 set_append_mode (fileno (stderr));
1357
1358#ifdef DEBUG_STDOUT_CLOSE_ISSUE
1359 if (ferror (stdout))
1360 my_stdout_error ("output_init", "error pending on exit!");
1361# ifdef KBUILD_OS_WINDOWS
1362 {
1363 HANDLE const hStdOut = (HANDLE)_get_osfhandle(_fileno(stdout));
1364 DWORD const dwType = GetFileType(hStdOut);
1365 birdResolveImportsWorker();
1366 if ((dwType & ~FILE_TYPE_REMOTE) == FILE_TYPE_PIPE)
1367 {
1368 my_output_pipe_info (hStdOut, "output_init");
1369# if 0
1370 DWORD cbOutBuf = 0;
1371 DWORD cbInBuf = 0;
1372 BOOL const fRc2 = GetNamedPipeInfo(hStdOut, NULL, &cbOutBuf, &cbInBuf, NULL);
1373 if (cbInBuf != 0x1000)
1374 {
1375 DWORD dwMode = 0;
1376 if (GetNamedPipeHandleStateW(hStdOut, &dwMode, NULL, NULL, NULL, NULL, 0))
1377 {
1378 dwMode &= ~PIPE_WAIT;
1379 dwMode |= PIPE_NOWAIT;
1380 if (!SetNamedPipeHandleState(hStdOut, &dwMode, NULL, NULL))
1381 fprintf(stderr, "SetNamedPipeHandleState failed: %u\n", GetLastError());
1382 else
1383 {
1384 GetNamedPipeHandleStateW(hStdOut, &dwMode, NULL, NULL, NULL, NULL, 0);
1385 fprintf(stderr, "SetNamedPipeHandleState succeeded: %#x\n", dwMode);
1386 }
1387 }
1388 }
1389# endif
1390# endif
1391 }
1392 }
1393#endif
1394#ifdef HAVE_ATEXIT
1395 if (STREAM_OK (stdout))
1396 atexit (close_stdout);
1397#endif
1398}
1399
1400void
1401output_close (struct output *out)
1402{
1403 if (! out)
1404 {
1405 if (stdio_traced)
1406 log_working_directory (0);
1407 return;
1408 }
1409
1410#ifndef NO_OUTPUT_SYNC
1411 output_dump (out);
1412#endif
1413
1414#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
1415 assert (out->out.total == 0);
1416 assert (out->out.head_seg == NULL);
1417 assert (out->err.total == 0);
1418 assert (out->err.head_seg == NULL);
1419#else
1420 if (out->out >= 0)
1421 close (out->out);
1422 if (out->err >= 0 && out->err != out->out)
1423 close (out->err);
1424#endif
1425
1426 output_init (out);
1427}
1428
1429/* We're about to generate output: be sure it's set up. */
1430void
1431output_start (void)
1432{
1433#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
1434 /* If we're syncing output make sure the sempahore (win) is set up. */
1435 if (output_context && output_context->syncout)
1436 if (combined_output < 0)
1437 {
1438 combined_output = 0;
1439 combined_output = sync_init ();
1440 }
1441#else
1442#ifndef NO_OUTPUT_SYNC
1443 /* If we're syncing output make sure the temporary file is set up. */
1444 if (output_context && output_context->syncout)
1445 if (! OUTPUT_ISSET(output_context))
1446 setup_tmpfile (output_context);
1447#endif
1448#endif
1449
1450#ifndef KMK
1451 /* If we're not syncing this output per-line or per-target, make sure we emit
1452 the "Entering..." message where appropriate. */
1453 if (output_sync == OUTPUT_SYNC_NONE || output_sync == OUTPUT_SYNC_RECURSE)
1454#else
1455 /* Indiscriminately output "Entering..." and "Leaving..." message for each
1456 command line or target is plain annoying! And when there is no recursion
1457 it's actually inappropriate. Haven't got a simple way of detecting that,
1458 so back to the old behavior for now. [bird] */
1459#endif
1460 if (! stdio_traced && print_directory_flag)
1461 stdio_traced = log_working_directory (1);
1462}
1463
1464void
1465outputs (int is_err, const char *msg)
1466{
1467 if (! msg || *msg == '\0')
1468 return;
1469
1470 output_start ();
1471
1472 _outputs (output_context, is_err, msg);
1473}
1474
1475
1476
1477static struct fmtstring
1478 {
1479 char *buffer;
1480 size_t size;
1481 } fmtbuf = { NULL, 0 };
1482
1483static char *
1484get_buffer (size_t need)
1485{
1486 /* Make sure we have room. NEED includes space for \0. */
1487 if (need > fmtbuf.size)
1488 {
1489 fmtbuf.size += need * 2;
1490 fmtbuf.buffer = xrealloc (fmtbuf.buffer, fmtbuf.size);
1491 }
1492
1493 fmtbuf.buffer[need-1] = '\0';
1494
1495 return fmtbuf.buffer;
1496}
1497
1498/* Print a message on stdout. */
1499
1500void
1501message (int prefix, size_t len, const char *fmt, ...)
1502{
1503 va_list args;
1504 char *p;
1505
1506 len += strlen (fmt) + strlen (program) + INTSTR_LENGTH + 4 + 1 + 1;
1507 p = get_buffer (len);
1508
1509 if (prefix)
1510 {
1511 if (makelevel == 0)
1512 sprintf (p, "%s: ", program);
1513 else
1514 sprintf (p, "%s[%u]: ", program, makelevel);
1515 p += strlen (p);
1516 }
1517
1518 va_start (args, fmt);
1519 vsprintf (p, fmt, args);
1520 va_end (args);
1521
1522 strcat (p, "\n");
1523
1524 assert (fmtbuf.buffer[len-1] == '\0');
1525 outputs (0, fmtbuf.buffer);
1526}
1527
1528/* Print an error message. */
1529
1530void
1531error (const floc *flocp, size_t len, const char *fmt, ...)
1532{
1533 va_list args;
1534 char *p;
1535
1536 len += (strlen (fmt) + strlen (program)
1537 + (flocp && flocp->filenm ? strlen (flocp->filenm) : 0)
1538 + INTSTR_LENGTH + 4 + 1 + 1);
1539 p = get_buffer (len);
1540
1541 if (flocp && flocp->filenm)
1542 sprintf (p, "%s:%lu: ", flocp->filenm, flocp->lineno + flocp->offset);
1543 else if (makelevel == 0)
1544 sprintf (p, "%s: ", program);
1545 else
1546 sprintf (p, "%s[%u]: ", program, makelevel);
1547 p += strlen (p);
1548
1549 va_start (args, fmt);
1550 vsprintf (p, fmt, args);
1551 va_end (args);
1552
1553 strcat (p, "\n");
1554
1555 assert (fmtbuf.buffer[len-1] == '\0');
1556 outputs (1, fmtbuf.buffer);
1557}
1558
1559/* Print an error message and exit. */
1560
1561void
1562fatal (const floc *flocp, size_t len, const char *fmt, ...)
1563{
1564 va_list args;
1565 const char *stop = _(". Stop.\n");
1566 char *p;
1567
1568 len += (strlen (fmt) + strlen (program)
1569 + (flocp && flocp->filenm ? strlen (flocp->filenm) : 0)
1570 + INTSTR_LENGTH + 8 + strlen (stop) + 1);
1571 p = get_buffer (len);
1572
1573 if (flocp && flocp->filenm)
1574 sprintf (p, "%s:%lu: *** ", flocp->filenm, flocp->lineno + flocp->offset);
1575 else if (makelevel == 0)
1576 sprintf (p, "%s: *** ", program);
1577 else
1578 sprintf (p, "%s[%u]: *** ", program, makelevel);
1579 p += strlen (p);
1580
1581 va_start (args, fmt);
1582 vsprintf (p, fmt, args);
1583 va_end (args);
1584
1585 strcat (p, stop);
1586
1587 assert (fmtbuf.buffer[len-1] == '\0');
1588 outputs (1, fmtbuf.buffer);
1589
1590 die (MAKE_FAILURE);
1591}
1592
1593/* Print an error message from errno. */
1594
1595void
1596perror_with_name (const char *str, const char *name)
1597{
1598 const char *err = strerror (errno);
1599 OSSS (error, NILF, _("%s%s: %s"), str, name, err);
1600}
1601
1602/* Print an error message from errno and exit. */
1603
1604void
1605pfatal_with_name (const char *name)
1606{
1607 const char *err = strerror (errno);
1608 OSS (fatal, NILF, _("%s: %s"), name, err);
1609
1610 /* NOTREACHED */
1611}
Note: See TracBrowser for help on using the repository browser.