/* "scm.c" Initialization and interrupt code. * Copyright (C) 1990-2006 Free Software Foundation, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, see * . */ /* Author: Aubrey Jaffer */ #ifdef PLAN9 # define signal(a,b) 0/* no signals in Plan 9 */ #else # include #endif #include "scm.h" #include "patchlvl.h" #ifdef _WIN32 # include #endif #ifdef __IBMC__ # include #endif /* See scm.h for definition of P */ #ifndef STDC_HEADERS int alarm P((unsigned int)); int pause P((void)); unsigned int sleep P((unsigned int seconds)); char *getenv P((const char *name)); int system P((const char *)); #else /* added by Denys Duchier */ # ifdef SVR4 # include # endif # ifdef __NetBSD__ # include # endif # ifdef __OpenBSD__ # include # endif # ifdef __amigaos__ # include # endif #endif void init_sbrk P((void)); void init_dynl P((void)); void init_edline P((void)); void init_eval P((void)); void init_features P((void)); void init_gsubr P((void)); void init_io P((void)); void init_ioext P((void)); void init_posix P((void)); void init_ramap P((void)); void init_record P((void)); void init_rgx P((void)); void init_rope P((void)); void init_repl P((int iverbose)); void init_sc2 P((void)); void init_scl P((void)); void init_signals P((void)); void init_socket P((void)); void init_subrs P((void)); void init_tables P((void)); void init_time P((void)); void init_types P((void)); void init_unif P((void)); void init_debug P((void)); void reset_time P((void)); void final_repl P((void)); void init_banner() { fputs("SCM version "SCMVERSION", Copyright (C) 1990-2006 \ Free Software Foundation.\n\ SCM comes with ABSOLUTELY NO WARRANTY; for details type `(terms)'.\n\ This is free software, and you are welcome to redistribute it\n\ under certain conditions; type `(terms)' for details.\n", stderr); } void scm_init_INITS() { if (!dumped) { #ifdef INITS INITS; /* call initialization of extension files */ #endif } } void (*init_user_scm) P((void)); SCM scm_init_extensions() { #ifdef COMPILED_INITS COMPILED_INITS; /* initialize statically linked add-ons */ #endif init_user_scm(); #ifndef HAVE_DYNL /* No more init_*s, so trim gra[]s */ scm_trim_gra(&subrs_gra); scm_trim_gra(&ptobs_gra); scm_trim_gra(&smobs_gra); scm_trim_gra(&finals_gra); #endif return UNSPECIFIED; } #if (__TURBOC__==1) # define signal ssignal /* Needed for TURBOC V1.0 */ #endif /* SIGRETTYPE is the type that signal handlers return. See */ #ifdef RETSIGTYPE # define SIGRETTYPE RETSIGTYPE #else # ifdef STDC_HEADERS # if (__TURBOC__==1) # define SIGRETTYPE int # else # define SIGRETTYPE void # endif # else # ifdef linux # define SIGRETTYPE void # else # define SIGRETTYPE int # endif # endif #endif #ifdef vms # ifdef __GNUC__ # define SIGRETTYPE int # endif #endif #define SIGNAL_BASE HUP_SIGNAL /* PROF_SIGNAL appears below because it is the last signal defined in scm.h and in errmsgs in repl.c */ static struct { int signo; SIGRETTYPE (*osig)(); SIGRETTYPE (*nsig)(); } sigdesc[PROF_SIGNAL - SIGNAL_BASE + 1]; #define NUM_SIGNALS (sizeof(sigdesc)/sizeof(sigdesc[0])) void process_signals() { int i, n; unsigned long mask = 1L; /* printf("process_signals; output_deferred=%d\n", output_deferred); fflush(stdout); */ if (output_deferred) { output_deferred = 0; /* if (NIMP(sys_errp) && OPOUTPORTP(sys_errp)) lfflush(sys_errp); */ } for (n = 0; SIG_deferred && n < NUM_SIGNALS; n++) { if (SIG_deferred & mask) { i = n + SIGNAL_BASE; SIG_deferred &= ~mask; if (i != handle_it(i)) wta(UNDEFINED, (char *)i, ""); } mask <<= 1; } if (gc_hook_pending) { gc_hook_pending = 0; scm_gc_hook(); } deferred_proc = 0; } #ifdef WINSIGNALS SCM_EXPORT HANDLE scm_hMainThread; HANDLE scm_hMainThread; static SIGRETTYPE scmable_signal(int sig); # ifdef __MINGW32__ static void sigintstub(); __asm(".globl _sigintstub"); __asm("_sigintstub:"); __asm(" pushl $2"); __asm(" call _scmable_signal"); __asm(" addl $4, %esp"); __asm(" popal"); __asm(" popfl"); __asm(" ret"); # else /* works for Microsoft VC++ */ static __declspec(naked) void sigintstub() { scmable_signal(SIGINT); __asm popad; __asm popfd; __asm ret; } # endif /* def __MINGW32__ */ /* control-c signal handler */ SIGRETTYPE win32_sigint(int sig) { CONTEXT ctx; DWORD *Stack; if (-1 == SuspendThread(scm_hMainThread)) return; ctx.ContextFlags = CONTEXT_FULL; if (0 == GetThreadContext(scm_hMainThread, &ctx)) { ResumeThread(scm_hMainThread); return; } Stack = (DWORD *)ctx.Esp; *--Stack = ctx.Eip; *--Stack = ctx.EFlags; *--Stack = ctx.Eax; *--Stack = ctx.Ecx; *--Stack = ctx.Edx; *--Stack = ctx.Ebx; *--Stack = ctx.Esp; *--Stack = ctx.Ebp; *--Stack = ctx.Esi; *--Stack = ctx.Edi; ctx.Esp = (DWORD)Stack; ctx.Eip = (DWORD)sigintstub; SetThreadContext(scm_hMainThread, &ctx); ResumeThread(scm_hMainThread); } #endif /*def WINSIGNALS*/ static char s_unksig[] = "unknown signal"; static SIGRETTYPE err_signal(sig) int sig; { int i = NUM_SIGNALS; signal(sig, err_signal); while (i--) if (sig == sigdesc[i].signo) break; wta(MAKINUM(sig), (i < 0 ? s_unksig : (char *)(i + SIGNAL_BASE)), ""); } static SIGRETTYPE scmable_signal(sig) int sig; { int oerr = errno; int i = NUM_SIGNALS; while (i--) if (sig == sigdesc[i].signo) break; ASRTER(i >= 0, MAKINUM(sig), s_unksig, ""); #ifdef WINSIGNALS if (SIGINT == sig) signal(sig, win32_sigint); else #endif signal(sig, scmable_signal); if (ints_disabled) { deferred_proc = process_signals; SIG_deferred |= (1L << i); } else { #ifdef SIG_UNBLOCK sigset_t set; sigemptyset(&set); sigaddset(&set, sig); sigprocmask(SIG_UNBLOCK, &set, 0L); #endif SIG_deferred &= ~(1L << i); i += SIGNAL_BASE; if (i != handle_it(i)) { errno = oerr; wta(UNDEFINED, (char *)i, ""); } } errno = oerr; } /* If doesn't have SIGFPE, disable FLOATS for the rest of this file. */ #ifndef SIGFPE # undef FLOATS #endif #ifdef macintosh # undef SIGALRM #endif #ifdef atarist # undef SIGALRM /* only available via MiNT libs */ #endif #ifdef __HIGHC__ # undef SIGALRM #endif #ifdef LACK_SETITIMER # undef SIGPROF #endif #ifdef SIGALRM static char s_alarm[] = "alarm"; SCM lalarm(i) SCM i; { unsigned int j; ASRTER(INUMP(i) && (INUM(i) >= 0), i, ARG1, s_alarm); SYSCALL(j = alarm(INUM(i));); return MAKINUM(j); } # ifdef SIGPROF # include static char s_setitimer[] = "setitimer"; static struct {SCM sym; int which;} setitimer_tab[3] = { {UNDEFINED, 0}, {UNDEFINED, 0}, {UNDEFINED, 0}}; /* VALUE and INTERVAL are milliseconds */ SCM scm_setitimer(which, value, interval) SCM which, value, interval; { struct itimerval tval, oval; int w; int i = sizeof(setitimer_tab)/sizeof(setitimer_tab[0]); while (i--) { if (which==setitimer_tab[i].sym) { w = setitimer_tab[i].which; if (BOOL_T==value) SYSCALL(w = getitimer(w, &oval);); else { if (BOOL_F==value) value = INUM0; ASRTER(INUMP(value), value, ARG2, s_setitimer); if (BOOL_F==interval) interval = INUM0; ASRTER(INUMP(interval), interval, ARG3, s_setitimer); tval.it_value.tv_sec = INUM(value) / 1000; tval.it_value.tv_usec = (INUM(value) % 1000)*1000; tval.it_interval.tv_sec = INUM(interval) / 1000; tval.it_interval.tv_usec = (INUM(interval) % 1000)*1000; SYSCALL(w = setitimer(w, &tval, &oval);); } if (w) return BOOL_F; return cons2(MAKINUM(oval.it_value.tv_usec/1000 + oval.it_value.tv_sec*1000), MAKINUM(oval.it_interval.tv_usec/1000 + oval.it_interval.tv_sec*1000), EOL); } } return BOOL_F; } # endif # ifndef AMIGA SCM l_pause() { pause(); return UNSPECIFIED; } # endif #endif /* SIGALRM */ #ifdef _WIN32 # include #endif #ifdef __IBMC__ # include #endif #ifndef AMIGA # ifndef _Windows static char s_sleep[] = "sleep"; SCM l_sleep(i) SCM i; { unsigned int j = 0; ASRTER(INUMP(i) && (INUM(i) >= 0), i, ARG1, s_sleep); # ifdef __HIGHC__ SYSCALL(sleep(INUM(i));); # else # ifdef _WIN32 Sleep(INUM(i) * 1000); # else # ifdef __IBMC__ DosSleep(INUM(i) * 1000); # else SYSCALL(j = sleep(INUM(i));); # endif # endif # endif return MAKINUM(j); } # endif #endif #ifdef PLAN9 int raise(sig) int sig; { char *str; int len; char ibuf[12]; char pidbuf[32]; int fd; int res; sprint(ibuf, "%ld", sig); len = strlen(ibuf); sprint(pidbuf, "/proc/%d/note", getpid()); fd = open(pidbuf, OWRITE); res = write(fd, ibuf, len); close (fd); return res==len; } #endif #ifndef _WIN32 # ifndef sun # ifndef THINK_C # ifndef __TURBOC__ # ifdef STDC_HEADERS # ifndef __MWERKS__ # ifndef __IBMC__ # ifndef PLAN9 # define LACK_RAISE # endif # endif # endif # endif # endif # endif # endif #endif /* int raise P((int sig)); */ static char s_raise[] = "raise"; SCM l_raise(sig) SCM sig; { ASRTER(INUMP(sig), sig, ARG1, s_raise); #ifdef LACK_RAISE # ifdef vms return MAKINUM(gsignal((int)INUM(sig))); # else return kill(getpid (), (int)INUM(sig)) ? BOOL_F : BOOL_T; # endif #else return raise((int)INUM(sig)) ? BOOL_F : BOOL_T; #endif } #ifdef TICKS unsigned int tick_count = 0, ticken = 0; SCM *loc_tick_signal; void tick_signal() { if (ticken && NIMP(*loc_tick_signal)) { ticken = 0; apply(*loc_tick_signal, EOL, EOL); } } static char s_ticks[] = "ticks"; SCM lticks(i) SCM i; { SCM j = ticken ? tick_count : 0; if (!UNBNDP(i)) ticken = tick_count = INUM(i); return MAKINUM(j); } #endif #ifdef SIGPIPE static SIGRETTYPE (*oldpipe) (); #endif int case_sensitize_symbols = 0; /* set to 8 to read case-sensitive symbols */ int dumped = 0; /* Is this an invocation of unexec exe? */ #ifdef SHORT_ALIGN typedef short STACKITEM; #else typedef long STACKITEM; #endif /* See scm.h for definition of P */ void init_storage P((STACKITEM *stack_start_ptr, long init_heap_size)); void init_scm(iverbose, buf0stdin, init_heap_size) int iverbose; int buf0stdin; long init_heap_size; { STACKITEM i; if (2 <= iverbose) init_banner(); if (!dumped) { init_types(); init_tables(); init_storage(&i, init_heap_size); /* CONT(rootcont)->stkbse gets set here */ } else { /* The streams when the program was dumped need to be reset. */ SETSTREAM(def_inp, stdin); SETSTREAM(def_outp, stdout); SETSTREAM(def_errp, stderr); } if (buf0stdin) SCM_PORTFLAGS(def_inp) |= BUF0; else SCM_PORTFLAGS(def_inp) &= ~BUF0; if (!dumped) { init_features(); init_subrs(); init_scl(); init_unif(); init_time(); init_io(); init_eval(); /* call to scm_evstr switches INTS discipline */ init_debug(); init_rope(); init_repl(iverbose); } else reset_time(); #ifdef HAVE_DYNL /* init_dynl() must check dumped to avoid redefining subrs */ init_dynl(); #endif } static void init_sig1(scm_err, signo, handler) int scm_err; int signo; SIGRETTYPE (*handler)(); { int i = scm_err - SIGNAL_BASE; ASRTER(i < NUM_SIGNALS, MAKINUM(i), OUTOFRANGE, "init_sig1"); sigdesc[i].signo = signo; sigdesc[i].nsig = handler; sigdesc[i].osig = signal(signo, handler); } void init_signals() { #ifdef WINSIGNALS init_sig1(INT_SIGNAL, SIGINT, win32_sigint); #else # ifdef SIGINT init_sig1(INT_SIGNAL, SIGINT, scmable_signal); # endif #endif #ifdef SIGHUP init_sig1(HUP_SIGNAL, SIGHUP, scmable_signal); #endif #ifdef FLOATS init_sig1(FPE_SIGNAL, SIGFPE, err_signal); #endif #ifdef SIGBUS init_sig1(BUS_SIGNAL, SIGBUS, err_signal); #endif #ifdef SIGSEGV /* AMIGA lacks! */ init_sig1(SEGV_SIGNAL, SIGSEGV, err_signal); #endif #ifdef SIGALRM alarm(0); /* kill any pending ALRM interrupts */ init_sig1(ALRM_SIGNAL, SIGALRM, scmable_signal); # ifdef SIGPROF init_sig1(PROF_SIGNAL, SIGPROF, scmable_signal); # endif # ifdef SIGVTALRM init_sig1(VTALRM_SIGNAL, SIGVTALRM, scmable_signal); # endif #endif #ifdef SIGPIPE oldpipe = signal(SIGPIPE, SIG_IGN); #endif #ifdef ultrix siginterrupt(SIGINT, 1); siginterrupt(SIGALRM, 1); siginterrupt(SIGHUP, 1); siginterrupt(SIGPIPE, 1); #endif /* ultrix */ } /* This is used in preparation for a possible fork(). Ignore all signals before the fork so that child will catch only if it establishes a handler */ void ignore_signals() { int i = NUM_SIGNALS; #ifdef ultrix siginterrupt(SIGINT, 0); siginterrupt(SIGALRM, 0); siginterrupt(SIGHUP, 0); siginterrupt(SIGPIPE, 0); #endif /* ultrix */ while (i--) if (sigdesc[i].signo) signal(sigdesc[i].signo, SIG_DFL); /* Some documentation claims that ALRMs are cleared accross forks. If this is not always true then the value returned by alarm(0) will have to be saved and unignore_signals() will have to reinstate it. */ /* This code should be necessary only if the forked process calls alarm() without establishing a handler: */ #ifdef SIGALRM /* oldalrm = signal(SIGALRM, SIG_DFL); */ #endif /* These flushes are per warning in man page on fork(). */ fflush(stdout); fflush(stderr); #ifdef SIG_UNBLOCK { sigset_t set; sigfillset(&set); sigprocmask(SIG_UNBLOCK, &set, 0L); } #endif } void unignore_signals() { int i = NUM_SIGNALS; while (i--) if (sigdesc[i].signo) signal(sigdesc[i].signo, sigdesc[i].nsig); #ifdef ultrix siginterrupt(SIGINT, 1); siginterrupt(SIGALRM, 1); siginterrupt(SIGHUP, 1); siginterrupt(SIGPIPE, 1); #endif /* ultrix */ } void restore_signals() { int i; #ifdef ultrix siginterrupt(SIGINT, 0); siginterrupt(SIGALRM, 0); siginterrupt(SIGHUP, 0); siginterrupt(SIGPIPE, 0); #endif /* ultrix */ #ifdef SIGALRM # ifndef SIGPROF alarm(0); /* kill any pending ALRM interrupts */ # else i = sizeof(setitimer_tab)/sizeof(setitimer_tab[0]); while (i--) if (NIMP(setitimer_tab[i].sym)) scm_setitimer(setitimer_tab[i].sym, BOOL_F, BOOL_F); # endif #endif i = NUM_SIGNALS; while (i--) if (sigdesc[i].signo) signal(sigdesc[i].signo, sigdesc[i].osig); #ifdef SIGPIPE oldpipe = signal(SIGPIPE, SIG_IGN); #endif } void scm_init_from_argv(argc, argv, script_arg, iverbose, buf0stdin) int argc; const char * const *argv; char *script_arg; int iverbose; int buf0stdin; { long i = 0L; int j = 0; if ((2 <= argc) && argv[1] && (0==strncmp("-a", argv[1], 2))) i = atol((0==argv[1][2] && 3 <= argc && argv[2]) ? argv[2] : &argv[1][2]); init_scm(iverbose, buf0stdin, (0 >= i) ? 0L : 1024L * i); /* size in kB */ for (j = 0; argv[j]; j++) { if (0==strcmp(argv[j], "--no-symbol-case-fold")) { case_sensitize_symbols = 8; break; } } progargs = EOL; progargs = makfromstrs(argc, argv); sysintern("*script*", script_arg ? makfrom0str(script_arg) : BOOL_F); } void final_scm(freeall) int freeall; { #ifdef TICKS ticken = 0; #endif scm_run_finalizers(!0); #ifdef FINALS FINALS; /* call shutdown of extensions files */ #endif /* for compatability with older modules */ /* call finalization of user extensions */ { int k = num_finals; while (k--) (finals[k])(); } final_repl(); if (freeall) free_storage(); /* free all allocated memory */ } #ifdef PLAN9 # define SYSTNAME "plan9" # define DIRSEP "/" #endif #ifdef __MACH__ # define SYSTNAME "unix" # define DIRSEP "/" #endif #ifdef __CYGWIN__ # define SYSTNAME "unix" # define DIRSEP "/" #endif #ifdef vms # define SYSTNAME "vms" #endif #ifdef HAVE_UNIX # define DIRSEP "/" # ifndef MSDOS /* DJGPP defines both */ # define SYSTNAME "unix" # endif #endif #ifdef MWC # define SYSTNAME "coherent" # define DIRSEP "/" #endif #ifdef _Windows # define SYSTNAME "windows" # define DIRSEP "\\" #else # ifdef MSDOS # define SYSTNAME "ms-dos" # ifndef HAVE_UNIX # define DIRSEP "\\" # endif # endif #endif #ifdef __EMX__ # define SYSTNAME "os/2" # define DIRSEP "\\" #endif #ifdef __IBMC__ # define SYSTNAME "os/2" # define DIRSEP "\\" #endif #ifdef THINK_C # define SYSTNAME "thinkc" # define DIRSEP ":" #endif #ifdef __MWERKS__ # define SYSTNAME "macos" # define DIRSEP ":" #endif #ifdef AMIGA # define SYSTNAME "amiga" # define DIRSEP "/" #endif #ifdef atarist # define SYSTNAME "atarist" # define DIRSEP "\\" #endif #ifdef ARM_ULIB # define SYSTNAME "acorn" #endif #ifdef nosve # define DIRSEP "." #endif #ifdef __amigaos__ # define SYSTNAME "amiga" # define DIRSEP "/" #endif #ifdef __NetBSD__ # define SYSTNAME "unix" # define DIRSEP "/" #endif const char dirsep[] = DIRSEP; SCM softtype() { #ifdef nosve return CAR(sysintern("nosve", UNDEFINED)); #else return CAR(sysintern(SYSTNAME, UNDEFINED)); #endif } #ifdef PLAN9 /* This code is adapted from /sys/src/ape/lib/ap/plan9/isatty.c. */ int isatty (int fd) { Dir d1, d2; char buf[40]; int t; if (dirfstat(fd, &d1) < 0) return 0; if (strncmp(d1.name, "ptty", 4) == 0) return 1; if (dirstat("/dev/cons", &d2) < 0) return 0; /* If we came in through con, /dev/cons is probably #d/0, which won't * match stdin. Opening #d/0 and fstating it gives the values of the * underlying channel */ if (d2.type == 'd') { strcpy(buf, "#d/"); strcpy(buf+3, d2.name); if ((t = open(buf, 0)) < 0) return 0; if (dirfstat(t, &d2) < 0) { close(t); return 0; } close(t); } return (d1.type == d2.type) && (d1.dev == d2.dev); } /* A temporary hack: give SCM our own errno. */ int errno; #endif int init_buf0(inport) FILE *inport; { if (isatty(fileno(inport))) { #ifndef NOSETBUF # ifndef _DCC # ifndef ultrix # ifndef __WATCOMC__ # ifndef macintosh # if (__TURBOC__ != 1) # ifndef _Windows setbuf(inport, 0L); /* Often setbuf isn't actually required */ # endif # endif # endif # endif # endif # endif #endif return !0; /* stdin gets marked BUF0 in init_scm() */ } return 0; } char *execpath = 0; char s_no_execpath[] = "no execpath"; #define s_execpath (s_no_execpath+3) SCM scm_execpath(newpath) SCM newpath; { SCM retval = execpath ? makfrom0str(execpath) : BOOL_F; if (UNBNDP(newpath)) return retval; if (FALSEP(newpath)) { if (execpath) free(execpath); execpath = 0; return retval; } ASRTER(NIMP(newpath) && STRINGP(newpath), newpath, ARG1, s_execpath); if (execpath) free(execpath); execpath = (char *)malloc((sizet)(LENGTH(newpath) + 1)); ASRTER(execpath, newpath, NALLOC, s_execpath); strncpy(execpath, CHARS(newpath), LENGTH(newpath) + 1); return retval; } char *scm_find_execpath(argc, argv, script_arg) int argc; const char * const *argv; const char *script_arg; { char *exepath = 0; #ifndef macintosh # ifdef HAVE_UNIX # ifndef MSDOS if (script_arg) exepath = script_find_executable(script_arg); # endif # endif if (!exepath && argv[0]) exepath = dld_find_executable(argv[0]); /*fprintf(stderr, "scm_find_execpath: argv[0] = %s; script_arg = %s; exepath = %s\n", argv[0], script_arg, exepath); fflush(stderr); */ #endif return exepath; } #ifdef PLAN9 int system(command) const char *command; { int sts; int pid = fork(); if (pid) { Waitmsg wm; sts = -1; while (wait(&wm) != -1) { if (pid==atoi(wm.pid)) { sts = 0; break; } } } else sts = execl("/bin/rc", "/bin/rc", "-c", command, nil); return sts; } #endif #ifndef _Windows char s_system[] = "system"; SCM lsystem(cmd) SCM cmd; { ASRTER(NIMP(cmd) && STRINGP(cmd), cmd, ARG1, s_system); ignore_signals(); # ifdef AZTEC_C cmd = MAKINUM(Execute(CHARS(cmd), 0, 0)); # else cmd = MAKINUM(0L+system(CHARS(cmd))); # endif unignore_signals(); return cmd; } #endif char s_getenv[] = "getenv"; char *getenv(); SCM lgetenv(nam) SCM nam; { char *val; ASRTER(NIMP(nam) && STRINGP(nam), nam, ARG1, s_getenv); val = getenv(CHARS(nam)); if (!val) return BOOL_F; return makfrom0str(val); } #ifdef vms # include # include char s_ed[] = "ed"; SCM ed(fname) SCM fname; { struct dsc$descriptor_s d; ASRTER(NIMP(fname) && STRINGP(fname), fname, ARG1, s_ed); d.dsc$b_dtype = DSC$K_DTYPE_T; d.dsc$b_class = DSC$K_CLASS_S; d.dsc$w_length = LENGTH(fname); d.dsc$a_pointer = CHARS(fname); /* I don't know what VMS does with signal handlers across the edt$edit call. */ ignore_signals(); edt$edit(&d); unignore_signals(); return fname; } SCM vms_debug() { lib$signal(SS$_DEBUG); return UNSPECIFIED; } #endif static iproc subr0s[] = { {"software-type", softtype}, {"scm_init_extensions", scm_init_extensions}, #ifdef vms {"vms-debug", vms_debug}, #endif #ifdef SIGALRM # ifndef AMIGA {"pause", l_pause}, # endif #endif {0, 0}}; static iproc subr1s[] = { {s_getenv, lgetenv}, #ifndef _Windows {s_system, lsystem}, #endif #ifdef vms {s_ed, ed}, #endif #ifdef SIGALRM {s_alarm, lalarm}, #endif #ifndef AMIGA # ifndef _Windows {s_sleep, l_sleep}, # endif #endif #ifndef sun # ifndef _WIN32 {s_raise, l_raise}, # endif #endif {0, 0}}; SCM *loc_features; void add_feature(str) char* str; { *loc_features = cons(CAR(sysintern(str, UNDEFINED)), *loc_features); } void init_features() { loc_features = &CDR(sysintern("slib:features", EOL)); init_iprocs(subr0s, tc7_subr_0); init_iprocs(subr1s, tc7_subr_1); make_subr(s_execpath, tc7_subr_1o, scm_execpath); #ifdef SIGALRM # ifdef SIGPROF make_subr(s_setitimer, tc7_subr_3, scm_setitimer); # ifdef ITIMER_REAL setitimer_tab[0].sym = CAR(sysintern("real", UNDEFINED)); setitimer_tab[0].which = ITIMER_REAL; # endif # ifdef ITIMER_VIRTUAL setitimer_tab[1].sym = CAR(sysintern("virtual", UNDEFINED)); setitimer_tab[1].which = ITIMER_VIRTUAL; # endif # ifdef ITIMER_PROF setitimer_tab[2].sym = CAR(sysintern("profile", UNDEFINED)); setitimer_tab[2].which = ITIMER_PROF; # endif # endif #endif #ifdef TICKS loc_tick_signal = &CDR(sysintern("ticks-interrupt", UNDEFINED)); make_subr(s_ticks, tc7_subr_1o, lticks); #endif #ifdef RECKLESS add_feature("reckless"); #endif #ifndef _Windows add_feature(s_system); #endif #ifdef vms add_feature(s_ed); #endif sysintern("*scm-version*", CAR(sysintern(SCMVERSION, UNDEFINED))); }