1 /* expr.c -operands, expressions-
2 Copyright (C) 1987, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
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 2, or (at your option)
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.
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. */
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.
34 static void clean_up_expression
PARAMS ((expressionS
* expressionP
));
35 extern const char EXP_CHARS
[], FLT_CHARS
[];
38 * Build any floating-point literal here.
39 * Also build any bignum literal here.
42 /* Seems atof_machine can backscan through generic_bignum and hit whatever
43 happens to be loaded before it in memory. And its way too complicated
44 for me to fix right. Thus a hack. JF: Just make generic_bignum bigger,
45 and never write into the early words, thus they'll always be zero.
46 I hate Dean's floating-point code. Bleh. */
47 LITTLENUM_TYPE generic_bignum
[SIZE_OF_LARGE_NUMBER
+ 6];
48 FLONUM_TYPE generic_floating_point_number
=
50 &generic_bignum
[6], /* low (JF: Was 0) */
51 &generic_bignum
[SIZE_OF_LARGE_NUMBER
+ 6 - 1], /* high JF: (added +6) */
56 /* If nonzero, we've been asked to assemble nan, +inf or -inf */
57 int generic_floating_point_magic
;
60 floating_constant (expressionP
)
61 expressionS
*expressionP
;
63 /* input_line_pointer->*/
64 /* floating-point constant. */
67 error_code
= atof_generic
68 (&input_line_pointer
, ".", EXP_CHARS
,
69 &generic_floating_point_number
);
73 if (error_code
== ERROR_EXPONENT_OVERFLOW
)
75 as_bad ("bad floating-point constant: exponent overflow, probably assembling junk");
79 as_bad ("bad floating-point constant: unknown error code=%d.", error_code
);
82 expressionP
->X_seg
= big_section
;
83 /* input_line_pointer->just after constant, */
84 /* which may point to whitespace. */
85 expressionP
->X_add_number
= -1;
90 integer_constant (radix
, expressionP
)
92 expressionS
*expressionP
;
94 char *digit_2
; /*->2nd digit of number. */
97 valueT number
; /* offset or (absolute) value */
98 short int digit
; /* value of next digit in current radix */
99 short int maxdig
= 0;/* highest permitted digit value. */
100 int too_many_digits
= 0; /* if we see >= this number of */
101 char *name
; /* points to name of symbol */
102 symbolS
*symbolP
; /* points to symbol */
104 int small
; /* true if fits in 32 bits. */
105 extern const char hex_value
[]; /* in hex_value.c */
107 /* May be bignum, or may fit in 32 bits. */
108 /* Most numbers fit into 32 bits, and we want this case to be fast.
109 so we pretend it will fit into 32 bits. If, after making up a 32
110 bit number, we realise that we have scanned more digits than
111 comfortably fit into 32 bits, we re-scan the digits coding them
112 into a bignum. For decimal and octal numbers we are
113 conservative: Some numbers may be assumed bignums when in fact
114 they do fit into 32 bits. Numbers of any radix can have excess
115 leading zeros: We strive to recognise this and cast them back
116 into 32 bits. We must check that the bignum really is more than
117 32 bits, and change it back to a 32-bit number if it fits. The
118 number we are looking for is expected to be positive, but if it
119 fits into 32 bits as an unsigned number, we let it be a 32-bit
120 number. The cavalier approach is for speed in ordinary cases. */
127 too_many_digits
= 33;
131 too_many_digits
= 11;
141 too_many_digits
= 11;
143 c
= *input_line_pointer
;
144 input_line_pointer
++;
145 digit_2
= input_line_pointer
;
146 for (number
= 0; (digit
= hex_value
[c
]) < maxdig
; c
= *input_line_pointer
++)
148 number
= number
* radix
+ digit
;
150 /* c contains character after number. */
151 /* input_line_pointer->char after c. */
152 small
= input_line_pointer
- digit_2
< too_many_digits
;
156 * we saw a lot of digits. manufacture a bignum the hard way.
158 LITTLENUM_TYPE
*leader
; /*->high order littlenum of the bignum. */
159 LITTLENUM_TYPE
*pointer
; /*->littlenum we are frobbing now. */
162 leader
= generic_bignum
;
163 generic_bignum
[0] = 0;
164 generic_bignum
[1] = 0;
165 /* we could just use digit_2, but lets be mnemonic. */
166 input_line_pointer
= --digit_2
; /*->1st digit. */
167 c
= *input_line_pointer
++;
168 for (; (carry
= hex_value
[c
]) < maxdig
; c
= *input_line_pointer
++)
170 for (pointer
= generic_bignum
;
176 work
= carry
+ radix
* *pointer
;
177 *pointer
= work
& LITTLENUM_MASK
;
178 carry
= work
>> LITTLENUM_NUMBER_OF_BITS
;
182 if (leader
< generic_bignum
+ SIZE_OF_LARGE_NUMBER
- 1)
183 { /* room to grow a longer bignum. */
188 /* again, c is char after number, */
189 /* input_line_pointer->after c. */
190 know (sizeof (int) * 8 == 32);
191 know (LITTLENUM_NUMBER_OF_BITS
== 16);
192 /* hence the constant "2" in the next line. */
193 if (leader
< generic_bignum
+ 2)
194 { /* will fit into 32 bits. */
196 ((generic_bignum
[1] & LITTLENUM_MASK
) << LITTLENUM_NUMBER_OF_BITS
)
197 | (generic_bignum
[0] & LITTLENUM_MASK
);
202 number
= leader
- generic_bignum
+ 1; /* number of littlenums in the bignum. */
208 * here with number, in correct radix. c is the next char.
209 * note that unlike un*x, we allow "011f" "0x9f" to
210 * both mean the same as the (conventional) "9f". this is simply easier
211 * than checking for strict canonical form. syntax sux!
217 #ifdef LOCAL_LABELS_FB
221 * backward ref to local label.
222 * because it is backward, expect it to be defined.
224 /* Construct a local label. */
225 name
= fb_label_name ((int) number
, 0);
227 /* seen before, or symbol is defined: ok */
228 symbolP
= symbol_find (name
);
229 if ((symbolP
!= NULL
) && (S_IS_DEFINED (symbolP
)))
232 /* local labels are never absolute. don't waste time
233 checking absoluteness. */
234 know (SEG_NORMAL (S_GET_SEGMENT (symbolP
)));
236 expressionP
->X_add_symbol
= symbolP
;
237 expressionP
->X_seg
= S_GET_SEGMENT (symbolP
);
242 /* either not seen or not defined. */
243 /* @@ Should print out the original string instead of
244 the parsed number. */
245 as_bad ("backw. ref to unknown label \"%d:\", 0 assumed.",
247 expressionP
->X_seg
= absolute_section
;
250 expressionP
->X_add_number
= 0;
257 * forward reference. expect symbol to be undefined or
258 * unknown. undefined: seen it before. unknown: never seen
260 * construct a local label name, then an undefined symbol.
261 * don't create a xseg frag for it: caller may do that.
262 * just return it as never seen before.
264 name
= fb_label_name ((int) number
, 1);
265 symbolP
= symbol_find_or_make (name
);
266 /* we have no need to check symbol properties. */
267 #ifndef many_segments
268 /* since "know" puts its arg into a "string", we
269 can't have newlines in the argument. */
270 know (S_GET_SEGMENT (symbolP
) == undefined_section
|| S_GET_SEGMENT (symbolP
) == text_section
|| S_GET_SEGMENT (symbolP
) == data_section
);
272 expressionP
->X_add_symbol
= symbolP
;
273 expressionP
->X_seg
= undefined_section
;
274 expressionP
->X_subtract_symbol
= NULL
;
275 expressionP
->X_add_number
= 0;
280 #endif /* LOCAL_LABELS_FB */
282 #ifdef LOCAL_LABELS_DOLLAR
287 /* If the dollar label is *currently* defined, then this is just
288 another reference to it. If it is not *currently* defined,
289 then this is a fresh instantiation of that number, so create
292 if (dollar_label_defined (number
))
294 name
= dollar_label_name (number
, 0);
295 symbolP
= symbol_find (name
);
296 know (symbolP
!= NULL
);
300 name
= dollar_label_name (number
, 1);
301 symbolP
= symbol_find_or_make (name
);
304 expressionP
->X_add_symbol
= symbolP
;
305 expressionP
->X_add_number
= 0;
306 expressionP
->X_seg
= S_GET_SEGMENT (symbolP
);
311 #endif /* LOCAL_LABELS_DOLLAR */
315 expressionP
->X_add_number
= number
;
316 expressionP
->X_seg
= absolute_section
;
317 input_line_pointer
--; /* restore following character. */
319 } /* really just a number */
321 } /* switch on char following the number */
327 /* not a small number */
328 expressionP
->X_add_number
= number
;
329 expressionP
->X_seg
= big_section
;
330 input_line_pointer
--; /*->char following number. */
332 } /* integer_constant() */
336 * Summary of operand().
338 * in: Input_line_pointer points to 1st char of operand, which may
341 * out: A expressionS. X_seg determines how to understand the rest of the
343 * The operand may have been empty: in this case X_seg == SEG_ABSENT.
344 * Input_line_pointer->(next non-blank) char after operand.
351 operand (expressionP
)
352 expressionS
*expressionP
;
355 symbolS
*symbolP
; /* points to symbol */
356 char *name
; /* points to name of symbol */
358 /* digits, assume it is a bignum. */
360 SKIP_WHITESPACE (); /* leading whitespace is part of operand. */
361 c
= *input_line_pointer
++; /* input_line_pointer->past char in c. */
367 integer_constant (2, expressionP
);
370 integer_constant (8, expressionP
);
373 integer_constant (16, expressionP
);
385 input_line_pointer
--;
387 integer_constant (10, expressionP
);
391 /* non-decimal radix */
394 c
= *input_line_pointer
;
399 if (c
&& strchr (FLT_CHARS
, c
))
401 input_line_pointer
++;
402 floating_constant (expressionP
);
406 /* The string was only zero */
407 expressionP
->X_add_symbol
= 0;
408 expressionP
->X_add_number
= 0;
409 expressionP
->X_seg
= absolute_section
;
416 input_line_pointer
++;
417 integer_constant (16, expressionP
);
421 #ifdef LOCAL_LABELS_FB
422 if (!*input_line_pointer
423 || (!strchr ("+-.0123456789", *input_line_pointer
)
424 && !strchr (EXP_CHARS
, *input_line_pointer
)))
426 input_line_pointer
--;
427 integer_constant (10, expressionP
);
432 input_line_pointer
++;
433 integer_constant (2, expressionP
);
444 integer_constant (8, expressionP
);
448 #ifdef LOCAL_LABELS_FB
449 /* if it says '0f' and the line ends or it doesn't look like
450 a floating point #, its a local label ref. dtrt */
451 /* likewise for the b's. xoxorich. */
453 && (!*input_line_pointer
||
454 (!strchr ("+-.0123456789", *input_line_pointer
) &&
455 !strchr (EXP_CHARS
, *input_line_pointer
))))
457 input_line_pointer
-= 1;
458 integer_constant (10, expressionP
);
472 input_line_pointer
++;
473 floating_constant (expressionP
);
474 expressionP
->X_add_number
= -(isupper (c
) ? tolower (c
) : c
);
477 #ifdef LOCAL_LABELS_DOLLAR
479 integer_constant (10, expressionP
);
486 /* didn't begin with digit & not a name */
488 (void) expression (expressionP
);
489 /* Expression() will pass trailing whitespace */
490 if (*input_line_pointer
++ != ')')
492 as_bad ("Missing ')' assumed");
493 input_line_pointer
--;
495 /* here with input_line_pointer->char after "(...)" */
497 return expressionP
->X_seg
;
501 /* Warning: to conform to other people's assemblers NO ESCAPEMENT is
502 permitted for a single quote. The next character, parity errors and
503 all, is taken as the value of the operand. VERY KINKY. */
504 expressionP
->X_add_number
= *input_line_pointer
++;
505 expressionP
->X_seg
= absolute_section
;
509 operand (expressionP
);
515 /* unary operator: hope for SEG_ABSOLUTE */
516 segT opseg
= operand (expressionP
);
517 if (opseg
== absolute_section
)
519 /* input_line_pointer -> char after operand */
522 expressionP
->X_add_number
= -expressionP
->X_add_number
;
523 /* Notice: '-' may overflow: no warning is given. This is
524 compatible with other people's assemblers. Sigh. */
528 expressionP
->X_add_number
= ~expressionP
->X_add_number
;
531 else if (opseg
== text_section
532 || opseg
== data_section
533 || opseg
== bss_section
534 || opseg
== pass1_section
535 || opseg
== undefined_section
)
539 expressionP
->X_subtract_symbol
= expressionP
->X_add_symbol
;
540 expressionP
->X_add_symbol
= 0;
541 expressionP
->X_seg
= diff_section
;
544 as_warn ("Unary operator %c ignored because bad operand follows",
548 as_warn ("Unary operator %c ignored because bad operand follows", c
);
553 if (!is_part_of_name (*input_line_pointer
))
556 extern struct obstack frags
;
558 /* JF: '.' is pseudo symbol with value of current location
559 in current segment. */
560 #ifdef DOT_LABEL_PREFIX
565 symbolP
= symbol_new (fake
,
567 (valueT
) ((char*)obstack_next_free (&frags
) - frag_now
->fr_literal
),
570 expressionP
->X_add_number
= 0;
571 expressionP
->X_add_symbol
= symbolP
;
572 expressionP
->X_seg
= now_seg
;
586 /* can't imagine any other kind of operand */
587 expressionP
->X_seg
= absent_section
;
588 input_line_pointer
--;
589 md_operand (expressionP
);
593 if (is_end_of_line
[c
])
595 if (is_name_beginner (c
)) /* here if did not begin with a digit */
598 * Identifier begins here.
599 * This is kludged for speed, so code is repeated.
602 name
= --input_line_pointer
;
603 c
= get_symbol_end ();
604 symbolP
= symbol_find_or_make (name
);
605 /* If we have an absolute symbol or a reg, then we know its value
607 expressionP
->X_seg
= S_GET_SEGMENT (symbolP
);
608 if (expressionP
->X_seg
== absolute_section
609 || expressionP
->X_seg
== reg_section
)
610 expressionP
->X_add_number
= S_GET_VALUE (symbolP
);
613 expressionP
->X_add_number
= 0;
614 expressionP
->X_add_symbol
= symbolP
;
616 *input_line_pointer
= c
;
617 expressionP
->X_subtract_symbol
= NULL
;
621 as_bad ("Bad expression");
622 expressionP
->X_add_number
= 0;
623 expressionP
->X_seg
= absolute_section
;
628 * It is more 'efficient' to clean up the expressionS when they are created.
629 * Doing it here saves lines of code.
631 clean_up_expression (expressionP
);
632 SKIP_WHITESPACE (); /*->1st char after operand. */
633 know (*input_line_pointer
!= ' ');
634 return (expressionP
->X_seg
);
638 /* Internal. Simplify a struct expression for use by expr() */
641 * In: address of a expressionS.
642 * The X_seg field of the expressionS may only take certain values.
643 * Now, we permit SEG_PASS1 to make code smaller & faster.
644 * Elsewise we waste time special-case testing. Sigh. Ditto SEG_ABSENT.
645 * Out: expressionS may have been modified:
646 * 'foo-foo' symbol references cancelled to 0,
647 * which changes X_seg from SEG_DIFFERENCE to SEG_ABSOLUTE;
648 * Unused fields zeroed to help expr().
652 clean_up_expression (expressionP
)
653 expressionS
*expressionP
;
655 segT s
= expressionP
->X_seg
;
656 if (s
== absent_section
657 || s
== pass1_section
)
659 expressionP
->X_add_symbol
= NULL
;
660 expressionP
->X_subtract_symbol
= NULL
;
661 expressionP
->X_add_number
= 0;
663 else if (s
== big_section
664 || s
== absolute_section
)
666 expressionP
->X_subtract_symbol
= NULL
;
667 expressionP
->X_add_symbol
= NULL
;
669 else if (s
== undefined_section
)
670 expressionP
->X_subtract_symbol
= NULL
;
671 else if (s
== diff_section
)
674 * It does not hurt to 'cancel' NULL==NULL
675 * when comparing symbols for 'eq'ness.
676 * It is faster to re-cancel them to NULL
677 * than to check for this special case.
679 if (expressionP
->X_subtract_symbol
== expressionP
->X_add_symbol
680 || (expressionP
->X_subtract_symbol
681 && expressionP
->X_add_symbol
682 && (expressionP
->X_subtract_symbol
->sy_frag
683 == expressionP
->X_add_symbol
->sy_frag
)
684 && SEG_NORMAL (S_GET_SEGMENT (expressionP
->X_add_symbol
))
685 && (S_GET_VALUE (expressionP
->X_subtract_symbol
)
686 == S_GET_VALUE (expressionP
->X_add_symbol
))))
688 expressionP
->X_subtract_symbol
= NULL
;
689 expressionP
->X_add_symbol
= NULL
;
690 expressionP
->X_seg
= absolute_section
;
693 else if (s
== reg_section
)
695 expressionP
->X_add_symbol
= NULL
;
696 expressionP
->X_subtract_symbol
= NULL
;
700 if (SEG_NORMAL (expressionP
->X_seg
))
702 expressionP
->X_subtract_symbol
= NULL
;
706 BAD_CASE (expressionP
->X_seg
);
714 * Internal. Made a function because this code is used in 2 places.
715 * Generate error or correct X_?????_symbol of expressionS.
719 * symbol_1 += symbol_2 ... well ... sort of.
723 expr_part (symbol_1_PP
, symbol_2_P
)
724 symbolS
**symbol_1_PP
;
729 #if !defined (BFD_ASSEMBLER) && (defined (OBJ_AOUT) || defined (OBJ_BOUT))
730 int test
= ((*symbol_1_PP
) == NULL
731 || (S_GET_SEGMENT (*symbol_1_PP
) == text_section
)
732 || (S_GET_SEGMENT (*symbol_1_PP
) == data_section
)
733 || (S_GET_SEGMENT (*symbol_1_PP
) == bss_section
)
734 || (!S_IS_DEFINED (*symbol_1_PP
)));
736 test
= (symbol_2_P
== NULL
737 || (S_GET_SEGMENT (symbol_2_P
) == text_section
)
738 || (S_GET_SEGMENT (symbol_2_P
) == data_section
)
739 || (S_GET_SEGMENT (symbol_2_P
) == bss_section
)
740 || (!S_IS_DEFINED (symbol_2_P
)));
745 if (!S_IS_DEFINED (*symbol_1_PP
))
749 return_value
= pass1_section
;
754 know (!S_IS_DEFINED (*symbol_1_PP
));
755 return_value
= undefined_section
;
762 if (!S_IS_DEFINED (symbol_2_P
))
765 return_value
= pass1_section
;
769 /* {seg1} - {seg2} */
770 as_bad ("Expression too complex, 2 symbolS forgotten: \"%s\" \"%s\"",
771 S_GET_NAME (*symbol_1_PP
), S_GET_NAME (symbol_2_P
));
773 return_value
= absolute_section
;
778 return_value
= S_GET_SEGMENT (*symbol_1_PP
);
783 { /* (* symbol_1_PP) == NULL */
786 *symbol_1_PP
= symbol_2_P
;
787 return_value
= S_GET_SEGMENT (symbol_2_P
);
792 return_value
= absolute_section
;
795 #if defined (OBJ_AOUT) && !defined (BFD_ASSEMBLER)
796 test
= (return_value
== absolute_section
797 || return_value
== text_section
798 || return_value
== data_section
799 || return_value
== bss_section
800 || return_value
== undefined_section
801 || return_value
== pass1_section
);
804 know ((*symbol_1_PP
) == NULL
805 || (S_GET_SEGMENT (*symbol_1_PP
) == return_value
));
806 return (return_value
);
809 /* Expression parser. */
812 * We allow an empty expression, and just assume (absolute,0) silently.
813 * Unary operators and parenthetical expressions are treated as operands.
814 * As usual, Q==quantity==operand, O==operator, X==expression mnemonics.
816 * We used to do a aho/ullman shift-reduce parser, but the logic got so
817 * warped that I flushed it and wrote a recursive-descent parser instead.
818 * Now things are stable, would anybody like to write a fast parser?
819 * Most expressions are either register (which does not even reach here)
820 * or 1 symbol. Then "symbol+constant" and "symbol-symbol" are common.
821 * So I guess it doesn't really matter how inefficient more complex expressions
824 * After expr(RANK,resultP) input_line_pointer->operator of rank <= RANK.
825 * Also, we have consumed any leading or trailing spaces (operand does that)
826 * and done all intervening operators.
831 O_illegal
, /* (0) what we get for illegal op */
833 O_multiply
, /* (1) * */
834 O_divide
, /* (2) / */
835 O_modulus
, /* (3) % */
836 O_left_shift
, /* (4) < */
837 O_right_shift
, /* (5) > */
838 O_bit_inclusive_or
, /* (6) | */
839 O_bit_or_not
, /* (7) ! */
840 O_bit_exclusive_or
, /* (8) ^ */
841 O_bit_and
, /* (9) & */
843 O_subtract
/* (11) - */
851 static const operatorT op_encoding
[256] =
852 { /* maps ASCII->operators */
854 __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
,
855 __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
,
857 __
, O_bit_or_not
, __
, __
, __
, O_modulus
, O_bit_and
, __
,
858 __
, __
, O_multiply
, O_add
, __
, O_subtract
, __
, O_divide
,
859 __
, __
, __
, __
, __
, __
, __
, __
,
860 __
, __
, __
, __
, O_left_shift
, __
, O_right_shift
, __
,
861 __
, __
, __
, __
, __
, __
, __
, __
,
862 __
, __
, __
, __
, __
, __
, __
, __
,
863 __
, __
, __
, __
, __
, __
, __
, __
,
864 __
, __
, __
, __
, __
, __
, O_bit_exclusive_or
, __
,
865 __
, __
, __
, __
, __
, __
, __
, __
,
866 __
, __
, __
, __
, __
, __
, __
, __
,
867 __
, __
, __
, __
, __
, __
, __
, __
,
868 __
, __
, __
, __
, O_bit_inclusive_or
, __
, __
, __
,
870 __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
,
871 __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
,
872 __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
,
873 __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
,
874 __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
,
875 __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
,
876 __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
,
877 __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
, __
883 * 0 operand, (expression)
888 static const operator_rankT
890 {0, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1};
892 /* Return resultP->X_seg. */
895 operator_rankT rank
; /* Larger # is higher rank. */
896 expressionS
*resultP
; /* Deliver result here. */
900 char c_left
; /* 1st operator character. */
905 (void) operand (resultP
);
906 know (*input_line_pointer
!= ' '); /* Operand() gobbles spaces. */
907 c_left
= *input_line_pointer
; /* Potential operator character. */
908 op_left
= op_encoding
[c_left
];
909 while (op_left
!= O_illegal
&& op_rank
[(int) op_left
] > rank
)
911 input_line_pointer
++; /*->after 1st character of operator. */
912 /* Operators "<<" and ">>" have 2 characters. */
913 if (*input_line_pointer
== c_left
&& (c_left
== '<' || c_left
== '>'))
915 input_line_pointer
++;
916 } /*->after operator. */
917 if (absent_section
== expr (op_rank
[(int) op_left
], &right
))
919 as_warn ("Missing operand value assumed absolute 0.");
920 resultP
->X_add_number
= 0;
921 resultP
->X_subtract_symbol
= NULL
;
922 resultP
->X_add_symbol
= NULL
;
923 resultP
->X_seg
= absolute_section
;
925 know (*input_line_pointer
!= ' ');
926 c_right
= *input_line_pointer
;
927 op_right
= op_encoding
[c_right
];
928 if (*input_line_pointer
== c_right
&& (c_right
== '<' || c_right
== '>'))
930 input_line_pointer
++;
931 } /*->after operator. */
932 know ((int) op_right
== 0 || op_rank
[(int) op_right
] <= op_rank
[(int) op_left
]);
933 /* input_line_pointer->after right-hand quantity. */
934 /* left-hand quantity in resultP */
935 /* right-hand quantity in right. */
936 /* operator in op_left. */
937 if (resultP
->X_seg
== pass1_section
|| right
.X_seg
== pass1_section
)
939 resultP
->X_seg
= pass1_section
;
943 if (resultP
->X_seg
== big_section
)
945 as_warn ("Left operand of %c is a %s. Integer 0 assumed.",
946 c_left
, resultP
->X_add_number
> 0 ? "bignum" : "float");
947 resultP
->X_seg
= absolute_section
;
948 resultP
->X_add_symbol
= 0;
949 resultP
->X_subtract_symbol
= 0;
950 resultP
->X_add_number
= 0;
952 if (right
.X_seg
== big_section
)
954 as_warn ("Right operand of %c is a %s. Integer 0 assumed.",
955 c_left
, right
.X_add_number
> 0 ? "bignum" : "float");
956 right
.X_seg
= absolute_section
;
957 right
.X_add_symbol
= 0;
958 right
.X_subtract_symbol
= 0;
959 right
.X_add_number
= 0;
961 if (op_left
== O_subtract
)
964 * Convert - into + by exchanging symbolS and negating number.
965 * I know -infinity can't be negated in 2's complement:
966 * but then it can't be subtracted either. This trick
967 * does not cause any further inaccuracy.
972 right
.X_add_number
= -right
.X_add_number
;
973 symbolP
= right
.X_add_symbol
;
974 right
.X_add_symbol
= right
.X_subtract_symbol
;
975 right
.X_subtract_symbol
= symbolP
;
978 right
.X_seg
= diff_section
;
983 if (op_left
== O_add
)
987 #if 0 /* @@ This rejects stuff in common sections too. Figure out some
988 reasonable test, and make it clean... */
989 #if !defined (MANY_SEGMENTS) && !defined (OBJ_ECOFF)
990 know (resultP
->X_seg
== data_section
|| resultP
->X_seg
== text_section
|| resultP
->X_seg
== bss_section
|| resultP
->X_seg
== undefined_section
|| resultP
->X_seg
== diff_section
|| resultP
->X_seg
== absolute_section
|| resultP
->X_seg
== pass1_section
|| resultP
->X_seg
== reg_section
);
992 know (right
.X_seg
== data_section
|| right
.X_seg
== text_section
|| right
.X_seg
== bss_section
|| right
.X_seg
== undefined_section
|| right
.X_seg
== diff_section
|| right
.X_seg
== absolute_section
|| right
.X_seg
== pass1_section
);
995 clean_up_expression (&right
);
996 clean_up_expression (resultP
);
998 seg1
= expr_part (&resultP
->X_add_symbol
, right
.X_add_symbol
);
999 seg2
= expr_part (&resultP
->X_subtract_symbol
, right
.X_subtract_symbol
);
1000 if (seg1
== pass1_section
|| seg2
== pass1_section
)
1003 resultP
->X_seg
= pass1_section
;
1005 else if (seg2
== absolute_section
)
1006 resultP
->X_seg
= seg1
;
1007 else if (seg1
!= undefined_section
1008 && seg1
!= absolute_section
1009 && seg2
!= undefined_section
1012 know (seg2
!= absolute_section
);
1013 know (resultP
->X_subtract_symbol
);
1014 #ifndef MANY_SEGMENTS
1016 know (seg1
== text_section
|| seg1
== data_section
|| seg1
== bss_section
);
1017 know (seg2
== text_section
|| seg2
== data_section
|| seg2
== bss_section
);
1020 know (resultP
->X_add_symbol
);
1021 know (resultP
->X_subtract_symbol
);
1022 as_bad ("Expression too complex: forgetting %s - %s",
1023 S_GET_NAME (resultP
->X_add_symbol
),
1024 S_GET_NAME (resultP
->X_subtract_symbol
));
1025 resultP
->X_seg
= absolute_section
;
1026 /* Clean_up_expression() will do the rest. */
1029 resultP
->X_seg
= diff_section
;
1031 resultP
->X_add_number
+= right
.X_add_number
;
1032 clean_up_expression (resultP
);
1036 if (resultP
->X_seg
== undefined_section
|| right
.X_seg
== undefined_section
)
1038 resultP
->X_seg
= pass1_section
;
1043 resultP
->X_subtract_symbol
= NULL
;
1044 resultP
->X_add_symbol
= NULL
;
1045 /* Will be absolute_section. */
1046 if (resultP
->X_seg
!= absolute_section
|| right
.X_seg
!= absolute_section
)
1048 as_bad ("Relocation error: Symbolic expressions may only involve");
1049 as_bad (" addition and subtraction. Absolute 0 assumed.");
1050 resultP
->X_seg
= absolute_section
;
1051 resultP
->X_add_number
= 0;
1057 case O_bit_inclusive_or
:
1058 resultP
->X_add_number
|= right
.X_add_number
;
1062 if (right
.X_add_number
)
1064 resultP
->X_add_number
%= right
.X_add_number
;
1068 as_warn ("Division by 0. Result of 0 substituted.");
1069 resultP
->X_add_number
= 0;
1074 resultP
->X_add_number
&= right
.X_add_number
;
1078 resultP
->X_add_number
*= right
.X_add_number
;
1082 if (right
.X_add_number
)
1084 resultP
->X_add_number
/= right
.X_add_number
;
1088 as_warn ("Division by 0. 0 assumed.");
1089 resultP
->X_add_number
= 0;
1094 resultP
->X_add_number
<<= right
.X_add_number
;
1098 /* @@ We should distinguish signed versus
1099 unsigned here somehow. */
1100 resultP
->X_add_number
>>= right
.X_add_number
;
1103 case O_bit_exclusive_or
:
1104 resultP
->X_add_number
^= right
.X_add_number
;
1108 resultP
->X_add_number
|= ~right
.X_add_number
;
1114 } /* switch(operator) */
1116 } /* If we have to force need_pass_2. */
1117 } /* If operator was +. */
1118 } /* If we didn't set need_pass_2. */
1120 } /* While next operator is >= this rank. */
1121 return (resultP
->X_seg
);
1127 * This lives here because it belongs equally in expr.c & read.c.
1128 * Expr.c is just a branch office read.c anyway, and putting it
1129 * here lessens the crowd at read.c.
1131 * Assume input_line_pointer is at start of symbol name.
1132 * Advance input_line_pointer past symbol name.
1133 * Turn that character into a '\0', returning its former value.
1134 * This allows a string compare (RMS wants symbol names to be strings)
1135 * of the symbol name.
1136 * There will always be a char following symbol name, because all good
1137 * lines end in end-of-line.
1144 while (is_part_of_name (c
= *input_line_pointer
++))
1146 *--input_line_pointer
= 0;
1152 get_single_number ()
1156 return exp
.X_add_number
;