[distcc] #line patchup (Re: distcc CVS)
Tim Janik
timj at gtk.org
Thu Nov 7 21:46:02 GMT 2002
On Thu, 7 Nov 2002, Martin Pool wrote:
> > actually no. if #line 1 "/<path>/foo.c" is the first thing fed into cpp,
> > all subsequent paths that cpp emits relative to this file, are actually
> > /<path>/ absolute, and not relative anymore.
>
> Wow, how interesting! Thanks for pointing that out. I can see now
> why it works.
>
> objdump shows that the original name of the file does still get in
> there, presumably since it's the first '#' line in the cpp output.
> However, gdb does look in the intended place.
>
> So this might fix it nicely. I'll try to put it in.
hey martin, i hacked up a short version of the agressive postprocessing
idea, and am currently testing it out. it seems to work so far.
please forgive the way i integrated the code into distcc (i.e.
dcc_post_process() and callers), i really just concentrated on
post_process() and descendants, because you probably want
to change the way things work anyway.
so here's the patch to fix up all #line directives for you to try out.
i'm going to give your lockup fix a couple hard tests now ;)
---
ciaoTJ
Index: distcc.c
===================================================================
RCS file: /cvsroot/distcc/src/distcc.c,v
retrieving revision 1.134
diff -u -u -p -r1.134 distcc.c
--- distcc.c 1 Nov 2002 08:02:57 -0000 1.134
+++ distcc.c 7 Nov 2002 21:38:48 -0000
@@ -61,6 +61,214 @@
#include "where.h"
+static void post_process_string_rest (FILE *fin,
+ FILE *fout,
+ int term /* must be '\"' or '\'' */)
+{
+ int escape = FALSE;
+ while (1) {
+ int c = fgetc (fin);
+ switch (c) {
+ case EOF:
+ return; /* broken input */
+ case '\\':
+ fputc (c, fout);
+ escape = !escape;
+ break;
+ case '\"':
+ case '\'':
+ fputc (c, fout);
+ if (c == term && !escape)
+ return;
+ escape = FALSE;
+ break;
+ default:
+ fputc (c, fout);
+ escape = FALSE;
+ break;
+ }
+ }
+}
+
+static void post_process_comment_rest (FILE *fin,
+ FILE *fout,
+ int term /* must be '\n' or '/' */)
+{
+ int seenast = FALSE;
+ /* read up to \n or * followed by / */
+ while (1) {
+ int c = fgetc (fin);
+ switch (c) {
+ case EOF:
+ return; /* broken input */
+ case '*':
+ fputc (c, fout);
+ seenast = TRUE;
+ break;
+ case '/':
+ fputc (c, fout);
+ if (seenast && term == c)
+ return;
+ break;
+ case '\n':
+ fputc (c, fout);
+ if (term == c)
+ return;
+ seenast = FALSE;
+ break;
+ default:
+ fputc (c, fout);
+ seenast = FALSE;
+ break;
+ }
+ }
+}
+
+static int post_process_hash (FILE *fin,
+ FILE *fout,
+ const char *pathprefix)
+{
+ int c;
+ /* check whether here comes a #line directive, hash already parsed.
+ * we need to return the last char processed
+ */
+
+ /* read up spaces */
+ c = fgetc (fin);
+ while (c == ' ' || c == '\t') {
+ fputc (c, fout);
+ c = fgetc (fin);
+ }
+ /* read up digits */
+ while (c >= '0' && c <= '9') {
+ fputc (c, fout);
+ c = fgetc (fin);
+ }
+ /* read up spaces */
+ while (c == ' ' || c == '\t') {
+ fputc (c, fout);
+ c = fgetc (fin);
+ }
+ /* read up double quote */
+ if (c != '\"')
+ goto abort;
+ fputc (c, fout);
+ c = fgetc (fin);
+ /* here it comes, if c is a slash, we got an absolute
+ * pathname, otherwise we insert our prefix and handle
+ * the rest as ordinary string
+ */
+ if (c != '/')
+ fputs (pathprefix, fout);
+ ungetc (c, fin);
+ post_process_string_rest (fin, fout, '\"');
+ return '\"';
+
+ abort:
+ if (c != EOF)
+ fputc (c, fout);
+ return c;
+}
+
+static void post_process (FILE *fin,
+ FILE *fout,
+ const char *pathprefix)
+{
+ int seennewline = TRUE;
+ int lastc, c = '\n';
+ while (1) {
+ lastc = c;
+ c = fgetc (fin);
+ switch (c) {
+ case EOF:
+ return;
+ case '\n':
+ fputc (c, fout);
+ seennewline = TRUE;
+ break;
+ case '#':
+ fputc (c, fout);
+ if (seennewline) {
+ c = post_process_hash (fin, fout, pathprefix);
+ if (c == EOF)
+ return;
+ }
+ seennewline = c == '\n';
+ break;
+ case ' ':
+ case '\t':
+ fputc (c, fout);
+ /* preserve seennewline */
+ break;
+ case '*':
+ fputc (c, fout);
+ if (lastc == '/') {
+ post_process_comment_rest (fin, fout, '/');
+ c = '/';
+ }
+ seennewline = FALSE;
+ break;
+ case '\"': case '\'':
+ fputc (c, fout);
+ post_process_string_rest (fin, fout, c);
+ seennewline = FALSE;
+ break;
+ default:
+ fputc (c, fout);
+ seennewline = FALSE;
+ break;
+ }
+ }
+}
+
+static int dcc_post_process(const char *input_fname,
+ char **pp_fname,
+ const char *source_name)
+{
+ FILE *fin, *fout;
+ char *p, *dirname;
+
+ *pp_fname = dcc_make_tmpnam ("ppline", ".i");
+
+ /* figure slash terminated directory name */
+ if (source_name[0] == '/') {
+ dirname = strdup (source_name);
+ } else {
+ int dl, sl = strlen (source_name);
+ dirname = get_current_dir_name ();
+ if (!dirname)
+ return -1;
+ dl = strlen (dirname);
+ dirname = realloc (dirname, dl + 1 + sl + 1);
+ dirname[dl++] = '/';
+ strcpy (dirname + dl, source_name);
+ p = strrchr (dirname, '/');
+ }
+ p = strrchr (dirname, '/');
+ if (p)
+ p[1] = 0;
+ dprintf (2, "#line postprocessing with path \"%s\"\n", dirname);
+
+ fin = fopen (input_fname, "r");
+ if (!fin)
+ dprintf (2, "++++++++++++++++++++ input %s failed: %s\n",input_fname,strerror(errno));
+ fout = fopen (*pp_fname, "w");
+ if (!fout)
+ dprintf (2, "++++++++++++++++++++ output %s failed: %s\n",*pp_fname,strerror(errno));
+ if (!fin || !fout)
+ return -1;
+
+ post_process (fin, fout, dirname);
+
+ fclose (fin);
+ if (fclose (fout)) {
+ dprintf (2, "++++++++++++++++++++ closing output %s failed: %s\n",*pp_fname,strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+
/* for trace.c */
const char *rs_program_name = "distcc";
@@ -169,9 +377,11 @@ static int dcc_send_job(int net_fd,
char **argv,
pid_t cpp_pid,
int *status,
+ const char *source_fname,
const char *cpp_fname)
{
long stime_usec, utime_usec;
+ char *pp_fname;
int ret;
if ((ret = dcc_x_req_header(net_fd))
@@ -202,7 +412,10 @@ static int dcc_send_job(int net_fd,
return EXIT_IO_ERROR;
}
- if ((ret = dcc_x_file(net_fd, cpp_fname, "DOTI", NULL)))
+ if ((ret = dcc_post_process (cpp_fname, &pp_fname, source_fname) != 0))
+ return ret;
+
+ if ((ret = dcc_x_file(net_fd, pp_fname, "DOTI", NULL)))
return ret;
rs_trace("client finished sending request to server");
@@ -228,13 +441,14 @@ static int dcc_send_job_corked(int net_f
char **argv,
pid_t cpp_pid,
int *status,
+ const char *source_fname,
const char *cpp_fname)
{
int ret;
tcp_cork_sock(net_fd, 1);
- ret = dcc_send_job(net_fd, argv, cpp_pid, status, cpp_fname);
+ ret = dcc_send_job(net_fd, argv, cpp_pid, status, source_fname, cpp_fname);
tcp_cork_sock(net_fd, 0);
@@ -294,7 +508,8 @@ static int dcc_retrieve_results(int net_
* necessarily imply the remote compiler itself succeeded, only that
* there were no communications problems.
**/
-static int dcc_compile_remote(char **argv,
+static int dcc_compile_remote(char **argv,
+ const char *source_fname,
char *cpp_fname, char *output_fname,
pid_t cpp_pid,
const struct dcc_hostdef *host,
@@ -312,7 +527,7 @@ static int dcc_compile_remote(char **arg
/* This waits for cpp and puts its status in *status. If cpp failed, then
* the connection will have been dropped and we need not bother trying to
* get any response from the server. */
- ret = dcc_send_job_corked(net_fd, argv, cpp_pid, status, cpp_fname);
+ ret = dcc_send_job_corked(net_fd, argv, cpp_pid, status, source_fname, cpp_fname);
if (ret == 0 && *status == 0) {
ret = dcc_retrieve_results(net_fd, status, output_fname);
}
@@ -447,7 +662,7 @@ static int dcc_build_somewhere(char *arg
if ((ret = dcc_strip_local_args(argv, &argv_stripped)))
goto fallback;
- if ((ret = dcc_compile_remote(argv_stripped, cpp_fname, output_fname,
+ if ((ret = dcc_compile_remote(argv_stripped, input_fname, cpp_fname, output_fname,
cpp_pid, host, status)) != 0) {
/* Returns zero if we successfully ran the compiler, even if
* the compiler itself bombed out. */
More information about the distcc
mailing list