[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