X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fruntime.c;h=f127933225786b82344bb2968bbcfdc1e601c2dd;hb=5c0a884190d6c98448d86fb05e1e99df901c9bf8;hp=5bf3f4db8b5a87ea35b8b62a6da9bdaa30d2739d;hpb=02e900a311f296b87ba34b89bd2a842c9198c7cf;p=sbcl.git diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 5bf3f4d..f127933 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -35,6 +35,7 @@ #endif #include #include +#include #if defined(SVR4) || defined(__linux__) #include @@ -43,14 +44,14 @@ #include "signal.h" #include "runtime.h" -#include "alloc.h" #include "vars.h" #include "globals.h" #include "os.h" +#include "interr.h" +#include "alloc.h" #include "interrupt.h" #include "arch.h" #include "gc.h" -#include "interr.h" #include "validate.h" #include "core.h" #include "save.h" @@ -67,16 +68,22 @@ #endif #ifndef SBCL_HOME -#define SBCL_HOME "/usr/local/lib/sbcl/" +#define SBCL_HOME SBCL_PREFIX"/lib/sbcl/" +#endif + +#ifdef LISP_FEATURE_HPUX +extern void *return_from_lisp_stub; +#include "genesis/closure.h" +#include "genesis/simple-fun.h" #endif /* SIGINT handler that invokes the monitor (for when Lisp isn't up to it) */ static void -sigint_handler(int signal, siginfo_t *info, void *void_context) +sigint_handler(int signal, siginfo_t *info, os_context_t *context) { lose("\nSIGINT hit at 0x%08lX\n", - (unsigned long) *os_context_pc_addr(void_context)); + (unsigned long) *os_context_pc_addr(context)); } /* (This is not static, because we want to be able to call it from @@ -122,18 +129,36 @@ copied_existing_filename_or_null(char *filename) } } -/* Convert a null-terminated array of null-terminated strings (e.g. - * argv or envp) into a Lisp list of Lisp base-strings. */ -static lispobj -alloc_base_string_list(char *array_ptr[]) +#ifndef LISP_FEATURE_WIN32 +char * +copied_realpath(const char *pathname) { - if (*array_ptr) { - return alloc_cons(alloc_base_string(*array_ptr), - alloc_base_string_list(1 + array_ptr)); - } else { - return NIL; + char *messy, *tidy; + size_t len; + + /* realpath() supposedly can't be counted on to always return + * an absolute path, so we prepend the cwd to relative paths */ + messy = NULL; + if (pathname[0] != '/') { + messy = successful_malloc(PATH_MAX + 1); + if (getcwd(messy, PATH_MAX + 1) == NULL) { + free(messy); + return NULL; + } + len = strlen(messy); + snprintf(messy + len, PATH_MAX + 1 - len, "/%s", pathname); + } + + tidy = successful_malloc(PATH_MAX + 1); + if (realpath((messy ? messy : pathname), tidy) == NULL) { + free(messy); + free(tidy); + return NULL; } + + return tidy; } +#endif /* LISP_FEATURE_WIN32 */ /* miscellaneous chattiness */ @@ -141,24 +166,27 @@ void print_help() { puts( -"SBCL is a Common Lisp programming environment. Ordinarily you shouldn't\n\ -need command line options when you invoke it interactively: you can just\n\ -start it and work with the customary Lisp READ-EVAL-PRINT loop.\n\ +"Usage: sbcl [runtime-options] [toplevel-options] [user-options]\n\ +Common runtime options:\n\ + --help Print this message and exit.\n\ + --version Print version information and exit.\n\ + --core Use the specified core file instead of the default.\n\ + --dynamic-space-size Size of reserved dynamic space in megabytes.\n\ + --control-stack-size Size of reserved control stack in megabytes.\n\ \n\ -One option idiom which is sometimes useful interactively (e.g. when\n\ -exercising a test case for a bug report) is\n\ - sbcl --no-sysinit --no-userinit\n\ -to keep SBCL from reading any initialization files at startup. And some\n\ -people like to suppress the default startup message:\n\ - sbcl --noinform\n\ +Common toplevel options:\n\ + --sysinit System-wide init-file to use instead of default.\n\ + --userinit Per-user init-file to use instead of default.\n\ + --no-sysinit Inhibit processing of any system-wide init-file.\n\ + --no-userinit Inhibit processing of any per-user init-file.\n\ \n\ -Other options can be useful when you're running SBCL noninteractively,\n\ -e.g. from a script, or if you have a strange system configuration, so\n\ -that SBCL can't by default find one of the files it needs. For\n\ -information on such options, see the sbcl(1) man page.\n\ +User options are not processed by SBCL. All runtime options must\n\ +appear before toplevel options, and all toplevel options must\n\ +appear before user options.\n\ \n\ -More information on SBCL can be found on its man page, or at\n\ -.\n"); +For more information please refer to the SBCL User Manual, which\n\ +should be installed along with SBCL, and is also available from the\n\ +website .\n"); } void @@ -192,22 +220,76 @@ search_for_core () char *stem = "/sbcl.core"; char *core; - if(!sbcl_home) sbcl_home = SBCL_HOME; + if (!(sbcl_home && *sbcl_home)) sbcl_home = SBCL_HOME; lookhere = (char *) calloc(strlen(sbcl_home) + strlen(stem) + 1, sizeof(char)); sprintf(lookhere, "%s%s", sbcl_home, stem); core = copied_existing_filename_or_null(lookhere); - free(lookhere); + if (!core) { - lose("can't find core file\n"); + lose("can't find core file at %s\n", lookhere); } + free(lookhere); + return core; } - +/* Try to find the path to an executable from argv[0], this is only + * used when os_get_runtime_executable_path() returns NULL */ +#ifdef LISP_FEATURE_WIN32 +char * +search_for_executable(const char *argv0) +{ + return NULL; +} +#else /* LISP_FEATURE_WIN32 */ +char * +search_for_executable(const char *argv0) +{ + char *search, *start, *end, *buf; + + /* If argv[0] contains a slash then it's probably an absolute path + * or relative to the current directory, so check if it exists. */ + if (strchr(argv0, '/') != NULL && access(argv0, F_OK) == 0) + return copied_realpath(argv0); + + /* Bail on an absolute path which doesn't exist */ + if (argv0[0] == '/') + return NULL; + + /* Otherwise check if argv[0] exists relative to any directory in PATH */ + search = getenv("PATH"); + if (search == NULL) + return NULL; + search = copied_string(search); + buf = successful_malloc(PATH_MAX + 1); + for (start = search; (end = strchr(start, ':')) != NULL; start = end + 1) { + *end = '\0'; + snprintf(buf, PATH_MAX + 1, "%s/%s", start, argv0); + if (access(buf, F_OK) == 0) { + free(search); + search = copied_realpath(buf); + free(buf); + return search; + } + } + + free(search); + free(buf); + return NULL; +} +#endif /* LISP_FEATURE_WIN32 */ + +char **posix_argv; +char *core_string; + +struct runtime_options *runtime_options; + +char *saved_runtime_path = NULL; + int main(int argc, char *argv[], char *envp[]) { @@ -221,33 +303,70 @@ main(int argc, char *argv[], char *envp[]) char *core = 0; char **sbcl_argv = 0; os_vm_offset_t embedded_core_offset = 0; + char *runtime_path = 0; /* other command line options */ boolean noinform = 0; boolean end_runtime_options = 0; + boolean disable_lossage_handler_p = 0; lispobj initial_function; + const char *sbcl_home = getenv("SBCL_HOME"); interrupt_init(); - block_blockable_signals(); + block_blockable_signals(0, 0); setlocale(LC_ALL, ""); - /* KLUDGE: os_vm_page_size is set by os_init(), and on some - * systems (e.g. Alpha) arch_init() needs need os_vm_page_size, so - * it must follow os_init(). -- WHN 2000-01-26 */ - os_init(argv, envp); - arch_init(); - gc_init(); - validate(); + runtime_options = NULL; + + /* Save the argv[0] derived runtime path in case + * os_get_runtime_executable_path(1) isn't able to get an + * externally-usable path later on. */ + saved_runtime_path = search_for_executable(argv[0]); + + /* Check early to see if this executable has an embedded core, + * which also populates runtime_options if the core has runtime + * options */ + runtime_path = os_get_runtime_executable_path(0); + if (runtime_path || saved_runtime_path) { + os_vm_offset_t offset = search_for_embedded_core( + runtime_path ? runtime_path : saved_runtime_path); + if (offset != -1) { + embedded_core_offset = offset; + core = (runtime_path ? runtime_path : + copied_string(saved_runtime_path)); + } else { + if (runtime_path) + free(runtime_path); + } + } + /* Parse our part of the command line (aka "runtime options"), * stripping out those options that we handle. */ - { + if (runtime_options != NULL) { + dynamic_space_size = runtime_options->dynamic_space_size; + thread_control_stack_size = runtime_options->thread_control_stack_size; + sbcl_argv = argv; + } else { int argi = 1; + + runtime_options = successful_malloc(sizeof(struct runtime_options)); + while (argi < argc) { char *arg = argv[argi]; - if (0 == strcmp(arg, "--noinform")) { + if (0 == strcmp(arg, "--script")) { + /* This is both a runtime and a toplevel option. As a + * runtime option, it is equivalent to --noinform. + * This exits, and does not increment argi, so that + * TOPLEVEL-INIT sees the option. */ + noinform = 1; + end_runtime_options = 1; + disable_lossage_handler_p = 1; + lose_on_corruption_p = 1; + break; + } else if (0 == strcmp(arg, "--noinform")) { noinform = 1; ++argi; } else if (0 == strcmp(arg, "--core")) { @@ -271,6 +390,36 @@ main(int argc, char *argv[], char *envp[]) /* As in "--help" case, I think this is expected. */ print_version(); exit(0); + } else if (0 == strcmp(arg, "--dynamic-space-size")) { + ++argi; + if (argi >= argc) + lose("missing argument for --dynamic-space-size"); + { + char *tail; + long tmp = strtol(argv[argi++], &tail, 0); + if (tail[0]) + lose("--dynamic-space-size argument is not a number"); + if ((tmp <= 0) || + (tmp >= (LONG_MAX >> 20))) { + lose("--dynamic-space-size argument is out of range"); + } + dynamic_space_size = tmp << 20; + } +# ifdef MAX_DYNAMIC_SPACE_END + if (!((DYNAMIC_SPACE_START < + DYNAMIC_SPACE_START+dynamic_space_size) && + (DYNAMIC_SPACE_START+dynamic_space_size <= + MAX_DYNAMIC_SPACE_END))) + lose("--dynamic-space-size argument is too large"); +# endif + } else if (0 == strcmp(arg, "--control-stack-size")) { + ++argi; + if (argi >= argc) + lose("missing argument for --control-stack-size"); + errno = 0; + thread_control_stack_size = strtol(argv[argi++], 0, 0) << 20; + if (errno) + lose("argument to --control-stack-size is not a number"); } else if (0 == strcmp(arg, "--debug-environment")) { int n = 0; printf("; Commandline arguments:\n"); @@ -285,6 +434,12 @@ main(int argc, char *argv[], char *envp[]) ++n; } ++argi; + } else if (0 == strcmp(arg, "--disable-ldb")) { + disable_lossage_handler_p = 1; + ++argi; + } else if (0 == strcmp(arg, "--lose-on-corruption")) { + lose_on_corruption_p = 1; + ++argi; } else if (0 == strcmp(arg, "--end-runtime-options")) { end_runtime_options = 1; ++argi; @@ -324,27 +479,34 @@ main(int argc, char *argv[], char *envp[]) } } + /* Align down to multiple of page_table page size, and to the appropriate + * stack alignment. */ + dynamic_space_size &= ~(PAGE_BYTES-1); +#ifdef LISP_FEATURE_GENCGC + dynamic_space_size &= ~(GENCGC_CARD_BYTES-1); +#endif + thread_control_stack_size &= ~(CONTROL_STACK_ALIGNMENT_BYTES-1); + + /* Preserve the runtime options for possible future core saving */ + runtime_options->dynamic_space_size = dynamic_space_size; + runtime_options->thread_control_stack_size = thread_control_stack_size; + + /* KLUDGE: os_vm_page_size is set by os_init(), and on some + * systems (e.g. Alpha) arch_init() needs need os_vm_page_size, so + * it must follow os_init(). -- WHN 2000-01-26 */ + os_init(argv, envp); + arch_init(); + gc_init(); + validate(); + /* If no core file was specified, look for one. */ if (!core) { - char *runtime_path = os_get_runtime_executable_path(); - - if (runtime_path) { - os_vm_offset_t offset = search_for_embedded_core(runtime_path); - - if (offset != -1) { - embedded_core_offset = offset; - core = runtime_path; - } else { - free(runtime_path); - core = search_for_core(); - } - } else { - core = search_for_core(); - } + core = search_for_core(); } - /* Make sure that SBCL_HOME is set, unless loading an embedded core. */ - if (!getenv("SBCL_HOME") && embedded_core_offset == 0) { + /* Make sure that SBCL_HOME is set and not the empty string, + unless loading an embedded core. */ + if (!(sbcl_home && *sbcl_home) && embedded_core_offset == 0) { char *envstring, *copied_core, *dir; char *stem = "SBCL_HOME="; copied_core = copied_string(core); @@ -358,19 +520,20 @@ main(int argc, char *argv[], char *envp[]) free(copied_core); } - if (!noinform) { + if (!noinform && embedded_core_offset == 0) { print_banner(); fflush(stdout); } -#if defined(SVR4) || defined(__linux__) +#if defined(SVR4) || defined(__linux__) || defined(__NetBSD__) tzset(); #endif define_var("nil", NIL, 1); define_var("t", T, 1); - enable_lossage_handler(); + if (!disable_lossage_handler_p) + enable_lossage_handler(); globals_init(); @@ -378,6 +541,12 @@ main(int argc, char *argv[], char *envp[]) if (initial_function == NIL) { lose("couldn't find initial function\n"); } +#ifdef LISP_FEATURE_HPUX + /* -1 = CLOSURE_FUN_OFFSET, 23 = SIMPLE_FUN_CODE_OFFSET, we are + * not in LANGUAGE_ASSEMBLY so we cant reach them. */ + return_from_lisp_stub = (void *) ((char *)*((unsigned long *) + ((char *)initial_function + -1)) + 23); +#endif gc_initialize_pointers(); @@ -389,15 +558,11 @@ main(int argc, char *argv[], char *envp[]) wos_install_interrupt_handlers(&exception_frame); #endif - /* Pass core filename into Lisp */ - SetSymbolValue(CORE_STRING, alloc_base_string(core),0); - SHOW("freeing core"); - free(core); - - /* Convert remaining argv values to something that Lisp can grok. */ - SHOW("setting POSIX-ARGV symbol value"); - SetSymbolValue(POSIX_ARGV, alloc_base_string_list(sbcl_argv),0); - free(sbcl_argv); + /* Pass core filename and the processed argv into Lisp. They'll + * need to be processed further there, to do locale conversion. + */ + core_string = core; + posix_argv = sbcl_argv; FSHOW((stderr, "/funcalling initial_function=0x%lx\n", (unsigned long)initial_function));