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) */