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