]> gcc.gnu.org Git - gcc.git/blame - gcc/tlink.c
If errorcount nonzero, don't call abort if the function is already defined.
[gcc.git] / gcc / tlink.c
CommitLineData
aa32d841
JL
1/* Scan linker error messages for missing template instantiations and provide
2 them.
3
2e6a5989 4 Copyright (C) 1995, 1998 Free Software Foundation, Inc.
aa32d841
JL
5 Contributed by Jason Merrill (jason@cygnus.com).
6
7This file is part of GNU CC.
8
9GNU CC is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2, or (at your option)
12any later version.
13
14GNU CC is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with GNU CC; see the file COPYING. If not, write to
21the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22
aa32d841 23#include "config.h"
670ee920 24#include "system.h"
aa32d841
JL
25#include "hash.h"
26#include "demangle.h"
10f0ad3d 27#include "toplev.h"
aa32d841
JL
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
35extern char * xmalloc PARAMS((unsigned));
aa32d841
JL
36
37/* Defined in collect2.c. */
38extern int vflag, debug;
39extern char *ldout;
40extern char *c_file_name;
41extern struct obstack temporary_obstack;
42extern struct obstack permanent_obstack;
43extern char * temporary_firstobj;
44
45/* Defined in the automatically-generated underscore.c. */
46extern int prepends_underscore;
47
48static int tlink_verbose;
49\f
50/* Hash table code. */
51
52typedef 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
61typedef 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
70typedef struct demangled_hash_entry
71{
72 struct hash_entry root;
73 const char *mangled;
74} demangled;
75
76static struct hash_table symbol_table;
77
78static struct hash_entry *
79symbol_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
101static struct symbol_hash_entry *
102symbol_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
110static struct hash_table file_table;
111
112static struct hash_entry *
113file_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
135static struct file_hash_entry *
136file_hash_lookup (string)
137 const char *string;
138{
139 return ((struct file_hash_entry *)
140 hash_lookup (&file_table, string, true, true));
141}
142
143static struct hash_table demangled_table;
144
145static struct hash_entry *
146demangled_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
165static struct demangled_hash_entry *
166demangled_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
176struct symbol_stack_entry
177{
178 symbol *value;
179 struct symbol_stack_entry *next;
180};
181struct obstack symbol_stack_obstack;
182struct symbol_stack_entry *symbol_stack;
183
184struct file_stack_entry
185{
186 file *value;
187 struct file_stack_entry *next;
188};
189struct obstack file_stack_obstack;
190struct file_stack_entry *file_stack;
191
192static void
193symbol_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
203static symbol *
204symbol_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
216static void
217file_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
233static file *
234file_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
249static void
250tlink_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
273static int
274tlink_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
283static char *
284frob_extension (s, ext)
285 char *s, *ext;
286{
670ee920 287 char *p = rindex (s, '/');
aa32d841
JL
288 if (! p)
289 p = s;
670ee920 290 p = rindex (p, '.');
aa32d841
JL
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
298static char *
299obstack_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
312static char *
313tfgets (stream)
314 FILE *stream;
315{
316 return obstack_fgets (stream, &temporary_obstack);
317}
318
319static char *
320pfgets (stream)
321 FILE *stream;
322{
323 return obstack_fgets (stream, &permanent_obstack);
324}
325\f
326/* Real tlink code. */
327
328static void
329freadsym (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
365static void
366read_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
407static void
408maybe_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
427static int
428recompile_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
477static int
478read_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
502static void
503demangle_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
520static int
521scan_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
e9a780ec 533 while (*p && ISSPACE (*p))
aa32d841
JL
534 ++p;
535
536 if (! *p)
537 continue;
538
e9a780ec 539 for (q = p; *q && ! ISSPACE (*q); ++q)
aa32d841
JL
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)
b4558b57 553 /* Try a mangled name in quotes. */
aa32d841 554 {
b4558b57 555 char *oldq = q+1;
aa32d841 556 demangled *dem = 0;
aa32d841
JL
557 q = 0;
558
b4558b57
JM
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, '"');
aa32d841 566
b4558b57 567 if (q)
aa32d841 568 {
b4558b57
JM
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);
aa32d841 575 }
aa32d841
JL
576 }
577
578 if (sym && sym->tweaked)
7b6ffd11
KI
579 {
580 fclose (stream);
581 return 0;
582 }
aa32d841
JL
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
7b6ffd11 595 fclose (stream);
aa32d841
JL
596 return (file_stack != NULL);
597}
598
599void
600do_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}
This page took 0.29652 seconds and 5 git commands to generate.