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. \n Perhaps some directories don't exist, or current executable ( \" %s \" ) is in a strange place. \n You 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 ) ;
}