|
|
1.1 root 1: #include "global.h"
2: #include <stdio.h>
3: #include <ctype.h>
4: #include "chars.h"
5:
6: struct readtable {
7: char ctable[132];
8: } initread = {
9: /* ^@ nul ^A soh ^B stx ^C etx ^D eot ^E eng ^F ack ^G bel */
10: VERR, VERR, VERR, VERR, VERR, VERR, VERR, VERR,
11: /* ^H bs ^I ht ^J nl ^K vt ^L np ^M cr ^N so ^O si */
12: VCHAR, VSEP, VSEP, VSEP, VSEP, VSEP, VERR, VERR,
13: /* ^P dle ^Q dc1 ^R dc2 ^S dc3 ^T dc4 ^U nak ^V syn ^W etb */
14: VERR, VERR, VERR, VERR, VERR, VERR, VERR, VERR,
15: /* ^X can ^Y em ^Z sub ^[ esc ^\ fs ^] gs ^^ rs ^_ us */
16: VERR, VERR, VERR, VSEP, VERR, VERR, VERR, VERR,
17: /* sp ! " # $ % & ' */
18: VSEP, VCHAR, VDQ, VCHAR, VCHAR, VCHAR, VCHAR, VSQ,
19: /* ( ) * + , - . / */
20: VLPARA, VRPARA, VCHAR, VSIGN, VCHAR, VSIGN, VPERD, VCHAR,
21: /* 0 1 2 3 4 5 6 7 */
22: VNUM, VNUM, VNUM, VNUM, VNUM, VNUM, VNUM, VNUM,
23: /* 8 9 : ; < = > ? */
24: VNUM, VNUM, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR,
25: /* @ A B C D E F G */
26: VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR,
27: /* H I J K L M N O */
28: VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR,
29: /* P Q R S T U V W */
30: VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR,
31: /* X Y Z [ \ ] ^ _ */
32: VCHAR, VCHAR, VCHAR, VLBRCK, VESC, VRBRCK, VCHAR, VCHAR,
33: /* ` a b c d e f g */
34: VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR,
35: /* h i j k l m n o */
36: VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR,
37: /* p q r s t u v w */
38: VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR,
39: /* x y z { | } ~ del */
40: VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VEOF,
41: /* unused unused Xesc Xdqc */
42: 0, 0, '\\', '"'
43: };
44:
45: char *ctable = initread.ctable;
46: lispval atomval; /* external varaible containing atom returned
47: from internal atom reading routine */
48: lispval protect();
49: lispval unprotect();
50: lispval readrx(); lispval readr(); lispval readry();
51: int keywait;
52: static int dbqflag;
53: static int macflag;
54: static int splflag;
55: static int mantisfl = 0;
56: lispval lastrtab; /* external variable designating current reader
57: table */
58: static char baddot1[]=
59: "Bad reader construction: (. <something>)\nShould be (nil . <something>)\n";
60: static char baddot2[]=
61: "Bad reader construction: (<something> .)\n\
62: Should be (<something> . <something>), assumed to be (<something>)";
63: static char baddot3[]=
64: "Bad reader construction: (<something> . <something> not followed by )";
65:
66: #include "chkrtab.h"
67: /* readr ****************************************************************/
68: /* returns a s-expression read in from the port specified as the first */
69: /* argument. Handles superbrackets, reader macros. */
70: lispval
71: readr(useport)
72: FILE *useport;
73: {
74: register lispval handy = Vreadtable->clb;
75:
76: chkrtab(handy);
77: rbktf = FALSE;
78: rdrport = (FILE *) useport;
79: if(useport==stdin)
80: keywait = TRUE;
81: handy = readrx(Iratom());
82: if(useport==stdin)
83: keywait = FALSE;
84: return(handy);
85:
86: }
87:
88:
89: /* readrx **************************************************************/
90: /* returns a s-expression beginning with the syntax code of an atom */
91: /* passed in the first */
92: /* argument. Does the actual work for readr, including list, dotted */
93: /* pair, and quoted atom detection */
94: lispval
95: readrx(code)
96: register int code;
97: {
98: register lispval work;
99: register lispval *current;
100: register struct argent *result;
101: register struct argent *lbot, *np;
102: int inlbkt = FALSE;
103: lispval errorh();
104:
105: top:
106: switch(code)
107: {
108: case TLBKT:
109: inlbkt = TRUE;
110: case TLPARA:
111: result = np;
112: current = (lispval *)np;
113: np++->val = nil; /*protect(nil);*/
114: for(EVER) {
115: switch(code = Iratom())
116: {
117: case TRPARA:
118: if(rbktf && inlbkt)
119: rbktf = FALSE;
120: return(result->val);
121: default:
122: atomval = readrx(code);
123: case TSCA:
124: np++->val=atomval;
125: *current = work = newdot();
126: work->car = atomval;
127: np--;
128: current = (lispval *) &(work->cdr);
129: break;
130: case TSPL:
131: macrox(); /* input and output in atomval */
132: *current = atomval;
133: while(*current!=nil) {
134: if(TYPE(*current)!=DTPR)
135: errorh(Vermisc,"Non-list returned from splicing macro",nil,FALSE,7,*current);
136: current=(lispval *)&((*current)->cdr);
137: }
138: break;
139: case TPERD:
140: if(result->val==nil) {
141: work = result->val=newdot();
142: current = (lispval *) &(work->cdr);
143: fprintf(stderr,baddot1);
144: }
145: code = Iratom();
146: if(code==TRPARA) {
147: return(errorh(Vermisc,baddot2,nil,TRUE,58,result->val));
148: }
149: *current = readrx(code);
150: if((code = Iratom())!=TRPARA) {
151: errorh(Vermisc,baddot3,nil,TRUE,59,result->val,atomval);
152: }
153: if(rbktf && inlbkt)
154: rbktf = FALSE;
155: return(result->val);
156: case TEOF:
157: clearerr(rdrport);
158: error("Premature end of file.", FALSE);
159: }
160: if(rbktf) {
161: if(inlbkt)
162: rbktf = FALSE;
163: return(result->val);
164: }
165: }
166: case TSCA:
167: return(atomval);
168: case TEOF:
169: return(eofa);
170: case TMAC:
171: macrox();
172: return(atomval);
173: case TSPL:
174: macrox();
175: if((work = atomval)!=nil) {
176: if(TYPE(work)==DTPR && work->cdr==nil)
177: return(work->car);
178: else
179: errorh(Vermisc,
180: "Improper value returned from splicing macro at top-level",nil,FALSE,9,work);
181: }
182: code = Iratom();
183: goto top;
184: /* return(readrx(Iratom())); */
185: case TSQ:
186: result = np;
187: protect(newdot());
188: (work = result->val)->car = quota;
189: work = work->cdr = newdot();
190: work->car = readrx(Iratom());
191: return(result->val);
192: default:
193: return(error("Readlist error",FALSE));
194: }
195: }
196: macrox()
197: {
198: lispval Lapply();
199:
200: snpand(0);
201: lbot = np;
202: protect(Iget(atomval,macro));
203: protect(nil);
204: atomval = Lapply();
205: return;
206: }
207:
208:
209:
210: /* ratomr ***************************************************************/
211: /* this routine returns a pointer to an atom read in from the port given*/
212: /* by the first argument */
213: lispval
214: ratomr(useport)
215: register FILE *useport;
216: {
217: rdrport = useport;
218: switch(Iratom())
219: {
220: case TEOF:
221: return(eofa);
222: case TSQ:
223: case TRPARA:
224: case TLPARA:
225: case TLBKT:
226: case TPERD:
227: strbuf[1]=0;
228: return(getatom());
229: default:
230: return(atomval);
231: }
232: }
233: Iratom()
234: {
235: register FILE *useport = rdrport;
236: register char c, marker, *name;
237: extern lispval finatom(), calcnum(), getnum();
238: char positv = TRUE;
239: int code;
240: int strflag = FALSE;
241:
242: name = strbuf;
243:
244: again: c = getc(useport) & 0177;
245: *name = c;
246:
247: switch(ctable[c] & 0377) {
248:
249: default: goto again;
250:
251: case VNUM:
252:
253: case VSIGN: *name++ = c;
254: atomval = (getnum(name));
255: return(TSCA);
256:
257: case VESC:
258: dbqflag = TRUE;
259: *name++ = getc(useport) & 0177;
260: atomval = (finatom(name));
261: return(TSCA);
262:
263: case VCHAR:
264: *name++ = c;
265: atomval = (finatom(name));
266: return(TSCA);
267:
268: case VLPARA: return(TLPARA);
269:
270: case VRPARA: return(TRPARA);
271:
272: case VPERD: c = peekc(useport);
273: if(VNUM!=ctable[c])
274: return(TPERD);
275: *name++ = '.';
276: mantisfl = 1;
277: atomval = (getnum(name));
278: return(TSCA);
279:
280: case VLBRCK: return(TLBKT);
281:
282: case VRBRCK: rbktf = TRUE;
283: return(TRPARA);
284:
285: case VEOF: /*printf("returning eof atom\n");*/
286: return(TEOF);
287:
288: case VSQ: return(TSQ);
289:
290: case VSD: strflag = TRUE;
291: case VDQ: name = strbuf;
292: marker = c;
293: while ((c = getc(useport)) != marker) {
294:
295: if(VESC==ctable[c]) c = getc(useport);
296: *name++ = c;
297: if (name >= endstrb)
298: error("ATOM TOO LONG",FALSE);
299: if (feof(useport)) {
300: clearerr(useport);
301: error("EOF ecountered while reading atom", FALSE);
302: }
303: }
304: *name = NULL_CHAR;
305: if(strflag)
306: atomval = (lispval) inewstr(strbuf);
307: else
308: atomval = (getatom(name));
309: return(TSCA);
310:
311: case VERR: if (c == '\0') goto same; /* null pname */
312: fprintf(stderr,"%c (%o): ",c,(int) c);
313: error("ILLEGAL CHARACTER IN ATOM",TRUE);
314:
315: case VSPL:
316: code = TSPL;
317: goto same;
318: case VMAC:
319: code = TMAC;
320: goto same;
321: case VSCA:
322: code = TSCA;
323: same:
324: strbuf[0] = c;
325: strbuf[1] = 0;
326: atomval = (getatom());
327: return(code);
328: }
329: }
330:
331: #define push(); if(name==endstrb) error("Int too long",FALSE); else *name++=c;
332: #define next() (stats = ctable[c=getc(useport) & 0177])
333:
334: lispval
335: getnum(name)
336: register char *name;
337: {
338: register char c;
339: register lispval result;
340: register FILE *useport=rdrport;
341: char stats;
342: double realno;
343: extern lispval finatom(), calcnum(), newdoub(), dopow();
344:
345: if(mantisfl) {
346: mantisfl = 0;
347: next();
348: goto mantissa;
349: }
350: while(VNUM==next()) {
351: push(); /* recognize [0-9]*, in "ex" parlance */
352: }
353: if(stats==VPERD) {
354: push(); /* continue */
355: } else if(stats & SEPMASK) {
356: ungetc(c,useport);
357: return(calcnum(strbuf,name,ibase->clb->i));
358: } else if(c=='^') {
359: push();
360: return(dopow(name,ibase->clb->i));
361: } else if(c=='_') {
362: push();
363: return(dopow(name,2));
364: } else{
365: ungetc(c,useport);
366: return(finatom(name));
367: }
368: /* at this point we have [0-9]*\. , which might
369: be a decimal int or the leading part of a
370: float */
371: if(next()!=VNUM) {
372: if(c=='e' || c=='E' || c=='d' ||c=='D')
373: goto expt;
374: else if(c=='^') {
375: push();
376: return(dopow(name,ibase->clb->i));
377: } else if(c=='_') {
378: push();
379: return(dopow(name,2));
380: } else {
381: /* Here we have 1.x where x not num, not sep */
382: /* Here we have decimal int. NOT FORTRAN! */
383: ungetc(c,useport);
384: return(calcnum(strbuf,name-1,10));
385: }
386: }
387: mantissa:
388: do {
389: push();
390: } while (VNUM==next());
391: /* Here we have [0-9]*\.[0-9]* */
392: if(stats & SEPMASK)
393: goto last;
394: else if(c!='e' && c!='E' && c!='d' && c!='D') {
395: ungetc(c,useport);
396: goto verylast;
397: }
398: expt: push();
399: next();
400: if(c=='+' || c =='-') {
401: push();
402: next();
403: }
404: while (VNUM==stats) {
405: push();
406: next();
407: }
408: last: ungetc(c,useport);
409: if(! (stats & SEPMASK) )
410: return(finatom(name));
411:
412: verylast:
413: *name=0;
414: sscanf(strbuf,"%F",&realno);
415: (result = newdoub())->r = realno;
416: return(result);
417: }
418:
419: lispval
420: dopow(part2,base)
421: lispval base;
422: char *part2;
423: {
424: register char *name = part2;
425: register char c;
426: register FILE *useport = rdrport;
427: register int power;
428: register struct argent *lbot, *np;
429: char stats;
430: char *end1 = part2 - 1; lispval Ltimes();
431:
432: while(VNUM==next()) {
433: push();
434: }
435: if(c!='.') {
436: ungetc(c,useport);
437: }
438: if(c!='.' && !(stats & SEPMASK)) {
439: return(finatom(name));
440: }
441: lbot = np;
442: np++->val = inewint(base);
443: /* calculate "mantissa"*/
444: if(*end1=='.')
445: np++->val = calcnum(strbuf,end1-1,10);
446: else
447: np++->val = calcnum(strbuf,end1,ibase->clb->i);
448:
449: /* calculate exponent */
450: if(c=='.')
451: power = calcnum(part2,name,10)->i;
452: else
453: power = calcnum(part2,name,ibase->clb->i)->i;
454: while(power-- > 0)
455: lbot[1].val = Ltimes();
456: return(lbot[1].val);
457: }
458:
459:
460: lispval
461: calcnum(strbuf,name,base)
462: char *name;
463: char *strbuf;
464: {
465: register char *p;
466: register lispval result, temp;
467: int negflag = 0;
468:
469: temp = rdrsdot; /* initialize sdot cell */
470: temp->CDR = nil;
471: temp->i = 0;
472: p = strbuf;
473: if(*p=='+') p++;
474: else if(*p=='-') {negflag = 1; p++;}
475: *name = 0;
476: if(p>=name) return(getatom());
477:
478: for(;p < name; p++)
479: dmlad(temp,base,*p-'0');
480: if(negflag)
481: dmlad(temp,-1,0);
482:
483: if(temp->CDR==0) {
484: result = inewint(temp->i);
485: return(result);
486: } else {
487: (result = newsdot())->i = temp->i;
488: result->CDR = temp->CDR;
489: temp->CDR = 0;
490: }
491: return(result);
492: }
493: lispval
494: finatom(name)
495: register char *name;
496: {
497: extern int uctolc;
498: register FILE *useport = rdrport;
499: register char c, stats;
500: register char *savenm;
501: savenm = name - 1; /* remember start of name */
502: while(!(next()&SEPMASK)) {
503:
504: if(stats == VESC) c = getc(useport) & 0177;
505: *name++=c;
506: if (name >= endstrb)
507: error("ATOM TOO LONG",FALSE);
508: }
509: *name = NULL_CHAR;
510: ungetc(c,useport);
511: if (uctolc) for(; *savenm ; savenm++)
512: if( isupper(*savenm) ) *savenm = tolower(*savenm);
513: return(getatom());
514: }
515:
516: /* printr ***************************************************************/
517: /* prints the first argument onto the port specified by the second */
518: printr(a,useport)
519: register lispval a;
520: register FILE *useport;
521: {
522: register lispval temp;
523: char strflag = 0;
524: char Idqc = 0;
525:
526:
527: val_loop:
528: if( ! VALID(a) )
529: {
530: error("BAD LISP DATA ENCOUNTERED BY PRINTR",TRUE);
531: a = badst;
532: }
533:
534: switch (TYPE(a)) {
535:
536:
537: case UNBO: fputs("<UNBOUND>",useport);
538: break;
539:
540: case VALUE: fputs("(ptr to)",useport);
541: a = a->l;
542: goto val_loop;
543:
544: case INT: fprintf(useport,"%d",a->i);
545: break;
546:
547: case DOUB: fprintf(useport,"%0.16G",a->r);
548: break;
549:
550: case PORT: fputs("port",useport);
551: break;
552:
553: case ARRAY: fputs("array[",useport);
554: printr(a->length,useport);
555: fputs("]",useport);
556: break;
557:
558: case BCD: fprintf(useport,"#%X-",a->entry);
559: printr(a->discipline,useport);
560: break;
561:
562: case SDOT: pbignum(a,useport);
563: break;
564:
565: case DTPR: if(a->car==quota && a->cdr!=nil
566: && a->cdr->cdr==nil) {
567: putc('\'',useport);
568: printr(a->cdr->car,useport);
569: break;
570: }
571: putc('(',useport);
572: morelist: printr(a->car,useport);
573: if ((a = a->cdr) != nil)
574: {
575: putc(' ',useport);
576: if (TYPE(a) == DTPR) goto morelist;
577: fputs(". ",useport);
578: printr(a,useport);
579: }
580: fputc(')',useport);
581: break;
582:
583: case STRNG: strflag = TRUE;
584: Idqc = Xsdc;
585:
586: case ATOM: {
587: char *front, *temp; int clean;
588: temp = front = (strflag ? ((char *) a) : a->pname);
589: if(Idqc==0) Idqc = Xdqc;
590:
591: if(Idqc) {
592: clean = *temp;
593: if (*temp == '-') temp++;
594: clean = clean && (ctable[*temp] != VNUM);
595: while (clean && *temp)
596: clean = (!(ctable[*temp++] & QUTMASK));
597: if (clean)
598: fputs(front,useport);
599: else {
600: putc(Idqc,useport);
601: for(temp=front;*temp;temp++) {
602: if( *temp==Idqc
603: || ctable[*temp] == VESC)
604: putc(Xesc,useport);
605: putc(*temp,useport);
606: }
607: putc(Idqc,useport);
608: }
609:
610: } else {
611: register char *cp = front;
612:
613: if(ctable[*cp]==VNUM)
614: putc(Xesc,useport);
615: for(; *cp; cp++) {
616: if(ctable[*cp]& QUTMASK)
617: putc(Xesc,useport);
618: putc(*cp,useport);
619: }
620:
621: }
622:
623: }
624: }
625: }
626:
627: /* dmpport ****************************************************************/
628: /* outputs buffer indicated by first argument whether full or not */
629: dmpport(useport)
630: register lispval useport;
631: {
632: fflush(useport);
633: }
634:
635: /* protect and unprot moved to eval.c (whr) */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.