# 2.11BSD#431 - /usr/src/lib/mip/reader.c

##### Functions

    canon             X
    cbranch           X
    codgen            X
    constore          X
    delay             X
    delay1            X
    delay2            X
    eprint            X
    eread             X
    ffld              X
    mainp2            X
    markcall          X
    order             X
    oreg2             X
    p2bbeg            X
    p2bend            X
    p2compile         X
    p2init            X
    prcook            X
    rcount            X
    rdin              X
    stoarg            X
    store             X

##### Variables

    CONSZ             X
    Oflag             X
    callflag          X
    cnames            X
    deli              X
    deltrees          X
    edebug            X
    filename          X
    fregs             X
    ftnno             X
    lflag             X
    lineno            X
    maxtreg           X
    negrel            X
    node              X
    nrecur            X
    odebug            X
    stocook           X
    stotree           X
    udebug            X
    vdebug            X
    xdebug            X

##### Macros

    NOMAIN            X

       1: #if !defined(lint) && defined(DOSCCS)
       2: static char *sccsid ="@(#)reader.c	4.4.1 (2.11BSD GTE) 1/17/94";
       3: #endif lint
       4:
       5: # include "pass2.h"
       6:
       7: /*	some storage declarations */
       8:
       9: # ifndef ONEPASS
      10: NODE node[TREESZ];
      11: char filename[100] = "";  /* the name of the file */
      12: int ftnno;  /* number of current function */
      13: int lineno;
      14: # else
      15: # define NOMAIN
      16: #endif
      17:
      18: int nrecur;
      19: int lflag;
      20: #ifdef FORT
      21: int Oflag = 0;
      22: #endif
      23: extern int Wflag;
      24: int edebug = 0;
      25: int xdebug = 0;
      26: int udebug = 0;
      27: int vdebug = 0;
      28:
      29: OFFSZ tmpoff;  /* offset for first temporary, in bits for current block */
      30: OFFSZ maxoff;  /* maximum temporary offset over all blocks in current ftn, in bits */
      31: int maxtreg;
      32:
      33: NODE *stotree;
      34: int stocook;
      35:
      36: OFFSZ baseoff = 0;
      37: OFFSZ maxtemp = 0;
      38:
      39: p2init( argc, argv ) char *argv[];{
      40:     /* set the values of the pass 2 arguments */
      41:
      42:     register int c;
      43:     register char *cp;
      44:     register files;
      45:
      46:     allo0();  /* free all regs */
      47:     files = 0;
      48:
      49:     for( c=1; c<argc; ++c ){
      50:         if( *(cp=argv[c]) == '-' ){
      51:             while( *++cp ){
      52:                 switch( *cp ){
      53:
      54:                 case 'X':  /* pass1 flags */
      55:                     while( *++cp ) { /* VOID */ }
      56:                     --cp;
      57:                     break;
      58:
      59:                 case 'l':  /* linenos */
      60:                     ++lflag;
      61:                     break;
      62:
      63:                 case 'e':  /* expressions */
      64:                     ++edebug;
      65:                     break;
      66:
      67:                 case 'o':  /* orders */
      68:                     ++odebug;
      69:                     break;
      70:
      71:                 case 'r':  /* register allocation */
      72:                     ++rdebug;
      73:                     break;
      74:
      75:                 case 'a':  /* rallo */
      76:                     ++radebug;
      77:                     break;
      78:
      79:                 case 'v':
      80:                     ++vdebug;
      81:                     break;
      82:
      83:                 case 't':  /* ttype calls */
      84:                     ++tdebug;
      85:                     break;
      86:
      87:                 case 's':  /* shapes */
      88:                     ++sdebug;
      89:                     break;
      90:
      91:                 case 'u':  /* Sethi-Ullman testing (machine dependent) */
      92:                     ++udebug;
      93:                     break;
      94:
      95:                 case 'x':  /* general machine-dependent debugging flag */
      96:                     ++xdebug;
      97:                     break;
      98:
      99:                 case 'w':
     100:                 case 'W':  /* shut up warnings */
     101:
     102:                     ++Wflag;
     103:                     break;
     104:
     105: #ifdef FORT
     106:                 case 'O':  /* optimizing */
     107:                     ++Oflag;
     108:                     break;
     109: #endif
     110:
     111:                 default:
     112:                     cerror("bad option: %c", *cp );
     113:                     }
     114:                 }
     115:             }
     116:         else files = 1;  /* assumed to be a filename */
     117:         }
     118:
     119:     mkdope();
     120:     setrew();
     121:     return( files );
     122:
     123:     }
     124:
     125: # ifndef NOMAIN
     126:
     127: OFFSZ caloff();
     128: OFFSZ offsz;
     129: mainp2( argc, argv ) char *argv[]; {
     130:     register files;
     131:     register temp;
     132:     register c;
     133:     register char *cp;
     134:     register NODE *p;
     135:
     136:     offsz = caloff();
     137:     files = p2init( argc, argv );
     138:     tinit();
     139:
     140:     reread:
     141:
     142:     if( files ){
     143:         while( files < argc && argv[files][0] == '-' ) {
     144:             ++files;
     145:             }
     146:         if( files > argc ) return( nerrors );
     147:         freopen( argv[files], "r", stdin );
     148:         }
     149:     while( (c=getchar()) > 0 ) switch( c ){
     150:     case ')':
     151:         /* copy line unchanged */
     152:         if ( c != ')' )
     153:             PUTCHAR( c );  /*  initial tab  */
     154:         while( (c=getchar()) > 0 ){
     155:             PUTCHAR(c);
     156:             if( c == '\n' ) break;
     157:             }
     158:         continue;
     159:
     160:     case BBEG:
     161:         /* beginning of a block */
     162:         temp = rdin(10);  /* ftnno */
     163:         tmpoff = baseoff = rdin(10); /* autooff for block gives max offset of autos in block */
     164:         maxtreg = rdin(10);
     165:         if( getchar() != '\n' ) cerror("intermediate file format error");
     166:
     167:         if( temp != ftnno ){ /* beginning of function */
     168:             maxoff = baseoff;
     169:             ftnno = temp;
     170:             maxtemp = 0;
     171:             }
     172:         else {
     173:             if( baseoff > maxoff ) maxoff = baseoff;
     174:             /* maxoff at end of ftn is max of autos and temps
     175: 			   over all blocks in the function */
     176:             }
     177:         setregs();
     178:         continue;
     179:
     180:     case BEND:  /* end of block */
     181:         SETOFF( maxoff, ALSTACK );
     182:         eobl2();
     183:         while( (c=getchar()) != '\n' ){
     184:             if( c <= 0 ) cerror("intermediate file format eof" );
     185:             }
     186:         continue;
     187:
     188:     case EXPR:
     189:         /* compile code for an expression */
     190:         lineno = rdin( 10 );
     191:         for( cp=filename; (*cp=getchar()) != '\n'; ++cp ) ; /* VOID, reads filename */
     192:         *cp = '\0';
     193:         if( lflag ) lineid( lineno, filename );
     194:
     195:         tmpoff = baseoff;  /* expression at top level reuses temps */
     196:         p = eread();
     197:
     198: # ifndef BUG4
     199:         if( edebug ) fwalk( p, eprint, 0 );
     200: # endif
     201:
     202: # ifdef MYREADER
     203:         MYREADER(p);  /* do your own laundering of the input */
     204: # endif
     205:
     206:         nrecur = 0;
     207:         delay( p );  /* expression statement  throws out results */
     208:         reclaim( p, RNULL, 0 );
     209:
     210:         allchk();
     211:         tcheck();
     212:         continue;
     213:
     214:     default:
     215:         cerror("intermediate file format error" );
     216:
     217:         }
     218:
     219:     /* EOF */
     220:     if( files ) goto reread;
     221:     return(nerrors);
     222:
     223:     }
     224:
     225: # endif
     226:
     227: # ifdef ONEPASS
     228:
     229: p2compile( p ) NODE *p; {
     230:
     231:     if( lflag ) lineid( lineno, filename );
     232:     tmpoff = baseoff;  /* expression at top level reuses temps */
     233:     /* generate code for the tree p */
     234: # ifndef BUG4
     235:     if( edebug ) fwalk( p, eprint, 0 );
     236: # endif
     237:
     238: # ifdef MYREADER
     239:     MYREADER(p);  /* do your own laundering of the input */
     240: # endif
     241:     nrecur = 0;
     242:     delay( p );  /* do the code generation */
     243:     reclaim( p, RNULL, 0 );
     244:     allchk();
     245:     /* can't do tcheck here; some stuff (e.g., attributes) may be around from first pass */
     246:     /* first pass will do it... */
     247:     }
     248:
     249: p2bbeg( aoff, myreg ) {
     250:     static int myftn = -1;
     251:
     252:     tmpoff = baseoff = (unsigned int) aoff;
     253:     maxtreg = myreg;
     254:     if( myftn != ftnno ){ /* beginning of function */
     255:         maxoff = baseoff;
     256:         myftn = ftnno;
     257:         maxtemp = 0;
     258:         }
     259:     else {
     260:         if( baseoff > maxoff ) maxoff = baseoff;
     261:         /* maxoff at end of ftn is max of autos and temps over all blocks */
     262:         }
     263:     setregs();
     264:     }
     265:
     266: p2bend(){
     267:     SETOFF( maxoff, ALSTACK );
     268:     eobl2();
     269:     }
     270:
     271: # endif
     272:
     273: NODE *deltrees[DELAYS];
     274: int deli;
     275:
     276: delay( p ) register NODE *p; {
     277:     /* look in all legal places for COMOP's and ++ and -- ops to delay */
     278:     /* note; don't delay ++ and -- within calls or things like
     279: 	/* getchar (in their macro forms) will start behaving strangely */
     280:     register i;
     281:
     282:     /* look for visible COMOPS, and rewrite repeatedly */
     283:
     284:     while( delay1( p ) ) { /* VOID */ }
     285:
     286:     /* look for visible, delayable ++ and -- */
     287:
     288:     deli = 0;
     289:     delay2( p );
     290:     codgen( p, FOREFF );  /* do what is left */
     291:     for( i = 0; i<deli; ++i ) codgen( deltrees[i], FOREFF );  /* do the rest */
     292:     }
     293:
     294: delay1( p ) register NODE *p; {  /* look for COMOPS */
     295:     register o, ty;
     296:
     297:     o = p->in.op;
     298:     ty = optype( o );
     299:     if( ty == LTYPE ) return( 0 );
     300:     else if( ty == UTYPE ) return( delay1( p->in.left ) );
     301:
     302:     switch( o ){
     303:
     304:     case QUEST:
     305:     case ANDAND:
     306:     case OROR:
     307:         /* don't look on RHS */
     308:         return( delay1(p->in.left ) );
     309:
     310:     case COMOP:  /* the meat of the routine */
     311:         delay( p->in.left );  /* completely evaluate the LHS */
     312:         /* rewrite the COMOP */
     313:         { register NODE *q;
     314:             q = p->in.right;
     315:             ncopy( p, p->in.right );
     316:             q->in.op = FREE;
     317:             }
     318:         return( 1 );
     319:         }
     320:
     321:     return( delay1(p->in.left) || delay1(p->in.right ) );
     322:     }
     323:
     324: delay2( p ) register NODE *p; {
     325:
     326:     /* look for delayable ++ and -- operators */
     327:
     328:     register o, ty;
     329:     o = p->in.op;
     330:     ty = optype( o );
     331:
     332:     switch( o ){
     333:
     334:     case NOT:
     335:     case QUEST:
     336:     case ANDAND:
     337:     case OROR:
     338:     case CALL:
     339:     case UNARY CALL:
     340:     case STCALL:
     341:     case UNARY STCALL:
     342:     case FORTCALL:
     343:     case UNARY FORTCALL:
     344:     case COMOP:
     345:     case CBRANCH:
     346:         /* for the moment, don't delay past a conditional context, or
     347: 		/* inside of a call */
     348:         return;
     349:
     350:     case UNARY MUL:
     351:         /* if *p++, do not rewrite */
     352:         if( autoincr( p ) ) return;
     353:         break;
     354:
     355:     case INCR:
     356:     case DECR:
     357:         if( deltest( p ) ){
     358:             if( deli < DELAYS ){
     359:                 register NODE *q;
     360:                 deltrees[deli++] = tcopy(p);
     361:                 q = p->in.left;
     362:                 p->in.right->in.op = FREE;  /* zap constant */
     363:                 ncopy( p, q );
     364:                 q->in.op = FREE;
     365:                 return;
     366:                 }
     367:             }
     368:
     369:         }
     370:
     371:     if( ty == BITYPE ) delay2( p->in.right );
     372:     if( ty != LTYPE ) delay2( p->in.left );
     373:     }
     374:
     375: codgen( p, cookie ) NODE *p; {
     376:
     377:     /* generate the code for p;
     378: 	   order may call codgen recursively */
     379:     /* cookie is used to describe the context */
     380:
     381:     for(;;){
     382:         canon(p);  /* creats OREG from * if possible and does sucomp */
     383:         stotree = NIL;
     384: # ifndef BUG4
     385:         if( edebug ){
     386:             printf( "store called on:\n" );
     387:             fwalk( p, eprint, 0 );
     388:             }
     389: # endif
     390:         store(p);
     391:         if( stotree==NIL ) break;
     392:
     393:         /* because it's minimal, can do w.o. stores */
     394:
     395:         order( stotree, stocook );
     396:         }
     397:
     398:     order( p, cookie );
     399:
     400:     }
     401:
     402: # ifndef BUG4
     403: char *cnames[] = {
     404:     "SANY",
     405:     "SAREG",
     406:     "STAREG",
     407:     "SBREG",
     408:     "STBREG",
     409:     "SCC",
     410:     "SNAME",
     411:     "SCON",
     412:     "SFLD",
     413:     "SOREG",
     414: # ifdef WCARD1
     415:     "WCARD1",
     416: # else
     417:     "STARNM",
     418: # endif
     419: # ifdef WCARD2
     420:     "WCARD2",
     421: # else
     422:     "STARREG",
     423: # endif
     424:     "INTEMP",
     425:     "FORARG",
     426:     "SWADD",
     427:     0,
     428:     };
     429:
     430: prcook( cookie ){
     431:
     432:     /* print a nice-looking description of cookie */
     433:
     434:     int i, flag;
     435:
     436:     if( cookie & SPECIAL ){
     437:         if( cookie == SZERO ) printf( "SZERO" );
     438:         else if( cookie == SONE ) printf( "SONE" );
     439:         else if( cookie == SMONE ) printf( "SMONE" );
     440:         else if( cookie == SCCON ) printf( "SCCON" );
     441:         else if( cookie == SSCON ) printf( "SSCON" );
     442:         else if( cookie == SSOREG ) printf( "SSOREG" );
     443:         else printf( "SPECIAL+%d", cookie & ~SPECIAL );
     444:         return;
     445:         }
     446:
     447:     flag = 0;
     448:     for( i=0; cnames[i]; ++i ){
     449:         if( cookie & (1<<i) ){
     450:             if( flag ) printf( "|" );
     451:             ++flag;
     452:             printf( cnames[i] );
     453:             }
     454:         }
     455:
     456:     }
     457: # endif
     458:
     459: int odebug = 0;
     460:
     461: order(p,cook) NODE *p; {
     462:
     463:     register o, ty, m;
     464:     int m1;
     465:     int cookie;
     466:     NODE *p1, *p2;
     467:
     468:     cookie = cook;
     469:     rcount();
     470:     canon(p);
     471:     rallo( p, p->in.rall );
     472:     goto first;
     473:     /* by this time, p should be able to be generated without stores;
     474: 	   the only question is how */
     475:
     476:     again:
     477:
     478:     if ( p->in.op == FREE )
     479:         return;     /* whole tree was done */
     480:     cookie = cook;
     481:     rcount();
     482:     canon(p);
     483:     rallo( p, p->in.rall );
     484:     /* if any rewriting and canonicalization has put
     485: 	 * the tree (p) into a shape that cook is happy
     486: 	 * with (exclusive of FOREFF, FORREW, and INTEMP)
     487: 	 * then we are done.
     488: 	 * this allows us to call order with shapes in
     489: 	 * addition to cookies and stop short if possible.
     490: 	 */
     491:     if( tshape(p, cook &(~(FOREFF|FORREW|INTEMP))) )return;
     492:
     493:     first:
     494: # ifndef BUG4
     495:     if( odebug ){
     496:         printf( "order( %o, ", p );
     497:         prcook( cookie );
     498:         printf( " )\n" );
     499:         fwalk( p, eprint, 0 );
     500:         }
     501: # endif
     502:
     503:     o = p->in.op;
     504:     ty = optype(o);
     505:
     506:     /* first of all, for most ops, see if it is in the table */
     507:
     508:     /* look for ops */
     509:
     510:     switch( m = p->in.op ){
     511:
     512:     default:
     513:         /* look for op in table */
     514:         for(;;){
     515:             if( (m = match( p, cookie ) ) == MDONE ) goto cleanup;
     516:             else if( m == MNOPE ){
     517:                 if( !(cookie = nextcook( p, cookie ) ) ) goto nomat;
     518:                 continue;
     519:                 }
     520:             else break;
     521:             }
     522:         break;
     523:
     524:     case COMOP:
     525:     case FORCE:
     526:     case CBRANCH:
     527:     case QUEST:
     528:     case ANDAND:
     529:     case OROR:
     530:     case NOT:
     531:     case UNARY CALL:
     532:     case CALL:
     533:     case UNARY STCALL:
     534:     case STCALL:
     535:     case UNARY FORTCALL:
     536:     case FORTCALL:
     537:         /* don't even go near the table... */
     538:         ;
     539:
     540:         }
     541:     /* get here to do rewriting if no match or
     542: 	   fall through from above for hard ops */
     543:
     544:     p1 = p->in.left;
     545:     if( ty == BITYPE ) p2 = p->in.right;
     546:     else p2 = NIL;
     547:
     548: # ifndef BUG4
     549:     if( odebug ){
     550:         printf( "order( %o, ", p );
     551:         prcook( cook );
     552:         printf( " ), cookie " );
     553:         prcook( cookie );
     554:         printf( ", rewrite %s\n", opst[m] );
     555:         }
     556: # endif
     557:     switch( m ){
     558:     default:
     559:         nomat:
     560:         cerror("no table entry for op %s", opst[p->in.op] );
     561:
     562:     case COMOP:
     563:         codgen( p1, FOREFF );
     564:         p2->in.rall = p->in.rall;
     565:         codgen( p2, cookie );
     566:         ncopy( p, p2 );
     567:         p2->in.op = FREE;
     568:         goto cleanup;
     569:
     570:     case FORCE:
     571:         /* recurse, letting the work be done by rallo */
     572:         p = p->in.left;
     573:         cook = INTAREG|INTBREG;
     574:         goto again;
     575:
     576:     case CBRANCH:
     577:         o = p2->tn.lval;
     578:         cbranch( p1, -1, o );
     579:         p2->in.op = FREE;
     580:         p->in.op = FREE;
     581:         return;
     582:
     583:     case QUEST:
     584:         cbranch( p1, -1, m=getlab() );
     585:         p2->in.left->in.rall = p->in.rall;
     586:         codgen( p2->in.left, INTAREG|INTBREG );
     587:         /* force right to compute result into same reg used by left */
     588:         p2->in.right->in.rall = p2->in.left->tn.rval|MUSTDO;
     589:         reclaim( p2->in.left, RNULL, 0 );
     590:         cbgen( 0, m1 = getlab(), 'I' );
     591:         deflab( m );
     592:         codgen( p2->in.right, INTAREG|INTBREG );
     593:         deflab( m1 );
     594:         p->in.op = REG;  /* set up node describing result */
     595:         p->tn.lval = 0;
     596:         p->tn.rval = p2->in.right->tn.rval;
     597:         p->in.type = p2->in.right->in.type;
     598:         tfree( p2->in.right );
     599:         p2->in.op = FREE;
     600:         goto cleanup;
     601:
     602:     case ANDAND:
     603:     case OROR:
     604:     case NOT:  /* logical operators */
     605:         /* if here, must be a logical operator for 0-1 value */
     606:         cbranch( p, -1, m=getlab() );
     607:         p->in.op = CCODES;
     608:         p->bn.label = m;
     609:         order( p, INTAREG );
     610:         goto cleanup;
     611:
     612:     case FLD:   /* fields of funny type */
     613:         if ( p1->in.op == UNARY MUL ){
     614:             offstar( p1->in.left );
     615:             goto again;
     616:             }
     617:
     618:     case UNARY MINUS:
     619:         order( p1, INBREG|INAREG );
     620:         goto again;
     621:
     622:     case NAME:
     623:         /* all leaves end up here ... */
     624:         if( o == REG ) goto nomat;
     625:         order( p, INTAREG|INTBREG );
     626:         goto again;
     627:
     628:     case INIT:
     629:         uerror("illegal initialization" );
     630:         return;
     631:
     632:     case UNARY FORTCALL:
     633:         p->in.right = NIL;
     634:     case FORTCALL:
     635:         o = p->in.op = UNARY FORTCALL;
     636:         if( genfcall( p, cookie ) ) goto nomat;
     637:         goto cleanup;
     638:
     639:     case UNARY CALL:
     640:         p->in.right = NIL;
     641:     case CALL:
     642:         o = p->in.op = UNARY CALL;
     643:         if( gencall( p, cookie ) ) goto nomat;
     644:         goto cleanup;
     645:
     646:     case UNARY STCALL:
     647:         p->in.right = NIL;
     648:     case STCALL:
     649:         o = p->in.op = UNARY STCALL;
     650:         if( genscall( p, cookie ) ) goto nomat;
     651:         goto cleanup;
     652:
     653:         /* if arguments are passed in register, care must be taken that reclaim
     654: 		/* not throw away the register which now has the result... */
     655:
     656:     case UNARY MUL:
     657:         if( cook == FOREFF ){
     658:             /* do nothing */
     659:             order( p->in.left, FOREFF );
     660:             p->in.op = FREE;
     661:             return;
     662:             }
     663:         offstar( p->in.left );
     664:         goto again;
     665:
     666:     case INCR:  /* INCR and DECR */
     667:         if( setincr(p) ) goto again;
     668:
     669:         /* x++ becomes (x += 1) -1; */
     670:
     671:         if( cook & FOREFF ){  /* result not needed so inc or dec and be done with it */
     672:             /* x++ => x += 1 */
     673:             p->in.op = (p->in.op==INCR)?ASG PLUS:ASG MINUS;
     674:             goto again;
     675:             }
     676:
     677:         p1 = tcopy(p);
     678:         reclaim( p->in.left, RNULL, 0 );
     679:         p->in.left = p1;
     680:         p1->in.op = (p->in.op==INCR)?ASG PLUS:ASG MINUS;
     681:         p->in.op = (p->in.op==INCR)?MINUS:PLUS;
     682:         goto again;
     683:
     684:     case STASG:
     685:         if( setstr( p ) ) goto again;
     686:         goto nomat;
     687:
     688:     case ASG PLUS:  /* and other assignment ops */
     689:         if( setasop(p) ) goto again;
     690:
     691:         /* there are assumed to be no side effects in LHS */
     692:
     693:         p2 = tcopy(p);
     694:         p->in.op = ASSIGN;
     695:         reclaim( p->in.right, RNULL, 0 );
     696:         p->in.right = p2;
     697:         canon(p);
     698:         rallo( p, p->in.rall );
     699:
     700: # ifndef BUG4
     701:         if( odebug ) fwalk( p, eprint, 0 );
     702: # endif
     703:
     704:         order( p2->in.left, INTBREG|INTAREG );
     705:         order( p2, INTBREG|INTAREG );
     706:         goto again;
     707:
     708:     case ASSIGN:
     709:         if( setasg( p ) ) goto again;
     710:         goto nomat;
     711:
     712:
     713:     case BITYPE:
     714:         if( setbin( p ) ) goto again;
     715:         /* try to replace binary ops by =ops */
     716:         switch(o){
     717:
     718:         case PLUS:
     719:         case MINUS:
     720:         case MUL:
     721:         case DIV:
     722:         case MOD:
     723:         case AND:
     724:         case OR:
     725:         case ER:
     726:         case LS:
     727:         case RS:
     728:             p->in.op = ASG o;
     729:             goto again;
     730:             }
     731:         goto nomat;
     732:
     733:         }
     734:
     735:     cleanup:
     736:
     737:     /* if it is not yet in the right state, put it there */
     738:
     739:     if( cook & FOREFF ){
     740:         reclaim( p, RNULL, 0 );
     741:         return;
     742:         }
     743:
     744:     if( p->in.op==FREE ) return;
     745:
     746:     if( tshape( p, cook ) ) return;
     747:
     748:     if( (m=match(p,cook) ) == MDONE ) return;
     749:
     750:     /* we are in bad shape, try one last chance */
     751:     if( lastchance( p, cook ) ) goto again;
     752:
     753:     goto nomat;
     754:     }
     755:
     756: int callflag;
     757: int fregs;
     758:
     759: store( p ) register NODE *p; {
     760:
     761:     /* find a subtree of p which should be stored */
     762:
     763:     register o, ty;
     764:
     765:     o = p->in.op;
     766:     ty = optype(o);
     767:
     768:     if( ty == LTYPE ) return;
     769:
     770:     switch( o ){
     771:
     772:     case UNARY CALL:
     773:     case UNARY FORTCALL:
     774:     case UNARY STCALL:
     775:         ++callflag;
     776:         break;
     777:
     778:     case UNARY MUL:
     779:         if( asgop(p->in.left->in.op) ) stoasg( p->in.left, UNARY MUL );
     780:         break;
     781:
     782:     case CALL:
     783:     case FORTCALL:
     784:     case STCALL:
     785:         store( p->in.left );
     786:         stoarg( p->in.right, o );
     787:         ++callflag;
     788:         return;
     789:
     790:     case COMOP:
     791:         markcall( p->in.right );
     792:         if( p->in.right->in.su > fregs ) SETSTO( p, INTEMP );
     793:         store( p->in.left );
     794:         return;
     795:
     796:     case ANDAND:
     797:     case OROR:
     798:     case QUEST:
     799:         markcall( p->in.right );
     800:         if( p->in.right->in.su > fregs ) SETSTO( p, INTEMP );
     801:     case CBRANCH:   /* to prevent complicated expressions on the LHS from being stored */
     802:     case NOT:
     803:         constore( p->in.left );
     804:         return;
     805:
     806:         }
     807:
     808:     if( ty == UTYPE ){
     809:         store( p->in.left );
     810:         return;
     811:         }
     812:
     813:     if( asgop( p->in.right->in.op ) ) stoasg( p->in.right, o );
     814:
     815:     if( p->in.su>fregs ){ /* must store */
     816:         mkadrs( p );  /* set up stotree and stocook to subtree
     817: 				 that must be stored */
     818:         }
     819:
     820:     store( p->in.right );
     821:     store( p->in.left );
     822:     }
     823:
     824: constore( p ) register NODE *p; {
     825:
     826:     /* store conditional expressions */
     827:     /* the point is, avoid storing expressions in conditional
     828: 	   conditional context, since the evaluation order is predetermined */
     829:
     830:     switch( p->in.op ) {
     831:
     832:     case ANDAND:
     833:     case OROR:
     834:     case QUEST:
     835:         markcall( p->in.right );
     836:     case NOT:
     837:         constore( p->in.left );
     838:         return;
     839:
     840:         }
     841:
     842:     store( p );
     843:     }
     844:
     845: markcall( p ) register NODE *p; {  /* mark off calls below the current node */
     846:
     847:     again:
     848:     switch( p->in.op ){
     849:
     850:     case UNARY CALL:
     851:     case UNARY STCALL:
     852:     case UNARY FORTCALL:
     853:     case CALL:
     854:     case STCALL:
     855:     case FORTCALL:
     856:         ++callflag;
     857:         return;
     858:
     859:         }
     860:
     861:     switch( optype( p->in.op ) ){
     862:
     863:     case BITYPE:
     864:         markcall( p->in.right );
     865:     case UTYPE:
     866:         p = p->in.left;
     867:         /* eliminate recursion (aren't I clever...) */
     868:         goto again;
     869:     case LTYPE:
     870:         return;
     871:         }
     872:
     873:     }
     874:
     875: stoarg( p, calltype ) register NODE *p; {
     876:     /* arrange to store the args */
     877:
     878:     if( p->in.op == CM ){
     879:         stoarg( p->in.left, calltype );
     880:         p = p->in.right ;
     881:         }
     882:     if( calltype == CALL ){
     883:         STOARG(p);
     884:         }
     885:     else if( calltype == STCALL ){
     886:         STOSTARG(p);
     887:         }
     888:     else {
     889:         STOFARG(p);
     890:         }
     891:     callflag = 0;
     892:     store(p);
     893: # ifndef NESTCALLS
     894:     if( callflag ){ /* prevent two calls from being active at once  */
     895:         SETSTO(p,INTEMP);
     896:         store(p); /* do again to preserve bottom up nature....  */
     897:         }
     898: #endif
     899:     }
     900:
     901: int negrel[] = { NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE } ;  /* negatives of relationals */
     902:
     903: cbranch( p, true, false ) NODE *p; {
     904:     /* evaluate p for truth value, and branch to true or false
     905: 	/* accordingly: label <0 means fall through */
     906:
     907:     register o, lab, flab, tlab;
     908:
     909:     lab = -1;
     910:
     911:     switch( o=p->in.op ){
     912:
     913:     case ULE:
     914:     case ULT:
     915:     case UGE:
     916:     case UGT:
     917:     case EQ:
     918:     case NE:
     919:     case LE:
     920:     case LT:
     921:     case GE:
     922:     case GT:
     923:         if( true < 0 ){
     924:             o = p->in.op = negrel[ o-EQ ];
     925:             true = false;
     926:             false = -1;
     927:             }
     928: #ifndef NOOPT
     929:         if( p->in.right->in.op == ICON && p->in.right->tn.lval == 0 && p->in.right->in.name[0] == '\0' ){
     930:             switch( o ){
     931:
     932:             case UGT:
     933:             case ULE:
     934:                 o = p->in.op = (o==UGT)?NE:EQ;
     935:             case EQ:
     936:             case NE:
     937:             case LE:
     938:             case LT:
     939:             case GE:
     940:             case GT:
     941:                 if( logop(p->in.left->in.op) ){
     942:                     /* strange situation: e.g., (a!=0) == 0 */
     943:                     /* must prevent reference to p->in.left->lable, so get 0/1 */
     944:                     /* we could optimize, but why bother */
     945:                     codgen( p->in.left, INAREG|INBREG );
     946:                     }
     947:                 codgen( p->in.left, FORCC );
     948:                 cbgen( o, true, 'I' );
     949:                 break;
     950:
     951:             case UGE:
     952:                 codgen(p->in.left, FORCC);
     953:                 cbgen( 0, true, 'I' );  /* unconditional branch */
     954:                 break;
     955:             case ULT:
     956:                 codgen(p->in.left, FORCC);
     957:                 }
     958:             }
     959:         else
     960: #endif
     961:             {
     962:             p->bn.label = true;
     963:             codgen( p, FORCC );
     964:             }
     965:         if( false>=0 ) cbgen( 0, false, 'I' );
     966:         reclaim( p, RNULL, 0 );
     967:         return;
     968:
     969:     case ANDAND:
     970:         lab = false<0 ? getlab() : false ;
     971:         cbranch( p->in.left, -1, lab );
     972:         cbranch( p->in.right, true, false );
     973:         if( false < 0 ) deflab( lab );
     974:         p->in.op = FREE;
     975:         return;
     976:
     977:     case OROR:
     978:         lab = true<0 ? getlab() : true;
     979:         cbranch( p->in.left, lab, -1 );
     980:         cbranch( p->in.right, true, false );
     981:         if( true < 0 ) deflab( lab );
     982:         p->in.op = FREE;
     983:         return;
     984:
     985:     case NOT:
     986:         cbranch( p->in.left, false, true );
     987:         p->in.op = FREE;
     988:         break;
     989:
     990:     case COMOP:
     991:         codgen( p->in.left, FOREFF );
     992:         p->in.op = FREE;
     993:         cbranch( p->in.right, true, false );
     994:         return;
     995:
     996:     case QUEST:
     997:         flab = false<0 ? getlab() : false;
     998:         tlab = true<0 ? getlab() : true;
     999:         cbranch( p->in.left, -1, lab = getlab() );
    1000:         cbranch( p->in.right->in.left, tlab, flab );
    1001:         deflab( lab );
    1002:         cbranch( p->in.right->in.right, true, false );
    1003:         if( true < 0 ) deflab( tlab);
    1004:         if( false < 0 ) deflab( flab );
    1005:         p->in.right->in.op = FREE;
    1006:         p->in.op = FREE;
    1007:         return;
    1008:
    1009:     case ICON:
    1010:         if( p->in.type != FLOAT && p->in.type != DOUBLE ){
    1011:
    1012:             if( p->tn.lval || p->in.name[0] ){
    1013:                 /* addresses of C objects are never 0 */
    1014:                 if( true>=0 ) cbgen( 0, true, 'I' );
    1015:                 }
    1016:             else if( false>=0 ) cbgen( 0, false, 'I' );
    1017:             p->in.op = FREE;
    1018:             return;
    1019:             }
    1020:         /* fall through to default with other strange constants */
    1021:
    1022:     default:
    1023:         /* get condition codes */
    1024:         codgen( p, FORCC );
    1025:         if( true >= 0 ) cbgen( NE, true, 'I' );
    1026:         if( false >= 0 ) cbgen( true >= 0 ? 0 : EQ, false, 'I' );
    1027:         reclaim( p, RNULL, 0 );
    1028:         return;
    1029:
    1030:         }
    1031:
    1032:     }
    1033:
    1034: rcount(){ /* count recursions */
    1035:     if( ++nrecur > NRECUR ){
    1036:         cerror("expression causes compiler loop: try simplifying" );
    1037:         }
    1038:
    1039:     }
    1040:
    1041: # ifndef BUG4
    1042: eprint( p, down, a, b ) NODE *p; int *a, *b; {
    1043:
    1044:     *a = *b = down+1;
    1045:     while( down >= 2 ){
    1046:         printf( "\t" );
    1047:         down -= 2;
    1048:         }
    1049:     if( down-- ) printf( "    " );
    1050:
    1051:
    1052:     printf( "%o) %s", p, opst[p->in.op] );
    1053:     switch( p->in.op ) { /* special cases */
    1054:
    1055:     case REG:
    1056:         printf( " %s", rnames[p->tn.rval] );
    1057:         break;
    1058:
    1059:     case ICON:
    1060:     case NAME:
    1061:     case OREG:
    1062:         printf( " " );
    1063:         adrput( p );
    1064:         break;
    1065:
    1066:     case STCALL:
    1067:     case UNARY STCALL:
    1068:     case STARG:
    1069:     case STASG:
    1070:         printf( " size=%d", p->stn.stsize );
    1071:         printf( " align=%d", p->stn.stalign );
    1072:         break;
    1073:         }
    1074:
    1075:     printf( ", " );
    1076:     tprint( p->in.type );
    1077:     printf( ", " );
    1078:     if( p->in.rall == NOPREF ) printf( "NOPREF" );
    1079:     else {
    1080:         if( p->in.rall & MUSTDO ) printf( "MUSTDO " );
    1081:         else printf( "PREF " );
    1082:         printf( "%s", rnames[p->in.rall&~MUSTDO]);
    1083:         }
    1084:     printf( ", SU= %d\n", p->in.su );
    1085:
    1086:     }
    1087: # endif
    1088:
    1089: # ifndef NOMAIN
    1090: NODE *
    1091: eread(){
    1092:
    1093:     /* call eread recursively to get subtrees, if any */
    1094:
    1095:     register NODE *p;
    1096:     register i, c;
    1097:     register char *pc;
    1098:     register j;
    1099:
    1100:     i = rdin( 10 );
    1101:
    1102:     p = talloc();
    1103:
    1104:     p->in.op = i;
    1105:
    1106:     i = optype(i);
    1107:
    1108:     if( i == LTYPE ) p->tn.lval = rdin( 10 );
    1109:     if( i != BITYPE ) p->tn.rval = rdin( 10 );
    1110:
    1111:     p->in.type = rdin(8 );
    1112:     p->in.rall = NOPREF;  /* register allocation information */
    1113:
    1114:     if( p->in.op == STASG || p->in.op == STARG || p->in.op == STCALL || p->in.op == UNARY STCALL ){
    1115:         p->stn.stsize = (rdin( 10 ) + (SZCHAR-1) )/SZCHAR;
    1116:         p->stn.stalign = rdin(10) / SZCHAR;
    1117:         if( getchar() != '\n' ) cerror("illegal \n" );
    1118:         }
    1119:     else {   /* usual case */
    1120:         if( p->in.op == REG ) rbusy( p->tn.rval, p->in.type );  /* non usually, but sometimes justified */
    1121: #ifndef FLEXNAMES
    1122:         for( pc=p->in.name,j=0; ( c = getchar() ) != '\n'; ++j ){
    1123:             if( j < NCHNAM ) *pc++ = c;
    1124:             }
    1125:         if( j < NCHNAM ) *pc = '\0';
    1126: #else
    1127:         { char buf[BUFSIZ];
    1128:         for( pc=buf,j=0; ( c = getchar() ) != '\n'; ++j ){
    1129:             if( j < BUFSIZ ) *pc++ = c;
    1130:             }
    1131:         if( j < BUFSIZ ) *pc = '\0';
    1132:         p->in.name = tstr(buf);
    1133:         }
    1134: #endif
    1135:         }
    1136:
    1137:     /* now, recursively read descendents, if any */
    1138:
    1139:     if( i != LTYPE ) p->in.left = eread();
    1140:     if( i == BITYPE ) p->in.right = eread();
    1141:
    1142:     return( p );
    1143:
    1144:     }
    1145:
    1146: CONSZ
    1147: rdin( base ){
    1148:     register sign, c;
    1149:     CONSZ val;
    1150:
    1151:     sign = 1;
    1152:     val = 0;
    1153:
    1154:     while( (c=getchar()) > 0 ) {
    1155:         if( c == '-' ){
    1156:             if( val != 0 ) cerror("illegal -");
    1157:             sign = -sign;
    1158:             continue;
    1159:             }
    1160:         if( c == '\t' ) break;
    1161:         if( c>='0' && c<='9' ) {
    1162:             val *= base;
    1163:             if( sign > 0 )
    1164:                 val += c-'0';
    1165:             else
    1166:                 val -= c-'0';
    1167:             continue;
    1168:             }
    1169:         cerror("illegal character `%c' on intermediate file", c );
    1170:         break;
    1171:         }
    1172:
    1173:     if( c <= 0 ) {
    1174:         cerror("unexpected EOF");
    1175:         }
    1176:     return( val );
    1177:     }
    1178: # endif
    1179:
    1180: #ifndef FIELDOPS
    1181:     /* do this if there is no special hardware support for fields */
    1182:
    1183: ffld( p, down, down1, down2 ) NODE *p; int *down1, *down2; {
    1184:      /* look for fields that are not in an lvalue context, and rewrite them... */
    1185:     register NODE *shp;
    1186:     register s, o, v, ty;
    1187:
    1188:     *down1 =  asgop( p->in.op );
    1189:     *down2 = 0;
    1190:
    1191:     if( !down && p->in.op == FLD ){ /* rewrite the node */
    1192:
    1193:         if( !rewfld(p) ) return;
    1194:
    1195:         ty = (szty(p->in.type) == 2)? LONG: INT;
    1196:         v = p->tn.rval;
    1197:         s = UPKFSZ(v);
    1198: # ifdef RTOLBYTES
    1199:         o = UPKFOFF(v);  /* amount to shift */
    1200: # else
    1201:         o = szty(p->in.type)*SZINT - s - UPKFOFF(v);  /* amount to shift */
    1202: #endif
    1203:
    1204:         /* make & mask part */
    1205:
    1206:         p->in.left->in.type = ty;
    1207:
    1208:         p->in.op = AND;
    1209:         p->in.right = talloc();
    1210:         p->in.right->in.op = ICON;
    1211:         p->in.right->in.rall = NOPREF;
    1212:         p->in.right->in.type = ty;
    1213:         p->in.right->tn.lval = 1;
    1214:         p->in.right->tn.rval = 0;
    1215: #ifndef FLEXNAMES
    1216:         p->in.right->in.name[0] = '\0';
    1217: #else
    1218:         p->in.right->in.name = "";
    1219: #endif
    1220:         p->in.right->tn.lval <<= s;
    1221:         p->in.right->tn.lval--;
    1222:
    1223:         /* now, if a shift is needed, do it */
    1224:
    1225:         if( o != 0 ){
    1226:             shp = talloc();
    1227:             shp->in.op = RS;
    1228:             shp->in.rall = NOPREF;
    1229:             shp->in.type = ty;
    1230:             shp->in.left = p->in.left;
    1231:             shp->in.right = talloc();
    1232:             shp->in.right->in.op = ICON;
    1233:             shp->in.right->in.rall = NOPREF;
    1234:             shp->in.right->in.type = ty;
    1235:             shp->in.right->tn.rval = 0;
    1236:             shp->in.right->tn.lval = o;  /* amount to shift */
    1237: #ifndef FLEXNAMES
    1238:             shp->in.right->in.name[0] = '\0';
    1239: #else
    1240:             shp->in.right->in.name = "";
    1241: #endif
    1242:             p->in.left = shp;
    1243:             /* whew! */
    1244:             }
    1245:         }
    1246:     }
    1247: #endif
    1248:
    1249: oreg2( p ) register NODE *p; {
    1250:
    1251:     /* look for situations where we can turn * into OREG */
    1252:
    1253:     NODE *q;
    1254:     register i;
    1255:     register r;
    1256:     register char *cp;
    1257:     register NODE *ql, *qr;
    1258:     CONSZ temp;
    1259:
    1260:     if( p->in.op == UNARY MUL ){
    1261:         q = p->in.left;
    1262:         if( q->in.op == REG ){
    1263:             temp = q->tn.lval;
    1264:             r = q->tn.rval;
    1265:             cp = q->in.name;
    1266:             goto ormake;
    1267:             }
    1268:
    1269:         if( q->in.op != PLUS && q->in.op != MINUS ) return;
    1270:         ql = q->in.left;
    1271:         qr = q->in.right;
    1272:
    1273: #ifdef R2REGS
    1274:
    1275:         /* look for doubly indexed expressions */
    1276:
    1277:         if( q->in.op == PLUS) {
    1278:             if( (r=base(ql))>=0 && (i=offset(qr, tlen(p)))>=0) {
    1279:                 makeor2(p, ql, r, i);
    1280:                 return;
    1281:             } else if( (r=base(qr))>=0 && (i=offset(ql, tlen(p)))>=0) {
    1282:                 makeor2(p, qr, r, i);
    1283:                 return;
    1284:                 }
    1285:             }
    1286:
    1287:
    1288: #endif
    1289:
    1290:         if( (q->in.op==PLUS || q->in.op==MINUS) && qr->in.op == ICON &&
    1291:                 ql->in.op==REG && szty(qr->in.type)==1) {
    1292:             temp = qr->tn.lval;
    1293:             if( q->in.op == MINUS ) temp = -temp;
    1294:             r = ql->tn.rval;
    1295:             temp += ql->tn.lval;
    1296:             cp = qr->in.name;
    1297:             if( *cp && ( q->in.op == MINUS || *ql->in.name ) ) return;
    1298:             if( !*cp ) cp = ql->in.name;
    1299:
    1300:             ormake:
    1301:             if( notoff( p->in.type, r, temp, cp ) ) return;
    1302:             p->in.op = OREG;
    1303:             p->tn.rval = r;
    1304:             p->tn.lval = temp;
    1305: #ifndef FLEXNAMES
    1306:             for( i=0; i<NCHNAM; ++i )
    1307:                 p->in.name[i] = *cp++;
    1308: #else
    1309:             p->in.name = cp;
    1310: #endif
    1311:             tfree(q);
    1312:             return;
    1313:             }
    1314:         }
    1315:
    1316:     }
    1317:
    1318: canon(p) NODE *p; {
    1319:     /* put p in canonical form */
    1320:     int oreg2(), sucomp();
    1321:
    1322: #ifndef FIELDOPS
    1323:     int ffld();
    1324:     fwalk( p, ffld, 0 ); /* look for field operators */
    1325: # endif
    1326:     walkf( p, oreg2 );  /* look for and create OREG nodes */
    1327: #ifdef MYCANON
    1328:     MYCANON(p);  /* your own canonicalization routine(s) */
    1329: #endif
    1330:     walkf( p, sucomp );  /* do the Sethi-Ullman computation */
    1331:
    1332:     }

#### Defined functions

canon defined in line 1318; used 4 times

- in line 382, 470, 482, 697

cbranch defined in line 903; used 12 times

- in line 578, 584, 606, 971-972(2), 979-980(2), 986, 993, 999-1002(3)

codgen defined in line 375; used 13 times

- in line 290-291(2), 563-565(2), 586, 592, 945-956(4), 963, 991, 1024

constore defined in line 824; used 2 times

- in line 803, 837

delay defined in line 276; used 4 times

- in line 207, 242, 311
- in /usr/src/lib/mip/fort.c line 263

delay1 defined in line 294; used 5 times

- in line 284, 300, 308, 321(2)

delay2 defined in line 324; used 3 times

- in line 289, 371-372(2)

eprint defined in line 1042; never used
eread defined in line 1090; used 4 times

- in line 196, 1139-1140(2)
- in /usr/src/lib/mip/pass2.h line 174

ffld defined in line 1183; used 2 times

- in line 1323-1324(2)

mainp2 defined in line 129; never used
markcall defined in line 845; used 4 times

- in line 791, 799, 835, 864

order defined in line 461; used 8 times

- in line 395-398(2), 609, 619, 625, 659, 704-705(2)

oreg2 defined in line 1249; used 2 times

- in line 1320, 1326

p2bbeg defined in line 249; never used
p2bend defined in line 266; never used
p2compile defined in line 229; never used
p2init defined in line 39; used 3 times

- in line 137
- in /usr/src/lib/mip/fort.c line 121
- in /usr/src/lib/mip/scan.c line 151

prcook defined in line 430; used 5 times

- in line 497, 551-553(2)
- in /usr/src/lib/mip/allo.c line 395
- in /usr/src/lib/mip/match.c line 54

rcount defined in line 1034; used 3 times

- in line 469, 481
- in /usr/src/lib/mip/match.c line 275

rdin defined in line 1146; used 11 times

- in line 162-164(3), 190, 1100, 1108-1116(5)
- in /usr/src/lib/mip/pass2.h line 178

stoarg defined in line 875; used 2 times

- in line 786, 879

store defined in line 759; used 9 times

- in line 390, 785, 793, 809, 820-821(2), 842, 892-896(2)

#### Defined variables

CONSZ defined in line 1146; used 2 times

- in line 1149, 1258

Oflag defined in line 21; used 2 times

- in line 107
- in /usr/src/lib/mip/reader.c line 107

callflag defined in line 756; used 10 times

- in line 775, 787, 856, 891-894(2)
- in /usr/src/lib/mip/reader.c line 775, 787, 856, 891-894(2)

cnames defined in line 403; used 2 times

- in line 448-452(2)

deli defined in line 274; used 8 times

- in line 288-291(2), 358-360(2)
- in /usr/src/lib/mip/reader.c line 288-291(2), 358-360(2)

deltrees defined in line 273; used 4 times

- in line 291, 360
- in /usr/src/lib/mip/reader.c line 291, 360

edebug defined in line 24; never used
filename defined in line 11; never used
fregs defined in line 757; used 6 times

- in line 792, 800, 815
- in /usr/src/lib/mip/reader.c line 792, 800, 815

ftnno defined in line 12; used 9 times

- in line 167-169(2), 254-256(2)
- in /usr/src/lib/mip/pftn.c line 460
- in /usr/src/lib/mip/reader.c line 167-169(2), 254-256(2)

lflag defined in line 19; used 6 times

- in line 60, 193, 231
- in /usr/src/lib/mip/reader.c line 60, 193, 231

lineno defined in line 13; used 19 times

- in line 190-193(2), 231
- in /usr/src/lib/mip/pftn.c line 303, 532, 560, 1857, 1871-1873(2), 1925
- in /usr/src/lib/mip/reader.c line 190-193(2), 231
- in /usr/src/lib/mip/scan.c line 156, 333, 340, 447, 693, 1023

maxtreg defined in line 31; used 4 times

- in line 164, 253
- in /usr/src/lib/mip/reader.c line 164, 253

negrel defined in line 901; used 1 times

- in line 924

node defined in line 10; used 2 times

- in /usr/src/lib/mip/pftn.c line 48(2)

nrecur defined in line 18; used 6 times

- in line 206, 241, 1035
- in /usr/src/lib/mip/reader.c line 206, 241, 1035

odebug defined in line 459; used 8 times

- in line 68, 495, 549, 701
- in /usr/src/lib/mip/reader.c line 68, 495, 549, 701

sccsid defined in line 2; never used
stocook defined in line 34; used 3 times

- in line 395
- in /usr/src/lib/mip/pass2.h line 135
- in /usr/src/lib/mip/reader.c line 395

stotree defined in line 33; used 7 times

- in line 383, 391-395(2)
- in /usr/src/lib/mip/pass2.h line 135
- in /usr/src/lib/mip/reader.c line 383, 391-395(2)

udebug defined in line 26; used 2 times

- in line 92
- in /usr/src/lib/mip/reader.c line 92

vdebug defined in line 27; used 1 times

- in line 80

xdebug defined in line 25; never used

#### Defined macros

NOMAIN defined in line 15; used 2 times

- in line 125, 1089

Last modified: 1995-01-18 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 3013 |