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 <[email protected]> Authored: Sat May 21 18:59:20 2016 +0200 Committer: Nick Wellnhofer <[email protected]> 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*
