2 * main() entry point for a stand-alone SBCL image
6 * This software is part of the SBCL system. See the README file for
9 * This software is derived from the CMU CL system, which was
10 * written at Carnegie Mellon University and released into the
11 * public domain. The software is in the public domain and is
12 * provided with absolutely no warranty. See the COPYING and CREDITS
13 * files for more information.
20 #ifndef LISP_FEATURE_WIN32
23 #include <sys/types.h>
24 #ifndef LISP_FEATURE_WIN32
30 #include <sys/param.h>
33 #ifndef LISP_FEATURE_WIN32
39 #if defined(SVR4) || defined(__linux__)
50 #include "interrupt.h"
60 #include "genesis/static-symbols.h"
61 #include "genesis/symbol.h"
70 #define SBCL_HOME "/usr/local/lib/sbcl/"
73 #ifdef LISP_FEATURE_HPUX
74 extern void *return_from_lisp_stub;
78 /* SIGINT handler that invokes the monitor (for when Lisp isn't up to it) */
80 sigint_handler(int signal, siginfo_t *info, void *void_context)
82 lose("\nSIGINT hit at 0x%08lX\n",
83 (unsigned long) *os_context_pc_addr(void_context));
86 /* (This is not static, because we want to be able to call it from
91 SHOW("entering sigint_init()");
92 install_handler(SIGINT, sigint_handler);
93 SHOW("leaving sigint_init()");
97 * helper functions for dealing with command line args
101 successful_malloc(size_t size)
103 void* result = malloc(size);
105 lose("malloc failure\n");
109 return (void *) NULL; /* dummy value: return something ... */
113 copied_string(char *string)
115 return strcpy(successful_malloc(1+strlen(string)), string);
119 copied_existing_filename_or_null(char *filename)
121 struct stat filename_stat;
122 if (stat(filename, &filename_stat)) { /* if failure */
125 return copied_string(filename);
129 /* miscellaneous chattiness */
135 "Usage: sbcl [runtime-options] [toplevel-options] [user-options]\n\
136 Common runtime options:\n\
137 --help Print this message and exit.\n\
138 --version Print version information and exit.\n\
139 --core <filename> Use the specified core file instead of the default.\n\
140 --dynamic-space-size <MiB> Size of reserved dynamic space in megabytes.\n\
141 --control-stack-size <MiB> Size of reserved control stack in megabytes.\n\
143 Common toplevel options:\n\
144 --sysinit <filename> System-wide init-file to use instead of default.\n\
145 --userinit <filename> Per-user init-file to use instead of default.\n\
146 --no-sysinit Inhibit processing of any system-wide init-file.\n\
147 --no-userinit Inhibit processing of any per-user init-file.\n\
149 User options are not processed by SBCL. All runtime options must\n\
150 appear before toplevel options, and all toplevel options must\n\
151 appear before user options.\n\
153 For more information please refer to the SBCL User Manual, which\n\
154 should be installed along with SBCL, and is also available from the\n\
155 website <http://www.sbcl.org/>.\n");
161 printf("SBCL %s\n", SBCL_VERSION_STRING);
168 "This is SBCL %s, an implementation of ANSI Common Lisp.\n\
169 More information about SBCL is available at <http://www.sbcl.org/>.\n\
171 SBCL is free software, provided as is, with absolutely no warranty.\n\
172 It is mostly in the public domain; some portions are provided under\n\
173 BSD-style licenses. See the CREDITS and COPYING files in the\n\
174 distribution for more information.\n\
175 ", SBCL_VERSION_STRING);
178 /* Look for a core file to load, first in the directory named by the
179 * SBCL_HOME environment variable, then in a hardcoded default
180 * location. Returns a malloced copy of the core filename. */
184 char *sbcl_home = getenv("SBCL_HOME");
186 char *stem = "/sbcl.core";
189 if (!(sbcl_home && *sbcl_home)) sbcl_home = SBCL_HOME;
190 lookhere = (char *) calloc(strlen(sbcl_home) +
194 sprintf(lookhere, "%s%s", sbcl_home, stem);
195 core = copied_existing_filename_or_null(lookhere);
198 lose("can't find core file at %s\n", lookhere);
209 struct runtime_options *runtime_options;
213 main(int argc, char *argv[], char *envp[])
215 #ifdef LISP_FEATURE_WIN32
216 /* Exception handling support structure. Evil Win32 hack. */
217 struct lisp_exception_frame exception_frame;
220 /* the name of the core file we're to execute. Note that this is
221 * a malloc'ed string which should be freed eventually. */
223 char **sbcl_argv = 0;
224 os_vm_offset_t embedded_core_offset = 0;
225 char *runtime_path = 0;
227 /* other command line options */
228 boolean noinform = 0;
229 boolean end_runtime_options = 0;
231 lispobj initial_function;
232 const char *sbcl_home = getenv("SBCL_HOME");
235 block_blockable_signals();
237 setlocale(LC_ALL, "");
239 runtime_options = NULL;
241 /* Check early to see if this executable has an embedded core,
242 * which also populates runtime_options if the core has runtime
244 runtime_path = os_get_runtime_executable_path();
246 os_vm_offset_t offset = search_for_embedded_core(runtime_path);
248 embedded_core_offset = offset;
256 /* Parse our part of the command line (aka "runtime options"),
257 * stripping out those options that we handle. */
258 if (runtime_options != NULL) {
259 dynamic_space_size = runtime_options->dynamic_space_size;
260 thread_control_stack_size = runtime_options->thread_control_stack_size;
265 runtime_options = successful_malloc(sizeof(struct runtime_options));
267 while (argi < argc) {
268 char *arg = argv[argi];
269 if (0 == strcmp(arg, "--script")) {
270 /* This is both a runtime and a toplevel option. As a
271 * runtime option, it is equivalent to --noinform.
272 * This exits, and does not increment argi, so that
273 * TOPLEVEL-INIT sees the option. */
275 end_runtime_options = 1;
277 } else if (0 == strcmp(arg, "--noinform")) {
280 } else if (0 == strcmp(arg, "--core")) {
282 lose("more than one core file specified\n");
286 lose("missing filename for --core argument\n");
288 core = copied_string(argv[argi]);
291 } else if (0 == strcmp(arg, "--help")) {
292 /* I think this is the (or a) usual convention: upon
293 * seeing "--help" we immediately print our help
294 * string and exit, ignoring everything else. */
297 } else if (0 == strcmp(arg, "--version")) {
298 /* As in "--help" case, I think this is expected. */
301 } else if (0 == strcmp(arg, "--dynamic-space-size")) {
304 lose("missing argument for --dynamic-space-size");
306 dynamic_space_size = strtol(argv[argi++], 0, 0) << 20;
308 lose("argument to --dynamic-space-size is not a number");
309 # ifdef MAX_DYNAMIC_SPACE_END
310 if (!((DYNAMIC_SPACE_START < DYNAMIC_SPACE_START+dynamic_space_size) &&
311 (DYNAMIC_SPACE_START+dynamic_space_size <= MAX_DYNAMIC_SPACE_END)))
312 lose("specified --dynamic-space-size too large");
314 } else if (0 == strcmp(arg, "--control-stack-size")) {
317 lose("missing argument for --control-stack-size");
319 thread_control_stack_size = strtol(argv[argi++], 0, 0) << 20;
321 lose("argument to --control-stack-size is not a number");
322 } else if (0 == strcmp(arg, "--debug-environment")) {
324 printf("; Commandline arguments:\n");
326 printf("; %2d: \"%s\"\n", n, argv[n]);
330 printf(";\n; Environment:\n");
332 printf("; %2d: \"%s\"\n", n, ENVIRON[n]);
336 } else if (0 == strcmp(arg, "--end-runtime-options")) {
337 end_runtime_options = 1;
341 /* This option was unrecognized as a runtime option,
342 * so it must be a toplevel option or a user option,
343 * so we must be past the end of the runtime option
348 /* This is where we strip out those options that we handle. We
349 * also take this opportunity to make sure that we don't find
350 * an out-of-place "--end-runtime-options" option. */
352 char *argi0 = argv[argi];
354 /* (argc - argi) for the arguments, one for the binary,
355 and one for the terminating NULL. */
356 sbcl_argv = successful_malloc((2 + argc - argi) * sizeof(char *));
357 sbcl_argv[0] = argv[0];
358 while (argi < argc) {
359 char *arg = argv[argi++];
360 /* If we encounter --end-runtime-options for the first
361 * time after the point where we had to give up on
362 * runtime options, then the point where we had to
363 * give up on runtime options must've been a user
365 if (!end_runtime_options &&
366 0 == strcmp(arg, "--end-runtime-options")) {
367 lose("bad runtime option \"%s\"\n", argi0);
369 sbcl_argv[argj++] = arg;
375 /* Align down to multiple of page_table page size, and to the appropriate
376 * stack alignment. */
377 dynamic_space_size &= ~(PAGE_BYTES-1);
378 thread_control_stack_size &= ~(CONTROL_STACK_ALIGNMENT_BYTES-1);
380 /* Preserve the runtime options for possible future core saving */
381 runtime_options->dynamic_space_size = dynamic_space_size;
382 runtime_options->thread_control_stack_size = thread_control_stack_size;
384 /* KLUDGE: os_vm_page_size is set by os_init(), and on some
385 * systems (e.g. Alpha) arch_init() needs need os_vm_page_size, so
386 * it must follow os_init(). -- WHN 2000-01-26 */
392 /* If no core file was specified, look for one. */
394 core = search_for_core();
397 /* Make sure that SBCL_HOME is set and not the empty string,
398 unless loading an embedded core. */
399 if (!(sbcl_home && *sbcl_home) && embedded_core_offset == 0) {
400 char *envstring, *copied_core, *dir;
401 char *stem = "SBCL_HOME=";
402 copied_core = copied_string(core);
403 dir = dirname(copied_core);
404 envstring = (char *) calloc(strlen(stem) +
408 sprintf(envstring, "%s%s", stem, dir);
413 if (!noinform && embedded_core_offset == 0) {
418 #if defined(SVR4) || defined(__linux__)
422 define_var("nil", NIL, 1);
423 define_var("t", T, 1);
425 enable_lossage_handler();
429 initial_function = load_core_file(core, embedded_core_offset);
430 if (initial_function == NIL) {
431 lose("couldn't find initial function\n");
433 #ifdef LISP_FEATURE_HPUX
434 return_from_lisp_stub = (void *) ((char *)*((unsigned long *)
435 ((char *)initial_function - 1)) + 23);
438 gc_initialize_pointers();
440 arch_install_interrupt_handlers();
441 #ifndef LISP_FEATURE_WIN32
442 os_install_interrupt_handlers();
444 /* wos_install_interrupt_handlers(handler); */
445 wos_install_interrupt_handlers(&exception_frame);
448 /* Pass core filename and the processed argv into Lisp. They'll
449 * need to be processed further there, to do locale conversion.
452 posix_argv = sbcl_argv;
454 FSHOW((stderr, "/funcalling initial_function=0x%lx\n",
455 (unsigned long)initial_function));
456 #ifdef LISP_FEATURE_WIN32
458 This is experimental prerelease support for the Windows platform: use\n\
459 at your own risk. \"Your Kitten of Death awaits!\"\n");
463 create_initial_thread(initial_function);
464 lose("CATS. CATS ARE NICE.\n");