Mercurial > parpg-core
diff bin/parpg.c.in @ 6:dd4ed4945411
Ported binary launcher to Windows.
* Reorganized the parpg executable source so that it now compiles with the MSVC compiler (tested with MSVC Express 2010).
* Cleaned up the launcher source by adding a bunch of const statements and removing the superfluous NULL_TERMINATE macro.
* Fixed a few memory leaks in the launcher source by freeing malloced/calloced pointers;
* Added a new SubstfileEscape builder to the SConstruct script used to escape certain sequences when substituting a template file. This is used to escape backslashes ("\") in c strings in the bin/parpg.c.in template for Windows paths.
* Fixed the PY_LIB_DIR_DEFAULT for Windows so that it now correctly points to the default Python installation path.
* Modified the SConstruct script to support compiling the launcher executable with debugging symbols in Windows with the DEBUG flag.
author | M. George Hansen |
---|---|
date | Sun, 22 May 2011 00:53:59 -0700 |
parents | 33684971cdb1 |
children |
line wrap: on
line diff
--- a/bin/parpg.c.in Tue May 17 14:18:25 2011 -0700 +++ b/bin/parpg.c.in Sun May 22 00:53:59 2011 -0700 @@ -1,37 +1,36 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#ifdef _MSC_VER +#ifdef _WIN32 # include <process.h> #else # include <sys/types.h> # include <sys/wait.h> #endif -#define CONCAT_ARRAYS(TYPE, ARRAY_A, SIZE_A, ARRAY_B, SIZE_B) \ - (TYPE*)concatArrays((const void**)(ARRAY_A), (SIZE_A), \ - (const void**)(ARRAY_B), (SIZE_B), sizeof(TYPE)) - -#define NULL_TERMINATE(TYPE, ARRAY, SIZE) \ - (TYPE*)realloc(ARRAY, sizeof(TYPE) * (SIZE + 1)) - #define ARRAY_LEN(ARRAY) (sizeof(ARRAY) / sizeof *(ARRAY)) +#define CONCAT_ARRAYS(TYPE, ARRAY_A, ARRAY_B) \ + (TYPE*)concatArrays((const void** const)(ARRAY_A), \ + ARRAY_LEN(ARRAY_A) * sizeof(TYPE), (const void** const)(ARRAY_B), \ + ARRAY_LEN(ARRAY_B) * sizeof(TYPE), sizeof(TYPE)) + void* -concatArrays(const void* arrayA, size_t sizeA, - const void* arrayB, size_t sizeB, size_t sizeType) { - char* concatenatedArray = malloc(sizeType * (sizeA + sizeB)); +concatArrays(const void* const arrayA, const size_t sizeA, + const void* const arrayB, const size_t sizeB, const size_t sizeType) { + char* const concatenatedArray = malloc(sizeType * (sizeA + sizeB)); memcpy(concatenatedArray, arrayA, sizeA * sizeType); memcpy(concatenatedArray + sizeA * sizeType, arrayB, sizeB * sizeType); return concatenatedArray; } char* -joinStr(char* strA, char* strB, char* separator) { - int lenA = strlen(strA); - int lenB = strlen(strB); - int lenSeparator = strlen(separator); - char* concatenatedStr = malloc(lenA + lenB + lenSeparator + 1); +joinStr(const char* const strA, const char* const strB, + const char* const separator) { + const int lenA = strlen(strA); + const int lenB = strlen(strB); + const int lenSeparator = strlen(separator); + char* const concatenatedStr = malloc(lenA + lenB + lenSeparator + 1); memcpy(concatenatedStr, strA, lenA); memcpy(concatenatedStr + lenA, separator, lenSeparator); memcpy(concatenatedStr + lenA + lenSeparator, strB, lenB + 1); @@ -39,38 +38,69 @@ } int -spawnParpgProcess(char* pythonExecutable, char* configDir, int argc, - char* argv[]) { - char* baseArgs[] = {pythonExecutable, "-m", "parpg.main", configDir}; - int nBaseArgs = ARRAY_LEN(baseArgs); - int nAdditionalArgs = argc - 1; - char* additionalArgs[nAdditionalArgs]; +spawnParpgProcess(char* const pythonExecutable, char* const configDir, + const int argc, char* const argv[]) { + const int sizeCharPtr = sizeof(char*); + const int nBaseArgs = 4; + char** const baseArgs = malloc(nBaseArgs * sizeCharPtr); + const int nAdditionalArgs = argc - 1; + char** const additionalArgs = + (char**)malloc(nAdditionalArgs * sizeCharPtr); + const int nArgs = nBaseArgs + nAdditionalArgs; + char* const oldPythonPath = getenv("PYTHONPATH"); + char* newPythonPath; + // Use calloc so that the last element is NULL. + char** const env = calloc(2, sizeCharPtr); + int exitStatus; + // Use calloc so that the last element is NULL. + char** const args = (char**)calloc(nArgs + 1, sizeCharPtr); int i; - for (i = 1; i < argc; i++) { - additionalArgs[i - 1] = argv[i]; + + baseArgs[0] = pythonExecutable; + baseArgs[1] = "-m"; + baseArgs[2] = "parpg.main"; + baseArgs[3] = configDir; + if (nAdditionalArgs > 0) { + for (i = 1; i < argc; i++) { + additionalArgs[i - 1] = argv[i]; + } + memcpy(args, CONCAT_ARRAYS(char*, baseArgs, additionalArgs), + nArgs * sizeCharPtr); + } else { + // Use memcpy so that the last NULL element in args is preserved. + memcpy(args, baseArgs, nArgs * sizeCharPtr); } - int nArgs = nBaseArgs + nAdditionalArgs; - char** args = NULL_TERMINATE(char*, CONCAT_ARRAYS(char*, baseArgs, - nBaseArgs, additionalArgs, nAdditionalArgs), nArgs); - char* oldPythonPath = getenv("PYTHONPATH"); - char* newPythonPath = joinStr(oldPythonPath, "@PY_PACKAGES_DIR@", ":"); - int exitStatus; - char* env[2] = {joinStr("PYTHONPATH=", newPythonPath, ""), (char*)(0)}; -#ifdef _MSC_VER + if (oldPythonPath != 0) { + newPythonPath = joinStr(oldPythonPath, "@PY_PACKAGES_DIR@", ":"); + } else { + newPythonPath = "@PY_PACKAGES_DIR@"; + } + env[0] = joinStr("PYTHONPATH=", newPythonPath, ""); +#ifdef _WIN32 +# ifdef _MSC_VER // MSVC deprecated POSIX spawn functions. + exitStatus = _spawnve(_P_WAIT, pythonExecutable, args, env); +# else exitStatus = spawnve(P_WAIT, pythonExecutable, args, env); +# endif #else exitStatus = execve(pythonExecutable, args, env); #endif + free(baseArgs); + free(additionalArgs); + free(env); + free(args); return exitStatus; } int main(int argc, char* argv[]) { - int exitStatus = spawnParpgProcess("@PYTHON@", "@SYS_CONF_DIR@", argc, - argv); - if (exitStatus) { - perror("parpg exited with error"); + const int exitStatus = spawnParpgProcess("@PYTHON@", "@SYS_CONF_DIR@", + argc, argv); + if (exitStatus < 0) { + perror("failed to execute subprocess"); + exit(EXIT_FAILURE); + } else { + exit(EXIT_SUCCESS); } - return exitStatus; }