|
|
1.1 ! root 1: /* Copyright (c) 1979 Regents of the University of California */ ! 2: ! 3: static char sccsid[] = "@(#)stat.c 1.1 8/27/80"; ! 4: ! 5: #include "whoami.h" ! 6: #include "0.h" ! 7: #include "tree.h" ! 8: #include "objfmt.h" ! 9: #ifdef PC ! 10: # include "pcops.h" ! 11: # include "pc.h" ! 12: #endif PC ! 13: ! 14: int cntstat; ! 15: short cnts = 3; ! 16: #include "opcode.h" ! 17: ! 18: /* ! 19: * Statement list ! 20: */ ! 21: statlist(r) ! 22: int *r; ! 23: { ! 24: register *sl; ! 25: ! 26: for (sl=r; sl != NIL; sl=sl[2]) ! 27: statement(sl[1]); ! 28: } ! 29: ! 30: /* ! 31: * Statement ! 32: */ ! 33: statement(r) ! 34: int *r; ! 35: { ! 36: register *s; ! 37: register struct nl *snlp; ! 38: long soffset; ! 39: ! 40: s = r; ! 41: snlp = nlp; ! 42: soffset = sizes[ cbn ].om_off; ! 43: top: ! 44: if (cntstat) { ! 45: cntstat = 0; ! 46: putcnt(); ! 47: } ! 48: if (s == NIL) ! 49: return; ! 50: line = s[1]; ! 51: if (s[0] == T_LABEL) { ! 52: labeled(s[2]); ! 53: s = s[3]; ! 54: noreach = 0; ! 55: cntstat = 1; ! 56: goto top; ! 57: } ! 58: if (noreach) { ! 59: noreach = 0; ! 60: warning(); ! 61: error("Unreachable statement"); ! 62: } ! 63: switch (s[0]) { ! 64: case T_PCALL: ! 65: putline(); ! 66: # ifdef OBJ ! 67: proc(s); ! 68: # endif OBJ ! 69: # ifdef PC ! 70: pcproc( s ); ! 71: # endif PC ! 72: break; ! 73: case T_ASGN: ! 74: putline(); ! 75: asgnop(s); ! 76: break; ! 77: case T_GOTO: ! 78: putline(); ! 79: gotoop(s[2]); ! 80: noreach = 1; ! 81: cntstat = 1; ! 82: break; ! 83: default: ! 84: level++; ! 85: switch (s[0]) { ! 86: default: ! 87: panic("stat"); ! 88: case T_IF: ! 89: case T_IFEL: ! 90: ifop(s); ! 91: break; ! 92: case T_WHILE: ! 93: whilop(s); ! 94: noreach = 0; ! 95: break; ! 96: case T_REPEAT: ! 97: repop(s); ! 98: break; ! 99: case T_FORU: ! 100: case T_FORD: ! 101: # ifdef OBJ ! 102: forop(s); ! 103: # endif OBJ ! 104: # ifdef PC ! 105: pcforop( s ); ! 106: # endif PC ! 107: noreach = 0; ! 108: break; ! 109: case T_BLOCK: ! 110: statlist(s[2]); ! 111: break; ! 112: case T_CASE: ! 113: putline(); ! 114: # ifdef OBJ ! 115: caseop(s); ! 116: # endif OBJ ! 117: # ifdef PC ! 118: pccaseop( s ); ! 119: # endif PC ! 120: break; ! 121: case T_WITH: ! 122: withop(s); ! 123: break; ! 124: case T_ASRT: ! 125: putline(); ! 126: asrtop(s); ! 127: break; ! 128: } ! 129: --level; ! 130: if (gotos[cbn]) ! 131: ungoto(); ! 132: break; ! 133: } ! 134: /* ! 135: * Free the temporary name list entries defined in ! 136: * expressions, e.g. STRs, and WITHPTRs from withs. ! 137: */ ! 138: nlfree(snlp); ! 139: /* ! 140: * free any temporaries allocated for this statement ! 141: * these come from strings and sets. ! 142: */ ! 143: if ( soffset != sizes[ cbn ].om_off ) { ! 144: sizes[ cbn ].om_off = soffset; ! 145: # ifdef PC ! 146: putlbracket( ftnno , -sizes[cbn].om_off ); ! 147: # endif PC ! 148: } ! 149: } ! 150: ! 151: ungoto() ! 152: { ! 153: register struct nl *p; ! 154: ! 155: for (p = gotos[cbn]; p != NIL; p = p->chain) ! 156: if ((p->nl_flags & NFORWD) != 0) { ! 157: if (p->value[NL_GOLEV] != NOTYET) ! 158: if (p->value[NL_GOLEV] > level) ! 159: p->value[NL_GOLEV] = level; ! 160: } else ! 161: if (p->value[NL_GOLEV] != DEAD) ! 162: if (p->value[NL_GOLEV] > level) ! 163: p->value[NL_GOLEV] = DEAD; ! 164: } ! 165: ! 166: putcnt() ! 167: { ! 168: ! 169: if (monflg == 0) { ! 170: return; ! 171: } ! 172: inccnt( getcnt() ); ! 173: } ! 174: ! 175: int ! 176: getcnt() ! 177: { ! 178: ! 179: return ++cnts; ! 180: } ! 181: ! 182: inccnt( counter ) ! 183: int counter; ! 184: { ! 185: ! 186: # ifdef OBJ ! 187: put2(O_COUNT, counter ); ! 188: # endif OBJ ! 189: # ifdef PC ! 190: putRV( PCPCOUNT , 0 , counter * sizeof (long) , P2INT ); ! 191: putleaf( P2ICON , 1 , 0 , P2INT , 0 ); ! 192: putop( P2ASG P2PLUS , P2INT ); ! 193: putdot( filename , line ); ! 194: # endif PC ! 195: } ! 196: ! 197: putline() ! 198: { ! 199: ! 200: # ifdef OBJ ! 201: if (opt('p') != 0) ! 202: put2(O_LINO, line); ! 203: # endif OBJ ! 204: # ifdef PC ! 205: static lastline; ! 206: ! 207: if ( line != lastline ) { ! 208: stabline( line ); ! 209: lastline = line; ! 210: } ! 211: if ( opt( 'p' ) ) { ! 212: if ( opt('t') ) { ! 213: putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 214: , "_LINO" ); ! 215: putop( P2UNARY P2CALL , P2INT ); ! 216: putdot( filename , line ); ! 217: } else { ! 218: putRV( STMTCOUNT , 0 , 0 , P2INT ); ! 219: putleaf( P2ICON , 1 , 0 , P2INT , 0 ); ! 220: putop( P2ASG P2PLUS , P2INT ); ! 221: putdot( filename , line ); ! 222: } ! 223: } ! 224: # endif PC ! 225: } ! 226: ! 227: /* ! 228: * With varlist do stat ! 229: * ! 230: * With statement requires an extra word ! 231: * in automatic storage for each level of withing. ! 232: * These indirect pointers are initialized here, and ! 233: * the scoping effect of the with statement occurs ! 234: * because lookup examines the field names of the records ! 235: * associated with the WITHPTRs on the withlist. ! 236: */ ! 237: withop(s) ! 238: int *s; ! 239: { ! 240: register *p; ! 241: register struct nl *r; ! 242: int i; ! 243: int *swl; ! 244: long soffset; ! 245: ! 246: putline(); ! 247: swl = withlist; ! 248: soffset = sizes[cbn].om_off; ! 249: for (p = s[2]; p != NIL; p = p[2]) { ! 250: i = sizes[cbn].om_off -= sizeof ( int * ); ! 251: if (sizes[cbn].om_off < sizes[cbn].om_max) ! 252: sizes[cbn].om_max = sizes[cbn].om_off; ! 253: # ifdef OBJ ! 254: put2(O_LV | cbn <<8+INDX, i ); ! 255: # endif OBJ ! 256: # ifdef PC ! 257: putlbracket( ftnno , -sizes[cbn].om_off ); ! 258: putRV( 0 , cbn , i , P2PTR|P2STRTY ); ! 259: # endif PC ! 260: r = lvalue(p[1], MOD , LREQ ); ! 261: if (r == NIL) ! 262: continue; ! 263: if (r->class != RECORD) { ! 264: error("Variable in with statement refers to %s, not to a record", nameof(r)); ! 265: continue; ! 266: } ! 267: r = defnl(0, WITHPTR, r, i); ! 268: r->nl_next = withlist; ! 269: withlist = r; ! 270: # ifdef OBJ ! 271: put(1, PTR_AS); ! 272: # endif OBJ ! 273: # ifdef PC ! 274: putop( P2ASSIGN , P2PTR|P2STRTY ); ! 275: putdot( filename , line ); ! 276: # endif PC ! 277: } ! 278: statement(s[3]); ! 279: sizes[cbn].om_off = soffset; ! 280: # ifdef PC ! 281: putlbracket( ftnno , -sizes[cbn].om_off ); ! 282: # endif PC ! 283: withlist = swl; ! 284: } ! 285: ! 286: extern flagwas; ! 287: /* ! 288: * var := expr ! 289: */ ! 290: asgnop(r) ! 291: int *r; ! 292: { ! 293: register struct nl *p; ! 294: register *av; ! 295: ! 296: if (r == NIL) ! 297: return (NIL); ! 298: /* ! 299: * Asgnop's only function is ! 300: * to handle function variable ! 301: * assignments. All other assignment ! 302: * stuff is handled by asgnop1. ! 303: * the if below checks for unqualified lefthandside: ! 304: * necessary for fvars. ! 305: */ ! 306: av = r[2]; ! 307: if (av != NIL && av[0] == T_VAR && av[3] == NIL) { ! 308: p = lookup1(av[2]); ! 309: if (p != NIL) ! 310: p->nl_flags = flagwas; ! 311: if (p != NIL && p->class == FVAR) { ! 312: /* ! 313: * Give asgnop1 the func ! 314: * which is the chain of ! 315: * the FVAR. ! 316: */ ! 317: p->nl_flags |= NUSED|NMOD; ! 318: p = p->chain; ! 319: if (p == NIL) { ! 320: rvalue(r[3], NIL , RREQ ); ! 321: return; ! 322: } ! 323: # ifdef OBJ ! 324: put2(O_LV | bn << 8+INDX, p->value[NL_OFFS]); ! 325: if (isa(p->type, "i") && width(p->type) == 1) ! 326: asgnop1(r, nl+T2INT); ! 327: else ! 328: asgnop1(r, p->type); ! 329: # endif OBJ ! 330: # ifdef PC ! 331: /* ! 332: * this should be the lvalue of the fvar, ! 333: * but since the second pass knows to use ! 334: * the address of the left operand of an ! 335: * assignment, what i want here is an rvalue. ! 336: * see note in funchdr about fvar allocation. ! 337: */ ! 338: p = p -> ptr[ NL_FVAR ]; ! 339: putRV( p -> symbol , bn , p -> value[ NL_OFFS ] ! 340: , p2type( p -> type ) ); ! 341: asgnop1( r , p -> type ); ! 342: # endif PC ! 343: return; ! 344: } ! 345: } ! 346: asgnop1(r, NIL); ! 347: } ! 348: ! 349: /* ! 350: * Asgnop1 handles all assignments. ! 351: * If p is not nil then we are assigning ! 352: * to a function variable, otherwise ! 353: * we look the variable up ourselves. ! 354: */ ! 355: struct nl * ! 356: asgnop1(r, p) ! 357: int *r; ! 358: register struct nl *p; ! 359: { ! 360: register struct nl *p1; ! 361: ! 362: if (r == NIL) ! 363: return (NIL); ! 364: if (p == NIL) { ! 365: # ifdef OBJ ! 366: p = lvalue(r[2], MOD|ASGN|NOUSE , LREQ ); ! 367: # endif OBJ ! 368: # ifdef PC ! 369: /* ! 370: * since the second pass knows that it should reference ! 371: * the lefthandside of asignments, what i need here is ! 372: * an rvalue. ! 373: */ ! 374: p = lvalue( r[2] , MOD|ASGN|NOUSE , RREQ ); ! 375: # endif PC ! 376: if ( p == NIL ) { ! 377: rvalue( r[3] , NIL , RREQ ); ! 378: return NIL; ! 379: } ! 380: } ! 381: # ifdef OBJ ! 382: p1 = rvalue(r[3], p , RREQ ); ! 383: # endif OBJ ! 384: # ifdef PC ! 385: /* ! 386: * if this is a scalar assignment, ! 387: * then i want to rvalue the righthandside. ! 388: * if this is a structure assignment, ! 389: * then i want an lvalue to the righthandside. ! 390: * that's what the intermediate form sez. ! 391: */ ! 392: switch ( classify( p ) ) { ! 393: case TINT: ! 394: case TCHAR: ! 395: case TBOOL: ! 396: case TSCAL: ! 397: precheck( p , "_RANG4" , "_RSNG4" ); ! 398: case TDOUBLE: ! 399: case TPTR: ! 400: p1 = rvalue( r[3] , p , RREQ ); ! 401: break; ! 402: default: ! 403: p1 = rvalue( r[3] , p , LREQ ); ! 404: break; ! 405: } ! 406: # endif PC ! 407: if (p1 == NIL) ! 408: return (NIL); ! 409: if (incompat(p1, p, r[3])) { ! 410: cerror("Type of expression clashed with type of variable in assignment"); ! 411: return (NIL); ! 412: } ! 413: switch (classify(p)) { ! 414: case TINT: ! 415: case TBOOL: ! 416: case TCHAR: ! 417: case TSCAL: ! 418: # ifdef OBJ ! 419: rangechk(p, p1); ! 420: # endif OBJ ! 421: # ifdef PC ! 422: postcheck( p ); ! 423: # endif PC ! 424: case TDOUBLE: ! 425: case TPTR: ! 426: # ifdef OBJ ! 427: gen(O_AS2, O_AS2, width(p), width(p1)); ! 428: # endif OBJ ! 429: # ifdef PC ! 430: putop( P2ASSIGN , p2type( p ) ); ! 431: putdot( filename , line ); ! 432: # endif PC ! 433: break; ! 434: default: ! 435: # ifdef OBJ ! 436: put2(O_AS, width(p)); ! 437: # endif OBJ ! 438: # ifdef PC ! 439: putstrop( P2STASG , p2type( p ) ! 440: , lwidth( p ) , align( p ) ); ! 441: putdot( filename , line ); ! 442: # endif PC ! 443: } ! 444: return (p); /* Used by for statement */ ! 445: } ! 446: ! 447: #ifdef OBJ ! 448: /* ! 449: * for var := expr [down]to expr do stat ! 450: */ ! 451: forop(r) ! 452: int *r; ! 453: { ! 454: register struct nl *t1, *t2; ! 455: int l1, l2, l3; ! 456: long soffset; ! 457: register op; ! 458: struct nl *p; ! 459: int *rr, goc, i; ! 460: ! 461: p = NIL; ! 462: goc = gocnt; ! 463: if (r == NIL) ! 464: goto aloha; ! 465: putline(); ! 466: /* ! 467: * Start with assignment ! 468: * of initial value to for variable ! 469: */ ! 470: t1 = asgnop1(r[2], NIL); ! 471: if (t1 == NIL) { ! 472: rvalue(r[3], NIL , RREQ ); ! 473: statement(r[4]); ! 474: goto aloha; ! 475: } ! 476: rr = r[2]; /* Assignment */ ! 477: rr = rr[2]; /* Lhs variable */ ! 478: if (rr[3] != NIL) { ! 479: error("For variable must be unqualified"); ! 480: rvalue(r[3], NIL , RREQ ); ! 481: statement(r[4]); ! 482: goto aloha; ! 483: } ! 484: p = lookup(rr[2]); ! 485: p->value[NL_FORV] = 1; ! 486: if (isnta(t1, "bcis")) { ! 487: error("For variables cannot be %ss", nameof(t1)); ! 488: statement(r[4]); ! 489: goto aloha; ! 490: } ! 491: /* ! 492: * Allocate automatic ! 493: * space for limit variable ! 494: */ ! 495: sizes[cbn].om_off -= 4; ! 496: if (sizes[cbn].om_off < sizes[cbn].om_max) ! 497: sizes[cbn].om_max = sizes[cbn].om_off; ! 498: i = sizes[cbn].om_off; ! 499: /* ! 500: * Initialize the limit variable ! 501: */ ! 502: put2(O_LV | cbn<<8+INDX, i); ! 503: t2 = rvalue(r[3], NIL , RREQ ); ! 504: if (incompat(t2, t1, r[3])) { ! 505: cerror("Limit type clashed with index type in 'for' statement"); ! 506: statement(r[4]); ! 507: goto aloha; ! 508: } ! 509: put1(width(t2) <= 2 ? O_AS24 : O_AS4); ! 510: /* ! 511: * See if we can skip the loop altogether ! 512: */ ! 513: rr = r[2]; ! 514: if (rr != NIL) ! 515: rvalue(rr[2], NIL , RREQ ); ! 516: put2(O_RV4 | cbn<<8+INDX, i); ! 517: gen(NIL, r[0] == T_FORU ? T_LE : T_GE, width(t1), 4); ! 518: /* ! 519: * L1 will be patched to skip the body of the loop. ! 520: * L2 marks the top of the loop when we go around. ! 521: */ ! 522: put2(O_IF, (l1 = getlab())); ! 523: putlab(l2 = getlab()); ! 524: putcnt(); ! 525: statement(r[4]); ! 526: /* ! 527: * now we see if we get to go again ! 528: */ ! 529: if (opt('t') == 0) { ! 530: /* ! 531: * Easy if we dont have to test ! 532: */ ! 533: put2(O_RV4 | cbn<<8+INDX, i); ! 534: if (rr != NIL) ! 535: lvalue(rr[2], MOD , RREQ ); ! 536: put2((r[0] == T_FORU ? O_FOR1U : O_FOR1D) + (width(t1) >> 1), l2); ! 537: } else { ! 538: line = r[1]; ! 539: putline(); ! 540: if (rr != NIL) ! 541: rvalue(rr[2], NIL , RREQ ); ! 542: put2(O_RV4 | cbn << 8+INDX, i); ! 543: gen(NIL, (r[0] == T_FORU ? T_LT : T_GT), width(t1), 4); ! 544: l3 = put2(O_IF, getlab()); ! 545: lvalue((int *) rr[2], MOD , RREQ ); ! 546: rvalue(rr[2], NIL , RREQ ); ! 547: put2(O_CON2, 1); ! 548: t2 = gen(NIL, r[0] == T_FORU ? T_ADD: T_SUB, width(t1), 2); ! 549: rangechk(t1, t2); /* The point of all this */ ! 550: gen(O_AS2, O_AS2, width(t1), width(t2)); ! 551: put2(O_TRA, l2); ! 552: patch(l3); ! 553: } ! 554: sizes[cbn].om_off += 4; ! 555: patch(l1); ! 556: aloha: ! 557: noreach = 0; ! 558: if (p != NIL) ! 559: p->value[NL_FORV] = 0; ! 560: if (goc != gocnt) ! 561: putcnt(); ! 562: } ! 563: #endif OBJ ! 564: ! 565: /* ! 566: * if expr then stat [ else stat ] ! 567: */ ! 568: ifop(r) ! 569: int *r; ! 570: { ! 571: register struct nl *p; ! 572: register l1, l2; /* l1 is start of else, l2 is end of else */ ! 573: int nr, goc; ! 574: ! 575: goc = gocnt; ! 576: if (r == NIL) ! 577: return; ! 578: putline(); ! 579: p = rvalue(r[2], NIL , RREQ ); ! 580: if (p == NIL) { ! 581: statement(r[3]); ! 582: noreach = 0; ! 583: statement(r[4]); ! 584: noreach = 0; ! 585: return; ! 586: } ! 587: if (isnta(p, "b")) { ! 588: error("Type of expression in if statement must be Boolean, not %s", nameof(p)); ! 589: statement(r[3]); ! 590: noreach = 0; ! 591: statement(r[4]); ! 592: noreach = 0; ! 593: return; ! 594: } ! 595: # ifdef OBJ ! 596: l1 = put2(O_IF, getlab()); ! 597: # endif OBJ ! 598: # ifdef PC ! 599: l1 = getlab(); ! 600: putleaf( P2ICON , l1 , 0 , P2INT , 0 ); ! 601: putop( P2CBRANCH , P2INT ); ! 602: putdot( filename , line ); ! 603: # endif PC ! 604: putcnt(); ! 605: statement(r[3]); ! 606: nr = noreach; ! 607: if (r[4] != NIL) { ! 608: /* ! 609: * else stat ! 610: */ ! 611: --level; ! 612: ungoto(); ! 613: ++level; ! 614: # ifdef OBJ ! 615: l2 = put2(O_TRA, getlab()); ! 616: # endif OBJ ! 617: # ifdef PC ! 618: l2 = getlab(); ! 619: putjbr( l2 ); ! 620: # endif PC ! 621: patch(l1); ! 622: noreach = 0; ! 623: statement(r[4]); ! 624: noreach &= nr; ! 625: l1 = l2; ! 626: } else ! 627: noreach = 0; ! 628: patch(l1); ! 629: if (goc != gocnt) ! 630: putcnt(); ! 631: } ! 632: ! 633: /* ! 634: * while expr do stat ! 635: */ ! 636: whilop(r) ! 637: int *r; ! 638: { ! 639: register struct nl *p; ! 640: register l1, l2; ! 641: int goc; ! 642: ! 643: goc = gocnt; ! 644: if (r == NIL) ! 645: return; ! 646: putlab(l1 = getlab()); ! 647: putline(); ! 648: p = rvalue(r[2], NIL , RREQ ); ! 649: if (p == NIL) { ! 650: statement(r[3]); ! 651: noreach = 0; ! 652: return; ! 653: } ! 654: if (isnta(p, "b")) { ! 655: error("Type of expression in while statement must be Boolean, not %s", nameof(p)); ! 656: statement(r[3]); ! 657: noreach = 0; ! 658: return; ! 659: } ! 660: l2 = getlab(); ! 661: # ifdef OBJ ! 662: put2(O_IF, l2); ! 663: # endif OBJ ! 664: # ifdef PC ! 665: putleaf( P2ICON , l2 , 0 , P2INT , 0 ); ! 666: putop( P2CBRANCH , P2INT ); ! 667: putdot( filename , line ); ! 668: # endif PC ! 669: putcnt(); ! 670: statement(r[3]); ! 671: # ifdef OBJ ! 672: put2(O_TRA, l1); ! 673: # endif OBJ ! 674: # ifdef PC ! 675: putjbr( l1 ); ! 676: # endif PC ! 677: patch(l2); ! 678: if (goc != gocnt) ! 679: putcnt(); ! 680: } ! 681: ! 682: /* ! 683: * repeat stat* until expr ! 684: */ ! 685: repop(r) ! 686: int *r; ! 687: { ! 688: register struct nl *p; ! 689: register l; ! 690: int goc; ! 691: ! 692: goc = gocnt; ! 693: if (r == NIL) ! 694: return; ! 695: l = putlab(getlab()); ! 696: putcnt(); ! 697: statlist(r[2]); ! 698: line = r[1]; ! 699: p = rvalue(r[3], NIL , RREQ ); ! 700: if (p == NIL) ! 701: return; ! 702: if (isnta(p,"b")) { ! 703: error("Until expression type must be Boolean, not %s, in repeat statement", nameof(p)); ! 704: return; ! 705: } ! 706: # ifdef OBJ ! 707: put2(O_IF, l); ! 708: # endif OBJ ! 709: # ifdef PC ! 710: putleaf( P2ICON , l , 0 , P2INT , 0 ); ! 711: putop( P2CBRANCH , P2INT ); ! 712: putdot( filename , line ); ! 713: # endif PC ! 714: if (goc != gocnt) ! 715: putcnt(); ! 716: } ! 717: ! 718: /* ! 719: * assert expr ! 720: */ ! 721: asrtop(r) ! 722: register int *r; ! 723: { ! 724: register struct nl *q; ! 725: ! 726: if (opt('s')) { ! 727: standard(); ! 728: error("Assert statement is non-standard"); ! 729: } ! 730: if (!opt('t')) ! 731: return; ! 732: r = r[2]; ! 733: # ifdef OBJ ! 734: q = rvalue((int *) r, NLNIL , RREQ ); ! 735: # endif OBJ ! 736: # ifdef PC ! 737: putleaf( P2ICON , 0 , 0 ! 738: , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_ASRT" ); ! 739: q = stkrval( r , NLNIL , RREQ ); ! 740: # endif PC ! 741: if (q == NIL) ! 742: return; ! 743: if (isnta(q, "b")) ! 744: error("Assert expression must be Boolean, not %ss", nameof(q)); ! 745: # ifdef OBJ ! 746: put1(O_ASRT); ! 747: # endif OBJ ! 748: # ifdef PC ! 749: putop( P2CALL , P2INT ); ! 750: putdot( filename , line ); ! 751: # endif PC ! 752: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.