/* Scan linker error messages for missing template instantiations and provide
them.
- Copyright (C) 1995, 1998, 1999, 2000, 2001, 2003
+ Copyright (C) 1995, 1998, 1999, 2000, 2001, 2003, 2004, 2005
Free Software Foundation, Inc.
Contributed by Jason Merrill (jason@cygnus.com).
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, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#include "config.h"
#include "system.h"
extern int prepends_underscore;
static int tlink_verbose;
+
+static char initial_cwd[MAXPATHLEN + 1];
\f
/* Hash table boilerplate for working with htab_t. We have hash tables
for symbol names, file names, and demangled symbols. */
static void file_push (file *);
static file * file_pop (void);
static void tlink_init (void);
-static int tlink_execute (const char *, char **, const char *);
+static int tlink_execute (const char *, char **, const char *, const char *);
static char * frob_extension (const char *, const char *);
static char * obstack_fgets (FILE *, struct obstack *);
static char * tfgets (FILE *);
if (debug)
tlink_verbose = 3;
}
+
+ getcwd (initial_cwd, sizeof (initial_cwd));
}
static int
-tlink_execute (const char *prog, char **argv, const char *redir)
+tlink_execute (const char *prog, char **argv, const char *outname,
+ const char *errname)
{
- collect_execute (prog, argv, redir);
- return collect_wait (prog);
+ struct pex_obj *pex;
+
+ pex = collect_execute (prog, argv, outname, errname);
+ return collect_wait (prog, pex);
}
static char *
if (obstack_object_size (ob) == 0)
return NULL;
obstack_1grow (ob, '\0');
- return obstack_finish (ob);
+ return XOBFINISH (ob, char *);
}
static char *
}
/* Update the repo files for each of the object files we have adjusted and
- recompile.
-
- XXX Should this use collect_execute instead of system? */
+ recompile. */
static int
recompile_files (void)
while ((f = file_pop ()) != NULL)
{
- char *line, *command;
+ char *line;
+ const char *p, *q;
+ char **argv;
+ struct obstack arg_stack;
FILE *stream = fopen (f->key, "r");
const char *const outname = frob_extension (f->key, ".rnw");
FILE *output = fopen (outname, "w");
}
fclose (stream);
fclose (output);
- rename (outname, f->key);
+ /* On Windows "rename" returns -1 and sets ERRNO to EACCESS if
+ the new file name already exists. Therefore, we explicitly
+ remove the old file first. */
+ if (remove (f->key) == -1)
+ fatal_perror ("removing .rpo file");
+ if (rename (outname, f->key) == -1)
+ fatal_perror ("renaming .rpo file");
+
+ if (!f->args)
+ {
+ error ("repository file '%s' does not contain command-line "
+ "arguments", f->key);
+ return 0;
+ }
+
+ /* Build a null-terminated argv array suitable for
+ tlink_execute(). Manipulate arguments on the arg_stack while
+ building argv on the temporary_obstack. */
- obstack_grow (&temporary_obstack, "cd ", 3);
- obstack_grow (&temporary_obstack, f->dir, strlen (f->dir));
- obstack_grow (&temporary_obstack, "; ", 2);
- obstack_grow (&temporary_obstack, c_file_name, strlen (c_file_name));
- obstack_1grow (&temporary_obstack, ' ');
- obstack_grow (&temporary_obstack, f->args, strlen (f->args));
- obstack_1grow (&temporary_obstack, ' ');
- command = obstack_copy0 (&temporary_obstack, f->main, strlen (f->main));
+ obstack_init (&arg_stack);
+ obstack_ptr_grow (&temporary_obstack, c_file_name);
+
+ for (p = f->args; *p != '\0'; p = q + 1)
+ {
+ /* Arguments are delimited by single-quotes. Find the
+ opening quote. */
+ p = strchr (p, '\'');
+ if (!p)
+ goto done;
+
+ /* Find the closing quote. */
+ q = strchr (p + 1, '\'');
+ if (!q)
+ goto done;
+
+ obstack_grow (&arg_stack, p + 1, q - (p + 1));
+
+ /* Replace '\'' with '. This is how set_collect_gcc_options
+ encodes a single-quote. */
+ while (q[1] == '\\' && q[2] == '\'' && q[3] == '\'')
+ {
+ const char *r;
+
+ r = strchr (q + 4, '\'');
+ if (!r)
+ goto done;
+
+ obstack_grow (&arg_stack, q + 3, r - (q + 3));
+ q = r;
+ }
+
+ obstack_1grow (&arg_stack, '\0');
+ obstack_ptr_grow (&temporary_obstack, obstack_finish (&arg_stack));
+ }
+ done:
+ obstack_ptr_grow (&temporary_obstack, f->main);
+ obstack_ptr_grow (&temporary_obstack, NULL);
+ argv = XOBFINISH (&temporary_obstack, char **);
if (tlink_verbose)
fprintf (stderr, _("collect: recompiling %s\n"), f->main);
- if (tlink_verbose >= 3)
- fprintf (stderr, "%s\n", command);
- if (system (command) != 0)
+ if (chdir (f->dir) != 0
+ || tlink_execute (c_file_name, argv, NULL, NULL) != 0
+ || chdir (initial_cwd) != 0)
return 0;
read_repo_file (f);
+ obstack_free (&arg_stack, NULL);
obstack_free (&temporary_obstack, temporary_firstobj);
}
return 1;
if (sym && sym->tweaked)
{
+ error ("'%s' was assigned to '%s', but was not defined "
+ "during recompilation, or vice versa",
+ sym->key, sym->file->key);
fclose (stream);
return 0;
}
void
do_tlink (char **ld_argv, char **object_lst ATTRIBUTE_UNUSED)
{
- int exit = tlink_execute ("ld", ld_argv, ldout);
+ int exit = tlink_execute ("ld", ld_argv, ldout, lderrout);
tlink_init ();
while (exit && i++ < MAX_ITERATIONS)
{
if (tlink_verbose >= 3)
- dump_file (ldout);
+ {
+ dump_file (ldout, stdout);
+ dump_file (lderrout, stderr);
+ }
demangle_new_symbols ();
- if (! scan_linker_output (ldout))
+ if (! scan_linker_output (ldout)
+ && ! scan_linker_output (lderrout))
break;
if (! recompile_files ())
break;
if (tlink_verbose)
fprintf (stderr, _("collect: relinking\n"));
- exit = tlink_execute ("ld", ld_argv, ldout);
+ exit = tlink_execute ("ld", ld_argv, ldout, lderrout);
}
}
- dump_file (ldout);
+ dump_file (ldout, stdout);
unlink (ldout);
+ dump_file (lderrout, stderr);
+ unlink (lderrout);
if (exit)
{
error ("ld returned %d exit status", exit);