OSDN Git Service

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