🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.lisp.x
Article #242

Re: Caling XLISP frling XLISP from C - help requested

#242
From: Niels Mayer
Date: Wed, 23 Jan 1991 21:25
147 lines
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!mayer
References: <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