Path: 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 Summary: Expires: Sender: Followup-To: Distribution: Keywords: 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. *