/* Scan linker error messages for missing template instantiations and provide
them.
- Copyright (C) 1995, 1998, 1999, 2000, 2001, 2003, 2004, 2005
+ Copyright (C) 1995, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2007, 2008
Free Software Foundation, Inc.
Contributed by Jason Merrill (jason@cygnus.com).
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "hashtab.h"
#include "demangle.h"
#include "collect2.h"
+#include "libiberty.h"
#define MAX_ITERATIONS 17
static int tlink_verbose;
-static char initial_cwd[MAXPATHLEN + 1];
+static char *initial_cwd;
\f
/* Hash table boilerplate for working with htab_t. We have hash tables
for symbol names, file names, and demangled symbols. */
if (*e == NULL)
{
struct symbol_hash_entry *v;
- *e = v = xcalloc (1, sizeof (*v));
+ *e = v = XCNEW (struct symbol_hash_entry);
v->key = xstrdup (string);
}
- return *e;
+ return (struct symbol_hash_entry *) *e;
}
static htab_t file_table;
if (*e == NULL)
{
struct file_hash_entry *v;
- *e = v = xcalloc (1, sizeof (*v));
+ *e = v = XCNEW (struct file_hash_entry);
v->key = xstrdup (string);
}
- return *e;
+ return (struct file_hash_entry *) *e;
}
static htab_t demangled_table;
if (*e == NULL)
{
struct demangled_hash_entry *v;
- *e = v = xcalloc (1, sizeof (*v));
+ *e = v = XCNEW (struct demangled_hash_entry);
v->key = xstrdup (string);
}
- return *e;
+ return (struct demangled_hash_entry *) *e;
}
\f
/* Stack code. */
static void
symbol_push (symbol *p)
{
- struct symbol_stack_entry *ep = obstack_alloc
- (&symbol_stack_obstack, sizeof (struct symbol_stack_entry));
+ struct symbol_stack_entry *ep
+ = XOBNEW (&symbol_stack_obstack, struct symbol_stack_entry);
ep->value = p;
ep->next = symbol_stack;
symbol_stack = ep;
if (p->tweaking)
return;
- ep = obstack_alloc
- (&file_stack_obstack, sizeof (struct file_stack_entry));
+ ep = XOBNEW (&file_stack_obstack, struct file_stack_entry);
ep->value = p;
ep->next = file_stack;
file_stack = ep;
tlink_verbose = 3;
}
- getcwd (initial_cwd, sizeof (initial_cwd));
+ initial_cwd = getpwd ();
}
static int
{
struct pex_obj *pex;
- pex = collect_execute (prog, argv, outname, errname);
+ pex = collect_execute (prog, argv, outname, errname, PEX_LAST | PEX_SEARCH);
return collect_wait (prog, pex);
}
p = s + strlen (s);
obstack_grow (&temporary_obstack, s, p - s);
- return obstack_copy0 (&temporary_obstack, ext, strlen (ext));
+ return (char *) obstack_copy0 (&temporary_obstack, ext, strlen (ext));
}
static char *
{
FILE *stream = fopen (fname, "r");
char *line;
+ int skip_next_in_line = 0;
while ((line = tfgets (stream)) != NULL)
{
char *p = line, *q;
symbol *sym;
int end;
+ int ok = 0;
+
+ /* On darwin9, we might have to skip " in " lines as well. */
+ if (skip_next_in_line
+ && strstr (p, " in "))
+ continue;
+ skip_next_in_line = 0;
while (*p && ISSPACE ((unsigned char) *p))
++p;
if (! sym && ! end)
/* Try a mangled name in quotes. */
{
- const char *oldq = q + 1;
+ char *oldq = q + 1;
demangled *dem = 0;
q = 0;
+ /* On darwin9, we look for "foo" referenced from:\n\(.* in .*\n\)* */
+ if (strcmp (oldq, "referenced from:") == 0)
+ {
+ /* We have to remember that we found a symbol to tweak. */
+ ok = 1;
+
+ /* We actually want to start from the first word on the
+ line. */
+ oldq = p;
+
+ /* Since the format is multiline, we have to skip
+ following lines with " in ". */
+ skip_next_in_line = 1;
+ }
+
/* First try `GNU style'. */
p = strchr (oldq, '`');
if (p)
/* Then try "double quotes". */
else if (p = strchr (oldq, '"'), p)
p++, q = strchr (p, '"');
+ /* Then try 'single quotes'. */
+ else if (p = strchr (oldq, '\''), p)
+ p++, q = strchr (p, '\'');
else {
/* Then try entire line. */
q = strchr (oldq, 0);
/* We need to check for certain error keywords here, or we would
mistakenly use GNU ld's "In function `foo':" message. */
- if (q && (strstr (oldq, "ndefined")
+ if (q && (ok
+ || strstr (oldq, "ndefined")
|| strstr (oldq, "nresolved")
|| strstr (oldq, "nsatisfied")
|| strstr (oldq, "ultiple")))
if (sym && sym->tweaked)
{
error ("'%s' was assigned to '%s', but was not defined "
- "during recompilation, or vice versa",
+ "during recompilation, or vice versa",
sym->key, sym->file->key);
fclose (stream);
return 0;