1/* Scan linker error messages for missing template instantiations and provide
2   them.
3
4   Copyright (C) 1995, 1998 Free Software Foundation, Inc.
5   Contributed by Jason Merrill (jason@cygnus.com).
6
7This file is part of GNU CC.
8
9GNU CC is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2, or (at your option)
12any later version.
13
14GNU CC is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with GNU CC; see the file COPYING.  If not, write to
21the Free Software Foundation, 59 Temple Place - Suite 330,
22Boston, MA 02111-1307, USA.  */
23
24#include "config.h"
25#include "system.h"
26#include "hash.h"
27#include "demangle.h"
28#include "toplev.h"
29#include "collect2.h"
30
31#define MAX_ITERATIONS 17
32
33/* Obstack allocation and deallocation routines.  */
34#define obstack_chunk_alloc xmalloc
35#define obstack_chunk_free free
36
37/* Defined in collect2.c.  */
38extern int vflag, debug;
39extern char *ldout;
40extern char *c_file_name;
41extern struct obstack temporary_obstack;
42extern struct obstack permanent_obstack;
43extern char * temporary_firstobj;
44
45/* Defined in the automatically-generated underscore.c.  */
46extern int prepends_underscore;
47
48static int tlink_verbose;
49
50/* Hash table boilerplate for working with hash.[ch].  We have hash tables
51   for symbol names, file names, and demangled symbols.  */
52
53typedef struct symbol_hash_entry
54{
55  struct hash_entry root;
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  struct hash_entry root;
65  const char *args;
66  const char *dir;
67  const char *main;
68  int tweaking;
69} file;
70
71typedef struct demangled_hash_entry
72{
73  struct hash_entry root;
74  const char *mangled;
75} demangled;
76
77static struct hash_table symbol_table;
78
79static struct hash_entry * symbol_hash_newfunc PARAMS ((struct hash_entry *,
80							struct hash_table *,
81							hash_table_key));
82static struct symbol_hash_entry * symbol_hash_lookup PARAMS ((const char *,
83							      boolean));
84static struct hash_entry * file_hash_newfunc PARAMS ((struct hash_entry *,
85						      struct hash_table *,
86						      hash_table_key));
87static struct file_hash_entry * file_hash_lookup PARAMS ((const char *));
88static struct hash_entry * demangled_hash_newfunc PARAMS ((struct hash_entry *,
89							   struct hash_table *,
90							   hash_table_key));
91static struct demangled_hash_entry *
92  demangled_hash_lookup PARAMS ((const char *, boolean));
93static void symbol_push PARAMS ((symbol *));
94static symbol * symbol_pop PARAMS ((void));
95static void file_push PARAMS ((file *));
96static file * file_pop PARAMS ((void));
97static void tlink_init PARAMS ((void));
98static int tlink_execute PARAMS ((char *, char **, char *));
99static char * frob_extension PARAMS ((char *, const char *));
100static char * obstack_fgets PARAMS ((FILE *, struct obstack *));
101static char * tfgets PARAMS ((FILE *));
102static char * pfgets PARAMS ((FILE *));
103static void freadsym PARAMS ((FILE *, file *, int));
104static void read_repo_file PARAMS ((file *));
105static void maybe_tweak PARAMS ((char *, file *));
106static int recompile_files PARAMS ((void));
107static int read_repo_files PARAMS ((char **));
108static void demangle_new_symbols PARAMS ((void));
109static int scan_linker_output PARAMS ((const char *));
110
111/* Create a new entry for the symbol hash table.
112   Passed to hash_table_init.  */
113
114static struct hash_entry *
115symbol_hash_newfunc (entry, table, string)
116     struct hash_entry *entry;
117     struct hash_table *table;
118     hash_table_key string;
119{
120  struct symbol_hash_entry *ret = (struct symbol_hash_entry *) entry;
121  if (ret == NULL)
122    {
123      ret = ((struct symbol_hash_entry *)
124	     hash_allocate (table, sizeof (struct symbol_hash_entry)));
125      if (ret == NULL)
126	return NULL;
127    }
128  ret->file = NULL;
129  ret->chosen = 0;
130  ret->tweaking = 0;
131  ret->tweaked = 0;
132  return (struct hash_entry *) ret;
133}
134
135/* Look up an entry in the symbol hash table.  */
136
137static struct symbol_hash_entry *
138symbol_hash_lookup (string, create)
139     const char *string;
140     boolean create;
141{
142  return ((struct symbol_hash_entry *)
143	  hash_lookup (&symbol_table, (hash_table_key) string,
144		       create, &string_copy));
145}
146
147static struct hash_table file_table;
148
149/* Create a new entry for the file hash table.
150   Passed to hash_table_init.  */
151
152static struct hash_entry *
153file_hash_newfunc (entry, table, string)
154     struct hash_entry *entry;
155     struct hash_table *table;
156     hash_table_key string;
157{
158   struct file_hash_entry *ret = (struct file_hash_entry *) entry;
159  if (ret == NULL)
160    {
161      ret = ((struct file_hash_entry *)
162	     hash_allocate (table, sizeof (struct file_hash_entry)));
163      if (ret == NULL)
164	return NULL;
165    }
166  ret->args = NULL;
167  ret->dir = NULL;
168  ret->main = NULL;
169  ret->tweaking = 0;
170  return (struct hash_entry *) ret;
171}
172
173/* Look up an entry in the file hash table.  */
174
175static struct file_hash_entry *
176file_hash_lookup (string)
177     const char *string;
178{
179  return ((struct file_hash_entry *)
180	  hash_lookup (&file_table, (hash_table_key) string, true,
181		       &string_copy));
182}
183
184static struct hash_table demangled_table;
185
186/* Create a new entry for the demangled name hash table.
187   Passed to hash_table_init.  */
188
189static struct hash_entry *
190demangled_hash_newfunc (entry, table, string)
191     struct hash_entry *entry;
192     struct hash_table *table;
193     hash_table_key string;
194{
195  struct demangled_hash_entry *ret = (struct demangled_hash_entry *) entry;
196  if (ret == NULL)
197    {
198      ret = ((struct demangled_hash_entry *)
199	     hash_allocate (table, sizeof (struct demangled_hash_entry)));
200      if (ret == NULL)
201	return NULL;
202    }
203  ret->mangled = NULL;
204  return (struct hash_entry *) ret;
205}
206
207/* Look up an entry in the demangled name hash table.  */
208
209static struct demangled_hash_entry *
210demangled_hash_lookup (string, create)
211     const char *string;
212     boolean create;
213{
214  return ((struct demangled_hash_entry *)
215	  hash_lookup (&demangled_table, (hash_table_key) string,
216		       create, &string_copy));
217}
218
219/* Stack code.  */
220
221struct symbol_stack_entry
222{
223  symbol *value;
224  struct symbol_stack_entry *next;
225};
226struct obstack symbol_stack_obstack;
227struct symbol_stack_entry *symbol_stack;
228
229struct file_stack_entry
230{
231  file *value;
232  struct file_stack_entry *next;
233};
234struct obstack file_stack_obstack;
235struct file_stack_entry *file_stack;
236
237static void
238symbol_push (p)
239     symbol *p;
240{
241  struct symbol_stack_entry *ep = (struct symbol_stack_entry *) obstack_alloc
242    (&symbol_stack_obstack, sizeof (struct symbol_stack_entry));
243  ep->value = p;
244  ep->next = symbol_stack;
245  symbol_stack = ep;
246}
247
248static symbol *
249symbol_pop ()
250{
251  struct symbol_stack_entry *ep = symbol_stack;
252  symbol *p;
253  if (ep == NULL)
254    return NULL;
255  p = ep->value;
256  symbol_stack = ep->next;
257  obstack_free (&symbol_stack_obstack, ep);
258  return p;
259}
260
261static void
262file_push (p)
263     file *p;
264{
265  struct file_stack_entry *ep;
266
267  if (p->tweaking)
268    return;
269
270  ep = (struct file_stack_entry *) obstack_alloc
271    (&file_stack_obstack, sizeof (struct file_stack_entry));
272  ep->value = p;
273  ep->next = file_stack;
274  file_stack = ep;
275  p->tweaking = 1;
276}
277
278static file *
279file_pop ()
280{
281  struct file_stack_entry *ep = file_stack;
282  file *p;
283  if (ep == NULL)
284    return NULL;
285  p = ep->value;
286  file_stack = ep->next;
287  obstack_free (&file_stack_obstack, ep);
288  p->tweaking = 0;
289  return p;
290}
291
292/* Other machinery.  */
293
294/* Initialize the tlink machinery.  Called from do_tlink.  */
295
296static void
297tlink_init ()
298{
299  char *p;
300
301  hash_table_init (&symbol_table, symbol_hash_newfunc, &string_hash,
302		   &string_compare);
303  hash_table_init (&file_table, file_hash_newfunc, &string_hash,
304		   &string_compare);
305  hash_table_init (&demangled_table, demangled_hash_newfunc,
306		   &string_hash, &string_compare);
307  obstack_begin (&symbol_stack_obstack, 0);
308  obstack_begin (&file_stack_obstack, 0);
309
310  p = getenv ("TLINK_VERBOSE");
311  if (p)
312    tlink_verbose = atoi (p);
313  else
314    {
315      tlink_verbose = 1;
316      if (vflag)
317	tlink_verbose = 2;
318      if (debug)
319	tlink_verbose = 3;
320    }
321}
322
323static int
324tlink_execute (prog, argv, redir)
325     char *prog;
326     char **argv;
327     char *redir;
328{
329  collect_execute (prog, argv, redir);
330  return collect_wait (prog);
331}
332
333static char *
334frob_extension (s, ext)
335     char *s;
336     const char *ext;
337{
338  char *p = rindex (s, '/');
339  if (! p)
340    p = s;
341  p = rindex (p, '.');
342  if (! p)
343    p = s + strlen (s);
344
345  obstack_grow (&temporary_obstack, s, p - s);
346  return obstack_copy0 (&temporary_obstack, ext, strlen (ext));
347}
348
349static char *
350obstack_fgets (stream, ob)
351     FILE *stream;
352     struct obstack *ob;
353{
354  int c;
355  while ((c = getc (stream)) != EOF && c != '\n')
356    obstack_1grow (ob, c);
357  if (obstack_object_size (ob) == 0)
358    return NULL;
359  obstack_1grow (ob, '\0');
360  return obstack_finish (ob);
361}
362
363static char *
364tfgets (stream)
365     FILE *stream;
366{
367  return obstack_fgets (stream, &temporary_obstack);
368}
369
370static char *
371pfgets (stream)
372     FILE *stream;
373{
374  return obstack_fgets (stream, &permanent_obstack);
375}
376
377/* Real tlink code.  */
378
379/* Subroutine of read_repo_file.  We are reading the repo file for file F,
380   which is coming in on STREAM, and the symbol that comes next in STREAM
381   is offerred, chosen or provided if CHOSEN is 0, 1 or 2, respectively.
382
383   XXX "provided" is unimplemented, both here and in the compiler.  */
384
385static void
386freadsym (stream, f, chosen)
387     FILE *stream;
388     file *f;
389     int chosen;
390{
391  symbol *sym;
392
393  {
394    char *name = tfgets (stream);
395    sym = symbol_hash_lookup (name, true);
396  }
397
398  if (sym->file == NULL)
399    {
400      /* We didn't have this symbol already, so we choose this file.  */
401
402      symbol_push (sym);
403      sym->file = f;
404      sym->chosen = chosen;
405    }
406  else if (chosen)
407    {
408      /* We want this file; cast aside any pretender.  */
409
410      if (sym->chosen && sym->file != f)
411	{
412	  if (sym->chosen == 1)
413	    file_push (sym->file);
414	  else
415	    {
416	      file_push (f);
417	      f = sym->file;
418	      chosen = sym->chosen;
419	    }
420	}
421      sym->file = f;
422      sym->chosen = chosen;
423    }
424}
425
426/* Read in the repo file denoted by F, and record all its information.  */
427
428static void
429read_repo_file (f)
430     file *f;
431{
432  char c;
433  FILE *stream = fopen ((char*) f->root.key, "r");
434
435  if (tlink_verbose >= 2)
436    fprintf (stderr, "collect: reading %s\n",
437	     (char*) f->root.key);
438
439  while (fscanf (stream, "%c ", &c) == 1)
440    {
441      switch (c)
442	{
443	case 'A':
444	  f->args = pfgets (stream);
445	  break;
446	case 'D':
447	  f->dir = pfgets (stream);
448	  break;
449	case 'M':
450	  f->main = pfgets (stream);
451	  break;
452	case 'P':
453	  freadsym (stream, f, 2);
454	  break;
455	case 'C':
456	  freadsym (stream, f, 1);
457	  break;
458	case 'O':
459	  freadsym (stream, f, 0);
460	  break;
461	}
462      obstack_free (&temporary_obstack, temporary_firstobj);
463    }
464  fclose (stream);
465  if (f->args == NULL)
466    f->args = getenv ("COLLECT_GCC_OPTIONS");
467  if (f->dir == NULL)
468    f->dir = ".";
469}
470
471/* We might want to modify LINE, which is a symbol line from file F.  We do
472   this if either we saw an error message referring to the symbol in
473   question, or we have already allocated the symbol to another file and
474   this one wants to emit it as well.  */
475
476static void
477maybe_tweak (line, f)
478     char *line;
479     file *f;
480{
481  symbol *sym = symbol_hash_lookup (line + 2, false);
482
483  if ((sym->file == f && sym->tweaking)
484      || (sym->file != f && line[0] == 'C'))
485    {
486      sym->tweaking = 0;
487      sym->tweaked = 1;
488
489      if (line[0] == 'O')
490	line[0] = 'C';
491      else
492	line[0] = 'O';
493    }
494}
495
496/* Update the repo files for each of the object files we have adjusted and
497   recompile.
498
499   XXX Should this use collect_execute instead of system?  */
500
501static int
502recompile_files ()
503{
504  file *f;
505
506  while ((f = file_pop ()) != NULL)
507    {
508      char *line, *command;
509      FILE *stream = fopen ((char*) f->root.key, "r");
510      char *outname = frob_extension ((char*) f->root.key, ".rnw");
511      FILE *output = fopen (outname, "w");
512
513      while ((line = tfgets (stream)) != NULL)
514	{
515	  switch (line[0])
516	    {
517	    case 'C':
518	    case 'O':
519	      maybe_tweak (line, f);
520	    }
521	  fprintf (output, "%s\n", line);
522	}
523      fclose (stream);
524      fclose (output);
525      rename (outname, (char*) f->root.key);
526
527      obstack_grow (&temporary_obstack, "cd ", 3);
528      obstack_grow (&temporary_obstack, f->dir, strlen (f->dir));
529      obstack_grow (&temporary_obstack, "; ", 2);
530      obstack_grow (&temporary_obstack, c_file_name, strlen (c_file_name));
531      obstack_1grow (&temporary_obstack, ' ');
532      obstack_grow (&temporary_obstack, f->args, strlen (f->args));
533      obstack_1grow (&temporary_obstack, ' ');
534      command = obstack_copy0 (&temporary_obstack, f->main, strlen (f->main));
535
536      if (tlink_verbose)
537	fprintf (stderr, "collect: recompiling %s\n", f->main);
538      if (tlink_verbose >= 3)
539	fprintf (stderr, "%s\n", command);
540
541      if (system (command) != 0)
542	return 0;
543
544      read_repo_file (f);
545
546      obstack_free (&temporary_obstack, temporary_firstobj);
547    }
548  return 1;
549}
550
551/* The first phase of processing: determine which object files have
552   .rpo files associated with them, and read in the information.  */
553
554static int
555read_repo_files (object_lst)
556     char **object_lst;
557{
558  char **object = object_lst;
559
560  for (; *object; object++)
561    {
562      char *p = frob_extension (*object, ".rpo");
563      file *f;
564
565      if (! file_exists (p))
566	continue;
567
568      f = file_hash_lookup (p);
569
570      read_repo_file (f);
571    }
572
573  if (file_stack != NULL && ! recompile_files ())
574    return 0;
575
576  return (symbol_stack != NULL);
577}
578
579/* Add the demangled forms of any new symbols to the hash table.  */
580
581static void
582demangle_new_symbols ()
583{
584  symbol *sym;
585
586  while ((sym = symbol_pop ()) != NULL)
587    {
588      demangled *dem;
589      char *p = cplus_demangle ((char*) sym->root.key,
590				DMGL_PARAMS | DMGL_ANSI);
591
592      if (! p)
593	continue;
594
595      dem = demangled_hash_lookup (p, true);
596      dem->mangled = (char*) sym->root.key;
597    }
598}
599
600/* Step through the output of the linker, in the file named FNAME, and
601   adjust the settings for each symbol encountered.  */
602
603static int
604scan_linker_output (fname)
605     const char *fname;
606{
607  FILE *stream = fopen (fname, "r");
608  char *line;
609
610  while ((line = tfgets (stream)) != NULL)
611    {
612      char *p = line, *q;
613      symbol *sym;
614      int end;
615
616      while (*p && ISSPACE ((unsigned char)*p))
617	++p;
618
619      if (! *p)
620	continue;
621
622      for (q = p; *q && ! ISSPACE ((unsigned char)*q); ++q)
623	;
624
625      /* Try the first word on the line.  */
626      if (*p == '.')
627	++p;
628      if (*p == '_' && prepends_underscore)
629	++p;
630
631      end = ! *q;
632      *q = 0;
633      sym = symbol_hash_lookup (p, false);
634
635      if (! sym && ! end)
636	/* Try a mangled name in quotes.  */
637	{
638	  char *oldq = q+1;
639	  demangled *dem = 0;
640	  q = 0;
641
642	  /* First try `GNU style'.  */
643	  p = index (oldq, '`');
644	  if (p)
645	    p++, q = index (p, '\'');
646	  /* Then try "double quotes".  */
647	  else if (p = index (oldq, '"'), p)
648	    p++, q = index (p, '"');
649
650	  if (q)
651	    {
652	      *q = 0;
653	      dem = demangled_hash_lookup (p, false);
654	      if (dem)
655		sym = symbol_hash_lookup (dem->mangled, false);
656	      else
657	        {
658	          if (*p == '_' && prepends_underscore)
659		    ++p;
660		  sym = symbol_hash_lookup (p, false);
661		}
662	    }
663	}
664
665      if (sym && sym->tweaked)
666	{
667	  fclose (stream);
668	  return 0;
669	}
670      if (sym && !sym->tweaking)
671	{
672	  if (tlink_verbose >= 2)
673	    fprintf (stderr, "collect: tweaking %s in %s\n",
674		     (char*) sym->root.key, (char*) sym->file->root.key);
675	  sym->tweaking = 1;
676	  file_push (sym->file);
677	}
678
679      obstack_free (&temporary_obstack, temporary_firstobj);
680    }
681
682  fclose (stream);
683  return (file_stack != NULL);
684}
685
686/* Entry point for tlink.  Called from main in collect2.c.
687
688   Iteratively try to provide definitions for all the unresolved symbols
689   mentioned in the linker error messages.
690
691   LD_ARGV is an array of arguments for the linker.
692   OBJECT_LST is an array of object files that we may be able to recompile
693     to provide missing definitions.  Currently ignored.  */
694
695void
696do_tlink (ld_argv, object_lst)
697     char **ld_argv, **object_lst;
698{
699  int exit = tlink_execute ("ld", ld_argv, ldout);
700
701  tlink_init ();
702
703  if (exit)
704    {
705      int i = 0;
706
707      /* Until collect does a better job of figuring out which are object
708	 files, assume that everything on the command line could be.  */
709      if (read_repo_files (ld_argv))
710	while (exit && i++ < MAX_ITERATIONS)
711	  {
712	    if (tlink_verbose >= 3)
713	      dump_file (ldout);
714	    demangle_new_symbols ();
715	    if (! scan_linker_output (ldout))
716	      break;
717	    if (! recompile_files ())
718	      break;
719	    if (tlink_verbose)
720	      fprintf (stderr, "collect: relinking\n");
721	    exit = tlink_execute ("ld", ld_argv, ldout);
722	  }
723    }
724
725  dump_file (ldout);
726  unlink (ldout);
727  if (exit)
728    {
729      error ("ld returned %d exit status", exit);
730      collect_exit (exit);
731    }
732}
733