OSDN Git Service

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