xlisp1.txt - new xlisp release
utzoo!decvax!betz
utzoo!decvax!betz
Thu Mar 31 20:37:58 AEST 1983
<<<<<<<<<< xlbind.c >>>>>>>>>>
/* xlbind - xlisp symbol binding routines */
#include <stdio.h>
#include "xlisp.h"
/* global variables */
struct node *xlenv;
/* xlunbind - unbind symbols bound in this environment */
xlunbind(env)
struct node *env;
{
struct node *bnd;
/* unbind each symbol in the environment chain */
for (; xlenv != env; xlenv = xlenv->n_listnext) {
bnd = xlenv->n_listvalue;
bnd->n_bndsym->n_symvalue = bnd->n_bndvalue;
}
}
/* xlbind - bind a symbol to a value */
xlbind(sym,val)
struct node *sym,*val;
{
struct node *lptr,*bptr;
/* create a new environment list entry */
lptr = newnode(LIST);
lptr->n_listnext = xlenv;
xlenv = lptr;
/* create a new variable binding */
lptr->n_listvalue = bptr = newnode(LIST);
bptr->n_bndsym = sym;
bptr->n_bndvalue = val;
}
/* xlfixbindings - make a new set of bindings visible */
xlfixbindings(env)
struct node *env;
{
struct node *eptr,*bnd,*sym,*oldvalue;
/* fix the bound value of each symbol in the environment chain */
for (eptr = xlenv; eptr != env; eptr = eptr->n_listnext) {
bnd = eptr->n_listvalue;
sym = bnd->n_bndsym;
oldvalue = sym->n_symvalue;
sym->n_symvalue = bnd->n_bndvalue;
bnd->n_bndvalue = oldvalue;
}
}
<<<<<<<<<< xldmem.c >>>>>>>>>>
/* xldmem - xlisp dynamic memory management routines */
#include <stdio.h>
#include "xlisp.h"
/* useful definitions */
#define ALLOCSIZE (sizeof(struct segment) + anodes * sizeof(struct node))
/* memory segment structure definition */
struct segment {
int sg_size;
struct segment *sg_next;
struct node sg_nodes[];
};
/* external variables */
extern struct node *oblist;
extern struct node *xlstack;
extern struct node *xlenv;
/* external procedures */
extern char *malloc();
extern char *calloc();
/* local variables */
int anodes,nnodes,nsegs,nfree,gccalls;
static struct segment *segs;
static struct node *fnodes;
/* newnode - allocate a new node */
struct node *newnode(type)
int type;
{
struct node *nnode;
/* get a free node */
if ((nnode = fnodes) == NULL) {
gc();
if ((nnode = fnodes) == NULL)
xlfail("insufficient node space");
}
/* unlink the node from the free list */
fnodes = nnode->n_right;
nfree -= 1;
/* initialize the new node */
nnode->n_type = type;
nnode->n_left = NULL;
nnode->n_right = NULL;
/* return the new node */
return (nnode);
}
/* stralloc - allocate memory for a string adding a byte for the terminator */
char *stralloc(size)
int size;
{
char *sptr;
/* allocate memory for the string copy */
if ((sptr = malloc(size+1)) == NULL) {
gc();
if ((sptr = malloc(size+1)) == NULL)
xlfail("insufficient string space");
}
/* return the new string memory */
return (sptr);
}
/* strsave - generate a dynamic copy of a string */
char *strsave(str)
char *str;
{
char *sptr;
/* create a new string */
sptr = stralloc(strlen(str));
strcpy(sptr,str);
/* return the new string */
return (sptr);
}
/* strfree - free string memory */
strfree(str)
char *str;
{
free(str);
}
/* gc - garbage collect */
static gc()
{
/* unmark all nodes */
unmark();
/* mark all accessible nodes */
mark(oblist);
mark(xlstack);
mark(xlenv);
/* sweep memory collecting all unmarked nodes */
sweep();
/* if there's still nothing available, allocate more memory */
if (fnodes == NULL)
addseg();
/* count the gc call */
gccalls += 1;
}
/* unmark - unmark each node */
static unmark()
{
struct node *n;
/* unmark the stack */
for (n = xlstack; n != NULL ; n = n->n_listnext)
n->n_flags &= ~(MARK | LEFT);
}
/* mark - mark all accessible nodes */
static mark(ptr)
struct node *ptr;
{
struct node *this,*prev,*tmp;
/* just return on null */
if (ptr == NULL)
return;
/* initialize */
prev = NULL;
this = ptr;
/* mark this list */
while (TRUE) {
/* descend as far as we can */
while (TRUE) {
/* check for this node being marked */
if (this->n_flags & MARK)
break;
/* mark it and its descendants */
else {
/* mark the node */
this->n_flags |= MARK;
/* follow the left sublist if there is one */
if (left(this)) {
this->n_flags |= LEFT;
tmp = prev;
prev = this;
this = prev->n_left;
prev->n_left = tmp;
}
else if (right(this)) {
this->n_flags &= ~LEFT;
tmp = prev;
prev = this;
this = prev->n_right;
prev->n_right = tmp;
}
else
break;
}
}
/* backup to a point where we can continue descending */
while (TRUE) {
/* check for termination condition */
if (prev == NULL)
return;
/* check for coming from the left side */
if (prev->n_flags & LEFT)
if (right(prev)) {
prev->n_flags &= ~LEFT;
tmp = prev->n_left;
prev->n_left = this;
this = prev->n_right;
prev->n_right = tmp;
break;
}
else {
tmp = prev;
prev = tmp->n_left;
tmp->n_left = this;
this = tmp;
}
/* came from the right side */
else {
tmp = prev;
prev = tmp->n_right;
tmp->n_right = this;
this = tmp;
}
}
}
}
/* sweep - sweep all unmarked nodes and add them to the free list */
static sweep()
{
struct segment *seg;
struct node *n;
int i;
/* empty the free list */
fnodes = NULL;
nfree = 0;
/* add all unmarked nodes */
for (seg = segs; seg != NULL; seg = seg->sg_next)
for (i = 0; i < seg->sg_size; i++)
if (!((n = &seg->sg_nodes[i])->n_flags & MARK)) {
switch (n->n_type) {
case STR:
if (n->n_strtype == DYNAMIC && n->n_str != NULL)
strfree(n->n_str);
break;
case SYM:
if (n->n_symname != NULL)
strfree(n->n_symname);
break;
case KMAP:
xlkmfree(n);
break;
}
n->n_type = FREE;
n->n_left = NULL;
n->n_right = fnodes;
fnodes = n;
nfree += 1;
}
else
n->n_flags &= ~MARK;
}
/* addseg - add a segment to the available memory */
static int addseg()
{
struct segment *newseg;
int i;
/* allocate a new segment */
if ((newseg = (struct segment *) calloc(1,ALLOCSIZE)) != NULL) {
/* initialize the new segment */
newseg->sg_size = anodes;
newseg->sg_next = segs;
segs = newseg;
/* add each new node to the free list */
for (i = 0; i < newseg->sg_size; i++) {
newseg->sg_nodes[i].n_right = fnodes;
fnodes = &newseg->sg_nodes[i];
}
/* update the statistics */
nnodes += anodes;
nfree += anodes;
nsegs += 1;
/* return successfully */
return (TRUE);
}
else
return (FALSE);
}
/* left - check for a left sublist */
static int left(n)
struct node *n;
{
switch (n->n_type) {
case SYM:
case SUBR:
case INT:
case STR:
case FPTR:
return (FALSE);
case KMAP:
xlkmmark(n);
return (FALSE);
case LIST:
case OBJ:
return (n->n_left != NULL);
default:
printf("bad node type (%d) found during left scan\n",n->n_type);
exit();
}
}
/* right - check for a right sublist */
static int right(n)
struct node *n;
{
switch (n->n_type) {
case SUBR:
case INT:
case STR:
case FPTR:
case KMAP:
return (FALSE);
case SYM:
case LIST:
case OBJ:
return (n->n_right != NULL);
default:
printf("bad node type (%d) found during right scan\n",n->n_type);
exit();
}
}
/* stats - print memory statistics */
static stats()
{
putchar('\n');
printf("Nodes: %d\n",nnodes);
printf("Free nodes: %d\n",nfree);
printf("Segments: %d\n",nsegs);
printf("Allocate: %d\n",anodes);
printf("Collections: %d\n",gccalls);
putchar('\n');
}
/* fgc - xlisp function to force garbage collection */
static struct node *fgc(args)
struct node *args;
{
/* make sure there aren't any arguments */
xllastarg(args);
/* garbage collect */
gc();
/* return null */
return (NULL);
}
/* fexpand - xlisp function to force memory expansion */
static struct node *fexpand(args)
struct node *args;
{
struct node *val;
int n,i;
/* get the new number to allocate */
if (args == NULL)
n = 1;
else
n = xlevmatch(INT,&args)->n_int;
/* make sure there aren't any more arguments */
xllastarg(args);
/* allocate more segments */
for (i = 0; i < n; i++)
if (!addseg())
break;
/* return the number of segments added */
val = newnode(INT);
val->n_int = i;
return (val);
}
/* falloc - xlisp function to set the number of nodes to allocate */
static struct node *falloc(args)
struct node *args;
{
struct node *val;
int n,oldn;
/* get the new number to allocate */
n = xlevmatch(INT,&args)->n_int;
/* make sure there aren't any more arguments */
xllastarg(args);
/* set the new number of nodes to allocate */
oldn = anodes;
anodes = n;
/* return the old number */
val = newnode(INT);
val->n_int = oldn;
return (val);
}
/* fmem - xlisp function to print memory statistics */
static struct node *fmem(args)
struct node *args;
{
/* make sure there aren't any arguments */
xllastarg(args);
/* print the statistics */
stats();
/* return null */
return (NULL);
}
/* xldmeminit - initialize the dynamic memory module */
xldmeminit()
{
/* setup the default number of nodes to allocate */
anodes = NNODES;
nnodes = nsegs = nfree = gccalls = 0;
/* define some xlisp functions */
xlsubr("gc",fgc);
xlsubr("expand",fexpand);
xlsubr("alloc",falloc);
xlsubr("mem",fmem);
}
<<<<<<<<<< xleval.c >>>>>>>>>>
/* xleval - xlisp evaluator */
#include <stdio.h>
#include <setjmp.h>
#include "xlisp.h"
/* global variables */
struct node *xlstack;
/* trace stack */
static struct node *trace_stack[TDEPTH];
static int trace_pointer;
/* external variables */
extern jmp_buf xljmpbuf;
extern struct node *xlenv;
/* local variables */
static struct node *slash;
/* forward declarations (the extern hack is for decusc) */
extern struct node *evlist();
extern struct node *evsym();
extern struct node *evfun();
/* eval - the builtin function 'eval' */
static struct node *eval(args)
struct node *args;
{
struct node *expr;
/* get the expression to evaluate */
expr = xlevarg(&args);
/* make sure there aren't any more arguments */
xllastarg(args);
/* return the expression evaluated */
return (xleval(expr));
}
/* xleval - evaluate an xlisp expression */
struct node *xleval(expr)
struct node *expr;
{
/* evaluate null to itself */
if (expr == NULL)
return (NULL);
/* check type of value */
switch (expr->n_type) {
case LIST:
return (evlist(expr));
case SYM:
return (evsym(expr));
case INT:
case STR:
case SUBR:
return (expr);
default:
xlfail("can't evaluate expression");
}
}
/* xlsave - save nodes on the stack */
struct node *xlsave(n)
struct node *n;
{
struct node **nptr,*oldstk;
/* save the old stack pointer */
oldstk = xlstack;
/* save each node */
for (nptr = &n; *nptr != NULL; nptr++) {
(*nptr)->n_type = LIST;
(*nptr)->n_listvalue = NULL;
(*nptr)->n_listnext = xlstack;
xlstack = *nptr;
}
/* return the old stack pointer */
return (oldstk);
}
/* evlist - evaluate a list */
static struct node *evlist(nptr)
struct node *nptr;
{
struct node *oldstk,fun,args,*val;
/* create a stack frame */
oldstk = xlsave(&fun,&args,NULL);
/* get the function and the argument list */
fun.n_ptr = nptr->n_listvalue;
args.n_ptr = nptr->n_listnext;
/* add trace entry */
tpush(nptr);
/* evaluate the first expression */
if ((fun.n_ptr = xleval(fun.n_ptr)) == NULL)
xlfail("null function");
/* evaluate the function */
switch (fun.n_ptr->n_type) {
case SUBR:
val = (*fun.n_ptr->n_subr)(args.n_ptr);
break;
case LIST:
val = evfun(fun.n_ptr,args.n_ptr);
break;
case OBJ:
val = xlsend(fun.n_ptr,args.n_ptr);
break;
default:
xlfail("bad function");
}
/* restore the previous stack frame */
xlstack = oldstk;
/* remove trace entry */
tpop();
/* return the result value */
return (val);
}
/* evsym - evaluate a symbol */
static struct node *evsym(sym)
struct node *sym;
{
struct node *lptr;
/* check for a current object */
if ((lptr = xlobsym(sym)) != NULL)
return (lptr->n_listvalue);
else
return (sym->n_symvalue);
}
/* evfun - evaluate a function */
static struct node *evfun(fun,args)
struct node *fun,*args;
{
struct node *oldenv,*oldstk,cptr,*val;
/* create a stack frame */
oldstk = xlsave(&cptr,NULL);
/* bind the formal parameters */
oldenv = xlenv;
xlabind(fun->n_listvalue,args);
xlfixbindings(oldenv);
/* execute the code */
for (cptr.n_ptr = fun->n_listnext; cptr.n_ptr != NULL; )
val = xlevarg(&cptr.n_ptr);
/* restore the environment */
xlunbind(oldenv);
/* restore the previous stack frame */
xlstack = oldstk;
/* return the result value */
return (val);
}
/* xlabind - bind the arguments for a function */
xlabind(fargs,aargs)
struct node *fargs,*aargs;
{
struct node *oldstk,farg,aarg,val;
/* create a stack frame */
oldstk = xlsave(&farg,&aarg,&val,NULL);
/* initialize the pointers */
farg.n_ptr = fargs;
aarg.n_ptr = aargs;
/* evaluate and bind each argument */
while (farg.n_ptr != NULL && aarg.n_ptr != NULL) {
/* check for local variable separator */
if (farg.n_ptr->n_listvalue == slash)
break;
/* evaluate the argument */
val.n_ptr = xlevarg(&aarg.n_ptr);
/* bind the formal variable to the argument value */
xlbind(farg.n_ptr->n_listvalue,val.n_ptr);
/* move the formal argument list pointer ahead */
farg.n_ptr = farg.n_ptr->n_listnext;
}
/* check for local variables */
if (farg.n_ptr != NULL && farg.n_ptr->n_listvalue == slash)
while ((farg.n_ptr = farg.n_ptr->n_listnext) != NULL)
xlbind(farg.n_ptr->n_listvalue,NULL);
/* restore the previous stack frame */
xlstack = oldstk;
/* make sure the correct number of arguments were supplied */
if (farg.n_ptr != aarg.n_ptr)
xlfail("incorrect number of arguments to a function");
}
/* xlfail - error handling routine */
xlfail(err)
char *err;
{
/* print the error message */
printf("error: %s\n",err);
/* unbind bound symbols */
xlunbind(NULL);
/* restore input to the terminal */
xltin(TRUE);
/* do the back trace */
trace();
trace_pointer = -1;
/* restart */
longjmp(xljmpbuf,1);
}
/* tpush - add an entry to the trace stack */
static tpush(nptr)
struct node *nptr;
{
if (++trace_pointer < TDEPTH)
trace_stack[trace_pointer] = nptr;
}
/* tpop - pop an entry from the trace stack */
static tpop()
{
trace_pointer--;
}
/* trace - do a back trace */
static trace()
{
for (; trace_pointer >= 0; trace_pointer--)
if (trace_pointer < TDEPTH) {
xlprint(trace_stack[trace_pointer],TRUE);
putchar('\n');
}
}
/* xleinit - initialize the evaluator */
xleinit()
{
/* enter the local variable separator symbol */
slash = xlenter("/");
/* initialize debugging stuff */
trace_pointer = -1;
/* builtin functions */
xlsubr("eval",eval);
}
<<<<<<<<<< xlfio.c >>>>>>>>>>
/* xlfio - xlisp file i/o */
#include <stdio.h>
#include "xlisp.h"
/* external variables */
extern struct node *xlstack;
/* local variables */
static char buf[STRMAX+1];
/* xlfopen - open a file */
static struct node *xlfopen(args)
struct node *args;
{
struct node *oldstk,arg,fname,mode,*val;
FILE *fp;
/* create a new stack frame */
oldstk = xlsave(&arg,&fname,&mode,NULL);
/* initialize */
arg.n_ptr = args;
/* get the file name */
fname.n_ptr = xlevmatch(STR,&arg.n_ptr);
/* get the mode */
mode.n_ptr = xlevmatch(STR,&arg.n_ptr);
/* make sure there aren't any more arguments */
xllastarg(arg.n_ptr);
/* try to open the file */
if ((fp = fopen(fname.n_ptr->n_str,
mode.n_ptr->n_str)) != NULL) {
val = newnode(FPTR);
val->n_fp = fp;
}
else
val = NULL;
/* restore the previous stack frame */
xlstack = oldstk;
/* return the file pointer */
return (val);
}
/* xlfclose - close a file */
static struct node *xlfclose(args)
struct node *args;
{
struct node *fptr;
/* get file pointer */
fptr = xlevmatch(FPTR,&args);
/* make sure there aren't any more arguments */
xllastarg(args);
/* make sure the file exists */
if (fptr->n_fp == NULL)
xlfail("file not open");
/* close the file */
fclose(fptr->n_fp);
fptr->n_fp = NULL;
/* return nil */
return (NULL);
}
/* xlgetc - get a character from a file */
static struct node *xlgetc(args)
struct node *args;
{
struct node *val;
FILE *fp;
int ch;
/* get file pointer */
if (args != NULL)
fp = xlevmatch(FPTR,&args)->n_fp;
else
fp = stdin;
/* make sure there aren't any more arguments */
xllastarg(args);
/* make sure the file exists */
if (fp == NULL)
xlfail("file not open");
/* get character and check for eof */
if ((ch = getc(fp)) != EOF) {
/* create return node */
val = newnode(INT);
val->n_int = ch;
}
else
val = NULL;
/* return the character */
return (val);
}
/* xlputc - put a character to a file */
static struct node *xlputc(args)
struct node *args;
{
struct node *oldstk,arg,chr;
FILE *fp;
/* create a new stack frame */
oldstk = xlsave(&arg,&chr,NULL);
/* initialize */
arg.n_ptr = args;
/* get the character */
chr.n_ptr = xlevmatch(INT,&arg.n_ptr);
/* get file pointer */
if (arg.n_ptr != NULL)
fp = xlevmatch(FPTR,&arg.n_ptr)->n_fp;
else
fp = stdout;
/* make sure there aren't any more arguments */
xllastarg(arg.n_ptr);
/* make sure the file exists */
if (fp == NULL)
xlfail("file not open");
/* put character to the file */
putc(chr.n_ptr->n_int,fp);
/* restore the previous stack frame */
xlstack = oldstk;
/* return the character */
return (chr.n_ptr);
}
/* xlfgets - get a string from a file */
static struct node *xlfgets(args)
struct node *args;
{
struct node *str;
char *sptr;
FILE *fp;
/* get file pointer */
if (args != NULL)
fp = xlevmatch(FPTR,&args)->n_fp;
else
fp = stdin;
/* make sure there aren't any more arguments */
xllastarg(args);
/* make sure the file exists */
if (fp == NULL)
xlfail("file not open");
/* get character and check for eof */
if (fgets(buf,STRMAX,fp) != NULL) {
/* create return node */
str = newnode(STR);
str->n_str = strsave(buf);
/* make sure we got the whole string */
while (buf[strlen(buf)-1] != '\n') {
if (fgets(buf,STRMAX,fp) == NULL)
break;
sptr = str->n_str;
str->n_str = stralloc(strlen(sptr) + strlen(buf));
strcpy(str->n_str,sptr);
strcat(buf);
strfree(sptr);
}
}
else
str = NULL;
/* return the string */
return (str);
}
/* xlfputs - put a string to a file */
static struct node *xlfputs(args)
struct node *args;
{
struct node *oldstk,arg,str;
FILE *fp;
/* create a new stack frame */
oldstk = xlsave(&arg,&str,NULL);
/* initialize */
arg.n_ptr = args;
/* get the string */
str.n_ptr = xlevmatch(STR,&arg.n_ptr);
/* get file pointer */
if (arg.n_ptr != NULL)
fp = xlevmatch(FPTR,&arg.n_ptr)->n_fp;
else
fp = stdout;
/* make sure there aren't any more arguments */
xllastarg(arg.n_ptr);
/* make sure the file exists */
if (fp == NULL)
xlfail("file not open");
/* put string to the file */
fputs(str.n_ptr->n_str,fp);
/* restore the previous stack frame */
xlstack = oldstk;
/* return the string */
return (str.n_ptr);
}
/* xlfinit - initialize file stuff */
xlfinit()
{
xlsubr("fopen",xlfopen);
xlsubr("fclose",xlfclose);
xlsubr("getc",xlgetc);
xlsubr("putc",xlputc);
xlsubr("fgets",xlfgets);
xlsubr("fputs",xlfputs);
}
More information about the Comp.sources.unix
mailing list