home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / mip / scan.c < prev    next >
Encoding:
C/C++ Source or Header  |  1979-01-17  |  18.0 KB  |  938 lines

  1. # include "mfile1"
  2. # include <ctype.h>
  3.     /* temporarily */
  4.  
  5.     /* lexical actions */
  6.  
  7. # define A_ERR 0        /* illegal character */
  8. # define A_LET 1        /* saw a letter */
  9. # define A_DIG 2        /* saw a digit */
  10. # define A_1C 3            /* return a single character */
  11. # define A_STR 4        /* string */
  12. # define A_CC 5            /* character constant */
  13. # define A_BCD 6        /* GCOS BCD constant */
  14. # define A_SL 7            /* saw a / */
  15. # define A_DOT 8        /* saw a . */
  16. # define A_PL 9        /* + */
  17. # define A_MI 10        /* - */
  18. # define A_EQ 11        /* = */
  19. # define A_NOT 12        /* ! */
  20. # define A_LT 13        /* < */
  21. # define A_GT 14        /* > */
  22. # define A_AND 16        /* & */
  23. # define A_OR 17        /* | */
  24. # define A_WS 18        /* whitespace (not \n) */
  25. # define A_NL 19        /* \n */
  26.  
  27.     /* character classes */
  28.  
  29. # define LEXLET 01
  30. # define LEXDIG 02
  31. # define LEXOCT 04
  32. # define LEXHEX 010
  33. # define LEXWS 020
  34. # define LEXDOT 040
  35.  
  36.     /* reserved word actions */
  37.  
  38. # define AR_TY 0        /* type word */
  39. # define AR_RW 1        /* simple reserved word */
  40. # define AR_CL 2        /* storage class word */
  41. # define AR_S 3        /* struct */
  42. # define AR_U 4        /* union */
  43. # define AR_E 5        /* enum */
  44. # define AR_A 6        /* asm */
  45.  
  46.     /* text buffer */
  47. # define LXTSZ 100
  48. char yytext[LXTSZ];
  49. char * lxgcp;
  50.  
  51.  
  52.     /* ARGSUSED */
  53. mainp1( argc, argv ) int argc; char *argv[]; {  /* control multiple files */
  54.  
  55.     register i;
  56.     register char *cp;
  57.     extern int idebug, bdebug, tdebug, edebug, ddebug, xdebug;
  58.  
  59.     for( i=1; i<argc; ++i ){
  60.         if( *(cp=argv[i]) == '-' && *++cp == 'X' ){
  61.             while( *++cp ){
  62.                 switch( *cp ){
  63.  
  64.                 case 'd':
  65.                     ++ddebug;
  66.                     break;
  67.                 case 'i':
  68.                     ++idebug;
  69.                     break;
  70.                 case 'b':
  71.                     ++bdebug;
  72.                     break;
  73.                 case 't':
  74.                     ++tdebug;
  75.                     break;
  76.                 case 'e':
  77.                     ++edebug;
  78.                     break;
  79.                 case 'x':
  80.                     ++xdebug;
  81.                     break;
  82.                     }
  83.                 }
  84.             }
  85.         }
  86.  
  87. # ifdef ONEPASS
  88.     p2init( argc, argv );
  89. # endif
  90.  
  91.     for( i=0; i<SYMTSZ; ++i ) stab[i].stype = TNULL;
  92.  
  93.     lxinit();
  94.     tinit();
  95.     mkdope();
  96.  
  97.     lineno = 1;
  98.  
  99.     /* dimension table initialization */
  100.  
  101.     dimtab[NULL] = 0;
  102.     dimtab[CHAR] = SZCHAR;
  103.     dimtab[INT] = SZINT;
  104.     dimtab[FLOAT] = SZFLOAT;
  105.     dimtab[DOUBLE] = SZDOUBLE;
  106.     dimtab[LONG] = SZLONG;
  107.     dimtab[SHORT] = SZSHORT;
  108.     dimtab[UCHAR] = SZCHAR;
  109.     dimtab[USHORT] = SZSHORT;
  110.     dimtab[UNSIGNED] = SZINT;
  111.     dimtab[ULONG] = SZLONG;
  112.     /* starts past any of the above */
  113.     curdim = 16;
  114.     reached = 1;
  115.  
  116.     yyparse();
  117.     yyaccpt();
  118.  
  119.     ejobcode( nerrors ? 1 : 0 );
  120.     return(nerrors?1:0);
  121.  
  122.     }
  123.  
  124. # ifdef ibm
  125.  
  126. # define CSMASK 0377
  127. # define CSSZ 256
  128.  
  129. # else
  130.  
  131. # define CSMASK 0177
  132. # define CSSZ 128
  133.  
  134. # endif
  135.  
  136. short lxmask[CSSZ+1];
  137.  
  138. lxenter( s, m ) register char *s; register short m; {
  139.     /* enter a mask into lxmask */
  140.     register c;
  141.  
  142.     while( c= *s++ ) lxmask[c+1] |= m;
  143.  
  144.     }
  145.  
  146.  
  147. # define lxget(c,m) (lxgcp=yytext,lxmore(c,m))
  148.  
  149. lxmore( c, m )  register c, m; {
  150.     register char *cp;
  151.  
  152.     *(cp = lxgcp) = c;
  153.     while( c=getchar(), lxmask[c+1]&m ){
  154.         if( cp < &yytext[LXTSZ-1] ){
  155.             *++cp = c;
  156.             }
  157.         }
  158.     ungetc(c,stdin);
  159.     *(lxgcp = cp+1) = '\0';
  160.     }
  161.  
  162. struct lxdope {
  163.     short lxch;    /* the character */
  164.     short lxact;    /* the action to be performed */
  165.     short lxtok;    /* the token number to be returned */
  166.     short lxval;    /* the value to be returned */
  167.     } lxdope[] = {
  168.  
  169.     '$',    A_ERR,    0,    0,    /* illegal characters go here... */
  170.     '_',    A_LET,    0,    0,    /* letters point here */
  171.     '0',    A_DIG,    0,    0,    /* digits point here */
  172.     ' ',    A_WS,    0,    0,    /* whitespace goes here */
  173.     '\n',    A_NL,    0,    0,
  174.     '"',    A_STR,    0,    0,    /* character string */
  175.     '\'',    A_CC,    0,    0,    /* character constant */
  176.     '`',    A_BCD,    0,    0,    /* GCOS BCD constant */
  177.     '(',    A_1C,    LP,    0,
  178.     ')',    A_1C,    RP,    0,
  179.     '{',    A_1C,    LC,    0,
  180.     '}',    A_1C,    RC,    0,
  181.     '[',    A_1C,    LB,    0,
  182.     ']',    A_1C,    RB,    0,
  183.     '*',    A_1C,    MUL,    MUL,
  184.     '?',    A_1C,    QUEST,    0,
  185.     ':',    A_1C,    COLON,    0,
  186.     '+',    A_PL,    PLUS,    PLUS,
  187.     '-',    A_MI,    MINUS,    MINUS,
  188.     '/',    A_SL,    DIVOP,    DIV,
  189.     '%',    A_1C,    DIVOP,    MOD,
  190.     '&',    A_AND,    AND,    AND,
  191.     '|',    A_OR,    OR,    OR,
  192.     '^',    A_1C,    ER,    ER,
  193.     '!',    A_NOT,    UNOP,    NOT,
  194.     '~',    A_1C,    UNOP,    COMPL,
  195.     ',',    A_1C,    CM,    CM,
  196.     ';',    A_1C,    SM,    0,
  197.     '.',    A_DOT,    STROP,    DOT,
  198.     '<',    A_LT,    RELOP,    LT,
  199.     '>',    A_GT,    RELOP,    GT,
  200.     '=',    A_EQ,    ASSIGN,    ASSIGN,
  201.     -1,    A_1C,    0,    0,
  202.     };
  203.  
  204. struct lxdope *lxcp[CSSZ+1];
  205.  
  206. lxinit(){
  207.     register struct lxdope *p;
  208.     register i;
  209.     register char *cp;
  210.     /* set up character classes */
  211.  
  212.     lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_", LEXLET );
  213.     lxenter( "0123456789", LEXDIG );
  214.     lxenter( "0123456789abcdefABCDEF", LEXHEX );
  215.     lxenter( " \t\r\b\f", LEXWS );
  216.     lxenter( "01234567", LEXOCT );
  217.     lxmask['.'+1] |= LEXDOT;
  218.  
  219.     /* make lxcp point to appropriate lxdope entry for each character */
  220.  
  221.     /* initialize error entries */
  222.  
  223.     for( i= 0; i<=CSSZ; ++i ) lxcp[i] = lxdope;
  224.  
  225.     /* make unique entries */
  226.  
  227.     for( p=lxdope; ; ++p ) {
  228.         lxcp[p->lxch+1] = p;
  229.         if( p->lxch < 0 ) break;
  230.         }
  231.  
  232.     /* handle letters, digits, and whitespace */
  233.     /* by convention, first, second, and third places */
  234.  
  235.     cp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  236.     while( *cp ) lxcp[*cp++ + 1] = &lxdope[1];
  237.     cp = "123456789";
  238.     while( *cp ) lxcp[*cp++ + 1] = &lxdope[2];
  239.     cp = "\t\b\r\f";
  240.     while( *cp ) lxcp[*cp++ + 1] = &lxdope[3];
  241.  
  242.     /* first line might have title */
  243.     lxtitle();
  244.  
  245.     }
  246.  
  247. int lxmatch;  /* character to be matched in char or string constant */
  248.  
  249. lxstr(ct){
  250.     /* match a string or character constant, up to lxmatch */
  251.  
  252.     register c;
  253.     register val;
  254.     register i;
  255.  
  256.     i=0;
  257.     while( (c=getchar()) != lxmatch ){
  258.         switch( c ) {
  259.  
  260.         case EOF:
  261.             uerror( "unexpected EOF" );
  262.             break;
  263.  
  264.         case '\n':
  265.             uerror( "newline in string or char constant" );
  266.             ++lineno;
  267.             break;
  268.  
  269.         case '\\':
  270.             switch( c = getchar() ){
  271.  
  272.             case '\n':
  273.                 ++lineno;
  274.                 continue;
  275.  
  276.             default:
  277.                 val = c;
  278.                 goto mkcc;
  279.  
  280.             case 'n':
  281.                 val = '\n';
  282.                 goto mkcc;
  283.  
  284.             case 'r':
  285.                 val = '\r';
  286.                 goto mkcc;
  287.  
  288.             case 'b':
  289.                 val = '\b';
  290.                 goto mkcc;
  291.  
  292.             case 't':
  293.                 val = '\t';
  294.                 goto mkcc;
  295.  
  296.             case 'f':
  297.                 val = '\f';
  298.                 goto mkcc;
  299.  
  300.             case '0':
  301.             case '1':
  302.             case '2':
  303.             case '3':
  304.             case '4':
  305.             case '5':
  306.             case '6':
  307.             case '7':
  308.                 val = c-'0';
  309.                 c=getchar();  /* try for 2 */
  310.                 if( lxmask[c+1] & LEXOCT ){
  311.                     val = (val<<3) | (c-'0');
  312.                     c = getchar();  /* try for 3 */
  313.                     if( lxmask[c+1] & LEXOCT ){
  314.                         val = (val<<3) | (c-'0');
  315.                         }
  316.                     else ungetc( c ,stdin);
  317.                     }
  318.                 else ungetc( c ,stdin);
  319.  
  320.                 goto mkcc1;
  321.  
  322.                 }
  323.         default:
  324.             val =c;
  325.         mkcc:
  326.             val = CCTRANS(val);
  327.         mkcc1:
  328.             if( lxmatch == '\'' ){
  329.                 val = CHARCAST(val);  /* it is, after all, a "character" constant */
  330.                 makecc( val, i );
  331.                 }
  332.             else { /* stash the byte into the string */
  333.                 if( strflg ) {
  334.                     if( ct==0 || i<ct ) putbyte( val );
  335.                     else if( i == ct ) werror( "non-null byte ignored in string initializer" );
  336.                     }
  337.                 else bycode( val, i );
  338.                 }
  339.             ++i;
  340.             continue;
  341.             }
  342.         break;
  343.         }
  344.     /* end of string or  char constant */
  345.  
  346.     if( lxmatch == '"' ){
  347.         if( strflg ){ /* end the string */
  348.             if( ct==0 || i<ct ) putbyte( 0 );  /* the null at the end */
  349.             }
  350.         else {  /* the initializer gets a null byte */
  351.             bycode( 0, i++ );
  352.             bycode( -1, i );
  353.             dimtab[curdim] = i;  /* in case of later sizeof ... */
  354.             }
  355.         }
  356.     else { /* end the character constant */
  357.         if( i == 0 ) uerror( "empty character constant" );
  358.         if( i>(SZINT/SZCHAR) || ( (pflag||hflag)&&i>1) )
  359.             uerror( "too many characters in character constant" );
  360.         }
  361.     }
  362.  
  363. lxcom(){
  364.     register c;
  365.     /* saw a /*: process a comment */
  366.  
  367.     for(;;){
  368.  
  369.         switch( c = getchar() ){
  370.  
  371.         case EOF:
  372.             uerror( "unexpected EOF" );
  373.             return;
  374.  
  375.         case '\n':
  376.             ++lineno;
  377.  
  378.         default:
  379.             continue;
  380.  
  381.         case '*':
  382.             if( (c = getchar()) == '/' ) return;
  383.             else ungetc( c ,stdin);
  384.             continue;
  385.  
  386. # ifdef LINT
  387.         case 'V':
  388.             lxget( c, LEXLET|LEXDIG );
  389.             {
  390.                 extern int vaflag;
  391.                 int i;
  392.                 i = yytext[7]?yytext[7]-'0':0;
  393.                 yytext[7] = '\0';
  394.                 if( strcmp( yytext, "VARARGS" ) ) continue;
  395.                 vaflag = i;
  396.                 continue;
  397.                 }
  398.         case 'L':
  399.             lxget( c, LEXLET );
  400.             if( strcmp( yytext, "LINTLIBRARY" ) ) continue;
  401.             {
  402.                 extern int libflag;
  403.                 libflag = 1;
  404.                 }
  405.             continue;
  406.  
  407.         case 'A':
  408.             lxget( c, LEXLET );
  409.             if( strcmp( yytext, "ARGSUSED" ) ) continue;
  410.             {
  411.                 extern int argflag, vflag;
  412.                 argflag = 1;
  413.                 vflag = 0;
  414.                 }
  415.             continue;
  416.  
  417.         case 'N':
  418.             lxget( c, LEXLET );
  419.             if( strcmp( yytext, "NOTREACHED" ) ) continue;
  420.             reached = 0;
  421.             continue;
  422. # endif
  423.             }
  424.         }
  425.     }
  426.  
  427. yylex(){
  428.     for(;;){
  429.  
  430.         register lxchar;
  431.         register struct lxdope *p;
  432.         register struct symtab *sp;
  433.         int id;
  434.  
  435.         switch( (p=lxcp[(lxchar=getchar())+1])->lxact ){
  436.  
  437.         onechar:
  438.             ungetc( lxchar ,stdin);
  439.  
  440.         case A_1C:
  441.             /* eat up a single character, and return an opcode */
  442.  
  443.             yylval.intval = p->lxval;
  444.             return( p->lxtok );
  445.  
  446.         case A_ERR:
  447.             uerror( "illegal character: %03o (octal)", lxchar );
  448.             break;
  449.  
  450.         case A_LET:
  451.             /* collect an identifier, check for reserved word, and return */
  452.             lxget( lxchar, LEXLET|LEXDIG );
  453.             if( (lxchar=lxres()) > 0 ) return( lxchar ); /* reserved word */
  454.             if( lxchar== 0 ) continue;
  455.             id = lookup( yytext, (stwart&(INSTRUCT|INUNION|FUNNYNAME))?SMOS:0 );
  456.             sp = &stab[id];
  457.             if( sp->sclass == TYPEDEF && !stwart ){
  458.                 stwart = instruct;
  459.                 yylval.nodep = mkty( sp->stype, sp->dimoff, sp->sizoff );
  460.                 return( TYPE );
  461.                 }
  462.             stwart = (stwart&SEENAME) ? instruct : 0;
  463.             yylval.intval = id;
  464.             return( NAME );
  465.  
  466.         case A_DIG:
  467.             /* collect a digit string, then look at last one... */
  468.             lastcon = 0;
  469.             lxget( lxchar, LEXDIG );
  470.             switch( lxchar=getchar() ){
  471.  
  472.             case 'x':
  473.             case 'X':
  474.                 if( yytext[0] != '0' && !yytext[1] ) uerror( "illegal hex constant" );
  475.                 lxmore( lxchar, LEXHEX );
  476.                 /* convert the value */
  477.                 {
  478.                     register char *cp;
  479.                     for( cp = yytext+2; *cp; ++cp ){
  480.                         /* this code won't work for all wild character sets,
  481.                            but seems ok for ascii and ebcdic */
  482.                         lastcon <<= 4;
  483.                         if( isdigit( *cp ) ) lastcon += *cp-'0';
  484.                         else if( isupper( *cp ) ) lastcon += *cp - 'A'+ 10;
  485.                         else lastcon += *cp - 'a'+ 10;
  486.                         }
  487.                     }
  488.  
  489.             hexlong:
  490.                 /* criterion for longness for hex and octal constants is that it
  491.                    fit within 0177777 */
  492.                 if( lastcon & ~0177777L ) yylval.intval = 1;
  493.                 else yylval.intval = 0;
  494.  
  495.                 goto islong;
  496.  
  497.             case '.':
  498.                 lxmore( lxchar, LEXDIG );
  499.  
  500.             getfp:
  501.                 if( (lxchar=getchar()) == 'e' || lxchar == 'E' ){ /* exponent */
  502.  
  503.             case 'e':
  504.             case 'E':
  505.                     if( (lxchar=getchar()) == '+' || lxchar == '-' ){
  506.                         *lxgcp++ = 'e';
  507.                         }
  508.                     else {
  509.                         ungetc(lxchar,stdin);
  510.                         lxchar = 'e';
  511.                         }
  512.                     lxmore( lxchar, LEXDIG );
  513.                     /* now have the whole thing... */
  514.                     }
  515.                 else {  /* no exponent */
  516.                     ungetc( lxchar ,stdin);
  517.                     }
  518.                 return( isitfloat( yytext ) );
  519.  
  520.             default:
  521.                 ungetc( lxchar ,stdin);
  522.                 if( yytext[0] == '0' ){
  523.                     /* convert in octal */
  524.                     register char *cp;
  525.                     for( cp = yytext+1; *cp; ++cp ){
  526.                         lastcon <<= 3;
  527.                         lastcon += *cp - '0';
  528.                         }
  529.                     goto hexlong;
  530.                     }
  531.                 else {
  532.                     /* convert in decimal */
  533.                     register char *cp;
  534.                     for( cp = yytext; *cp; ++cp ){
  535.                         lastcon = lastcon * 10 + *cp - '0';
  536.                         }
  537.                     }
  538.  
  539.                 /* decide if it is long or not (decimal case) */
  540.  
  541.                 /* if it is positive and fits in 15 bits, or negative and
  542.                    and fits in 15 bits plus an extended sign, it is int; otherwise long */
  543.                 /* if there is an l or L following, all bets are off... */
  544.  
  545.                 {    CONSZ v;
  546.                     v = lastcon & ~077777L;
  547.                     if( v == 0 || v == ~077777L ) yylval.intval = 0;
  548.                     else yylval.intval = 1;
  549.                     }
  550.  
  551.             islong:
  552.                 /* finally, look for trailing L or l */
  553.                 if( (lxchar = getchar()) == 'L' || lxchar == 'l' ) yylval.intval = 1;
  554.                 else ungetc( lxchar ,stdin);
  555.                 return( ICON );
  556.                 }
  557.  
  558.         case A_DOT:
  559.             /* look for a dot: if followed by a digit, floating point */
  560.             lxchar = getchar();
  561.             if( lxmask[lxchar+1] & LEXDIG ){
  562.                 ungetc(lxchar,stdin);
  563.                 lxget( '.', LEXDIG );
  564.                 goto getfp;
  565.                 }
  566.             stwart = FUNNYNAME;
  567.             goto onechar;
  568.  
  569.         case A_STR:
  570.             /* string constant */
  571.             lxmatch = '"';
  572.             return( STRING );
  573.  
  574.         case A_CC:
  575.             /* character constant */
  576.             lxmatch = '\'';
  577.             lastcon = 0;
  578.             lxstr(0);
  579.             yylval.intval = 0;
  580.             return( ICON );
  581.  
  582.         case A_BCD:
  583.             {
  584.                 register i;
  585.                 int j;
  586.                 for( i=0; i<LXTSZ; ++i ){
  587.                     if( ( j = getchar() ) == '`' ) break;
  588.                     if( j == '\n' ){
  589.                         uerror( "newline in BCD constant" );
  590.                         break;
  591.                         }
  592.                     yytext[i] = j;
  593.                     }
  594.                 yytext[i] = '\0';
  595.                 if( i>6 ) uerror( "BCD constant exceeds 6 characters" );
  596. # ifdef gcos
  597.                 else strtob( yytext, &lastcon, i );
  598.                 lastcon >>= 6*(6-i);
  599. # else
  600.                 uerror( "gcos BCD constant illegal" );
  601. # endif
  602.                 yylval.intval = 0;  /* not long */
  603.                 return( ICON );
  604.                 }
  605.  
  606.         case A_SL:
  607.             /* / */
  608.             if( (lxchar=getchar()) != '*' ) goto onechar;
  609.             lxcom();
  610.         case A_WS:
  611.             continue;
  612.  
  613.         case A_NL:
  614.             ++lineno;
  615.             lxtitle();
  616.             continue;
  617.  
  618.         case A_NOT:
  619.             /* ! */
  620.             if( (lxchar=getchar()) != '=' ) goto onechar;
  621.             yylval.intval = NE;
  622.             return( EQUOP );
  623.  
  624.         case A_MI:
  625.             /* - */
  626.             if( (lxchar=getchar()) == '-' ){
  627.                 yylval.intval = DECR;
  628.                 return( INCOP );
  629.                 }
  630.             if( lxchar != '>' ) goto onechar;
  631.             stwart = FUNNYNAME;
  632.             yylval.intval=STREF;
  633.             return( STROP );
  634.  
  635.         case A_PL:
  636.             /* + */
  637.             if( (lxchar=getchar()) != '+' ) goto onechar;
  638.             yylval.intval = INCR;
  639.             return( INCOP );
  640.  
  641.         case A_AND:
  642.             /* & */
  643.             if( (lxchar=getchar()) != '&' ) goto onechar;
  644.             return( yylval.intval = ANDAND );
  645.  
  646.         case A_OR:
  647.             /* | */
  648.             if( (lxchar=getchar()) != '|' ) goto onechar;
  649.             return( yylval.intval = OROR );
  650.  
  651.         case A_LT:
  652.             /* < */
  653.             if( (lxchar=getchar()) == '<' ){
  654.                 yylval.intval = LS;
  655.                 return( SHIFTOP );
  656.                 }
  657.             if( lxchar != '=' ) goto onechar;
  658.             yylval.intval = LE;
  659.             return( RELOP );
  660.  
  661.         case A_GT:
  662.             /* > */
  663.             if( (lxchar=getchar()) == '>' ){
  664.                 yylval.intval = RS;
  665.                 return(SHIFTOP );
  666.                 }
  667.             if( lxchar != '=' ) goto onechar;
  668.             yylval.intval = GE;
  669.             return( RELOP );
  670.  
  671.         case A_EQ:
  672.             /* = */
  673.             switch( lxchar = getchar() ){
  674.  
  675.             case '=':
  676.                 yylval.intval = EQ;
  677.                 return( EQUOP );
  678.  
  679.             case '+':
  680.                 yylval.intval = ASG PLUS;
  681.                 break;
  682.  
  683.             case '-':
  684.                 yylval.intval = ASG MINUS;
  685.  
  686.             warn:
  687.                 if( lxmask[ (lxchar=getchar())+1] & (LEXLET|LEXDIG|LEXDOT) ){
  688.                     werror( "ambiguous assignment: assignment op taken" );
  689.                     }
  690.                 ungetc( lxchar ,stdin);
  691.                 break;
  692.  
  693.             case '*':
  694.                 yylval.intval = ASG MUL;
  695.                 goto warn;
  696.  
  697.             case '/':
  698.                 yylval.intval = ASG DIV;
  699.                 break;
  700.  
  701.             case '%':
  702.                 yylval.intval = ASG MOD;
  703.                 break;
  704.  
  705.             case '&':
  706.                 yylval.intval = ASG AND;
  707.                 break;
  708.  
  709.             case '|':
  710.                 yylval.intval = ASG OR;
  711.                 break;
  712.  
  713.             case '^':
  714.                 yylval.intval = ASG ER;
  715.                 break;
  716.  
  717.             case '<':
  718.                 if( (lxchar=getchar()) != '<' ){
  719.                     uerror( "=<%c illegal", lxchar );
  720.                     }
  721.                 yylval.intval = ASG LS;
  722.                 break;
  723.  
  724.             case '>':
  725.                 if( (lxchar=getchar()) != '>' ){
  726.                     uerror( "=>%c illegal", lxchar );
  727.                     }
  728.                 yylval.intval = ASG RS;
  729.                 break;
  730.  
  731.             default:
  732.                 goto onechar;
  733.  
  734.                 }
  735.  
  736.             return( ASOP );
  737.  
  738.         default:
  739.             cerror( "yylex error, character %03o (octal)", lxchar );
  740.  
  741.             }
  742.  
  743.         /* ordinarily, repeat here... */
  744.         cerror( "out of switch in yylex" );
  745.  
  746.         }
  747.  
  748.     }
  749.  
  750. struct lxrdope {
  751.     /* dope for reserved, in alphabetical order */
  752.  
  753.     char *lxrch;    /* name of reserved word */
  754.     short lxract;    /* reserved word action */
  755.     short lxrval;    /* value to be returned */
  756.     } lxrdope[] = {
  757.  
  758.     "asm",        AR_A,    0,
  759.     "auto",        AR_CL,    AUTO,
  760.     "break",    AR_RW,    BREAK,
  761.     "char",        AR_TY,    CHAR,
  762.     "case",        AR_RW,    CASE,
  763.     "continue",    AR_RW,    CONTINUE,
  764.     "double",    AR_TY,    DOUBLE,
  765.     "default",    AR_RW,    DEFAULT,
  766.     "do",        AR_RW,    DO,
  767.     "extern",    AR_CL,    EXTERN,
  768.     "else",        AR_RW,    ELSE,
  769.     "enum",        AR_E,    ENUM,
  770.     "for",        AR_RW,    FOR,
  771.     "float",    AR_TY,    FLOAT,
  772.     "fortran",    AR_CL,    FORTRAN,
  773.     "goto",        AR_RW,    GOTO,
  774.     "if",        AR_RW,    IF,
  775.     "int",        AR_TY,    INT,
  776.     "long",        AR_TY,    LONG,
  777.     "return",    AR_RW,    RETURN,
  778.     "register",    AR_CL,    REGISTER,
  779.     "switch",    AR_RW,    SWITCH,
  780.     "struct",    AR_S,    0,
  781.     "sizeof",    AR_RW,    SIZEOF,
  782.     "short",    AR_TY,    SHORT,
  783.     "static",    AR_CL,    STATIC,
  784.     "typedef",    AR_CL,    TYPEDEF,
  785.     "unsigned",    AR_TY,    UNSIGNED,
  786.     "union",    AR_U,    0,
  787.     "while",    AR_RW,    WHILE,
  788.     "",        0,    0,    /* to stop the search */
  789.     };
  790.  
  791. lxres() {
  792.     /* check to see of yytext is reserved; if so,
  793.     /* do the appropriate action and return */
  794.     /* otherwise, return -1 */
  795.  
  796.     register c, ch;
  797.     register struct lxrdope *p;
  798.  
  799.     ch = yytext[0];
  800.  
  801.     if( !islower(ch) ) return( -1 );
  802.  
  803.     switch( ch ){
  804.  
  805.     case 'a':
  806.         c=0; break;
  807.     case 'b':
  808.         c=2; break;
  809.     case 'c':
  810.         c=3; break;
  811.     case 'd':
  812.         c=6; break;
  813.     case 'e':
  814.         c=9; break;
  815.     case 'f':
  816.         c=12; break;
  817.     case 'g':
  818.         c=15; break;
  819.     case 'i':
  820.         c=16; break;
  821.     case 'l':
  822.         c=18; break;
  823.     case 'r':
  824.         c=19; break;
  825.     case 's':
  826.         c=21; break;
  827.     case 't':
  828.         c=26; break;
  829.     case 'u':
  830.         c=27; break;
  831.     case 'w':
  832.         c=29; break;
  833.  
  834.     default:
  835.         return( -1 );
  836.         }
  837.  
  838.     for( p= lxrdope+c; p->lxrch[0] == ch; ++p ){
  839.         if( !strcmp( yytext, p->lxrch ) ){ /* match */
  840.             switch( p->lxract ){
  841.  
  842.             case AR_TY:
  843.                 /* type word */
  844.                 stwart = instruct;
  845.                 yylval.nodep = mkty( (TWORD)p->lxrval, 0, p->lxrval );
  846.                 return( TYPE );
  847.  
  848.             case AR_RW:
  849.                 /* ordinary reserved word */
  850.                 return( yylval.intval = p->lxrval );
  851.  
  852.             case AR_CL:
  853.                 /* class word */
  854.                 yylval.intval = p->lxrval;
  855.                 return( CLASS );
  856.  
  857.             case AR_S:
  858.                 /* struct */
  859.                 stwart = INSTRUCT|SEENAME;
  860.                 yylval.intval = INSTRUCT;
  861.                 return( STRUCT );
  862.  
  863.             case AR_U:
  864.                 /* union */
  865.                 stwart = INUNION|SEENAME;
  866.                 yylval.intval = INUNION;
  867.                 return( STRUCT );
  868.  
  869.             case AR_E:
  870.                 /* enums */
  871.                 stwart = SEENAME;
  872.                 return( yylval.intval = ENUM );
  873.  
  874.             case AR_A:
  875.                 /* asm */
  876.                 lxget( ' ', LEXWS );
  877.                 if( getchar() != '(' ) goto badasm;
  878.                 lxget( ' ', LEXWS );
  879.                 if( getchar() != '"' ) goto badasm;
  880. # ifndef ONEPASS
  881. # ifndef LINT
  882.                 putchar(')');
  883. # endif
  884. # endif
  885.                 while( (c=getchar()) != '"' ){
  886.                     if( c=='\n' || c==EOF ) goto badasm;
  887. # ifndef LINT
  888.                     putchar(c);
  889. # endif
  890.                     }
  891.                 lxget( ' ', LEXWS );
  892.                 if( getchar() != ')' ) goto badasm;
  893. # ifndef LINT
  894.                 putchar('\n');
  895. # endif
  896.                 return( 0 );
  897.  
  898.             badasm:
  899.                 uerror( "bad asm construction" );
  900.                 return( 0 );
  901.  
  902.             default:
  903.                 cerror( "bad AR_?? action" );
  904.                 }
  905.             }
  906.         }
  907.     return( -1 );
  908.     }
  909.  
  910. lxtitle(){
  911.     /* called after a newline; set linenumber and file name */
  912.  
  913.     register c, val;
  914.     register char *cp;
  915.  
  916.     for(;;){  /* might be several such lines in a row */
  917.         if( (c=getchar()) != '#' ){
  918.             if( c != EOF ) ungetc(c,stdin);
  919.             return;
  920.             }
  921.  
  922.         lxget( ' ', LEXWS );
  923.         val = 0;
  924.         for( c=getchar(); isdigit(c); c=getchar() ){
  925.             val = val*10+ c - '0';
  926.             }
  927.         ungetc( c, stdin );
  928.         lineno = val;
  929.         lxget( ' ', LEXWS );
  930.         if( (c=getchar()) != '\n' ){
  931.             for( cp=ftitle; c!='\n'; c=getchar(),++cp ){
  932.                 *cp = c;
  933.                 }
  934.             *cp = '\0';
  935.             }
  936.         }
  937.     }
  938.