Remove the last vestiges of -DCCVER from 2.95.x contrib so we can remove
[dragonfly.git] / contrib / gcc / tlink.c
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
7 This file is part of GNU CC.
8
9 GNU CC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 GNU CC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GNU CC; see the file COPYING.  If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, 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.  */
38 extern int vflag, debug;
39 extern char *ldout;
40 extern char *c_file_name;
41 extern struct obstack temporary_obstack;
42 extern struct obstack permanent_obstack;
43 extern char * temporary_firstobj;
44
45 /* Defined in the automatically-generated underscore.c.  */
46 extern int prepends_underscore;
47
48 static int tlink_verbose;
49 \f
50 /* Hash table boilerplate for working with hash.[ch].  We have hash tables
51    for symbol names, file names, and demangled symbols.  */
52
53 typedef 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
62 typedef 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
71 typedef struct demangled_hash_entry
72 {
73   struct hash_entry root;
74   const char *mangled;
75 } demangled;
76
77 static struct hash_table symbol_table;
78
79 static struct hash_entry * symbol_hash_newfunc PARAMS ((struct hash_entry *,
80                                                         struct hash_table *,
81                                                         hash_table_key));
82 static struct symbol_hash_entry * symbol_hash_lookup PARAMS ((const char *,
83                                                               boolean));
84 static struct hash_entry * file_hash_newfunc PARAMS ((struct hash_entry *,
85                                                       struct hash_table *,
86                                                       hash_table_key));
87 static struct file_hash_entry * file_hash_lookup PARAMS ((const char *));
88 static struct hash_entry * demangled_hash_newfunc PARAMS ((struct hash_entry *,
89                                                            struct hash_table *,
90                                                            hash_table_key));
91 static struct demangled_hash_entry *
92   demangled_hash_lookup PARAMS ((const char *, boolean));
93 static void symbol_push PARAMS ((symbol *));
94 static symbol * symbol_pop PARAMS ((void));
95 static void file_push PARAMS ((file *));
96 static file * file_pop PARAMS ((void));
97 static void tlink_init PARAMS ((void));
98 static int tlink_execute PARAMS ((char *, char **, char *));
99 static char * frob_extension PARAMS ((char *, const char *));
100 static char * obstack_fgets PARAMS ((FILE *, struct obstack *));
101 static char * tfgets PARAMS ((FILE *));
102 static char * pfgets PARAMS ((FILE *));
103 static void freadsym PARAMS ((FILE *, file *, int));
104 static void read_repo_file PARAMS ((file *));
105 static void maybe_tweak PARAMS ((char *, file *));
106 static int recompile_files PARAMS ((void));
107 static int read_repo_files PARAMS ((char **));
108 static void demangle_new_symbols PARAMS ((void));
109 static 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
114 static struct hash_entry *
115 symbol_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
137 static struct symbol_hash_entry *
138 symbol_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
147 static struct hash_table file_table;
148
149 /* Create a new entry for the file hash table.
150    Passed to hash_table_init.  */
151
152 static struct hash_entry *
153 file_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
175 static struct file_hash_entry *
176 file_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
184 static struct hash_table demangled_table;
185
186 /* Create a new entry for the demangled name hash table.
187    Passed to hash_table_init.  */
188
189 static struct hash_entry *
190 demangled_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
209 static struct demangled_hash_entry *
210 demangled_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 \f
219 /* Stack code.  */
220
221 struct symbol_stack_entry
222 {
223   symbol *value;
224   struct symbol_stack_entry *next;
225 };
226 struct obstack symbol_stack_obstack;
227 struct symbol_stack_entry *symbol_stack;
228
229 struct file_stack_entry
230 {
231   file *value;
232   struct file_stack_entry *next;
233 };
234 struct obstack file_stack_obstack;
235 struct file_stack_entry *file_stack;
236
237 static void
238 symbol_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
248 static symbol *
249 symbol_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
261 static void
262 file_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
278 static file *
279 file_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 \f
292 /* Other machinery.  */
293
294 /* Initialize the tlink machinery.  Called from do_tlink.  */
295
296 static void
297 tlink_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
323 static int
324 tlink_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
333 static char *
334 frob_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
349 static char *
350 obstack_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
363 static char *
364 tfgets (stream)
365      FILE *stream;
366 {
367   return obstack_fgets (stream, &temporary_obstack);
368 }
369
370 static char *
371 pfgets (stream)
372      FILE *stream;
373 {
374   return obstack_fgets (stream, &permanent_obstack);
375 }
376 \f
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
385 static void
386 freadsym (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
428 static void
429 read_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
476 static void
477 maybe_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
501 static int
502 recompile_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
554 static int
555 read_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
581 static void
582 demangle_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
603 static int
604 scan_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
695 void
696 do_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 }