1: # ifndef lint
   2: static char *sccsid ="@(#)local2.c	1.14 (Berkeley) 4/23/86";
   3: # endif
   4: 
   5: # include "pass2.h"
   6: # include "ctype.h"
   7: # ifdef FORT
   8: int ftlab1, ftlab2;
   9: # endif
  10: /* a lot of the machine dependent parts of the second pass */
  11: 
  12: # define putstr(s)  fputs((s), stdout)
  13: 
  14: # define BITMASK(n) ((1L<<n)-1)
  15: 
  16: where(c){
  17:     fprintf( stderr, "%s, line %d: ", filename, lineno );
  18:     }
  19: 
  20: lineid( l, fn ) char *fn; {
  21:     /* identify line l and file fn */
  22:     printf( "#	line %d, file %s\n", l, fn );
  23:     }
  24: 
  25: 
  26: eobl2(){
  27:     OFFSZ spoff;    /* offset from stack pointer */
  28: #ifdef FORT
  29:     spoff = maxoff;
  30:     if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
  31:     spoff /= SZCHAR;
  32:     SETOFF(spoff,4);
  33: #ifndef FLEXNAMES
  34:     printf( "	.set	.F%d,%ld\n", ftnno, spoff );
  35: #else
  36:     /* SHOULD BE L%d ... ftnno but must change pc/f77 */
  37:     printf( "	.set	LF%d,%ld\n", ftnno, spoff );
  38: #endif
  39: #else
  40:     extern int ftlab1, ftlab2;
  41: 
  42:     spoff = maxoff;
  43:     if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
  44:     spoff /= SZCHAR;
  45:     SETOFF(spoff,4);
  46:     printf( "L%d:\n", ftlab1);
  47:     if( spoff!=0 )
  48:         if( spoff < 64 )
  49:             printf( "	subl2	$%ld,sp\n", spoff);
  50:         else
  51:             printf( "	movab	-%ld(sp),sp\n", spoff);
  52:     printf( "	jbr 	L%d\n", ftlab2);
  53: #endif
  54:     maxargs = -1;
  55:     }
  56: 
  57: struct hoptab { int opmask; char * opstring; } ioptab[] = {
  58: 
  59:     ASG PLUS, "add",
  60:     ASG MINUS, "sub",
  61:     ASG MUL, "mul",
  62:     ASG DIV, "div",
  63:     ASG OR, "bis",
  64:     ASG ER, "xor",
  65:     ASG AND, "bic",
  66:     PLUS,   "add",
  67:     MINUS,  "sub",
  68:     MUL,    "mul",
  69:     DIV,    "div",
  70:     OR, "bis",
  71:     ER, "xor",
  72:     AND,    "bic",
  73:     -1, ""    };
  74: 
  75: hopcode( f, o ){
  76:     /* output the appropriate string from the above table */
  77: 
  78:     register struct hoptab *q;
  79: 
  80:     for( q = ioptab;  q->opmask>=0; ++q ){
  81:         if( q->opmask == o ){
  82:             putstr( q->opstring );
  83: /* tbl
  84: 			if( f == 'F' ) putchar( 'e' );
  85: 			else if( f == 'D' ) putchar( 'd' );
  86:    tbl */
  87: /* tbl */
  88:             switch( f ) {
  89:                 case 'L':
  90:                 case 'W':
  91:                 case 'B':
  92:                 case 'D':
  93:                 case 'F':
  94:                     putchar(tolower(f));
  95:                     break;
  96: 
  97:                 }
  98: /* tbl */
  99:             return;
 100:             }
 101:         }
 102:     cerror( "no hoptab for %s", opst[o] );
 103:     }
 104: 
 105: char *
 106: rnames[] = {  /* keyed to register number tokens */
 107: 
 108:     "r0", "r1",
 109:     "r2", "r3", "r4", "r5",
 110:     "r6", "r7", "r8", "r9", "r10", "r11",
 111:     "ap", "fp", "sp", "pc",
 112: 
 113:     };
 114: 
 115: int rstatus[] = {
 116:     SAREG|STAREG, SAREG|STAREG,
 117:     SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG,
 118:     SAREG, SAREG, SAREG, SAREG, SAREG, SAREG,
 119:     SAREG, SAREG, SAREG, SAREG,
 120: 
 121:     };
 122: 
 123: tlen(p) NODE *p;
 124: {
 125:     switch(p->in.type) {
 126:         case CHAR:
 127:         case UCHAR:
 128:             return(1);
 129: 
 130:         case SHORT:
 131:         case USHORT:
 132:             return(2);
 133: 
 134:         case DOUBLE:
 135:             return(8);
 136: 
 137:         default:
 138:             return(4);
 139:         }
 140: }
 141: 
 142: mixtypes(p, q) NODE *p, *q;
 143: {
 144:     register TWORD tp, tq;
 145: 
 146:     tp = p->in.type;
 147:     tq = q->in.type;
 148: 
 149:     return( (tp==FLOAT || tp==DOUBLE) !=
 150:         (tq==FLOAT || tq==DOUBLE) );
 151: }
 152: 
 153: prtype(n) NODE *n;
 154: {
 155:     switch (n->in.type)
 156:         {
 157:         case DOUBLE:
 158:             putchar('d');
 159:             return;
 160: 
 161:         case FLOAT:
 162:             putchar('f');
 163:             return;
 164: 
 165:         case LONG:
 166:         case ULONG:
 167:         case INT:
 168:         case UNSIGNED:
 169:             putchar('l');
 170:             return;
 171: 
 172:         case SHORT:
 173:         case USHORT:
 174:             putchar('w');
 175:             return;
 176: 
 177:         case CHAR:
 178:         case UCHAR:
 179:             putchar('b');
 180:             return;
 181: 
 182:         default:
 183:             if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type");
 184:             else {
 185:                 putchar('l');
 186:                 return;
 187:                 }
 188:         }
 189: }
 190: 
 191: zzzcode( p, c ) register NODE *p; {
 192:     register m;
 193:     CONSZ val;
 194:     switch( c ){
 195: 
 196:     case 'N':  /* logical ops, turned into 0-1 */
 197:         /* use register given by register 1 */
 198:         cbgen( 0, m=getlab(), 'I' );
 199:         deflab( p->bn.label );
 200:         printf( "	clrl	%s\n", rnames[getlr( p, '1' )->tn.rval] );
 201:         deflab( m );
 202:         return;
 203: 
 204:     case 'I':
 205:     case 'P':
 206:         cbgen( p->in.op, p->bn.label, c );
 207:         return;
 208: 
 209:     case 'A':
 210:         {
 211:         register NODE *l, *r;
 212: 
 213:         if (xdebug) eprint(p, 0, &val, &val);
 214:         r = getlr(p, 'R');
 215:         if (p->in.op == ASSIGN)
 216:             l = getlr(p, 'L');
 217:         else if (p->in.op == SCONV) {
 218:             l = resc;
 219: #if defined(FORT) || defined(SPRECC)
 220:             l->in.type = r->in.type;
 221: #else
 222:             l->in.type = r->in.type==FLOAT ? DOUBLE : r->in.type;
 223: #endif
 224:             r = getlr(p, 'L');
 225:             }
 226:         else {      /* OPLTYPE */
 227:             l = resc;
 228: #if defined(FORT) || defined(SPRECC)
 229:             l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT);
 230: #else
 231:             l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? DOUBLE : INT);
 232: #endif
 233:             }
 234:         if (r->in.op == ICON)
 235:             if (r->in.name[0] == '\0') {
 236:                 if (r->tn.lval == 0) {
 237:                     putstr("clr");
 238:                     prtype(l);
 239:                     putchar('\t');
 240:                     adrput(l);
 241:                     return;
 242:                     }
 243:                 if (r->tn.lval < 0 && r->tn.lval >= -63) {
 244:                     putstr("mneg");
 245:                     prtype(l);
 246:                     r->tn.lval = -r->tn.lval;
 247:                     goto ops;
 248:                     }
 249:                 if (r->tn.lval < 0)
 250:                     r->in.type = r->tn.lval >= -128 ? CHAR
 251:                         : (r->tn.lval >= -32768 ? SHORT
 252:                         : INT);
 253:                 else if (l->in.type == FLOAT ||
 254:                     l->in.type == DOUBLE)
 255:                     r->in.type = r->tn.lval <= 63 ? INT
 256:                         : (r->tn.lval <= 127 ? CHAR
 257:                         : (r->tn.lval <= 32767 ? SHORT
 258:                         : INT));
 259:                 else
 260:                     r->in.type = r->tn.lval <= 63 ? INT
 261:                         : (r->tn.lval <= 127 ? CHAR
 262:                         : (r->tn.lval <= 255 ? UCHAR
 263:                         : (r->tn.lval <= 32767 ? SHORT
 264:                         : (r->tn.lval <= 65535 ? USHORT
 265:                         : INT))));
 266:                 }
 267:             else {
 268:                 putstr("moval");
 269:                 putchar('\t');
 270:                 acon(r);
 271:                 putchar(',');
 272:                 adrput(l);
 273:                 return;
 274:                 }
 275: 
 276:         if (p->in.op == SCONV &&
 277:             !(l->in.type == FLOAT || l->in.type == DOUBLE) &&
 278:             !mixtypes(l, r)) {
 279:             /*
 280: 			 * Because registers must always contain objects
 281: 			 * of the same width as INTs, we may have to
 282: 			 * perform two conversions to get an INT.  Can
 283: 			 * the conversions be collapsed into one?
 284: 			 */
 285:             if (m = collapsible(l, r))
 286:                 r->in.type = m;
 287:             else {
 288:                 /*
 289: 				 * Two steps are required.
 290: 				 */
 291:                 NODE *x = &resc[1];
 292: 
 293:                 *x = *l;
 294:                 if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type))
 295:                     putstr("movz");
 296:                 else
 297:                     putstr("cvt");
 298:                 prtype(r);
 299:                 prtype(x);
 300:                 putchar('\t');
 301:                 adrput(r);
 302:                 putchar(',');
 303:                 adrput(x);
 304:                 putchar('\n');
 305:                 putchar('\t');
 306:                 r = x;
 307:                 }
 308:             l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT);
 309:             }
 310: 
 311:         if ((r->in.type == UNSIGNED || r->in.type == ULONG) &&
 312:             mixtypes(l, r)) {
 313:             int label1, label2;
 314: 
 315:             label1 = getlab();
 316:             label2 = getlab();
 317: 
 318:             putstr("movl\t");
 319:             adrput(r);
 320:             putchar(',');
 321:             adrput(l);
 322:             putstr("\n\tjbsc\t$31,");
 323:             adrput(l);
 324:             printf(",L%d\n\tcvtl", label1);
 325:             prtype(l);
 326:             putchar('\t');
 327:             adrput(l);
 328:             putchar(',');
 329:             adrput(l);
 330:             printf("\n\tjbr\tL%d\nL%d:\n\tcvtl", label2, label1);
 331:             prtype(l);
 332:             putchar('\t');
 333:             adrput(l);
 334:             putchar(',');
 335:             adrput(l);
 336:             putstr("\n\tadd");
 337:             prtype(l);
 338:             putstr("2\t$0");
 339:             prtype(l);
 340:             putstr("2.147483648e9,");
 341:             adrput(l);
 342:             printf("\nL%d:", label2);
 343: 
 344:             return;
 345:             }
 346: 
 347:         if (!mixtypes(l,r)) {
 348:             if (tlen(l) == tlen(r)) {
 349:                 putstr("mov");
 350: #ifdef FORT
 351:                 if (Oflag)
 352:                     prtype(l);
 353:                 else {
 354:                     if (l->in.type == DOUBLE)
 355:                         putchar('q');
 356:                     else if(l->in.type == FLOAT)
 357:                         putchar('l');
 358:                     else
 359:                         prtype(l);
 360:                     }
 361: #else
 362:                 prtype(l);
 363: #endif FORT
 364:                 goto ops;
 365:                 }
 366:             else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type))
 367:                 putstr("movz");
 368:             else
 369:                 putstr("cvt");
 370:             }
 371:         else
 372:             putstr("cvt");
 373:         prtype(r);
 374:         prtype(l);
 375:     ops:
 376:         putchar('\t');
 377:         adrput(r);
 378:         putchar(',');
 379:         adrput(l);
 380:         return;
 381:         }
 382: 
 383:     case 'G':   /* i *= f; asgops with int lhs and float rhs */
 384:         {
 385:         register NODE *l, *r, *s;
 386:         int rt;
 387: 
 388:         l = p->in.left;
 389:         r = p->in.right;
 390:         s = talloc();
 391:         rt = r->in.type;
 392: 
 393:         s->in.op = SCONV;
 394:         s->in.left = l;
 395:         s->in.type = rt;
 396:         zzzcode(s, 'A');
 397:         putstr("\n\t");
 398: 
 399:         hopcode(rt == FLOAT ? 'F' : 'D', p->in.op);
 400:         putstr("2\t");
 401:         adrput(r);
 402:         putchar(',');
 403:         adrput(resc);
 404:         putstr("\n\t");
 405: 
 406:         s->in.op = ASSIGN;
 407:         s->in.left = l;
 408:         s->in.right = resc;
 409:         s->in.type = l->in.type;
 410:         zzzcode(s, 'A');
 411: 
 412:         s->in.op = FREE;
 413:         return;
 414:         }
 415: 
 416:     case 'B':   /* get oreg value in temp register for left shift */
 417:         {
 418:         register NODE *r;
 419:         if (xdebug) eprint(p, 0, &val, &val);
 420:         r = p->in.right;
 421:         if( tlen(r) == sizeof(int) && r->in.type != FLOAT )
 422:             putstr("movl");
 423:         else {
 424:             putstr("cvt");
 425:             prtype(r);
 426:             putchar('l');
 427:             }
 428:         return;
 429:         }
 430: 
 431:     case 'C':   /* num words pushed on arg stack */
 432:         {
 433:         extern int gc_numbytes;
 434:         extern int xdebug;
 435: 
 436:         if (xdebug) printf("->%d<-",gc_numbytes);
 437: 
 438:         printf("$%d", gc_numbytes/(SZLONG/SZCHAR) );
 439:         return;
 440:         }
 441: 
 442:     case 'D':   /* INCR and DECR */
 443:         zzzcode(p->in.left, 'A');
 444:         putchar('\n');
 445:         putchar('\t');
 446: 
 447:     case 'E':   /* INCR and DECR, FOREFF */
 448:         if (p->in.right->tn.lval == 1)
 449:             {
 450:             putstr( p->in.op == INCR ? "inc" : "dec" );
 451:             prtype(p->in.left);
 452:             putchar('\t');
 453:             adrput(p->in.left);
 454:             return;
 455:             }
 456:         putstr( p->in.op == INCR ? "add" : "sub" );
 457:         prtype(p->in.left);
 458:         putchar('2');
 459:         putchar('\t');
 460:         adrput(p->in.right);
 461:         putchar(',');
 462:         adrput(p->in.left);
 463:         return;
 464: 
 465:     case 'F':   /* register type of right operand */
 466:         {
 467:         register NODE *n;
 468:         extern int xdebug;
 469:         register int ty;
 470: 
 471:         n = getlr( p, 'R' );
 472:         ty = n->in.type;
 473: 
 474:         if (xdebug) printf("->%d<-", ty);
 475: 
 476:         if ( ty==DOUBLE) putchar('d');
 477:         else if ( ty==FLOAT ) putchar('f');
 478:         else putchar('l');
 479:         return;
 480:         }
 481: 
 482:     case 'L':   /* type of left operand */
 483:     case 'R':   /* type of right operand */
 484:         {
 485:         register NODE *n;
 486:         extern int xdebug;
 487: 
 488:         n = getlr( p, c );
 489:         if (xdebug) printf("->%d<-", n->in.type);
 490: 
 491:         prtype(n);
 492:         return;
 493:         }
 494: 
 495:     case 'Z':   /* complement mask for bit instr */
 496:         printf("$%ld", ~p->in.right->tn.lval);
 497:         return;
 498: 
 499:     case 'U':   /* 32 - n, for unsigned right shifts */
 500:         printf("$%d", 32 - p->in.right->tn.lval );
 501:         return;
 502: 
 503:     case 'T':   /* rounded structure length for arguments */
 504:         {
 505:         int size;
 506: 
 507:         size = p->stn.stsize;
 508:         SETOFF( size, 4);
 509:         printf("$%d", size);
 510:         return;
 511:         }
 512: 
 513:     case 'S':  /* structure assignment */
 514:         {
 515:             register NODE *l, *r;
 516:             register size;
 517: 
 518:             if( p->in.op == STASG ){
 519:                 l = p->in.left;
 520:                 r = p->in.right;
 521: 
 522:                 }
 523:             else if( p->in.op == STARG ){  /* store an arg into a temporary */
 524:                 r = p->in.left;
 525:                 }
 526:             else cerror( "STASG bad" );
 527: 
 528:             if( r->in.op == ICON ) r->in.op = NAME;
 529:             else if( r->in.op == REG ) r->in.op = OREG;
 530:             else if( r->in.op != OREG ) cerror( "STASG-r" );
 531: 
 532:             size = p->stn.stsize;
 533: 
 534:             if( size <= 0 || size > 65535 )
 535:                 cerror("structure size <0=0 or >65535");
 536: 
 537:             switch(size) {
 538:                 case 1:
 539:                     putstr("	movb	");
 540:                     break;
 541:                 case 2:
 542:                     putstr("	movw	");
 543:                     break;
 544:                 case 4:
 545:                     putstr("	movl	");
 546:                     break;
 547:                 case 8:
 548:                     putstr("	movq	");
 549:                     break;
 550:                 default:
 551:                     printf("	movc3	$%d,", size);
 552:                     break;
 553:             }
 554:             adrput(r);
 555:             if( p->in.op == STASG ){
 556:                 putchar(',');
 557:                 adrput(l);
 558:                 putchar('\n');
 559:                 }
 560:             else
 561:                 putstr(",(sp)\n");
 562: 
 563:             if( r->in.op == NAME ) r->in.op = ICON;
 564:             else if( r->in.op == OREG ) r->in.op = REG;
 565: 
 566:             }
 567:         break;
 568: 
 569:     default:
 570:         cerror( "illegal zzzcode" );
 571:         }
 572:     }
 573: 
 574: /*
 575:  * collapsible(dest, src) -- if a conversion with a register destination
 576:  *	can be accomplished in one instruction, return the type of src
 577:  *	that will do the job correctly; otherwise return 0.  Note that
 578:  *	a register must always end up having type INT or UNSIGNED.
 579:  */
 580: int
 581: collapsible(dest, src)
 582: NODE *dest, *src;
 583: {
 584:     int st = src->in.type;
 585:     int dt = dest->in.type;
 586:     int newt = 0;
 587: 
 588:     /*
 589: 	 * Are there side effects of evaluating src?
 590: 	 * If the derived type will not be the same size as src,
 591: 	 * we may have to use two steps.
 592: 	 */
 593:     if (tlen(src) > tlen(dest)) {
 594:         if (tshape(src, STARREG))
 595:             return (0);
 596:         if (src->in.op == OREG && R2TEST(src->tn.rval))
 597:             return (0);
 598:         }
 599: 
 600:     /*
 601: 	 * Can we get an object of dest's type by punning src?
 602: 	 * Praises be to great Cthulhu for little-endian machines...
 603: 	 */
 604:     if (st == CHAR && dt == USHORT)
 605:         /*
 606: 		 * Special case -- we must sign-extend to 16 bits.
 607: 		 */
 608:         return (0);
 609: 
 610:     if (tlen(src) < tlen(dest))
 611:         newt = st;
 612:     else
 613:         newt = dt;
 614: 
 615:     return (newt);
 616:     }
 617: 
 618: rmove( rt, rs, t ) TWORD t; {
 619:     printf( "	%s	%s,%s\n",
 620: #ifdef FORT
 621:         !Oflag ? (t==DOUBLE ? "movq" : "movl") :
 622: #endif
 623:         (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),
 624:         rnames[rs], rnames[rt] );
 625:     }
 626: 
 627: struct respref
 628: respref[] = {
 629:     INTAREG|INTBREG,    INTAREG|INTBREG,
 630:     INAREG|INBREG,  INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
 631:     INTEMP, INTEMP,
 632:     FORARG, FORARG,
 633:     INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
 634:     0,  0 };
 635: 
 636: setregs(){ /* set up temporary registers */
 637:     fregs = 6;  /* tbl- 6 free regs on VAX (0-5) */
 638:     ;
 639:     }
 640: 
 641: rewfld( p ) NODE *p; {
 642:     return(1);
 643:     }
 644: 
 645: callreg(p) NODE *p; {
 646:     return( R0 );
 647:     }
 648: 
 649: base( p ) register NODE *p; {
 650:     register int o = p->in.op;
 651: 
 652:     if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */
 653:     if( o==REG ) return( p->tn.rval );
 654:     if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
 655:         return( p->in.left->tn.rval );
 656:     if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
 657:         return( p->tn.rval + 0200*1 );
 658:     if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 );
 659:     if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 );
 660:     if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG
 661:       && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
 662:         return( p->in.left->in.left->tn.rval + 0200*(1+2) );
 663:     return( -1 );
 664:     }
 665: 
 666: offset( p, tyl ) register NODE *p; int tyl; {
 667: 
 668:     if( tyl==1 &&
 669:         p->in.op==REG &&
 670:         (p->in.type==INT || p->in.type==UNSIGNED) )
 671:         return( p->tn.rval );
 672:     if( p->in.op==LS &&
 673:         p->in.left->in.op==REG &&
 674:         (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
 675:         p->in.right->in.op==ICON &&
 676:         p->in.right->in.name[0]=='\0' &&
 677:         (1<<p->in.right->tn.lval)==tyl)
 678:         return( p->in.left->tn.rval );
 679:     if( tyl==2 &&
 680:         p->in.op==PLUS &&
 681:         (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
 682:         p->in.left->in.op==REG &&
 683:         p->in.right->in.op==REG &&
 684:         p->in.left->tn.rval==p->in.right->tn.rval )
 685:         return( p->in.left->tn.rval );
 686:     return( -1 );
 687:     }
 688: 
 689: makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
 690:     register NODE *t;
 691:     register int i;
 692:     NODE *f;
 693: 
 694:     p->in.op = OREG;
 695:     f = p->in.left;     /* have to free this subtree later */
 696: 
 697:     /* init base */
 698:     switch (q->in.op) {
 699:         case ICON:
 700:         case REG:
 701:         case OREG:
 702:             t = q;
 703:             break;
 704: 
 705:         case MINUS:
 706:             q->in.right->tn.lval = -q->in.right->tn.lval;
 707:         case PLUS:
 708:             t = q->in.right;
 709:             break;
 710: 
 711:         case INCR:
 712:         case ASG MINUS:
 713:             t = q->in.left;
 714:             break;
 715: 
 716:         case UNARY MUL:
 717:             t = q->in.left->in.left;
 718:             break;
 719: 
 720:         default:
 721:             cerror("illegal makeor2");
 722:     }
 723: 
 724:     p->tn.lval = t->tn.lval;
 725: #ifndef FLEXNAMES
 726:     for(i=0; i<NCHNAM; ++i)
 727:         p->in.name[i] = t->in.name[i];
 728: #else
 729:     p->in.name = t->in.name;
 730: #endif
 731: 
 732:     /* init offset */
 733:     p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
 734: 
 735:     tfree(f);
 736:     return;
 737:     }
 738: 
 739: canaddr( p ) NODE *p; {
 740:     register int o = p->in.op;
 741: 
 742:     if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
 743:     return(0);
 744:     }
 745: 
 746: flshape( p ) register NODE *p; {
 747:     return( p->in.op == REG || p->in.op == NAME || p->in.op == ICON ||
 748:         (p->in.op == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) );
 749:     }
 750: 
 751: shtemp( p ) register NODE *p; {
 752:     if( p->in.op == STARG ) p = p->in.left;
 753:     return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) );
 754:     }
 755: 
 756: shumul( p ) register NODE *p; {
 757:     register o;
 758:     extern int xdebug;
 759: 
 760:     if (xdebug) {
 761:          printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op);
 762:         printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval);
 763:         }
 764: 
 765: 
 766:     o = p->in.op;
 767:     if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM );
 768: 
 769:     if( ( o == INCR || o == ASG MINUS ) &&
 770:         ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) &&
 771:         p->in.right->in.name[0] == '\0' )
 772:         {
 773:         switch (p->in.type)
 774:             {
 775:             case CHAR|PTR:
 776:             case UCHAR|PTR:
 777:                 o = 1;
 778:                 break;
 779: 
 780:             case SHORT|PTR:
 781:             case USHORT|PTR:
 782:                 o = 2;
 783:                 break;
 784: 
 785:             case INT|PTR:
 786:             case UNSIGNED|PTR:
 787:             case LONG|PTR:
 788:             case ULONG|PTR:
 789:             case FLOAT|PTR:
 790:                 o = 4;
 791:                 break;
 792: 
 793:             case DOUBLE|PTR:
 794:                 o = 8;
 795:                 break;
 796: 
 797:             default:
 798:                 if ( ISPTR(p->in.type) &&
 799:                      ISPTR(DECREF(p->in.type)) ) {
 800:                     o = 4;
 801:                     break;
 802:                     }
 803:                 else return(0);
 804:             }
 805:         return( p->in.right->tn.lval == o ? STARREG : 0);
 806:         }
 807: 
 808:     return( 0 );
 809:     }
 810: 
 811: adrcon( val ) CONSZ val; {
 812:     putchar( '$' );
 813:     printf( CONFMT, val );
 814:     }
 815: 
 816: conput( p ) register NODE *p; {
 817:     switch( p->in.op ){
 818: 
 819:     case ICON:
 820:         acon( p );
 821:         return;
 822: 
 823:     case REG:
 824:         putstr( rnames[p->tn.rval] );
 825:         return;
 826: 
 827:     default:
 828:         cerror( "illegal conput" );
 829:         }
 830:     }
 831: 
 832: insput( p ) register NODE *p; {
 833:     cerror( "insput" );
 834:     }
 835: 
 836: upput( p ) register NODE *p; {
 837:     cerror( "upput" );
 838:     }
 839: 
 840: adrput( p ) register NODE *p; {
 841:     register int r;
 842:     /* output an address, with offsets, from p */
 843: 
 844:     if( p->in.op == FLD ){
 845:         p = p->in.left;
 846:         }
 847:     switch( p->in.op ){
 848: 
 849:     case NAME:
 850:         acon( p );
 851:         return;
 852: 
 853:     case ICON:
 854:         /* addressable value of the constant */
 855:         putchar( '$' );
 856:         acon( p );
 857:         return;
 858: 
 859:     case REG:
 860:         putstr( rnames[p->tn.rval] );
 861:         return;
 862: 
 863:     case OREG:
 864:         r = p->tn.rval;
 865:         if( R2TEST(r) ){ /* double indexing */
 866:             register int flags;
 867: 
 868:             flags = R2UPK3(r);
 869:             if( flags & 1 ) putchar('*');
 870:             if( flags & 4 ) putchar('-');
 871:             if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
 872:             if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
 873:             if( flags & 2 ) putchar('+');
 874:             printf( "[%s]", rnames[R2UPK2(r)] );
 875:             return;
 876:             }
 877:         if( r == AP ){  /* in the argument region */
 878:             if( p->tn.lval <= 0 || p->in.name[0] != '\0' ) werror( "bad arg temp" );
 879:             printf( CONFMT, p->tn.lval );
 880:             putstr( "(ap)" );
 881:             return;
 882:             }
 883:         if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
 884:         printf( "(%s)", rnames[p->tn.rval] );
 885:         return;
 886: 
 887:     case UNARY MUL:
 888:         /* STARNM or STARREG found */
 889:         if( tshape(p, STARNM) ) {
 890:             putchar( '*' );
 891:             adrput( p->in.left);
 892:             }
 893:         else {  /* STARREG - really auto inc or dec */
 894:             register NODE *q;
 895: 
 896: /* tbl
 897: 			p = p->in.left;
 898: 			p->in.left->in.op = OREG;
 899: 			if( p->in.op == INCR ) {
 900: 				adrput( p->in.left );
 901: 				putchar( '+' );
 902: 				}
 903: 			else {
 904: 				putchar( '-' );
 905: 				adrput( p->in.left );
 906: 				}
 907:    tbl */
 908:             q = p->in.left;
 909:             if( q->in.right->tn.lval != tlen(p) )
 910:                 cerror("adrput: bad auto-increment/decrement");
 911:             printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"),
 912:                 rnames[q->in.left->tn.rval],
 913:                 (q->in.op==INCR ? "+" : "") );
 914:             p->in.op = OREG;
 915:             p->tn.rval = q->in.left->tn.rval;
 916:             p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0);
 917: #ifndef FLEXNAMES
 918:             p->in.name[0] = '\0';
 919: #else
 920:             p->in.name = "";
 921: #endif
 922:             tfree(q);
 923:         }
 924:         return;
 925: 
 926:     default:
 927:         cerror( "illegal address" );
 928:         return;
 929: 
 930:         }
 931: 
 932:     }
 933: 
 934: acon( p ) register NODE *p; { /* print out a constant */
 935: 
 936:     if( p->in.name[0] == '\0' ){
 937:         printf( CONFMT, p->tn.lval);
 938:         }
 939:     else if( p->tn.lval == 0 ) {
 940: #ifndef FLEXNAMES
 941:         printf( "%.8s", p->in.name );
 942: #else
 943:         putstr( p->in.name );
 944: #endif
 945:         }
 946:     else {
 947: #ifndef FLEXNAMES
 948:         printf( "%.8s+", p->in.name );
 949: #else
 950:         printf( "%s+", p->in.name );
 951: #endif
 952:         printf( CONFMT, p->tn.lval );
 953:         }
 954:     }
 955: 
 956: /*
 957: aacon( p ) register NODE *p; { /* print out a constant */
 958: /*
 959: 
 960: 	if( p->in.name[0] == '\0' ){
 961: 		printf( CONFMT, p->tn.lval);
 962: 		return( 0 );
 963: 		}
 964: 	else if( p->tn.lval == 0 ) {
 965: #ifndef FLEXNAMES
 966: 		printf( "$%.8s", p->in.name );
 967: #else
 968: 		printf( "$%s", p->in.name );
 969: #endif
 970: 		return( 1 );
 971: 		}
 972: 	else {
 973: 		printf( "$(" );
 974: 		printf( CONFMT, p->tn.lval );
 975: 		printf( "+" );
 976: #ifndef FLEXNAMES
 977: 		printf( "%.8s)", p->in.name );
 978: #else
 979: 		printf( "%s)", p->in.name );
 980: #endif
 981: 		return(1);
 982: 		}
 983: 	}
 984:  */
 985: 
 986: genscall( p, cookie ) register NODE *p; {
 987:     /* structure valued call */
 988:     return( gencall( p, cookie ) );
 989:     }
 990: 
 991: /* tbl */
 992: int gc_numbytes;
 993: /* tbl */
 994: 
 995: gencall( p, cookie ) register NODE *p; {
 996:     /* generate the call given by p */
 997:     register NODE *p1;
 998:     register temp, temp1;
 999:     register m;
1000: 
1001:     if( p->in.right ) temp = argsize( p->in.right );
1002:     else temp = 0;
1003: 
1004:     if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
1005:         /* set aside room for structure return */
1006: 
1007:         if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
1008:         else temp1 = temp;
1009:         }
1010: 
1011:     if( temp > maxargs ) maxargs = temp;
1012:     SETOFF(temp1,4);
1013: 
1014:     if( p->in.right ){ /* make temp node, put offset in, and generate args */
1015:         genargs( p->in.right );
1016:         }
1017: 
1018:     p1 = p->in.left;
1019:     if( p1->in.op != ICON ){
1020:         if( p1->in.op != REG ){
1021:             if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
1022:                 if( p1->in.op != NAME ){
1023:                     order( p1, INAREG );
1024:                     }
1025:                 }
1026:             }
1027:         }
1028: 
1029: /*
1030: 	if( p1->in.op == REG && p->tn.rval == R5 ){
1031: 		cerror( "call register overwrite" );
1032: 		}
1033:  */
1034: /* tbl
1035: 	setup gc_numbytes so reference to ZC works */
1036: 
1037:     gc_numbytes = temp&(0x3ff);
1038: /* tbl */
1039: 
1040:     p->in.op = UNARY CALL;
1041:     m = match( p, INTAREG|INTBREG );
1042: 
1043:     /* compensate for deficiency in 'ret' instruction ... wah,kre */
1044:     /* (plus in assignment to gc_numbytes above, for neatness only) */
1045:     if (temp >= 1024)
1046:         printf("	addl2	$%d,sp\n", (temp&(~0x3ff)));
1047: 
1048: /* tbl
1049: 	switch( temp ) {
1050: 	case 0:
1051: 		break;
1052: 	case 2:
1053: 		printf( "	tst	(sp)+\n" );
1054: 		break;
1055: 	case 4:
1056: 		printf( "	cmp	(sp)+,(sp)+\n" );
1057: 		break;
1058: 	default:
1059: 		printf( "	add	$%d,sp\n", temp);
1060: 		}
1061:    tbl */
1062:     return(m != MDONE);
1063:     }
1064: 
1065: /* tbl */
1066: char *
1067: ccbranches[] = {
1068:     "	jeql	L%d\n",
1069:     "	jneq	L%d\n",
1070:     "	jleq	L%d\n",
1071:     "	jlss	L%d\n",
1072:     "	jgeq	L%d\n",
1073:     "	jgtr	L%d\n",
1074:     "	jlequ	L%d\n",
1075:     "	jlssu	L%d\n",
1076:     "	jgequ	L%d\n",
1077:     "	jgtru	L%d\n",
1078:     };
1079: /* tbl */
1080: 
1081: cbgen( o, lab, mode ) { /*   printf conditional and unconditional branches */
1082: 
1083: /* tbl */
1084:     if( o == 0 ) printf( "	jbr	L%d\n", lab );
1085: /* tbl */
1086:     else {
1087:         if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] );
1088:         printf( ccbranches[o-EQ], lab );
1089:         }
1090:     }
1091: 
1092: nextcook( p, cookie ) NODE *p; {
1093:     /* we have failed to match p with cookie; try another */
1094:     if( cookie == FORREW ) return( 0 );  /* hopeless! */
1095:     if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
1096:     if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
1097:     return( FORREW );
1098:     }
1099: 
1100: lastchance( p, cook ) NODE *p; {
1101:     /* forget it! */
1102:     return(0);
1103:     }
1104: 
1105: optim2( p ) register NODE *p; {
1106:     /* do local tree transformations and optimizations */
1107: 
1108:     register NODE *l, *r;
1109:     int m, ml;
1110: 
1111:     switch( p->in.op ) {
1112: 
1113:     case AND:
1114:         /* commute L and R to eliminate complements and constants */
1115:         if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 ||
1116:             l->in.op == COMPL ) {
1117:             p->in.left = p->in.right;
1118:             p->in.right = l;
1119:             }
1120:     case ASG AND:
1121:         /* change meaning of AND to ~R&L - bic on pdp11 */
1122:         r = p->in.right;
1123:         if( r->in.op==ICON && r->in.name[0]==0 ) { /* complement constant */
1124:             r->tn.lval = ~r->tn.lval;
1125:             }
1126:         else if( r->in.op==COMPL ) { /* ~~A => A */
1127:             r->in.op = FREE;
1128:             p->in.right = r->in.left;
1129:             }
1130:         else { /* insert complement node */
1131:             p->in.right = l = talloc();
1132:             l->in.op = COMPL;
1133:             l->in.rall = NOPREF;
1134:             l->in.type = r->in.type;
1135:             l->in.left = r;
1136:             l->in.right = NULL;
1137:             }
1138:         break;
1139: 
1140:     case SCONV:
1141:         l = p->in.left;
1142: #if defined(FORT) || defined(SPRECC)
1143:         if( p->in.type == FLOAT || p->in.type == DOUBLE ||
1144:             l->in.type == FLOAT || l->in.type == DOUBLE )
1145:             return;
1146: #else
1147:         if( mixtypes(p, l) ) return;
1148: #endif
1149:         if( l->in.op == PCONV )
1150:             return;
1151: 
1152:         /* Only trust it to get it right if the size is the same */
1153:         if( tlen(p) != tlen(l) )
1154:             return;
1155: 
1156:         /* clobber conversion */
1157:         if( l->in.op != FLD )
1158:             l->in.type = p->in.type;
1159:         ncopy( p, l );
1160:         l->in.op = FREE;
1161: 
1162:         break;
1163: 
1164:     case ASSIGN:
1165:         /*
1166: 		 * Conversions are equivalent to assignments;
1167: 		 * when the two operations are combined,
1168: 		 * we can sometimes zap the conversion.
1169: 		 */
1170:         r = p->in.right;
1171:         l = p->in.left;
1172:         if ( r->in.op == SCONV &&
1173:              !mixtypes(l, r) &&
1174:              tlen(l) == tlen(r) ) {
1175:                 p->in.right = r->in.left;
1176:                 r->in.op = FREE;
1177:             }
1178:         break;
1179: 
1180:         }
1181:     }
1182: 
1183: NODE * addroreg(l) NODE *l;
1184:                 /* OREG was built in clocal()
1185: 				 * for an auto or formal parameter
1186: 				 * now its address is being taken
1187: 				 * local code must unwind it
1188: 				 * back to PLUS/MINUS REG ICON
1189: 				 * according to local conventions
1190: 				 */
1191: {
1192:     cerror("address of OREG taken");
1193:     /*NOTREACHED*/
1194: }
1195: 
1196: 
1197: 
1198: # ifndef ONEPASS
1199: main( argc, argv ) char *argv[]; {
1200:     return( mainp2( argc, argv ) );
1201:     }
1202: # endif
1203: 
1204: 
1205: /* added by jwf */
1206: struct functbl {
1207:     int fop;
1208:     TWORD ftype;
1209:     char *func;
1210:     } opfunc[] = {
1211:     DIV,        TANY,   "udiv",
1212:     MOD,        TANY,   "urem",
1213:     ASG DIV,    TANY,   "audiv",
1214:     ASG MOD,    TANY,   "aurem",
1215:     0,  0,  0 };
1216: 
1217: hardops(p)  register NODE *p; {
1218:     /* change hard to do operators into function calls.  */
1219:     register NODE *q;
1220:     register struct functbl *f;
1221:     register o;
1222:     NODE *old,*temp;
1223: 
1224:     o = p->in.op;
1225:     if( ! (optype(o)==BITYPE &&
1226:            (ISUNSIGNED(p->in.left->in.type) ||
1227:         ISUNSIGNED(p->in.right->in.type))) )
1228:         return;
1229: 
1230:     for( f=opfunc; f->fop; f++ ) {
1231:         if( o==f->fop ) goto convert;
1232:         }
1233:     return;
1234: 
1235:     convert:
1236:     if( asgop( o ) ) {
1237:         old = NIL;
1238:         switch( p->in.left->in.op ){
1239:         case FLD:
1240:             q = p->in.left->in.left;
1241:             /*
1242: 			 * rewrite (lval.fld /= rval); as
1243: 			 *  ((*temp).fld = udiv((*(temp = &lval)).fld,rval));
1244: 			 * else the compiler will evaluate lval twice.
1245: 			 */
1246:             if( q->in.op == UNARY MUL ){
1247:                 /* first allocate a temp storage */
1248:                 temp = talloc();
1249:                 temp->in.op = OREG;
1250:                 temp->tn.rval = TMPREG;
1251:                 temp->tn.lval = BITOOR(freetemp(1));
1252:                 temp->in.type = INCREF(p->in.type);
1253: #ifdef FLEXNAMES
1254:                 temp->in.name = "";
1255: #else
1256:                 temp->in.name[0] = '\0';
1257: #endif
1258:                 old = q->in.left;
1259:                 q->in.left = temp;
1260:             }
1261:             /* fall thru ... */
1262: 
1263:         case REG:
1264:         case NAME:
1265:         case OREG:
1266:             /* change ASG OP to a simple OP */
1267:             q = talloc();
1268:             q->in.op = NOASG p->in.op;
1269:             q->in.rall = NOPREF;
1270:             q->in.type = p->in.type;
1271:             q->in.left = tcopy(p->in.left);
1272:             q->in.right = p->in.right;
1273:             p->in.op = ASSIGN;
1274:             p->in.right = q;
1275:             p = q;
1276:             f -= 2; /* Note: this depends on the table order */
1277:             /* on the right side only - replace *temp with
1278: 			 *(temp = &lval), build the assignment node */
1279:             if( old ){
1280:                 temp = q->in.left->in.left; /* the "*" node */
1281:                 q = talloc();
1282:                 q->in.op = ASSIGN;
1283:                 q->in.left = temp->in.left;
1284:                 q->in.right = old;
1285:                 q->in.type = old->in.type;
1286: #ifdef FLEXNAMES
1287:                 q->in.name = "";
1288: #else
1289:                 q->in.name[0] = '\0';
1290: #endif
1291:                 temp->in.left = q;
1292:             }
1293:             break;
1294: 
1295:         case UNARY MUL:
1296:             /* avoid doing side effects twice */
1297:             q = p->in.left;
1298:             p->in.left = q->in.left;
1299:             q->in.op = FREE;
1300:             break;
1301: 
1302:         default:
1303:             cerror( "hardops: can't compute & LHS" );
1304:             }
1305:         }
1306: 
1307:     /* build comma op for args to function */
1308:     q = talloc();
1309:     q->in.op = CM;
1310:     q->in.rall = NOPREF;
1311:     q->in.type = INT;
1312:     q->in.left = p->in.left;
1313:     q->in.right = p->in.right;
1314:     p->in.op = CALL;
1315:     p->in.right = q;
1316: 
1317:     /* put function name in left node of call */
1318:     p->in.left = q = talloc();
1319:     q->in.op = ICON;
1320:     q->in.rall = NOPREF;
1321:     q->in.type = INCREF( FTN + p->in.type );
1322: #ifndef FLEXNAMES
1323:     strcpy( q->in.name, f->func );
1324: #else
1325:     q->in.name = f->func;
1326: #endif
1327:     q->tn.lval = 0;
1328:     q->tn.rval = 0;
1329: 
1330:     }
1331: 
1332: zappost(p) NODE *p; {
1333:     /* look for ++ and -- operators and remove them */
1334: 
1335:     register o, ty;
1336:     register NODE *q;
1337:     o = p->in.op;
1338:     ty = optype( o );
1339: 
1340:     switch( o ){
1341: 
1342:     case INCR:
1343:     case DECR:
1344:             q = p->in.left;
1345:             p->in.right->in.op = FREE;  /* zap constant */
1346:             ncopy( p, q );
1347:             q->in.op = FREE;
1348:             return;
1349: 
1350:         }
1351: 
1352:     if( ty == BITYPE ) zappost( p->in.right );
1353:     if( ty != LTYPE ) zappost( p->in.left );
1354: }
1355: 
1356: fixpre(p) NODE *p; {
1357: 
1358:     register o, ty;
1359:     o = p->in.op;
1360:     ty = optype( o );
1361: 
1362:     switch( o ){
1363: 
1364:     case ASG PLUS:
1365:             p->in.op = PLUS;
1366:             break;
1367:     case ASG MINUS:
1368:             p->in.op = MINUS;
1369:             break;
1370:         }
1371: 
1372:     if( ty == BITYPE ) fixpre( p->in.right );
1373:     if( ty != LTYPE ) fixpre( p->in.left );
1374: }
1375: 
1376: strip(p) register NODE *p; {
1377:     NODE *q;
1378: 
1379:     /* strip nodes off the top when no side effects occur */
1380:     for( ; ; ) {
1381:         switch( p->in.op ) {
1382:         case SCONV:         /* remove lint tidbits */
1383:             q = p->in.left;
1384:             ncopy( p, q );
1385:             q->in.op = FREE;
1386:             break;
1387:         /* could probably add a few more here */
1388:         default:
1389:             return;
1390:             }
1391:         }
1392:     }
1393: 
1394: myreader(p) register NODE *p; {
1395:     strip( p );     /* strip off operations with no side effects */
1396:     canon( p );     /* expands r-vals for fields */
1397:     walkf( p, hardops );    /* convert ops to function calls */
1398:     walkf( p, optim2 );
1399:     /* jwf toff = 0;  /* stack offset swindle */
1400:     }

Defined functions

acon defined in line 934; used 6 times
addroreg defined in line 1183; never used
adrcon defined in line 811; never used
adrput defined in line 840; used 22 times
base defined in line 649; never used
callreg defined in line 645; never used
canaddr defined in line 739; used 4 times
cbgen defined in line 1081; used 2 times
collapsible defined in line 580; used 1 times
conput defined in line 816; never used
eobl2 defined in line 26; never used
fixpre defined in line 1356; used 2 times
flshape defined in line 746; never used
gencall defined in line 995; used 2 times
genscall defined in line 986; never used
hardops defined in line 1217; used 1 times
hopcode defined in line 75; used 1 times
insput defined in line 832; never used
lastchance defined in line 1100; never used
lineid defined in line 20; never used
main defined in line 1199; never used
makeor2 defined in line 689; never used
mixtypes defined in line 142; used 5 times
myreader defined in line 1394; used 1 times
nextcook defined in line 1092; never used
offset defined in line 666; never used
optim2 defined in line 1105; used 2 times
prtype defined in line 153; used 17 times
rewfld defined in line 641; never used
rmove defined in line 618; never used
setregs defined in line 636; never used
shtemp defined in line 751; never used
shumul defined in line 756; used 3 times
strip defined in line 1376; used 1 times
tlen defined in line 123; used 17 times
upput defined in line 836; never used
where defined in line 16; never used
zappost defined in line 1332; used 2 times
zzzcode defined in line 191; used 3 times

Defined variables

ccbranches defined in line 1067; used 1 times
ftlab1 defined in line 8; used 2 times
ftlab2 defined in line 8; used 2 times
gc_numbytes defined in line 992; used 4 times
ioptab defined in line 57; used 1 times
  • in line 80
opfunc defined in line 1210; used 1 times
respref defined in line 628; never used
rnames defined in line 106; used 9 times
rstatus defined in line 115; never used
sccsid defined in line 2; never used

Defined struct's

functbl defined in line 1206; used 2 times
hoptab defined in line 57; used 2 times
  • in line 78(2)

Defined macros

BITMASK defined in line 14; never used
putstr defined in line 12; used 31 times
Last modified: 1986-04-23
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2273
Valid CSS Valid XHTML 1.0 Strict