home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Atari / Gnu / gassrc04.zoo / expr.c < prev    next >
C/C++ Source or Header  |  1991-02-08  |  30KB  |  977 lines

  1. /* expr.c -operands, expressions-
  2.    Copyright (C) 1987 Free Software Foundation, Inc.
  3.  
  4. This file is part of GAS, the GNU Assembler.
  5.  
  6. GAS is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GAS is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GAS; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * This is really a branch office of as-read.c. I split it out to clearly
  22.  * distinguish the world of expressions from the world of statements.
  23.  * (It also gives smaller files to re-compile.)
  24.  * Here, "operand"s are of expressions, not instructions.
  25.  */
  26.  
  27. #include <ctype.h>
  28. #include "as.h"
  29. #include "flonum.h"
  30. #include "read.h"
  31. #include "struc-symbol.h"
  32. #include "expr.h"
  33. #include "obstack.h"
  34. #include "symbols.h"
  35.  
  36. static void clean_up_expression();    /* Internal. */
  37. extern const char EXP_CHARS[];    /* JF hide MD floating pt stuff all the same place */
  38. extern const char FLT_CHARS[];
  39.  
  40. #ifdef SUN_ASM_SYNTAX
  41. extern int local_label_defined[];
  42. #endif
  43.  
  44. /*
  45.  * Build any floating-point literal here.
  46.  * Also build any bignum literal here.
  47.  */
  48.  
  49. /* LITTLENUM_TYPE    generic_buffer [6];    /* JF this is a hack */
  50. /* Seems atof_machine can backscan through generic_bignum and hit whatever
  51.    happens to be loaded before it in memory.  And its way too complicated
  52.    for me to fix right.  Thus a hack.  JF:  Just make generic_bignum bigger,
  53.    and never write into the early words, thus they'll always be zero.
  54.    I hate Dean's floating-point code.  Bleh.
  55.  */
  56. LITTLENUM_TYPE    generic_bignum [SIZE_OF_LARGE_NUMBER+6];
  57. FLONUM_TYPE    generic_floating_point_number =
  58. {
  59.   & generic_bignum [6],        /* low (JF: Was 0) */
  60.   & generic_bignum [SIZE_OF_LARGE_NUMBER+6 - 1], /* high JF: (added +6) */
  61.   0,                /* leader */
  62.   0,                /* exponent */
  63.   0                /* sign */
  64. };
  65. /* If nonzero, we've been asked to assemble nan, +inf or -inf */
  66. int generic_floating_point_magic;
  67.  
  68. /*
  69.  * Summary of operand().
  70.  *
  71.  * in:    Input_line_pointer points to 1st char of operand, which may
  72.  *    be a space.
  73.  *
  74.  * out:    A expressionS. X_seg determines how to understand the rest of the
  75.  *    expressionS.
  76.  *    The operand may have been empty: in this case X_seg == SEG_NONE.
  77.  *    Input_line_pointer -> (next non-blank) char after operand.
  78.  *
  79.  */
  80.  
  81. static segT
  82. operand (expressionP)
  83.      register expressionS *    expressionP;
  84. {
  85.   register char        c;
  86.   register char *name;    /* points to name of symbol */
  87.   register struct symbol *    symbolP; /* Points to symbol */
  88.  
  89.   extern  char hex_value[];    /* In hex_value.c */
  90.   char    *local_label_name();
  91.  
  92.   SKIP_WHITESPACE();        /* Leading whitespace is part of operand. */
  93.   c = * input_line_pointer ++;    /* Input_line_pointer -> past char in c. */
  94.   if (isdigit(c))
  95.     {
  96.       register valueT    number;    /* offset or (absolute) value */
  97.       register short int digit;    /* value of next digit in current radix */
  98.                 /* invented for humans only, hope */
  99.                 /* optimising compiler flushes it! */
  100.       register short int radix;    /* 8, 10 or 16 */
  101.                 /* 0 means we saw start of a floating- */
  102.                 /* point constant. */
  103.       register short int maxdig;/* Highest permitted digit value. */
  104.       register int    too_many_digits; /* If we see >= this number of */
  105.                 /* digits, assume it is a bignum. */
  106.       register char *    digit_2; /* -> 2nd digit of number. */
  107.                int    small;    /* TRUE if fits in 32 bits. */
  108.  
  109.       if (c=='0')
  110.     {            /* non-decimal radix */
  111.       if ((c = * input_line_pointer ++)=='x' || c=='X')
  112.         {
  113.           c = * input_line_pointer ++; /* read past "0x" or "0X" */
  114.           maxdig = radix = 16;
  115.           too_many_digits = 9;
  116.         }
  117.       else
  118.         {
  119.           /* If it says '0f' and the line ends or it DOESN'T look like
  120.              a floating point #, its a local label ref.  DTRT */
  121.           if(c=='f' && (! *input_line_pointer ||
  122.                 (!index("+-.0123456789",*input_line_pointer) &&
  123.                  !index(EXP_CHARS,*input_line_pointer))))
  124.         {
  125.               maxdig = radix = 10;
  126.           too_many_digits = 11;
  127.           c='0';
  128.           input_line_pointer-=2;
  129.         }
  130.           else if (c && index (FLT_CHARS,c))
  131.         {
  132.           radix = 0;    /* Start of floating-point constant. */
  133.                 /* input_line_pointer -> 1st char of number. */
  134.           expressionP -> X_add_number =  - (isupper(c) ? tolower(c) : c);
  135.         }
  136.           else
  137.         {        /* By elimination, assume octal radix. */
  138.           radix = 8;
  139.           maxdig = 10;    /* Un*x sux. Compatibility. */
  140.           too_many_digits = 11;
  141.         }
  142.         }
  143.       /* c == char after "0" or "0x" or "0X" or "0e" etc.*/
  144.     }
  145.       else
  146.     {
  147.       maxdig = radix = 10;
  148.       too_many_digits = 11;
  149.     }
  150.       if (radix)
  151.     {            /* Fixed-point integer constant. */
  152.                 /* May be bignum, or may fit in 32 bits. */
  153. /*
  154.  * Most numbers fit into 32 bits, and we want this case to be fast.
  155.  * So we pretend it will fit into 32 bits. If, after making up a 32
  156.  * bit number, we realise that we have scanned more digits than
  157.  * comfortably fit into 32 bits, we re-scan the digits coding
  158.  * them into a bignum. For decimal and octal numbers we are conservative: some
  159.  * numbers may be assumed bignums when in fact they do fit into 32 bits.
  160.  * Numbers of any radix can have excess leading zeros: we strive
  161.  * to recognise this and cast them back into 32 bits.
  162.  * We must check that the bignum really is more than 32
  163.  * bits, and change it back to a 32-bit number if it fits.
  164.  * The number we are looking for is expected to be positive, but
  165.  * if it fits into 32 bits as an unsigned number, we let it be a 32-bit
  166.  * number. The cavalier approach is for speed in ordinary cases.
  167.  */
  168.       digit_2 = input_line_pointer;
  169.       for (number=0;  (digit=hex_value[c])<maxdig;  c = * input_line_pointer ++)
  170.         {
  171.           number = number * radix + digit;
  172.         }
  173.       /* C contains character after number. */
  174.       /* Input_line_pointer -> char after C. */
  175.       small = input_line_pointer - digit_2 < too_many_digits;
  176.       if ( ! small)
  177.         {
  178.           /*
  179.            * We saw a lot of digits. Manufacture a bignum the hard way.
  180.            */
  181.           LITTLENUM_TYPE *    leader;    /* -> high order littlenum of the bignum. */
  182.           LITTLENUM_TYPE *    pointer; /* -> littlenum we are frobbing now. */
  183.           long int        carry;
  184.  
  185.           leader = generic_bignum;
  186.           generic_bignum [0] = 0;
  187.           generic_bignum [1] = 0;
  188.                 /* We could just use digit_2, but lets be mnemonic. */
  189.           input_line_pointer = -- digit_2; /* -> 1st digit. */
  190.           c = *input_line_pointer ++;
  191.           for (;   (carry = hex_value [c]) < maxdig;   c = * input_line_pointer ++)
  192.         {
  193.           for (pointer = generic_bignum;
  194.                pointer <= leader;
  195.                pointer ++)
  196.             {
  197.               long int    work;
  198.  
  199.               work = carry + radix * * pointer;
  200.               * pointer = work & LITTLENUM_MASK;
  201.               carry = work >> LITTLENUM_NUMBER_OF_BITS;
  202.             }
  203.           if (carry)
  204.             {
  205.               if (leader < generic_bignum + SIZE_OF_LARGE_NUMBER - 1)
  206.             {    /* Room to grow a longer bignum. */
  207.               * ++ leader = carry;
  208.             }
  209.             }
  210.         }
  211.           /* Again, C is char after number, */
  212.           /* input_line_pointer -> after C. */
  213.           know( BITS_PER_INT == 32 );
  214.           know( LITTLENUM_NUMBER_OF_BITS == 16 );
  215.           /* Hence the constant "2" in the next line. */
  216.           if (leader < generic_bignum + 2)
  217.         {        /* Will fit into 32 bits. */
  218.           number =
  219.             ( (generic_bignum [1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS )
  220.             | (generic_bignum [0] & LITTLENUM_MASK);
  221.           small = TRUE;
  222.         }
  223.           else
  224.         {
  225.           number = leader - generic_bignum + 1;    /* Number of littlenums in the bignum. */
  226.         }
  227.         }
  228.       if (small)
  229.         {
  230.           /*
  231.            * Here with number, in correct radix. c is the next char.
  232.            * Note that unlike Un*x, we allow "011f" "0x9f" to
  233.            * both mean the same as the (conventional) "9f". This is simply easier
  234.            * than checking for strict canonical form. Syntax sux!
  235.            */
  236.           if (number<10)
  237.         {
  238. #ifdef SUN_ASM_SYNTAX
  239.           if (c=='b' || (c=='$' && local_label_defined[number]))
  240. #else
  241.           if (c=='b')
  242. #endif
  243.             {
  244.               /*
  245.                * Backward ref to local label.
  246.                * Because it is backward, expect it to be DEFINED.
  247.                */
  248.               /*
  249.                * Construct a local label.
  250.                */
  251.               name = local_label_name ((int)number, 0);
  252.               if ( (symbolP = symbol_table_lookup(name)) /* seen before */
  253.               && (symbolP -> sy_type & N_TYPE) != N_UNDF /* symbol is defined: OK */
  254.               )
  255.             {        /* Expected path: symbol defined. */
  256.               /* Local labels are never absolute. Don't waste time checking absoluteness. */
  257.               know(   (symbolP -> sy_type & N_TYPE) == N_DATA
  258.                    || (symbolP -> sy_type & N_TYPE) == N_TEXT );
  259.               expressionP -> X_add_symbol = symbolP;
  260.               expressionP -> X_add_number = 0;
  261.               expressionP -> X_seg          = N_TYPE_seg [symbolP -> sy_type];
  262.             }
  263.               else
  264.             {        /* Either not seen or not defined. */
  265.               as_warn( "Backw. ref to unknown label \"%d:\", 0 assumed.",
  266.                   number
  267.                   );
  268.               expressionP -> X_add_number = 0;
  269.               expressionP -> X_seg        = SEG_ABSOLUTE;
  270.             }
  271.             }
  272.           else
  273.             {
  274. #ifdef SUN_ASM_SYNTAX
  275.               if (c=='f' || (c=='$' && !local_label_defined[number]))
  276. #else
  277.               if (c=='f')
  278. #endif
  279.             {
  280.               /*
  281.                * Forward reference. Expect symbol to be undefined or
  282.                * unknown. Undefined: seen it before. Unknown: never seen
  283.                * it in this pass.
  284.                * Construct a local label name, then an undefined symbol.
  285.                * Don't create a XSEG frag for it: caller may do that.
  286.                * Just return it as never seen before.
  287.                */
  288.               name = local_label_name ((int)number, 1);
  289.               if ( symbolP = symbol_table_lookup( name ))
  290.                 {
  291.                   /* We have no need to check symbol properties. */
  292.                   know(   (symbolP -> sy_type & N_TYPE) == N_UNDF
  293.                    || (symbolP -> sy_type & N_TYPE) == N_DATA
  294.                    || (symbolP -> sy_type & N_TYPE) == N_TEXT);
  295.                 }
  296.               else
  297.                 {
  298.                   symbolP = symbol_new (name, N_UNDF, 0,0,0, & zero_address_frag);
  299.                   symbol_table_insert (symbolP);
  300.                 }
  301.               expressionP -> X_add_symbol      = symbolP;
  302.               expressionP -> X_seg             = SEG_UNKNOWN;
  303.               expressionP -> X_subtract_symbol = NULL;
  304.               expressionP -> X_add_number      = 0;
  305.             }
  306.               else
  307.             {        /* Really a number, not a local label. */
  308.               expressionP -> X_add_number = number;
  309.               expressionP -> X_seg        = SEG_ABSOLUTE;
  310.               input_line_pointer --; /* Restore following character. */
  311.             }        /* if (c=='f') */
  312.             }            /* if (c=='b') */
  313.         }
  314.           else
  315.         {            /* Really a number. */
  316.           expressionP -> X_add_number = number;
  317.           expressionP -> X_seg        = SEG_ABSOLUTE;
  318.           input_line_pointer --; /* Restore following character. */
  319.         }            /* if (number<10) */
  320.         }
  321.       else
  322.         {
  323.           expressionP -> X_add_number = number;
  324.           expressionP -> X_seg = SEG_BIG;
  325.           input_line_pointer --; /* -> char following number. */
  326.         }            /* if (small) */
  327.     }            /* (If integer constant) */
  328.       else
  329.     {            /* input_line_pointer -> */
  330.                 /* floating-point constant. */
  331.       int error_code;
  332.  
  333.       error_code = atof_generic
  334.         (& input_line_pointer, ".", EXP_CHARS,
  335.          & generic_floating_point_number);
  336.  
  337.       if (error_code)
  338.         {
  339.           if (error_code == ERROR_EXPONENT_OVERFLOW)
  340.         {
  341.           as_warn( "Bad floating-point constant: exponent overflow, probably assembling junk" );
  342.         }
  343.           else
  344.         {          
  345.           as_warn( "Bad floating-point constant: unknown error code=%d.", error_code);
  346.         }
  347.         }
  348.       expressionP -> X_seg = SEG_BIG;
  349.                 /* input_line_pointer -> just after constant, */
  350.                 /* which may point to whitespace. */
  351.       know( expressionP -> X_add_number < 0 ); /* < 0 means "floating point". */
  352.     }            /* if (not floating-point constant) */
  353.     }
  354.   else if(c=='.' && !is_part_of_name(*input_line_pointer)) {
  355.     extern struct obstack frags;
  356.  
  357.     /*
  358.        JF:  '.' is pseudo symbol with value of current location in current
  359.        segment. . .
  360.      */
  361.     symbolP = symbol_new("L0\001",
  362.              (unsigned char)(seg_N_TYPE[(int)now_seg]),
  363.              0,
  364.              0,
  365.              (valueT)(obstack_next_free(&frags)-frag_now->fr_literal),
  366.              frag_now);
  367.     expressionP->X_add_number=0;
  368.     expressionP->X_add_symbol=symbolP;
  369.     expressionP->X_seg = now_seg;
  370.  
  371.   } else if ( is_name_beginner(c) ) /* here if did not begin with a digit */
  372.     {
  373.       /*
  374.        * Identifier begins here.
  375.        * This is kludged for speed, so code is repeated.
  376.        */
  377.       name =  -- input_line_pointer;
  378.       c = get_symbol_end();
  379.       symbolP = symbol_table_lookup(name);
  380.       if (symbolP)
  381.         {
  382.           /*
  383.            * If we have an absolute symbol, then we know it's value now.
  384.            */
  385.           register segT        seg;
  386.  
  387.           seg = N_TYPE_seg [(int) symbolP -> sy_type & N_TYPE];
  388.           if ((expressionP -> X_seg = seg) == SEG_ABSOLUTE )
  389.         {
  390.           expressionP -> X_add_number = symbolP -> sy_value;
  391.         }
  392.       else
  393.         {
  394.           expressionP -> X_add_number  = 0;
  395.           expressionP -> X_add_symbol  = symbolP;
  396.         }
  397.     }
  398.       else
  399.     {
  400.       expressionP -> X_add_symbol
  401.         = symbolP
  402.         = symbol_new (name, N_UNDF, 0,0,0, & zero_address_frag);
  403.  
  404.       expressionP -> X_add_number  = 0;
  405.       expressionP -> X_seg         = SEG_UNKNOWN;
  406.       symbol_table_insert (symbolP);
  407.     }
  408.       * input_line_pointer = c;
  409.       expressionP -> X_subtract_symbol = NULL;
  410.     }
  411.   else if (c=='(')/* didn't begin with digit & not a name */
  412.     {
  413.       (void)expression( expressionP );
  414.       /* Expression() will pass trailing whitespace */
  415.       if ( * input_line_pointer ++ != ')' )
  416.     {
  417.       as_warn( "Missing ')' assumed");
  418.       input_line_pointer --;
  419.     }
  420.       /* here with input_line_pointer -> char after "(...)" */
  421.     }
  422.   else if ( c=='~' || c=='-' )
  423.     {        /* unary operator: hope for SEG_ABSOLUTE */
  424.       switch(operand (expressionP)) {
  425.       case SEG_ABSOLUTE:
  426.             /* input_line_pointer -> char after operand */
  427.     if ( c=='-' )
  428.       {
  429.         expressionP -> X_add_number = - expressionP -> X_add_number;
  430. /*
  431.  * Notice: '-' may  overflow: no warning is given. This is compatible
  432.  * with other people's assemblers. Sigh.
  433.  */
  434.       }
  435.     else
  436.       {
  437.         expressionP -> X_add_number = ~ expressionP -> X_add_number;
  438.       }
  439.       break;
  440.  
  441.       case SEG_TEXT:
  442.       case SEG_DATA:
  443.       case SEG_BSS:
  444.       case SEG_PASS1:
  445.       case SEG_UNKNOWN:
  446.     if(c=='-') {        /* JF I hope this hack works */
  447.       expressionP->X_subtract_symbol=expressionP->X_add_symbol;
  448.       expressionP->X_add_symbol=0;
  449.       expressionP->X_seg=SEG_DIFFERENCE;
  450.       break;
  451.     }
  452.       default:        /* unary on non-absolute is unsuported */
  453.     as_warn("Unary operator %c ignored because bad operand follows", c);
  454.     break;
  455.     /* Expression undisturbed from operand(). */
  456.       }
  457.     }
  458.   else if (c=='\'')
  459.     {
  460. /*
  461.  * Warning: to conform to other people's assemblers NO ESCAPEMENT is permitted
  462.  * for a single quote. The next character, parity errors and all, is taken
  463.  * as the value of the operand. VERY KINKY.
  464.  */
  465.       expressionP -> X_add_number = * input_line_pointer ++;
  466.       expressionP -> X_seg        = SEG_ABSOLUTE;
  467.     }
  468.   else
  469.     {
  470.               /* can't imagine any other kind of operand */
  471.       expressionP -> X_seg = SEG_NONE;
  472.       input_line_pointer --;
  473.     }
  474. /*
  475.  * It is more 'efficient' to clean up the expressions when they are created.
  476.  * Doing it here saves lines of code.
  477.  */
  478.   clean_up_expression (expressionP);
  479.   SKIP_WHITESPACE();        /* -> 1st char after operand. */
  480.   know( * input_line_pointer != ' ' );
  481.   return (expressionP -> X_seg);
  482. }                /* operand */
  483.  
  484. /* Internal. Simplify a struct expression for use by expr() */
  485.  
  486. /*
  487.  * In:    address of a expressionS.
  488.  *    The X_seg field of the expressionS may only take certain values.
  489.  *    Now, we permit SEG_PASS1 to make code smaller & faster.
  490.  *    Elsewise we waste time special-case testing. Sigh. Ditto SEG_NONE.
  491.  * Out:    expressionS may have been modified:
  492.  *    'foo-foo' symbol references cancelled to 0,
  493.  *        which changes X_seg from SEG_DIFFERENCE to SEG_ABSOLUTE;
  494.  *    Unused fields zeroed to help expr().
  495.  */
  496.  
  497. static void
  498. clean_up_expression (expressionP)
  499.      register expressionS * expressionP;
  500. {
  501.   switch (expressionP -> X_seg)
  502.     {
  503.     case SEG_NONE:
  504.     case SEG_PASS1:
  505.       expressionP -> X_add_symbol    = NULL;
  506.       expressionP -> X_subtract_symbol    = NULL;
  507.       expressionP -> X_add_number    = 0;
  508.       break;
  509.  
  510.     case SEG_BIG:
  511.     case SEG_ABSOLUTE:
  512.       expressionP -> X_subtract_symbol    = NULL;
  513.       expressionP -> X_add_symbol    = NULL;
  514.       break;
  515.  
  516.     case SEG_TEXT:
  517.     case SEG_DATA:
  518.     case SEG_BSS:
  519.     case SEG_UNKNOWN:
  520.       expressionP -> X_subtract_symbol    = NULL;
  521.       break;
  522.  
  523.     case SEG_DIFFERENCE:
  524.       /*
  525.        * It does not hurt to 'cancel' NULL==NULL
  526.        * when comparing symbols for 'eq'ness.
  527.        * It is faster to re-cancel them to NULL
  528.        * than to check for this special case.
  529.        */
  530.       if (expressionP -> X_subtract_symbol == expressionP -> X_add_symbol)
  531.     {
  532.       expressionP -> X_subtract_symbol    = NULL;
  533.       expressionP -> X_add_symbol        = NULL;
  534.       expressionP -> X_seg            = SEG_ABSOLUTE;
  535.     }
  536.       break;
  537.  
  538.     default:
  539.       BAD_CASE( expressionP -> X_seg);
  540.       break;
  541.     }
  542. }
  543.  
  544. /*
  545.  *            expr_part ()
  546.  *
  547.  * Internal. Made a function because this code is used in 2 places.
  548.  * Generate error or correct X_?????_symbol of expressionS.
  549.  */
  550.  
  551. /*
  552.  * symbol_1 += symbol_2 ... well ... sort of.
  553.  */
  554.  
  555. static segT
  556. expr_part (symbol_1_PP, symbol_2_P)
  557.      struct symbol **    symbol_1_PP;
  558.      struct symbol *    symbol_2_P;
  559. {
  560.   segT            return_value;
  561.  
  562.   know(    (* symbol_1_PP)                   == NULL
  563.        || ((* symbol_1_PP) -> sy_type & N_TYPE) == N_TEXT
  564.        || ((* symbol_1_PP) -> sy_type & N_TYPE) == N_DATA
  565.        || ((* symbol_1_PP) -> sy_type & N_TYPE) == N_BSS
  566.        || ((* symbol_1_PP) -> sy_type & N_TYPE) == N_UNDF
  567.        );
  568.   know(      symbol_2_P             == NULL
  569.        ||    (symbol_2_P   -> sy_type & N_TYPE) == N_TEXT
  570.        ||    (symbol_2_P   -> sy_type & N_TYPE) == N_DATA
  571.        ||    (symbol_2_P   -> sy_type & N_TYPE) == N_BSS
  572.        ||    (symbol_2_P   -> sy_type & N_TYPE) == N_UNDF
  573.        );
  574.   if (* symbol_1_PP)
  575.     {
  576.       if (((* symbol_1_PP) -> sy_type & N_TYPE) == N_UNDF)
  577.     {
  578.       if (symbol_2_P)
  579.         {
  580.           return_value = SEG_PASS1;
  581.           * symbol_1_PP = NULL;
  582.         }
  583.       else
  584.         {
  585.           know( ((* symbol_1_PP) -> sy_type & N_TYPE) == N_UNDF)
  586.           return_value = SEG_UNKNOWN;
  587.         }
  588.     }
  589.       else
  590.     {
  591.       if (symbol_2_P)
  592.         {
  593.           if ((symbol_2_P -> sy_type & N_TYPE) == N_UNDF)
  594.         {
  595.           * symbol_1_PP = NULL;
  596.           return_value = SEG_PASS1;
  597.         }
  598.           else
  599.         {
  600.           /* {seg1} - {seg2} */
  601.           as_warn( "Expression too complex, 2 symbols forgotten: \"%s\" \"%s\"",
  602.               (* symbol_1_PP) -> sy_name, symbol_2_P -> sy_name );
  603.           * symbol_1_PP = NULL;
  604.           return_value = SEG_ABSOLUTE;
  605.         }
  606.         }
  607.       else
  608.         {
  609.           return_value = N_TYPE_seg [(* symbol_1_PP) -> sy_type & N_TYPE];
  610.         }
  611.     }
  612.     }
  613.   else
  614.     {                /* (* symbol_1_PP) == NULL */
  615.       if (symbol_2_P)
  616.     {
  617.       * symbol_1_PP = symbol_2_P;
  618.       return_value = N_TYPE_seg [(symbol_2_P) -> sy_type & N_TYPE];
  619.     }
  620.       else
  621.     {
  622.       * symbol_1_PP = NULL;
  623.       return_value = SEG_ABSOLUTE;
  624.     }
  625.     }
  626.   know(   return_value == SEG_ABSOLUTE            
  627.        || return_value == SEG_TEXT            
  628.        || return_value == SEG_DATA            
  629.        || return_value == SEG_BSS            
  630.        || return_value == SEG_UNKNOWN            
  631.        || return_value == SEG_PASS1            
  632.        );
  633.   know(   (* symbol_1_PP) == NULL                
  634.        || ((* symbol_1_PP) -> sy_type & N_TYPE) == seg_N_TYPE [(int) return_value] );
  635.   return (return_value);
  636. }                /* expr_part() */
  637.  
  638. /* Expression parser. */
  639.  
  640. /*
  641.  * We allow an empty expression, and just assume (absolute,0) silently.
  642.  * Unary operators and parenthetical expressions are treated as operands.
  643.  * As usual, Q==quantity==operand, O==operator, X==expression mnemonics.
  644.  *
  645.  * We used to do a aho/ullman shift-reduce parser, but the logic got so
  646.  * warped that I flushed it and wrote a recursive-descent parser instead.
  647.  * Now things are stable, would anybody like to write a fast parser?
  648.  * Most expressions are either register (which does not even reach here)
  649.  * or 1 symbol. Then "symbol+constant" and "symbol-symbol" are common.
  650.  * So I guess it doesn't really matter how inefficient more complex expressions
  651.  * are parsed.
  652.  *
  653.  * After expr(RANK,resultP) input_line_pointer -> operator of rank <= RANK.
  654.  * Also, we have consumed any leading or trailing spaces (operand does that)
  655.  * and done all intervening operators.
  656.  */
  657.  
  658. typedef enum
  659. {
  660. O_illegal,            /* (0)  what we get for illegal op */
  661.  
  662. O_multiply,            /* (1)  * */
  663. O_divide,            /* (2)  / */
  664. O_modulus,            /* (3)  % */
  665. O_left_shift,            /* (4)  < */
  666. O_right_shift,            /* (5)  > */
  667. O_bit_inclusive_or,        /* (6)  | */
  668. O_bit_or_not,            /* (7)  ! */
  669. O_bit_exclusive_or,        /* (8)  ^ */
  670. O_bit_and,            /* (9)  & */
  671. O_add,                /* (10) + */
  672. O_subtract            /* (11) - */
  673. }
  674. operatorT;
  675.  
  676. #define __ O_illegal
  677.  
  678. static const operatorT op_encoding [256] = {    /* maps ASCII -> operators */
  679.  
  680. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  681. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  682.  
  683. __, O_bit_or_not, __, __, __, O_modulus, O_bit_and, __,
  684. __, __, O_multiply, O_add, __, O_subtract, __, O_divide,
  685. __, __, __, __, __, __, __, __,
  686. __, __, __, __, O_left_shift, __, O_right_shift, __,
  687. __, __, __, __, __, __, __, __,
  688. __, __, __, __, __, __, __, __,
  689. __, __, __, __, __, __, __, __,
  690. __, __, __, __, __, __, O_bit_exclusive_or, __,
  691. __, __, __, __, __, __, __, __,
  692. __, __, __, __, __, __, __, __,
  693. __, __, __, __, __, __, __, __,
  694. __, __, __, __, O_bit_inclusive_or, __, __, __,
  695.  
  696. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  697. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  698. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  699. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  700. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  701. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  702. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  703. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __
  704. };
  705.  
  706.  
  707. /*
  708.  *    Rank    Examples
  709.  *    0    operand, (expression)
  710.  *    1    + -
  711.  *    2    & ^ ! |
  712.  *    3    * / % < >
  713.  */
  714. typedef char operator_rankT;
  715. static const operator_rankT
  716. op_rank [] = { 0, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1 };
  717.  
  718. segT                /* Return resultP -> X_seg. */
  719. expr (rank, resultP)
  720.      register operator_rankT    rank; /* Larger # is higher rank. */
  721.      register expressionS *    resultP; /* Deliver result here. */
  722. {
  723.   expressionS        right;
  724.   register operatorT    op_left;
  725.   register char        c_left;    /* 1st operator character. */
  726.   register operatorT    op_right;
  727.   register char        c_right;
  728.  
  729.   know( rank >= 0 );
  730.   (void)operand (resultP);
  731.   know( * input_line_pointer != ' ' ); /* Operand() gobbles spaces. */
  732.   c_left = * input_line_pointer; /* Potential operator character. */
  733.   op_left = op_encoding [c_left];
  734.   while (op_left != O_illegal && op_rank [(int) op_left] > rank)
  735.     {
  736.       input_line_pointer ++;    /* -> after 1st character of operator. */
  737.                 /* Operators "<<" and ">>" have 2 characters. */
  738.       if (* input_line_pointer == c_left && (c_left == '<' || c_left == '>') )
  739.     {
  740.       input_line_pointer ++;
  741.     }            /* -> after operator. */
  742.       if (SEG_NONE == expr (op_rank[(int) op_left], &right))
  743.     {
  744.       as_warn("Missing operand value assumed absolute 0.");
  745.       resultP -> X_add_number    = 0;
  746.       resultP -> X_subtract_symbol    = NULL;
  747.       resultP -> X_add_symbol    = NULL;
  748.       resultP -> X_seg = SEG_ABSOLUTE;
  749.     }
  750.       know( * input_line_pointer != ' ' );
  751.       c_right = * input_line_pointer;
  752.       op_right = op_encoding [c_right];
  753.       if (* input_line_pointer == c_right && (c_right == '<' || c_right == '>') )
  754.     {
  755.       input_line_pointer ++;
  756.     }            /* -> after operator. */
  757.       know(   (int) op_right == 0
  758.        || op_rank [(int) op_right] <= op_rank[(int) op_left] );
  759.       /* input_line_pointer -> after right-hand quantity. */
  760.       /* left-hand quantity in resultP */
  761.       /* right-hand quantity in right. */
  762.       /* operator in op_left. */
  763.       if ( resultP -> X_seg == SEG_PASS1 || right . X_seg == SEG_PASS1 )
  764.     {
  765.       resultP -> X_seg = SEG_PASS1;
  766.     }
  767.       else
  768.     {
  769.       if ( resultP -> X_seg == SEG_BIG )
  770.         {
  771.           as_warn( "Left operand of %c is a %s.  Integer 0 assumed.",
  772.               c_left, resultP -> X_add_number > 0 ? "bignum" : "float");
  773.           resultP -> X_seg = SEG_ABSOLUTE;
  774.           resultP -> X_add_symbol = 0;
  775.           resultP -> X_subtract_symbol = 0;
  776.           resultP -> X_add_number = 0;
  777.         }
  778.       if ( right . X_seg == SEG_BIG )
  779.         {
  780.           as_warn( "Right operand of %c is a %s.  Integer 0 assumed.",
  781.               c_left, right . X_add_number > 0 ? "bignum" : "float");
  782.           right . X_seg = SEG_ABSOLUTE;
  783.           right . X_add_symbol = 0;
  784.           right . X_subtract_symbol = 0;
  785.           right . X_add_number = 0;
  786.         }
  787.       if ( op_left == O_subtract )
  788.         {
  789.           /*
  790.            * Convert - into + by exchanging symbols and negating number.
  791.            * I know -infinity can't be negated in 2's complement:
  792.            * but then it can't be subtracted either. This trick
  793.            * does not cause any further inaccuracy.
  794.            */
  795.  
  796.           register struct symbol *    symbolP;
  797.  
  798.           right . X_add_number      = - right . X_add_number;
  799.           symbolP                   = right . X_add_symbol;
  800.           right . X_add_symbol    = right . X_subtract_symbol;
  801.           right . X_subtract_symbol = symbolP;
  802.           if (symbolP)
  803.         {
  804.           right . X_seg        = SEG_DIFFERENCE;
  805.         }
  806.           op_left = O_add;
  807.         }
  808.  
  809.       if ( op_left == O_add )
  810.         {
  811.           segT    seg1;
  812.           segT    seg2;
  813.           
  814.           know(   resultP -> X_seg == SEG_DATA        
  815.            || resultP -> X_seg == SEG_TEXT        
  816.            || resultP -> X_seg == SEG_BSS        
  817.            || resultP -> X_seg == SEG_UNKNOWN        
  818.            || resultP -> X_seg == SEG_DIFFERENCE    
  819.            || resultP -> X_seg == SEG_ABSOLUTE        
  820.            || resultP -> X_seg == SEG_PASS1        
  821.            );
  822.           know(     right .  X_seg == SEG_DATA        
  823.            ||   right .  X_seg == SEG_TEXT        
  824.            ||   right .  X_seg == SEG_BSS        
  825.            ||   right .  X_seg == SEG_UNKNOWN        
  826.            ||   right .  X_seg == SEG_DIFFERENCE    
  827.            ||   right .  X_seg == SEG_ABSOLUTE        
  828.            ||   right .  X_seg == SEG_PASS1        
  829.            );
  830.           
  831.           clean_up_expression (& right);
  832.           clean_up_expression (resultP);
  833.  
  834.           seg1 = expr_part (& resultP -> X_add_symbol, right . X_add_symbol);
  835.           seg2 = expr_part (& resultP -> X_subtract_symbol, right . X_subtract_symbol);
  836.           if (seg1 == SEG_PASS1 || seg2 == SEG_PASS1) {
  837.           need_pass_2 = TRUE;
  838.           resultP -> X_seg = SEG_PASS1;
  839.           } else if (seg2 == SEG_ABSOLUTE)
  840.           resultP -> X_seg = seg1;
  841.           else if (   seg1 != SEG_UNKNOWN
  842.             && seg1 != SEG_ABSOLUTE
  843.             && seg2 != SEG_UNKNOWN
  844.             && seg1 != seg2) {
  845.           know( seg2 != SEG_ABSOLUTE );
  846.           know( resultP -> X_subtract_symbol );
  847.  
  848.           know( seg1 == SEG_TEXT || seg1 == SEG_DATA || seg1== SEG_BSS );
  849.           know( seg2 == SEG_TEXT || seg2 == SEG_DATA || seg2== SEG_BSS );
  850.           know( resultP -> X_add_symbol      );
  851.           know( resultP -> X_subtract_symbol );
  852.           as_warn("Expression too complex: forgetting %s - %s",
  853.               resultP -> X_add_symbol      -> sy_name,
  854.               resultP -> X_subtract_symbol -> sy_name);
  855.           resultP -> X_seg = SEG_ABSOLUTE;
  856.           /* Clean_up_expression() will do the rest. */
  857.         } else
  858.           resultP -> X_seg = SEG_DIFFERENCE;
  859.  
  860.           resultP -> X_add_number += right . X_add_number;
  861.           clean_up_expression (resultP);
  862.         }
  863.       else
  864.         {            /* Not +. */
  865.           if ( resultP -> X_seg == SEG_UNKNOWN || right . X_seg == SEG_UNKNOWN )
  866.         {
  867.           resultP -> X_seg = SEG_PASS1;
  868.           need_pass_2 = TRUE;
  869.         }
  870.           else
  871.         {
  872.           resultP -> X_subtract_symbol = NULL;
  873.           resultP -> X_add_symbol = NULL;
  874.           /* Will be SEG_ABSOLUTE. */
  875.           if ( resultP -> X_seg != SEG_ABSOLUTE || right . X_seg != SEG_ABSOLUTE )
  876.             {
  877.               as_warn( "Relocation error. Absolute 0 assumed.");
  878.               resultP -> X_seg        = SEG_ABSOLUTE;
  879.               resultP -> X_add_number = 0;
  880.             }
  881.           else
  882.             {
  883.               switch ( op_left )
  884.             {
  885.             case O_bit_inclusive_or:
  886.               resultP -> X_add_number |= right . X_add_number;
  887.               break;
  888.               
  889.             case O_modulus:
  890.               if (right . X_add_number)
  891.                 {
  892.                   resultP -> X_add_number %= right . X_add_number;
  893.                 }
  894.               else
  895.                 {
  896.                   as_warn( "Division by 0. 0 assumed." );
  897.                   resultP -> X_add_number = 0;
  898.                 }
  899.               break;
  900.               
  901.             case O_bit_and:
  902.               resultP -> X_add_number &= right . X_add_number;
  903.               break;
  904.               
  905.             case O_multiply:
  906.               resultP -> X_add_number *= right . X_add_number;
  907.               break;
  908.               
  909.             case O_divide:
  910.               if (right . X_add_number)
  911.                 {
  912.                   resultP -> X_add_number /= right . X_add_number;
  913.                 }
  914.               else
  915.                 {
  916.                   as_warn( "Division by 0. 0 assumed." );
  917.                   resultP -> X_add_number = 0;
  918.                 }
  919.               break;
  920.               
  921.             case O_left_shift:
  922.               resultP -> X_add_number <<= right . X_add_number;
  923.               break;
  924.               
  925.             case O_right_shift:
  926.               resultP -> X_add_number >>= right . X_add_number;
  927.               break;
  928.               
  929.             case O_bit_exclusive_or:
  930.               resultP -> X_add_number ^= right . X_add_number;
  931.               break;
  932.               
  933.             case O_bit_or_not:
  934.               resultP -> X_add_number |= ~ right . X_add_number;
  935.               break;
  936.               
  937.             default:
  938.               BAD_CASE( op_left );
  939.               break;
  940.             } /* switch(operator) */
  941.             }
  942.         }        /* If we have to force need_pass_2. */
  943.         }            /* If operator was +. */
  944.     }            /* If we didn't set need_pass_2. */
  945.       op_left = op_right;
  946.     }                /* While next operator is >= this rank. */
  947.   return (resultP -> X_seg);
  948. }
  949.  
  950. /*
  951.  *            get_symbol_end()
  952.  *
  953.  * This lives here because it belongs equally in expr.c & read.c.
  954.  * Expr.c is just a branch office read.c anyway, and putting it
  955.  * here lessens the crowd at read.c.
  956.  *
  957.  * Assume input_line_pointer is at start of symbol name.
  958.  * Advance input_line_pointer past symbol name.
  959.  * Turn that character into a '\0', returning its former value.
  960.  * This allows a string compare (RMS wants symbol names to be strings)
  961.  * of the symbol name.
  962.  * There will always be a char following symbol name, because all good
  963.  * lines end in end-of-line.
  964.  */
  965. char
  966. get_symbol_end()
  967. {
  968.   register char c;
  969.  
  970.   while ( is_part_of_name( c = * input_line_pointer ++ ) )
  971.     ;
  972.   * -- input_line_pointer = 0;
  973.   return (c);
  974. }
  975.  
  976. /* end: expr.c */
  977.