home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
lisp
/
interpre
/
xlispplu
/
sources
/
xlread.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-03
|
26KB
|
1,028 lines
/* xlread - xlisp expression input routine */
/* Copyright (c) 1985, by David Michael Betz
All Rights Reserved
Permission is granted for unrestricted non-commercial use */
#include "xlisp.h"
#ifndef ANSI
#include <math.h> /* for atof(), ANSI puts it in stdlib also,
which is included in xlisp.h. What a mess! */
#endif
#ifdef AMIGA
#include <math.h>
#endif
/* symbol parser modes */
#define DONE 0
#define NORMAL 1
#define ESCAPE 2
/* external variables */
extern LVAL true,s_dot;
extern LVAL s_quote,s_function,s_bquote,s_comma,s_comat;
extern LVAL s_rtable,k_wspace,k_const,k_nmacro,k_tmacro;
extern LVAL k_sescape,k_mescape;
#ifdef READTABLECASE
extern LVAL s_rtcase,k_upcase,k_downcase,k_preserve,k_invert;
#endif
/* For xlload bug fix */
extern LVAL xlvalue;
extern CONTEXT *xltarget;
extern int xlmask;
/* string constants */
#define WSPACE "\t \f\r\n"
#define CONST1 "!$%&*+-./0123456789:<=>?@[]^_{}~"
#define CONST2 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
/* forward declarations */
#ifdef ANSI
LVAL NEAR callmacro(LVAL fptr, int ch);
LVAL NEAR psymbol(LVAL fptr);
LVAL NEAR punintern(LVAL fptr);
LVAL NEAR pnumber(LVAL fptr, int radix);
LVAL NEAR pquote(LVAL fptr, LVAL sym);
LVAL NEAR plist(LVAL fptr);
LVAL NEAR pvector(LVAL fptr);
LVAL NEAR pstruct(LVAL fptr);
LVAL NEAR readlist(LVAL fptr, int *plen);
void NEAR pcomment(LVAL fptr);
void NEAR badeof(LVAL fptr);
void NEAR upcase(char *str);
void NEAR storech(int *c, int ch);
int NEAR nextch(LVAL fptr);
int NEAR checkeof(LVAL fptr);
int NEAR readone(LVAL fptr, LVAL FAR *pval);
int NEAR pname(LVAL fptr, int *pescflag);
#else
FORWARD LVAL callmacro();
FORWARD LVAL psymbol(),punintern();
FORWARD LVAL pnumber(),pquote(),plist(),pvector();
FORWARD LVAL pstruct();
FORWARD LVAL readlist();
FORWARD VOID pcomment();
FORWARD VOID badeof();
FORWARD VOID upcase();
FORWARD VOID storech();
#endif
/* xlload - load a file of xlisp expressions */
int xlload(fname,vflag,pflag)
char *fname; int vflag,pflag;
{
char fullname[STRMAX+1];
LVAL fptr,expr;
CONTEXT cntxt;
FILEP fp;
int sts, mask;
/* protect some pointers */
xlstkcheck(2);
xlsave(fptr);
xlsave(expr);
/* default the extension */
if (needsextension(fname)) {
strcpy(fullname,fname);
strcat(fullname,".lsp");
fname = fullname;
}
/* allocate a file node */
fptr = cvfile(CLOSED,S_FORREADING);
/* open the file */
#ifdef PATHNAMES
if ((fp = ospopen(fname,TRUE)) == CLOSED)
#else
if ((fp = OSAOPEN(fname,OPEN_RO)) == CLOSED)
#endif
{
xlpopn(2);
return (FALSE);
}
setfile(fptr,fp);
/* print the information line */
if (vflag) /* TAA MOD -- changed from printing to stdout */
{ sprintf(buf,"; loading \"%s\"\n",fname); dbgputstr(buf); }
/* read, evaluate and possibly print each expression in the file */
xlbegin(&cntxt,CF_ERROR|CF_UNWIND,true); /* TAA mod so file gets closed */
if ((mask = setjmp(cntxt.c_jmpbuf)) != 0) /* TAA mod -- save mask */
sts = FALSE;
else {
while (xlread(fptr,&expr)) {
expr = xleval(expr);
if (pflag)
stdprint(expr);
}
sts = TRUE;
}
xlend(&cntxt);
/* close the file */
OSCLOSE(getfile(fptr));
setfile(fptr,CLOSED);
/* restore the stack */
xlpopn(2);
/* check for unwind protect TAA MOD */
if ((mask & ~CF_ERROR) != 0)
xljump(xltarget, xlmask, xlvalue);
/* return status */
return (sts);
}
/* xlread - read an xlisp expression */
int xlread(fptr,pval)
LVAL fptr,*pval;
{
int sts;
/* read an expression */
while ((sts = readone(fptr,pval)) == FALSE)
;
/* return status */
return (sts == EOF ? FALSE : TRUE);
}
/* readone - attempt to read a single expression */
LOCAL int NEAR readone(fptr,pval)
LVAL fptr, FAR *pval;
{
LVAL val,type;
int ch;
/* get a character and check for EOF */
if ((ch = xlgetc(fptr)) == EOF)
return (EOF);
/* handle white space */
if ((type = tentry(ch)) == k_wspace)
return (FALSE);
/* handle symbol constituents */
/* handle single and multiple escapes */ /* combined by TAA MOD */
else if (type == k_const ||
type == k_sescape || type == k_mescape) {
xlungetc(fptr,ch);
*pval = psymbol(fptr);
return (TRUE);
}
/* handle read macros */
else if (consp(type)) {
if (((val = callmacro(fptr,ch)) != NIL) && consp(val)) {
*pval = car(val);
return (TRUE);
}
else
return (FALSE);
}
/* handle illegal characters */
else {
/* xlerror("illegal character",cvfixnum((FIXTYPE)ch)); */
xlerror("illegal character",cvchar(ch)); /* friendlier TAA MOD*/
return (0); /* compiler warning */
}
}
/* rmhash - read macro for '#' */
LVAL rmhash()
{
LVAL fptr,val;
char *bufp; /* TAA fix to allow control character literals */
int i;
int ch;
/* protect some pointers */
xlsave1(val);
/* get the file and macro character */
fptr = xlgetarg(); /* internal -- don't bother with error checks */
/* make the return value */
val = consa(NIL);
/* check the next character */
switch (ch = xlgetc(fptr)) {
case '\'':
rplaca(val,pquote(fptr,s_function));
break;
case '(':
xlungetc(fptr,ch);
rplaca(val,pvector(fptr));
break;
case '.':
readone(fptr,&car(val));
rplaca(val,xleval(car(val)));
break;
case 'b':
case 'B':
rplaca(val,pnumber(fptr,2));
break;
case 'o':
case 'O':
rplaca(val,pnumber(fptr,8));
break;
case 'x':
case 'X':
rplaca(val,pnumber(fptr,16));
break;
case 's':
case 'S':
rplaca(val,pstruct(fptr));
break;
case '\\':
for (i = 0; i < STRMAX-1; i++) {
ch = xlgetc(fptr); /* TAA fix to scan at end of file */
if (ch == EOF ||
((tentry(buf[i] = ch) != k_const) &&
(i > 0) && /* TAA fix for left and right paren */
buf[i] != '\\' && buf[i] != '|')) {
xlungetc(fptr, buf[i]);
break;
}
}
buf[i] = 0;
ch = buf[0];
if (strlen(buf) > 1) { /* TAA Fixed */
i = buf[strlen(buf)-1]; /* Value of last character */
upcase(buf);
bufp = &buf[0];
ch = 0;
if (strncmp(bufp,"M-",2) == 0) {
ch = 128;
bufp += 2;
}
if (strcmp(bufp,"NEWLINE") == 0)
ch += '\n';
else if (strcmp(bufp,"SPACE") == 0)
ch += ' ';
else if (strcmp(bufp,"RUBOUT") == 0)
ch += 127;
else if (strlen(bufp) == 1)
ch += i;
else if (strncmp(bufp,"C-",2) == 0 && strlen(bufp) == 3)
ch += bufp[2] & 31;
else xlerror("unknown character name",cvstring(buf));
}
rplaca(val,cvchar(ch));
break;
case ':':
rplaca(val,punintern(fptr));
break;
case '|':
pcomment(fptr);
val = NIL;
break;
#ifdef COMPLX
case 'c':
case 'C': /* From XLISP-STAT, Copyright (c) 1988, Luke Tierney */
{
LVAL list;
readone(fptr, &list);
if (! consp(list) || ! consp(cdr(list)) || cdr(cdr(list)) != NIL)
xlerror("bad complex number specification", list);
rplaca(val, newcomplex(car(list), car(cdr(list))));
break;
}
#endif
default:
/* xlerror("illegal character after #",cvfixnum((FIXTYPE)ch)); */
xlerror("illegal character after #",cvchar(ch)); /*TAA Mod */
}
/* restore the stack */
xlpop();
/* return the value */
return (val);
}
/* rmquote - read macro for '\'' */
LVAL rmquote()
{
LVAL fptr;
/* get the file and macro character */
fptr = xlgetarg(); /* internal -- don't bother with error checks */
/* parse the quoted expression */
return (consa(pquote(fptr,s_quote)));
}
/* rmdquote - read macro for '"' */
LVAL rmdquote()
{
char buf[STRMAX+1],*p, FAR *sptr;
LVAL fptr,str,newstr;
int len,blen,ch,d2,d3;
/* protect some pointers */
xlsave1(str);
/* get the file and macro character */
fptr = xlgetarg(); /* internal -- don't bother with error checks */
/* loop looking for a closing quote */
len = blen = 0; p = buf;
while ((ch = checkeof(fptr)) != '"') {
/* handle escaped characters */
switch (ch) {
case '\\':
switch (ch = checkeof(fptr)) {
case 't':
ch = '\011';
break;
case 'n':
ch = '\012';
break;
case 'f':
ch = '\014';
break;
case 'r':
ch = '\015';
break;
default:
if (ch >= '0' && ch <= '7') {
d2 = checkeof(fptr);
d3 = checkeof(fptr);
if (d2 < '0' || d2 > '7'
|| d3 < '0' || d3 > '7')
xlfail("invalid octal digit");
ch -= '0'; d2 -= '0'; d3 -= '0';
ch = (ch << 6) | (d2 << 3) | d3;
}
break;
}
}
/* check for buffer overflow */
if (blen >= STRMAX) {
newstr = newstring(len + STRMAX);
sptr = getstring(newstr);
if (str != NIL)
MEMCPY(sptr, getstring(str), len);
*p = '\0';
MEMCPY(sptr+len, buf, blen+1);
p = buf;
blen = 0;
len += STRMAX;
str = newstr;
}
/* store the character */
*p++ = ch; ++blen;
}
/* append the last substring */
if (str == NIL || blen) {
newstr = newstring(len + blen);
sptr = getstring(newstr);
if (str != NIL) MEMCPY(sptr, getstring(str), len);
*p = '\0';
MEMCPY(sptr+len, buf, blen+1);
str = newstr;
}
/* restore the stack */
xlpop();
/* return the new string */
return (consa(str));
}
/* rmbquote - read macro for '`' */
LVAL rmbquote()
{
LVAL fptr;
/* get the file and macro character */
fptr = xlgetarg(); /* internal -- don't bother with error checks */
/* parse the quoted expression */
return (consa(pquote(fptr,s_bquote)));
}
/* rmcomma - read macro for ',' */
LVAL rmcomma()
{
LVAL fptr,sym;
int ch;
/* get the file and macro character */
fptr = xlgetarg(); /* internal -- don't bother with error checks */
/* check the next character */
if ((ch = xlgetc(fptr)) == '@')
sym = s_comat;
else {
xlungetc(fptr,ch);
sym = s_comma;
}
/* make the return value */
return (consa(pquote(fptr,sym)));
}
/* rmlpar - read macro for '(' */
LVAL rmlpar()
{
LVAL fptr;
/* get the file and macro character */
fptr = xlgetarg(); /* internal -- don't bother with error checks */
/* make the return value */
return (consa(plist(fptr)));
}
/* rmrpar - read macro for ')' */
LVAL rmrpar()
{
xlfail("misplaced right paren");
return (NIL); /* never returns */
}
/* rmsemi - read macro for ';' */
LVAL rmsemi()
{
LVAL fptr;
int ch;
/* get the file and macro character */
fptr = xlgetarg(); /* internal -- don't bother with error checks */
/* skip to end of line */
while ((ch = xlgetc(fptr)) != EOF && ch != '\n')
;
/* return nil (nothing read) */
return (NIL);
}
/* pcomment - parse a comment delimited by #| and |# */
LOCAL VOID NEAR pcomment(fptr)
LVAL fptr;
{
int lastch,ch,n;
/* look for the matching delimiter (and handle nesting) */
for (n = 1, lastch = -1; n > 0 && (ch = xlgetc(fptr)) != EOF; ) {
if (lastch == '|' && ch == '#')
{ --n; ch = -1; }
else if (lastch == '#' && ch == '|')
{ ++n; ch = -1; }
lastch = ch;
}
}
/* pnumber - parse a number */
LOCAL LVAL NEAR pnumber(fptr,radix)
LVAL fptr; int radix;
{
int digit,ch;
long num;
for (num = 0L; (ch = xlgetc(fptr)) != EOF; ) {
if (islower(ch)) ch = toupper(ch);
if (!('0' <= ch && ch <= '9') && !('A' <= ch && ch <= 'F'))
break;
if ((digit = (ch <= '9' ? ch - '0' : ch - 'A' + 10)) >= radix)
break;
num = num * (long)radix + (long)digit;
}
xlungetc(fptr,ch);
return (cvfixnum((FIXTYPE)num));
}
/* plist - parse a list */
LOCAL LVAL NEAR plist(fptr)
LVAL fptr;
{
LVAL val,expr,lastnptr,nptr;
/* protect some pointers */
xlstkcheck(2);
xlsave(val);
xlsave(expr);
/* keep appending nodes until a closing paren is found */
for (lastnptr = NIL; nextch(fptr) != ')'; )
/* get the next expression */
switch (readone(fptr,&expr)) {
case EOF:
badeof(fptr);
case TRUE:
/* check for a dotted tail */
if (expr == s_dot) {
/* make sure there's a node */
if (lastnptr == NIL)
xlfail("invalid dotted pair");
/* parse the expression after the dot */
if (!xlread(fptr,&expr))
badeof(fptr);
rplacd(lastnptr,expr);
/* make sure its followed by a close paren */
if (nextch(fptr) != ')')
xlfail("invalid dotted pair");
}
/* otherwise, handle a normal list element */
else {
nptr = consa(expr);
if (lastnptr == NIL)
val = nptr;
else
rplacd(lastnptr,nptr);
lastnptr = nptr;
}
break;
}
/* skip the closing paren */
xlgetc(fptr);
/* restore the stack */
xlpopn(2);
/* return successfully */
return (val);
}
/* pvector - parse a vector */
LOCAL LVAL NEAR pvector(fptr)
LVAL fptr;
{
LVAL list,val;
int len,i;
/* protect some pointers */
xlsave1(list);
/* read the list */
list = readlist(fptr,&len);
/* make a vector of the appropriate length */
val = newvector(len);
/* copy the list into the vector */
for (i = 0; i < len; ++i, list = cdr(list))
setelement(val,i,car(list));
/* restore the stack */
xlpop();
/* return successfully */
return (val);
}
/* pstruct - parse a structure */
LOCAL LVAL NEAR pstruct(fptr)
LVAL fptr;
{
LVAL list,val;
int len;
/* protect some pointers */
xlsave1(list);
/* read the list */
list = readlist(fptr,&len);
/* make the structure */
val = xlrdstruct(list);
/* restore the stack */
xlpop();
/* return successfully */
return (val);
}
/* pquote - parse a quoted expression */
LOCAL LVAL NEAR pquote(fptr,sym)
LVAL fptr,sym;
{
LVAL val,p;
/* protect some pointers */
xlsave1(val);
/* allocate two nodes */
val = consa(sym);
rplacd(val,consa(NIL));
/* initialize the second to point to the quoted expression */
if (!xlread(fptr,&p))
badeof(fptr);
rplaca(cdr(val),p);
/* restore the stack */
xlpop();
/* return the quoted expression */
return (val);
}
/* psymbol - parse a symbol name */
LOCAL LVAL NEAR psymbol(fptr)
LVAL fptr;
{
int escflag;
LVAL val;
pname(fptr,&escflag);
return (escflag || !isnumber(buf,&val) ? xlenter(buf) : val);
}
/* punintern - parse an uninterned symbol */
LOCAL LVAL NEAR punintern(fptr)
LVAL fptr;
{
int escflag;
pname(fptr,&escflag);
return (xlmakesym(buf));
}
/* pname - parse a symbol/package name */
#ifdef ANSI
static int NEAR pname(LVAL fptr, int *pescflag)
#else
LOCAL int pname(fptr,pescflag)
LVAL fptr; int *pescflag;
#endif
{
int mode,ch,i;
LVAL type;
#ifdef READTABLECASE
LVAL rtcase = getvalue(s_rtcase);
int low=0, up=0;
#endif
/* initialize */
*pescflag = FALSE;
mode = NORMAL;
i = 0;
/* accumulate the symbol name */
while (mode != DONE) {
/* handle normal mode */
while (mode == NORMAL)
if ((ch = xlgetc(fptr)) == EOF)
mode = DONE;
else if ((type = tentry(ch)) == k_sescape) {
storech(&i,checkeof(fptr));
*pescflag = TRUE;
}
else if (type == k_mescape) {
*pescflag = TRUE;
mode = ESCAPE;
}
else if (type == k_const
|| (consp(type) && car(type) == k_nmacro))
#ifdef READTABLECASE
{
if (rtcase == k_preserve)
storech(&i,ch);
else if (rtcase == k_downcase)
storech(&i,isupper(ch) ? tolower(ch) : ch);
else if (rtcase == k_invert)
storech(&i,islower(ch) ? (low++, toupper(ch)) :
(isupper(ch) ? (up++, tolower(ch)) : ch));
else /* default upcase */
storech(&i,islower(ch) ? toupper(ch) : ch);
}
#else
storech(&i,islower(ch) ? toupper(ch) : ch);
#endif
else
mode = DONE;
/* handle multiple escape mode */
while (mode == ESCAPE)
if ((ch = xlgetc(fptr)) == EOF)
badeof(fptr);
else if ((type = tentry(ch)) == k_sescape)
storech(&i,checkeof(fptr));
else if (type == k_mescape)
mode = NORMAL;
else
storech(&i,ch);
}
buf[i] = 0;
#ifdef READTABLECASE /* TAA Mod, sorta fixing a bug */
if (rtcase == k_invert && low != 0 && up != 0) {
/* must undo inversion (ugh!). Unfortunately, we don't know if
any characters are quoted, so we'll just label this bug as
a feature in the manual. The problem will only occur in symbols
with mixed case characters outside of quotes and at least one
quoted alpha character -- not very likely, I hope. */
int cnt, c;
for (cnt = 0; cnt < i; cnt++ ) {
if (isupper(c=buf[cnt])) buf[cnt] = tolower(c);
else if (islower(c)) buf[cnt] = toupper(c);
}
}
#endif
/* check for a zero length name */
if (i == 0)
xlfail("zero length name"); /* TAA fix, Jeff Prothero improved*/
/* unget the last character and return it */
xlungetc(fptr,ch);
return (ch);
}
/* readlist - read a list terminated by a ')' */
LOCAL LVAL NEAR readlist(fptr,plen)
LVAL fptr; int *plen;
{
LVAL list,expr,lastnptr,nptr;
int ch;
/* protect some pointers */
xlstkcheck(2);
xlsave(list);
xlsave(expr);
/* get the open paren */
if ((ch = nextch(fptr)) != '(')
xlfail("expecting an open paren");
xlgetc(fptr);
/* keep appending nodes until a closing paren is found */
for (lastnptr = NIL, *plen = 0; (ch = nextch(fptr)) != ')'; ) {
/* check for end of file */
if (ch == EOF)
badeof(fptr);
/* get the next expression */
switch (readone(fptr,&expr)) {
case EOF:
badeof(fptr);
case TRUE:
nptr = consa(expr);
if (lastnptr == NIL)
list = nptr;
else
rplacd(lastnptr,nptr);
lastnptr = nptr;
++(*plen);
break;
}
}
/* skip the closing paren */
xlgetc(fptr);
/* restore the stack */
xlpopn(2);
/* return the list */
return (list);
}
/* storech - store a character in the print name buffer */
/* TAA MOD -- since buffer is always global buf, it is no longer passed
as argument. also return value is stored in i, so i is now address of
the int rather than its value */
LOCAL VOID NEAR storech(i,ch)
int *i,ch;
{
if (*i < STRMAX)
buf[(*i)++] = ch;
}
/* tentry - get a readtable entry */
LVAL tentry(ch)
int ch;
{
LVAL rtable;
rtable = getvalue(s_rtable);
if (!vectorp(rtable) || ch < 0 || ch >= getsize(rtable))
return (NIL);
return (getelement(rtable,ch));
}
/* nextch - look at the next non-blank character */
LOCAL int NEAR nextch(fptr)
LVAL fptr;
{
int ch;
/* return and save the next non-blank character */
while ((ch = xlgetc(fptr)) != EOF && isspace(ch))
;
xlungetc(fptr,ch);
return (ch);
}
/* checkeof - get a character and check for end of file */
LOCAL int NEAR checkeof(fptr)
LVAL fptr;
{
int ch;
if ((ch = xlgetc(fptr)) == EOF)
badeof(fptr);
return (ch);
}
/* badeof - unexpected eof */
LOCAL VOID NEAR badeof(fptr)
LVAL fptr;
{
xlgetc(fptr);
xlfail("unexpected EOF");
}
/* isnumber - check if this string is a number */
int isnumber(str,pval)
char *str; LVAL *pval;
{
int dl=0, dr=0;
char *p = str;
#ifdef RATIOS
int ratio=0;
FIXTYPE denom=0;
#endif
/* check for a sign */
if (*p == '+' || *p == '-')
p++;
/* check for a string of digits */
while (isdigit(*p))
p++, dl++;
/* check for a decimal point */
if (*p == '.') {
p++;
while (isdigit(*p))
p++, dr++;
}
#ifdef RATIOS
else if (*p == '/') {
if (dl == 0) return FALSE;
p++;
while (isdigit(*p)) {
denom = denom * 10 + *p - '0';
p++, dr++;
}
if (dr == 0) return FALSE;
if (denom == 0)
xlerror ("invalid rational number", cvstring (str));
ratio = 1;
}
#endif
/* check for an exponent */
#ifdef RATIOS
#ifdef READTABLECASE
if ((dl || dr) && !ratio && (*p == 'E' || *p == 'e'))
#else
if ((dl || dr) && !ratio && *p == 'E')
#endif
#else
#ifdef READTABLECASE
if ((dl || dr) && (*p == 'E' || *p == 'e'))
#else
if ((dl || dr) && *p == 'E')
#endif
#endif
{
p++;
/* check for a sign */
if (*p == '+' || *p == '-')
p++;
/* check for a string of digits */
while (isdigit(*p))
p++, dr++;
}
/* make sure there was at least one digit and this is the end */
if ((dl == 0 && dr == 0) || *p) return (FALSE);
/* convert the string to an integer and return successfully */
if (pval != NULL) {
if (*str == '+') ++str;
if (str[strlen(str)-1] == '.') str[strlen(str)-1] = 0;
#ifdef RATIOS
if (ratio) {
*pval = cvratio(ICNV(str), denom);
}
else
#endif
*pval = (dr ? cvflonum(atof(str)) : cvfixnum(ICNV(str)));
}
return (TRUE);
}
/* defmacro - define a read macro */
#ifdef ANSI
static void NEAR defmacro(int ch, LVAL type, int offset)
#else
LOCAL VOID defmacro(ch,type,offset)
int ch; LVAL type; int offset;
#endif
{
extern FUNDEF funtab[];
LVAL subr;
subr = cvsubr(funtab[offset].fd_subr,funtab[offset].fd_type,offset);
setelement(getvalue(s_rtable),ch,cons(type,subr));
}
/* callmacro - call a read macro */
LOCAL LVAL NEAR callmacro(fptr,ch)
LVAL fptr; int ch;
{
FRAMEP newfp;
/* create the new call frame */
newfp = xlsp;
pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
pusharg(cdr(getelement(getvalue(s_rtable),ch)));
pusharg(cvfixnum((FIXTYPE)2));
pusharg(fptr);
pusharg(cvchar(ch));
xlfp = newfp;
return (xlapply(2));
}
/* upcase - translate a string to upper case */
LOCAL VOID NEAR upcase(str)
char *str;
{
for (; *str != '\0'; ++str)
if (islower(*str))
*str = toupper(*str);
}
/* xlrinit - initialize the reader */
VOID xlrinit()
{
LVAL rtable;
char *p;
int ch;
/* create the read table */
rtable = newvector(256);
setvalue(s_rtable,rtable);
/* initialize the readtable */
for (p = WSPACE; (ch = *p++) != 0; )
setelement(rtable,ch,k_wspace);
for (p = CONST1; (ch = *p++) != 0; )
setelement(rtable,ch,k_const);
for (p = CONST2; (ch = *p++) != 0; )
setelement(rtable,ch,k_const);
/* setup the escape characters */
setelement(rtable,'\\',k_sescape);
setelement(rtable,'|', k_mescape);
/* install the read macros */
defmacro('#', k_nmacro,FT_RMHASH);
defmacro('\'',k_tmacro,FT_RMQUOTE);
defmacro('"', k_tmacro,FT_RMDQUOTE);
defmacro('`', k_tmacro,FT_RMBQUOTE);
defmacro(',', k_tmacro,FT_RMCOMMA);
defmacro('(', k_tmacro,FT_RMLPAR);
defmacro(')', k_tmacro,FT_RMRPAR);
defmacro(';', k_tmacro,FT_RMSEMI);
}