X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fruntime.c;h=3491f03d555258b30dbec20af609ccd16f244a53;hb=dc5d8cef786c974258601109f79ab18f874b1270;hp=0307d055fc20a220daf39b74151b9a0d77e554e9;hpb=5bf4a6a677c80a71dfa31b5c9c374f986594392f;p=sbcl.git diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 0307d05..3491f03 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -13,14 +13,28 @@ * files for more information. */ +#include "sbcl.h" + #include #include +#ifndef LISP_FEATURE_WIN32 +#include +#endif #include +#ifndef LISP_FEATURE_WIN32 +#include +#endif #include #include #include #include #include +#include +#ifndef LISP_FEATURE_WIN32 +#include +#endif +#include +#include #if defined(SVR4) || defined(__linux__) #include @@ -29,7 +43,6 @@ #include "signal.h" #include "runtime.h" -#include "sbcl.h" #include "alloc.h" #include "vars.h" #include "globals.h" @@ -38,23 +51,32 @@ #include "arch.h" #include "gc.h" #include "interr.h" -#include "monitor.h" #include "validate.h" #include "core.h" #include "save.h" #include "lispregs.h" +#include "thread.h" + +#include "genesis/static-symbols.h" +#include "genesis/symbol.h" + #ifdef irix #include #include "interr.h" #endif + +#ifndef SBCL_HOME +#define SBCL_HOME "/usr/local/lib/sbcl/" +#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) { - lose("\nSIGINT hit at 0x%08lX\n", - (unsigned long) *os_context_pc_addr(void_context)); + lose("\nSIGINT hit at 0x%08lX\n", + (unsigned long) *os_context_pc_addr(void_context)); } /* (This is not static, because we want to be able to call it from @@ -76,9 +98,9 @@ successful_malloc(size_t size) { void* result = malloc(size); if (0 == result) { - lose("malloc failure"); + lose("malloc failure\n"); } else { - return result; + return result; } return (void *) NULL; /* dummy value: return something ... */ } @@ -94,154 +116,284 @@ copied_existing_filename_or_null(char *filename) { struct stat filename_stat; if (stat(filename, &filename_stat)) { /* if failure */ - return 0; + return 0; } else { return copied_string(filename); } } /* Convert a null-terminated array of null-terminated strings (e.g. - * argv or envp) into a Lisp list of Lisp strings. */ + * argv or envp) into a Lisp list of Lisp base-strings. */ static lispobj -alloc_string_list(char *array_ptr[]) +alloc_base_string_list(char *array_ptr[]) { if (*array_ptr) { - return alloc_cons(alloc_string(*array_ptr), - alloc_string_list(1 + array_ptr)); + return alloc_cons(alloc_base_string(*array_ptr), + alloc_base_string_list(1 + array_ptr)); } else { - return NIL; + return NIL; } } +/* miscellaneous chattiness */ + +void +print_help() +{ + puts( +"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\ +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\ +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\ +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 +print_version() +{ + printf("SBCL %s\n", SBCL_VERSION_STRING); +} + +void +print_banner() +{ + printf( +"This is SBCL %s, an implementation of ANSI Common Lisp.\n\ +More information about SBCL is available at .\n\ +\n\ +SBCL is free software, provided as is, with absolutely no warranty.\n\ +It is mostly in the public domain; some portions are provided under\n\ +BSD-style licenses. See the CREDITS and COPYING files in the\n\ +distribution for more information.\n\ +", SBCL_VERSION_STRING); +} + +/* Look for a core file to load, first in the directory named by the + * SBCL_HOME environment variable, then in a hardcoded default + * location. Returns a malloced copy of the core filename. */ +char * +search_for_core () +{ + char *sbcl_home = getenv("SBCL_HOME"); + char *lookhere; + char *stem = "/sbcl.core"; + char *core; + + 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); + + if (!core) { + lose("can't find core file at %s\n", lookhere); + } + + free(lookhere); + + return core; +} + +char **posix_argv; +char *core_string; + + int main(int argc, char *argv[], char *envp[]) { +#ifdef LISP_FEATURE_WIN32 + /* Exception handling support structure. Evil Win32 hack. */ + struct lisp_exception_frame exception_frame; +#endif + /* the name of the core file we're to execute. Note that this is * a malloc'ed string which should be freed eventually. */ char *core = 0; + char **sbcl_argv = 0; + os_vm_offset_t embedded_core_offset = 0; /* other command line options */ boolean noinform = 0; boolean end_runtime_options = 0; lispobj initial_function; + const char *sbcl_home = getenv("SBCL_HOME"); + + interrupt_init(); + block_blockable_signals(); + + setlocale(LC_ALL, ""); + + /* Parse our part of the command line (aka "runtime options"), + * stripping out those options that we handle. */ + { + int argi = 1; + while (argi < argc) { + char *arg = argv[argi]; + if (0 == strcmp(arg, "--noinform")) { + noinform = 1; + ++argi; + } else if (0 == strcmp(arg, "--core")) { + if (core) { + lose("more than one core file specified\n"); + } else { + ++argi; + if (argi >= argc) { + lose("missing filename for --core argument\n"); + } + core = copied_string(argv[argi]); + ++argi; + } + } else if (0 == strcmp(arg, "--help")) { + /* I think this is the (or a) usual convention: upon + * seeing "--help" we immediately print our help + * string and exit, ignoring everything else. */ + print_help(); + exit(0); + } else if (0 == strcmp(arg, "--version")) { + /* 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"); + errno = 0; + dynamic_space_size = strtol(argv[argi++], 0, 0) << 20; + if (errno) + lose("argument to --dynamic-space-size is not a number"); + } 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 --dynamic-space-size is not a number"); + } else if (0 == strcmp(arg, "--debug-environment")) { + int n = 0; + printf("; Commandline arguments:\n"); + while (n < argc) { + printf("; %2d: \"%s\"\n", n, argv[n]); + ++n; + } + n = 0; + printf(";\n; Environment:\n"); + while (ENVIRON[n]) { + printf("; %2d: \"%s\"\n", n, ENVIRON[n]); + ++n; + } + ++argi; + } else if (0 == strcmp(arg, "--end-runtime-options")) { + end_runtime_options = 1; + ++argi; + break; + } else { + /* This option was unrecognized as a runtime option, + * so it must be a toplevel option or a user option, + * so we must be past the end of the runtime option + * section. */ + break; + } + } + /* This is where we strip out those options that we handle. We + * also take this opportunity to make sure that we don't find + * an out-of-place "--end-runtime-options" option. */ + { + char *argi0 = argv[argi]; + int argj = 1; + /* (argc - argi) for the arguments, one for the binary, + and one for the terminating NULL. */ + sbcl_argv = successful_malloc((2 + argc - argi) * sizeof(char *)); + sbcl_argv[0] = argv[0]; + while (argi < argc) { + char *arg = argv[argi++]; + /* If we encounter --end-runtime-options for the first + * time after the point where we had to give up on + * runtime options, then the point where we had to + * give up on runtime options must've been a user + * error. */ + if (!end_runtime_options && + 0 == strcmp(arg, "--end-runtime-options")) { + lose("bad runtime option \"%s\"\n", argi0); + } + sbcl_argv[argj++] = arg; + } + sbcl_argv[argj] = 0; + } + } + + /* Align down to multiple of page_table page size, and to the appropriate + * stack alignment. */ + dynamic_space_size &= ~(PAGE_BYTES-1); + thread_control_stack_size &= ~(CONTROL_STACK_ALIGNMENT_BYTES-1); /* 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(); + os_init(argv, envp); arch_init(); gc_init(); validate(); - /* Parse our part of the command line (aka "runtime options"), - * stripping out those options that we handle. */ - { - int argi = 1; - while (argi < argc) { - char *arg = argv[argi]; - if (0 == strcmp(arg, "--noinform")) { - noinform = 1; - ++argi; - } else if (0 == strcmp(arg, "--core")) { - if (core) { - lose("more than one core file specified"); - } else { - ++argi; - if (argi >= argc) { - lose("missing filename for --core argument"); - } - core = copied_string(argv[argi]); - ++argi; - } - } else if (0 == strcmp(arg, "--end-runtime-options")) { - end_runtime_options = 1; - ++argi; - break; - } else { - /* This option was unrecognized as a runtime option, - * so it must be a toplevel option or a user option, - * so we must be past the end of the runtime option - * section. */ - break; - } - } - /* This is where we strip out those options that we handle. We - * also take this opportunity to make sure that we don't find - * an out-of-place "--end-runtime-options" option. */ - { - char *argi0 = argv[argi]; - int argj = 1; - while (argi < argc) { - char *arg = argv[argi++]; - /* If we encounter --end-runtime-options for the first - * time after the point where we had to give up on - * runtime options, then the point where we had to - * give up on runtime options must've been a user - * error. */ - if (!end_runtime_options && - 0 == strcmp(arg, "--end-runtime-options")) { - lose("bad runtime option \"%s\"", argi0); - } - argv[argj++] = arg; - } - argv[argj] = 0; - argc = argj; - } - } - /* If no core file was specified, look for one. */ if (!core) { - char *sbcl_home = getenv("SBCL_HOME"); - if (sbcl_home) { - char *lookhere; - char *stem = "/sbcl.core"; - 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); - } else { - core = copied_existing_filename_or_null("/usr/lib/sbcl.core"); - if (!core) { - core = - copied_existing_filename_or_null("/usr/local/lib/sbcl.core"); - } - } - if (!core) { - lose("can't find core file"); - } + 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(); + } } - if (!noinform) { - printf( -"This is SBCL %s, an implementation of ANSI Common Lisp.\n\ -\n\ -SBCL is derived from the CMU CL system created at Carnegie Mellon University.\n\ -Besides software and documentation originally created at Carnegie Mellon\n\ -University, SBCL contains some software originally from the Massachusetts\n\ -Institute of Technology, Symbolics Incorporated, and Xerox Corporation, and\n\ -material contributed by volunteers since the release of CMU CL into the\n\ -public domain. See the CREDITS file in the distribution for more information.\n\ -\n\ -SBCL is a free software system, provided as is, with absolutely no warranty.\n\ -It is mostly in the public domain, but also includes some software copyrighted\n\ - Massachusetts Institute of Technology, 1986;\n\ - Symbolics, Inc., 1989, 1990, 1991, 1992; and\n\ - Xerox Corporation, 1985, 1986, 1987, 1988, 1989, 1990\n\ -used under BSD-style licenses allowing copying only under certain conditions.\n\ -See the COPYING file in the distribution for more information.\n\ -\n\ -More information about SBCL is available at .\n\ -", SBCL_VERSION_STRING); - fflush(stdout); + /* 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); + dir = dirname(copied_core); + envstring = (char *) calloc(strlen(stem) + + strlen(dir) + + 1, + sizeof(char)); + sprintf(envstring, "%s%s", stem, dir); + putenv(envstring); + free(copied_core); + } + + if (!noinform && embedded_core_offset == 0) { + print_banner(); + fflush(stdout); } -#ifdef MACH - mach_init(); -#endif #if defined(SVR4) || defined(__linux__) tzset(); #endif @@ -249,48 +401,41 @@ More information about SBCL is available at .\n\ define_var("nil", NIL, 1); define_var("t", T, 1); - set_lossage_handler(monitor_or_something); + enable_lossage_handler(); globals_init(); - initial_function = load_core_file(core); + initial_function = load_core_file(core, embedded_core_offset); if (initial_function == NIL) { - lose("couldn't find initial function"); + lose("couldn't find initial function\n"); } - SHOW("freeing core"); - free(core); gc_initialize_pointers(); -#ifdef BINDING_STACK_POINTER - SetSymbolValue(BINDING_STACK_POINTER, BINDING_STACK_START); -#endif - - interrupt_init(); - arch_install_interrupt_handlers(); +#ifndef LISP_FEATURE_WIN32 os_install_interrupt_handlers(); - -#ifdef PSEUDO_ATOMIC_ATOMIC - /* Turn on pseudo atomic for when we call into Lisp. */ - SHOW("turning on pseudo atomic"); - SetSymbolValue(PSEUDO_ATOMIC_ATOMIC, make_fixnum(1)); - SetSymbolValue(PSEUDO_ATOMIC_INTERRUPTED, make_fixnum(0)); +#else +/* wos_install_interrupt_handlers(handler); */ + wos_install_interrupt_handlers(&exception_frame); #endif - /* Convert remaining argv values to something that Lisp can grok. */ - SHOW("setting POSIX-ARGV symbol value"); - SetSymbolValue(POSIX_ARGV, alloc_string_list(argv)); - - /* Install a handler to pick off SIGINT until the Lisp system gets - * far enough along to install its own handler. */ - sigint_init(); - - FSHOW((stderr, "/funcalling initial_function=0x%lx\n", initial_function)); - funcall0(initial_function); - - /* initial_function() is not supposed to return. */ - lose("Lisp initial_function gave up control."); - return 0; /* dummy value: return something */ + /* 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)); +#ifdef LISP_FEATURE_WIN32 + fprintf(stderr, "\n\ +This is experimental prerelease support for the Windows platform: use\n\ +at your own risk. \"Your Kitten of Death awaits!\"\n"); + fflush(stdout); + fflush(stderr); +#endif + create_initial_thread(initial_function); + lose("CATS. CATS ARE NICE.\n"); + return 0; } -