/* "repl.c" error, read-eval-print loop, read, write and load 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 */ #include "scm.h" #include "setjump.h" void igc P((const char *what, SCM basecont)); void unexec P((char *new_name, char *a_name, unsigned data_start, unsigned bss_start, unsigned entry_address)); void scm_fill_freelist P((void)); #ifdef __CYGWIN__ # include #endif #ifdef __NetBSD__ # include # include #endif #ifdef __OpenBSD__ # include # include #endif #ifdef PLAN9 # include #endif #ifdef linux # include #endif #ifdef ARM_ULIB # include int set_erase() { struct termio tin; ioctl(0, TCGETA, &tin); tin.c_cc[VERASE] = '\010'; ioctl(0, TCSETA, &tin); return(0); } #endif unsigned char upcase[CHAR_CODE_LIMIT]; unsigned char downcase[CHAR_CODE_LIMIT]; unsigned char lowers[] = "abcdefghijklmnopqrstuvwxyz"; unsigned char uppers[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; void init_tables() { int i; for (i = 0;i", "#@define", "#@eval-values", "#@unquote", "#@unquote-splicing", "#@else", "#@=>", "#@values-token", "#@keyword", /* user visible ISYMS */ /* other keywords */ /* Flags */ "#f", "#t", "#", "#", "()", "#" }; static char s_read_char[] = "read-char", s_peek_char[] = "peek-char"; char s_write[] = "write", s_newline[] = "newline"; static char s_display[] = "display", s_write_char[] = "write-char"; static char s_freshline[] = "freshline"; static char s_eofin[] = "end of file in "; static char s_unknown_sharp[] = "unknown # object"; static SCM scm_lread1 P((SCM port, int flgs, const char *what)); static SCM scm_lreadr P((SCM tok_buf, SCM port, int flgs)); static SCM scm_lreadpr P((SCM tok_buf, SCM port, int flgs)); static SCM scm_lreadparen P((SCM tok_buf, SCM port, int flgs, char *name)); static SCM scm_lread_rec P((SCM tok_buf, SCM port)); static sizet scm_read_token P((int ic, SCM tok_buf, SCM port, int flgs)); static void err_head P((char *str)); extern int case_sensitize_symbols; /* 0 or 8 */ void scm_intprint(n, radix, port) long n; int radix; SCM port; { char num_buf[INTBUFLEN]; lfwrite(num_buf, (sizet)sizeof(char), ilong2str(n, radix, num_buf), port); } void scm_ipruk(hdr, ptr, port) char *hdr; SCM ptr; SCM port; { lputs("#', port); } void scm_iprlist(hdr, exp, tlr, port, writing) char *hdr, tlr; SCM exp; SCM port; int writing; { lputs(hdr, port); /* CHECK_INTS; */ scm_iprin1(CAR(exp), port, writing); exp = GCCDR(exp); /* CDR(exp); */ for (;NIMP(exp);exp = GCCDR(exp) /* CDR(exp)*/) { if (!scm_cell_p(~1L & exp)) break; if (NECONSP(exp)) break; lputc(' ', port); /* CHECK_INTS; */ scm_iprin1(CAR(exp), port, writing); } if (NNULLP(exp)) { lputs(" . ", port); scm_iprin1(exp, port, writing); } lputc(tlr, port); } void scm_iprin1(exp, port, writing) SCM exp; SCM port; int writing; { register long i; taloop: switch (7 & PTR2INT(exp)) { case 2: case 6: scm_intprint(INUM(exp), 10, port); break; case 4: if (ICHRP(exp)) { i = ICHR(exp); if (writing) lputs("#\\", port); if (!writing) lputc((int)i, port); else if ((i <= ' ') && charnames[i]) lputs(charnames[i], port); #ifndef EBCDIC else if (i=='\177') lputs(charnames[(sizeof charnames/sizeof(char *))-1], port); #endif /* ndef EBCDIC */ else if (i > '\177') scm_intprint(i, -8, port); else lputc((int)i, port); } else if (SCM_LINUMP(exp)) { lputs("#', port); } else if (IFLAGP(exp) && (ISYMNUM(exp)<(sizeof isymnames/sizeof(char *)))) lputs(ISYMCHARS(exp), port); else if (ILOCP(exp)) { lputs("#@", port); scm_intprint((long)IFRAME(exp), -10, port); lputc(ICDRP(exp)?'-':'+', port); scm_intprint((long)IDIST(exp), -10, port); } else goto idef; break; case 1: /* gloc */ if (!scm_cell_p(exp-1)) { scm_ipruk("gloc", exp, port); break; } lputs("#@", port); #ifdef _M_ARM /* MS CLARM compiler workaround */ exp = CAR(MS_CLARM_dumy = exp - 1); #else exp = CAR(exp-1); #endif goto taloop; default: idef: scm_ipruk("immediate", exp, port); break; case 0: if (!scm_cell_p(exp)) { scm_ipruk("heap", exp, port); break; } switch TYP7(exp) { case (127 & IM_LET): if (CAR(exp) != IM_LET) { lputs("(#@call ", port); exp = CDR(exp); scm_iprin1(CAR(exp), port, writing); scm_iprlist(" ", CAR(CDR(exp)), ')', port, writing); break; } /* else fall through */ case (127 & IM_AND): case (127 & IM_BEGIN): case (127 & IM_CASE): case (127 & IM_COND): case (127 & IM_DO): case (127 & IM_IF): case (127 & IM_LAMBDA): case (127 & IM_LETSTAR): case (127 & IM_LETREC): case (127 & IM_OR): case (127 & IM_QUOTE): case (127 & IM_SET): case (127 & IM_FUNCALL): case tcs_cons_inum: case tcs_cons_iloc: case tcs_cons_chflag: case tcs_cons_gloc: case tcs_cons_nimcar: scm_iprlist("(", exp, ')', port, writing); break; case tcs_closures: scm_princlosure(exp, port, writing); break; case tc7_string: if (writing) { lputc('\"', port); for (i = 0;i', port); break; case tc7_specfun: #ifdef CCLO if (tc16_cclo==TYP16(exp)) { lputs("#', port); break; } #endif lputs("#', port); break; case tc7_contin: lputs("#', port); break; case tc7_port: i = PTOBNUM(exp); if (i # include static int input_waiting(f) FILE *f; { if (feof(f)) return 1; if (fileno(f)==fileno(stdin) && (isatty(fileno(stdin)))) return kbhit(); return -1; } #else # ifdef _DCC # include # else # ifndef AMIGA # ifndef vms # ifdef MWC # include # else # ifndef macintosh # ifndef ARM_ULIB # ifndef PLAN9 # include # endif # endif # endif # endif # endif # endif # endif # ifdef HAVE_SYS_TIME_H # include # endif static int input_waiting(f) FILE *f; { # ifdef HAVE_SELECT fd_set ifds; struct timeval tv; int ret; FD_ZERO(&ifds); FD_SET(fileno(f), &ifds); tv.tv_sec = 0; tv.tv_usec = 0; SYSCALL(ret = select((fileno(f) + 1), &ifds, (fd_set *) NULL, (fd_set *) NULL, &tv);); ASRTER(ret>=0, MAKINUM(ret), "select error", s_char_readyp); return FD_ISSET(fileno(f), &ifds); # else # ifdef FIONREAD long remir; if (feof(f)) return 1; ioctl(fileno(f), FIONREAD, &remir); return remir; # else return -1; # endif # endif } #endif /* perhaps should undefine MSDOS from __IBMC__ here */ SCM char_readyp(port) SCM port; { if (UNBNDP(port)) port = cur_inp; ASRTER(NIMP(port) && OPINPORTP(port), port, ARG1, s_char_readyp); if (CRDYP(port) || !(BUF0 & SCM_PORTFLAGS(port))) return BOOL_T; return input_waiting(STREAM(port)) ? BOOL_T : BOOL_F; } #ifdef GO32 # include #endif #ifndef HAVE_SELECT # ifdef PLAN9 # define kbhit() 0 # else # include # endif #endif #ifdef __STDC__ # define timet time_t #else # define timet long #endif static char s_wfi[] = "wait-for-input"; SCM wait_for_input(args) SCM args; { SCM how_long, port1, port, ports, ans = EOL; int timeout, pos = ARG2; ASRTER(!NULLP(args), INUM0, WNA, s_wfi); how_long = CAR(args); args = CDR(args); if (NULLP(args)) port1 = cur_inp; else { port1 = CAR(args); args = CDR(args); } timeout = num2long(how_long, (char *)ARG1, s_wfi); ASRTER(timeout >= 0, how_long, ARG1, s_wfi); port = port1; ports = args; while (1) { /* ASRTER(NIMP(port) && OPINPORTP(port) && (BUF0 & SCM_PORTFLAGS(port)), */ /* port, pos, s_wfi); */ if (CRDYP(port) || feof(STREAM(port))) timeout = 0; if (NULLP(ports)) break; if (ARG5 <= pos) pos = ARGn; else if (ARG1 < pos) pos = 1 + pos; port = CAR(ports); ports = CDR(ports); } { #ifdef HAVE_SELECT fd_set ifds; struct timeval tv; int ret, fd_max = 0; tv.tv_sec = timeout; tv.tv_usec = 0; FD_ZERO(&ifds); port = port1; ports = args; while (1) { int fd = fileno(STREAM(port)); FD_SET(fd, &ifds); if (fd_max < fd) fd_max = fd; if (NULLP(ports)) break; port = CAR(ports); ports = CDR(ports); } SYSCALL(ret = select(fd_max + 1, &ifds, (fd_set *)0L, (fd_set *)0L, &tv);); ASRTER(ret>=0, MAKINUM(ret), "select error", s_wfi); port = port1; ports = args; while (1) { if (FD_ISSET(fileno(STREAM(port)), &ifds) || CRDYP(port) || feof(STREAM(port))) ans = cons(port, ans); if (NULLP(ports)) break; port = CAR(ports); ports = CDR(ports); } #else timet start = 0; time(&start); start = start + timeout; port = port1; ports = args; do { FILE *f = STREAM(port); if (feof(f)) ans = cons(port, ans); else { # ifdef _WIN32 if (fileno(f)==fileno(stdin) && (isatty(fileno(stdin))) && kbhit()) ans = cons(port, ans); # else # ifdef FIONREAD long remir; ioctl(fileno(f), FIONREAD, &remir); if (remir) ans = cons(port, ans); # else /* If we get here this is not going to work */ # endif # endif if (NULLP(ports)) break; port = CAR(ports); ports = CDR(ports); } } while (time((timet*)0L) < start); #endif return NULLP(ans) ? BOOL_F : ans; } } SCM eof_objectp(x) SCM x; { return (EOF_VAL==x) ? BOOL_T : BOOL_F; } static SCM *loc_broken_pipe = 0; /* returning non-zero means try again. */ int scm_io_error(port, what) SCM port; const char *what; { #ifdef HAVE_PIPE # ifdef EPIPE if (EPIPE==errno) { if (scm_verbose > 2) { err_head("WARNING"); lputs(";;", cur_errp); lputs(what, cur_errp); lputs(": closing pipe ", cur_errp); scm_iprin1(port, cur_errp, 1); scm_newline(cur_errp); } close_port(port); if (*loc_broken_pipe && NIMP(*loc_broken_pipe)) apply(*loc_broken_pipe, port, listofnull); return 0; } # endif #endif if (SCM_INTERRUPTED(errno)) { errno = 0; return !0; } wta(port, what, "Input/Output"); return 0; /* squelch warning */ } void lfflush(port) /* internal SCM call */ SCM port; { sizet i = PTOBNUM(port); while ((ptobs[i].fflush)(STREAM(port)) && scm_io_error(port, "lfflush")) ; } static char s_force_output[] = "force-output"; SCM scm_force_output(port) SCM port; { if (UNBNDP(port)) port = cur_outp; else ASRTER(NIMP(port) && OPOUTPORTP(port), port, ARG1, s_force_output); lfflush(port); return UNSPECIFIED; } SCM scm_write(obj, port) SCM obj, port; { if (UNBNDP(port)) port = cur_outp; else ASRTER(NIMP(port) && OPOUTPORTP(port), port, ARG2, s_write); scm_iprin1(obj, port, 1); return UNSPECIFIED; } SCM scm_display(obj, port) SCM obj, port; { if (UNBNDP(port)) port = cur_outp; else ASRTER(NIMP(port) && OPOUTPORTP(port), port, ARG2, s_display); scm_iprin1(obj, port, 0); return UNSPECIFIED; } SCM scm_newline(port) SCM port; { if (UNBNDP(port)) port = cur_outp; else ASRTER(NIMP(port) && OPOUTPORTP(port), port, ARG1, s_newline); lputc('\n', port); if (port==cur_outp) lfflush(port); return UNSPECIFIED; } SCM scm_write_char(chr, port) SCM chr, port; { if (UNBNDP(port)) port = cur_outp; else ASRTER(NIMP(port) && OPOUTPORTP(port), port, ARG2, s_write_char); ASRTER(ICHRP(chr), chr, ARG1, s_write_char); lputc((int)ICHR(chr), port); return UNSPECIFIED; } SCM scm_freshline(port) SCM port; { if (UNBNDP(port)) port = cur_outp; else ASRTER(NIMP(port) && OPOUTPORTP(port), port, ARG1, s_freshline); if (INUM0==scm_port_col(port)) return UNSPECIFIED; lputc('\n', port); if (port==cur_outp) lfflush(port); return UNSPECIFIED; } void lputc(c, port) int c; SCM port; { sizet i = PTOBNUM(port); while (EOF==(ptobs[i].fputc)(c, STREAM(port)) && scm_io_error(port, "fputc")) ; if (CRDY & CAR(port)) { i = SCM_PORTNUM(port); switch (c) { case LINE_INCREMENTORS: scm_port_table[i].line++; scm_port_table[i].col = 1; break; default: scm_port_table[i].col++; } } } void lputs(s, port) const char *s; SCM port; { sizet i = PTOBNUM(port); ASRTER(s, INUM0, ARG1, "lputs"); while (EOF==(ptobs[i].fputs)(s, STREAM(port)) && scm_io_error(port, "fputs")) ; if (CRDY & CAR(port)) { sizet j; i = SCM_PORTNUM(port); for (j = 0; s[j]; j++) { switch (s[j]) { case LINE_INCREMENTORS: scm_port_table[i].line++; scm_port_table[i].col = 1; break; default: scm_port_table[i].col++; } } } } sizet lfwrite(ptr, size, nitems, port) char *ptr; sizet size; sizet nitems; SCM port; { sizet ret, i = PTOBNUM(port); do { ret = (ptobs[i].fwrite)(ptr, size, nitems, STREAM(port)); } while(nitems != ret && scm_io_error(port, "fwrite")); if (CRDY & CAR(port)) { sizet j; i = SCM_PORTNUM(port); for (j = 0; j < ret*size; j++) { switch (ptr[j]) { case LINE_INCREMENTORS: scm_port_table[i].line++; scm_port_table[i].col = 1; break; default: scm_port_table[i].col++; } } } return ret; } int lgetc(port) SCM port; { FILE *f; int c; int i, j = -1; if (CRDY & CAR(port)) { j = SCM_PORTNUM(port); c = scm_port_table[j].unread; if (c != EOF) { scm_port_table[j].unread = EOF; CAR(port) &= (scm_port_table[j].flags | (~0xf0000)); /* CLRDY(port) */ return c; } } f = STREAM(port); i = PTOBNUM(port); #ifdef linux c = (ptobs[i].fgetc)(f); #else SYSCALL(c = (ptobs[i].fgetc)(f);); #endif if (j > -1) { /* This means that CRDY is set, note that CRDY is overloaded */ switch (c) { case LINE_INCREMENTORS: scm_port_table[j].line++; scm_port_table[j].colprev = scm_port_table[j].col; scm_port_table[j].col = 1; break; default: scm_port_table[j].col++; } } return c; } void lungetc(c, port) int c; SCM port; { int i = PTOBNUM(port); /* ASRTER(!CRDYP(port), port, ARG2, "too many lungetc");*/ if (ptobs[i].ungetc) (ptobs[i].ungetc)(c, port); else { scm_port_table[SCM_PORTNUM(port)].unread = c; CAR(port) |= CRDY; } } SCM scm_read_char(port) SCM port; { int c; if (UNBNDP(port)) port = cur_inp; ASRTER(NIMP(port) && OPINPORTP(port), port, ARG1, s_read_char); c = lgetc(port); if (EOF==c) return EOF_VAL; return MAKICHR(c); } SCM scm_peek_char(port) SCM port; { int c; if (UNBNDP(port)) port = cur_inp; else ASRTER(NIMP(port) && OPINPORTP(port), port, ARG1, s_peek_char); c = lgetc(port); if (EOF==c) return EOF_VAL; lungetc(c, port); return MAKICHR(c); } char *grow_tok_buf(tok_buf) SCM tok_buf; { sizet len = LENGTH(tok_buf); len += len / 2; resizuve(tok_buf, (SCM)MAKINUM(len)); return CHARS(tok_buf); } static int flush_ws(port) SCM port; { register int c; while(1) switch (c = lgetc(port)) { case ';': lp: switch (c = lgetc(port)) { default: goto lp; case EOF: return c; case LINE_INCREMENTORS: break; } case LINE_INCREMENTORS: case WHITE_SPACES: break; case EOF: default: return c; } } /* Top-level readers */ static SCM p_read_for_load, p_read; static char s_read[] = "read"; static char s_read_for_load[] = "read-for-load"; #ifndef MEMOIZE_LOCALS static SCM p_read_numbered; static char s_read_numbered[] = "read-numbered"; #endif SCM scm_read(port) SCM port; { return scm_lread1(port, case_sensitize_symbols, s_read); } SCM scm_read_for_load(port) SCM port; { return scm_lread1(port, 4 | case_sensitize_symbols, s_read_for_load); } #ifndef MEMOIZE_LOCALS SCM scm_read_numbered(port) SCM port; { return scm_lread1(port, 6 | case_sensitize_symbols, s_read_numbered); } #endif static SCM scm_lread1(port, flgs, what) SCM port; int flgs; const char *what; { int c; SCM tok_buf; if (UNBNDP(port)) port = cur_inp; ASRTER(NIMP(port) && OPINPORTP(port), port, ARG1, what); do { c = flush_ws(port); if (EOF==c) return EOF_VAL; lungetc(c, port); tok_buf = makstr(30L); } while (EOF_VAL==(tok_buf = scm_lreadr(tok_buf, port, flgs))); return tok_buf; } static SCM *loc_loadsharp = 0, *loc_readsharp = 0, *loc_charsharp = 0; static SCM scm_lreadpr(tok_buf, port, flgs) SCM tok_buf; SCM port; int flgs; { int c; sizet j; SCM p; if (2==(3 & flgs)) return scm_lread_rec(tok_buf, port); tryagain: c = flush_ws(port); switch (c) { case EOF: return EOF_VAL; #ifdef BRACKETS_AS_PARENS case '[': #endif case '(': return scm_lreadparen(tok_buf, port, flgs, s_list); #ifdef BRACKETS_AS_PARENS case ']': #endif case ')': return UNDEFINED; /* goto tryagain; */ case '\'': return cons2(i_quote, scm_lreadr(tok_buf, port, flgs), EOL); case '`': return cons2(i_quasiquote, scm_lreadr(tok_buf, port, flgs), EOL); case ',': c = lgetc(port); if ('@'==c) p = i_uq_splicing; else { lungetc(c, port); p = i_unquote; } return cons2(p, scm_lreadr(tok_buf, port, flgs), EOL); case '#': c = lgetc(port); switch (c) { #ifdef BRACKETS_AS_PARENS case '[': #endif case '(': p = scm_lreadparen(tok_buf, port, flgs, s_vector); return NULLP(p) ? nullvect : vector(p); case 't': case 'T': return BOOL_T; case 'f': case 'F': return BOOL_F; case 'b': case 'B': case 'o': case 'O': case 'd': case 'D': case 'x': case 'X': case 'i': case 'I': case 'e': case 'E': lungetc(c, port); c = '#'; goto num; case '*': j = scm_read_token(c, tok_buf, port, flgs); p = istr2bve(CHARS(tok_buf)+1, (long)(j-1)); if (NFALSEP(p)) return p; else goto unkshrp; case '\\': c = lgetc(port); if ('\\'==c) { CHARS(tok_buf)[0] = c; j = 1; } else j = scm_read_token(c, tok_buf, port, flgs); if (j==1) return MAKICHR(c); for (c = 0;c= LENGTH(tok_buf)) grow_tok_buf(tok_buf); switch (c) { case LINE_INCREMENTORS: break; case '\\': switch (c = lgetc(port)) { case LINE_INCREMENTORS: continue; case '0': c = '\0'; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'a': c = '\007'; break; case 'v': c = '\v'; break; } } CHARS(tok_buf)[j] = c; ++j; } if (j==0) return nullstr; CHARS(tok_buf)[j] = 0; return makfromstr(CHARS(tok_buf), j); case DIGITS: case '.': case '-': case '+': num: j = scm_read_token(c, tok_buf, port, flgs); p = istring2number(CHARS(tok_buf), (long)j, 10L); if (NFALSEP(p)) return p; if (c=='#') { if ((j==2) && (lgetc(port)=='(')) { lungetc('(', port); c = CHARS(tok_buf)[1]; goto callshrp; } wta(UNDEFINED, s_unknown_sharp, CHARS(tok_buf)); } goto tok; default: j = scm_read_token(c, tok_buf, port, flgs); tok: p = intern(CHARS(tok_buf), j); return CAR(p); } } static SCM scm_lreadr(tok_buf, port, flgs) SCM tok_buf; SCM port; int flgs; { SCM ans = scm_lreadpr(tok_buf, port, flgs); switch (ans) { case UNDEFINED: scm_warn("unexpected \")\"", "", port); return scm_lreadpr(tok_buf, port, flgs); } return ans; } static SCM scm_lread_rec(tok_buf, port) SCM tok_buf; SCM port; { SCM line, form; int c = flush_ws(port); switch (c) { default: lungetc(c, port); line = scm_port_line(port); form = scm_lreadpr(tok_buf, port, 5); if (NFALSEP(line) && NIMP(form) && (CONSP(form) || VECTORP(form))) { return cons(SCM_MAKE_LINUM(INUM(line)), form); } return form; #ifdef BRACKETS_AS_PARENS case ']': #endif case ')': return UNDEFINED; case EOF: return EOF_VAL; } } #ifdef _UNICOS _Pragma("noopt"); /* # pragma _CRI noopt */ #endif static sizet scm_read_token(ic, tok_buf, port, flgs) int ic; SCM tok_buf; SCM port; int flgs; { register sizet j = 1; register int c = ic; register char *p = CHARS(tok_buf); p[0] = '\\'==c ? lgetc(port) : 8 & flgs ? c : downcase[c]; while(1) { if (j+1 >= LENGTH(tok_buf)) p = grow_tok_buf(tok_buf); switch (c = lgetc(port)) { #ifdef BRACKETS_AS_PARENS case '[': case ']': #endif case '(': case ')': case '\"': case ';': case ',': case '`': /* case '#': */ case WHITE_SPACES: case LINE_INCREMENTORS: lungetc(c, port); case EOF: p[j] = 0; return j; case '\\': /* slashified symbol */ p[j++] = lgetc(port); break; default: p[j++] = 8 & flgs ? c : downcase[c]; } } } #ifdef _UNICOS _Pragma("opt"); /* # pragma _CRI opt */ #endif /* flgs was originally an argument to determine whether a read was */ /* top-level or recursve. It has been overloaded to determine also */ /* what to do in the case of a recursive read. */ /* It distinguishes four states: */ /* 0 - not adding line-numbers - never changes. Uses READ:SHARP */ /* 4 - not adding line-numbers - never changes. Uses LOAD:SHARP */ /* 5 - top level read when adding line-numbers. Uses LOAD:SHARP */ /* 6 - recursive read when adding line-numbers. Uses LOAD:SHARP */ static SCM scm_lreadparen(tok_buf, port, flgs, name) SCM tok_buf; SCM port; int flgs; char *name; { SCM lst, fst, tmp = scm_lreadpr(tok_buf, port, (0xC & flgs) | ((3 & flgs) ? 2 : 0)); if (UNDEFINED==tmp) return EOL; if (i_dot==tmp) { fst = scm_lreadr(tok_buf, port, (0xC & flgs) | ((3 & flgs) ? 1 : 0)); closeit: tmp = scm_lreadpr(tok_buf, port, 0); if (UNDEFINED != tmp) wta(UNDEFINED, "missing close paren", name); return fst; } fst = lst = cons(tmp, EOL); while (UNDEFINED != (tmp = scm_lreadpr(tok_buf, port, (0xC & flgs) | ((3 & flgs) ? 2 : 0)))) { if (EOF_VAL==tmp) wta(lst, s_eofin, s_list); if (i_dot==tmp) { CDR(lst) = scm_lreadr(tok_buf, port, (0xC & flgs) | ((3 & flgs) ? 1 : 0)); goto closeit; } lst = (CDR(lst) = cons(tmp, EOL)); } return fst; } /* These procedures implement synchronization primitives. Processors with an atomic test-and-set instruction can use it here (and not DEFER_INTS). */ char s_swapcar[] = "swap-car!"; SCM swapcar(pair, value) SCM pair, value; { SCM ret; ASRTER(NIMP(pair) && CONSP(pair), pair, ARG1, s_swapcar); DEFER_INTS; ret = CAR(pair); CAR(pair) = value; ALLOW_INTS; return ret; } char s_tryarb[] = "try-arbiter"; char s_relarb[] = "release-arbiter"; long tc16_arbiter; SCM tryarb(arb) SCM arb; { ASRTER((TYP16(arb)==tc16_arbiter), arb, ARG1, s_tryarb); DEFER_INTS; if (CAR(arb) & (1L<<16)) arb = BOOL_F; else { CAR(arb) = tc16_arbiter | (1L<<16); arb = BOOL_T; } ALLOW_INTS; return arb; } SCM relarb(arb) SCM arb; { ASRTER((TYP16(arb)==tc16_arbiter), arb, ARG1, s_relarb); if (!(CAR(arb) & (1L<<16))) return BOOL_F; CAR(arb) = tc16_arbiter; return BOOL_T; } SCM makarb(name) SCM name; { register SCM z; NEWCELL(z); CDR(z) = name; CAR(z) = tc16_arbiter; return z; } static int prinarb(exp, port, writing) SCM exp; SCM port; int writing; { lputs("#', port); return !0; } static char s_tryload[] = "try-load"; #define s_load (&s_tryload[4]) struct errdesc {char *msg;char *s_response;short parent_err;}; struct errdesc errmsgs[] = { {"Wrong number of args", 0, 0}, {"numerical overflow", 0, FPE_SIGNAL}, {"Argument out of range", 0, FPE_SIGNAL}, {"Could not allocate", "out-of-storage", 0}, {"Thrashing", "thrashing", 0}, {"EXIT", "end-of-program", -1}, {"hang up", "hang-up", EXIT}, {"user interrupt", "user-interrupt", 0}, {"arithmetic error", "arithmetic-error", 0}, {"bus error", 0, 0}, {"segment violation", 0, 0}, {"alarm", "alarm-interrupt", 0}, {"virtual alarm", "virtual-alarm-interrupt", 0}, {"profile interrupt", "profile-alarm-interrupt", 0}, }; void (* deferred_proc) P((void)) = 0; char *errjmp_bad = "init"; VOLATILE int ints_disabled = 1; unsigned long SIG_deferred = 0; int scm_verbose = 1; /* Low so that monitor info won't be */ /* printed while in init_storage. (BOOM) */ static int errjmp_recursive = 0; static int errobj_codep; static SCM err_exp, err_env; static char *err_pos, *err_s_subr; static cell tmp_errobj = {(SCM)UNDEFINED, (SCM)EOL}; static cell tmp_loadpath = {(SCM)BOOL_F, (SCM)EOL}; SCM *loc_errobj = (SCM *)&tmp_errobj; SCM *loc_loadpath = (SCM *)&tmp_loadpath; long cells_allocated = 0, lcells_allocated = 0, mallocated = 0, lmallocated = 0, rt = 0, gc_rt, gc_time_taken; long gc_cells_collected, gc_malloc_collected, gc_ports_collected; long gc_syms_collected; long scm_env_work = 0, scm_gcs = 0, scm_egcs = 0, scm_stk_moved = 0, scm_clo_moved = 0, scm_egc_rt; static void def_err_response P((void)); int handle_it(i) int i; { SCM proc; char *name = errmsgs[i-WNA].s_response; if (errjmp_bad || errjmp_recursive) wta(UNDEFINED, (char *)i, ""); /* sends it to def_err_response */ /* NEWCELL does not defer interrupts; so be careful to maintain the freelist integrity. */ if (name) { int j; SCM n[2]; /* GC-protect discarded cells (possibly being used by interrupted code). */ DEFER_INTS; /* Two cells are discarded because NEWCELL may have been interrupted between computing the right-hand-side of freelist = CDR(freelist) and assigning it to freelist. */ for (j=0; j<2; j++) NEWCELL(n[j]); /* discard 2 possibly-used cells */ CDR(n[1]) = EOL; /* lose pointer to freelist */ ALLOW_INTS; /* discarding was necessary here because intern() may do NEWCELL */ proc = CDR(intern(name, (sizet)strlen(name))); if (NIMP(proc)) { /* Save environment stack, in case it moves when applying proc. Do an ecache gc to protect contents of stack. */ SCM estk, *estk_ptr, env, env_tmp; DEFER_INTS; #ifndef NO_ENV_CACHE scm_egc(); #endif estk = scm_estk; estk_ptr = scm_estk_ptr; env = scm_env; env_tmp = scm_env_tmp; scm_estk = BOOL_F; scm_estk_reset(0); SCM_ESTK_PARENT(scm_estk) = estk; SCM_ESTK_PARENT_INDEX(scm_estk) = MAKINUM(estk_ptr - VELTS(estk)); ALLOW_INTS; apply(proc, EOL, EOL); DEFER_INTS; scm_estk = estk; scm_estk_ptr = estk_ptr; scm_env = env; scm_env_tmp = env_tmp; scm_fill_freelist(); ALLOW_INTS; return i; } } /* Ensure that freelist is not empty when returning from interrupt */ DEFER_INTS; scm_fill_freelist(); ALLOW_INTS; return errmsgs[i-WNA].parent_err; } SCM exitval = MAKINUM(EXIT_FAILURE); /* INUM return value */ extern char s_unexec[]; SCM scm_top_level(initpath, toplvl_fun) char *initpath; SCM (*toplvl_fun)(); { SCM ret; #ifdef _UNICOS int i; #else long i; #endif if (!toplvl_fun) toplvl_fun = repl; CONT(rootcont)->stkbse = (STACKITEM *)&i; i = setjump(CONT(rootcont)->jmpbuf); #ifndef SHORT_INT if (i) i = UNCOOK(i); #endif drloop: switch (PTR2INT(i)) { default: { char *name = errmsgs[i-WNA].s_response; if (name) { SCM proc = CDR(intern(name, (sizet)strlen(name))); if (NIMP(proc)) apply(proc, EOL, EOL); }} i = errmsgs[i-WNA].parent_err; if (i) goto drloop; case 1: /* from everr() */ def_err_response(); goto reset_toplvl; case 0: exitval = MAKINUM(EXIT_SUCCESS); errjmp_bad = (char *)0; errjmp_recursive = 0; if (NIMP(sys_errp) && OPOUTPORTP(sys_errp)) lfflush(sys_errp); errno = 0; SIG_deferred = 0; deferred_proc = 0; ints_disabled = 0; scm_init_INITS(); if (dumped) { lcells_allocated = cells_allocated; lmallocated = mallocated; rt = INUM(my_time()); gc_time_taken = 0; } else if (initpath && (isspace(initpath[0]) || ';'==initpath[0] || '('==initpath[0])) scm_ldstr(initpath); else if (scm_ldfile(initpath ? initpath : "")) /* load Scheme init files */ wta(*loc_errobj, "Could not open file", s_load); { SCM boot_tail = scm_evstr("boot-tail"); /* initialization tail-call */ if (NIMP(boot_tail)) apply(boot_tail, (dumped ? makfrom0str(initpath) : BOOL_F), listofnull); } case -2: /* abrt */ reset_toplvl: ints_disabled = 1; errjmp_bad = (char *)0; errjmp_recursive = 0; if (NIMP(sys_errp) && OPOUTPORTP(sys_errp)) lfflush(sys_errp); SIG_deferred = 0; deferred_proc = 0; gc_hook_active = 0; scm_estk_reset(0); /* Closing the loading file turned out to be a bad idea. */ /* But I will leave the code here in case someone wants it. */ #ifdef CLOSE_LOADING_PORTS_ON_ABORT if (NIMP(loadports) && OPINPORTP(CAR(loadports))) { if (scm_verbose > 1) { lputs("; Aborting load (closing): ", cur_errp); scm_display(*loc_loadpath, cur_errp); scm_newline(cur_errp); } close_port(CAR(loadports)); /* close loading file. */ } #endif *loc_loadpath = BOOL_F; loadports = EOL; ints_disabled = 0; dowinds(EOL); ret = toplvl_fun(); /* typically repl() */ if (INUMP(ret)) exitval = ret; err_pos = (char *)EXIT; i = EXIT; goto drloop; /* encountered EOF on stdin */ case -1: /* quit */ dowinds(EOL); if (MAKINUM(EXIT_SUCCESS) != exitval) { lputs("; program args: ", cur_errp); scm_write(progargs, cur_errp); scm_newline(cur_errp); } return exitval; case -3: /* restart. */ dowinds(EOL); return 0; #ifdef CAN_DUMP case -4: /* dump */ DEFER_INTS; scm_estk_reset(0); scm_egc(); igc(s_unexec, BOOL_F); ALLOW_INTS; dumped = 1; # ifdef linux sbrk(getpagesize()); /* The last few words of the .data segment were not being mapped in for dumped executables. */ # endif unexec(CHARS(*loc_errobj), execpath, 0, 0, 0); goto reset_toplvl; #endif } } SCM line_num() { if (IMP(loadports)) return INUM0; return scm_port_line(CAR(loadports)); } static char s_port_line[] = "port-line"; SCM scm_port_line(port) SCM port; { sizet lnum; ASRTER(NIMP(port) && PORTP(port), port, ARG1, s_port_line); if (! (TRACKED & SCM_PORTFLAGS(port))) return BOOL_F; lnum = scm_port_table[SCM_PORTNUM(port)].line; switch (CGETUN(port)) { default: case EOF: /* no ungetted char */ break; case LINE_INCREMENTORS: lnum--; break; } return MAKINUM(lnum); } static char s_port_col[] = "port-column"; SCM scm_port_col(port) SCM port; { long col; ASRTER(NIMP(port) && PORTP(port), port, ARG1, s_port_col); if (! (TRACKED & SCM_PORTFLAGS(port))) return BOOL_F; col = scm_port_table[SCM_PORTNUM(port)].col; switch (CGETUN(port)) { default: col--; break; case EOF: /* no ungetted char */ break; case LINE_INCREMENTORS: col = scm_port_table[SCM_PORTNUM(port)].colprev; break; } return MAKINUM(col); } static char s_file_position[] = "file-position"; SCM scm_file_position(port, pos) SCM port, pos; { ASRTER(NIMP(port) && OPFPORTP(port), port, ARG1, s_file_position); if (UNBNDP(pos) || FALSEP(pos)) { long ans; SYSCALL(ans = ftell(STREAM(port));); if (ans < 0) return BOOL_F; if (CRDYP(port)) ans--; return MAKINUM(ans); } ASRTER((INUMP(pos) && (INUM(pos) >= 0)) || (NIMP(pos) && (TYP16(pos)==tc16_bigpos)), port, ARG2, s_file_position); #ifndef RECKLESS if (TRACKED & SCM_PORTFLAGS(port)) { if (INUM0==pos) { int i = SCM_PORTNUM(port); scm_port_table[i].line = 1L; scm_port_table[i].col = 1; } else { if (2 <= scm_verbose) scm_warn("Setting file position for tracked port: ", "", port); SCM_PORTFLAGS(port) &= (~TRACKED); } } #endif { int ans; CLRDY(port); /* Clear ungetted char */ SYSCALL(ans = fseek(STREAM(port), INUM(pos), 0);); #ifdef HAVE_PIPE # ifdef ESPIPE if (!OPIOPORTP(port)) ASRTER(ESPIPE != errno, port, ARG1, s_file_position); # endif #endif return ans ? BOOL_F : BOOL_T; } } static char s_port_filename[] = "port-filename"; SCM scm_port_filename(port) SCM port; { SCM x; ASRTER(NIMP(port) && PORTP(port), port, ARG1, s_port_filename); x = SCM_PORTDATA(port); if (NIMP(x) && STRINGP(x)) return SCM_PORTDATA(port); return BOOL_F; } SCM prog_args() { return progargs; } extern char s_heap[]; void growth_mon(obj, size, units, grewp) char *obj; long size; char *units; int grewp; { if (scm_verbose > 2) { lputs((grewp ? "; grew " : "; shrank "), sys_errp); lputs(obj, sys_errp); lputs(" to ", sys_errp); scm_intprint(size, -10, sys_errp); lputc(' ', sys_errp); lputs(units, sys_errp); if ((scm_verbose > 4) && (obj==s_heap)) heap_report(); lputs("\n; ", sys_errp); } } void gc_start(what) const char *what; { if (scm_verbose > 4) { lputs(";GC(", sys_errp); lputs(what, sys_errp); lputs(") ", sys_errp); } scm_gcs++; gc_rt = INUM(my_time()); gc_cells_collected = 0; gc_malloc_collected = 0; gc_ports_collected = 0; gc_syms_collected = 0; } void gc_end() { gc_rt = INUM(my_time()) - gc_rt; gc_time_taken = gc_time_taken + gc_rt; if (scm_verbose > 4) { scm_intprint(time_in_msec(gc_rt), -10, sys_errp); lputs(".ms cpu, ", sys_errp); scm_intprint(gc_cells_collected, -10, sys_errp); lputs(" cells, ", sys_errp); scm_intprint(gc_malloc_collected, -10, sys_errp); lputs(" malloc, ", sys_errp); scm_intprint(gc_syms_collected, -10, sys_errp); lputs(" syms, ", sys_errp); scm_intprint(gc_ports_collected, -10, sys_errp); lputs(" ports collected\n", sys_errp); } } void scm_egc_start() { scm_egc_rt = INUM(my_time()); scm_egcs++; } void scm_egc_end() { scm_egc_rt = INUM(my_time()) - scm_egc_rt; gc_time_taken = gc_time_taken + scm_egc_rt; } void repl_report() { if (scm_verbose > 2) { lfflush(cur_outp); lputs(";Evaluation took ", cur_errp); scm_intprint(time_in_msec(INUM(my_time())-rt), -10, cur_errp); lputs(".ms (", cur_errp); scm_intprint(time_in_msec(gc_time_taken), -10, cur_errp); lputs(".ms in gc) ", cur_errp); scm_intprint(cells_allocated - lcells_allocated, -10, cur_errp); lputs(" cells work, ", cur_errp); scm_env_work += scm_ecache_len - scm_ecache_index; scm_intprint(scm_env_work, -10, cur_errp); lputs(" env, ", cur_errp); scm_intprint(mallocated - lmallocated, -10, cur_errp); lputs(".B other\n", cur_errp); if (scm_verbose > 3) { lputc(';', cur_errp); scm_intprint(scm_gcs, -10, cur_errp); lputs( " gc, ", cur_errp); scm_intprint(scm_egcs, -10, cur_errp); lputs( " ecache gc, ", cur_errp); scm_intprint(scm_clo_moved, -10, cur_errp); lputs(" env migrated from closures, ", cur_errp); scm_intprint(scm_stk_moved, -10, cur_errp); lputs(" from stack\n", cur_errp); } lfflush(cur_errp); } } #ifndef LACK_SBRK unsigned long scm_init_brk = 0, scm_dumped_brk = 0; void init_sbrk() { if (dumped) scm_dumped_brk = (unsigned long)sbrk(0); else scm_init_brk = (unsigned long)sbrk(0); } void scm_brk_report() { unsigned long scm_curbrk = (unsigned long)sbrk(0), dif1 = ((dumped ? scm_dumped_brk : scm_curbrk) - scm_init_brk)/1024, dif2 = (scm_curbrk - scm_dumped_brk)/1024; lputs("initial brk = 0x", cur_errp); scm_intprint(scm_init_brk, -16, cur_errp); if (dumped) { lputs(", dumped = 0x", cur_errp); scm_intprint(scm_dumped_brk, -16, cur_errp); } lputs(", current = 0x", cur_errp); scm_intprint(scm_curbrk, -16, cur_errp); lputs("; ", cur_errp); scm_intprint(dif1, 10, cur_errp); if (dumped) { lputs(dif2 < 0 ? " - " : " + ", cur_errp); scm_intprint(dif2 < 0 ? -dif2 : dif2, 10, cur_errp); } lputs(".kiB\n", cur_errp); } #endif SCM lroom(opt) SCM opt; { scm_intprint(cells_allocated, -10, cur_errp); lputs(" out of ", cur_errp); scm_intprint(heap_cells, -10, cur_errp); lputs(" cells in use, ", cur_errp); scm_intprint(mallocated, -10, cur_errp); lputs(".B allocated (of ", cur_errp); scm_intprint(mtrigger, 10, cur_errp); lputs(")\n", cur_errp); if (!UNBNDP(opt)) { #ifndef LACK_SBRK if (scm_init_brk) scm_brk_report(); #endif scm_ecache_report(); heap_report(); lputc('\n', cur_errp); gra_report(); stack_report(); } return UNSPECIFIED; } void scm_ecache_report() { scm_intprint(scm_estk_size, 10 , cur_errp); lputs(" env stack items, ", cur_errp); scm_intprint(scm_ecache_len - scm_ecache_index, 10, cur_errp); lputs(" out of ", cur_errp); scm_intprint(scm_ecache_len, 10, cur_errp); lputs(" env cells in use.\n", cur_errp); } void exit_report() { if (scm_verbose > 2) { lputs(";Totals: ", cur_errp); scm_intprint(time_in_msec(INUM(my_time())), -10, cur_errp); lputs(".ms my time, ", cur_errp); scm_intprint(time_in_msec(INUM(your_time())), -10, cur_errp); lputs(".ms your time\n", cur_errp); } } SCM prolixity(arg) SCM arg; { int old = scm_verbose; if (!UNBNDP(arg)) { if (FALSEP(arg)) scm_verbose = 1; else scm_verbose = INUM(arg); } return MAKINUM(old); } static SCM i_repl; SCM repl() { SCM x; SCM env = EOL; /* scm_env_addprop(SCM_ENV_FILENAME, i_repl, EOL); */ int c; if (OPINPORTP(cur_inp) && OPOUTPORTP(cur_outp)) { repl_report(); while(1) { if (OPOUTPORTP(cur_inp)) { /* This case for curses window */ lfflush(cur_outp); if (scm_verbose) lputs(PROMPT, cur_inp); lfflush(cur_inp); } else { if (scm_verbose) lputs(PROMPT, cur_outp); lfflush(cur_outp); } lcells_allocated = cells_allocated; scm_env_work = scm_ecache_index - scm_ecache_len; scm_egcs = scm_clo_moved = scm_stk_moved = 0; lmallocated = mallocated; x = scm_read_for_load(cur_inp); rt = INUM(my_time()); scm_gcs = 0; gc_time_taken = 0; if (EOF_VAL==x) return MAKINUM(EXIT_SUCCESS); if (!CRDYP(cur_inp)) { /* assure newline read (and transcripted) */ if (EOF==(c = lgetc(cur_inp))) break; lungetc(c, cur_inp); } #ifdef __HIGHC__ # define __MSDOS__ #endif #ifdef __MSDOS__ if ('\n' != CGETUN(cur_inp)) if (OPOUTPORTP(cur_inp)) /* This case for curses window */ {lfflush(cur_outp); scm_newline(cur_inp);} else scm_newline(cur_outp); #endif if (NIMP(x)) { x = CONSP(x) ? scm_eval_values(x, env, (SCM)EOL) : cons(EVAL(x, env, (SCM)EOL), EOL); } else x = cons(x, EOL); repl_report(); if (IMP(x)) {if (scm_verbose > 2) lputs(";;no values\n", cur_outp);} else if (IMP(CDR(x))) { scm_iprin1(CAR(x), cur_outp, 1); lputc('\n', cur_outp); } else while (NIMP(x)) { lputc(' ', cur_outp); scm_iprin1(CAR(x), cur_outp, 1); lputc('\n', cur_outp); x = CDR(x); } } } return UNSPECIFIED; } SCM quit(n) SCM n; { if (UNBNDP(n) || BOOL_T==n) n = MAKINUM(EXIT_SUCCESS); if (INUMP(n)) exitval = n; else exitval = MAKINUM(EXIT_FAILURE); if (errjmp_bad) exit(INUM(exitval)); longjump(CONT(rootcont)->jmpbuf, COOKIE(-1)); } SCM abrt() { if (errjmp_bad) exit(EXIT_FAILURE); longjump(CONT(rootcont)->jmpbuf, COOKIE(-2)); } char s_restart[] = "restart"; SCM restart() { /* ASRTER(!dumped, UNDEFINED, "dumped can't", s_restart); */ longjump(CONT(rootcont)->jmpbuf, COOKIE(-3)); } #ifdef CAN_DUMP char s_unexec[] = "unexec"; SCM scm_unexec(newpath) SCM newpath; { ASRTER(NIMP(newpath) && STRINGP(newpath), newpath, ARG1, s_unexec); ASRTER(execpath, UNSPECIFIED, s_no_execpath, s_unexec); *loc_errobj = newpath; longjump(CONT(rootcont)->jmpbuf, COOKIE(-4)); } #endif #ifdef CAREFUL_INTS ints_infot *ints_info = 0; static void ints_viol_iprin(num) int num; { char num_buf[INTBUFLEN]; sizet i = ilong2str(num+0L, 10, num_buf); num_buf[i] = 0; fputs(num_buf, stderr); } void ints_viol(info, sense) ints_infot *info; int sense; { fputs(info->fname, stderr); fputc(':', stderr); ints_viol_iprin(info->linum); fputs(": ints already ", stderr); fputs(sense ? "dis" : "en", stderr); fputs("abled (", stderr); ints_viol_iprin(ints_disabled); fputs(")\n", stderr); if (ints_info) { fputs(ints_info->fname, stderr); fputc(':', stderr); ints_viol_iprin(ints_info->linum); fputs(": last change\n", stderr); } ints_info = info; } void ints_warn(str1, str2, fname, linum) char *str1, *str2, *fname; int linum; { fputs(fname, stderr); fputc(':', stderr); ints_viol_iprin(linum); fputs(": unprotected call to ", stderr); fputs(str1, stderr); if (str2) { fputs(" (", stderr); fputs(str2, stderr); fputc(')', stderr); } fputc('\n', stderr); } #endif SCM tryload(filename, reader) SCM filename, reader; { ASRTER(NIMP(filename) && STRINGP(filename), filename, ARG1, s_load); if (FALSEP(reader)) reader = UNDEFINED; #ifndef RECKLESS if (!UNBNDP(reader)) scm_arity_check(reader, 1L, s_load); #endif { SCM oloadpath = *loc_loadpath; SCM oloadports = loadports; SCM form, port; SCM env = EOL; port = open_file(filename, makfromstr("r?", (sizet)2*sizeof(char))); if (FALSEP(port)) return port; *loc_loadpath = filename; loadports = cons(port, loadports); #ifdef SCM_ENV_FILENAME env = scm_env_addprop(SCM_ENV_FILENAME, filename, env); #endif while(1) { if (UNBNDP(reader)) form = scm_read_for_load(port); else form = scm_cvapply(reader, 1L, &port); if (EOF_VAL==form) break; SIDEVAL(form, env, EOL); } close_port(port); loadports = oloadports; *loc_loadpath = oloadpath; } return BOOL_T; } static char s_eval_string[] = "eval-string"; static char s_load_string[] = "load-string"; static SCM i_eval_string = 0; SCM scm_eval_string(str) SCM str; { SCM env = EOL; #ifdef SCM_ENV_FILENAME if (i_eval_string) env = scm_env_addprop(SCM_ENV_FILENAME, i_eval_string, env); #endif str = mkstrport(INUM0, str, OPN | RDNG, s_eval_string); str = scm_read(str); return EVAL(str, env, EOL); } static SCM i_load_string = 0; SCM scm_load_string(str) SCM str; { SCM env = EOL; #ifdef SCM_ENV_FILENAME if (i_load_string) env = scm_env_addprop(SCM_ENV_FILENAME, i_load_string, env); #endif ASRTER(NIMP(str) && (STRINGP(str) || SYMBOLP(str)), str, ARG1, s_load_string); str = mkstrport(INUM0, str, OPN | RDNG, s_load_string); while(1) { SCM form = scm_read_for_load(str); if (EOF_VAL==form) break; SIDEVAL(form, env, EOL); } return BOOL_T; } void scm_line_msg(file, linum, port) SCM file, linum, port; { scm_iprin1(file, port, 1); if (SCM_LINUMP(linum)) { lputs(", line ", port); scm_intprint(SCM_LINUM(linum), -10, port); } lputs(": ", port); } void scm_err_line(what, file, linum, port) const char *what; SCM file, linum, port; { lputs(what, port); if (NIMP(file) && STRINGP(file)) scm_line_msg(file, linum, port); #ifdef CAUTIOUS else { SCM env = scm_env_getprop(SCM_ENV_FILENAME, scm_trace_env); if (NIMP(env)) { file = CAR(env); scm_check_linum(scm_trace, &linum); scm_line_msg(file, linum, port); } } #endif } static void err_head(str) char *str; { SCM lps; int oerrno = errno; exitval = MAKINUM(EXIT_FAILURE); if (NIMP(cur_outp) && OPOUTPORTP(cur_outp)) lfflush(cur_outp); lps = IMP(loadports) ? loadports : CDR(loadports); if (NIMP(lps)) { lputs("\n;In file loaded from ", cur_errp); for (; NIMP(lps); lps = CDR(lps)) { scm_iprin1(scm_port_filename(CAR(lps)), cur_errp, 0); lputs(":", cur_errp); scm_iprin1(scm_port_line(CAR(lps)), cur_errp, 1); lputs(IMP(CDR(lps)) ? ":" : ",\n; loaded from ", cur_errp); } } lputs("\n;", cur_errp); lfflush(cur_errp); errno = oerrno; /* if (NIMP(cur_errp) && stderr==STREAM(cur_errp)) { ... } */ if (errno>0) perror(str); fflush(stderr); } void scm_warn(str1, str2, obj) char *str1, *str2; SCM obj; { err_head("WARNING"); scm_err_line("WARNING: ", UNDEFINED, UNDEFINED, cur_errp); lputs(str1, cur_errp); if (str2 && *str2) { lputs(str2, cur_errp); lputc('\n', cur_errp); } if (!UNBNDP(obj)) { scm_iprin1(obj, cur_errp, 1); lputc('\n', cur_errp); } lfflush(cur_errp); } SCM lerrno(arg) SCM arg; { int old = errno; if (!UNBNDP(arg)) { if (FALSEP(arg)) errno = 0; else errno = INUM(arg); } return MAKINUM(old); } static char s_perror[] = "perror"; SCM lperror(arg) SCM arg; { ASRTER(NIMP(arg) && STRINGP(arg), arg, ARG1, s_perror); err_head(CHARS(arg)); return UNSPECIFIED; } static void def_err_response() { SCM file, env = err_env, obj = *loc_errobj; SCM linum = UNDEFINED; int badport = IMP(cur_errp) || !OPOUTPORTP(cur_errp); int writing = 2; /* Value of 2 used only for printing error messages */ int codep = errobj_codep; DEFER_INTS; if (badport || (errjmp_recursive++)) { if (IMP(def_errp) || !OPOUTPORTP(def_errp)) exit(EXIT_FAILURE); lputs("RECURSIVE ERROR: ", def_errp); if (badport || TYP16(cur_errp)==tc16_sfport) { lputs("reverting from ", def_errp); scm_iprin1(cur_errp, def_errp, 2); lputs("to default error port\n", def_errp); cur_errp = def_errp; errjmp_recursive = 0; } else exit(EXIT_FAILURE); } #ifdef SCM_ENV_FILENAME file = scm_env_getprop(SCM_ENV_FILENAME, env); if (NIMP(file)) file = CAR(file); else file = UNDEFINED; #else file = BOOL_F; #endif if (codep) obj = scm_check_linum(obj, &linum); err_exp = scm_check_linum(err_exp, UNBNDP(linum) ? &linum : 0L); err_head("ERROR"); scm_err_line("ERROR: ", file, linum, cur_errp); if (err_s_subr && *err_s_subr) { lputs(err_s_subr, cur_errp); lputs(": ", cur_errp); } if (!err_pos) return; /* Already been printed */ if (err_pos==(char *)ARG1 && UNBNDP(obj)) err_pos = (char *)WNA; #ifdef nosve if ((~0x1fL) & (short)err_pos) lputs(err_pos, cur_errp); else if (WNA > (short)err_pos) { lputs("Wrong type in arg", cur_errp); lputc((short)err_pos <= ARGn ? ' ' : '1' + (short)err_pos - ARG1, cur_errp); } #else if ((~0x1fL) & (long)err_pos) lputs(err_pos, cur_errp); else if (WNA > (long)err_pos) { lputs("Wrong type in arg", cur_errp); lputc((long)err_pos <= ARGn ? ' ' : '1' + (int)err_pos - ARG1, cur_errp); } #endif else lputs(errmsgs[((int)err_pos)-WNA].msg, cur_errp); lputs(((long)err_pos==WNA)?" given ":" ", cur_errp); err_pos = 0; if (!UNBNDP(obj)) if (reset_safeport(sys_safep, 55, cur_errp)) if (0==setjmp(SAFEP_JMPBUF(sys_safep))) { if (codep) scm_princode(obj, EOL, sys_safep, writing); else scm_iprin1(obj, sys_safep, writing); } if (UNBNDP(err_exp)) goto getout; if (NIMP(err_exp)) { if (reset_safeport(sys_safep, 55, cur_errp)) if (0==setjmp(SAFEP_JMPBUF(sys_safep))) { lputs("\n; in expression: ", cur_errp); if (NCONSP(err_exp)) scm_princode(err_exp, env, sys_safep, writing); else if (UNDEFINED==CDR(err_exp)) scm_iprin1(CAR(err_exp), sys_safep, writing); else { if (UNBNDP(env)) scm_iprlist("(... ", err_exp, ')', sys_safep, writing); else scm_princode(err_exp, env, sys_safep, writing); } } } scm_scope_trace(env); getout: #ifdef CAUTIOUS scm_stack_trace(UNDEFINED); #endif lputc('\n', cur_errp); lfflush(cur_errp); err_exp = err_env = UNDEFINED; if (errjmp_bad) { lputs("\nFATAL ERROR DURING CRITICAL CODE SECTION: ", cur_errp); lputs(errjmp_bad, cur_errp); lputc('\n', cur_errp); lroom(BOOL_T); #ifdef vms exit(EXIT_FAILURE); #else exit(errno? (long)errno : EXIT_FAILURE); #endif } errno = 0; ALLOW_INTS; } void everr(exp, env, arg, pos, s_subr, codep) SCM exp, env, arg; const char *pos, *s_subr; int codep; { err_exp = exp; err_env = env; *loc_errobj = arg; err_pos = pos; err_s_subr = s_subr; errobj_codep = codep; if (errjmp_bad || errjmp_recursive) def_err_response(); longjump(CONT(rootcont)->jmpbuf, (~0x1fL) & (long)pos || (WNA > (long)pos) ? COOKIE(1) : COOKIE((int)pos)); /* will do error processing at stack base */ } void wta(arg, pos, s_subr) SCM arg; const char *pos, *s_subr; { #ifndef RECKLESS everr(scm_trace, scm_trace_env, arg, pos, s_subr, 0); #else everr(UNDEFINED, EOL, arg, pos, s_subr, 0); #endif } void scm_experr(arg, pos, s_subr) SCM arg; const char *pos, *s_subr; { #ifndef RECKLESS everr(scm_trace, scm_trace_env, arg, pos, s_subr, !0); #else everr(UNDEFINED, EOL, arg, pos, s_subr, !0); #endif } SCM cur_input_port() { return cur_inp; } SCM cur_output_port() { return cur_outp; } SCM cur_error_port() { return cur_errp; } char s_cur_inp[] = "set-current-input-port"; char s_cur_outp[] = "set-current-output-port"; char s_cur_errp[] = "set-current-error-port"; SCM set_inp(port) SCM port; { SCM oinp; ASRTER(NIMP(port) && INPORTP(port), port, ARG1, s_cur_inp); DEFER_INTS; oinp = cur_inp; cur_inp = port; ALLOW_INTS; return oinp; } SCM set_outp(port) SCM port; { SCM ooutp; ASRTER(NIMP(port) && OUTPORTP(port), port, ARG1, s_cur_outp); DEFER_INTS; ooutp = cur_outp; cur_outp = port; ALLOW_INTS; return ooutp; } SCM set_errp(port) SCM port; { SCM oerrp; ASRTER(NIMP(port) && OUTPORTP(port), port, ARG1, s_cur_errp); DEFER_INTS; oerrp = cur_errp; cur_errp = port; ALLOW_INTS; return oerrp; } static char s_isatty[] = "isatty?"; SCM l_isatty(port) SCM port; { int fn; ASRTER(NIMP(port) && OPPORTP(port), port, ARG1, s_isatty); if (tc16_fport != TYP16(port)) return BOOL_F; fn = fileno(STREAM(port)); return (fn >= 0 && isatty(fn)) ? BOOL_T : BOOL_F; } static iproc subr0s[] = { {&s_cur_inp[4], cur_input_port}, {&s_cur_outp[4], cur_output_port}, {&s_cur_errp[4], cur_error_port}, {"program-arguments", prog_args}, {"line-number", line_num}, {"abort", abrt}, {s_restart, restart}, {0, 0}}; static iproc subr1s[] = { {s_cur_inp, set_inp}, {s_cur_outp, set_outp}, {s_cur_errp, set_errp}, {s_load_string, scm_load_string}, {s_eval_string, scm_eval_string}, {s_perror, lperror}, {"make-arbiter", makarb}, {s_tryarb, tryarb}, {s_relarb, relarb}, {s_isatty, l_isatty}, {s_port_line, scm_port_line}, {s_port_col, scm_port_col}, {s_port_filename, scm_port_filename}, {0, 0}}; static iproc subr1os[] = { {s_read_char, scm_read_char}, {s_peek_char, scm_peek_char}, {s_newline, scm_newline}, {s_freshline, scm_freshline}, {s_force_output, scm_force_output}, {s_char_readyp, char_readyp}, {"quit", quit}, {"verbose", prolixity}, {"errno", lerrno}, {"room", lroom}, {0, 0}}; static iproc subr2os[] = { {s_write, scm_write}, {s_display, scm_display}, {s_write_char, scm_write_char}, {s_tryload, tryload}, {s_file_position, scm_file_position}, #ifdef CAN_DUMP {s_unexec, scm_unexec}, #endif {0, 0}}; static smobfuns arbsmob = {markcdr, free0, prinarb}; char s_ccl[] = "char-code-limit"; void init_repl( iverbose ) int iverbose; { sysintern(s_ccl, MAKINUM(CHAR_CODE_LIMIT)); i_repl = CAR(sysintern("repl", UNDEFINED)); loc_errobj = &CDR(sysintern("errobj", UNDEFINED)); loc_loadpath = &CDR(sysintern("*load-pathname*", BOOL_F)); loc_loadsharp = &CDR(sysintern("load:sharp", UNDEFINED)); loc_readsharp = &CDR(sysintern("read:sharp", UNDEFINED)); loc_charsharp = &CDR(sysintern("char:sharp", UNDEFINED)); loc_broken_pipe = &CDR(sysintern("broken-pipe", UNDEFINED)); scm_verbose = iverbose; init_iprocs(subr0s, tc7_subr_0); init_iprocs(subr1os, tc7_subr_1o); init_iprocs(subr1s, tc7_subr_1); init_iprocs(subr2os, tc7_subr_2o); add_feature(s_char_readyp); make_subr(s_swapcar, tc7_subr_2, swapcar); make_subr(s_wfi, tc7_lsubr, wait_for_input); #ifndef MEMOIZE_LOCALS p_read_numbered = make_subr(s_read_numbered, tc7_subr_1, scm_read_numbered); #endif p_read_for_load = make_subr(s_read_for_load, tc7_subr_1, scm_read_for_load); p_read = make_subr(s_read, tc7_subr_1o, scm_read); i_eval_string = CAR(sysintern(s_eval_string, UNDEFINED)); i_load_string = CAR(sysintern(s_load_string, UNDEFINED)); scm_ldstr("\n\ (define file-set-position file-position)\n\ "); #ifdef CAN_DUMP add_feature("dump"); scm_ldstr("\ (define (dump file . thunk)\n\ (cond ((null? thunk) (set! *interactive* #f) (set! *argv* #f))\n\ ((not (car thunk)) (set! *argv* #f))\n\ ((boolean? (car thunk)))\n\ (else (set! boot-tail (lambda (t) ((car thunk))))))\n\ (set! restart exec-self)\n\ (require #f)\n\ (unexec file))\n\ "); #endif #ifdef ARM_ULIB set_erase(); #endif tc16_arbiter = newsmob(&arbsmob); } void final_repl() { i_eval_string = i_load_string = 0; loc_errobj = (SCM *)&tmp_errobj; loc_loadpath = (SCM *)&tmp_loadpath; loadports = EOL; }