#include <stdio.h>
#include <string.h>
+#include <ctype.h>
#ifndef LISP_FEATURE_WIN32
#include <libgen.h>
#endif
#include <sys/file.h>
#include <sys/param.h>
#include <sys/stat.h>
-#include <signal.h>
+#include "runtime.h"
#ifndef LISP_FEATURE_WIN32
#include <sched.h>
#endif
#include <time.h>
#endif
+#if !(defined(LISP_FEATURE_WIN32) && defined(LISP_FEATURE_SB_THREAD))
#include "signal.h"
+#endif
#include "runtime.h"
#include "vars.h"
sigint_init(void)
{
SHOW("entering sigint_init()");
- install_handler(SIGINT, sigint_handler);
+ install_handler(SIGINT, sigint_handler, 1);
SHOW("leaving sigint_init()");
}
\f
--userinit <filename> 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\
+ --disable-debugger Invoke sb-ext:disable-debugger.\n\
+ --noprint Run a Read-Eval Loop without printing results.\n\
+ --script [<filename>] Skip #! line, disable debugger, avoid verbosity.\n\
+ --quit Exit with code 0 after option processing.\n\
+ --non-interactive Sets both --quit and --disable-debugger.\n\
+Common toplevel options that are processed in order:\n\
+ --eval <form> Form to eval when processing this option.\n\
+ --load <filename> File to load when processing this option.\n\
\n\
User options are not processed by SBCL. All runtime options must\n\
appear before toplevel options, and all toplevel options must\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);
+"
+#ifdef LISP_FEATURE_WIN32
+"\n\
+WARNING: the Windows port is fragile, particularly for multithreaded\n\
+code. Unfortunately, the development team currently lacks the time\n\
+and resources this platform demands.\n\
+"
+#endif
+, SBCL_VERSION_STRING);
}
/* Look for a core file to load, first in the directory named by the
return search;
}
}
+ /* The above for-loop fails to process the last part of PATH if PATH does
+ * not end with ':'. We may consider appending an extra ':' to the end of
+ * SEARCH. -- houjingyi 2013-05-24 */
+ if (start != NULL && *start != '\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);
}
#endif /* LISP_FEATURE_WIN32 */
+size_t
+parse_size_arg(char *arg, char *arg_name)
+{
+ char *tail, *power_name;
+ size_t power, res;
+
+ res = strtoul(arg, &tail, 0);
+
+ if (arg == tail) {
+ lose("%s argument is not a number: %s", arg_name, arg);
+ } else if (tail[0]) {
+ int i, size;
+ power_name = copied_string(tail);
+ size = strlen(power_name);
+ for (i=0; i<size; i++)
+ power_name[i] = toupper(power_name[i]);
+ } else {
+ power = 20;
+ power_name = NULL;
+ }
+ if (power_name) {
+ if ((0==strcmp("KB", power_name)) ||
+ (0==strcmp("KIB", power_name))) {
+ power = 10;
+ } else if ((0==strcmp("MB", power_name)) ||
+ (0==strcmp("MIB", power_name))) {
+ power = 20;
+ } else if ((0==strcmp("GB", power_name)) ||
+ (0==strcmp("GIB", power_name))) {
+ power = 30;
+ } else {
+ lose("%s argument has an unknown suffix: %s", arg_name, tail);
+ }
+ free(power_name);
+ }
+ if ((res <= 0) ||
+ (res >= (SIZE_MAX >> power))) {
+ lose("%s argument is out of range: %s", arg_name, arg);
+ }
+ res <<= power;
+ return res;
+}
+
char **posix_argv;
char *core_string;
struct runtime_options *runtime_options;
char *saved_runtime_path = NULL;
+#if defined(LISP_FEATURE_WIN32) && defined(LISP_FEATURE_SB_THREAD)
+void pthreads_win32_init();
+#endif
+
+void print_locale_variable(const char *name)
+{
+ char *value = getenv(name);
+
+ if (value) {
+ fprintf(stderr, "\n %s=%s", name, value);
+ }
+}
+
+void setup_locale()
+{
+ if(setlocale(LC_ALL, "") == NULL) {
+#ifndef LISP_FEATURE_WIN32
+
+ fprintf(stderr, "WARNING: Setting locale failed.\n");
+ fprintf(stderr, " Check the following variables for correct values:");
+
+ if (setlocale(LC_CTYPE, "") == NULL) {
+ print_locale_variable("LC_ALL");
+ print_locale_variable("LC_CTYPE");
+ print_locale_variable("LANG");
+ }
+
+ if (setlocale(LC_MESSAGES, "") == NULL) {
+ print_locale_variable("LC_MESSAGES");
+ }
+ if (setlocale(LC_COLLATE, "") == NULL) {
+ print_locale_variable("LC_COLLATE");
+ }
+ if (setlocale(LC_MONETARY, "") == NULL) {
+ print_locale_variable("LC_MONETARY");
+ }
+ if (setlocale(LC_NUMERIC, "") == NULL) {
+ print_locale_variable("LC_NUMERIC");
+ }
+ if (setlocale(LC_TIME, "") == NULL) {
+ print_locale_variable("LC_TIME");
+ }
+ fprintf(stderr, "\n");
+
+#endif
+ }
+}
+
\f
int
main(int argc, char *argv[], char *envp[])
lispobj initial_function;
const char *sbcl_home = getenv("SBCL_HOME");
+#if defined(LISP_FEATURE_WIN32) && defined(LISP_FEATURE_SB_THREAD)
+ os_preinit();
+ pthreads_win32_init();
+#endif
+
interrupt_init();
block_blockable_signals(0, 0);
- setlocale(LC_ALL, "");
-
runtime_options = NULL;
/* Save the argv[0] derived runtime path in case
core = (runtime_path ? runtime_path :
copied_string(saved_runtime_path));
} else {
- free(runtime_path);
+ if (runtime_path)
+ free(runtime_path);
}
}
++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");
+ dynamic_space_size = parse_size_arg(argv[argi++],
+ "--dynamic-space-size");
# 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("specified --dynamic-space-size too large");
+ MAX_DYNAMIC_SPACE_END))) {
+ char* suffix = "";
+ char* size = argv[argi-1];
+ if (!strchr(size, 'B') && !strchr(size, 'b')) {
+ suffix = " [MB]";
+ }
+ lose("--dynamic-space-size argument %s%s is too large, max %lu KB",
+ size, suffix,
+ (MAX_DYNAMIC_SPACE_END-DYNAMIC_SPACE_START) / 1024);
+ }
# 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");
+ thread_control_stack_size = parse_size_arg(argv[argi++], "--control-stack-size");
} else if (0 == strcmp(arg, "--debug-environment")) {
int n = 0;
printf("; Commandline arguments:\n");
end_runtime_options = 1;
++argi;
break;
+ } else if (0 == strcmp(arg, "--merge-core-pages")) {
+ ++argi;
+ merge_core_pages = 1;
+ } else if (0 == strcmp(arg, "--no-merge-core-pages")) {
+ ++argi;
+ merge_core_pages = 0;
+ } else if (0 == strcmp(arg, "--default-merge-core-pages")) {
+ ++argi;
+ merge_core_pages = -1;
} else {
/* This option was unrecognized as a runtime option,
* so it must be a toplevel option or a user option,
/* 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);
+ dynamic_space_size &= ~(sword_t)(PAGE_BYTES-1);
+#ifdef LISP_FEATURE_GENCGC
+ dynamic_space_size &= ~(sword_t)(GENCGC_CARD_BYTES-1);
+#endif
+ thread_control_stack_size &= ~(sword_t)(CONTROL_STACK_ALIGNMENT_BYTES-1);
/* Preserve the runtime options for possible future core saving */
runtime_options->dynamic_space_size = dynamic_space_size;
* 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);
+ dyndebug_init(); /* after os_init: do not print output before execve */
arch_init();
gc_init();
validate();
+ setup_locale();
+
/* If no core file was specified, look for one. */
if (!core) {
core = search_for_core();
fflush(stdout);
}
+ if (embedded_core_offset == 0) {
+ /* Here we make a last attempt at recognizing an embedded core,
+ * so that a file with an embedded core is a valid argument to
+ * --core. We take care that any decisions on special behaviour
+ * (suppressed banner, embedded options) have already been made
+ * before we reach this block, so that there is no observable
+ * difference between "embedded" and "bare" images given to
+ * --core. */
+ os_vm_offset_t offset = search_for_embedded_core(core);
+ if (offset != -1)
+ embedded_core_offset = offset;
+ }
+
#if defined(SVR4) || defined(__linux__) || defined(__NetBSD__)
tzset();
#endif
if (initial_function == NIL) {
lose("couldn't find initial function\n");
}
+#ifdef LISP_FEATURE_SB_DYNAMIC_CORE
+ os_link_runtime();
+#endif
#ifdef LISP_FEATURE_HPUX
/* -1 = CLOSURE_FUN_OFFSET, 23 = SIMPLE_FUN_CODE_OFFSET, we are
* not in LANGUAGE_ASSEMBLY so we cant reach them. */
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");
+ lose("unexpected return from initial thread in main()\n");
return 0;
}