Article View: comp.lang.lisp.x
Article #242Re: Caling XLISP frling XLISP from C - help requested
From: Niels Mayer
Date: Wed, 23 Jan 1991 21:25
Date: Wed, 23 Jan 1991 21:25
147 lines
6094 bytes
6094 bytes
In article <1218@prlhp1.prl.philips.co.uk> colers@prl.philips.co.uk writes:
>Hi Folks,
> we are trying to make a version of XLISP that can be called
>from a C program as a function call (to a modified eval loop that only
>evals once and then returns so we need to pass it something to
>evaluate). As far as we can see there are two avenues we could persue;
>if someone can provide a definition of exactly what goes in an LVAL
>structure we could modify xeval. Alternatively we could modify the file
>reading function instead.
>
>Has anyone already done this ? (hope hope :-) ) or can anyone shed any
>light as to what goes into LVAL ?
I've done this in WINTERP Motif Widget INTERPreter (anon ftp from host
expo.lcs.mit.edu directory contrib/winterp file winterp-1.01.tar.Z).
The following code fragment reads a lisp s-expression from a socket, turns
it into an XLISP unnamed stream. xlread() then reads from that stream as if
it were reading input from a FILE*, and xleval() evaluates the read
s-expression.
Although transforming character strings into an unnamed stream is somewhat
inefficient, it allows you to interface with xlisp's reader with a minimum
of changes to XLISP itself. I wanted to avoid modifications to xleval() and
xlread() because the changes required would be extensive, and because I
didn't want to support a version of XLISP that diverges from the
"standard".
.
.
.
int rdsock;
static char rdbuf[BUFSIZ];
.
.
.
{
/*
* Read the sexpression from the socket -- note assumption that entire
* sexpression is sent in one "packet" and then the socket is closed.
*/
int len, i;
LVAL sexp_stream, new_elt, last_elt = NIL;
xlsave1(sexp_stream); /* protect from gc */
sexp_stream = newustream(); /* note - stream obj has ptrs for head and tail*/
while (len = recv(rdsock, rdbuf, BUFSIZ, 0)) { /* read len characters into rdbuf */
if (len < 0) {
perror(app_name);
sprintf(temptext, "%s: unable to recv\n", app_name);
xlfatal(temptext); /* CLEANUP & EXIT */
}
/* foreach character received, stuff it into an xlisp unnamed stream */
for (i = 0; i < len; i++) {
new_elt = cons(cvchar(rdbuf[i]), NIL);
if (last_elt) { /* if we've already created the head of the stream */
rplacd(last_elt, new_elt); /* add new_elt to the tail of the list */
last_elt = new_elt; /* increment last_elt pointer */
}
else { /* else create the head of the stream */
sethead(sexp_stream, new_elt);
last_elt = new_elt;
}
}
}
close(rdsock); /* we've finished reading from the socket */
if (last_elt)
settail(sexp_stream, last_elt); /* streams are cdr-coded -- give ptr to tail */
else
sexp_stream = NIL; /* loop never executed, no characters read. */
lisp_reader_hit_eof = !(Read_From_Stream_Eval_And_Print(sexp_stream));
xlpop(); /*sexp_stream*/
}
/*******************************************************************************
* This fn reads from its input, which is assumed to be a xlisp stream.
* returns false if EOF hit during read.
******************************************************************************/
int Read_From_Stream_Eval_And_Print(sexp_stream)
LVAL sexp_stream; /* make sure this is a stream, and not other LVAL */
{
extern int xldebug;
extern LVAL s_1plus,s_2plus,s_3plus,s_1star,s_2star,s_3star,s_minus;
LVAL rep_expr;
int read_result;
xlprot1(sexp_stream); /* protect against GC */
/* Read Evaluate and Print the expression in sexp_stream */
if ((read_result = xlread(sexp_stream, &rep_expr, FALSE))) {
/* save the last expression returned by the reader */
setvalue(s_3plus, getvalue(s_2plus));
setvalue(s_2plus, getvalue(s_1plus));
setvalue(s_1plus, getvalue(s_minus));
setvalue(s_minus, rep_expr);
/* evaluate the expression returned by the reader */
rep_expr = xleval(rep_expr);
/* save the last expression returned by the evaluator */
setvalue(s_3star,getvalue(s_2star));
setvalue(s_2star,getvalue(s_1star));
setvalue(s_1star,rep_expr);
if (xldebug) /* print eval results */
dbgprint(rep_expr);
else
stdprint(rep_expr);
}
else { /* if reader hit EOF, just print a new line */
if (xldebug)
dbgputstr("\n");
else
stdputstr("\n");
}
xlpop(/*sexp_stream*/);
return (read_result); /* return FALSE if hit EOF */
}
--------------------
Homework for the reader:
(1) it should be trivial to modify the code above to
read from a C character array, instead of a socket.
(2) you need to consider where to set up Xlisp's error
return longjmp() target (see xlisp.c and xldbug.c for examples).
If the C call to the Xlisp evaluator causes an error, you should
have a place in your program where execution can do a stack unwind in an
orderly fashion. I have a hack in winterp.c:main() and xlisp/xldbug.c
that does this for event driven programs such as those running under
the X toolkit (e.g. WINTERP). There are comments in the code that should
help you do what you're trying to do.
-------------------------------------------------------------------------------
Niels Mayer -- hplabs!mayer -- mayer@hplabs.hp.com
Human-Computer Interaction Department
Hewlett-Packard Laboratories
Palo Alto, CA.
*
Technical Details
Message-ID:
<6492@hplabsz.HP.COM>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sun-barr!olivea!samsung!usc!ucsd!ucbvax!hplabs!hplabsz!mayerReferences:
<1218@prlhp1.prl.philips.co.uk>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sun-barr!olivea!samsung!usc!ucsd!ucbvax!hplabs!hplabsz!mayer From: mayer@hplabsz.HP.COM (Niels Mayer) Newsgroups: comp.lang.lisp.x Subject: Re: Caling XLISP frling XLISP from C - help requested Message-ID: <6492@hplabsz.HP.COM> Date: 23 Jan 91 21:25:56 GMT References: <1218@prlhp1.prl.philips.co.uk> Reply-To: mayer@hplabs.hp.com (Niels Mayer) Organization: Hewlett-Packard Labs, Software & Systems Lab, Palo Alto, CA. Lines: 147