|
|
1.1 root 1: #ifndef lint
2: static char *rcsid =
3: "$Header: io.c,v 1.11 85/03/24 11:03:19 sklower Exp $";
4: #endif
5:
6: /* -[Tue Nov 22 10:01:14 1983 by jkf]-
7: * io.c $Locker: $
8: * input output functions
9: *
10: * (c) copyright 1982, Regents of the University of California
11: */
12:
13: #include "global.h"
14: #include <ctype.h>
15: #include "chars.h"
16: #include "chkrtab.h"
17:
18: struct readtable {
19: unsigned char ctable[132];
20: } initread = {
21: /* ^@ nul ^A soh ^B stx ^C etx ^D eot ^E eng ^F ack ^G bel */
22: VERR, VERR, VERR, VERR, VERR, VERR, VERR, VERR,
23: /* ^H bs ^I ht ^J nl ^K vt ^L np ^M cr ^N so ^O si */
24: VCHAR, VSEP, VSEP, VSEP, VSEP, VSEP, VERR, VERR,
25: /* ^P dle ^Q dc1 ^R dc2 ^S dc3 ^T dc4 ^U nak ^V syn ^W etb */
26: VERR, VERR, VERR, VERR, VERR, VERR, VERR, VERR,
27: /* ^X can ^Y em ^Z sub ^[ esc ^\ fs ^] gs ^^ rs ^_ us */
28: VERR, VERR, VERR, VSEP, VERR, VERR, VERR, VERR,
29: /* sp ! " # $ % & ' */
30: VSEP, VCHAR, VSD, VCHAR, VCHAR, VCHAR, VCHAR, VSQ,
31: /* ( ) * + , - . / */
32: VLPARA, VRPARA, VCHAR, VSIGN, VCHAR, VSIGN, VPERD, VCHAR,
33: /* 0 1 2 3 4 5 6 7 */
34: VNUM, VNUM, VNUM, VNUM, VNUM, VNUM, VNUM, VNUM,
35: /* 8 9 : ; < = > ? */
36: VNUM, VNUM, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR,
37: /* @ A B C D E F G */
38: VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR,
39: /* H I J K L M N O */
40: VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR,
41: /* P Q R S T U V W */
42: VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR,
43: /* X Y Z [ \ ] ^ _ */
44: VCHAR, VCHAR, VCHAR, VLBRCK, VESC, VRBRCK, VCHAR, VCHAR,
45: /* ` a b c d e f g */
46: VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR,
47: /* h i j k l m n o */
48: VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR,
49: /* p q r s t u v w */
50: VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR, VCHAR,
51: /* x y z { | } ~ del */
52: VCHAR, VCHAR, VCHAR, VCHAR, VDQ, VCHAR, VCHAR, VERR,
53: /* unused Xsdc Xesc Xdqc */
54: 0, '"', '\\', '|'
55: };
56:
57: extern unsigned char *ctable;
58: lispval atomval; /* external varaible containing atom returned
59: from internal atom reading routine */
60: lispval readrx(); lispval readr(); lispval readry();
61: char *atomtoolong();
62: int keywait;
63: int plevel = -1; /* contains maximum list recursion count */
64: int plength = -1; /* maximum number of list elements printed */
65: static int dbqflag;
66: static int mantisfl = 0;
67: extern int uctolc;
68: extern lispval lastrtab; /* external variable designating current reader
69: table */
70: static char baddot1[]=
71: "Bad reader construction: (. <something>)\nShould be (nil . <something>)\n";
72: static char baddot2[]=
73: "Bad reader construction: (<something> . <something> not followed by )";
74:
75: /* readr ****************************************************************/
76: /* returns a s-expression read in from the port specified as the first */
77: /* argument. Handles superbrackets, reader macros. */
78: lispval
79: readr(useport)
80: FILE *useport;
81: {
82: register lispval handy = Vreadtable->a.clb;
83:
84: chkrtab(handy);
85: rbktf = FALSE;
86: rdrport = (FILE *) useport;
87: if(useport==stdin)
88: keywait = TRUE;
89: handy = readrx(Iratom());
90: if(useport==stdin)
91: keywait = FALSE;
92: return(handy);
93:
94: }
95:
96:
97: /* readrx **************************************************************/
98: /* returns a s-expression beginning with the syntax code of an atom */
99: /* passed in the first */
100: /* argument. Does the actual work for readr, including list, dotted */
101: /* pair, and quoted atom detection */
102: lispval
103: readrx(code)
104: register int code;
105: {
106: register lispval work;
107: register lispval *current;
108: register struct argent *result;
109: int inlbkt = FALSE;
110: lispval errorh();
111: Savestack(4); /* ???not necessary because np explicitly restored if
112: changed */
113:
114: top:
115: switch(code)
116: {
117: case TLBKT:
118: inlbkt = TRUE;
119: case TLPARA:
120: result = np;
121: current = (lispval *)np;
122: np++->val = nil; /*protect(nil);*/
123: for(EVER) {
124: switch(code = Iratom())
125: {
126: case TRPARA:
127: if(rbktf && inlbkt)
128: rbktf = FALSE;
129: goto out;
130: default:
131: atomval = readrx(code);
132: case TSCA:
133: np++->val=atomval;
134: *current = work = newdot();
135: work->d.car = atomval;
136: np--;
137: current = (lispval *) &(work->d.cdr);
138: break;
139: case TINF:
140: imacrox(result->val,TRUE);
141: work = atomval;
142: result->val = work->d.car;
143: current = (lispval *) & (result->val);
144: goto mcom;
145: case TSPL:
146: macrox(); /* input and output in atomval */
147: *current = atomval;
148: mcom:
149: while(*current!=nil) {
150: if(TYPE(*current)!=DTPR)
151: errorh1(Vermisc,"Non-list returned from splicing macro",nil,FALSE,7,*current);
152: current=(lispval *)&((*current)->d.cdr);
153: }
154: break;
155: case TPERD:
156: if(result->val==nil) {
157: work = result->val=newdot();
158: current = (lispval *) &(work->d.cdr);
159: fprintf(stderr,baddot1);
160: }
161: work = readrx(TLPARA);
162: if (work->d.cdr!=nil) {
163: *current = work; work = newdot();
164: work->d.cdr = *current; *current = nil;
165: work->d.car = result->val;
166: result->val = errorh1(Vermisc,baddot2,nil,TRUE,58,work);
167: goto out;
168: }
169: *current = work->d.car;
170: /* there is the possibility that the expression
171: following the dot is terminated with a "]"
172: and thus needs no closing lparens to follow
173: */
174: if(rbktf && inlbkt)
175: rbktf = FALSE;
176: goto out;
177: case TEOF:
178: errorh1(Vermisc,"Premature end of file after ",
179: nil,FALSE,0,result->val);
180: }
181: if(rbktf) {
182: if(inlbkt)
183: rbktf = FALSE;
184: goto out;
185: }
186: }
187: case TSCA:
188: Restorestack();
189: return(atomval);
190: case TEOF:
191: Restorestack();
192: return(eofa);
193: case TMAC:
194: macrox();
195: Restorestack();
196: return(atomval);
197: case TINF:
198: imacrox(nil,FALSE);
199: work = atomval;
200: if(work==nil) { code = Iratom(); goto top;}
201: work = work->d.car;
202: Restorestack();
203: if(work->d.cdr==nil)
204: return(work->d.car);
205: else
206: return(work);
207: case TSPL:
208: macrox();
209: if((work = atomval)!=nil) {
210: if(TYPE(work)==DTPR && work->d.cdr==nil) {
211: Restorestack();
212: return(work->d.car);
213: } else {
214: errorh1(Vermisc,
215: "Improper value returned from splicing macro at top-level",nil,FALSE,9,work);
216: }
217: }
218: code = Iratom();
219: goto top;
220: /* return(readrx(Iratom())); */
221: case TSQ:
222: result = np;
223: protect(newdot());
224: (work = result->val)->d.car = quota;
225: work = work->d.cdr = newdot();
226: work->d.car = readrx(Iratom());
227: goto out;
228:
229: case TRPARA:
230: Restorestack();
231: return(errorh(Vermisc,
232: "read: read a right paren when expecting an s-expression",
233: nil,FALSE,0));
234: case TPERD:
235: Restorestack();
236: return(errorh(Vermisc,
237: "read: read a period when expecting an s-expression",
238: nil,FALSE,0));
239:
240: /* should never get here, we should have covered all cases above */
241: default:
242: Restorestack();
243: return(errorh1(Vermisc,"Readlist error, code ",nil,FALSE,0,inewint((long)code)));
244: }
245: out:
246: work = result->val;
247: np = result;
248: Restorestack();
249: return(work);
250: }
251: macrox()
252: {
253: FILE *svport;
254: lispval handy, Lapply();
255:
256: Savestack(0);
257: svport = rdrport; /* save from possible changing */
258: lbot = np;
259: protect(handy=Iget(atomval,lastrtab));
260: if (handy == nil)
261: {
262: errorh1(Vermisc,"read: can't find the character macro for ",nil,
263: FALSE,0,atomval);
264: }
265: protect(nil);
266: atomval = Lapply();
267: chkrtab(Vreadtable->a.clb); /* the macro could have changed
268: the readtable
269: */
270: rdrport = svport; /* restore old value */
271: Restorestack();
272: return;
273: }
274: imacrox(current,inlist)
275: register lispval current;
276: {
277: FILE *svport;
278: register lispval work;
279: lispval Lapply(), handy;
280:
281: Savestack(2);
282: svport = rdrport; /* save from possible changing */
283: if(inlist)
284: {
285: protect(handy = newdot());
286: handy->d.car = current;
287: for(work = handy->d.car; (TYPE(work->d.cdr))==DTPR; )
288: work = work->d.cdr;
289: handy->d.cdr = work;
290: }
291: else handy = current;
292:
293: lbot = np;
294: protect(Iget(atomval,lastrtab));
295: protect(handy);
296: atomval = Lfuncal();
297: chkrtab(Vreadtable->a.clb); /* the macro could have changed
298: the readtable
299: */
300: rdrport = svport; /* restore old value */
301: Restorestack();
302: return;
303: }
304:
305:
306:
307: /* ratomr ***************************************************************/
308: /* this routine returns a pointer to an atom read in from the port given*/
309: /* by the first argument */
310: lispval
311: ratomr(useport)
312: register FILE *useport;
313: {
314: rdrport = useport;
315: switch(Iratom())
316: {
317: case TEOF:
318: return(eofa);
319: case TSQ:
320: case TRPARA:
321: case TLPARA:
322: case TLBKT:
323: case TPERD:
324: strbuf[1]=0;
325: return(getatom(TRUE));
326: default:
327: return(atomval);
328: }
329: }
330:
331: #define push(); *name++ = c; if(name>=endstrb) name = atomtoolong(name);
332: #define next() (((cc=getc(useport))!=EOF)?(stats = ctable[c = cc &0177]):\
333: ((c=0),(saweof = 1),(stats = SEPMASK)))
334: Iratom()
335: {
336: register FILE *useport = rdrport;
337: register char c, marker, *name;
338: extern lispval finatom(), calcnum(), getnum();
339: int code, cc;
340: int strflag = FALSE;
341:
342: name = strbuf;
343:
344: again: cc = getc(useport);
345: if(cc==EOF)
346: {
347: clearerr(useport);
348: return(TEOF);
349: }
350: c = cc & 0177;
351: *name = c;
352:
353: switch(synclass(ctable[c])) {
354:
355: default: goto again;
356:
357: case synclass(VNUM):
358:
359: case synclass(VSIGN): *name++ = c;
360: atomval = (getnum(name));
361: return(TSCA);
362:
363: case synclass(VESC):
364: dbqflag = TRUE;
365: *name++ = getc(useport) & 0177;
366: atomval = (finatom(name));
367: return(TSCA);
368:
369: case synclass(VCHAR):
370: if(uctolc && isupper(c)) c = tolower(c);
371: *name++ = c;
372: atomval = (finatom(name));
373: return(TSCA);
374:
375: case synclass(VLPARA): return(TLPARA);
376:
377: case synclass(VRPARA): return(TRPARA);
378:
379: case synclass(VPERD): marker = peekc(useport) & 0177;
380: if(synclass(VNUM)!=synclass(ctable[marker]))
381: { if(SEPMASK & ctable[marker])
382: return(TPERD);
383: else { *name++ = c; /* this period begins an atm */
384: atomval = finatom(name);
385: return(TSCA);
386: }
387: }
388: *name++ = '.';
389: mantisfl = 1;
390: atomval = (getnum(name));
391: return(TSCA);
392:
393: case synclass(VLBRCK): return(TLBKT);
394:
395: case synclass(VRBRCK): rbktf = TRUE;
396: return(TRPARA);
397:
398: case synclass(VSQ): return(TSQ);
399:
400: case synclass(VSD): strflag = TRUE;
401: case synclass(VDQ): name = strbuf;
402: marker = c;
403: while ((c = getc(useport)) != marker) {
404:
405: if(synclass(VESC)==synclass(ctable[c]))
406: c = getc(useport) & 0177;
407: push();
408: if (feof(useport)) {
409: clearerr(useport);
410: error("EOF encountered while reading atom", FALSE);
411: }
412: }
413: *name = NULL_CHAR;
414: if(strflag)
415: atomval = (lispval) newstr(TRUE);
416: else
417: atomval = (getatom(TRUE));
418: return(TSCA);
419:
420: case synclass(VERR): if (c == '\0')
421: {
422: fprintf(stderr,"[read: null read and ignored]\n");
423: goto again; /* null pname */
424: }
425: fprintf(stderr,"%c (%o): ",c,(int) c);
426: error("ILLEGAL CHARACTER IN ATOM",TRUE);
427:
428: case synclass(VSINF):
429: code = TINF;
430: goto same;
431: case synclass(VSSPL):
432: code = TSPL;
433: goto same;
434: case synclass(VSMAC):
435: code = TMAC;
436: same:
437: marker = peekc(rdrport);
438: if(! (SEPMASK & ctable[marker]) ) {
439: *name++ = c; /* this is not a macro */
440: atomval = (finatom(name));
441: return(TSCA);
442: }
443: goto simple;
444: case synclass(VINF):
445: code = TINF;
446: goto simple;
447: case synclass(VSCA):
448: code = TSCA;
449: goto simple;
450: case synclass(VSPL):
451: code = TSPL;
452: goto simple;
453: case synclass(VMAC):
454: code = TMAC;
455: simple:
456: strbuf[0] = c;
457: strbuf[1] = 0;
458: atomval = (getatom(TRUE));
459: return(code);
460: }
461: }
462:
463: lispval
464: getnum(name)
465: register char *name;
466: {
467: unsigned char c;
468: register lispval result;
469: register FILE *useport=rdrport;
470: unsigned char stats;
471: int sawdigit = 0, saweof = 0,cc;
472: char *exploc = (char *) 0;
473: double realno;
474: extern lispval finatom(), calcnum(), newdoub(), dopow();
475:
476: if(mantisfl) {
477: mantisfl = 0;
478: next();
479: goto mantissa;
480: }
481: if(VNUM==ctable[*(unsigned char*)(name-1)]) sawdigit = 1;
482: while(VNUM==next()) {
483: push(); /* recognize [0-9]*, in "ex" parlance */
484: sawdigit = 1;
485: }
486: if(c=='.') {
487: push(); /* continue */
488: } else if(stats & SEPMASK) {
489: if(!saweof)ungetc((int)c,useport);
490: return(calcnum(strbuf,name,(int)ibase->a.clb->i));
491: } else if(c=='^') {
492: push();
493: return(dopow(name,(int)ibase->a.clb->i));
494: } else if(c=='_') {
495: if(sawdigit) /* _ must be preceeded by a digit */
496: {
497: push();
498: return(dopow(name,2));
499: }
500: else goto backout;
501: } else if(c=='e' || c=='E' || c=='d' ||c=='D') {
502: if(sawdigit) goto expt;
503: else goto backout;
504: } else {
505: backout:
506: ungetc((int)c,useport);
507: return(finatom(name));
508: }
509: /* at this point we have [0-9]*\. , which might
510: be a decimal int or the leading part of a
511: float */
512: if(next()!=VNUM) {
513: if(c=='e' || c=='E' || c=='d' ||c=='D')
514: goto expt;
515: else if(c=='^') {
516: push();
517: return(dopow(name,(int)ibase->a.clb->i));
518: } else if(c=='_') {
519: push();
520: return(dopow(name,2));
521: } else if( stats & SEPMASK) {
522: /* Here we have 1.x where x is not number
523: * but is a separator
524: * Here we have decimal int. NOT FORTRAN!
525: */
526: if(!saweof)ungetc((int)c,useport);
527: return(calcnum(strbuf,name-1,10));
528: }
529: else goto last; /* return a symbol */
530: }
531: mantissa:
532: do {
533: push();
534: } while (VNUM==next());
535:
536: /* Here we have [0-9]*\.[0-9]*
537: * three possibilities:
538: * next character is e,E,d or D in which case we examine
539: * the exponent [then we are faced with a similar
540: * situation to this one: is the character after the
541: * exponent a separator or not]
542: * next character is a separator, in which case we have a
543: * number (without an exponent)
544: * next character is not a separator in which case we have
545: * an atom (whose prefix just happens to look like a
546: * number)
547: */
548: if( (c == 'e') || (c == 'E') || (c == 'd') || (c == 'D')) goto expt;
549:
550: if(stats & SEPMASK) goto verylast; /* a real number */
551: else goto last; /* prefix makes it look like a number, but it isn't */
552:
553: expt:
554: exploc = name; /* remember location of exponent character */
555: push();
556: next();
557: if(c=='+' || c =='-') {
558: push();
559: next();
560: }
561: while (VNUM==stats) {
562: push();
563: next();
564: }
565:
566: /* if a separator follows then we have a number, else just
567: * an atom
568: */
569: if (stats & SEPMASK) goto verylast;
570:
571: last: /* get here when what looks like a number turns out to be an atom */
572: if(!saweof) ungetc((int)c,useport);
573: return(finatom(name));
574:
575: verylast:
576: if(!saweof) ungetc((int)c,useport);
577: /* scanf requires that the exponent be 'e' */
578: if(exploc != (char *) 0 ) *exploc = 'e';
579: *name=0;
580: sscanf(strbuf,"%F",&realno);
581: (result = newdoub())->r = realno;
582: return(result);
583: }
584:
585: lispval
586: dopow(part2,base)
587: register char *part2;
588: {
589: register char *name = part2;
590: register FILE *useport = rdrport;
591: register int power;
592: lispval work;
593: unsigned char stats,c;
594: int cc, saweof = 0;
595: char *end1 = part2 - 1; lispval Ltimes();
596: Savestack(4);
597:
598: while(VNUM==next()) {
599: push();
600: }
601: if(c!='.') {
602: if(!saweof)ungetc((int)c,useport);
603: }
604: if(c!='.' && !(stats & SEPMASK)) {
605: return(finatom(name));
606: }
607: lbot = np;
608: np++->val = inewint(base);
609: /* calculate "mantissa"*/
610: if(*end1=='.')
611: np++->val = calcnum(strbuf,end1-1,10);
612: else
613: np++->val = calcnum(strbuf,end1,(int)ibase->a.clb->i);
614:
615: /* calculate exponent */
616: if(c=='.')
617: power = calcnum(part2,name,10)->i;
618: else
619: power = calcnum(part2,name,(int)ibase->a.clb->i)->i;
620: while(power-- > 0)
621: lbot[1].val = Ltimes();
622: work = lbot[1].val;
623: Restorestack();
624: return(work);
625: }
626:
627:
628: lispval
629: calcnum(strbuf,name,base)
630: register char *name;
631: char *strbuf;
632: {
633: register char *p;
634: register lispval result, temp;
635: int negflag = 0;
636:
637: result = temp = newsdot(); /* initialize sdot cell */
638: protect(temp);
639: p = strbuf;
640: if(*p=='+') p++;
641: else if(*p=='-') {negflag = 1; p++;}
642: *name = 0;
643: if(p>=name) return(getatom(TRUE));
644:
645: for(;p < name; p++)
646: dmlad(temp,(long)base,(long)*p-'0');
647: if(negflag)
648: dmlad(temp,-1L,0L);
649:
650: if(temp->s.CDR==0) {
651: result = inewint(temp->i);
652: pruneb(np[-1].val);
653: }
654: np--;
655: return(result);
656: }
657: lispval
658: finatom(name)
659: register char *name;
660: {
661: register FILE *useport = rdrport;
662: unsigned char c, stats;
663: int cc, saweof = 0;
664:
665: while(!(next()&SEPMASK)) {
666:
667: if(synclass(stats) == synclass(VESC)) {
668: c = getc(useport) & 0177;
669: } else {
670: if(uctolc && isupper(c)) c = tolower(c);
671: }
672: push();
673: }
674: *name = NULL_CHAR;
675: if(!saweof)ungetc((int)c,useport);
676: return(getatom(TRUE));
677: }
678:
679: char *
680: atomtoolong(copyto)
681: char *copyto;
682: {
683: int size;
684: register char *oldp = strbuf;
685: register char *newp;
686: lispval nveci();
687: /*
688: * the string buffer contains an string which is too long
689: * so we get a bigger buffer.
690: */
691:
692: size = (endstrb - strbuf)*4 + 28 ;
693: newp = (char *) nveci(size);
694: atom_buffer = (lispval) newp;
695: strbuf = newp;
696: endstrb = newp + size - 1;
697: while(oldp < copyto) *newp++ = *oldp++;
698: return(newp);
699: }
700:
701: /* printr ***************************************************************/
702: /* prints the first argument onto the port specified by the second */
703:
704: /*
705: * Last modified Mar 21, 1980 for hunks
706: */
707:
708: printr(a,useport)
709: register lispval a;
710: register FILE *useport;
711: {
712: register hsize, i;
713: char strflag = 0;
714: char Idqc = 0;
715: char *chstr;
716: int curplength = plength;
717: int quot;
718: lispval Istsrch();
719: lispval debugmode;
720:
721: val_loop:
722: if(! VALID(a)) {
723: debugmode = Istsrch(matom("debugging"))->d.cdr->d.cdr->d.cdr;
724: if(debugmode != nil) {
725: printf("<printr:bad lisp data: 0x%x>\n",a);
726: error("Bad lisp data encountered by printr", FALSE);
727: } else {
728: a = badst;
729: printf("<printr:bad lisp data: 0x%x>",a);
730: return;
731: }
732: }
733:
734: switch (TYPE(a))
735: {
736:
737:
738: case UNBO: fputs("<UNBOUND>",useport);
739: break;
740:
741: case VALUE: fputs("(ptr to)",useport);
742: a = a->l;
743: goto val_loop;
744:
745: case INT: fprintf(useport,"%d",a->i);
746: break;
747:
748: case DOUB: { char buf[64];
749: lfltpr(buf,a->r);
750: fputs(buf,useport);
751: }
752: break;
753:
754: case PORT: { lispval cp;
755: if((cp = ioname[PN(a->p)]) == nil)
756: fputs("%$unopenedport",useport);
757: else fprintf(useport,"%%%s",cp);
758: }
759: break;
760:
761: case HUNK2:
762: case HUNK4:
763: case HUNK8:
764: case HUNK16:
765: case HUNK32:
766: case HUNK64:
767: case HUNK128:
768: if(plevel == 0)
769: {
770: fputs("%",useport);
771: break;
772: }
773: hsize = 2 << HUNKSIZE(a);
774: fputs("{", useport);
775: plevel--;
776: printr(a->h.hunk[0], useport);
777: curplength--;
778: for (i=1; i < hsize; i++)
779: {
780: if (a->h.hunk[i] == hunkfree)
781: break;
782: if (curplength-- == 0)
783: {
784: fputs(" ...",useport);
785: break;
786: }
787: else
788: {
789: fputs(" ", useport);
790: printr(a->h.hunk[i], useport);
791: }
792: }
793: fputs("}", useport);
794: plevel++;
795: break;
796:
797: case VECTOR:
798: chstr = "vector";
799: quot = 4; /* print out # of longwords */
800: goto veccommon;
801:
802: case VECTORI:
803: chstr = "vectori";
804: quot = 1;
805: veccommon:
806: /* print out 'vector' or 'vectori' except in
807: * these circumstances:
808: * property is a symbol, in which case print
809: * the symbol's pname
810: * property is a list with a 'print' property,
811: * in which case it is funcalled to print the
812: * vector
813: */
814: if(a->v.vector[VPropOff] != nil)
815: {
816: if ((i=TYPE(a->v.vector[VPropOff])) == ATOM)
817: {
818: chstr = a->v.vector[VPropOff]->a.pname;
819: }
820: else if ((i == DTPR) && vectorpr(a,useport))
821: {
822: break; /* printed by vectorpr */
823: }
824: else if ((i == DTPR)
825: && (a->v.vector[VPropOff]->d.car != nil)
826: && TYPE(a->v.vector[VPropOff]->d.car)
827: == ATOM)
828: {
829: chstr = a->v.vector[VPropOff]->d.car->a.pname;
830: }
831: }
832: fprintf(useport,"%s[%d]",
833: chstr, a->vl.vectorl[VSizeOff]/quot);
834: break;
835:
836: case ARRAY: fputs("array[",useport);
837: printr(a->ar.length,useport);
838: fputs("]",useport);
839: break;
840:
841: case BCD: fprintf(useport,"#%X-",a->bcd.start);
842: printr(a->bcd.discipline,useport);
843: break;
844:
845: case OTHER: fprintf(useport,"#Other-%X",a);
846: break;
847:
848: case SDOT: pbignum(a,useport);
849: break;
850:
851: case DTPR: if(plevel==0)
852: {
853: fputs("&",useport);
854: break;
855: }
856: plevel--;
857: if(a->d.car==quota && a->d.cdr!=nil
858: && a->d.cdr->d.cdr==nil) {
859: putc('\'',useport);
860: printr(a->d.cdr->d.car,useport);
861: plevel++;
862: break;
863: }
864: putc('(',useport);
865: curplength--;
866: morelist: printr(a->d.car,useport);
867: if ((a = a->d.cdr) != nil)
868: {
869: if(curplength-- == 0)
870: {
871: fputs(" ...",useport);
872: goto out;
873: }
874: putc(' ',useport);
875: if (TYPE(a) == DTPR) goto morelist;
876: fputs(". ",useport);
877: printr(a,useport);
878: }
879: out:
880: fputc(')',useport);
881: plevel++;
882: break;
883:
884: case STRNG: strflag = TRUE;
885: Idqc = Xsdc;
886:
887: case ATOM: {
888: char *front, *temp, first; int clean;
889: temp = front = (strflag ? ((char *) a) : a->a.pname);
890: if(Idqc==0) Idqc = Xdqc;
891:
892: if(Idqc) {
893: clean = first = *temp;
894: first &= 0177;
895: switch(QUTMASK & ctable[first]) {
896: case QWNFRST:
897: case QALWAYS:
898: clean = 0; break;
899: case QWNUNIQ:
900: if(temp[1]==0) clean = 0;
901: }
902: if (first=='-'||first=='+') temp++;
903: if(synclass(ctable[*temp])==VNUM) clean = 0;
904: while (clean && *temp) {
905: if((ctable[*temp]&QUTMASK)==QALWAYS)
906: clean = 0;
907: else if(uctolc && (isupper(*temp)))
908: clean = 0;
909: temp++;
910: }
911: if (clean && !strflag)
912: fputs(front,useport);
913: else {
914: putc(Idqc,useport);
915: for(temp=front;*temp;temp++) {
916: if( *temp==Idqc
917: || (synclass(ctable[*temp])) == CESC)
918: putc(Xesc,useport);
919: putc(*temp,useport);
920: }
921: putc(Idqc,useport);
922: }
923:
924: } else {
925: register char *cp = front;
926: int handy = ctable[*cp & 0177];
927:
928: if(synclass(handy)==CNUM)
929: putc(Xesc,useport);
930: else switch(handy & QUTMASK) {
931: case QWNUNIQ:
932: if(cp[1]==0) putc(Xesc,useport);
933: break;
934: case QWNFRST:
935: case QALWAYS:
936: putc(Xesc,useport);
937: }
938: for(; *cp; cp++) {
939: if((ctable[*cp]& QUTMASK)==QALWAYS)
940: putc(Xesc,useport);
941: putc(*cp,useport);
942: }
943: }
944: }
945: }
946: }
947:
948: /* -- vectorpr
949: * (perhaps) print out vector specially
950: * this is called with a vector whose property list begins with
951: * a list. We search for the 'print' property and if it exists,
952: * funcall the print function with two args: the vector and the port.
953: * We return TRUE iff we funcalled the function, else we return FALSE
954: * to have the standard printing done
955: */
956:
957: vectorpr(vec,port)
958: register lispval vec;
959: FILE *port;
960: {
961: register lispval handy;
962: int svplevel = plevel; /* save these global values */
963: int svplength = plength;
964: Savestack(2);
965:
966:
967: for ( handy = vec->v.vector[VPropOff]->d.cdr
968: ; handy != nil; handy = handy->d.cdr->d.cdr)
969: {
970: if (handy->d.car == Vprintsym)
971: {
972: lbot = np;
973: protect(handy->d.cdr->d.car); /* function to call */
974: protect(vec);
975: protect(P(port));
976: Lfuncal();
977: plevel = svplevel; /* restore globals */
978: plength = svplength;
979: Restorestack();
980: return(TRUE); /* did the call */
981: }
982: }
983: Restorestack();
984: return(FALSE); /* nothing printed */
985: }
986:
987:
988:
989:
990:
991:
992: lfltpr(buf,val) /* lisp floating point printer */
993: char *buf;
994: double val;
995: {
996: register char *cp1; char *sprintf();
997:
998: sprintf(buf,(char *)Vfloatformat->a.clb,val);
999: for(cp1 = buf; *cp1; cp1++)
1000: if(*cp1=='.'|| *cp1=='E' || *cp1 == 'e') return;
1001:
1002: /* if we are here, there was no dot, so the number was
1003: an integer. Furthermore, cp1 already points to the
1004: end of the string. */
1005:
1006: *cp1++ = '.';
1007: *cp1++ = '0';
1008: *cp1++ = 0;
1009: }
1010:
1011:
1012: /* dmpport ****************************************************************/
1013: /* outputs buffer indicated by first argument whether full or not */
1014:
1015: dmpport(useport)
1016: FILE *useport;
1017: {
1018: fflush(useport);
1019: }
1020:
1021: /* 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.