c-decl.c: Mark strings for translation.
[gcc.git] / gcc / tlink.c
1 /* Scan linker error messages for missing template instantiations and provide
2 them.
3
4 Copyright (C) 1995, 1998, 1999 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 "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 the automatically-generated underscore.c. */
37 extern int prepends_underscore;
38
39 static int tlink_verbose;
40 \f
41 /* Hash table boilerplate for working with hash.[ch]. We have hash tables
42 for symbol names, file names, and demangled symbols. */
43
44 typedef struct symbol_hash_entry
45 {
46 struct hash_entry root;
47 struct file_hash_entry *file;
48 int chosen;
49 int tweaking;
50 int tweaked;
51 } symbol;
52
53 typedef struct file_hash_entry
54 {
55 struct hash_entry root;
56 const char *args;
57 const char *dir;
58 const char *main;
59 int tweaking;
60 } file;
61
62 typedef struct demangled_hash_entry
63 {
64 struct hash_entry root;
65 const char *mangled;
66 } demangled;
67
68 static struct hash_table symbol_table;
69
70 static struct hash_entry * symbol_hash_newfunc PARAMS ((struct hash_entry *,
71 struct hash_table *,
72 hash_table_key));
73 static struct symbol_hash_entry * symbol_hash_lookup PARAMS ((const char *,
74 boolean));
75 static struct hash_entry * file_hash_newfunc PARAMS ((struct hash_entry *,
76 struct hash_table *,
77 hash_table_key));
78 static struct file_hash_entry * file_hash_lookup PARAMS ((const char *));
79 static struct hash_entry * demangled_hash_newfunc PARAMS ((struct hash_entry *,
80 struct hash_table *,
81 hash_table_key));
82 static struct demangled_hash_entry *
83 demangled_hash_lookup PARAMS ((const char *, boolean));
84 static void symbol_push PARAMS ((symbol *));
85 static symbol * symbol_pop PARAMS ((void));
86 static void file_push PARAMS ((file *));
87 static file * file_pop PARAMS ((void));
88 static void tlink_init PARAMS ((void));
89 static int tlink_execute PARAMS ((const char *, char **, const char *));
90 static char * frob_extension PARAMS ((const char *, const char *));
91 static char * obstack_fgets PARAMS ((FILE *, struct obstack *));
92 static char * tfgets PARAMS ((FILE *));
93 static char * pfgets PARAMS ((FILE *));
94 static void freadsym PARAMS ((FILE *, file *, int));
95 static void read_repo_file PARAMS ((file *));
96 static void maybe_tweak PARAMS ((char *, file *));
97 static int recompile_files PARAMS ((void));
98 static int read_repo_files PARAMS ((char **));
99 static void demangle_new_symbols PARAMS ((void));
100 static int scan_linker_output PARAMS ((const char *));
101
102 /* Create a new entry for the symbol hash table.
103 Passed to hash_table_init. */
104
105 static struct hash_entry *
106 symbol_hash_newfunc (entry, table, string)
107 struct hash_entry *entry;
108 struct hash_table *table;
109 hash_table_key string ATTRIBUTE_UNUSED;
110 {
111 struct symbol_hash_entry *ret = (struct symbol_hash_entry *) entry;
112 if (ret == NULL)
113 {
114 ret = ((struct symbol_hash_entry *)
115 hash_allocate (table, sizeof (struct symbol_hash_entry)));
116 if (ret == NULL)
117 return NULL;
118 }
119 ret->file = NULL;
120 ret->chosen = 0;
121 ret->tweaking = 0;
122 ret->tweaked = 0;
123 return (struct hash_entry *) ret;
124 }
125
126 /* Look up an entry in the symbol hash table. */
127
128 static struct symbol_hash_entry *
129 symbol_hash_lookup (string, create)
130 const char *string;
131 boolean create;
132 {
133 return ((struct symbol_hash_entry *)
134 hash_lookup (&symbol_table, (const hash_table_key) string,
135 create, string_copy));
136 }
137
138 static struct hash_table file_table;
139
140 /* Create a new entry for the file hash table.
141 Passed to hash_table_init. */
142
143 static struct hash_entry *
144 file_hash_newfunc (entry, table, string)
145 struct hash_entry *entry;
146 struct hash_table *table;
147 hash_table_key string ATTRIBUTE_UNUSED;
148 {
149 struct file_hash_entry *ret = (struct file_hash_entry *) entry;
150 if (ret == NULL)
151 {
152 ret = ((struct file_hash_entry *)
153 hash_allocate (table, sizeof (struct file_hash_entry)));
154 if (ret == NULL)
155 return NULL;
156 }
157 ret->args = NULL;
158 ret->dir = NULL;
159 ret->main = NULL;
160 ret->tweaking = 0;
161 return (struct hash_entry *) ret;
162 }
163
164 /* Look up an entry in the file hash table. */
165
166 static struct file_hash_entry *
167 file_hash_lookup (string)
168 const char *string;
169 {
170 return ((struct file_hash_entry *)
171 hash_lookup (&file_table, (const hash_table_key) string, true,
172 string_copy));
173 }
174
175 static struct hash_table demangled_table;
176
177 /* Create a new entry for the demangled name hash table.
178 Passed to hash_table_init. */
179
180 static struct hash_entry *
181 demangled_hash_newfunc (entry, table, string)
182 struct hash_entry *entry;
183 struct hash_table *table;
184 hash_table_key string ATTRIBUTE_UNUSED;
185 {
186 struct demangled_hash_entry *ret = (struct demangled_hash_entry *) entry;
187 if (ret == NULL)
188 {
189 ret = ((struct demangled_hash_entry *)
190 hash_allocate (table, sizeof (struct demangled_hash_entry)));
191 if (ret == NULL)
192 return NULL;
193 }
194 ret->mangled = NULL;
195 return (struct hash_entry *) ret;
196 }
197
198 /* Look up an entry in the demangled name hash table. */
199
200 static struct demangled_hash_entry *
201 demangled_hash_lookup (string, create)
202 const char *string;
203 boolean create;
204 {
205 return ((struct demangled_hash_entry *)
206 hash_lookup (&demangled_table, (const hash_table_key) string,
207 create, string_copy));
208 }
209 \f
210 /* Stack code. */
211
212 struct symbol_stack_entry
213 {
214 symbol *value;
215 struct symbol_stack_entry *next;
216 };
217 struct obstack symbol_stack_obstack;
218 struct symbol_stack_entry *symbol_stack;
219
220 struct file_stack_entry
221 {
222 file *value;
223 struct file_stack_entry *next;
224 };
225 struct obstack file_stack_obstack;
226 struct file_stack_entry *file_stack;
227
228 static void
229 symbol_push (p)
230 symbol *p;
231 {
232 struct symbol_stack_entry *ep = (struct symbol_stack_entry *) obstack_alloc
233 (&symbol_stack_obstack, sizeof (struct symbol_stack_entry));
234 ep->value = p;
235 ep->next = symbol_stack;
236 symbol_stack = ep;
237 }
238
239 static symbol *
240 symbol_pop ()
241 {
242 struct symbol_stack_entry *ep = symbol_stack;
243 symbol *p;
244 if (ep == NULL)
245 return NULL;
246 p = ep->value;
247 symbol_stack = ep->next;
248 obstack_free (&symbol_stack_obstack, ep);
249 return p;
250 }
251
252 static void
253 file_push (p)
254 file *p;
255 {
256 struct file_stack_entry *ep;
257
258 if (p->tweaking)
259 return;
260
261 ep = (struct file_stack_entry *) obstack_alloc
262 (&file_stack_obstack, sizeof (struct file_stack_entry));
263 ep->value = p;
264 ep->next = file_stack;
265 file_stack = ep;
266 p->tweaking = 1;
267 }
268
269 static file *
270 file_pop ()
271 {
272 struct file_stack_entry *ep = file_stack;
273 file *p;
274 if (ep == NULL)
275 return NULL;
276 p = ep->value;
277 file_stack = ep->next;
278 obstack_free (&file_stack_obstack, ep);
279 p->tweaking = 0;
280 return p;
281 }
282 \f
283 /* Other machinery. */
284
285 /* Initialize the tlink machinery. Called from do_tlink. */
286
287 static void
288 tlink_init ()
289 {
290 const char *p;
291
292 hash_table_init (&symbol_table, symbol_hash_newfunc, string_hash,
293 string_compare);
294 hash_table_init (&file_table, file_hash_newfunc, string_hash,
295 string_compare);
296 hash_table_init (&demangled_table, demangled_hash_newfunc,
297 string_hash, string_compare);
298 obstack_begin (&symbol_stack_obstack, 0);
299 obstack_begin (&file_stack_obstack, 0);
300
301 p = getenv ("TLINK_VERBOSE");
302 if (p)
303 tlink_verbose = atoi (p);
304 else
305 {
306 tlink_verbose = 1;
307 if (vflag)
308 tlink_verbose = 2;
309 if (debug)
310 tlink_verbose = 3;
311 }
312 }
313
314 static int
315 tlink_execute (prog, argv, redir)
316 const char *prog;
317 char **argv;
318 const char *redir;
319 {
320 collect_execute (prog, argv, redir);
321 return collect_wait (prog);
322 }
323
324 static char *
325 frob_extension (s, ext)
326 const char *s;
327 const char *ext;
328 {
329 const char *p = rindex (s, '/');
330 if (! p)
331 p = s;
332 p = rindex (p, '.');
333 if (! p)
334 p = s + strlen (s);
335
336 obstack_grow (&temporary_obstack, s, p - s);
337 return obstack_copy0 (&temporary_obstack, ext, strlen (ext));
338 }
339
340 static char *
341 obstack_fgets (stream, ob)
342 FILE *stream;
343 struct obstack *ob;
344 {
345 int c;
346 while ((c = getc (stream)) != EOF && c != '\n')
347 obstack_1grow (ob, c);
348 if (obstack_object_size (ob) == 0)
349 return NULL;
350 obstack_1grow (ob, '\0');
351 return obstack_finish (ob);
352 }
353
354 static char *
355 tfgets (stream)
356 FILE *stream;
357 {
358 return obstack_fgets (stream, &temporary_obstack);
359 }
360
361 static char *
362 pfgets (stream)
363 FILE *stream;
364 {
365 return obstack_fgets (stream, &permanent_obstack);
366 }
367 \f
368 /* Real tlink code. */
369
370 /* Subroutine of read_repo_file. We are reading the repo file for file F,
371 which is coming in on STREAM, and the symbol that comes next in STREAM
372 is offerred, chosen or provided if CHOSEN is 0, 1 or 2, respectively.
373
374 XXX "provided" is unimplemented, both here and in the compiler. */
375
376 static void
377 freadsym (stream, f, chosen)
378 FILE *stream;
379 file *f;
380 int chosen;
381 {
382 symbol *sym;
383
384 {
385 const char *name = tfgets (stream);
386 sym = symbol_hash_lookup (name, true);
387 }
388
389 if (sym->file == NULL)
390 {
391 /* We didn't have this symbol already, so we choose this file. */
392
393 symbol_push (sym);
394 sym->file = f;
395 sym->chosen = chosen;
396 }
397 else if (chosen)
398 {
399 /* We want this file; cast aside any pretender. */
400
401 if (sym->chosen && sym->file != f)
402 {
403 if (sym->chosen == 1)
404 file_push (sym->file);
405 else
406 {
407 file_push (f);
408 f = sym->file;
409 chosen = sym->chosen;
410 }
411 }
412 sym->file = f;
413 sym->chosen = chosen;
414 }
415 }
416
417 /* Read in the repo file denoted by F, and record all its information. */
418
419 static void
420 read_repo_file (f)
421 file *f;
422 {
423 char c;
424 FILE *stream = fopen ((char*) f->root.key, "r");
425
426 if (tlink_verbose >= 2)
427 fprintf (stderr, _("collect: reading %s\n"),
428 (char*) f->root.key);
429
430 while (fscanf (stream, "%c ", &c) == 1)
431 {
432 switch (c)
433 {
434 case 'A':
435 f->args = pfgets (stream);
436 break;
437 case 'D':
438 f->dir = pfgets (stream);
439 break;
440 case 'M':
441 f->main = pfgets (stream);
442 break;
443 case 'P':
444 freadsym (stream, f, 2);
445 break;
446 case 'C':
447 freadsym (stream, f, 1);
448 break;
449 case 'O':
450 freadsym (stream, f, 0);
451 break;
452 }
453 obstack_free (&temporary_obstack, temporary_firstobj);
454 }
455 fclose (stream);
456 if (f->args == NULL)
457 f->args = getenv ("COLLECT_GCC_OPTIONS");
458 if (f->dir == NULL)
459 f->dir = ".";
460 }
461
462 /* We might want to modify LINE, which is a symbol line from file F. We do
463 this if either we saw an error message referring to the symbol in
464 question, or we have already allocated the symbol to another file and
465 this one wants to emit it as well. */
466
467 static void
468 maybe_tweak (line, f)
469 char *line;
470 file *f;
471 {
472 symbol *sym = symbol_hash_lookup (line + 2, false);
473
474 if ((sym->file == f && sym->tweaking)
475 || (sym->file != f && line[0] == 'C'))
476 {
477 sym->tweaking = 0;
478 sym->tweaked = 1;
479
480 if (line[0] == 'O')
481 line[0] = 'C';
482 else
483 line[0] = 'O';
484 }
485 }
486
487 /* Update the repo files for each of the object files we have adjusted and
488 recompile.
489
490 XXX Should this use collect_execute instead of system? */
491
492 static int
493 recompile_files ()
494 {
495 file *f;
496
497 while ((f = file_pop ()) != NULL)
498 {
499 char *line, *command;
500 FILE *stream = fopen ((char*) f->root.key, "r");
501 const char *outname = frob_extension ((char*) f->root.key, ".rnw");
502 FILE *output = fopen (outname, "w");
503
504 while ((line = tfgets (stream)) != NULL)
505 {
506 switch (line[0])
507 {
508 case 'C':
509 case 'O':
510 maybe_tweak (line, f);
511 }
512 fprintf (output, "%s\n", line);
513 }
514 fclose (stream);
515 fclose (output);
516 rename (outname, (char*) f->root.key);
517
518 obstack_grow (&temporary_obstack, "cd ", 3);
519 obstack_grow (&temporary_obstack, f->dir, strlen (f->dir));
520 obstack_grow (&temporary_obstack, "; ", 2);
521 obstack_grow (&temporary_obstack, c_file_name, strlen (c_file_name));
522 obstack_1grow (&temporary_obstack, ' ');
523 obstack_grow (&temporary_obstack, f->args, strlen (f->args));
524 obstack_1grow (&temporary_obstack, ' ');
525 command = obstack_copy0 (&temporary_obstack, f->main, strlen (f->main));
526
527 if (tlink_verbose)
528 fprintf (stderr, _("collect: recompiling %s\n"), f->main);
529 if (tlink_verbose >= 3)
530 fprintf (stderr, "%s\n", command);
531
532 if (system (command) != 0)
533 return 0;
534
535 read_repo_file (f);
536
537 obstack_free (&temporary_obstack, temporary_firstobj);
538 }
539 return 1;
540 }
541
542 /* The first phase of processing: determine which object files have
543 .rpo files associated with them, and read in the information. */
544
545 static int
546 read_repo_files (object_lst)
547 char **object_lst;
548 {
549 char **object = object_lst;
550
551 for (; *object; object++)
552 {
553 const char *p;
554 file *f;
555
556 /* Don't bother trying for ld flags. */
557 if (*object[0] == '-')
558 continue;
559
560 p = frob_extension (*object, ".rpo");
561
562 if (! file_exists (p))
563 continue;
564
565 f = file_hash_lookup (p);
566
567 read_repo_file (f);
568 }
569
570 if (file_stack != NULL && ! recompile_files ())
571 return 0;
572
573 return (symbol_stack != NULL);
574 }
575
576 /* Add the demangled forms of any new symbols to the hash table. */
577
578 static void
579 demangle_new_symbols ()
580 {
581 symbol *sym;
582
583 while ((sym = symbol_pop ()) != NULL)
584 {
585 demangled *dem;
586 const char *p = cplus_demangle ((char*) sym->root.key,
587 DMGL_PARAMS | DMGL_ANSI);
588
589 if (! p)
590 continue;
591
592 dem = demangled_hash_lookup (p, true);
593 dem->mangled = (char*) sym->root.key;
594 }
595 }
596
597 /* Step through the output of the linker, in the file named FNAME, and
598 adjust the settings for each symbol encountered. */
599
600 static int
601 scan_linker_output (fname)
602 const char *fname;
603 {
604 FILE *stream = fopen (fname, "r");
605 char *line;
606
607 while ((line = tfgets (stream)) != NULL)
608 {
609 char *p = line, *q;
610 symbol *sym;
611 int end;
612
613 while (*p && ISSPACE ((unsigned char)*p))
614 ++p;
615
616 if (! *p)
617 continue;
618
619 for (q = p; *q && ! ISSPACE ((unsigned char)*q); ++q)
620 ;
621
622 /* Try the first word on the line. */
623 if (*p == '.')
624 ++p;
625 if (*p == '_' && prepends_underscore)
626 ++p;
627
628 end = ! *q;
629 *q = 0;
630 sym = symbol_hash_lookup (p, false);
631
632 if (! sym && ! end)
633 /* Try a mangled name in quotes. */
634 {
635 const char *oldq = q+1;
636 demangled *dem = 0;
637 q = 0;
638
639 /* First try `GNU style'. */
640 p = index (oldq, '`');
641 if (p)
642 p++, q = index (p, '\'');
643 /* Then try "double quotes". */
644 else if (p = index (oldq, '"'), p)
645 p++, q = index (p, '"');
646
647 /* Don't let the strstr's below see the demangled name; we
648 might get spurious matches. */
649 if (p)
650 p[-1] = '\0';
651
652 /* We need to check for certain error keywords here, or we would
653 mistakenly use GNU ld's "In function `foo':" message. */
654 if (q && (strstr (oldq, "ndefined")
655 || strstr (oldq, "nresolved")
656 || strstr (oldq, "ultiple")))
657 {
658 *q = 0;
659 dem = demangled_hash_lookup (p, false);
660 if (dem)
661 sym = symbol_hash_lookup (dem->mangled, false);
662 else
663 {
664 if (*p == '_' && prepends_underscore)
665 ++p;
666 sym = symbol_hash_lookup (p, false);
667 }
668 }
669 }
670
671 if (sym && sym->tweaked)
672 {
673 fclose (stream);
674 return 0;
675 }
676 if (sym && !sym->tweaking)
677 {
678 if (tlink_verbose >= 2)
679 fprintf (stderr, _("collect: tweaking %s in %s\n"),
680 (char*) sym->root.key, (char*) sym->file->root.key);
681 sym->tweaking = 1;
682 file_push (sym->file);
683 }
684
685 obstack_free (&temporary_obstack, temporary_firstobj);
686 }
687
688 fclose (stream);
689 return (file_stack != NULL);
690 }
691
692 /* Entry point for tlink. Called from main in collect2.c.
693
694 Iteratively try to provide definitions for all the unresolved symbols
695 mentioned in the linker error messages.
696
697 LD_ARGV is an array of arguments for the linker.
698 OBJECT_LST is an array of object files that we may be able to recompile
699 to provide missing definitions. Currently ignored. */
700
701 void
702 do_tlink (ld_argv, object_lst)
703 char **ld_argv, **object_lst ATTRIBUTE_UNUSED;
704 {
705 int exit = tlink_execute ("ld", ld_argv, ldout);
706
707 tlink_init ();
708
709 if (exit)
710 {
711 int i = 0;
712
713 /* Until collect does a better job of figuring out which are object
714 files, assume that everything on the command line could be. */
715 if (read_repo_files (ld_argv))
716 while (exit && i++ < MAX_ITERATIONS)
717 {
718 if (tlink_verbose >= 3)
719 dump_file (ldout);
720 demangle_new_symbols ();
721 if (! scan_linker_output (ldout))
722 break;
723 if (! recompile_files ())
724 break;
725 if (tlink_verbose)
726 fprintf (stderr, _("collect: relinking\n"));
727 exit = tlink_execute ("ld", ld_argv, ldout);
728 }
729 }
730
731 dump_file (ldout);
732 unlink (ldout);
733 if (exit)
734 {
735 error ("ld returned %d exit status", exit);
736 collect_exit (exit);
737 }
738 }