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