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