/************************************************************************* * * lispIO.c -- * * This module contains the builtin mini-scheme I/O functions. * * (c) 1996 California Institute of Technology * Department of Computer Science * Pasadena, CA 91125. * * Permission to use, copy, modify, and distribute this software * and its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice appear in all * copies. The California Institute of Technology makes no representations * about the suitability of this software for any purpose. It is * provided "as is" without express or implied warranty. Export of this * software outside of the United States of America may require an * export license. * * $Header$ * *************************************************************************/ #include #include #include "lisp/lisp.h" #include "lispInt.h" #include "lispargs.h" #include "textio/textio.h" #include "utils/malloc.h" #include "utils/utils.h" #include "utils/signals.h" /*----------------------------------------------------------------------------- * * LispLoad -- * * ("load-scm" "filename") * Reads and evaluates file. * * * Results: * #t => file was opened successfully. * #f => failure. * * Side effects: * None. * *----------------------------------------------------------------------------- */ LispObj * LispLoad (name,s,f) char *name; Sexp *s; Sexp *f; { extern int LispEchoResult; LispObj *l, *inp, *res; FILE *fp; int val, pos; char *buffer, *tmp; int buflen; int nest; int line; if (!ARG1P(s) || LTYPE(ARG1(s)) != S_STRING || ARG2P(s)) { TxPrintf ("Usage: (%s string)\n", name); RETURN; } l = LispFrameLookup (LispNewString ("scm-library-path"), f); if (!l) tmp = NULL; else if (LTYPE(l) != S_STRING) { TxPrintf ("%s: scm-library-path is not a string\n", name); RETURN; } else tmp = LSTR(l); if (!(fp = PaOpen (LSTR(ARG1(s)), "r", NULL, ".", tmp, NULL))) { TxPrintf ("%s: could not open file %s for reading\n",name,LSTR(ARG1(s))); l = LispNewObj (); LTYPE(l) = S_BOOL; LBOOL(l) = 0; RETURN; } LispGCAddSexp (s); buffer = (char *) mallocMagic((unsigned) (buflen = 4096)); pos = 0; nest = 0; line = 1; while ((val = fgetc (fp)) != EOF) { if (pos == buflen) { int i; /* extend buffer */ tmp = buffer; buflen += 1024; buffer = (char *) mallocMagic((unsigned) buflen); for (i=0; i < pos; i++) buffer[i] = tmp[i]; freeMagic(tmp); } if (val == ';') { /* skip to eol */ while ((val = fgetc(fp)) != EOF && val != '\n') ; if (val == '\n') line++; continue; } if (val == '\n') line++; if (val == '\t' || val == '\n') val = ' '; /* skip white space at nesting level zero */ if (nest == 0 && isspace (val)) continue; if (nest == 0 && val != '(') { TxPrintf ("Error reading file %s, line %d\n", LSTR(ARG1(s)), line); l = LispNewObj (); LTYPE(l) = S_BOOL; LBOOL(l) = 0; freeMagic(buffer); fclose (fp); LispGCRemoveSexp (s); RETURN; } buffer[pos++] = val; if (val == '(') nest++; else if (val == ')') { nest--; if (nest == 0) { buffer[pos] = '\0'; inp = LispParseString (buffer); if (inp) { res = LispEval (inp, f); inp = LispFrameLookup (LispNewString ("scm-echo-result"), f); if (res && inp && LTYPE(inp) == S_BOOL && LBOOL(inp)) { LispPrint (stdout,res); TxPrintf ("\n"); } if (!res) { if (!SigInterruptPending) TxPrintf ("Error evaluating file %s, line %d\n", LSTR(ARG1(s)), line); freeMagic(buffer); fclose (fp); LispGCRemoveSexp (s); RETURN; } } else { TxPrintf ("Error parsing file %s, line %d\n", LSTR(ARG1(s)), line); freeMagic(buffer); fclose (fp); LispGCRemoveSexp (s); RETURN; } pos = 0; } if (nest < 0) { TxPrintf ("Error reading file %s, line %d\n", LSTR(ARG1(s)), line); l = LispNewObj (); LTYPE(l) = S_BOOL; LBOOL(l) = 0; freeMagic(buffer); fclose (fp); LispGCRemoveSexp (s); return l; } } else if (val == '\"') { while ((val = fgetc (fp)) != EOF && val != '\"') { if (val == '\n') line++; if (pos > buflen-1) { /* extend buffer */ int i; tmp = buffer; buflen += 1024; buffer = (char *) mallocMagic((unsigned) (buflen)); for (i=0; i < pos; i++) buffer[i] = tmp[i]; freeMagic(tmp); } buffer[pos++] = val; if (val == '\\') { val = fgetc (fp); buffer[pos++] = val; if (val == '\n') line++; } } if (val == EOF) { TxPrintf ("Error reading file %s, line %d\n", LSTR(ARG1(s)), line); freeMagic(buffer); fclose (fp); LispGCRemoveSexp (s); RETURN; } buffer[pos++] = val; } } freeMagic(buffer); fclose (fp); if (pos > 0) { TxPrintf ("Error reading file %s, line %d\n", LSTR(ARG1(s)), line); LispGCRemoveSexp (s); RETURN; } else { LispGCRemoveSexp (s); l = LispNewObj (); LTYPE(l) = S_BOOL; LBOOL(l) = 1; } return l; } /*----------------------------------------------------------------------------- * * LispWrite -- * * Write an object to a file. * * Results: * none. * * Side effects: * None. * *----------------------------------------------------------------------------- */ LispObj * LispWrite (name,s,f) char *name; Sexp *s; Sexp *f; { FILE *fp; LispObj *l; if (!ARG1P(s) || LTYPE(ARG1(s)) != S_STRING || !ARG2P(s) || ARG3P(s)) { TxPrintf ("Usage: (%s str obj)\n", name); RETURN; } if (!(fp = PaOpen (LSTR(ARG1(s)), "a", NULL, ".", NULL, NULL))) { TxPrintf ("%s: could not open file %s for writing\n",name,LSTR(ARG1(s))); RETURN; } fprintf (fp, ";\n"); LispPrint (fp,ARG2(s)); fprintf (fp, "\n"); fclose (fp); l = LispNewObj (); LTYPE(l) = S_BOOL; LBOOL(l) = 1; return l; } /*----------------------------------------------------------------------------- * * LispSpawn -- * * (spawn list-of-strings) * Reads and evaluates file. * * * Results: * pid => the pid of the spawned process. * -1 => if spawn failed. * * Side effects: * None. * *----------------------------------------------------------------------------- */ LispObj * LispSpawn (name,s,f) char *name; Sexp *s; Sexp *f; { LispObj *l; int pid; Sexp *t; char **argv; int n; if (!ARG1P(s)) { TxPrintf ("Usage: (%s string-list)\n", name); RETURN; } t = s; n = 1; while (ARG1P(t)) { if (LTYPE(CAR(t)) != S_STRING) { TxPrintf ("Usage: (%s string-list)\n", name); RETURN; } n++; t = LLIST(CDR(t)); } argv = (char **) mallocMagic((unsigned) (sizeof(char*)*n)); t = s; n = 0; while (ARG1P(t)) { argv[n] = LSTR(CAR(t)); n++; t = LLIST(CDR(t)); } argv[n] = NULL; FORK_f(pid); if (pid < 0) { TxPrintf ("Error: could not fork a process!\n"); freeMagic(argv); RETURN; } else if (pid == 0) { int i; /* try closing all files, so that we don't mess up the state of the parent */ for (i=3; i < 256; i++) close (i); execvp (argv[0], argv); _exit (1000); } freeMagic(argv); l = LispNewObj (); LTYPE(l) = S_INT; LINTEGER(l) = pid; return l; } /*----------------------------------------------------------------------------- * * LispWait -- * * (wait pid) * Wait for pid to terminate. * * Results: * The status, error if the pid is an invalid pid. * * Side effects: * None. * *----------------------------------------------------------------------------- */ LispObj * LispWait (name,s,f) char *name; Sexp *s; Sexp *f; { LispObj *l; int stat; if (!ARG1P(s) || LTYPE(ARG1(s)) != S_INT) { TxPrintf ("Usage: (%s pid)\n", name); RETURN; } if (WaitPid (LINTEGER(ARG1(s)), &stat) < 0) { TxPrintf ("%s: waiting for an invalid pid\n", name); RETURN; } l = LispNewObj (); LTYPE(l) = S_INT; LINTEGER(l) = stat; return l; }