stk/Src/toplevel.c

383 lines
11 KiB
C
Raw Normal View History

1996-09-27 06:29:02 -04:00
/*
*
* t o p l e v e l . c -- The REP loop
*
1998-04-10 06:59:06 -04:00
* Copyright <EFBFBD> 1993-1998 Erick Gallesio - I3S-CNRS/ESSI <eg@unice.fr>
1996-09-27 06:29:02 -04:00
*
*
* Permission to use, copy, and/or distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that both the above copyright notice and this permission notice appear in
* all copies and derived works. Fees for distribution or use of this
* software or derived works may only be charged with express written
* permission of the copyright holder.
* This software is provided ``as is'' without express or implied warranty.
*
* This software is a derivative work of other copyrighted softwares; the
* copyright notices of these softwares are placed in the file COPYRIGHTS
*
1998-04-30 07:04:33 -04:00
* $Id: toplevel.c 1.5 Mon, 27 Apr 1998 08:44:17 +0000 eg $
1996-09-27 06:29:02 -04:00
*
* Author: Erick Gallesio [eg@kaolin.unice.fr]
* Creation date: 6-Apr-1994 14:46
1998-04-30 07:04:33 -04:00
* Last file update: 26-Apr-1998 18:41
1996-09-27 06:29:02 -04:00
*/
#include "stk.h"
#include "gc.h"
1998-04-10 06:59:06 -04:00
#include "module.h"
1996-09-27 06:29:02 -04:00
/* The cell representing NIL */
static struct obj VNIL = {0, tc_nil};
static void print_banner(void)
{
1998-04-10 06:59:06 -04:00
if (STk_lookup_variable(PRINT_BANNER, NIL) != Ntruth){
1996-09-27 06:29:02 -04:00
fprintf(STk_stderr, "Welcome to the STk interpreter version %s [%s]\n",
STK_VERSION, MACHINE);
1998-04-10 06:59:06 -04:00
fprintf(STk_stderr, "Copyright <20> 1993-1998 Erick Gallesio - ");
1996-09-27 06:29:02 -04:00
fprintf(STk_stderr, "I3S - CNRS / ESSI <eg@unice.fr>\n");
}
}
static void weird_dirs(char *argv0)
{
1998-04-10 06:59:06 -04:00
STk_panic("Could not find the directory where STk was installed.\nPerhaps some directories don't exist, or current executable (\"%s\") is in a strange place.\nYou should consider to set the \"STK_LIBRARY\" shell variable.", argv0);
1996-09-27 06:29:02 -04:00
}
static void load_init_file(void)
{
/* Try to load init.stk in "." and, if not present, in $STK_LIBRARY/STk */
char init_file[] = "init.stk";
char file[2*MAX_PATH_LENGTH];
sprintf(file, "./%s", init_file);
1998-04-10 06:59:06 -04:00
if (STk_load_file(file, FALSE, STk_selected_module) == Truth) return;
1996-09-27 06:29:02 -04:00
sprintf(file, "%s/STk/%s", STk_library_path, init_file);
1998-04-10 06:59:06 -04:00
if (STk_load_file(file, FALSE, STk_selected_module) == Ntruth)
1996-09-27 06:29:02 -04:00
weird_dirs(STk_Argv0);
}
1998-04-10 06:59:06 -04:00
static void load_user_init_file(void)
{
/* Try to load .stkrc in "." and, if not present, in $HOME */
char init_file[] = ".stkrc";
char file[2*MAX_PATH_LENGTH];
char *s;
sprintf(file, "./%s", init_file);
if (STk_load_file(file, FALSE, STk_selected_module) == Truth) return;
if ((s = getenv("HOME")) != NULL) {
sprintf(file, "%s/%s", s, init_file);
STk_load_file(file, FALSE, STk_selected_module);
}
}
1996-09-27 06:29:02 -04:00
static void init_library_path(char *argv0)
{
char *s;
STk_library_path = "";
if (s = getenv("STK_LIBRARY")) {
/* Initialize STk_library_path with the content of STK_LIBRARY
* shell variable.
* Make a copy of environment variable (copy is necessary for
* images files)
*/
STk_library_path = (char *) must_malloc(strlen(s) + 1);
strcpy(STk_library_path, s);
}
else {
SCM canonical_argv0 = STk_resolve_link(argv0, 0);
if (canonical_argv0 != Ntruth) {
/* STk_library must be set to the parent directory of the executable */
char *s, *e;
s = CHARS(canonical_argv0);
e = s + strlen(s) - 1;
while (e > s && !ISDIRSEP(*e)) e -= 1; /* delete exec name */
e -= 1;
while (e > s && !ISDIRSEP(*e)) e -= 1; /* delete directory name */
*e = '\0';
STk_library_path = must_malloc(strlen(s) + 1);
strcpy(STk_library_path, s);
}
else weird_dirs(argv0);
}
}
static void init_interpreter(void)
{
#ifdef WIN32
/* First initialize the IO system, to have a console on Windows */
STk_init_io();
#endif
/* Remember if we are running the stk or snow interpreter */
#ifdef USE_TK
STk_snow_is_running = FALSE;
#else
STk_snow_is_running = TRUE;
#endif
/* Global variables to initialize */
NIL = &VNIL;
STk_tkbuffer = (char *) must_malloc(TKBUFFERN+1);
STk_interactivep = STk_arg_interactive ||isatty(fileno(STk_stdin));
1998-04-10 06:59:06 -04:00
STk_is_safe = 0;
1996-09-27 06:29:02 -04:00
/* Initialize GC */
STk_init_gc();
/* Initialize symbol & keyword tables */
STk_initialize_symbol_table();
STk_initialize_keyword_table();
/*
1998-04-10 06:59:06 -04:00
* Define some scheme objects used by the interpreter
* and protect them against GC
*/
1996-09-27 06:29:02 -04:00
NEWCELL(UNDEFINED, tc_undefined); STk_gc_protect(&UNDEFINED);
NEWCELL(UNBOUND, tc_unbound); STk_gc_protect(&UNBOUND);
NEWCELL(Truth, tc_boolean); STk_gc_protect(&Truth);
NEWCELL(Ntruth, tc_boolean); STk_gc_protect(&Ntruth);
Sym_lambda = Intern("lambda"); STk_gc_protect(&Sym_lambda);
Sym_quote = Intern("quote"); STk_gc_protect(&Sym_quote);
Sym_imply = Intern("=>"); STk_gc_protect(&Sym_imply);
Sym_dot = Intern("."); STk_gc_protect(&Sym_dot);
Sym_debug = Intern(DEBUG_MODE); STk_gc_protect(&Sym_debug);
Sym_else = Intern("else"); STk_gc_protect(&Sym_else);
Sym_quasiquote = Intern("quasiquote"); STk_gc_protect(&Sym_quasiquote);
Sym_unquote = Intern("unquote"); STk_gc_protect(&Sym_unquote);
Sym_unq_splicing = Intern("unquote-splicing"); STk_gc_protect(&Sym_unq_splicing);
Sym_break = Intern("break"); STk_gc_protect(&Sym_break);
STk_globenv = STk_makeenv(NIL, 1); STk_gc_protect(&STk_globenv);
/* GC_VERBOSE and REPORT_ERROR must ABSOLUTLY initialized before any GC occurs
* Otherwise, they will be allocated during a GC and this lead to an infinite
* loop
*/
1998-04-10 06:59:06 -04:00
STk_define_variable(GC_VERBOSE, Ntruth, NIL);
STk_define_variable(REPORT_ERROR, NIL, NIL);
STk_define_variable(LOAD_SUFFIXES, NIL, NIL);
STk_define_variable(LOAD_PATH, NIL, NIL);
STk_define_variable(LOAD_VERBOSE, Ntruth, NIL);
1996-09-27 06:29:02 -04:00
1998-04-10 06:59:06 -04:00
/* Initialize module system */
STk_init_modules();
1996-09-27 06:29:02 -04:00
/* Initialize the path of the library */
init_library_path(STk_Argv0);
/* Initialize *eval-hook* */
STk_init_eval_hook();
/* Initialize standard ports */
STk_init_standard_ports();
/* Initialize Scheme primitives */
STk_init_primitives();
/* Initialize signal table */
STk_init_signal();
/* initialize STk_wind_stack and protect it against garbage colection */
STk_wind_stack = NIL; STk_gc_protect(&STk_wind_stack);
}
static void finish_initialisation(void)
{
/*
* Initialize user extensions
*/
STk_user_init();
/*
* See if we have the '-file' option
*/
if (STk_arg_file) {
1998-04-10 06:59:06 -04:00
SCM res;
1996-09-27 06:29:02 -04:00
STk_set_signal_handler(STk_makeinteger(SIGINT), Truth);
STk_interactivep = 0;
1998-04-10 06:59:06 -04:00
if (STk_load_file(STk_arg_file, FALSE, STk_selected_module) == Ntruth)
STk_panic("Cannot open file \"%s\".", STk_arg_file);
1996-09-27 06:29:02 -04:00
#ifdef USE_TK
if (Tk_initialized) Tk_MainLoop();
#endif
exit(0);
}
1998-04-30 07:04:33 -04:00
1996-09-27 06:29:02 -04:00
/*
* See if we've used the '-interactive' option; if so,
* - unbufferize stdout and stderr so that the interpreter can
* be used with Emacs and
* - print the STk banner
1998-04-30 07:04:33 -04:00
* - set the input handler
1996-09-27 06:29:02 -04:00
*/
if (STk_interactivep) {
static char *out, *err;
out = STk_line_bufferize_io(STk_stdout);
err = STk_line_bufferize_io(STk_stderr);
print_banner();
1998-04-30 07:04:33 -04:00
#if (defined(USE_TK) && !defined(WIN32))
/* Set up a handler for characters coming from stdin */
Tcl_CreateFileHandler(fileno(STk_stdin),
TCL_READABLE,
(Tk_FileProc *) STk_StdinProc,
(ClientData) NULL);
#endif
1996-09-27 06:29:02 -04:00
}
fflush(stdout);
/*
* Manage -load option
*/
if (STk_arg_load) {
1998-04-10 06:59:06 -04:00
STk_load_file(STk_arg_load, TRUE, STk_selected_module);
1996-09-27 06:29:02 -04:00
#ifdef USE_TK
if (Tk_initialized) Tcl_GlobalEval(STk_main_interp, "(update)");
#endif
}
}
static void repl_loop(void)
{
/* The print/eval/read loop */
for( ; ; ) {
SCM x;
1998-04-10 06:59:06 -04:00
SCM env = MOD_ENV(STk_selected_module);
1996-09-27 06:29:02 -04:00
if (STk_interactivep) {
1998-04-10 06:59:06 -04:00
if (STk_internal_eval_string("(catch (repl-display-prompt (current-module)))",
0, env) == Truth)
fprintf(STk_stderr, "STk> ");
1996-09-27 06:29:02 -04:00
fflush(STk_stderr);
fflush(STk_stdout); /* This is for Ilisp users */
}
if (EQ(x=STk_readf(STk_stdin, FALSE), STk_eof_object)) return;
1998-04-10 06:59:06 -04:00
x = STk_eval(x, env);
1996-09-27 06:29:02 -04:00
if (STk_dumped_core) {
/*
* When restoring an image we arrive here x contains the result of applying
* the saved continuation.
*/
STk_dumped_core = 0;
longjmp(*Top_jmp_buf, JMP_RESTORE);
}
else {
1998-04-10 06:59:06 -04:00
if (STk_interactivep) {
STk_define_variable("*repl-result*", x, NIL);
if (STk_internal_eval_string("(catch (repl-display-result *repl-result*))",
0, env) == Truth) {
STk_print(x, STk_curr_oport, WRT_MODE);
Putc('\n', STk_stdout);
}
}
1996-09-27 06:29:02 -04:00
}
}
}
static void repl_driver(int argc, char **argv)
{
static int k;
static char **new_argv;
new_argv = STk_process_argc_argv(argc, argv);
if (STk_arg_image) {
STk_save_unix_args_and_environment(argc, argv);
STk_restore_image(STk_arg_image);
}
else {
/* Normal initialisation */
STk_reset_eval_stack();
}
/* Point where we come back on errors, image restoration, ... */
k = setjmp(*Top_jmp_buf);
Error_context = ERR_OK;
STk_sigint_counter = 0;
STk_control_C = 0;
switch (k) {
case 0: init_interpreter();
STk_initialize_scheme_args(new_argv);
load_init_file();
1998-04-10 06:59:06 -04:00
/* And now set the default module to the global one */
STk_initialize_stk_module();
1996-09-27 06:29:02 -04:00
#ifdef USE_TK
# ifdef WIN32
if (!STk_arg_no_tk)
Tk_main(STk_arg_sync,
STk_arg_name,
STk_arg_file,
"localhost:0",
STk_arg_geometry);
# else
if (!STk_arg_Xdisplay)
STk_arg_Xdisplay = getenv("DISPLAY");
if (!STk_arg_no_tk && STk_arg_Xdisplay)
Tk_main(STk_arg_sync,
STk_arg_name,
STk_arg_file,
STk_arg_Xdisplay,
STk_arg_geometry);
# endif
#endif
1998-04-10 06:59:06 -04:00
load_user_init_file();
1996-09-27 06:29:02 -04:00
finish_initialisation();
break;
case JMP_RESTORE: STk_restore_unix_args_and_environment(&argc, &argv);
/* Process another time args since we have lost them ! */
new_argv = STk_process_argc_argv(argc, argv);
STk_initialize_scheme_args(new_argv);
#ifdef USE_TK
if (!STk_arg_no_tk && (STk_arg_Xdisplay||getenv("DISPLAY")))
Tk_main(STk_arg_sync,
STk_arg_name,
STk_arg_file,
STk_arg_Xdisplay,
STk_arg_geometry);
#endif
finish_initialisation();
break;
case JMP_THROW:
case JMP_ERROR: break;
}
repl_loop();
if (STk_interactivep) fprintf(STk_stderr, "Bye.\n");
STk_quit_interpreter(UNBOUND);
}
/******************************************************************************
*
* Toplevel
*
******************************************************************************/
void STk_toplevel(int argc, char **argv)
{
SCM stack_start; /* Unused variable. Its the first stack allocated variable */
STk_stack_start_ptr = &stack_start;
repl_driver(argc, argv);
}