magic/lisp/lispIO.c

382 lines
8.1 KiB
C

/*************************************************************************
*
* 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 <stdio.h>
#include <stdlib.h>
#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;
}