[distcc] patches to 2.12.1 for Windows, AIX, HPUX

Joe Buehler jbuehler at hekimian.com
Thu Mar 4 15:43:24 GMT 2004


Attached are some patches for 2.12.1 that I did to get distcc working
well with an existing build system (not gmake -- AT&T nmake) using
AIX xlC, HPUX aCC and Microsoft Visual C++ under Cygwin.

Contents:

- partial support for Microsoft Visual C++ /Fd option (two output
   files, .o and .pdb, instead of just the usual .o); some attempt was
   made to make the code handle multiple output files in a generic way

- compiler identification (by looking at its name) so we can alter
   behavior accordingly for things like file suffixes

- disabled mmap() for HPUX -- some UNIX versions do not integrate the
   file cache and mmap() and modifying a file both ways can be
   problematic

- dynamically increase buffer size when uncompressing files --
   Microsoft .pdb files compress REALLY well

- compensation for some compiler oddities -- AIX xlC does not have any
   suffix for preprocessed C input so you have to feed it a .c file so
   it knows what it is and does not treat it as C++ -- HPUX aCC wants
   .i file as C++ input

- had some problems with running from / under AIX -- the compiler
   could not write some temp files as I recall

- switched to stdio and increased default output buffer size and
   forced line-buffering to alleviate output interleaving problems from
   large command lines

- fixed some minor syntax errors and prototyping problems that gcc
   doesn't care about

note that I changed the wire protocol to be able to handle multiple
compiler output files -- this needs compatibility work

The .pdb handling for Microsoft Visual C++ is incomplete -- There is
an assumption that there is one .pdb per .o, which is not necessarily
the case (that's what my build system does), and the .pdb file names
embedded in the .o result file are wrong (the .o output file needs to
be corrected by distcc before exiting and I didn't implement that yet
-- the strings appear to be length-prefixed, not zero-terminated if
anyone wants to work on it).
-- 
Joe Buehler

-------------- next part --------------

- partial support for Microsoft Visual C++ /Fd option (two output
  files, .o and .pdb, instead of just the usual .o); some attempt was
  made to make the code handle multiple output files in a generic way

- compiler identification (by looking at its name) so we can alter
  behavior accordingly for things like file suffixes

- disabled mmap() for HPUX -- some UNIX versions do not integrate the
  file cache and mmap() and modifying a file both ways can be
  problematic

- dynamically increase buffer size when uncompressing files --
  Microsoft .pdb files compress REALLY well

- compensation for some compiler oddities -- AIX xlC does not have any
  suffix for preprocessed C input so you have to feed it a .c file so
  it knows what it is and does not treat it as C++ -- HPUX aCC wants
  .i file as C++ input

- had some problems with running from / under AIX -- the compiler
  could not write some temp files as I recall

- switched to stdio and increased default output buffer size and
  forced line-buffering to alleviate output interleaving problems from
  large command lines

- fixed some minor syntax errors and prototyping problems that gcc
  doesn't care about

note that I changed the wire protocol to be able to handle multiple
compiler output files -- this needs compatibility work

The .pdb handling for Microsoft Visual C++ is incomplete -- There is
an assumption that there is one .pdb per .o, which is not necessarily
the case (that's what my build system does), and the .pdb file names
embedded in the .o result file are wrong (the .o output file needs to
be corrected by distcc before exiting and I didn't implement that yet
-- the strings appear to be length-prefixed, not zero-terminated if
anyone wants to work on it).

--- src/arg.c.~1~	2003-10-08 01:41:49.000000000 -0400
+++ src/arg.c	2004-02-10 08:35:01.000000000 -0500
@@ -122,13 +122,15 @@
  *
  * @returns 0 if it's ok to distribute this compilation, or an error code.
  **/
-int dcc_scan_args(char *argv[], char **input_file, char **output_file,
-                  char ***ret_newargv)
+int dcc_scan_args(char *argv[], char **input_file, struct output_files *of,
+                  char ***ret_newargv, enum compiler_id *cid)
 {
     int seen_opt_c = 0, seen_opt_s = 0;
     int i;
     char *a;
     int ret;
+    char *s;
+    char *s2;
 
      /* allow for -o foo.o */
     if ((ret = dcc_shallowcopy_argv(argv, ret_newargv, 2)) != 0)
@@ -145,24 +147,57 @@
         exit(EXIT_BAD_ARGUMENTS);
     }
 
-    *input_file = *output_file = NULL;
+    *input_file = NULL;
+    memset(of, 0, sizeof(*of));
+
+    /* strip directory from compiler name */
+    rs_log_info("argv[0] %s", argv[0]);
+    s = strrchr(argv[0], '/');
+    if (s) {
+        s = s + 1;
+    } else {
+        s = argv[0];
+    }
+    rs_log_info("s %s", s);
+    s2 = strrchr(s, '\\');
+    if (s2) {
+        s = s2 + 1;
+    }
+    rs_log_info("s %s", s);
+    /* figure out which compiler we are using */
+    if (!strncmp(s, "xlC", 3)) {
+        *cid = COMPILER_ID_AIX_XLC;
+    } else if (!strcmp(s, "aCC")) {
+        *cid = COMPILER_ID_HPUX_ACC;
+    } else if (!strcmp(s, "cl")) {
+        *cid = COMPILER_ID_WINDOWS_MSVC;
+    } else if (!strcmp(s, "cl.exe")) {
+        *cid = COMPILER_ID_WINDOWS_MSVC;
+    } else if (!strcmp(s, "CL")) {
+        *cid = COMPILER_ID_WINDOWS_MSVC;
+    } else if (!strcmp(s, "CL.EXE")) {
+        *cid = COMPILER_ID_WINDOWS_MSVC;
+    } else {
+        *cid = COMPILER_ID_GCC;
+    }
+    rs_log_info("compiler id %d", *cid);
 
     for (i = 0; (a = argv[i]); i++) {
         if (a[0] == '-') {
             if (!strcmp(a, "-E")) {
                 rs_trace("-E call for cpp must be local");
                 return EXIT_DISTCC_FAILED;
-            } else if (!strcmp(a, "-MD") || !strcmp(a, "-MMD")) {
+            } else if (*cid == COMPILER_ID_GCC && (!strcmp(a, "-MD") || !strcmp(a, "-MMD"))) {
                 /* These two generate dependencies as a side effect.  They
                  * should work with the way we call cpp. */
-            } else if (!strcmp(a, "-MG") || !strcmp(a, "-MP")) {
+            } else if (*cid == COMPILER_ID_GCC && (!strcmp(a, "-MG") || !strcmp(a, "-MP"))) {
                 /* These just modify the behaviour of other -M* options and do
                  * nothing by themselves. */
-            } else if (!strcmp(a, "-MF") || !strcmp(a, "-MT") || 
-                       !strcmp(a, "-MQ")) {
+            } else if (*cid == COMPILER_ID_GCC && (!strcmp(a, "-MF") || !strcmp(a, "-MT") || 
+                       !strcmp(a, "-MQ"))) {
                 /* as above but with extra argument */
                 i++;
-            } else if (a[1] == 'M') {
+            } else if (*cid == COMPILER_ID_GCC && (a[1] == 'M')) {
                 /* -M(anything else) causes the preprocessor to
                     produce a list of make-style dependencies on
                     header files, either to stdout or to a local file.
@@ -213,14 +248,25 @@
                     return EXIT_DISTCC_FAILED;
                 }
                 *input_file = a;
+            } else if (*cid == COMPILER_ID_WINDOWS_MSVC && str_startswith("/Fd", a)) {
+                a += 3;         /* skip "/Fd" */
+                rs_trace("found debug/output file \"%s\"", a);
+                if (of->debug_file) {
+                    rs_log_info("two debug output files?  i give up");
+                    return EXIT_DISTCC_FAILED;
+                }
+                of->debug_file = a;
+            } else if (*cid == COMPILER_ID_WINDOWS_MSVC && str_startswith("/Fo", a)) {
+                a += 3;         /* skip "/Fo" */
+                goto GOT_OUTPUT;
             } else if (str_endswith(".o", a)) {
               GOT_OUTPUT:
                 rs_trace("found object/output file \"%s\"", a);
-                if (*output_file) {
+                if (of->object_file) {
                     rs_log_info("called for link?  i give up");
                     return EXIT_DISTCC_FAILED;
                 }
-                *output_file = a;
+                of->object_file = a;
             }
         }
     }
@@ -239,7 +285,7 @@
         return EXIT_DISTCC_FAILED;
     }
 
-    if (!*output_file) {
+    if (!of->object_file) {
         /* This is a commandline like "gcc -c hello.c".  They want
          * hello.o, but they don't say so.  For example, the Ethereal
          * makefile does this. 
@@ -266,12 +312,12 @@
                       ofile);
         dcc_argv_append(argv, strdup("-o"));
         dcc_argv_append(argv, ofile);
-        *output_file = ofile;
+        of->object_file = ofile;
     }
 
-    dcc_note_compiled(*input_file, *output_file);
+    dcc_note_compiled(*input_file, of->object_file);
 
-    if (strcmp(*output_file, "-") == 0) {
+    if (strcmp(of->object_file, "-") == 0) {
         /* Different compilers may treat "-o -" as either "write to
          * stdout", or "write to a file called '-'".  We can't know,
          * so we just always run it locally.  Hopefully this is a
@@ -322,29 +368,52 @@
  * detected by dcc_scan_args(), it's also correctly identified here.
  * It might be better to make the code shared.
  **/
-int dcc_set_output(char **a, char *ofname)
+int dcc_set_output(char **a, struct output_files *of, enum compiler_id cid)
 {
     int i;
+    int ok = 0;
     
     for (i = 0; a[i]; i++) 
         if (0 == strcmp(a[i], "-o")  &&  a[i+1] != NULL) {
             rs_trace("changed output from \"%s\" to \"%s\"", a[i+1],
-                     ofname);
-            a[i+1] = ofname;
+                     of->object_file);
+            a[i+1] = of->object_file;
             dcc_trace_argv("command after", a);
-            return 0;
+            ok = 1;
         } else if (0 == strncmp(a[i], "-o", 2)) {
             char *newptr;
 
-            if (asprintf(&newptr, "-o%s", ofname) == -1) {
+            if (asprintf(&newptr, "-o%s", of->object_file) == -1) {
                 rs_fatal("failed to allocate space for output parameter");
             }
             
             a[i] = newptr;
             dcc_trace_argv("command after", a);
-            return 0;
-        }
+            ok = 1;
+        } else if (cid == COMPILER_ID_WINDOWS_MSVC && !strncmp(a[i], "/Fd", 3)) {
+            char *newptr;
 
+            if (asprintf(&newptr, "/Fd%s", of->debug_file) == -1) {
+                rs_fatal("failed to allocate space for debug parameter");
+            }
+            
+            a[i] = newptr;
+            dcc_trace_argv("command after", a);
+            /* ok = 1; */ /* debug output file is optional */
+        } else if (cid == COMPILER_ID_WINDOWS_MSVC && !strncmp(a[i], "/Fo", 3)) {
+            char *newptr;
+
+            if (asprintf(&newptr, "/Fo%s", of->object_file) == -1) {
+                rs_fatal("failed to allocate space for output parameter");
+            }
+            
+            a[i] = newptr;
+            dcc_trace_argv("command after", a);
+            ok = 1;
+        }
+    if (ok) {
+        return 0;
+    }
     rs_log_error("failed to find \"-o\"");
     return EXIT_DISTCC_FAILED;
 }
--- src/arg.h.~1~	2003-07-08 01:41:05.000000000 -0400
+++ src/arg.h	2004-02-10 08:35:01.000000000 -0500
@@ -1,9 +1,9 @@
 /* arg.c */
 int dcc_set_action_opt(char **, const char *);
-int dcc_set_output(char **, char *);
+int dcc_set_output(char **, struct output_files *of, enum compiler_id cid);
 int dcc_set_input(char **, char *);
-int dcc_scan_args(char *argv[], /*@out@*/ /*@relnull@*/ char **orig_o,
-                  char **orig_i, char ***ret_newargv);
+int dcc_scan_args(char *argv[], /*@out@*/ /*@relnull@*/ char **input_file,
+                  struct output_files *of, char ***ret_newargv, enum compiler_id *cid);
 
 /* argutil.c */
 int dcc_argv_len(char **a);
--- src/clirpc.c.~1~	2003-09-23 00:07:01.000000000 -0400
+++ src/clirpc.c	2004-02-10 08:35:01.000000000 -0500
@@ -206,7 +206,7 @@
  **/
 int dcc_retrieve_results(int net_fd,
                          int *status,
-                         const char *output_fname,
+                         struct output_files *of,
                          struct dcc_hostdef *host)
 {
     unsigned len;
@@ -225,13 +225,32 @@
         || (ret = dcc_r_bulk(STDERR_FILENO, net_fd, len, host->compr))
         || (ret = dcc_r_token_int(net_fd, "SOUT", &len))
         || (ret = dcc_r_bulk(STDOUT_FILENO, net_fd, len, host->compr))
-        || (ret = dcc_r_token_int(net_fd, "DOTO", &o_len)))
+        || (ret = dcc_r_token_int(net_fd, "RSLT", &o_len)))
         return ret;
 
     /* If the compiler succeeded, then we always retrieve the result,
      * even if it's 0 bytes.  */
     if (*status == 0) {
-        return dcc_r_file_timed(net_fd, output_fname, o_len, host->compr);
+        len = 0;
+        if (of->object_file) ++len;
+        if (of->debug_file) ++len;
+        if (o_len != len) {
+            rs_log_error("remote compiler returned unexpected number of files: "
+                         "I don't know what to do");
+        } else {
+            if (of->object_file) {
+                ret = dcc_r_token_int(net_fd, "FILE", &len);
+                if (ret) return ret;
+                ret = dcc_r_file_timed(net_fd, of->object_file, len, host->compr);
+                if (ret) return ret;
+            }
+            if (of->debug_file) {
+                ret = dcc_r_token_int(net_fd, "FILE", &len);
+                if (ret) return ret;
+                ret = dcc_r_file_timed(net_fd, of->debug_file, len, host->compr);
+                if (ret) return ret;
+            }
+        }
     } else if (o_len != 0) {
         rs_log_error("remote compiler failed but also returned output: "
                      "I don't know what to do");
--- src/compile.c.~1~	2003-09-23 00:07:01.000000000 -0400
+++ src/compile.c	2004-02-10 08:35:01.000000000 -0500
@@ -115,19 +115,22 @@
                                int sg_level,
                                int *status)
 {
-    char *input_fname = NULL, *output_fname, *cpp_fname;
+    char *input_fname = NULL, *cpp_fname;
     char **argv_stripped;
     pid_t cpp_pid = 0;
     int cpu_lock_fd;
     int ret;
+    int is_cplusplus = 0;
     struct dcc_hostdef *host = NULL;
+    struct output_files of;
+    enum compiler_id cid;
 
     if (sg_level)
         goto run_local;
 
     /* TODO: Perhaps tidy up these gotos. */
 
-    if (dcc_scan_args(argv, &input_fname, &output_fname, &argv) != 0) {
+    if (dcc_scan_args(argv, &input_fname, &of, &argv, &cid) != 0) {
         /* we need to scan the arguments even if we already know it's
          * local, so that we can pick up distcc client options. */
         goto lock_local;
@@ -147,16 +150,16 @@
     if (host->mode == DCC_MODE_LOCAL)
         goto run_local;
 
-    if ((ret = dcc_cpp_maybe(argv, input_fname, &cpp_fname, &cpp_pid) != 0))
+    if ((ret = dcc_cpp_maybe(argv, input_fname, &cpp_fname, &cpp_pid, &is_cplusplus, cid) != 0))
         goto fallback;
 
-    if ((ret = dcc_strip_local_args(argv, &argv_stripped)))
+    if ((ret = dcc_strip_local_args(argv, &argv_stripped, is_cplusplus, cid)))
         goto fallback;
 
     if ((ret = dcc_compile_remote(argv_stripped,
                                   input_fname,
                                   cpp_fname,
-                                  output_fname,
+                                  &of,
                                   cpp_pid, host, status)) != 0) {
         /* Returns zero if we successfully ran the compiler, even if
          * the compiler itself bombed out. */
--- src/compile.h.~1~	2003-07-17 03:13:43.000000000 -0400
+++ src/compile.h	2004-02-10 08:35:01.000000000 -0500
@@ -24,7 +24,7 @@
 int dcc_compile_remote(char **argv,
                        char *input_fname,
                        char *cpp_fname,
-                       char *output_fname,
+                       struct output_files *of,
                        pid_t cpp_pid,
                        struct dcc_hostdef *host,
                        int *status);
--- src/compress.c.~1~	2003-09-21 23:15:28.000000000 -0400
+++ src/compress.c	2004-02-10 09:21:12.000000000 -0500
@@ -95,7 +95,7 @@
     int is_mmapped = 0;
 
     if (in_len >= 65536 && dcc_want_mmap()) {
-#ifdef HAVE_MMAP
+#if defined(HAVE_MMAP) && !defined(__hpux)
         in_buf = mmap(NULL,            /* suggested address */
                       in_len, PROT_READ, MAP_SHARED, in_fd,
                       0);              /* offset */
@@ -229,8 +229,10 @@
     /* Generously sized output buffer */
     out_size = 64 * in_len;
 
+    try_again_with_a_bigger_buffer:
+
     if (out_size >= 65536  &&  dcc_want_mmap()) {
-#ifdef HAVE_MMAP
+#if defined(HAVE_MMAP) && !defined(__hpux)
         /* First truncate the file, so that we have space to write to it.  This
          * will fail if we're e.g. writing to stdout. */
     
@@ -274,9 +276,26 @@
     lzo_ret = lzo1x_decompress_safe((lzo_byte*)in_buf, in_len,
                                     (lzo_byte*)out_buf, &out_len, work_mem);
     if (lzo_ret != LZO_E_OK) {
-        rs_log_error("LZO1X1 decompression failed: %d", lzo_ret);
-        ret = EXIT_IO_ERROR;
-        goto out;
+        if (lzo_ret != LZO_E_OUTPUT_OVERRUN) {
+            rs_log_error("LZO1X1 decompression failed: %d", lzo_ret);
+            ret = EXIT_IO_ERROR;
+            goto out;
+        }
+        out_size *= 2;
+        rs_log_error("LZO_E_OUTPUT_OVERRUN, trying again with a bigger buffer (%d)", out_size);
+        if (is_mmapped) {
+            if (munmap(out_buf, out_size) == -1) {
+                rs_log_error("munmap (output) failed: %s",
+                             strerror(errno));
+                ret = EXIT_IO_ERROR;
+                goto out;
+            }
+            is_mmapped = 0;
+        } else if (out_buf != NULL) {
+            free(out_buf);
+            out_buf = 0;
+        }
+        goto try_again_with_a_bigger_buffer;
     }
 
     rs_trace("decompressed %ld bytes to %ld bytes: %d%%",
--- src/cpp.c.~1~	2003-07-25 00:10:04.000000000 -0400
+++ src/cpp.c	2004-02-10 08:35:01.000000000 -0500
@@ -57,13 +57,14 @@
  * use many cycles, with running the preprocessor.
  **/
 int dcc_cpp_maybe(char **argv, char *input_fname, char **cpp_fname,
-		  pid_t *cpp_pid)
+		  pid_t *cpp_pid, int *is_cplusplus, enum compiler_id cid)
 {
     char **cpp_argv;
     int ret;
     char *input_exten;
     const char *output_exten;
 
+    *is_cplusplus = 0;
     *cpp_pid = 0;
     
     if (dcc_is_preprocessed(input_fname)) {
@@ -79,7 +80,7 @@
     }
 
     input_exten = dcc_find_extension(input_fname);
-    output_exten = dcc_preproc_exten(input_exten);
+    output_exten = dcc_preproc_exten(input_exten, is_cplusplus, cid);
     if ((ret = dcc_make_tmpnam("distcc", output_exten, cpp_fname)))
         return ret;
 
--- src/cpp.h.~1~	2003-07-08 02:49:44.000000000 -0400
+++ src/cpp.h	2004-02-10 08:35:01.000000000 -0500
@@ -1,2 +1,2 @@
 int dcc_cpp_maybe(char **argv, char *input_fname, char **cpp_fname,
-		  pid_t *cpp_pid);
+		  pid_t *cpp_pid, int *is_cplusplus, enum compiler_id cid);
--- src/daemon.c.~1~	2003-11-27 19:11:45.000000000 -0500
+++ src/daemon.c	2004-02-10 08:35:01.000000000 -0500
@@ -181,8 +181,8 @@
     /* Do everything from root directory.  Allows start directory to be
      * unmounted, should make accidental writing of local files cause a
      * failure... */
-    if (chdir("/") == -1) {
-        rs_log_error("failed to chdir to /: %s", strerror(errno));
+    if (chdir("/tmp") == -1) {
+        rs_log_error("failed to chdir to /tmp: %s", strerror(errno));
         ret = EXIT_IO_ERROR;
         goto out;
     }
--- src/distcc.c.~1~	2003-10-13 05:59:25.000000000 -0400
+++ src/distcc.c	2004-02-10 08:35:01.000000000 -0500
@@ -163,6 +163,9 @@
 
     dcc_trace_version();
 
+    setvbuf(stdout, 0, _IOLBF, 32768);
+    setvbuf(stderr, 0, _IOLBF, 32768);
+
     compiler_name = (char *) dcc_find_basename(argv[0]);
 
     /* Ignore SIGPIPE; we consistently check error codes and will
--- src/distcc.h.~1~	2003-11-27 19:18:49.000000000 -0500
+++ src/distcc.h	2004-02-10 08:35:01.000000000 -0500
@@ -53,10 +53,17 @@
 
 struct dcc_hostdef;
 
+struct output_files {
+    char *object_file;
+    char *debug_file;
+};
 
-
-
-
+enum compiler_id {
+    COMPILER_ID_GCC = 0,
+    COMPILER_ID_WINDOWS_MSVC = 1,
+    COMPILER_ID_AIX_XLC = 2,
+    COMPILER_ID_HPUX_ACC = 3
+};
 
 enum dcc_compress {
     /* wierd values to catch errors */
@@ -125,7 +132,8 @@
                         struct dcc_hostdef *);
 
 int dcc_retrieve_results(int net_fd,
-                         int *status, const char *output_fname,
+                         int *status,
+                         struct output_files *of,
                          struct dcc_hostdef *);
 
 /* climasq.c */
@@ -183,4 +191,3 @@
 #ifndef MAXPATHLEN
 #define MAXPATHLEN 4096
 #endif
-
--- src/exitcode.h.~1~	2003-08-04 22:09:29.000000000 -0400
+++ src/exitcode.h	2004-02-10 08:35:01.000000000 -0500
@@ -53,7 +53,7 @@
     EXIT_BUSY                     = 114, /**< In use by another process. */
     EXIT_NO_SUCH_FILE             = 115,
     EXIT_NO_HOSTS                 = 116,
-    EXIT_GONE                     = 117, /**< No longer relevant */
+    EXIT_GONE                     = 117 /**< No longer relevant */
 };
 
 
--- src/filename.c.~1~	2003-07-22 03:32:36.000000000 -0400
+++ src/filename.c	2004-02-10 08:35:01.000000000 -0500
@@ -133,18 +133,29 @@
  * @returns preprocessed extension, (e.g. ".i"), or NULL if
  * unrecognized.
  **/
-const char * dcc_preproc_exten(const char *e)
+const char * dcc_preproc_exten(const char *e, int *is_cplusplus, enum compiler_id cid)
 {
     if (e[0] != '.')
         return NULL;
     e++;
     if (!strcmp(e, "i") || !strcmp(e, "c")) {
-        return ".i";
+        if (cid == COMPILER_ID_AIX_XLC) {
+            /* AIX xlC C/C++ compiler treats .i file as C++ so we have to leave it .c */
+            return ".c";
+        } else {
+            return ".i";
+        }
     } else if (!strcmp(e, "c") || !strcmp(e, "cc")
                || !strcmp(e, "cpp") || !strcmp(e, "cxx")
                || !strcmp(e, "cp") || !strcmp(e, "c++")
                || !strcmp(e, "C") || !strcmp(e, "ii")) {
-        return ".ii";
+        *is_cplusplus = 1;
+        if (cid == COMPILER_ID_HPUX_ACC) {
+            /* HPUX aCC C++ compiler wants .i file as C++ input */
+            return ".i";
+        } else {
+            return ".ii";
+        }
     } else if(!strcmp(e,"mi") || !strcmp(e, "m")) {
         return ".mi";
     } else if(!strcmp(e,"mii") || !strcmp(e,"mm")
--- src/filename.h.~1~	2003-07-11 00:18:28.000000000 -0400
+++ src/filename.h	2004-02-10 08:35:01.000000000 -0500
@@ -7,5 +7,5 @@
 int dcc_output_from_source(const char *sfile, const char *out_extn,
                            char **ofile);
 
-const char * dcc_preproc_exten(const char *e);
+const char * dcc_preproc_exten(const char *e, int *is_cplusplus, enum compiler_id cid);
 const char * dcc_find_basename(const char *sfile);
--- src/h_scanargs.c.~1~	2003-07-13 20:43:07.000000000 -0400
+++ src/h_scanargs.c	2004-02-10 08:35:01.000000000 -0500
@@ -49,8 +49,12 @@
 int main(int argc, char *argv[])
 {
     int result;
-    char *infname, *outfname;
+    char *infname;
     char **newargv, **outargv;
+    struct output_files of;
+    enum compiler_id cid;
+
+    memset(&of, 0, sizeof(of));
 
     rs_trace_set_level(RS_LOG_DEBUG);
 
@@ -64,11 +68,11 @@
     if (result)
 	return result;
 
-    result = dcc_scan_args(newargv, &infname, &outfname, &outargv);
+    result = dcc_scan_args(newargv, &infname, &of, &outargv, &cid);
 
     printf("%s %s %s\n",
 	   result == 0 ? "distribute" : "local",
-	   infname ? infname : "(NULL)", outfname ? outfname : "(NULL)");
+	   infname ? infname : "(NULL)", of->object_file ? of->object_file : "(NULL)");
 
     return 0;
 }
--- src/h_strip.c.~1~	2003-07-13 20:43:07.000000000 -0400
+++ src/h_strip.c	2004-02-10 08:35:01.000000000 -0500
@@ -56,7 +56,8 @@
         return 1;
     }
 
-    if ((ret = dcc_strip_local_args(argv + 1, &new_args))) {
+    if ((ret = dcc_strip_local_args(argv + 1, &new_args, 0 /* is_cplusplus */,
+                                    COMPILER_ID_GCC))) {
         return ret;
     }
 
--- src/hosts.c.~1~	2003-07-20 22:00:38.000000000 -0400
+++ src/hosts.c	2004-02-10 08:35:01.000000000 -0500
@@ -383,7 +383,7 @@
         }
 
         /* Store verbatim hostname */
-        if (!(curr->hostdef_string = strndup(token_start, token_len))) {
+        if (!(curr->hostdef_string = (char *)strndup(token_start, token_len))) {
             rs_log_crit("failed to allocate hostdef_string");
             return EXIT_OUT_OF_MEMORY;
         }
--- src/io.c.~1~	2003-08-25 01:37:11.000000000 -0400
+++ src/io.c	2004-02-10 08:35:01.000000000 -0500
@@ -72,7 +72,7 @@
 
 int dcc_want_mmap(void)
 {
-#ifdef HAVE_MMAP
+#if defined(HAVE_MMAP) && !defined(__hpux)
     return dcc_getenv_bool("DISTCC_MMAP", 1);
 #else
     return 0;
@@ -166,7 +166,7 @@
     int ret;
 
     while (len > 0) {
-	r = read(fd, buf, len);
+        r = read(fd, buf, len);
 
         if (r == -1 && errno == EAGAIN) {
             if ((ret = dcc_select_for_read(fd, dcc_io_timeout)))
@@ -176,15 +176,15 @@
         } else if (r == -1 && errno == EAGAIN) {
             continue;
         } else if (r == -1) {
-	    rs_log_error("failed to read: %s", strerror(errno));
-	    return EXIT_IO_ERROR;
-	} else if (r == 0) {
-	    rs_log_error("unexpected eof on fd%d", fd);
-	    return EXIT_TRUNCATED;
-	} else {
-	    buf = &((char *) buf)[r];
-	    len -= r;
-	}
+            rs_log_error("failed to read: %s", strerror(errno));
+            return EXIT_IO_ERROR;
+        } else if (r == 0) {
+            rs_log_error("dcc_readx() unexpected eof on fd%d", fd);
+            return EXIT_TRUNCATED;
+        } else {
+            buf = &((char *) buf)[r];
+            len -= r;
+        }
     }
 
     return 0;
@@ -203,7 +203,15 @@
     int ret;
 	
     while (len > 0) {
-        r = write(fd, buf, len);
+        if (fd == STDOUT_FILENO) {
+            r = (fwrite(buf, len, 1, stdout) == 1) ? len : -1;
+            /* fflush(stdout); */
+        } else if (fd == STDERR_FILENO) {
+            r = (fwrite(buf, len, 1, stderr) == 1) ? len : -1;
+            /* fflush(stderr); */
+        } else {
+            r = write(fd, buf, len);
+        }
 
         if (r == -1 && errno == EAGAIN) {
             if ((ret = dcc_select_for_write(fd, dcc_io_timeout)))
@@ -216,7 +224,7 @@
             rs_log_error("failed to write: %s", strerror(errno));
             return EXIT_IO_ERROR;
         } else if (r == 0) {
-            rs_log_error("unexpected eof on fd%d", fd);
+            rs_log_error("dcc_writex() unexpected eof on fd%d", fd);
             return EXIT_TRUNCATED;
         } else {
             buf = &((char *) buf)[r];
--- src/pump.c.~1~	2004-01-08 20:08:32.000000000 -0500
+++ src/pump.c	2004-02-10 08:35:01.000000000 -0500
@@ -75,7 +75,7 @@
         return 0;               /* just check */
 
     if (len >= 65536  &&  dcc_want_mmap()) {
-#ifdef HAVE_MMAP
+#if defined(HAVE_MMAP) && !defined(__hpux)
         /* First truncate the file, so that we have space to write to it.  This
          * will fail if we're e.g. writing to stdout. */
     
@@ -204,7 +204,7 @@
                          (long) wanted, strerror(errno));
             return EXIT_IO_ERROR;
         } else if (r_in == 0) {
-            rs_log_error("unexpected eof on fd%d", ifd);
+            rs_log_error("dcc_pump_readwrite() unexpected eof on fd%d", ifd);
             return EXIT_IO_ERROR;
         }
         
--- src/remote.c.~1~	2003-09-23 00:07:03.000000000 -0400
+++ src/remote.c	2004-02-10 08:35:01.000000000 -0500
@@ -127,7 +127,7 @@
 int dcc_compile_remote(char **argv, 
                        char *input_fname,
                        char *cpp_fname,
-                       char *output_fname,
+                       struct output_files *of,
                        pid_t cpp_pid,
                        struct dcc_hostdef *host,
                        int *status)
@@ -168,8 +168,7 @@
     /* If cpp failed, just abandon the connection, without trying to
      * receive results. */
     if (ret == 0 && *status == 0) {
-        ret = dcc_retrieve_results(from_net_fd, status, output_fname,
-                                   host);
+        ret = dcc_retrieve_results(from_net_fd, status, of, host);
     }
 
     /* Close socket so that the server can terminate, rather than
--- src/serve.c.~1~	2003-11-16 22:00:15.000000000 -0500
+++ src/serve.c	2004-02-10 08:35:01.000000000 -0500
@@ -162,14 +162,16 @@
 
 
 static int dcc_input_tmpnam(char * orig_input,
-                            char **tmpnam_ret)
+                            char **tmpnam_ret,
+                            enum compiler_id cid)
 {
+    int is_cplusplus = 0;
     const char *input_exten;
     
     rs_trace("input file %s", orig_input);
     input_exten = dcc_find_extension(orig_input);
     if (input_exten)
-        input_exten = dcc_preproc_exten(input_exten);
+        input_exten = dcc_preproc_exten(input_exten, &is_cplusplus, cid);
     if (!input_exten)           /* previous line might return NULL */
         input_exten = ".tmp";
     return dcc_make_tmpnam("distccd", input_exten, tmpnam_ret);
@@ -252,13 +254,19 @@
 {
     char **argv;
     int status;
-    char *temp_i, *temp_o, *err_fname, *out_fname;
+    char *temp_i, *err_fname, *out_fname;
     int ret, compile_ret;
-    char *orig_input, *orig_output;
+    char *orig_input;
     pid_t cc_pid;
     enum dcc_protover protover;
     enum dcc_compress compr;
+    struct output_files of_orig;
+    struct output_files of_temp;
+    enum compiler_id cid;
     
+    memset(&of_temp, 0, sizeof(of_temp));
+    memset(&of_orig, 0, sizeof(of_orig));
+
     if ((ret = dcc_make_tmpnam("distcc", ".stderr", &err_fname)))
         return ret;
     if ((ret = dcc_make_tmpnam("distcc", ".stdout", &out_fname)))
@@ -282,21 +290,28 @@
 
     if ((ret = dcc_r_request_header(in_fd, &protover))
         || (ret = dcc_r_argv(in_fd, &argv))
-        || (ret = dcc_scan_args(argv, &orig_input, &orig_output, &argv)))
+        || (ret = dcc_scan_args(argv, &orig_input, &of_orig, &argv, &cid)))
         goto out_cleanup;
     
-    rs_trace("output file %s", orig_output);
+    rs_trace("output file %s", of_orig.object_file);
+    rs_trace("debug file %s", of_orig.debug_file ? of_orig.debug_file : "not present");
 
-    if ((ret = dcc_input_tmpnam(orig_input, &temp_i)))
-        goto out_cleanup;
-    if ((ret = dcc_make_tmpnam("distccd", ".o", &temp_o)))
+    if ((ret = dcc_input_tmpnam(orig_input, &temp_i, cid)))
         goto out_cleanup;
+    if (of_orig.object_file) {
+        if ((ret = dcc_make_tmpnam("distccd", ".o", &of_temp.object_file)))
+            goto out_cleanup;
+    }
+    if (of_orig.debug_file) {
+        if ((ret = dcc_make_tmpnam("distccd", ".pdb", &of_temp.debug_file)))
+            goto out_cleanup;
+    }
 
     compr = (protover == 2) ? DCC_COMPRESS_LZO1X : DCC_COMPRESS_NONE;
 
     if ((ret = dcc_r_token_file(in_fd, "DOTI", temp_i, compr))
         || (ret = dcc_set_input(argv, temp_i))
-        || (ret = dcc_set_output(argv, temp_o)))
+        || (ret = dcc_set_output(argv, &of_temp, cid)))
         goto out_cleanup;
 
     if ((ret = dcc_check_compiler_masq(argv[0])))
@@ -315,10 +330,19 @@
         || (ret = dcc_x_file(out_fd, out_fname, "SOUT", compr))
         || WIFSIGNALED(status)
         || WEXITSTATUS(status)) {
-        /* Something went wrong, so send DOTO 0 */
-        dcc_x_token_int(out_fd, "DOTO", 0);
+        /* Something went wrong, so send RSLT 0 */
+        ret = dcc_x_token_int(out_fd, "RSLT", 0);
     } else {
-        ret = dcc_x_file(out_fd, temp_o, "DOTO", compr);
+        int len = 0;
+        if (of_orig.object_file) ++len;
+        if (of_orig.debug_file) ++len;
+        ret = dcc_x_token_int(out_fd, "RSLT", len);
+        if (of_orig.object_file) {
+            ret = ret || dcc_x_file(out_fd, of_temp.object_file, "FILE", compr);
+        }
+        if (of_orig.debug_file) {
+            ret = ret || dcc_x_file(out_fd, of_temp.debug_file, "FILE", compr);
+        }
     }
 
     dcc_critique_status(status, argv[0], dcc_hostdef_local, 0);
--- src/strip.c.~1~	2003-07-08 01:42:38.000000000 -0400
+++ src/strip.c	2004-02-10 08:35:01.000000000 -0500
@@ -59,14 +59,14 @@
  * passed directly to cpp.  When given to gcc they have different
  * meanings.
  **/
-int dcc_strip_local_args(char **from, char ***out_argv)
+int dcc_strip_local_args(char **from, char ***out_argv, int is_cplusplus, enum compiler_id cid)
 {
     char **to;
     int from_i, to_i;
     int from_len;
 
     from_len = dcc_argv_len(from);
-    *out_argv = to = malloc((from_len + 1) * sizeof (char *));
+    *out_argv = to = malloc((from_len + 1 + (is_cplusplus && cid == COMPILER_ID_AIX_XLC)) * sizeof (char *));
 
     if (!to) {
         rs_log_error("failed to allocate space for arguments");
@@ -81,9 +81,9 @@
             || str_equal("-U", from[from_i])
             || str_equal("-L", from[from_i])
             || str_equal("-l", from[from_i])
-            || str_equal("-MF", from[from_i])
-            || str_equal("-MT", from[from_i])
-            || str_equal("-MQ", from[from_i])
+            || (cid == COMPILER_ID_GCC && str_equal("-MF", from[from_i]))
+            || (cid == COMPILER_ID_GCC && str_equal("-MT", from[from_i]))
+            || (cid == COMPILER_ID_GCC && str_equal("-MQ", from[from_i]))
             || str_equal("-include", from[from_i])
             || str_equal("-imacros", from[from_i])
             || str_equal("-iprefix", from[from_i])
@@ -109,16 +109,20 @@
         else if (str_equal("-undef", from[from_i])
                  || str_equal("-nostdinc", from[from_i])
                  || str_equal("-nostdinc++", from[from_i])
-                 || str_equal("-MD", from[from_i])
-                 || str_equal("-MMD", from[from_i])
-                 || str_equal("-MG", from[from_i])
-                 || str_equal("-MP", from[from_i])) {
+                 || (cid == COMPILER_ID_GCC && str_equal("-MD", from[from_i]))
+                 || (cid == COMPILER_ID_GCC && str_equal("-MMD", from[from_i]))
+                 || (cid == COMPILER_ID_GCC && str_equal("-MG", from[from_i]))
+                 || (cid == COMPILER_ID_GCC && str_equal("-MP", from[from_i]))) {
             /* Options that only affect cpp; skip */
             ;
         }
         else {
             to[to_i++] = from[from_i];
         }
+        if (from_i == 0 && is_cplusplus && cid == COMPILER_ID_AIX_XLC) {
+            /* force AIX xlC to compile as C++ if the input is indeed C++ */
+            to[to_i++] = "-+";
+        }
     }
     
     /* NULL-terminate */
--- src/strip.h.~1~	2002-12-04 16:29:50.000000000 -0500
+++ src/strip.h	2004-02-10 08:35:01.000000000 -0500
@@ -21,5 +21,5 @@
  * USA
  */
 
-int dcc_strip_local_args(char **from, char ***out_argv);
+int dcc_strip_local_args(char **from, char ***out_argv, int is_cplusplus, enum compiler_id cid);
 int dcc_strip_dasho(char **from, char ***out_argv);
--- src/tempfile.c.~1~	2003-09-29 02:56:24.000000000 -0400
+++ src/tempfile.c	2004-02-10 08:49:18.000000000 -0500
@@ -268,6 +268,12 @@
                      suffix) == -1)
             return EXIT_OUT_OF_MEMORY;
 
+        if (!strcmp(suffix, ".pdb")) {
+            /* do NOT create .pdb file for compiler -- in fact, make sure it does not exist */
+            unlink(s);
+            break;
+        }
+
         /* Note that if the name already exists as a symlink, this
          * open call will fail.
          *


More information about the distcc mailing list