You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by nw...@apache.org on 2016/06/04 15:30:33 UTC

[1/7] lucy-charmonizer git commit: Separate detection of shell and binary format

Repository: lucy-charmonizer
Updated Branches:
  refs/heads/master bd9f6b531 -> 77d32d09a


Separate detection of shell and binary format

Detect shell by escape character. This should be more robust than
looking for /dev/null files.

Detect binary format by looking at the magic bytes of a compiled
executable.

Move information about binary format and file extensions to Compiler.
That's where it belongs if you think about cross-compiling.


Project: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/commit/e3b57156
Tree: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/tree/e3b57156
Diff: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/diff/e3b57156

Branch: refs/heads/master
Commit: e3b57156cde95a9e74039e5bad2d74dff6674380
Parents: bd9f6b5
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sat May 21 18:59:20 2016 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Wed Jun 1 23:47:27 2016 +0200

----------------------------------------------------------------------
 src/Charmonizer/Core/CFlags.c          |  22 ++--
 src/Charmonizer/Core/Compiler.c        | 168 ++++++++++++++++++++++++----
 src/Charmonizer/Core/Compiler.h        |  29 +++++
 src/Charmonizer/Core/Library.c         |  34 +++---
 src/Charmonizer/Core/Make.c            |  30 ++---
 src/Charmonizer/Core/OperatingSystem.c | 107 +++++-------------
 src/Charmonizer/Core/OperatingSystem.h |  26 -----
 7 files changed, 245 insertions(+), 171 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/e3b57156/src/Charmonizer/Core/CFlags.c
----------------------------------------------------------------------
diff --git a/src/Charmonizer/Core/CFlags.c b/src/Charmonizer/Core/CFlags.c
index 99c6668..1c177b5 100644
--- a/src/Charmonizer/Core/CFlags.c
+++ b/src/Charmonizer/Core/CFlags.c
@@ -207,19 +207,15 @@ chaz_CFlags_compile_shared_library(chaz_CFlags *flags) {
         string = "/MD";
     }
     else if (flags->style == CHAZ_CFLAGS_STYLE_GNU) {
-        const char *shlib_ext = chaz_OS_shared_lib_ext();
-        if (strcmp(shlib_ext, ".dylib") == 0) {
+        int binary_format = chaz_CC_binary_format();
+        if (binary_format == CHAZ_CC_BINFMT_MACHO) {
             string = "-fno-common";
         }
-        else if (strcmp(shlib_ext, ".so") == 0) {
+        else if (binary_format == CHAZ_CC_BINFMT_ELF) {
             string = "-fPIC";
         }
-        else if (strcmp(shlib_ext, ".dll") == 0) {
-            /* MinGW */
-            return;
-        }
         else {
-            /* unknown */
+            /* MinGW. */
             return;
         }
     }
@@ -235,7 +231,7 @@ chaz_CFlags_compile_shared_library(chaz_CFlags *flags) {
 void
 chaz_CFlags_hide_symbols(chaz_CFlags *flags) {
     if (flags->style == CHAZ_CFLAGS_STYLE_GNU) {
-        if (strcmp(chaz_OS_shared_lib_ext(), ".dll") != 0) {
+        if (chaz_CC_binary_format() != CHAZ_CC_BINFMT_PE) {
             chaz_CFlags_append(flags, "-fvisibility=hidden");
         }
     }
@@ -254,7 +250,7 @@ chaz_CFlags_link_shared_library(chaz_CFlags *flags) {
         string = "/DLL";
     }
     else if (flags->style == CHAZ_CFLAGS_STYLE_GNU) {
-        if (strcmp(chaz_OS_shared_lib_ext(), ".dylib") == 0) {
+        if (chaz_CC_binary_format() == CHAZ_CC_BINFMT_MACHO) {
             string = "-dynamiclib";
         }
         else {
@@ -274,16 +270,16 @@ chaz_CFlags_link_shared_library(chaz_CFlags *flags) {
 void
 chaz_CFlags_set_shared_library_version(chaz_CFlags *flags, chaz_Lib *lib) {
     if (flags->style == CHAZ_CFLAGS_STYLE_GNU) {
-        const char *shlib_ext = chaz_OS_shared_lib_ext();
+        int binary_format = chaz_CC_binary_format();
 
-        if (strcmp(shlib_ext, ".dylib") == 0) {
+        if (binary_format == CHAZ_CC_BINFMT_MACHO) {
             const char *version = chaz_Lib_get_version(lib);
             char *string
                 = chaz_Util_join(" ", "-current_version", version, NULL);
             chaz_CFlags_append(flags, string);
             free(string);
         }
-        else if (strcmp(shlib_ext, ".so") == 0) {
+        else if (binary_format == CHAZ_CC_BINFMT_ELF) {
             char *soname = chaz_Lib_major_version_filename(lib);
             char *string = chaz_Util_join("", "-Wl,-soname,", soname, NULL);
             chaz_CFlags_append(flags, string);

http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/e3b57156/src/Charmonizer/Core/Compiler.c
----------------------------------------------------------------------
diff --git a/src/Charmonizer/Core/Compiler.c b/src/Charmonizer/Core/Compiler.c
index 32a6d43..1136d68 100644
--- a/src/Charmonizer/Core/Compiler.c
+++ b/src/Charmonizer/Core/Compiler.c
@@ -22,6 +22,11 @@
 #include "Charmonizer/Core/ConfWriter.h"
 #include "Charmonizer/Core/OperatingSystem.h"
 
+/* Detect binary format.
+ */
+static void
+chaz_CC_detect_binary_format(const char *filename);
+
 /* Detect macros which may help to identify some compilers.
  */
 static void
@@ -37,8 +42,13 @@ static struct {
     char     *cc_command;
     char     *cflags;
     char     *try_exe_name;
+    char      exe_ext[10];
+    char      shared_lib_ext[10];
+    char      static_lib_ext[10];
+    char      import_lib_ext[10];
     char      obj_ext[10];
     char      gcc_version_str[30];
+    int       binary_format;
     int       cflags_style;
     int       intval___GNUC__;
     int       intval___GNUC_MINOR__;
@@ -50,8 +60,8 @@ static struct {
     chaz_CFlags *temp_cflags;
 } chaz_CC = {
     NULL, NULL, NULL,
-    "", "",
-    0, 0, 0, 0, 0, 0, 0,
+    "", "", "", "", "", "",
+    0, 0, 0, 0, 0, 0, 0, 0,
     NULL, NULL
 };
 
@@ -70,40 +80,40 @@ chaz_CC_init(const char *compiler_command, const char *compiler_flags) {
     chaz_CC.temp_cflags  = NULL;
 
     /* Set names for the targets which we "try" to compile. */
+    strcpy(chaz_CC.exe_ext, ".exe");
     chaz_CC.try_exe_name
-        = chaz_Util_join("", CHAZ_CC_TRY_BASENAME, chaz_OS_exe_ext(), NULL);
+        = chaz_Util_join("", CHAZ_CC_TRY_BASENAME, chaz_CC.exe_ext, NULL);
 
     /* If we can't compile or execute anything, game over. */
     if (chaz_Util_verbosity) {
         printf("Trying to compile and execute a small test file...\n");
     }
-    if (!chaz_Util_remove_and_verify(chaz_CC.try_exe_name)) {
-        chaz_Util_die("Failed to delete file '%s'", chaz_CC.try_exe_name);
-    }
+
     /* Try MSVC argument style. */
-    strcpy(chaz_CC.obj_ext, ".obj");
-    chaz_CC.cflags_style = CHAZ_CFLAGS_STYLE_MSVC;
-    compile_succeeded = chaz_CC_compile_exe(CHAZ_CC_TRY_SOURCE_PATH,
-                                            CHAZ_CC_TRY_BASENAME, code);
     if (!compile_succeeded) {
-        /* Try POSIX argument style. */
-        strcpy(chaz_CC.obj_ext, ".o");
+        chaz_CC.cflags_style = CHAZ_CFLAGS_STYLE_MSVC;
+        if (!chaz_Util_remove_and_verify(chaz_CC.try_exe_name)) {
+            chaz_Util_die("Failed to delete file '%s'", chaz_CC.try_exe_name);
+        }
+        compile_succeeded = chaz_CC_compile_exe(CHAZ_CC_TRY_SOURCE_PATH,
+                                                CHAZ_CC_TRY_BASENAME, code);
+    }
+
+    /* Try POSIX argument style. */
+    if (!compile_succeeded) {
         chaz_CC.cflags_style = CHAZ_CFLAGS_STYLE_POSIX;
+        if (!chaz_Util_remove_and_verify(chaz_CC.try_exe_name)) {
+            chaz_Util_die("Failed to delete file '%s'", chaz_CC.try_exe_name);
+        }
         compile_succeeded = chaz_CC_compile_exe(CHAZ_CC_TRY_SOURCE_PATH,
                                                 CHAZ_CC_TRY_BASENAME, code);
     }
+
     if (!compile_succeeded) {
         chaz_Util_die("Failed to compile a small test file");
     }
-    retval = chaz_OS_run_local_redirected(chaz_CC.try_exe_name,
-                                          chaz_OS_dev_null());
+    chaz_CC_detect_binary_format(chaz_CC.try_exe_name);
     chaz_Util_remove_and_verify(chaz_CC.try_exe_name);
-    if (retval < 0) {
-        chaz_Util_die("Failed to execute test file: %s", strerror(errno));
-    }
-    if (retval > 0) {
-        chaz_Util_die("Unexpected exit code %d from test file", retval);
-    }
 
     chaz_CC_detect_known_compilers();
 
@@ -121,6 +131,97 @@ chaz_CC_init(const char *compiler_command, const char *compiler_flags) {
     }
     chaz_CC.extra_cflags = chaz_CFlags_new(chaz_CC.cflags_style);
     chaz_CC.temp_cflags  = chaz_CFlags_new(chaz_CC.cflags_style);
+
+    /* File extensions. */
+    if (chaz_CC.binary_format == CHAZ_CC_BINFMT_ELF) {
+        if (chaz_Util_verbosity) {
+            printf("Detected binary format: ELF\n");
+        }
+        strcpy(chaz_CC.exe_ext, "");
+        strcpy(chaz_CC.shared_lib_ext, ".so");
+        strcpy(chaz_CC.static_lib_ext, ".a");
+        strcpy(chaz_CC.obj_ext, ".o");
+    }
+    else if (chaz_CC.binary_format == CHAZ_CC_BINFMT_MACHO) {
+        if (chaz_Util_verbosity) {
+            printf("Detected binary format: Mach-O\n");
+        }
+        strcpy(chaz_CC.exe_ext, "");
+        strcpy(chaz_CC.shared_lib_ext, ".dylib");
+        strcpy(chaz_CC.static_lib_ext, ".a");
+        strcpy(chaz_CC.obj_ext, ".o");
+    }
+    else if (chaz_CC.binary_format == CHAZ_CC_BINFMT_PE) {
+        if (chaz_Util_verbosity) {
+            printf("Detected binary format: Portable Executable\n");
+        }
+        strcpy(chaz_CC.exe_ext, ".exe");
+        strcpy(chaz_CC.shared_lib_ext, ".dll");
+        if (chaz_CC.intval___GNUC__) {
+            strcpy(chaz_CC.static_lib_ext, ".a");
+            strcpy(chaz_CC.import_lib_ext, ".dll.a");
+            strcpy(chaz_CC.obj_ext, ".o");
+        }
+        else {
+            strcpy(chaz_CC.static_lib_ext, ".lib");
+            strcpy(chaz_CC.import_lib_ext, ".lib");
+            strcpy(chaz_CC.obj_ext, ".obj");
+        }
+    }
+    else {
+        chaz_Util_die("Failed to detect binary format");
+    }
+
+    free(chaz_CC.try_exe_name);
+    chaz_CC.try_exe_name
+        = chaz_Util_join("", CHAZ_CC_TRY_BASENAME, chaz_CC.exe_ext, NULL);
+}
+
+static void
+chaz_CC_detect_binary_format(const char *filename) {
+    char *output;
+    size_t output_len;
+    int binary_format = 0;
+
+    output = chaz_Util_slurp_file(filename, &output_len);
+
+    /* ELF. */
+    if (binary_format == 0 && output_len >= 4
+        && memcmp(output, "\x7F" "ELF", 4) == 0
+       ) {
+        binary_format = CHAZ_CC_BINFMT_ELF;
+    }
+
+    /* Macho-O. */
+    if (binary_format == 0 && output_len >= 4
+        && (memcmp(output, "\xCA\xFE\xBA\xBE", 4) == 0      /* Fat binary. */
+            || memcmp(output, "\xFE\xED\xFA\xCE", 4) == 0   /* 32-bit BE. */
+            || memcmp(output, "\xFE\xED\xFA\xCF", 4) == 0   /* 64-bit BE. */
+            || memcmp(output, "\xCE\xFA\xED\xFE", 4) == 0   /* 32-bit LE. */
+            || memcmp(output, "\xCF\xFA\xED\xFE", 4) == 0)  /* 64-bit LE. */
+       ) {
+        binary_format = CHAZ_CC_BINFMT_MACHO;
+    }
+
+    /* Portable Executable. */
+    if (binary_format == 0 && output_len >= 0x40
+        && memcmp(output, "MZ", 2) == 0
+       ) {
+        size_t pe_header_off =
+            (unsigned char)output[0x3C]
+            | ((unsigned char)output[0x3D] << 8)
+            | ((unsigned char)output[0x3E] << 16)
+            | ((unsigned char)output[0x3F] << 24);
+
+        if (output_len >= pe_header_off + 4
+            && memcmp(output + pe_header_off, "PE\0\0", 4) == 0
+           ) {
+            binary_format = CHAZ_CC_BINFMT_PE;
+        }
+    }
+
+    chaz_CC.binary_format = binary_format;
+    free(output);
 }
 
 static const char chaz_CC_detect_macro_code[] =
@@ -185,7 +286,7 @@ chaz_CC_compile_exe(const char *source_path, const char *exe_name,
     const char *extra_cflags_string = "";
     const char *temp_cflags_string  = "";
     const char *local_cflags_string;
-    char *exe_file = chaz_Util_join("", exe_name, chaz_OS_exe_ext(), NULL);
+    char *exe_file = chaz_Util_join("", exe_name, chaz_CC.exe_ext, NULL);
     char *command;
     int result;
 
@@ -369,6 +470,31 @@ chaz_CC_new_cflags(void) {
     return chaz_CFlags_new(chaz_CC.cflags_style);
 }
 
+int
+chaz_CC_binary_format(void) {
+    return chaz_CC.binary_format;
+}
+
+const char*
+chaz_CC_exe_ext(void) {
+    return chaz_CC.exe_ext;
+}
+
+const char*
+chaz_CC_shared_lib_ext(void) {
+    return chaz_CC.shared_lib_ext;
+}
+
+const char*
+chaz_CC_static_lib_ext(void) {
+    return chaz_CC.static_lib_ext;
+}
+
+const char*
+chaz_CC_import_lib_ext(void) {
+    return chaz_CC.import_lib_ext;
+}
+
 const char*
 chaz_CC_obj_ext(void) {
     return chaz_CC.obj_ext;

http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/e3b57156/src/Charmonizer/Core/Compiler.h
----------------------------------------------------------------------
diff --git a/src/Charmonizer/Core/Compiler.h b/src/Charmonizer/Core/Compiler.h
index e916553..f8a8a3a 100644
--- a/src/Charmonizer/Core/Compiler.h
+++ b/src/Charmonizer/Core/Compiler.h
@@ -28,6 +28,10 @@ extern "C" {
 #include "Charmonizer/Core/Defines.h"
 #include "Charmonizer/Core/CFlags.h"
 
+#define CHAZ_CC_BINFMT_ELF      1
+#define CHAZ_CC_BINFMT_MACHO    2
+#define CHAZ_CC_BINFMT_PE       3
+
 /* Attempt to compile and link an executable.  Return true if the executable
  * file exists after the attempt.
  */
@@ -97,6 +101,31 @@ chaz_CC_get_temp_cflags(void);
 chaz_CFlags*
 chaz_CC_new_cflags(void);
 
+/* Return the binary format.
+ */
+int
+chaz_CC_binary_format(void);
+
+/* Return the extension for an executable.
+ */
+const char*
+chaz_CC_exe_ext(void);
+
+/* Return the extension for a shared (dynamic) library.
+ */
+const char*
+chaz_CC_shared_lib_ext(void);
+
+/* Return the extension for a static library.
+ */
+const char*
+chaz_CC_static_lib_ext(void);
+
+/* Return the extension for an import library (Windows).
+ */
+const char*
+chaz_CC_import_lib_ext(void);
+
 /* Return the extension for a compiled object.
  */
 const char*

http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/e3b57156/src/Charmonizer/Core/Library.c
----------------------------------------------------------------------
diff --git a/src/Charmonizer/Core/Library.c b/src/Charmonizer/Core/Library.c
index 3b1225e..b07c7a5 100644
--- a/src/Charmonizer/Core/Library.c
+++ b/src/Charmonizer/Core/Library.c
@@ -97,8 +97,8 @@ chaz_Lib_filename(chaz_Lib *lib) {
         return chaz_Lib_no_version_filename(lib);
     }
     else {
-        const char *ext = chaz_OS_shared_lib_ext();
-        if (strcmp(ext, ".dll") == 0) {
+        const char *ext = chaz_CC_shared_lib_ext();
+        if (chaz_CC_binary_format() == CHAZ_CC_BINFMT_PE) {
             return S_build_filename(lib, lib->major_version, ext);
         }
         else {
@@ -113,7 +113,7 @@ chaz_Lib_major_version_filename(chaz_Lib *lib) {
         return chaz_Lib_no_version_filename(lib);
     }
     else {
-        const char *ext = chaz_OS_shared_lib_ext();
+        const char *ext = chaz_CC_shared_lib_ext();
         return S_build_filename(lib, lib->major_version, ext);
     }
 }
@@ -122,14 +122,15 @@ char*
 chaz_Lib_no_version_filename(chaz_Lib *lib) {
     const char *prefix = S_get_prefix();
     const char *ext = lib->is_shared
-                      ? chaz_OS_shared_lib_ext()
-                      : chaz_OS_static_lib_ext();
+                      ? chaz_CC_shared_lib_ext()
+                      : chaz_CC_static_lib_ext();
     return chaz_Util_join("", prefix, lib->name, ext, NULL);
 }
 
 char*
 chaz_Lib_implib_filename(chaz_Lib *lib) {
-    return S_build_filename(lib, lib->major_version, ".lib");
+    const char *ext = chaz_CC_import_lib_ext();
+    return S_build_filename(lib, lib->major_version, ext);
 }
 
 char*
@@ -139,20 +140,22 @@ chaz_Lib_export_filename(chaz_Lib *lib) {
 
 static char*
 S_build_filename(chaz_Lib *lib, const char *version, const char *ext) {
-    const char *prefix    = S_get_prefix();
-    const char *shlib_ext = chaz_OS_shared_lib_ext();
+    const char *prefix = S_get_prefix();
+    int binary_format = chaz_CC_binary_format();
 
-    /* Use `shlib_ext` as a proxy for OS to determine behavior, but append
-     * the supplied `ext`. */
-    if (strcmp(shlib_ext, ".dll") == 0) {
+    if (binary_format == CHAZ_CC_BINFMT_PE) {
         return chaz_Util_join("", prefix, lib->name, "-", version, ext, NULL);
     }
-    else if (strcmp(shlib_ext, ".dylib") == 0) {
+    else if (binary_format == CHAZ_CC_BINFMT_MACHO) {
         return chaz_Util_join("", prefix, lib->name, ".", version, ext, NULL);
     }
-    else {
+    else if (binary_format == CHAZ_CC_BINFMT_ELF) {
         return chaz_Util_join("", prefix, lib->name, ext, ".", version, NULL);
     }
+    else {
+        chaz_Util_die("Unsupported binary format");
+        return NULL;
+    }
 }
 
 static const char*
@@ -160,9 +163,10 @@ S_get_prefix() {
     if (chaz_CC_msvc_version_num()) {
         return "";
     }
-    else if (chaz_OS_is_cygwin()) {
+    /* TODO: Readd Cygwin detection. */
+    /*else if (chaz_OS_is_cygwin()) {
         return "cyg";
-    }
+    }*/
     else {
         return "lib";
     }

http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/e3b57156/src/Charmonizer/Core/Make.c
----------------------------------------------------------------------
diff --git a/src/Charmonizer/Core/Make.c b/src/Charmonizer/Core/Make.c
index df2a217..d72cccc 100644
--- a/src/Charmonizer/Core/Make.c
+++ b/src/Charmonizer/Core/Make.c
@@ -171,7 +171,7 @@ chaz_Make_audition(const char *make) {
 chaz_MakeFile*
 chaz_MakeFile_new() {
     chaz_MakeFile *makefile = (chaz_MakeFile*)malloc(sizeof(chaz_MakeFile));
-    const char    *exe_ext  = chaz_OS_exe_ext();
+    const char    *exe_ext  = chaz_CC_exe_ext();
     const char    *obj_ext  = chaz_CC_obj_ext();
     char *generated;
 
@@ -333,14 +333,14 @@ chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe,
 chaz_MakeRule*
 chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_Lib *lib,
                              const char *sources, chaz_CFlags *link_flags) {
-    chaz_CFlags   *local_flags  = chaz_CC_new_cflags();
-    const char    *link         = chaz_CC_link_command();
-    const char    *shlib_ext    = chaz_OS_shared_lib_ext();
-    const char    *link_flags_string = "";
-    const char    *local_flags_string;
+    chaz_CFlags *local_flags = chaz_CC_new_cflags();
+    const char *link = chaz_CC_link_command();
+    const char *link_flags_string = "";
+    const char *local_flags_string;
+    int binfmt = chaz_CC_binary_format();
     chaz_MakeRule *rule;
-    char          *filename;
-    char          *command;
+    char *filename;
+    char *command;
 
     filename = chaz_Lib_filename(lib);
     rule = chaz_MakeFile_add_rule(makefile, filename, sources);
@@ -353,7 +353,7 @@ chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_Lib *lib,
         chaz_CFlags_append(local_flags, "/nologo");
     }
     chaz_CFlags_link_shared_library(local_flags);
-    if (strcmp(shlib_ext, ".dylib") == 0) {
+    if (binfmt == CHAZ_CC_BINFMT_MACHO) {
         /* Set temporary install name with full path on Darwin. */
         const char *dir_sep = chaz_OS_dir_sep();
         char *major_v_name = chaz_Lib_major_version_filename(lib);
@@ -375,7 +375,7 @@ chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_Lib *lib,
     chaz_MakeRule_add_rm_command(makefile->clean, filename);
 
     /* Add symlinks. */
-    if (strcmp(shlib_ext, ".dll") != 0) {
+    if (binfmt == CHAZ_CC_BINFMT_ELF || binfmt == CHAZ_CC_BINFMT_MACHO) {
         char *major_v_name = chaz_Lib_major_version_filename(lib);
         char *no_v_name    = chaz_Lib_no_version_filename(lib);
 
@@ -383,7 +383,7 @@ chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_Lib *lib,
         chaz_MakeRule_add_command(rule, command);
         free(command);
 
-        if (strcmp(shlib_ext, ".dylib") == 0) {
+        if (binfmt == CHAZ_CC_BINFMT_MACHO) {
             command = chaz_Util_join(" ", "ln -sf", filename, no_v_name,
                                      NULL);
         }
@@ -419,7 +419,6 @@ chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_Lib *lib,
 chaz_MakeRule*
 chaz_MakeFile_add_static_lib(chaz_MakeFile *makefile, chaz_Lib *lib,
                              const char *objects) {
-    const char    *shlib_ext    = chaz_OS_shared_lib_ext();
     chaz_MakeRule *rule;
     char          *filename;
     char          *command;
@@ -445,7 +444,7 @@ chaz_MakeFile_add_lemon_exe(chaz_MakeFile *makefile, const char *dir) {
     chaz_CFlags   *cflags = chaz_CC_new_cflags();
     chaz_MakeRule *rule;
     const char *dir_sep = chaz_OS_dir_sep();
-    const char *exe_ext = chaz_OS_exe_ext();
+    const char *exe_ext = chaz_CC_exe_ext();
     char *lemon_exe = chaz_Util_join("", dir, dir_sep, "lemon", exe_ext, NULL);
     char *lemon_c   = chaz_Util_join(dir_sep, dir, "lemon.c", NULL);
 
@@ -676,8 +675,9 @@ chaz_MakeRule_add_command_with_libpath(chaz_MakeRule *rule,
     va_list args;
     char *path        = NULL;
     char *lib_command = NULL;
+    int binfmt = chaz_CC_binary_format();
 
-    if (strcmp(chaz_OS_shared_lib_ext(), ".so") == 0) {
+    if (binfmt == CHAZ_CC_BINFMT_ELF) {
         va_start(args, command);
         path = chaz_Util_vjoin(":", args);
         va_end(args);
@@ -687,7 +687,7 @@ chaz_MakeRule_add_command_with_libpath(chaz_MakeRule *rule,
 
         free(path);
     }
-    else if (strcmp(chaz_OS_shared_lib_ext(), ".dll") == 0) {
+    else if (binfmt == CHAZ_CC_BINFMT_PE) {
         va_start(args, command);
         path = chaz_Util_vjoin(";", args);
         va_end(args);

http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/e3b57156/src/Charmonizer/Core/OperatingSystem.c
----------------------------------------------------------------------
diff --git a/src/Charmonizer/Core/OperatingSystem.c b/src/Charmonizer/Core/OperatingSystem.c
index c872b68..cd5bfeb 100644
--- a/src/Charmonizer/Core/OperatingSystem.c
+++ b/src/Charmonizer/Core/OperatingSystem.c
@@ -33,107 +33,52 @@ static struct {
     char name[CHAZ_OS_NAME_MAX+1];
     char dev_null[20];
     char dir_sep[2];
-    char exe_ext[5];
-    char static_lib_ext[5];
-    char shared_lib_ext[7];
     char local_command_start[3];
     int  shell_type;
-} chaz_OS = { "", "", "", "", "", "", "", 0 };
+} chaz_OS = { "", "", "", "", 0 };
 
 void
 chaz_OS_init(void) {
+    char *output;
+    size_t output_len;
+
     if (chaz_Util_verbosity) {
         printf("Initializing Charmonizer/Core/OperatingSystem...\n");
     }
 
-    if (chaz_Util_verbosity) {
-        printf("Trying to find a bit-bucket a la /dev/null...\n");
-    }
+    /* Detect shell based on escape character. */
 
-    /* Detect shell based on whether the bitbucket is "/dev/null" or "nul".
-     * Start with "nul" as some Windows boxes seem to have a "/dev/null".
-     */
-    if (chaz_Util_can_open_file("nul")) {
-        strcpy(chaz_OS.name, "windows");
-        strcpy(chaz_OS.dev_null, "nul");
+    /* Needed to make redirection work. */
+    chaz_OS.shell_type = CHAZ_OS_POSIX;
+
+    output = chaz_OS_run_and_capture("echo foo\\^bar", &output_len);
+
+    if (output_len >= 7 && memcmp(output, "foo\\bar", 7) == 0) {
+        /* Escape character is caret. */
+        if (chaz_Util_verbosity) {
+            printf("Detected cmd.exe shell\n");
+        }
+        chaz_OS.shell_type = CHAZ_OS_CMD_EXE;
         strcpy(chaz_OS.dir_sep, "\\");
-        strcpy(chaz_OS.exe_ext, ".exe");
-        strcpy(chaz_OS.shared_lib_ext, ".dll");
-        strcpy(chaz_OS.static_lib_ext, ".lib");
+        strcpy(chaz_OS.dev_null, "nul");
+        /* Empty string should work, too. */
         strcpy(chaz_OS.local_command_start, ".\\");
-        chaz_OS.shell_type = CHAZ_OS_CMD_EXE;
     }
-    else if (chaz_Util_can_open_file("/dev/null")) {
-        char   *uname;
-        size_t  uname_len;
-        size_t i;
-
-        chaz_OS.shell_type = CHAZ_OS_POSIX;
-
-        /* Detect Unix name. */
-        uname = chaz_OS_run_and_capture("uname", &uname_len);
-        for (i = 0; i < CHAZ_OS_NAME_MAX && i < uname_len; i++) {
-            char c = uname[i];
-            if (!c || isspace((unsigned char)c)) { break; }
-            chaz_OS.name[i] = tolower((unsigned char)c);
+    else if (output_len >= 7 && memcmp(output, "foo^bar", 7) == 0) {
+        /* Escape character is backslash. */
+        if (chaz_Util_verbosity) {
+            printf("Detected POSIX shell\n");
         }
-        if (i > 0) { chaz_OS.name[i] = '\0'; }
-        else       { strcpy(chaz_OS.name, "unknown_unix"); }
-        free(uname);
-
-        strcpy(chaz_OS.dev_null, "/dev/null");
+        chaz_OS.shell_type = CHAZ_OS_POSIX;
         strcpy(chaz_OS.dir_sep, "/");
-        strcpy(chaz_OS.exe_ext, "");
-        strcpy(chaz_OS.static_lib_ext, ".a");
-        if (memcmp(chaz_OS.name, "darwin", 6) == 0) {
-            strcpy(chaz_OS.shared_lib_ext, ".dylib");
-        }
-        else if (memcmp(chaz_OS.name, "cygwin", 6) == 0) {
-            strcpy(chaz_OS.shared_lib_ext, ".dll");
-        }
-        else {
-            strcpy(chaz_OS.shared_lib_ext, ".so");
-        }
+        strcpy(chaz_OS.dev_null, "/dev/null");
         strcpy(chaz_OS.local_command_start, "./");
     }
     else {
-        /* Bail out because we couldn't find anything like /dev/null. */
-        chaz_Util_die("Couldn't find anything like /dev/null");
-    }
-
-    if (chaz_Util_verbosity) {
-        printf("Detected OS: %s\n", chaz_OS.name);
+        chaz_Util_die("Couldn't identify shell");
     }
-}
-
-const char*
-chaz_OS_name(void) {
-    return chaz_OS.name;
-}
-
-int
-chaz_OS_is_darwin(void) {
-    return memcmp(chaz_OS.name, "darwin", 6) == 0;
-}
 
-int
-chaz_OS_is_cygwin(void) {
-    return memcmp(chaz_OS.name, "cygwin", 6) == 0;
-}
-
-const char*
-chaz_OS_exe_ext(void) {
-    return chaz_OS.exe_ext;
-}
-
-const char*
-chaz_OS_shared_lib_ext(void) {
-    return chaz_OS.shared_lib_ext;
-}
-
-const char*
-chaz_OS_static_lib_ext(void) {
-    return chaz_OS.static_lib_ext;
+    free(output);
 }
 
 const char*

http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/e3b57156/src/Charmonizer/Core/OperatingSystem.h
----------------------------------------------------------------------
diff --git a/src/Charmonizer/Core/OperatingSystem.h b/src/Charmonizer/Core/OperatingSystem.h
index 7c01db8..eda3890 100644
--- a/src/Charmonizer/Core/OperatingSystem.h
+++ b/src/Charmonizer/Core/OperatingSystem.h
@@ -68,32 +68,6 @@ chaz_OS_mkdir(const char *filepath);
 void
 chaz_OS_rmdir(const char *filepath);
 
-/* Return the operating system name.
- */
-const char*
-chaz_OS_name(void);
-
-int
-chaz_OS_is_darwin(void);
-
-int
-chaz_OS_is_cygwin(void);
-
-/* Return the extension for an executable on this system.
- */
-const char*
-chaz_OS_exe_ext(void);
-
-/* Return the extension for a shared object on this system.
- */
-const char*
-chaz_OS_shared_lib_ext(void);
-
-/* Return the extension for a static library on this system.
- */
-const char*
-chaz_OS_static_lib_ext(void);
-
 /* Return the equivalent of /dev/null on this system.
  */
 const char*


[3/7] lucy-charmonizer git commit: Readd Cygwin detection

Posted by nw...@apache.org.
Readd Cygwin detection

Also add a new public function chaz_CC_has_macro.


Project: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/commit/41d94077
Tree: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/tree/41d94077
Diff: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/diff/41d94077

Branch: refs/heads/master
Commit: 41d940779ee7b022251fc422cff7132b80ef54f7
Parents: 76e4dbe
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Tue May 31 13:14:19 2016 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu Jun 2 00:04:17 2016 +0200

----------------------------------------------------------------------
 src/Charmonizer/Core/Compiler.c | 50 ++++++++++++++++++++++++++++--------
 src/Charmonizer/Core/Compiler.h |  8 ++++++
 src/Charmonizer/Core/Library.c  | 15 +++++------
 3 files changed, 54 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/41d94077/src/Charmonizer/Core/Compiler.c
----------------------------------------------------------------------
diff --git a/src/Charmonizer/Core/Compiler.c b/src/Charmonizer/Core/Compiler.c
index 1136d68..dd4fa6c 100644
--- a/src/Charmonizer/Core/Compiler.c
+++ b/src/Charmonizer/Core/Compiler.c
@@ -27,6 +27,11 @@
 static void
 chaz_CC_detect_binary_format(const char *filename);
 
+/** Return the numeric value of a macro or 0 if it isn't defined.
+ */
+static int
+chaz_CC_eval_macro(const char *macro);
+
 /* Detect macros which may help to identify some compilers.
  */
 static void
@@ -56,12 +61,13 @@ static struct {
     int       intval__MSC_VER;
     int       intval___clang__;
     int       intval___SUNPRO_C;
+    int       is_cygwin;
     chaz_CFlags *extra_cflags;
     chaz_CFlags *temp_cflags;
 } chaz_CC = {
     NULL, NULL, NULL,
     "", "", "", "", "", "",
-    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0,
     NULL, NULL
 };
 
@@ -167,6 +173,10 @@ chaz_CC_init(const char *compiler_command, const char *compiler_flags) {
             strcpy(chaz_CC.import_lib_ext, ".lib");
             strcpy(chaz_CC.obj_ext, ".obj");
         }
+
+        if (chaz_CC_has_macro("__CYGWIN__")) {
+            chaz_CC.is_cygwin = 1;
+        }
     }
     else {
         chaz_Util_die("Failed to detect binary format");
@@ -224,7 +234,7 @@ chaz_CC_detect_binary_format(const char *filename) {
     free(output);
 }
 
-static const char chaz_CC_detect_macro_code[] =
+static const char chaz_CC_eval_macro_code[] =
     CHAZ_QUOTE(  #include <stdio.h>             )
     CHAZ_QUOTE(  int main() {                   )
     CHAZ_QUOTE(  #ifndef %s                     )
@@ -235,15 +245,15 @@ static const char chaz_CC_detect_macro_code[] =
     CHAZ_QUOTE(  }                              );
 
 static int
-chaz_CC_detect_macro(const char *macro) {
-    size_t size = sizeof(chaz_CC_detect_macro_code)
+chaz_CC_eval_macro(const char *macro) {
+    size_t size = sizeof(chaz_CC_eval_macro_code)
                   + (strlen(macro) * 2)
                   + 20;
     char *code = (char*)malloc(size);
     int retval = 0;
     char *output;
     size_t len;
-    sprintf(code, chaz_CC_detect_macro_code, macro, macro);
+    sprintf(code, chaz_CC_eval_macro_code, macro, macro);
     output = chaz_CC_capture_output(code, &len);
     if (output) {
         retval = atoi(output);
@@ -253,21 +263,34 @@ chaz_CC_detect_macro(const char *macro) {
     return retval;
 }
 
+int
+chaz_CC_has_macro(const char *macro) {
+    size_t size = sizeof(chaz_CC_eval_macro_code)
+                  + (strlen(macro) * 2)
+                  + 20;
+    char *code = (char*)malloc(size);
+    int retval = 0;
+    sprintf(code, chaz_CC_eval_macro_code, macro, macro);
+    retval = chaz_CC_test_compile(code);
+    free(code);
+    return retval;
+}
+
 static void
 chaz_CC_detect_known_compilers(void) {
-    chaz_CC.intval___GNUC__  = chaz_CC_detect_macro("__GNUC__");
+    chaz_CC.intval___GNUC__  = chaz_CC_eval_macro("__GNUC__");
     if (chaz_CC.intval___GNUC__) {
         chaz_CC.intval___GNUC_MINOR__
-            = chaz_CC_detect_macro("__GNUC_MINOR__");
+            = chaz_CC_eval_macro("__GNUC_MINOR__");
         chaz_CC.intval___GNUC_PATCHLEVEL__
-            = chaz_CC_detect_macro("__GNUC_PATCHLEVEL__");
+            = chaz_CC_eval_macro("__GNUC_PATCHLEVEL__");
         sprintf(chaz_CC.gcc_version_str, "%d.%d.%d", chaz_CC.intval___GNUC__,
                 chaz_CC.intval___GNUC_MINOR__,
                 chaz_CC.intval___GNUC_PATCHLEVEL__);
     }
-    chaz_CC.intval__MSC_VER   = chaz_CC_detect_macro("_MSC_VER");
-    chaz_CC.intval___clang__  = chaz_CC_detect_macro("__clang__");
-    chaz_CC.intval___SUNPRO_C = chaz_CC_detect_macro("__SUNPRO_C");
+    chaz_CC.intval__MSC_VER   = chaz_CC_eval_macro("_MSC_VER");
+    chaz_CC.intval___clang__  = chaz_CC_eval_macro("__clang__");
+    chaz_CC.intval___SUNPRO_C = chaz_CC_eval_macro("__SUNPRO_C");
 }
 
 void
@@ -522,6 +545,11 @@ chaz_CC_sun_c_version_num(void) {
     return chaz_CC.intval___SUNPRO_C;
 }
 
+int
+chaz_CC_is_cygwin(void) {
+    return chaz_CC.is_cygwin;
+}
+
 const char*
 chaz_CC_link_command() {
     if (chaz_CC.intval__MSC_VER) {

http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/41d94077/src/Charmonizer/Core/Compiler.h
----------------------------------------------------------------------
diff --git a/src/Charmonizer/Core/Compiler.h b/src/Charmonizer/Core/Compiler.h
index f8a8a3a..6361af7 100644
--- a/src/Charmonizer/Core/Compiler.h
+++ b/src/Charmonizer/Core/Compiler.h
@@ -66,6 +66,11 @@ chaz_CC_test_link(const char *source);
 char*
 chaz_CC_capture_output(const char *source, size_t *output_len);
 
+/** Return true if macro is defined.
+ */
+int
+chaz_CC_has_macro(const char *macro);
+
 /** Initialize the compiler environment.
  */
 void
@@ -143,6 +148,9 @@ chaz_CC_msvc_version_num(void);
 int
 chaz_CC_sun_c_version_num(void);
 
+int
+chaz_CC_is_cygwin(void);
+
 const char*
 chaz_CC_link_command(void);
 

http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/41d94077/src/Charmonizer/Core/Library.c
----------------------------------------------------------------------
diff --git a/src/Charmonizer/Core/Library.c b/src/Charmonizer/Core/Library.c
index b07c7a5..d1e0cb6 100644
--- a/src/Charmonizer/Core/Library.c
+++ b/src/Charmonizer/Core/Library.c
@@ -33,7 +33,7 @@ static char*
 S_build_filename(chaz_Lib *lib, const char *version, const char *ext);
 
 static const char*
-S_get_prefix(void);
+S_get_prefix(chaz_Lib *lib);
 
 chaz_Lib*
 chaz_Lib_new_shared(const char *name, const char *version,
@@ -120,7 +120,7 @@ chaz_Lib_major_version_filename(chaz_Lib *lib) {
 
 char*
 chaz_Lib_no_version_filename(chaz_Lib *lib) {
-    const char *prefix = S_get_prefix();
+    const char *prefix = S_get_prefix(lib);
     const char *ext = lib->is_shared
                       ? chaz_CC_shared_lib_ext()
                       : chaz_CC_static_lib_ext();
@@ -140,7 +140,7 @@ chaz_Lib_export_filename(chaz_Lib *lib) {
 
 static char*
 S_build_filename(chaz_Lib *lib, const char *version, const char *ext) {
-    const char *prefix = S_get_prefix();
+    const char *prefix = S_get_prefix(lib);
     int binary_format = chaz_CC_binary_format();
 
     if (binary_format == CHAZ_CC_BINFMT_PE) {
@@ -159,14 +159,13 @@ S_build_filename(chaz_Lib *lib, const char *version, const char *ext) {
 }
 
 static const char*
-S_get_prefix() {
+S_get_prefix(chaz_Lib *lib) {
     if (chaz_CC_msvc_version_num()) {
         return "";
     }
-    /* TODO: Readd Cygwin detection. */
-    /*else if (chaz_OS_is_cygwin()) {
-        return "cyg";
-    }*/
+    else if (chaz_CC_is_cygwin()) {
+        return lib->is_static ? "lib" : "cyg";
+    }
     else {
         return "lib";
     }


[2/7] lucy-charmonizer git commit: Fix add_command_with_libpath on Cygwin

Posted by nw...@apache.org.
Fix add_command_with_libpath on Cygwin

Fixes LUCY-303.


Project: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/commit/76e4dbe3
Tree: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/tree/76e4dbe3
Diff: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/diff/76e4dbe3

Branch: refs/heads/master
Commit: 76e4dbe39532675b31f7756cb3f84f8fea3807e4
Parents: e3b5715
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Tue May 31 12:40:51 2016 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu Jun 2 00:03:56 2016 +0200

----------------------------------------------------------------------
 src/Charmonizer/Core/Make.c | 28 ++++++++++++++++++++--------
 1 file changed, 20 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/76e4dbe3/src/Charmonizer/Core/Make.c
----------------------------------------------------------------------
diff --git a/src/Charmonizer/Core/Make.c b/src/Charmonizer/Core/Make.c
index d72cccc..1c1d728 100644
--- a/src/Charmonizer/Core/Make.c
+++ b/src/Charmonizer/Core/Make.c
@@ -688,15 +688,27 @@ chaz_MakeRule_add_command_with_libpath(chaz_MakeRule *rule,
         free(path);
     }
     else if (binfmt == CHAZ_CC_BINFMT_PE) {
-        va_start(args, command);
-        path = chaz_Util_vjoin(";", args);
-        va_end(args);
+        if (chaz_Make.shell_type == CHAZ_OS_CMD_EXE) {
+            va_start(args, command);
+            path = chaz_Util_vjoin(";", args);
+            va_end(args);
+
+            /* It's important to not add a space before `&&`. Otherwise, the
+             * space is added to the search path.
+             */
+            lib_command = chaz_Util_join("", "path ", path, ";%path%&& ",
+                                         command, NULL);
+        }
+        else {
+            va_start(args, command);
+            path = chaz_Util_vjoin(":", args);
+            va_end(args);
 
-        /* It's important to not add a space before `&&`. Otherwise, the
-	 * space is added to the search path.
-	 */
-        lib_command = chaz_Util_join("", "path ", path, ";%path%&& ", command,
-                                     NULL);
+            lib_command = chaz_Util_join("", "PATH=", path, ":$$PATH ",
+                                         command, NULL);
+        }
+
+        free(path);
     }
     else {
         /* Assume that library paths are compiled into the executable on


[7/7] lucy-charmonizer git commit: Merge branch 'binfmt-and-shell-detection'

Posted by nw...@apache.org.
Merge branch 'binfmt-and-shell-detection'


Project: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/commit/77d32d09
Tree: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/tree/77d32d09
Diff: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/diff/77d32d09

Branch: refs/heads/master
Commit: 77d32d09a177d14eef6e7f772cf53f1a92dd445c
Parents: bd9f6b5 f324690
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sat Jun 4 17:30:11 2016 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sat Jun 4 17:30:11 2016 +0200

----------------------------------------------------------------------
 src/Charmonizer/Core/CFlags.c          |  22 ++-
 src/Charmonizer/Core/Compiler.c        | 216 +++++++++++++++++++++++----
 src/Charmonizer/Core/Compiler.h        |  37 +++++
 src/Charmonizer/Core/Library.c         |  39 ++---
 src/Charmonizer/Core/Make.c            |  75 ++++++----
 src/Charmonizer/Core/OperatingSystem.c | 217 ++++++++++++++++++----------
 src/Charmonizer/Core/OperatingSystem.h |  26 ----
 src/Charmonizer/Probe/DirManip.c       |  10 +-
 8 files changed, 435 insertions(+), 207 deletions(-)
----------------------------------------------------------------------



[4/7] lucy-charmonizer git commit: Support POSIX shells under MinGW

Posted by nw...@apache.org.
Support POSIX shells under MinGW

Fixes CLOWNFISH-100.


Project: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/commit/c5387af3
Tree: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/tree/c5387af3
Diff: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/diff/c5387af3

Branch: refs/heads/master
Commit: c5387af383d317dcd887f9e07769c589039e099c
Parents: 7f2cb31
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Wed Jun 1 20:57:27 2016 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu Jun 2 00:04:18 2016 +0200

----------------------------------------------------------------------
 src/Charmonizer/Core/OperatingSystem.c | 126 ++++++++++++++++++++++++++--
 1 file changed, 119 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/c5387af3/src/Charmonizer/Core/OperatingSystem.c
----------------------------------------------------------------------
diff --git a/src/Charmonizer/Core/OperatingSystem.c b/src/Charmonizer/Core/OperatingSystem.c
index cd5bfeb..47a66af 100644
--- a/src/Charmonizer/Core/OperatingSystem.c
+++ b/src/Charmonizer/Core/OperatingSystem.c
@@ -35,7 +35,11 @@ static struct {
     char dir_sep[2];
     char local_command_start[3];
     int  shell_type;
-} chaz_OS = { "", "", "", "", 0 };
+    int  run_sh_via_cmd_exe;
+} chaz_OS = { "", "", "", "", 0, 0 };
+
+static int
+chaz_OS_run_sh_via_cmd_exe(const char *command);
 
 void
 chaz_OS_init(void) {
@@ -58,11 +62,27 @@ chaz_OS_init(void) {
         if (chaz_Util_verbosity) {
             printf("Detected cmd.exe shell\n");
         }
-        chaz_OS.shell_type = CHAZ_OS_CMD_EXE;
-        strcpy(chaz_OS.dir_sep, "\\");
-        strcpy(chaz_OS.dev_null, "nul");
-        /* Empty string should work, too. */
-        strcpy(chaz_OS.local_command_start, ".\\");
+
+        /* Try to see whether running commands via the `sh` command works.
+         * Run the `find` command to check whether we're in a somewhat POSIX
+         * compatible environment. */
+        free(output);
+        chaz_OS.run_sh_via_cmd_exe = 1;
+        output = chaz_OS_run_and_capture("find . -prune", &output_len);
+
+        if (output_len >= 2
+            && output[0] == '.'
+            && isspace((unsigned char)output[1])
+           ) {
+            if (chaz_Util_verbosity) {
+                printf("Detected POSIX shell via cmd.exe\n");
+            }
+            chaz_OS.shell_type = CHAZ_OS_POSIX;
+        }
+        else {
+            chaz_OS.shell_type = CHAZ_OS_CMD_EXE;
+            chaz_OS.run_sh_via_cmd_exe = 0;
+        }
     }
     else if (output_len >= 7 && memcmp(output, "foo^bar", 7) == 0) {
         /* Escape character is backslash. */
@@ -70,6 +90,15 @@ chaz_OS_init(void) {
             printf("Detected POSIX shell\n");
         }
         chaz_OS.shell_type = CHAZ_OS_POSIX;
+    }
+
+    if (chaz_OS.shell_type == CHAZ_OS_CMD_EXE) {
+        strcpy(chaz_OS.dir_sep, "\\");
+        strcpy(chaz_OS.dev_null, "nul");
+        /* Empty string should work, too. */
+        strcpy(chaz_OS.local_command_start, ".\\");
+    }
+    else if (chaz_OS.shell_type == CHAZ_OS_POSIX) {
         strcpy(chaz_OS.dir_sep, "/");
         strcpy(chaz_OS.dev_null, "/dev/null");
         strcpy(chaz_OS.local_command_start, "./");
@@ -177,11 +206,94 @@ chaz_OS_run_redirected(const char *command, const char *path) {
     else {
         chaz_Util_die("Don't know the shell type");
     }
-    retval = system(quiet_command);
+    if (chaz_OS.run_sh_via_cmd_exe) {
+        retval = chaz_OS_run_sh_via_cmd_exe(quiet_command);
+    }
+    else {
+        retval = system(quiet_command);
+    }
     free(quiet_command);
     return retval;
 }
 
+static int
+chaz_OS_run_sh_via_cmd_exe(const char *command) {
+    size_t i;
+    size_t size;
+    char *sh_command;
+    char *p;
+    int retval;
+
+    /* Compute size. */
+
+    size = sizeof("sh -c \"\"");
+
+    for (i = 0; command[i] != '\0'; i++) {
+        char c = command[i];
+
+        switch (c) {
+            case '"':
+            case '\\':
+                size += 2;
+                break;
+
+            case '%':
+            case '!':
+                size += 3;
+                break;
+
+            default:
+                size += 1;
+                break;
+        }
+    }
+
+    /* Build sh command. */
+
+    sh_command = (char*)malloc(size);
+    p = sh_command;
+    memcpy(p, "sh -c \"", 7);
+    p += 7;
+
+    /* Escape special characters. */
+
+    for (i = 0; command[i] != '\0'; i++) {
+        char c = command[i];
+
+        switch (c) {
+            case '"':
+            case '\\':
+                /* Escape double quote and backslash. */
+                *p++ = '\\';
+                *p++ = c;
+                break;
+
+            case '%':
+            case '!':
+                /* Break out of double quotes for percent sign and
+                 * exclamation mark. This prevents variable expansion. */
+                *p++ = '"';
+                *p++ = c;
+                *p++ = '"';
+                break;
+
+            default:
+                *p++ = c;
+                break;
+        }
+    }
+
+    /* Finish and run sh command. */
+
+    *p++ = '"';
+    *p++ = '\0';
+
+    retval = system(sh_command);
+
+    free(sh_command);
+    return retval;
+}
+
 char*
 chaz_OS_run_and_capture(const char *command, size_t *output_len) {
     char *output;


[5/7] lucy-charmonizer git commit: Rework detection of directory separator

Posted by nw...@apache.org.
Rework detection of directory separator

Use _WIN32 and __CYGWIN__ macros to detect Windows directory separators.


Project: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/commit/7f2cb31d
Tree: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/tree/7f2cb31d
Diff: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/diff/7f2cb31d

Branch: refs/heads/master
Commit: 7f2cb31d06aeaf46499785aabfa3eb4bcf9d1b7b
Parents: 41d9407
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Wed Jun 1 21:35:25 2016 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu Jun 2 00:04:18 2016 +0200

----------------------------------------------------------------------
 src/Charmonizer/Probe/DirManip.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/7f2cb31d/src/Charmonizer/Probe/DirManip.c
----------------------------------------------------------------------
diff --git a/src/Charmonizer/Probe/DirManip.c b/src/Charmonizer/Probe/DirManip.c
index c737f22..50e7cdc 100644
--- a/src/Charmonizer/Probe/DirManip.c
+++ b/src/Charmonizer/Probe/DirManip.c
@@ -119,7 +119,6 @@ chaz_DirManip_try_rmdir(void) {
 
 void
 chaz_DirManip_run(void) {
-    const char *dir_sep = chaz_OS_dir_sep();
     int has_dirent_h = chaz_HeadCheck_check_header("dirent.h");
     int has_direct_h = chaz_HeadCheck_check_header("direct.h");
     int has_dirent_d_namlen = false;
@@ -176,16 +175,13 @@ chaz_DirManip_run(void) {
         chaz_ConfWriter_add_def("MAKEDIR_MODE_IGNORED", "1");
     }
 
-    if (strcmp(dir_sep, "\\") == 0) {
+    if (chaz_CC_has_macro("_WIN32") && !chaz_CC_is_cygwin()) {
         chaz_ConfWriter_add_def("DIR_SEP", "\"\\\\\"");
         chaz_ConfWriter_add_def("DIR_SEP_CHAR", "'\\\\'");
     }
     else {
-        char scratch[5];
-        sprintf(scratch, "\"%s\"", dir_sep);
-        chaz_ConfWriter_add_def("DIR_SEP", scratch);
-        sprintf(scratch, "'%s'", dir_sep);
-        chaz_ConfWriter_add_def("DIR_SEP_CHAR", scratch);
+        chaz_ConfWriter_add_def("DIR_SEP", "\"/\"");
+        chaz_ConfWriter_add_def("DIR_SEP_CHAR", "'/'");
     }
 
     /* See whether remove works on directories. */


[6/7] lucy-charmonizer git commit: Check whether the make command matches the OS shell

Posted by nw...@apache.org.
Check whether the make command matches the OS shell


Project: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/commit/f324690a
Tree: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/tree/f324690a
Diff: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/diff/f324690a

Branch: refs/heads/master
Commit: f324690a7d9a810e3c1bd93aec7ae982de2b227f
Parents: c5387af
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Wed Jun 1 21:50:25 2016 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu Jun 2 00:04:27 2016 +0200

----------------------------------------------------------------------
 src/Charmonizer/Core/Make.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/f324690a/src/Charmonizer/Core/Make.c
----------------------------------------------------------------------
diff --git a/src/Charmonizer/Core/Make.c b/src/Charmonizer/Core/Make.c
index 1c1d728..8e8699b 100644
--- a/src/Charmonizer/Core/Make.c
+++ b/src/Charmonizer/Core/Make.c
@@ -80,6 +80,8 @@ S_write_rule(chaz_MakeRule *rule, FILE *out);
 
 void
 chaz_Make_init(const char *make_command) {
+    chaz_Make.shell_type = chaz_OS_shell_type();
+
     if (make_command) {
         if (!chaz_Make_detect(make_command, NULL)) {
             chaz_Util_warn("Make utility '%s' doesn't appear to work");
@@ -95,11 +97,6 @@ chaz_Make_init(const char *make_command) {
             printf("Detected make utility '%s'\n", chaz_Make.make_command);
         }
     }
-
-    if (chaz_Make.shell_type == 0) {
-        // Assume POSIX.
-        chaz_Make.shell_type = CHAZ_OS_POSIX;
-    }
 }
 
 void
@@ -149,12 +146,14 @@ chaz_Make_audition(const char *make) {
         size_t len;
         char *content = chaz_Util_slurp_file("_charm_foo", &len);
         if (NULL != strstr(content, "foo\\bar")) {
-            chaz_Make.shell_type = CHAZ_OS_CMD_EXE;
-            succeeded = 1;
+            if (chaz_Make.shell_type == CHAZ_OS_CMD_EXE) {
+                succeeded = 1;
+            }
         }
         else if (NULL != strstr(content, "foo^bar")) {
-            chaz_Make.shell_type = CHAZ_OS_POSIX;
-            succeeded = 1;
+            if (chaz_Make.shell_type == CHAZ_OS_POSIX) {
+                succeeded = 1;
+            }
         }
         free(content);
     }