diff options
author | dos-reis <gdr@axiomatics.org> | 2008-02-10 04:48:39 +0000 |
---|---|---|
committer | dos-reis <gdr@axiomatics.org> | 2008-02-10 04:48:39 +0000 |
commit | 6b365f926f1f0430c34498392e1dddbff126bc48 (patch) | |
tree | bdbc548cea2b0968863d9695bbdfc1732b16c3c5 /src/driver | |
parent | 06e82157a75ebb6f14dae6a76a9e3a2b883b2c7a (diff) | |
download | open-axiom-6b365f926f1f0430c34498392e1dddbff126bc48.tar.gz |
Add support for batch processing.
Diffstat (limited to 'src/driver')
-rw-r--r-- | src/driver/Makefile.in | 15 | ||||
-rw-r--r-- | src/driver/main.c | 163 | ||||
-rw-r--r-- | src/driver/utils.c | 281 | ||||
-rw-r--r-- | src/driver/utils.h | 79 |
4 files changed, 391 insertions, 147 deletions
diff --git a/src/driver/Makefile.in b/src/driver/Makefile.in index 0a1ba801..f64cfab0 100644 --- a/src/driver/Makefile.in +++ b/src/driver/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2007, Gabriel Dos Reis. +# Copyright (C) 2007-2008, Gabriel Dos Reis. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -30,11 +30,11 @@ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -bin_PROGRAMS = axiom$(EXEEXT) +bin_PROGRAMS = open-axiom$(EXEEXT) -axiom_SOURCES = main.c +open_axiom_SOURCES = main.c utils.c -axiom_objects = $(axiom_SOURCES:.c=.lo) +open_axiom_objects = $(open_axiom_SOURCES:.c=.lo) .PHONY: all all-ax all-driver @@ -55,8 +55,11 @@ stamp: $(bin_PROGRAMS) -DOPENAXIOM_ROOT_DIRECTORY="\"$(open_axiom_installdir)\"" \ $(axiom_includes) $< -axiom$(EXEEXT): $(axiom_objects) - $(LINK) -o $@ $< +utils.lo: utils.h +main.lo: utils.h + +open-axiom$(EXEEXT): $(open_axiom_objects) + $(LINK) -o $@ $(open_axiom_objects) mostlyclean-local: @rm -f $(axiom_objects) diff --git a/src/driver/main.c b/src/driver/main.c index 313f9115..82e51384 100644 --- a/src/driver/main.c +++ b/src/driver/main.c @@ -37,57 +37,11 @@ as the seesion manager. */ -#include "axiom-c-macros.h" +#include "utils.h" #include <stdlib.h> #include <string.h> #include <errno.h> #include <stdio.h> -#if HAVE_UNISTD_H -# include <unistd.h> -#endif -#ifdef __WIN32__ -# include <windows.h> -#endif - -/* The basename of the file holding the OpenAxiom core executable. */ -#define OPENAXIOM_CORE_EXECUTABLE \ - "AXIOMsys" OPENAXIOM_EXEEXT - -/* The basename of the file holding the session manager executable. */ -#define OPENAXIOM_SMAN_EXECUTABLE \ - "sman" OPENAXIOM_EXEEXT - -/* Path to the OpenAxiom executable core, relative to - OPENAXIOM_ROOT_DIRECTORY, or to the system root directory as specified - on command line. */ -#define OPENAXIOM_CORE_PATH \ - "/bin/" OPENAXIOM_CORE_EXECUTABLE - -/* Path to the session manager, relative to OPENAXIOM_ROOT_DIRECTORY, - or to the system root directory as specified on command line. */ -#define OPENAXIOM_SMAN_PATH \ - "/bin/" OPENAXIOM_SMAN_EXECUTABLE - -/* Return a path to the running system, either as specified on command - line through --system=, or as specified at configuration time. */ -static const char* -get_systemdir(int argc, char* argv[]) -{ - int i; - - /* Root directory specified on command line takes precedence - over location specified at configuration time. */ - for (i = 1; i < argc; ++i) - if (strcmp("--", argv[i]) == 0) - break; - else if (strncmp("--system=", argv[i], sizeof("--system=") - 1) == 0) { - return argv[i] + sizeof ("--system=") - 1; - } - - /* Command line did not change the system location to use. - Return what was computed at configuration time. */ - return OPENAXIOM_ROOT_DIRECTORY; -} #define OPENAXIOM_GLOBAL_ENV "AXIOM" @@ -114,106 +68,33 @@ publish_systemdir(const char* dir) } -/* Return a path for PROG specified as a relative path to PREFIX. */ -static const char* -make_path_for(const char* prefix, const char* prog) -{ - const int prefix_length = strlen(prefix); - char* execpath = (char*) malloc(prefix_length + strlen(prog) + 1); - strcpy(execpath, prefix); - strcpy(execpath + prefix_length, prog); - return execpath; -} - - int main(int argc, char* argv[]) { - const char* root_dir = get_systemdir(argc, argv); - const char* execpath = - make_path_for(root_dir, - OPENAXIOM_USE_SMAN ? - OPENAXIOM_SMAN_PATH : OPENAXIOM_CORE_PATH); -#ifdef __WIN32__ - char* command_line; - int cur = strlen(argv[0]); - int command_line_length = 0; - int i; - PROCESS_INFORMATION procInfo; - STARTUPINFO startupInfo = { 0 }; - DWORD status; /* Exit code for this program masqueraded as - the child created below. */ - - command_line_length += cur; - for (i = 1; i < argc; ++i) - command_line_length += 1 /* blank char as separator */ - + strlen(argv[i]); /* room for each argument */ - - /* Don't forget room for the doubledash string. */ - command_line_length += sizeof("--") - 1; - - command_line = (char*) malloc(command_line_length + 1); - - strcpy(command_line, argv[0]); - command_line[cur++] = ' '; - - /* Now start arguments to the core executable. */ - command_line[cur++] = '-'; - command_line[cur++] = '-'; - - /* Concatenate the arguments into a single string. */ - for (i = 1; i < argc; ++i) { - const int arg_length = strlen(argv[i]); - command_line[cur++] = ' '; - /* Note that strcpy will terminate `command_line' with a NUL - character, and since the next iteration will write the - blank precisely where the NUL character is, the whole command - line string will be a proper C-style string when the loop - normally exits. */ - strcpy(command_line + cur, argv[i]); - cur += arg_length; - } - - publish_systemdir(root_dir); - if(CreateProcess(/* lpApplicationName */ execpath, - /* lpCommandLine */ command_line, - /* lpProcessAttributes */ NULL, - /* lpThreadAttributes */ NULL, - /* bInheritHandles */ TRUE, - /* dwCreationFlags */ 0, - /* lpEnvironment */ NULL, - /* lpCurrentDirectory */ NULL, - /* lpstartupInfo */ &startupInfo, - /* lpProcessInformation */ &procInfo) == 0) { - fprintf(stderr, GetLastError()); + openaxiom_command command = { }; + openaxiom_driver driver = + openaxiom_preprocess_arguments(&command, argc, argv); + + switch (driver) { + case openaxiom_core_driver: + case openaxiom_script_driver: + case openaxiom_compiler_driver: + return openaxiom_execute_core(&command, driver); + + case openaxiom_sman_driver: + break; + + default: abort(); } - WaitForSingleObject(procInfo.hProcess, INFINITE); - GetExitCodeProcess(procInfo.hProcess, &status); - CloseHandle(procInfo.hThread); - CloseHandle(procInfo.hProcess); - return status; - + +#ifdef __WIN32__ + /* Should not happen on MS platforms. */ + abort(); #else /* __WIN32__ */ - int i; - char** args = (char**) malloc(sizeof (char*) * (argc + 2)); - publish_systemdir(root_dir); - - /* Pretend that we are still running the OpenAxiom driver, even if - it is actually the session manager or the core executable running. - We don't want to expose implementation details to users. */ - args[0] = argv[0]; - /* If we are running the core executable, we need to insert a - doubledash to indicate beginning of arguments. The session manager - does not need that temporary necessary obfuscation, and will - be confused. */ - if (!OPENAXIOM_USE_SMAN) - args[1] = "--"; - for (i = 1; i < argc; ++i) - args[i + !OPENAXIOM_USE_SMAN] = argv[i]; - args[argc + !OPENAXIOM_USE_SMAN] = NULL; - - execv(execpath, args); + publish_systemdir(command.root_dir); + execv(openaxiom_make_path_for(command.root_dir, openaxiom_sman_driver), + argv); perror(strerror(errno)); return -1; #endif /* __WIN32__ */ diff --git a/src/driver/utils.c b/src/driver/utils.c new file mode 100644 index 00000000..04148015 --- /dev/null +++ b/src/driver/utils.c @@ -0,0 +1,281 @@ +/* + Copyright (C) 2008, Gabriel Dos Reis. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + - Neither the name of The Numerical ALgorithms Group Ltd. nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "axiom-c-macros.h" +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include "utils.h" +#include <stdio.h> + +/* The basename of the file holding the OpenAxiom core executable. */ +#define OPENAXIOM_CORE_EXECUTABLE \ + "AXIOMsys" OPENAXIOM_EXEEXT + +/* The basename of the file holding the session manager executable. */ +#define OPENAXIOM_SMAN_EXECUTABLE \ + "sman" OPENAXIOM_EXEEXT + +/* Path to the OpenAxiom executable core, relative to + OPENAXIOM_ROOT_DIRECTORY, or to the system root directory as specified + on command line. */ +#define OPENAXIOM_CORE_PATH \ + "/bin/" OPENAXIOM_CORE_EXECUTABLE + +/* Path to the session manager, relative to OPENAXIOM_ROOT_DIRECTORY, + or to the system root directory as specified on command line. */ +#define OPENAXIOM_SMAN_PATH \ + "/bin/" OPENAXIOM_SMAN_EXECUTABLE + +/* Name of the entry point for Lisp-based OpenAxiom. */ +#define OPENAXIOM_LISP_CORE_ENTRY_POINT \ + "|AxiomCore|::|topLevel|" + + +/* Return a path to the running system, either as specified on command + line through --system=, or as specified at configuration time. */ +const char* +openaxiom_get_systemdir(int argc, char* argv[]) +{ + int i; + + /* Root directory specified on command line takes precedence + over location specified at configuration time. */ + for (i = 1; i < argc; ++i) + if (strcmp("--", argv[i]) == 0) + break; + else if (strncmp("--system=", argv[i], sizeof("--system=") - 1) == 0) { + return argv[i] + sizeof ("--system=") - 1; + } + + /* Command line did not change the system location to use. + Return what was computed at configuration time. */ + return OPENAXIOM_ROOT_DIRECTORY; +} + +/* Return the path to `driver'. */ +static const char* +get_driver_name(openaxiom_driver driver) +{ + switch (driver) { + case openaxiom_sman_driver: + return OPENAXIOM_SMAN_PATH; + + case openaxiom_script_driver: + case openaxiom_compiler_driver: + case openaxiom_core_driver: + return OPENAXIOM_CORE_PATH; + + default: + abort(); + } +} + + +/* Return a path for PROG specified as a relative path to PREFIX. */ +const char* +openaxiom_make_path_for(const char* prefix, openaxiom_driver driver) +{ + const int prefix_length = strlen(prefix); + const char* prog = get_driver_name(driver); + char* execpath = (char*) malloc(prefix_length + strlen(prog) + 1); + strcpy(execpath, prefix); + strcpy(execpath + prefix_length, prog); + return execpath; +} + +/* Build arguments, if any, to be supplied to the runtime system + of `driver'. */ +void +openaxiom_build_rts_options(openaxiom_command* command, + openaxiom_driver driver) +{ + switch (driver) { + case openaxiom_sman_driver: + case openaxiom_unknown_driver: + break; + + case openaxiom_core_driver: + break; + + case openaxiom_compiler_driver: + case openaxiom_script_driver: + switch (OPENAXIOM_BASE_RTS) { + case openaxiom_gcl_runtime: + command->rt_argc = 3; + command->rt_argv = (char **) + malloc(command->rt_argc * sizeof (char*)); + command->rt_argv[0] = "-batch"; + command->rt_argv[1] = "-eval"; + command->rt_argv[2] = "(" OPENAXIOM_LISP_CORE_ENTRY_POINT ")"; + break; + + default: + abort(); + } + break; + + default: + abort(); + } +} + +#ifdef __WIN32__ +# define OPENAXIOM_DEFAULT_DRIVER openaxiom_core_driver +#elif OPENAXIOM_USE_SMAN +# define OPENAXIOM_DEFAULT_DRIVER openaxiom_sman_driver +#else +# define OPENAXIOM_DEFAULT_DRIVER openaxiom_unknown_driver +#endif + + +/* Determine driver to be used for executing `command'. */ +openaxiom_driver +openaxiom_preprocess_arguments(openaxiom_command* command, + int argc, char** argv) +{ + int i; + openaxiom_driver driver = OPENAXIOM_DEFAULT_DRIVER; + + command->core_argc = argc; + command->core_argv = argv; + command->root_dir = openaxiom_get_systemdir(argc, argv); + for (i = 1; i < argc; ++i) + if (strcmp(argv[i], "--script") == 0) + driver = openaxiom_script_driver; + else if(strcmp(argv[i], "--compile") == 0) + driver = openaxiom_compiler_driver; + + openaxiom_build_rts_options(command, driver); + return driver; +} + + + + +/* Execute the Core Executable as described by `command'. On + POSIX systems, this is a non-return function on success. + See execv(). */ +int +openaxiom_execute_core(const openaxiom_command* command, + openaxiom_driver driver) +{ + const char* execpath = + openaxiom_make_path_for(command->root_dir, driver); +#ifdef __WIN32__ + char* command_line; + int cur = strlen(command->core_argv[0]); + int command_line_length = 0; + int i; + PROCESS_INFORMATION procInfo; + STARTUPINFO startupInfo = { 0 }; + DWORD status; /* Exit code for this program masqueraded as + the child created below. */ + + /* How long is the final command line for the MS system? */ + command_line_length += cur; + for (i = 0; i < comand->rt_argc; ++i) + command_line_length += 1 /* blank char as separator */ + + strlen(command->rt_argv[i]); /* room for each argument */ + /* Don't forget room for the doubledash string. */ + command_line_length += sizeof("--") - 1; + /* And arguments to the actual command. */ + for (i = 1; i < comand->core_argc; ++i) + command_line_length += 1 + strlen(command->core_argv[i]); + + /* Now, build the actual command line. This is done by + concatenating the arguments into a single string. */ + command_line = (char*) malloc(command_line_length + 1); + strcpy(command_line, command->core_argv[0]); + command_line[cur++] = ' '; + for (i = 0; i < command->rt_argc; ++i) { + const int arg_length = strlen(command->rt_argv[i]); + command_line[cur++] = ' '; + /* Note that strcpy will terminate `command_line' with a NUL + character, and since the next iteration will write the + blank precisely where the NUL character is, the whole command + line string will be a proper C-style string when the loop + normally exits. */ + strcpy(command_line + cur, command->rt_argv[i]); + cur += arg_length; + } + command_line[cur++] = '-'; /* start arguments to the core executable. */ + command_line[cur++] = '-'; + for (i = 1; i < command->core_argc; ++i) { + const int arg_length = strlen(command->core_argv[i]); + command_line[cur++] = ' '; + strcpy(command_line + cur, command->core_argv[i]); + cur += arg_length; + } + + if(CreateProcess(/* lpApplicationName */ execpath, + /* lpCommandLine */ command_line, + /* lpProcessAttributes */ NULL, + /* lpThreadAttributes */ NULL, + /* bInheritHandles */ TRUE, + /* dwCreationFlags */ 0, + /* lpEnvironment */ NULL, + /* lpCurrentDirectory */ NULL, + /* lpstartupInfo */ &startupInfo, + /* lpProcessInformation */ &procInfo) == 0) { + fprintf(stderr, GetLastError()); + abort(); + } + WaitForSingleObject(procInfo.hProcess, INFINITE); + GetExitCodeProcess(procInfo.hProcess, &status); + CloseHandle(procInfo.hThread); + CloseHandle(procInfo.hProcess); + return status; + +#else /* __WIN32__ */ + int i; + char** args = (char**) + malloc(sizeof (char*) * (command->rt_argc + command->core_argc + 2)); + args[0] = command->core_argv[0]; + for (i = 0; i < command->rt_argc; ++i) + args[i + 1] = command->rt_argv[i]; + if (command->core_argc > 1) { + /* Insert a doubledash to indicate beginning of arguments. */ + args[command->rt_argc + 1] = "--"; + for (i = 1; i < command->core_argc; ++i) + args[command->rt_argc + i + 1] = command->core_argv[i]; + args[command->rt_argc + command->core_argc + 1] = NULL; + } + else + args[command->rt_argc + command->core_argc] = NULL; + + execv(execpath, args); + perror(strerror(errno)); + return -1; +#endif /* __WIN32__ */ +} diff --git a/src/driver/utils.h b/src/driver/utils.h new file mode 100644 index 00000000..41d7c345 --- /dev/null +++ b/src/driver/utils.h @@ -0,0 +1,79 @@ +/* + Copyright (C) 2008, Gabriel Dos Reis. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + - Neither the name of The Numerical ALgorithms Group Ltd. nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef OPENAXIOM_UTILS_INCLUDED +#define OPENAXIOM_UTILS_INCLUDED + +#include "axiom-c-macros.h" +#if HAVE_UNISTD_H +# include <unistd.h> +#endif +#ifdef __WIN32__ +# include <windows.h> +#endif + +/* A list of drivers for OpenAxiom. */ +typedef enum openaxiom_driver { + openaxiom_unknown_driver, + openaxiom_sman_driver, + openaxiom_core_driver, + openaxiom_script_driver, + openaxiom_compiler_driver +} openaxiom_driver; + +/* A list of runtime support systems for OpenAxiom. */ +typedef enum openaxiom_runtime { + openaxiom_unknown_runtime, + openaxiom_gcl_runtime, + openaxiom_sbcl_runtime, + openaxiom_clisp_runtime, + openaxiom_ecl_runtime, + openaxiom_bemol_runtime +} openaxiom_runtime; + +/* A description of external command to be executed. */ +typedef struct openaxiom_command { + char** core_argv; /* arguments for the actual executable. */ + int core_argc; /* number of such arguments. */ + char** rt_argv; /* arguments to the base RT, if any. */ + int rt_argc; /* number of such arguments. */ + const char* root_dir; /* path to the OpenAxiom system. */ +} openaxiom_command; + +const char* openaxiom_get_systemdir(int argc, char*[]); +const char* openaxiom_make_path_for(const char*, openaxiom_driver); + +int openaxiom_execute_core(const openaxiom_command*, openaxiom_driver); +void openaxiom_build_rts_options(openaxiom_command*, openaxiom_driver); + +#endif /* OPENAXIOM_UTILS_INCLUDED */ |