#include <stdio.h>
#include <string.h>
+#ifndef LISP_FEATURE_WIN32
#include <libgen.h>
+#endif
#include <sys/types.h>
+#ifndef LISP_FEATURE_WIN32
#include <sys/wait.h>
+#endif
#include <stdlib.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <signal.h>
+#ifndef LISP_FEATURE_WIN32
#include <sched.h>
+#endif
#include <errno.h>
+#include <locale.h>
#if defined(SVR4) || defined(__linux__)
#include <time.h>
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
{
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 ... */
}
{
struct stat filename_stat;
if (stat(filename, &filename_stat)) { /* if failure */
- return 0;
+ return 0;
} else {
return copied_string(filename);
}
alloc_base_string_list(char *array_ptr[])
{
if (*array_ptr) {
- return alloc_cons(alloc_base_string(*array_ptr),
- alloc_base_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;
}
}
\f
{
printf(
"This is SBCL %s, an implementation of ANSI Common Lisp.\n\
-More information about SBCL is available at <http://www.sbcl.org/>.
+More information about SBCL is available at <http://www.sbcl.org/>.\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\
distribution for more information.\n\
", SBCL_VERSION_STRING);
}
-\f
-FILE *stdlog;
-\f
+/* 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;
+ 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");
+ }
+
+ return core;
+}
+
+ \f
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;
lispobj initial_function;
+ interrupt_init();
+ block_blockable_signals();
+
+ 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();
+ 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, "--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, "--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;
- }
+ 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, "--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;
+ }
}
/* If no core file was specified, look for one. */
if (!core) {
- char *sbcl_home = getenv("SBCL_HOME");
- char *lookhere;
- char *stem = "/sbcl.core";
- if(!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");
- }
+ 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();
+ }
}
- /* Make sure that SBCL_HOME is set, no matter where the core was
- * found */
- if (!getenv("SBCL_HOME")) {
- 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);
+
+ /* Make sure that SBCL_HOME is set, unless loading an embedded core. */
+ if (!getenv("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) {
- print_banner();
- fflush(stdout);
+ print_banner();
+ fflush(stdout);
}
#if defined(SVR4) || defined(__linux__)
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();
- interrupt_init();
arch_install_interrupt_handlers();
+#ifndef LISP_FEATURE_WIN32
os_install_interrupt_handlers();
+#else
+/* wos_install_interrupt_handlers(handler); */
+ 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(argv),0);
-
- /* 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));
- create_thread(initial_function);
- /* in a unithread build, create_thread never returns */
-#ifdef LISP_FEATURE_SB_THREAD
- parent_loop();
+ SetSymbolValue(POSIX_ARGV, alloc_base_string_list(sbcl_argv),0);
+ free(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;
}
-
-#ifdef LISP_FEATURE_SB_THREAD
-
-/* this is being pared down as time goes on; eventually we want to get
- * to the point that we have no parent loop at all and the parent
- * thread runs Lisp just like any other */
-
-static void /* noreturn */ parent_loop(void)
-{
- struct sigaction sa;
- sigset_t sigset;
- int status;
- pid_t pid=0;
-
- sigemptyset(&sigset);
- sa.sa_handler=SIG_IGN;
- sa.sa_mask=sigset;
- sa.sa_flags=0;
- sigaction(SIGINT, &sa, 0); /* ^c should go to the lisp thread instead */
- sigaction(SIG_THREAD_EXIT, &sa, 0);
- sigaction(SIGCHLD, &sa, 0);
-
- while(!all_threads) {
- sched_yield();
- }
- while(all_threads && (pid=waitpid(-1,&status,__WALL))) {
- struct thread *th;
- if(pid==-1) {
- if(errno == EINTR) continue;
- fprintf(stderr,"waitpid: %s\n",strerror(errno));
- }
- else if(WIFEXITED(status) || WIFSIGNALED(status)) {
- th=find_thread_by_pid(pid);
- if(!th) continue;
- destroy_thread(th);
- if(!all_threads) break;
- }
- }
- exit(WEXITSTATUS(status));
-}
-
-#endif