home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / compiler / sozobon / scsrc20 / jas / parse.c < prev    next >
C/C++ Source or Header  |  1991-02-22  |  15KB  |  773 lines

  1.  
  2. /*
  3.  * Copyright (c) 1988,1991 by Sozobon, Limited.  Author: Joseph M Treat
  4.  *
  5.  * Permission is granted to anyone to use this software for any purpose
  6.  * on any computer system, and to redistribute it freely, with the
  7.  * following restrictions:
  8.  * 1) No charge may be made other than reasonable charges for reproduction.
  9.  * 2) Modified versions must be clearly marked as such.
  10.  * 3) The authors are not responsible for any harmful consequences
  11.  *    of using this software, even if they result from defects in it.
  12.  */
  13.  
  14. #include "jas.h"
  15.  
  16. #include "parse.h"
  17.  
  18. int line = 1;
  19. int sawerror = 0;
  20. int ignore = 0;
  21. int funny_state = -1;
  22.  
  23. jmp_buf YYljbuf;
  24. jmp_buf YYopbuf;
  25.  
  26. YYSTYPE yylval;
  27. int yywidth = 0;
  28.  
  29. int token = 0;
  30.  
  31. SYM *cursym = (SYM *) NULL;
  32.  
  33. extern SYM dot;
  34. extern long newdot;
  35.  
  36. extern EXPR Yexpr(), Xexpr(), Aexpr(), Sexpr(),
  37.         Pexpr(), Mexpr(), Uexpr(), Yfactor();
  38. extern LIST *Yname_list(), *Yexpr_list();
  39. extern OPERAND *Yoperand();
  40.  
  41. yyparse()
  42. {
  43.     token = yylex();
  44.     while ( token ) {
  45.         Yline();
  46.         dot.value = newdot;
  47.     }
  48.     return sawerror;
  49. }
  50.  
  51. Yline()
  52. {
  53.     if ( setjmp( YYljbuf ) ) {
  54.         /*
  55.          * Return here on any call to Yerror to gobble up through NL
  56.          */
  57.         while ( token && token != NL )
  58.             token = yylex();
  59.         if ( token ) {
  60.             line++;
  61.             token = yylex();
  62.         }
  63.         ignore = 0;
  64.         return;
  65.     }
  66.  
  67.     if ( Ylabel_list() )
  68.         Ystatement();
  69.  
  70.     if ( token != NL )
  71.         Yerror( "end of line expected" );
  72.     line++;
  73.     token = yylex();
  74.     ignore = 0;
  75. }
  76.  
  77. Ylabel_list()
  78. {
  79.      while ( token == NAME ) {
  80.          cursym = yylval.sym;
  81.          token = yylex();
  82.         if ( token == _EQU ) {
  83.             EXPR val;
  84.             if ( cursym->flags & (SEGMT|EQUATED) )
  85.                 Yerror( "symbol redefinition" );
  86.             token = yylex();
  87.             val = Yexpr();
  88.             if ( val.psym )
  89.                 Yerror( "illegal equated expression" );
  90.             cursym->value = val.value;
  91.             cursym->flags |= EQUATED | DEFINED;
  92.             return 0;
  93.         }
  94.          if ( token != COLON  )
  95.              Yerror( "missing ':'" );
  96.         if ( cursym->flags & (SEGMT|EQUATED) )
  97.             Yerror( "symbol redefinition" );
  98.         cursym->flags |= ( dot.flags & SEGMT ) | DEFINED;
  99.         cursym->value = dot.value;
  100.          token = yylex();
  101.      }
  102.     return 1;
  103. }
  104.  
  105. Ystatement()
  106. {
  107.     if ( token != NL ) {
  108.         Yinstruction();
  109.         cursym = (SYM *) NULL;
  110.     }
  111. }
  112.  
  113. Yinstruction()
  114. {
  115.     STMT *sp;
  116.     SYM *sym;
  117.     EXPR val;
  118.     register short size;
  119.     register LIST *lp, *xlp;
  120. #ifdef MINIX
  121.     short asciz = 0;
  122. #endif
  123.     extern LIST *Yname_list();
  124.     extern LIST *Yexpr_list();
  125.  
  126.     switch ( token ) {
  127.     default:
  128.         Yerror( "syntax error" );
  129.         break;
  130. #ifdef MINIX
  131.     case _SECT:            /* must be followed by a section name */
  132.         switch (token = yylex()) {
  133.         default:
  134.             Yerror( "syntax error" );
  135.             break;
  136.         case _TEXT:
  137.             chsegmt( TXT );
  138.             token = yylex();
  139.             break;
  140.         case _DATA:
  141.             chsegmt( DAT );
  142.             token = yylex();
  143.             break;
  144.         case END:
  145.         case _BSS:
  146.             chsegmt( BSS );
  147.             token = yylex();
  148.             break;
  149.         }
  150.         break;
  151. #endif
  152.     case END:
  153.         token = yylex();
  154.         break;
  155.     case _TEXT:
  156.         chsegmt( TXT );
  157.         token = yylex();
  158.         break;
  159.     case _DATA:
  160.         chsegmt( DAT );
  161.         token = yylex();
  162.         break;
  163.     case _BSS:
  164.         chsegmt( BSS );
  165.         token = yylex();
  166.         break;
  167.     case _GLOBL:
  168.         token = yylex();
  169.         lp = Yname_list();
  170.         for ( ; lp; lp = xlp ) {
  171.             xlp = lp->next;
  172.             lp->u.sym->flags |= GLOBAL | DEFINED;
  173.             free( (char *) lp );
  174.         }
  175.         break;
  176. #ifdef MINIX
  177.     case _ASCII:
  178.         asciz = 1;
  179.         yywidth = 8;
  180.         /* FALL THROUGH */
  181. #endif
  182.     case _DC:
  183.         size = yywidth;
  184.         if ( size == 0 )
  185.             Yerror( ".dc must have width specifier" );
  186.         token = yylex();
  187.         lp = Yexpr_list();
  188.  
  189.         if ( size != 8 ) {
  190.             if ( newdot & 1 ) {
  191.                 zeros( 1L );
  192.                 if ( cursym != (SYM *) NULL ) 
  193.                     cursym->value = newdot;
  194.             }
  195.         }
  196.         for ( ; lp; lp = xlp ) {
  197.             xlp = lp->next;
  198.             generate(size, GENRELOC, lp->u.val.value, lp->u.sym );
  199.             free( (char *) lp );
  200.         }
  201. #ifdef MINIX
  202.         if ( asciz ) {
  203.             generate(size, GENRELOC, 0L, (SYM *) NULL );
  204.         }
  205. #endif
  206.         break;
  207.     case _ORG:
  208.         token = yylex();
  209.         val = Yexpr();
  210.         if ( val.psym )
  211.             Yerror( "illegal use of symbol in expression" );
  212.         if ( val.value < newdot )
  213.             Yerror( "attempt to move current location backward" );
  214.         if ( val.value > newdot ) {
  215.             if ( newdot & 1 )
  216.                 zeros( 1L );
  217.             if ( val.value > newdot )
  218.                 zeros( val.value - newdot );
  219.         }
  220.         break;
  221.     case _DS:
  222.         size = yywidth;
  223.         if ( size == 0 )
  224.             Yerror( ".ds must have width specifier" );
  225.         token = yylex();
  226.         val = Yexpr();
  227.         if ( size != 8 ) {
  228.             if ( newdot & 1 ) {
  229.                 zeros( 1L );
  230.                 if ( cursym != (SYM *) NULL ) 
  231.                     cursym->value = newdot;
  232.             }
  233.         }
  234.         if ( val.psym )
  235.             Yerror( "illegal use of symbol in expression" );
  236.         zeros( val.value * (size/8) );
  237.         break;
  238. #ifdef MINIX
  239.     case _ALIGN:
  240.         token = yylex();
  241.         val = Yexpr();
  242.         if ( val.psym )
  243.             Yerror( "illegal use of symbol in expression" );
  244.         if ( val.value <= 0 )
  245.             Yerror( "operand of .align must be > 0" );
  246.         if ( newdot % val.value ) {
  247.             long n = val.value - ( newdot % val.value );
  248.  
  249.             zeros( n );
  250.             if ( cursym != (SYM *) NULL ) 
  251.                 cursym->value = newdot;
  252.         }
  253.         break;
  254. #endif
  255.     case _EVEN:
  256.         if ( newdot & 1 ) {
  257.             zeros( 1L );
  258.             if ( cursym != (SYM *) NULL ) 
  259.                 cursym->value = newdot;
  260.         }
  261.         token = yylex();
  262.         break;
  263.     case _COMM:
  264.          if ( (token = yylex()) != NAME  )
  265.              Yerror( "missing label" );
  266.         sym = yylval.sym;
  267.         if ( sym->flags & (SEGMT|EQUATED) )
  268.             Yerror( "symbol redefinition" );
  269.          if ( (token = yylex()) != COMMA  )
  270.              Yerror( "missing ','" );
  271.          token = yylex();
  272.          val = Yexpr();
  273.         sym->flags |= EXTERN | DEFINED;
  274.         sym->value = val.value;
  275.         break;
  276.     case INSTR:
  277.         sp = yylval.stmt;
  278.         sp->op0 = sp->op1 = (OPERAND *) NULL;
  279.         token = yylex();
  280.         if ( token != NL ) {
  281.             sp->op0 = Yoperand();
  282.             if ( token == COMMA ) {
  283.                 token = yylex();
  284.                 sp->op1 = Yoperand();
  285.             }
  286.         }
  287.         geninst( sp );
  288.         if ( sp->op0 ) {
  289.             free( sp->op0 );
  290.             if ( sp->op1 )
  291.                 free( sp->op1 );
  292.         }
  293.         free( sp );
  294.         break;
  295.      }
  296.  }
  297.  
  298. LIST *
  299. Yname_list()
  300. {
  301.     register LIST *lp, *xlp;
  302.  
  303.     if ( token != NAME )
  304.         Yerror( "label expected" );
  305.     lp = xlp = ALLO(LIST);
  306.     xlp->next = (LIST *) NULL;
  307.     xlp->u.sym = yylval.sym;
  308.     token = yylex();
  309.     while ( token == COMMA ) {
  310.         if ( (token = yylex()) != NAME )
  311.             Yerror( "label expected" );
  312.         xlp->next = ALLO(LIST);
  313.         xlp = xlp->next;
  314.         xlp->next = (LIST *) NULL;
  315.         xlp->u.sym = yylval.sym;
  316.         token = yylex();
  317.     }
  318.     return lp;
  319. }
  320.  
  321. LIST *
  322. Yexpr_list()
  323. {
  324.     EXPR val;
  325.     register LIST *lp;
  326.     LIST *xlp, *slp;
  327.     extern LIST *make_slist();
  328.  
  329.     if ( token == STRING ) {
  330.         lp = make_slist( &xlp, yylval.str );
  331.         token = yylex();
  332.         free( yylval.str );
  333.     } else {
  334.         val = Yexpr();
  335.         lp = xlp = ALLO(LIST);
  336.         xlp->next = (LIST *) NULL;
  337.         xlp->u.val = val;
  338.     }
  339.     while ( token == COMMA ) {
  340.         token = yylex();
  341.         if ( token == STRING ) {
  342.             xlp->next = make_slist( &slp, yylval.str );
  343.             xlp = slp;
  344.             token = yylex();
  345.             free( yylval.str );
  346.         } else {
  347.             val = Yexpr();
  348.             xlp->next = ALLO(LIST);
  349.             xlp = xlp->next;
  350.             xlp->next = (LIST *) NULL;
  351.             xlp->u.val = val;
  352.         }
  353.     }
  354.     return lp;
  355. }
  356.  
  357. LIST *
  358. make_slist( last, string )
  359.     LIST **last;
  360.     char *string;
  361. {
  362.     char *cp;
  363.     LIST *lp, *xlp;
  364.     EXPR val;
  365.  
  366.     lp = xlp = (LIST *) NULL;
  367.  
  368.     for ( cp = string; *cp; cp++ ) {
  369.         int ch;
  370.  
  371.         if ( *cp == '\\' ) {
  372.             switch ( cp[1] ) {
  373.             case 'n': ch = '\n'; break;
  374.             case 't': ch = '\t'; break;
  375.             case 'r': ch = '\r'; break;
  376.             case 'b': ch = '\b'; break;
  377.             case '0': ch = '\0'; break;
  378.             default:  ch = cp[1]; break;
  379.             }
  380.             cp++;
  381.         } else {
  382.             ch = *cp;
  383.         }
  384.         if ( lp == (LIST *) NULL ) {
  385.             lp = xlp = ALLO(LIST);
  386.             xlp->next = (LIST *) NULL;
  387.         } else {
  388.             xlp->next = ALLO(LIST);
  389.             xlp = xlp->next;
  390.             xlp->next = (LIST *) NULL;
  391.         }
  392.         xlp->u.val.psym = (SYM *) NULL;
  393.         xlp->u.val.value = ch;
  394.     }
  395.  
  396.     *last = xlp;
  397.     return lp;
  398. }
  399.  
  400. OPERAND *
  401. Yoperand()
  402. {
  403.     register OPERAND *op;
  404.     register int reg, inx;
  405.     int short_abs = 0;
  406.     EXPR val;
  407.  
  408.     op = ALLO(OPERAND);
  409.     switch ( token ) {
  410.     case SREG:
  411.          op->mode = yylval.val;
  412.          token = yylex();
  413.          break;
  414.      case REG:
  415.          op->mode = yylval.val < 8 ? O_DN : O_AN;
  416.         op->reg = reg = yylval.val;
  417.          token = yylex();
  418.         if ( token == MINUS || token == DIV ) {
  419.             /*
  420.              * we have a register mask list
  421.              */
  422.             op->mode = O_REGS;
  423.             op->expr.value = 1L << reg;
  424.             while ( token == MINUS || token == DIV ) {
  425.                 int tok = token;
  426.  
  427.                 token = yylex();
  428.                 inx = yylval.val;
  429.                 if ( token != REG ) 
  430.                     Yerror("invalid register list");
  431.                 if ( tok == DIV ) {
  432.                     op->expr.value |= (1L << inx);
  433.                     reg = inx;
  434.                 } else {
  435.                     int i;
  436.  
  437.                     if ( inx < reg )
  438.                         Yerror("invalid register list");
  439.                     for ( i = reg+1; i <= inx; i++ )
  440.                         op->expr.value |= (1L << i);
  441.                 }
  442.                 token = yylex();
  443.                 if ( tok == MINUS && token == MINUS )
  444.                     Yerror("invalid register list");
  445.             }
  446.         }
  447.          break;
  448.     case LP: 
  449.         if ( (token = yylex()) != REG )
  450.             Yerror( "missing register" );
  451.         reg = yylval.val;
  452.         if ( (token = yylex()) != RP )
  453.             Yerror( "missing ')'" );
  454.         token = yylex();
  455.         if ( token == PLUS ) {
  456.             op->mode = O_POST;
  457.             op->reg = reg;
  458.             token = yylex();
  459.         } else {
  460.             op->mode = O_INDR;
  461.             op->reg = reg;
  462.         }
  463.         break;
  464.     default:
  465. #ifdef MINIX
  466.         if ( token == NAME && yywidth == 16 )
  467.             short_abs = 1;
  468. #endif
  469.         funny_state = 0;
  470.         if ( setjmp( YYopbuf ) ) {
  471.             /* 
  472.              * Yexpr() saw MINUS LP REG
  473.              */
  474.             reg = yylval.val;
  475.             if ( (token = yylex()) != RP )
  476.                 Yerror( "missing ')'" );
  477.             op->mode = O_PRE;
  478.             op->reg = reg;
  479.             token = yylex();
  480.             funny_state = -1;
  481.             break;
  482.         }
  483.         val = Yexpr();
  484.         funny_state = -1;
  485.         if ( token != LP ) {
  486. #ifdef MINIX
  487.             if ( short_abs )
  488.                 op->mode = O_SABS;
  489.             else
  490.                 op->mode = O_ABS;
  491. #else
  492.             op->mode = O_ABS;
  493. #endif
  494.             op->expr = val;
  495.             break;
  496.         }
  497.         token = yylex();
  498.         if ( token == REG ) {
  499.             reg = yylval.val;
  500.             if ( (token = yylex()) == COMMA ) {
  501.                 if ( (token = yylex()) != REG )
  502.                     Yerror( "missing register" );
  503.                 inx = yylval.val;
  504.                 if ( yywidth == 8 )
  505.                     Yerror( "index reg can't be byte" );
  506.                 if ( yywidth == 32 )
  507.                     inx |= 0x10;
  508.                 if ( (token = yylex()) != RP )
  509.                     Yerror( "missing ')'" );
  510.                 op->mode = O_INDX;
  511.                 op->reg = reg;
  512.                 op->inx = inx;
  513.                 op->expr = val;
  514.                 token = yylex();
  515.             } else {
  516.                 if ( token != RP )
  517.                     Yerror( "missing ')'" );
  518.                 op->mode = O_DISP;
  519.                 op->reg = reg;
  520.                 op->expr = val;
  521.                 token = yylex();
  522.             }
  523.         } else if ( token == PC ) {
  524.             if ( (token = yylex()) == COMMA ) {
  525.                 if ( (token = yylex()) != REG )
  526.                     Yerror( "missing register" );
  527.                 inx = yylval.val;
  528.                 if ( yywidth == 8 )
  529.                     Yerror( "index reg can't be byte" );
  530.                 if ( yywidth == 32 )
  531.                     inx |= 0x10;
  532.                 if ( (token = yylex()) != RP )
  533.                     Yerror( "missing ')'" );
  534.                 op->mode = O_PCIX;
  535.                 op->inx = inx;
  536.                 op->expr = val;
  537.                 token = yylex();
  538.             } else {
  539.                 if ( token != RP )
  540.                     Yerror( "missing ')'" );
  541.                 op->mode = O_PCRL;
  542.                 op->expr = val;
  543.                 token = yylex();
  544.             }
  545.         } else
  546.             Yerror( "register or pc expected" );
  547.         break;
  548.     case POUND:
  549.         token = yylex();
  550.         val = Yexpr();
  551.         op->mode = O_IMM;
  552.         op->expr = val;
  553.         break;
  554.      }
  555.      return op;
  556.  }
  557.  
  558. EXPR
  559. Yexpr()
  560. {
  561.     EXPR val1, val2;
  562.  
  563.     val1 = Xexpr();
  564.     while ( token == OR ) {
  565.         funny_state = -1;
  566.         token = yylex();
  567.         val2 = Xexpr();
  568.          if ( val1.psym || val2.psym )
  569.              Yerror( "illegal use of symbol in expression" );
  570.          val1.value |= val2.value;
  571.      }
  572.      return val1;
  573. }
  574.  
  575. EXPR
  576. Xexpr()
  577. {
  578.     EXPR val1, val2;
  579.  
  580.     val1 = Aexpr();
  581.     while ( token == XOR ) {
  582.         funny_state = -1;
  583.         token = yylex();
  584.         val2 = Aexpr();
  585.          if ( val1.psym || val2.psym )
  586.              Yerror( "illegal use of symbol in expression" );
  587.          val1.value ^= val2.value;
  588.      }
  589.      return val1;
  590. }
  591.  
  592. EXPR
  593. Aexpr()
  594. {
  595.     EXPR val1, val2;
  596.  
  597.     val1 = Sexpr();
  598.     while ( token == AND ) {
  599.         funny_state = -1;
  600.         token = yylex();
  601.         val2 = Sexpr();
  602.          if ( val1.psym || val2.psym )
  603.              Yerror( "illegal use of symbol in expression" );
  604.          val1.value &= val2.value;
  605.      }
  606.      return val1;
  607. }
  608.  
  609. EXPR
  610. Sexpr()
  611. {
  612.     register int op;
  613.     EXPR val1, val2;
  614.  
  615.     val1 = Pexpr();
  616.     while ( token == LSH || token == RSH ) {
  617.         op = token;
  618.         funny_state = -1;
  619.         token = yylex();
  620.         val2 = Pexpr();
  621.          if ( val1.psym || val2.psym )
  622.              Yerror( "illegal use of symbol in expression" );
  623.          if ( op == LSH )
  624.              val1.value <<= val2.value;
  625.          else
  626.              val1.value >>= val2.value;
  627.      }
  628.      return val1;
  629. }
  630.  
  631. EXPR
  632. Pexpr()
  633. {
  634.     register int op;
  635.     EXPR val1, val2;
  636.  
  637.     val1 = Mexpr();
  638.     while ( token == PLUS || token == MINUS ) {
  639.         op = token;
  640.         funny_state = -1;
  641.         token = yylex();
  642.         val2 = Mexpr();
  643.          if ( op == PLUS ) {
  644.              if ( val1.psym && val2.psym )
  645.                  Yerror( "illegal use of symbol in expression" );
  646.             if ( val2.psym )
  647.                 val1.psym = val2.psym;
  648.             val1.value += val2.value;
  649.         } else {
  650.              if ( val2.psym )
  651.                  Yerror( "illegal use of symbol in expression" );
  652.             val1.value -= val2.value;
  653.         }
  654.      }
  655.      return val1;
  656. }
  657.  
  658. EXPR
  659. Mexpr()
  660. {
  661.     register int op;
  662.     EXPR val1, val2;
  663.     jmp_buf oldYYljbuf;
  664.  
  665.     val1 = Uexpr();
  666.     while ( token == STAR || token == DIV || token == MOD ) {
  667.         op = token;
  668.         funny_state = -1;
  669.         token = yylex();
  670.         val2 = Uexpr();
  671.          if ( val1.psym || val2.psym )
  672.              Yerror( "illegal use of symbol in expression" );
  673.          if ( op == DIV ) {
  674.              if ( val2.value == 0L ) 
  675.                  Yerror( "divison by zero" );
  676.              val1.value /= val2.value;
  677.          } else if ( op == MOD ) {
  678.              if ( val2.value == 0L ) 
  679.                  Yerror( "modulo by zero" );
  680.              val1.value %= val2.value;
  681.          } else {
  682.              val1.value *= val2.value;
  683.         }
  684.      }
  685.      return val1;
  686. }
  687.  
  688. EXPR
  689. Uexpr()
  690. {
  691.     EXPR val;
  692.  
  693.     switch ( token ) {
  694.     case MINUS:
  695.         if ( funny_state == 0 )
  696.             funny_state = 1;
  697.         else
  698.             funny_state = -1;
  699.         token = yylex();
  700.         val = Yfactor();
  701.         val.value = - val.value;
  702.          if ( val.psym )
  703.              Yerror( "illegal use of symbol in expression" );
  704.         break;
  705.     case NOT:
  706.         funny_state = -1;
  707.         token = yylex();
  708.         val = Yfactor();
  709.         if ( val.psym )
  710.              Yerror( "illegal use of symbol in expression" );
  711.         val.value = - val.value;
  712.         break;
  713.     default:
  714.         val = Yfactor();
  715.         break;
  716.     }
  717.     return val;
  718. }
  719.  
  720. EXPR
  721. Yfactor()
  722. {
  723.     EXPR val;
  724.  
  725.     switch ( token ) {
  726.     case NUMBER:
  727.         funny_state = -1;
  728.         val.psym = (SYM *) NULL;
  729.         val.value = yylval.val;
  730.         break;
  731.     case NAME:
  732.         funny_state = -1;
  733.         if ( yylval.sym->flags & EQUATED ) {
  734.             val.psym = (SYM *) NULL;
  735.             val.value = yylval.sym->value;
  736.             break;
  737.         }
  738.         val.psym = yylval.sym;
  739.         val.value = 0L;
  740.         break;
  741.     case LP:
  742.         if ( funny_state == 1 )
  743.             funny_state = 2;
  744.         else
  745.             funny_state = -1;
  746.         token = yylex();
  747.         val = Yexpr();
  748.         if ( token != RP )
  749.             Yerror( "missing ')'" );
  750.         break;
  751.     case REG:
  752.         if ( funny_state == 2 ) {
  753.             longjmp( YYopbuf, 1 );
  754.         }
  755.     default:
  756.         Yerror( "illegal expression" );
  757.     }
  758.     token = yylex();
  759.     return val;
  760. }
  761.         
  762. Yerror( s )
  763.     char *s;
  764. {
  765.     if (! ignore) {
  766.         fprintf( stderr, "jas: line %d ( %s )\n", line, s );
  767.         ignore = 1;
  768.     }
  769.     sawerror = 1;
  770.     funny_state = -1;
  771.     longjmp( YYljbuf, 1 );
  772. }
  773.