OSDN Git Service

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