OSDN Git Service

Update FSF address in copyright header.
[pf3gnuchains/gcc-fork.git] / 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 code.  */
51
52 typedef struct symbol_hash_entry
53 {
54   struct hash_entry root;
55   struct file_hash_entry *file;
56   int chosen;
57   int tweaking;
58   int tweaked;
59 } symbol;
60
61 typedef struct file_hash_entry
62 {
63   struct hash_entry root;
64   const char *args;
65   const char *dir;
66   const char *main;
67   int tweaking;
68 } file;
69
70 typedef struct demangled_hash_entry
71 {
72   struct hash_entry root;
73   const char *mangled;
74 } demangled;
75
76 static struct hash_table symbol_table;
77
78 static struct hash_entry *
79 symbol_hash_newfunc (entry, table, string)
80      struct hash_entry *entry;
81      struct hash_table *table;
82      const char *string;
83 {
84   struct symbol_hash_entry *ret = (struct symbol_hash_entry *) entry;
85   if (ret == NULL)
86     {
87       ret = ((struct symbol_hash_entry *)
88              hash_allocate (table, sizeof (struct symbol_hash_entry)));
89       if (ret == NULL)
90         return NULL;
91     }
92   ret = ((struct symbol_hash_entry *)
93          hash_newfunc ((struct hash_entry *) ret, table, 
94                        (hash_table_key) string));
95   ret->file = NULL;
96   ret->chosen = 0;
97   ret->tweaking = 0;
98   ret->tweaked = 0;
99   return (struct hash_entry *) ret;
100 }
101
102 static struct symbol_hash_entry *
103 symbol_hash_lookup (string, create)
104      const char *string;
105      boolean create;
106 {
107   return ((struct symbol_hash_entry *)
108           hash_lookup (&symbol_table, (hash_table_key) string, 
109                        create, &string_copy));
110 }
111
112 static struct hash_table file_table;
113
114 static struct hash_entry *
115 file_hash_newfunc (entry, table, string)
116      struct hash_entry *entry;
117      struct hash_table *table;
118      const char *string;
119 {
120    struct file_hash_entry *ret = (struct file_hash_entry *) entry;
121   if (ret == NULL)
122     {
123       ret = ((struct file_hash_entry *)
124              hash_allocate (table, sizeof (struct file_hash_entry)));
125       if (ret == NULL)
126         return NULL;
127     }
128   ret = ((struct file_hash_entry *)
129          hash_newfunc ((struct hash_entry *) ret, table, 
130                        (hash_table_key) string));
131   ret->args = NULL;
132   ret->dir = NULL;
133   ret->main = NULL;
134   ret->tweaking = 0;
135   return (struct hash_entry *) ret;
136 }
137
138 static struct file_hash_entry *
139 file_hash_lookup (string)
140      const char *string;
141 {
142   return ((struct file_hash_entry *)
143           hash_lookup (&file_table, (hash_table_key) string, true, 
144                        &string_copy));
145 }
146
147 static struct hash_table demangled_table;
148
149 static struct hash_entry *
150 demangled_hash_newfunc (entry, table, string)
151      struct hash_entry *entry;
152      struct hash_table *table;
153      const char *string;
154 {
155   struct demangled_hash_entry *ret = (struct demangled_hash_entry *) entry;
156   if (ret == NULL)
157     {
158       ret = ((struct demangled_hash_entry *)
159              hash_allocate (table, sizeof (struct demangled_hash_entry)));
160       if (ret == NULL)
161         return NULL;
162     }
163   ret = ((struct demangled_hash_entry *)
164          hash_newfunc ((struct hash_entry *) ret, table, 
165                        (hash_table_key) string));
166   ret->mangled = NULL;
167   return (struct hash_entry *) ret;
168 }
169
170 static struct demangled_hash_entry *
171 demangled_hash_lookup (string, create)
172      const char *string;
173      boolean create;
174 {
175   return ((struct demangled_hash_entry *)
176           hash_lookup (&demangled_table, (hash_table_key) string, 
177                        create, &string_copy));
178 }
179 \f
180 /* Stack code.  */
181
182 struct symbol_stack_entry
183 {
184   symbol *value;
185   struct symbol_stack_entry *next;
186 };
187 struct obstack symbol_stack_obstack;
188 struct symbol_stack_entry *symbol_stack;
189
190 struct file_stack_entry
191 {
192   file *value;
193   struct file_stack_entry *next;
194 };
195 struct obstack file_stack_obstack;
196 struct file_stack_entry *file_stack;
197
198 static void
199 symbol_push (p)
200      symbol *p;
201 {
202   struct symbol_stack_entry *ep = (struct symbol_stack_entry *) obstack_alloc
203     (&symbol_stack_obstack, sizeof (struct symbol_stack_entry));
204   ep->value = p;
205   ep->next = symbol_stack;
206   symbol_stack = ep;
207 }
208
209 static symbol *
210 symbol_pop ()
211 {
212   struct symbol_stack_entry *ep = symbol_stack;
213   symbol *p;
214   if (ep == NULL)
215     return NULL;
216   p = ep->value;
217   symbol_stack = ep->next;
218   obstack_free (&symbol_stack_obstack, ep);
219   return p;
220 }
221
222 static void
223 file_push (p)
224      file *p;
225 {
226   struct file_stack_entry *ep;
227
228   if (p->tweaking)
229     return;
230
231   ep = (struct file_stack_entry *) obstack_alloc
232     (&file_stack_obstack, sizeof (struct file_stack_entry));
233   ep->value = p;
234   ep->next = file_stack;
235   file_stack = ep;
236   p->tweaking = 1;
237 }
238
239 static file *
240 file_pop ()
241 {
242   struct file_stack_entry *ep = file_stack;
243   file *p;
244   if (ep == NULL)
245     return NULL;
246   p = ep->value;
247   file_stack = ep->next;
248   obstack_free (&file_stack_obstack, ep);
249   p->tweaking = 0;
250   return p;
251 }
252 \f
253 /* Other machinery.  */
254
255 static void
256 tlink_init ()
257 {
258   char *p;
259
260   hash_table_init (&symbol_table, symbol_hash_newfunc, &string_hash,
261                    &string_compare);
262   hash_table_init (&file_table, file_hash_newfunc, &string_hash, 
263                    &string_compare);
264   hash_table_init (&demangled_table, demangled_hash_newfunc,
265                    &string_hash, &string_compare);
266   obstack_begin (&symbol_stack_obstack, 0);
267   obstack_begin (&file_stack_obstack, 0);
268
269   p = getenv ("TLINK_VERBOSE");
270   if (p)
271     tlink_verbose = atoi (p);
272   else
273     {
274       tlink_verbose = 1;
275       if (vflag)
276         tlink_verbose = 2;
277       if (debug)
278         tlink_verbose = 3;
279     }
280 }
281
282 static int
283 tlink_execute (prog, argv, redir)
284      char *prog;
285      char **argv;
286      char *redir;
287 {
288   collect_execute (prog, argv, redir);
289   return collect_wait (prog);
290
291
292 static char *
293 frob_extension (s, ext)
294      char *s, *ext;
295 {
296   char *p = rindex (s, '/');
297   if (! p)
298     p = s;
299   p = rindex (p, '.');
300   if (! p)
301     p = s + strlen (s);
302
303   obstack_grow (&temporary_obstack, s, p - s);
304   return obstack_copy0 (&temporary_obstack, ext, strlen (ext));
305 }
306
307 static char *
308 obstack_fgets (stream, ob)
309      FILE *stream;
310      struct obstack *ob;
311 {
312   int c;
313   while ((c = getc (stream)) != EOF && c != '\n')
314     obstack_1grow (ob, c);
315   if (obstack_object_size (ob) == 0)
316     return NULL;
317   obstack_1grow (ob, '\0');
318   return obstack_finish (ob);
319 }
320
321 static char *
322 tfgets (stream)
323      FILE *stream;
324 {
325   return obstack_fgets (stream, &temporary_obstack);
326 }
327
328 static char *
329 pfgets (stream)
330      FILE *stream;
331 {
332   return obstack_fgets (stream, &permanent_obstack);
333 }
334 \f
335 /* Real tlink code.  */
336
337 static void
338 freadsym (stream, f, chosen)
339      FILE *stream;
340      file *f;
341      int chosen;
342 {
343   symbol *sym;
344
345   {
346     char *name = tfgets (stream);
347     sym = symbol_hash_lookup (name, true);
348   }
349
350   if (sym->file == NULL)
351     {
352       symbol_push (sym);
353       sym->file = f;
354       sym->chosen = chosen;
355     }
356   else if (chosen)
357     {
358       if (sym->chosen && sym->file != f)
359         {
360           if (sym->chosen == 1)
361             file_push (sym->file);
362           else
363             {
364               file_push (f);
365               f = sym->file;
366               chosen = sym->chosen;
367             }
368         }
369       sym->file = f;
370       sym->chosen = chosen;
371     }
372 }
373
374 static void
375 read_repo_file (f)
376      file *f;
377 {
378   char c;
379   FILE *stream = fopen ((char*) f->root.key, "r");
380
381   if (tlink_verbose >= 2)
382     fprintf (stderr, "collect: reading %s\n", 
383              (char*) f->root.key);
384
385   while (fscanf (stream, "%c ", &c) == 1)
386     {
387       switch (c)
388         {
389         case 'A':
390           f->args = pfgets (stream);
391           break;
392         case 'D':
393           f->dir = pfgets (stream);
394           break;
395         case 'M':
396           f->main = pfgets (stream);
397           break;
398         case 'P':
399           freadsym (stream, f, 2);
400           break;
401         case 'C':
402           freadsym (stream, f, 1);
403           break;
404         case 'O':
405           freadsym (stream, f, 0);
406           break;
407         }
408       obstack_free (&temporary_obstack, temporary_firstobj);
409     }
410   fclose (stream);
411   if (f->args == NULL)
412     f->args = getenv ("COLLECT_GCC_OPTIONS");
413   if (f->dir == NULL)
414     f->dir = ".";
415 }
416
417 static void
418 maybe_tweak (line, f)
419      char *line;
420      file *f;
421 {
422   symbol *sym = symbol_hash_lookup (line + 2, false);
423
424   if ((sym->file == f && sym->tweaking)
425       || (sym->file != f && line[0] == 'C'))
426     {
427       sym->tweaking = 0;
428       sym->tweaked = 1;
429
430       if (line[0] == 'O')
431         line[0] = 'C';
432       else
433         line[0] = 'O';
434     }
435 }
436
437 static int
438 recompile_files ()
439 {
440   file *f;
441
442   while ((f = file_pop ()) != NULL)
443     {
444       char *line, *command;
445       FILE *stream = fopen ((char*) f->root.key, "r");
446       char *outname = frob_extension ((char*) f->root.key, ".rnw");
447       FILE *output = fopen (outname, "w");
448
449       while ((line = tfgets (stream)) != NULL)
450         {
451           switch (line[0])
452             {
453             case 'C':
454             case 'O':
455               maybe_tweak (line, f);
456             }
457           fprintf (output, "%s\n", line);
458         }
459       fclose (stream);
460       fclose (output);
461       rename (outname, (char*) f->root.key);
462
463       obstack_grow (&temporary_obstack, "cd ", 3);
464       obstack_grow (&temporary_obstack, f->dir, strlen (f->dir));
465       obstack_grow (&temporary_obstack, "; ", 2);
466       obstack_grow (&temporary_obstack, c_file_name, strlen (c_file_name));
467       obstack_1grow (&temporary_obstack, ' ');
468       obstack_grow (&temporary_obstack, f->args, strlen (f->args));
469       obstack_1grow (&temporary_obstack, ' ');
470       command = obstack_copy0 (&temporary_obstack, f->main, strlen (f->main));
471
472       if (tlink_verbose)
473         fprintf (stderr, "collect: recompiling %s\n", f->main);
474       if (tlink_verbose >= 3)
475         fprintf (stderr, "%s\n", command);
476
477       if (system (command) != 0)
478         return 0;
479
480       read_repo_file (f);
481
482       obstack_free (&temporary_obstack, temporary_firstobj);
483     }
484   return 1;
485 }
486
487 static int
488 read_repo_files (object_lst)
489      char **object_lst;
490 {
491   char **object = object_lst;
492
493   for (; *object; object++)
494     {
495       char *p = frob_extension (*object, ".rpo");
496       file *f;
497
498       if (! file_exists (p))
499         continue;
500
501       f = file_hash_lookup (p);
502
503       read_repo_file (f);
504     }
505
506   if (file_stack != NULL && ! recompile_files ())
507     return 0;
508
509   return (symbol_stack != NULL);
510 }
511
512 static void
513 demangle_new_symbols ()
514 {
515   symbol *sym;
516
517   while ((sym = symbol_pop ()) != NULL)
518     {
519       demangled *dem;
520       char *p = cplus_demangle ((char*) sym->root.key, 
521                                 DMGL_PARAMS | DMGL_ANSI);
522
523       if (! p)
524         continue;
525
526       dem = demangled_hash_lookup (p, true);
527       dem->mangled = (char*) sym->root.key;
528     }
529 }
530
531 static int
532 scan_linker_output (fname)
533      char *fname;
534 {
535   FILE *stream = fopen (fname, "r");
536   char *line;
537
538   while ((line = tfgets (stream)) != NULL)
539     {
540       char *p = line, *q;
541       symbol *sym;
542       int end;
543       
544       while (*p && ISSPACE ((unsigned char)*p))
545         ++p;
546
547       if (! *p)
548         continue;
549
550       for (q = p; *q && ! ISSPACE ((unsigned char)*q); ++q)
551         ;
552
553       /* Try the first word on the line.  */
554       if (*p == '.')
555         ++p;
556       if (*p == '_' && prepends_underscore)
557         ++p;
558
559       end = ! *q;
560       *q = 0;
561       sym = symbol_hash_lookup (p, false);
562
563       if (! sym && ! end)
564         /* Try a mangled name in quotes.  */
565         {
566           char *oldq = q+1;
567           demangled *dem = 0;
568           q = 0;
569
570           /* First try `GNU style'.  */
571           p = index (oldq, '`');
572           if (p)
573             p++, q = index (p, '\'');
574           /* Then try "double quotes".  */
575           else if (p = index (oldq, '"'), p)
576             p++, q = index (p, '"');
577
578           if (q)
579             {
580               *q = 0;
581               dem = demangled_hash_lookup (p, false);
582               if (dem)
583                 sym = symbol_hash_lookup (dem->mangled, false);
584               else
585                 sym = symbol_hash_lookup (p, false);
586             }
587         }
588
589       if (sym && sym->tweaked)
590         {
591           fclose (stream);
592           return 0;
593         }
594       if (sym && !sym->tweaking)
595         {
596           if (tlink_verbose >= 2)
597             fprintf (stderr, "collect: tweaking %s in %s\n",
598                      (char*) sym->root.key, (char*) sym->file->root.key);
599           sym->tweaking = 1;
600           file_push (sym->file);
601         }
602         
603       obstack_free (&temporary_obstack, temporary_firstobj);
604     }
605
606   fclose (stream);
607   return (file_stack != NULL);
608 }
609
610 void
611 do_tlink (ld_argv, object_lst)
612      char **ld_argv, **object_lst;
613 {
614   int exit = tlink_execute ("ld", ld_argv, ldout);
615
616   tlink_init ();
617
618   if (exit)
619     {
620       int i = 0;
621
622       /* Until collect does a better job of figuring out which are object
623          files, assume that everything on the command line could be.  */
624       if (read_repo_files (ld_argv))
625         while (exit && i++ < MAX_ITERATIONS)
626           {
627             if (tlink_verbose >= 3)
628               dump_file (ldout);
629             demangle_new_symbols ();
630             if (! scan_linker_output (ldout))
631               break;
632             if (! recompile_files ())
633               break;
634             if (tlink_verbose)
635               fprintf (stderr, "collect: relinking\n");
636             exit = tlink_execute ("ld", ld_argv, ldout);
637           }
638     }
639
640   dump_file (ldout);
641   unlink (ldout);
642   if (exit)
643     {
644       error ("ld returned %d exit status", exit);
645       collect_exit (exit);
646     }
647 }