1/* Scan linker error messages for missing template instantiations and provide
2   them.
3
4   Copyright (C) 1995-2015 Free Software Foundation, Inc.
5   Contributed by Jason Merrill (jason@cygnus.com).
6
7This file is part of GCC.
8
9GCC is free software; you can redistribute it and/or modify it under
10the terms of the GNU General Public License as published by the Free
11Software Foundation; either version 3, or (at your option) any later
12version.
13
14GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15WARRANTY; without even the implied warranty of MERCHANTABILITY or
16FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17for more details.
18
19You should have received a copy of the GNU General Public License
20along with GCC; see the file COPYING3.  If not see
21<http://www.gnu.org/licenses/>.  */
22
23#include "config.h"
24#include "system.h"
25#include "coretypes.h"
26#include "tm.h"
27#include "intl.h"
28#include "obstack.h"
29#include "hashtab.h"
30#include "demangle.h"
31#include "collect2.h"
32#include "collect-utils.h"
33#include "filenames.h"
34#include "diagnostic-core.h"
35#include "vec.h"
36
37/* TARGET_64BIT may be defined to use driver specific functionality. */
38#undef TARGET_64BIT
39#define TARGET_64BIT TARGET_64BIT_DEFAULT
40
41#define MAX_ITERATIONS 17
42
43/* Defined in the automatically-generated underscore.c.  */
44extern int prepends_underscore;
45
46static int tlink_verbose;
47
48static char *initial_cwd;
49
50/* Hash table boilerplate for working with htab_t.  We have hash tables
51   for symbol names, file names, and demangled symbols.  */
52
53typedef struct symbol_hash_entry
54{
55  const char *key;
56  struct file_hash_entry *file;
57  int chosen;
58  int tweaking;
59  int tweaked;
60} symbol;
61
62typedef struct file_hash_entry
63{
64  const char *key;
65  const char *args;
66  const char *dir;
67  const char *main;
68  int tweaking;
69} file;
70
71typedef const char *str;
72
73typedef struct demangled_hash_entry
74{
75  const char *key;
76  vec<str> mangled;
77} demangled;
78
79/* Hash and comparison functions for these hash tables.  */
80
81static int hash_string_eq (const void *, const void *);
82static hashval_t hash_string_hash (const void *);
83
84static int
85hash_string_eq (const void *s1_p, const void *s2_p)
86{
87  const char *const *s1 = (const char *const *) s1_p;
88  const char *s2 = (const char *) s2_p;
89  return strcmp (*s1, s2) == 0;
90}
91
92static hashval_t
93hash_string_hash (const void *s_p)
94{
95  const char *const *s = (const char *const *) s_p;
96  return (*htab_hash_string) (*s);
97}
98
99static htab_t symbol_table;
100
101static struct symbol_hash_entry * symbol_hash_lookup (const char *, int);
102static struct file_hash_entry * file_hash_lookup (const char *);
103static struct demangled_hash_entry *demangled_hash_lookup (const char *, int);
104static void symbol_push (symbol *);
105static symbol * symbol_pop (void);
106static void file_push (file *);
107static file * file_pop (void);
108static char * frob_extension (const char *, const char *);
109static char * obstack_fgets (FILE *, struct obstack *);
110static char * tfgets (FILE *);
111static char * pfgets (FILE *);
112static void freadsym (FILE *, file *, int);
113static void read_repo_file (file *);
114static void maybe_tweak (char *, file *);
115static int recompile_files (void);
116static int read_repo_files (char **);
117static void demangle_new_symbols (void);
118static int scan_linker_output (const char *);
119
120/* Look up an entry in the symbol hash table.  */
121
122static struct symbol_hash_entry *
123symbol_hash_lookup (const char *string, int create)
124{
125  void **e;
126  e = htab_find_slot_with_hash (symbol_table, string,
127				(*htab_hash_string) (string),
128				create ? INSERT : NO_INSERT);
129  if (e == NULL)
130    return NULL;
131  if (*e == NULL)
132    {
133      struct symbol_hash_entry *v;
134      *e = v = XCNEW (struct symbol_hash_entry);
135      v->key = xstrdup (string);
136    }
137  return (struct symbol_hash_entry *) *e;
138}
139
140static htab_t file_table;
141
142/* Look up an entry in the file hash table.  */
143
144static struct file_hash_entry *
145file_hash_lookup (const char *string)
146{
147  void **e;
148  e = htab_find_slot_with_hash (file_table, string,
149				(*htab_hash_string) (string),
150				INSERT);
151  if (*e == NULL)
152    {
153      struct file_hash_entry *v;
154      *e = v = XCNEW (struct file_hash_entry);
155      v->key = xstrdup (string);
156    }
157  return (struct file_hash_entry *) *e;
158}
159
160static htab_t demangled_table;
161
162/* Look up an entry in the demangled name hash table.  */
163
164static struct demangled_hash_entry *
165demangled_hash_lookup (const char *string, int create)
166{
167  void **e;
168  e = htab_find_slot_with_hash (demangled_table, string,
169				(*htab_hash_string) (string),
170				create ? INSERT : NO_INSERT);
171  if (e == NULL)
172    return NULL;
173  if (*e == NULL)
174    {
175      struct demangled_hash_entry *v;
176      *e = v = XCNEW (struct demangled_hash_entry);
177      v->key = xstrdup (string);
178    }
179  return (struct demangled_hash_entry *) *e;
180}
181
182/* Stack code.  */
183
184struct symbol_stack_entry
185{
186  symbol *value;
187  struct symbol_stack_entry *next;
188};
189struct obstack symbol_stack_obstack;
190struct symbol_stack_entry *symbol_stack;
191
192struct file_stack_entry
193{
194  file *value;
195  struct file_stack_entry *next;
196};
197struct obstack file_stack_obstack;
198struct file_stack_entry *file_stack;
199
200static void
201symbol_push (symbol *p)
202{
203  struct symbol_stack_entry *ep
204    = XOBNEW (&symbol_stack_obstack, struct symbol_stack_entry);
205  ep->value = p;
206  ep->next = symbol_stack;
207  symbol_stack = ep;
208}
209
210static symbol *
211symbol_pop (void)
212{
213  struct symbol_stack_entry *ep = symbol_stack;
214  symbol *p;
215  if (ep == NULL)
216    return NULL;
217  p = ep->value;
218  symbol_stack = ep->next;
219  obstack_free (&symbol_stack_obstack, ep);
220  return p;
221}
222
223static void
224file_push (file *p)
225{
226  struct file_stack_entry *ep;
227
228  if (p->tweaking)
229    return;
230
231  ep = XOBNEW (&file_stack_obstack, struct file_stack_entry);
232  ep->value = p;
233  ep->next = file_stack;
234  file_stack = ep;
235  p->tweaking = 1;
236}
237
238static file *
239file_pop (void)
240{
241  struct file_stack_entry *ep = file_stack;
242  file *p;
243  if (ep == NULL)
244    return NULL;
245  p = ep->value;
246  file_stack = ep->next;
247  obstack_free (&file_stack_obstack, ep);
248  p->tweaking = 0;
249  return p;
250}
251
252/* Other machinery.  */
253
254/* Initialize the tlink machinery.  Called from do_tlink.  */
255
256static void
257tlink_init (void)
258{
259  const char *p;
260
261  symbol_table = htab_create (500, hash_string_hash, hash_string_eq,
262			      NULL);
263  file_table = htab_create (500, hash_string_hash, hash_string_eq,
264			    NULL);
265  demangled_table = htab_create (500, hash_string_hash, hash_string_eq,
266				 NULL);
267
268  obstack_begin (&symbol_stack_obstack, 0);
269  obstack_begin (&file_stack_obstack, 0);
270
271  p = getenv ("TLINK_VERBOSE");
272  if (p)
273    tlink_verbose = atoi (p);
274  else
275    {
276      tlink_verbose = 1;
277      if (verbose)
278	tlink_verbose = 2;
279      if (debug)
280	tlink_verbose = 3;
281    }
282
283  initial_cwd = getpwd ();
284}
285
286static int
287tlink_execute (const char *prog, char **argv, const char *outname,
288	       const char *errname, bool use_atfile)
289{
290  struct pex_obj *pex;
291
292  pex = collect_execute (prog, argv, outname, errname,
293			 PEX_LAST | PEX_SEARCH, use_atfile);
294  return collect_wait (prog, pex);
295}
296
297static char *
298frob_extension (const char *s, const char *ext)
299{
300  const char *p;
301
302  p = strrchr (lbasename (s), '.');
303  if (! p)
304    p = s + strlen (s);
305
306  obstack_grow (&temporary_obstack, s, p - s);
307  return (char *) obstack_copy0 (&temporary_obstack, ext, strlen (ext));
308}
309
310static char *
311obstack_fgets (FILE *stream, struct obstack *ob)
312{
313  int c;
314  while ((c = getc (stream)) != EOF && c != '\n')
315    obstack_1grow (ob, c);
316  if (obstack_object_size (ob) == 0)
317    return NULL;
318  obstack_1grow (ob, '\0');
319  return XOBFINISH (ob, char *);
320}
321
322static char *
323tfgets (FILE *stream)
324{
325  return obstack_fgets (stream, &temporary_obstack);
326}
327
328static char *
329pfgets (FILE *stream)
330{
331  return xstrdup (tfgets (stream));
332}
333
334/* Real tlink code.  */
335
336/* Subroutine of read_repo_file.  We are reading the repo file for file F,
337   which is coming in on STREAM, and the symbol that comes next in STREAM
338   is offered, chosen or provided if CHOSEN is 0, 1 or 2, respectively.
339
340   XXX "provided" is unimplemented, both here and in the compiler.  */
341
342static void
343freadsym (FILE *stream, file *f, int chosen)
344{
345  symbol *sym;
346
347  {
348    const char *name = tfgets (stream);
349    sym = symbol_hash_lookup (name, true);
350  }
351
352  if (sym->file == NULL)
353    {
354      /* We didn't have this symbol already, so we choose this file.  */
355
356      symbol_push (sym);
357      sym->file = f;
358      sym->chosen = chosen;
359    }
360  else if (chosen)
361    {
362      /* We want this file; cast aside any pretender.  */
363
364      if (sym->chosen && sym->file != f)
365	{
366	  if (sym->chosen == 1)
367	    file_push (sym->file);
368	  else
369	    {
370	      file_push (f);
371	      f = sym->file;
372	      chosen = sym->chosen;
373	    }
374	}
375      sym->file = f;
376      sym->chosen = chosen;
377    }
378}
379
380/* Read in the repo file denoted by F, and record all its information.  */
381
382static void
383read_repo_file (file *f)
384{
385  char c;
386  FILE *stream = fopen (f->key, "r");
387
388  if (tlink_verbose >= 2)
389    fprintf (stderr, _("collect: reading %s\n"), f->key);
390
391  while (fscanf (stream, "%c ", &c) == 1)
392    {
393      switch (c)
394	{
395	case 'A':
396	  f->args = pfgets (stream);
397	  break;
398	case 'D':
399	  f->dir = pfgets (stream);
400	  break;
401	case 'M':
402	  f->main = pfgets (stream);
403	  break;
404	case 'P':
405	  freadsym (stream, f, 2);
406	  break;
407	case 'C':
408	  freadsym (stream, f, 1);
409	  break;
410	case 'O':
411	  freadsym (stream, f, 0);
412	  break;
413	}
414      obstack_free (&temporary_obstack, temporary_firstobj);
415    }
416  fclose (stream);
417  if (f->args == NULL)
418    f->args = getenv ("COLLECT_GCC_OPTIONS");
419  if (f->dir == NULL)
420    f->dir = ".";
421}
422
423/* We might want to modify LINE, which is a symbol line from file F.  We do
424   this if either we saw an error message referring to the symbol in
425   question, or we have already allocated the symbol to another file and
426   this one wants to emit it as well.  */
427
428static void
429maybe_tweak (char *line, file *f)
430{
431  symbol *sym = symbol_hash_lookup (line + 2, false);
432
433  if ((sym->file == f && sym->tweaking)
434      || (sym->file != f && line[0] == 'C'))
435    {
436      sym->tweaking = 0;
437      sym->tweaked = 1;
438
439      if (line[0] == 'O')
440	{
441	  line[0] = 'C';
442	  sym->chosen = 1;
443	}
444      else
445	{
446	  line[0] = 'O';
447	  sym->chosen = 0;
448	}
449    }
450}
451
452/* Update the repo files for each of the object files we have adjusted and
453   recompile.  */
454
455static int
456recompile_files (void)
457{
458  file *f;
459
460  putenv (xstrdup ("COMPILER_PATH="));
461  putenv (xstrdup ("LIBRARY_PATH="));
462
463  while ((f = file_pop ()) != NULL)
464    {
465      char *line;
466      const char *p, *q;
467      char **argv;
468      struct obstack arg_stack;
469      FILE *stream = fopen (f->key, "r");
470      const char *const outname = frob_extension (f->key, ".rnw");
471      FILE *output = fopen (outname, "w");
472
473      while ((line = tfgets (stream)) != NULL)
474	{
475	  switch (line[0])
476	    {
477	    case 'C':
478	    case 'O':
479	      maybe_tweak (line, f);
480	    }
481	  fprintf (output, "%s\n", line);
482	}
483      fclose (stream);
484      fclose (output);
485      /* On Windows "rename" returns -1 and sets ERRNO to EACCESS if
486	 the new file name already exists.  Therefore, we explicitly
487	 remove the old file first.  */
488      if (remove (f->key) == -1)
489	fatal_error (input_location, "removing .rpo file: %m");
490      if (rename (outname, f->key) == -1)
491	fatal_error (input_location, "renaming .rpo file: %m");
492
493      if (!f->args)
494	{
495	  error ("repository file '%s' does not contain command-line "
496		 "arguments", f->key);
497	  return 0;
498	}
499
500      /* Build a null-terminated argv array suitable for
501	 tlink_execute().  Manipulate arguments on the arg_stack while
502	 building argv on the temporary_obstack.  */
503
504      obstack_init (&arg_stack);
505      obstack_ptr_grow (&temporary_obstack, c_file_name);
506
507      for (p = f->args; *p != '\0'; p = q + 1)
508	{
509	  /* Arguments are delimited by single-quotes.  Find the
510	     opening quote.  */
511	  p = strchr (p, '\'');
512	  if (!p)
513	    goto done;
514
515	  /* Find the closing quote.  */
516	  q = strchr (p + 1, '\'');
517	  if (!q)
518	    goto done;
519
520	  obstack_grow (&arg_stack, p + 1, q - (p + 1));
521
522	  /* Replace '\'' with '.  This is how set_collect_gcc_options
523	     encodes a single-quote.  */
524	  while (q[1] == '\\' && q[2] == '\'' && q[3] == '\'')
525	    {
526	      const char *r;
527
528	      r = strchr (q + 4, '\'');
529	      if (!r)
530		goto done;
531
532	      obstack_grow (&arg_stack, q + 3, r - (q + 3));
533	      q = r;
534	    }
535
536	  obstack_1grow (&arg_stack, '\0');
537	  obstack_ptr_grow (&temporary_obstack, obstack_finish (&arg_stack));
538	}
539    done:
540      obstack_ptr_grow (&temporary_obstack, f->main);
541      obstack_ptr_grow (&temporary_obstack, NULL);
542      argv = XOBFINISH (&temporary_obstack, char **);
543
544      if (tlink_verbose)
545	fprintf (stderr, _("collect: recompiling %s\n"), f->main);
546
547      if (chdir (f->dir) != 0
548	  || tlink_execute (c_file_name, argv, NULL, NULL, false) != 0
549	  || chdir (initial_cwd) != 0)
550	return 0;
551
552      read_repo_file (f);
553
554      obstack_free (&arg_stack, NULL);
555      obstack_free (&temporary_obstack, temporary_firstobj);
556    }
557  return 1;
558}
559
560/* The first phase of processing: determine which object files have
561   .rpo files associated with them, and read in the information.  */
562
563static int
564read_repo_files (char **object_lst)
565{
566  char **object = object_lst;
567
568  for (; *object; object++)
569    {
570      const char *p;
571      file *f;
572
573      /* Don't bother trying for ld flags.  */
574      if (*object[0] == '-')
575	continue;
576
577      p = frob_extension (*object, ".rpo");
578
579      if (! file_exists (p))
580	continue;
581
582      f = file_hash_lookup (p);
583
584      read_repo_file (f);
585    }
586
587  if (file_stack != NULL && ! recompile_files ())
588    return 0;
589
590  return (symbol_stack != NULL);
591}
592
593/* Add the demangled forms of any new symbols to the hash table.  */
594
595static void
596demangle_new_symbols (void)
597{
598  symbol *sym;
599
600  while ((sym = symbol_pop ()) != NULL)
601    {
602      demangled *dem;
603      const char *p = cplus_demangle (sym->key, DMGL_PARAMS | DMGL_ANSI);
604
605      if (! p)
606	continue;
607
608      dem = demangled_hash_lookup (p, true);
609      dem->mangled.safe_push (sym->key);
610    }
611}
612
613/* We want to tweak symbol SYM.  Return true if all is well, false on
614   error.  */
615
616static bool
617start_tweaking (symbol *sym)
618{
619  if (sym && sym->tweaked)
620    {
621      error ("'%s' was assigned to '%s', but was not defined "
622	     "during recompilation, or vice versa",
623	     sym->key, sym->file->key);
624      return 0;
625    }
626  if (sym && !sym->tweaking)
627    {
628      if (tlink_verbose >= 2)
629	fprintf (stderr, _("collect: tweaking %s in %s\n"),
630		 sym->key, sym->file->key);
631      sym->tweaking = 1;
632      file_push (sym->file);
633    }
634  return true;
635}
636
637/* Step through the output of the linker, in the file named FNAME, and
638   adjust the settings for each symbol encountered.  */
639
640static int
641scan_linker_output (const char *fname)
642{
643  FILE *stream = fopen (fname, "r");
644  char *line;
645  int skip_next_in_line = 0;
646
647  while ((line = tfgets (stream)) != NULL)
648    {
649      char *p = line, *q;
650      symbol *sym;
651      demangled *dem = 0;
652      int end;
653      int ok = 0;
654      unsigned ix;
655      str s;
656
657      /* On darwin9, we might have to skip " in " lines as well.  */
658      if (skip_next_in_line
659	  && strstr (p, " in "))
660	  continue;
661      skip_next_in_line = 0;
662
663      while (*p && ISSPACE ((unsigned char) *p))
664	++p;
665
666      if (! *p)
667	continue;
668
669      for (q = p; *q && ! ISSPACE ((unsigned char) *q); ++q)
670	;
671
672      /* Try the first word on the line.  */
673      if (*p == '.')
674	++p;
675      if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
676	p += strlen (USER_LABEL_PREFIX);
677
678      end = ! *q;
679      *q = 0;
680      sym = symbol_hash_lookup (p, false);
681
682      /* Some SVR4 linkers produce messages like
683	 ld: 0711-317 ERROR: Undefined symbol: .g__t3foo1Zi
684	 */
685      if (! sym && ! end && strstr (q + 1, "Undefined symbol: "))
686	{
687	  char *p = strrchr (q + 1, ' ');
688	  p++;
689	  if (*p == '.')
690	    p++;
691	  if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
692	    p += strlen (USER_LABEL_PREFIX);
693	  sym = symbol_hash_lookup (p, false);
694	}
695
696      if (! sym && ! end)
697	/* Try a mangled name in quotes.  */
698	{
699	  char *oldq = q + 1;
700	  q = 0;
701
702	  /* On darwin9, we look for "foo" referenced from:\n\(.* in .*\n\)*  */
703	  if (strcmp (oldq, "referenced from:") == 0)
704	    {
705	      /* We have to remember that we found a symbol to tweak.  */
706	      ok = 1;
707
708	      /* We actually want to start from the first word on the
709		 line.  */
710	      oldq = p;
711
712	      /* Since the format is multiline, we have to skip
713		 following lines with " in ".  */
714	      skip_next_in_line = 1;
715	    }
716
717	  /* First try `GNU style'.  */
718	  p = strchr (oldq, '`');
719	  if (p)
720	    p++, q = strchr (p, '\'');
721	  /* Then try "double quotes".  */
722	  else if (p = strchr (oldq, '"'), p)
723	    p++, q = strchr (p, '"');
724	  /* Then try 'single quotes'.  */
725	  else if (p = strchr (oldq, '\''), p)
726	    p++, q = strchr (p, '\'');
727	  else {
728	    /* Then try entire line.  */
729	    q = strchr (oldq, 0);
730	    if (q != oldq)
731	      p = (char *)oldq;
732	  }
733
734	  if (p)
735	    {
736	      /* Don't let the strstr's below see the demangled name; we
737		 might get spurious matches.  */
738	      p[-1] = '\0';
739
740	      /* powerpc64-linux references .foo when calling function foo.  */
741	      if (*p == '.')
742		p++;
743	    }
744
745	  /* We need to check for certain error keywords here, or we would
746	     mistakenly use GNU ld's "In function `foo':" message.  */
747	  if (q && (ok
748		    || strstr (oldq, "ndefined")
749		    || strstr (oldq, "nresolved")
750		    || strstr (oldq, "nsatisfied")
751		    || strstr (oldq, "ultiple")))
752	    {
753	      *q = 0;
754	      dem = demangled_hash_lookup (p, false);
755	      if (!dem)
756		{
757		  if (!strncmp (p, USER_LABEL_PREFIX,
758				strlen (USER_LABEL_PREFIX)))
759		    p += strlen (USER_LABEL_PREFIX);
760		  sym = symbol_hash_lookup (p, false);
761		}
762	    }
763	}
764
765      if (dem)
766	{
767	  /* We found a demangled name.  If this is the name of a
768	     constructor or destructor, there can be several mangled names
769	     that match it, so choose or unchoose all of them.  If some are
770	     chosen and some not, leave the later ones that don't match
771	     alone for now; either this will cause the link to succeed, or
772	     on the next attempt we will switch all of them the other way
773	     and that will cause it to succeed.  */
774	  int chosen = 0;
775	  int len = dem->mangled.length ();
776	  ok = true;
777	  FOR_EACH_VEC_ELT (dem->mangled, ix, s)
778	    {
779	      sym = symbol_hash_lookup (s, false);
780	      if (ix == 0)
781		chosen = sym->chosen;
782	      else if (sym->chosen != chosen)
783		/* Mismatch.  */
784		continue;
785	      /* Avoid an error about re-tweaking when we guess wrong in
786		 the case of mismatch.  */
787	      if (len > 1)
788		sym->tweaked = false;
789	      ok = start_tweaking (sym);
790	    }
791	}
792      else
793	ok = start_tweaking (sym);
794
795      obstack_free (&temporary_obstack, temporary_firstobj);
796
797      if (!ok)
798	{
799	  fclose (stream);
800	  return 0;
801	}
802    }
803
804  fclose (stream);
805  return (file_stack != NULL);
806}
807
808/* Entry point for tlink.  Called from main in collect2.c.
809
810   Iteratively try to provide definitions for all the unresolved symbols
811   mentioned in the linker error messages.
812
813   LD_ARGV is an array of arguments for the linker.
814   OBJECT_LST is an array of object files that we may be able to recompile
815     to provide missing definitions.  Currently ignored.  */
816
817void
818do_tlink (char **ld_argv, char **object_lst ATTRIBUTE_UNUSED)
819{
820  int ret = tlink_execute ("ld", ld_argv, ldout, lderrout,
821			   HAVE_GNU_LD && at_file_supplied);
822
823  tlink_init ();
824
825  if (ret)
826    {
827      int i = 0;
828
829      /* Until collect does a better job of figuring out which are object
830	 files, assume that everything on the command line could be.  */
831      if (read_repo_files (ld_argv))
832	while (ret && i++ < MAX_ITERATIONS)
833	  {
834	    if (tlink_verbose >= 3)
835	      {
836		dump_ld_file (ldout, stdout);
837		dump_ld_file (lderrout, stderr);
838	      }
839	    demangle_new_symbols ();
840	    if (! scan_linker_output (ldout)
841		&& ! scan_linker_output (lderrout))
842	      break;
843	    if (! recompile_files ())
844	      break;
845	    if (tlink_verbose)
846	      fprintf (stderr, _("collect: relinking\n"));
847	    ret = tlink_execute ("ld", ld_argv, ldout, lderrout,
848				 HAVE_GNU_LD && at_file_supplied);
849	  }
850    }
851
852  dump_ld_file (ldout, stdout);
853  unlink (ldout);
854  dump_ld_file (lderrout, stderr);
855  unlink (lderrout);
856  if (ret)
857    {
858      error ("ld returned %d exit status", ret);
859      exit (ret);
860    }
861  else
862    {
863      /* We have just successfully produced an output file, so assume that we
864	 may unlink it if need be for now on.  */
865      may_unlink_output_file = true;
866    }
867}
868