home *** CD-ROM | disk | FTP | other *** search
- /* 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 XNEAR callmacro(LVAL fptr, int ch);
- LVAL XNEAR psymbol(LVAL fptr);
- LVAL XNEAR punintern(LVAL fptr);
- LVAL XNEAR pnumber(LVAL fptr, int radix);
- LVAL XNEAR pquote(LVAL fptr, LVAL sym);
- LVAL XNEAR plist(LVAL fptr);
- LVAL XNEAR pvector(LVAL fptr);
- LVAL XNEAR pstruct(LVAL fptr);
- LVAL XNEAR readlist(LVAL fptr, int *plen);
- void XNEAR pcomment(LVAL fptr);
- void XNEAR badeof(LVAL fptr);
- void XNEAR upcase(char *str);
- void XNEAR storech(int *c, int ch);
- int XNEAR nextch(LVAL fptr);
- int XNEAR checkeof(LVAL fptr);
- int XNEAR readone(LVAL fptr, LVAL XFAR *pval);
- int XNEAR 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 XNEAR readone(fptr,pval)
- LVAL fptr, XFAR *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, XFAR *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 XNEAR 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 XNEAR 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 XNEAR 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 XNEAR 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 XNEAR 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 XNEAR 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 XNEAR 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 XNEAR punintern(fptr)
- LVAL fptr;
- {
- int escflag;
- pname(fptr,&escflag);
- return (xlmakesym(buf));
- }
-
- /* pname - parse a symbol/package name */
- #ifdef ANSI
- static int XNEAR 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 XNEAR 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 XNEAR 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 XNEAR 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 XNEAR checkeof(fptr)
- LVAL fptr;
- {
- int ch;
-
- if ((ch = xlgetc(fptr)) == EOF)
- badeof(fptr);
- return (ch);
- }
-
- /* badeof - unexpected eof */
- LOCAL VOID XNEAR 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 XNEAR 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 XNEAR 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 XNEAR 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);
- }
-
-