|
|
1.1 ! root 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 <string.h> ! 29: #include "stuff/round.h" ! 30: #include "as.h" ! 31: #include "flonum.h" ! 32: #include "struc-symbol.h" ! 33: #include "expr.h" ! 34: #include "read.h" ! 35: #include "obstack.h" ! 36: #include "symbols.h" ! 37: #include "hex_value.h" ! 38: #include "md.h" ! 39: #include "messages.h" ! 40: #include "sections.h" ! 41: ! 42: char *seg_name[] = { ! 43: "absolute", ! 44: "section", ! 45: "difference", ! 46: "unknown", ! 47: "absent", ! 48: "bignum/flonum", ! 49: }; ! 50: ! 51: #ifdef SUSPECT ! 52: static int seg_N_TYPE[] = { ! 53: N_ABS, /* absolute */ ! 54: N_SECT, /* section */ ! 55: -1, /* difference */ ! 56: N_UNDF, /* unknown */ ! 57: -1, /* absent */ ! 58: -1 /* bignum/flonum */ ! 59: }; ! 60: #endif ! 61: ! 62: segT N_TYPE_seg[] = ! 63: { ! 64: /* N_UNDF == 0, N_ABS == 2 */ ! 65: SEG_UNKNOWN, -1, SEG_ABSOLUTE, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, ! 66: /* N_SECT == 0xe */ ! 67: SEG_SECT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ! 68: }; ! 69: ! 70: /* ! 71: * SEG_BIG expressions encode either a floating point number or an integer ! 72: * larger than 32 bits in this manner: ! 73: * For a floating point number: ! 74: * X_add_number is < 0 ! 75: * The result is in the global variable generic_floating_point_number. ! 76: * The value in X_add_number is -'c' where c is the character that ! 77: * introduced the constant. e.g. "0f6.9" will have -'f' as a ! 78: * X_add_number value. ! 79: * For an integer larger than 32 bits: ! 80: * X_add_number > 0 ! 81: * The result is in the global variable generic_bignum. ! 82: * The value in X_add_number is a count of how many littlenums it ! 83: * took to represent the bignum. ! 84: */ ! 85: ! 86: /* LITTLENUM_TYPE generic_buffer [6]; JF this is a hack */ ! 87: /* Seems atof_machine can backscan through generic_bignum and hit whatever ! 88: happens to be loaded before it in memory. And its way too complicated ! 89: for me to fix right. Thus a hack. JF: Just make generic_bignum bigger, ! 90: and never write into the early words, thus they'll always be zero. ! 91: I hate Dean's floating-point code. Bleh. ! 92: */ ! 93: LITTLENUM_TYPE generic_bignum[SIZE_OF_LARGE_NUMBER + 6] = { 0 }; ! 94: ! 95: FLONUM_TYPE generic_floating_point_number = { ! 96: &generic_bignum[6], /* low (JF: Was 0) */ ! 97: &generic_bignum[SIZE_OF_LARGE_NUMBER + 6 - 1],/* high JF: (added +6) */ ! 98: 0, /* leader */ ! 99: 0, /* exponent */ ! 100: 0 /* sign */ ! 101: }; ! 102: ! 103: /* ! 104: * The type operatorT is for the types of operators in expressions. ! 105: */ ! 106: typedef enum { ! 107: O_illegal, /* (0) what we get for illegal op */ ! 108: ! 109: O_multiply, /* (1) * Ordered by rank*/ ! 110: O_divide, /* (2) / */ ! 111: O_modulus, /* (3) % */ ! 112: ! 113: O_add, /* (4) + */ ! 114: O_subtract, /* (5) - */ ! 115: ! 116: O_right_shift, /* (6) >> */ ! 117: O_left_shift, /* (7) << */ ! 118: ! 119: O_less_than, /* (8) < */ ! 120: O_greater_than, /* (9) > */ ! 121: O_less_than_or_equal, /* (10) <= */ ! 122: O_greater_than_or_equal, /* (11) >= */ ! 123: ! 124: O_equal, /* (12) == */ ! 125: O_not_equal, /* (13) != */ /* or <> */ ! 126: ! 127: O_bit_and, /* (14) & */ ! 128: ! 129: O_bit_exclusive_or, /* (15) ^ */ ! 130: ! 131: O_bit_inclusive_or, /* (16) | */ ! 132: O_bit_or_not, /* (17) ! */ ! 133: two_char_operator /* (18) encoding for two char operator */ ! 134: } operatorT; ! 135: ! 136: /* ! 137: * op_size is indexed by an operatorT and tells the size of the operator ! 138: * which is used to advance the input_line_pointer over the operator. ! 139: */ ! 140: static int op_size [] = ! 141: { 0, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1 }; ! 142: ! 143: /* ! 144: * op_rank is indexed by an operatorT and tells the rank of the operator. ! 145: * ! 146: * Rank Examples ! 147: * 8 * / % ! 148: * 7 + - ! 149: * 6 >> << ! 150: * 5 < > <= >= ! 151: * 4 == != ! 152: * 3 & ! 153: * 2 ^ ! 154: * 1 | ! ! 155: * 0 operand, (expression) ! 156: */ ! 157: typedef char operator_rankT; ! 158: static operator_rankT op_rank [] = ! 159: { 0, 8, 8, 8, 7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 3, 2, 1, 1 }; ! 160: ! 161: /* ! 162: * op_encoding is indexed by a an ASCII character and maps it to an operator. ! 163: */ ! 164: #define __ O_illegal ! 165: static const operatorT op_encoding [256] = { ! 166: __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, ! 167: __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, ! 168: ! 169: __, two_char_operator, __, __, __, O_modulus, O_bit_and, __, ! 170: __, __, O_multiply, O_add, __, O_subtract, __, O_divide, ! 171: __, __, __, __, __, __, __, __, ! 172: __, __, __, __, two_char_operator, two_char_operator, two_char_operator, __, ! 173: __, __, __, __, __, __, __, __, ! 174: __, __, __, __, __, __, __, __, ! 175: __, __, __, __, __, __, __, __, ! 176: __, __, __, __, __, __, O_bit_exclusive_or, __, ! 177: __, __, __, __, __, __, __, __, ! 178: __, __, __, __, __, __, __, __, ! 179: __, __, __, __, __, __, __, __, ! 180: __, __, __, __, O_bit_inclusive_or, __, __, __, ! 181: ! 182: __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, ! 183: __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, ! 184: __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, ! 185: __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, ! 186: __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, ! 187: __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, ! 188: __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, ! 189: __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __ ! 190: }; ! 191: ! 192: static segT expr( ! 193: operator_rankT rank, ! 194: expressionS *resultP); ! 195: ! 196: static segT operand( ! 197: expressionS *expressionP); ! 198: ! 199: static void clean_up_expression( ! 200: expressionS *expressionP); ! 201: ! 202: static segT expr_part( ! 203: struct symbol **symbol_1_PP, ! 204: struct symbol *symbol_2_P); ! 205: ! 206: static operatorT two_char_op_encoding( ! 207: char first_op_char); ! 208: ! 209: segT /* Return resultP -> X_seg */ ! 210: expression( ! 211: expressionS *resultP) /* deliver result here */ ! 212: { ! 213: segT segment; ! 214: ! 215: segment = expr(0, resultP); ! 216: ! 217: /* what about caller's that just want to ignore this and print the're own ! 218: error message? ok I guess */ ! 219: if(segment == SEG_DIFFSECT && ! 220: resultP->X_add_symbol == NULL && ! 221: (resultP->X_subtract_symbol->sy_type & N_TYPE) != N_UNDF){ ! 222: as_warn("Subtracting symbol \"%s\"(segment\"%s\") is too " ! 223: "hard. Absolute segment assumed.", ! 224: resultP->X_subtract_symbol->sy_name, ! 225: seg_name[(int)N_TYPE_seg[ ! 226: resultP->X_subtract_symbol->sy_type & N_TYPE]]); ! 227: segment = SEG_ABSOLUTE; ! 228: /* Leave exp .X_add_number alone. */ ! 229: } ! 230: return(segment); ! 231: } ! 232: ! 233: /* Expression parser. */ ! 234: ! 235: /* ! 236: * We allow an empty expression, and just assume (absolute,0) silently. ! 237: * Unary operators and parenthetical expressions are treated as operands. ! 238: * As usual, Q==quantity==operand, O==operator, X==expression mnemonics. ! 239: * ! 240: * Most expressions are either register (which does not even reach here) ! 241: * or 1 symbol. Then "symbol+constant" and "symbol-symbol" are common. ! 242: * ! 243: * After expr(RANK,resultP) input_line_pointer -> operator of rank <= RANK. ! 244: * Also, we have consumed any leading or trailing spaces (operand does that) ! 245: * and done all intervening operators. ! 246: */ ! 247: static ! 248: segT /* Return resultP -> X_seg */ ! 249: expr( ! 250: operator_rankT rank, /* larger # is higher rank */ ! 251: expressionS *resultP) /* deliver result here */ ! 252: { ! 253: expressionS right; ! 254: operatorT op_left; ! 255: char c_left; /* 1st operator character. */ ! 256: operatorT op_right; ! 257: char c_right; ! 258: ! 259: know(rank >= 0); ! 260: ! 261: (void)operand(resultP); ! 262: know(*input_line_pointer != ' '); /* Operand() gobbles spaces. */ ! 263: ! 264: c_left = *input_line_pointer; /* Potential operator character. */ ! 265: op_left = (operatorT)op_encoding[(int)c_left]; ! 266: if(op_left == two_char_operator) ! 267: op_left = two_char_op_encoding(c_left); ! 268: ! 269: while(op_left != O_illegal && op_rank[op_left] > rank){ ! 270: ! 271: input_line_pointer += op_size[op_left]; ! 272: /* -> after 1st character of operator. */ ! 273: ! 274: if(SEG_NONE == expr(op_rank[op_left], &right)){ ! 275: as_warn("Missing operand value assumed absolute 0."); ! 276: resultP->X_add_number = 0; ! 277: resultP->X_subtract_symbol = NULL; ! 278: resultP->X_add_symbol = NULL; ! 279: resultP->X_seg = SEG_ABSOLUTE; ! 280: } ! 281: know(*input_line_pointer != ' '); ! 282: ! 283: c_right = *input_line_pointer; ! 284: op_right = (operatorT)op_encoding[(int)c_right]; ! 285: if(op_right == two_char_operator) ! 286: op_right = two_char_op_encoding(c_right); ! 287: ! 288: /* -> after 1st character of operator. */ ! 289: know(op_right == 0 || op_rank [op_right] <= op_rank[op_left]); ! 290: ! 291: /* input_line_pointer -> after right-hand quantity. */ ! 292: /* left-hand quantity in resultP */ ! 293: /* right-hand quantity in right. */ ! 294: /* operator in op_left. */ ! 295: ! 296: /* ! 297: * Operations are not supported on bignums or floating-point ! 298: * operands. ! 299: */ ! 300: if(resultP->X_seg == SEG_BIG){ ! 301: as_warn("Left operand of %c is a %s integer 0 assumed", ! 302: c_left, resultP->X_add_number > 0 ? "bignum" : ! 303: "float"); ! 304: resultP->X_seg = SEG_ABSOLUTE; ! 305: resultP->X_add_symbol = 0; ! 306: resultP->X_subtract_symbol = 0; ! 307: resultP->X_add_number = 0; ! 308: } ! 309: if(right.X_seg == SEG_BIG){ ! 310: as_warn("Right operand of %c is a %s integer 0 assumed", ! 311: c_left, right.X_add_number > 0 ? "bignum" : ! 312: "float"); ! 313: right.X_seg = SEG_ABSOLUTE; ! 314: right.X_add_symbol = 0; ! 315: right.X_subtract_symbol = 0; ! 316: right.X_add_number = 0; ! 317: } ! 318: if(op_left == O_subtract){ ! 319: /* ! 320: * Convert - into + by exchanging symbols and negating ! 321: * number. I know -infinity can't be negated in 2's ! 322: * complement: but then it can't be subtracted either. ! 323: * This trick does not cause any further inaccuracy. ! 324: */ ! 325: struct symbol *symbolP; ! 326: ! 327: right.X_add_number = - right.X_add_number; ! 328: symbolP = right.X_add_symbol; ! 329: right.X_add_symbol = right.X_subtract_symbol; ! 330: right.X_subtract_symbol = symbolP; ! 331: if(symbolP){ ! 332: /* This is not used, as it drops in to the next if */ ! 333: right.X_seg = SEG_DIFFSECT; ! 334: } ! 335: op_left = O_add; ! 336: } ! 337: if(op_left == O_add){ ! 338: segT seg1; ! 339: segT seg2; ! 340: ! 341: /* not SEG_NONE and not SEG_BIG */ ! 342: know(resultP->X_seg == SEG_SECT || ! 343: resultP->X_seg == SEG_UNKNOWN || ! 344: resultP->X_seg == SEG_DIFFSECT || ! 345: resultP->X_seg == SEG_ABSOLUTE); ! 346: /* not SEG_NONE and not SEG_BIG */ ! 347: know(right.X_seg == SEG_SECT || ! 348: right.X_seg == SEG_UNKNOWN || ! 349: right.X_seg == SEG_DIFFSECT || ! 350: right.X_seg == SEG_ABSOLUTE); ! 351: ! 352: clean_up_expression(&right); ! 353: clean_up_expression(resultP); ! 354: ! 355: /* could this just return -1 instead of SEG_PASS1? and tested in the below if ! 356: statement */ ! 357: seg1 = expr_part(&resultP->X_add_symbol, ! 358: right.X_add_symbol); ! 359: seg2 = expr_part(&resultP->X_subtract_symbol, ! 360: right.X_subtract_symbol); ! 361: if(seg1 == -1 || seg2 == -1){ ! 362: as_warn("Can't relocate expression. Absolute 0 assumed."); ! 363: resultP->X_seg = SEG_ABSOLUTE; ! 364: resultP->X_add_number = 0; ! 365: } ! 366: else{ ! 367: if(seg2 == SEG_ABSOLUTE){ ! 368: resultP->X_seg = seg1; ! 369: } ! 370: else{ ! 371: /* also know seg2 != -1 (SEG_PASS1) */ ! 372: know(seg2 != SEG_ABSOLUTE); ! 373: /* seg2 is for the subtract symbols, since seg2 != SEG_ABSOLUTE as would be ! 374: returned when there is no subtract symbols then expr_part() must have ! 375: combined a symbol into resultP->X_subtract_symbol that is either undefined ! 376: or defined in a section. */ ! 377: know(resultP->X_subtract_symbol); ! 378: /* ! 379: * If we are not to use the new incompatible features ! 380: * then "symbol1 - symbol2" must both be in the same ! 381: * section and will turn out as absolute. ! 382: */ ! 383: if(!flagseen['k']){ ! 384: if(seg1 != SEG_UNKNOWN && ! 385: seg1 != SEG_ABSOLUTE && ! 386: seg2 != SEG_UNKNOWN && ! 387: seg1 != seg2 && ! 388: resultP->X_add_symbol->sy_other != ! 389: resultP->X_subtract_symbol->sy_other){ ! 390: know(seg1 == SEG_SECT); ! 391: know(seg2 == SEG_SECT); ! 392: know(resultP->X_add_symbol); ! 393: know(resultP->X_subtract_symbol); ! 394: as_warn("Expression too complex: " ! 395: "forgetting %s - %s", ! 396: resultP->X_add_symbol->sy_name, ! 397: resultP->X_subtract_symbol->sy_name); ! 398: resultP->X_seg = SEG_ABSOLUTE; ! 399: /* Clean_up_expression() will do the rest */ ! 400: } ! 401: else{ ! 402: /* this can result in returning an expression that is NULL - symbol and the ! 403: caller must deal with this being illegal. maybe this should be put in ! 404: expression() routine (not a macro). Note the code in cons() */ ! 405: resultP->X_seg = SEG_DIFFSECT; ! 406: } /* If relocation too complex. */ ! 407: } ! 408: else{ ! 409: resultP->X_seg = SEG_DIFFSECT; ! 410: } ! 411: ! 412: } /* If seg2 == SEG_ABSOLUTE. */ ! 413: } /* If need pass 2. */ ! 414: resultP->X_add_number += right.X_add_number; ! 415: clean_up_expression(resultP); ! 416: } ! 417: else{ /* Not +. */ ! 418: if(resultP->X_seg == SEG_UNKNOWN || ! 419: right.X_seg == SEG_UNKNOWN){ ! 420: as_warn("Can't relocate expression. Absolute 0 assumed."); ! 421: resultP->X_seg = SEG_ABSOLUTE; ! 422: resultP->X_add_number = 0; ! 423: } ! 424: else{ ! 425: /* ! 426: * Will be SEG_ABSOLUTE. (or error) ! 427: */ ! 428: try_to_make_absolute(resultP); ! 429: try_to_make_absolute(&right); ! 430: resultP->X_subtract_symbol = NULL; ! 431: resultP->X_add_symbol = NULL; ! 432: if(resultP->X_seg != SEG_ABSOLUTE || ! 433: right.X_seg != SEG_ABSOLUTE){ ! 434: as_warn("Relocation error. Absolute 0 assumed"); ! 435: resultP->X_seg = SEG_ABSOLUTE; ! 436: resultP->X_add_number = 0; ! 437: } ! 438: else{ ! 439: /* ! 440: * Both are absolute so perform the operation ! 441: * on the constants. ! 442: */ ! 443: switch(op_left){ ! 444: case O_bit_inclusive_or: ! 445: resultP->X_add_number |= right.X_add_number; ! 446: break; ! 447: ! 448: case O_modulus: ! 449: if(right.X_add_number){ ! 450: resultP->X_add_number %= ! 451: right.X_add_number; ! 452: } ! 453: else{ ! 454: as_warn("Division by 0. 0 assumed."); ! 455: resultP->X_add_number = 0; ! 456: } ! 457: break; ! 458: ! 459: case O_bit_and: ! 460: resultP->X_add_number &= right.X_add_number; ! 461: break; ! 462: ! 463: case O_multiply: ! 464: resultP->X_add_number *= right.X_add_number; ! 465: break; ! 466: ! 467: case O_divide: ! 468: if(right.X_add_number){ ! 469: resultP->X_add_number /= ! 470: right.X_add_number; ! 471: } ! 472: else{ ! 473: as_warn("Division by 0. 0 assumed."); ! 474: resultP->X_add_number = 0; ! 475: } ! 476: break; ! 477: ! 478: case O_left_shift: ! 479: resultP->X_add_number <<= ! 480: right.X_add_number; ! 481: break; ! 482: ! 483: case O_right_shift: ! 484: resultP->X_add_number >>= ! 485: right.X_add_number; ! 486: break; ! 487: ! 488: case O_bit_exclusive_or: ! 489: resultP->X_add_number ^= right.X_add_number; ! 490: break; ! 491: ! 492: case O_bit_or_not: ! 493: resultP->X_add_number |= ! 494: ~right.X_add_number; ! 495: break; ! 496: ! 497: case O_less_than: ! 498: resultP->X_add_number = ! 499: (resultP->X_add_number < ! 500: right.X_add_number); ! 501: break; ! 502: ! 503: case O_greater_than: ! 504: resultP->X_add_number = ! 505: (resultP->X_add_number > ! 506: right.X_add_number); ! 507: break; ! 508: ! 509: case O_less_than_or_equal: ! 510: resultP->X_add_number = ! 511: (resultP->X_add_number <= ! 512: right.X_add_number); ! 513: break; ! 514: ! 515: case O_greater_than_or_equal: ! 516: resultP->X_add_number = ! 517: (resultP->X_add_number >= ! 518: right.X_add_number); ! 519: break; ! 520: ! 521: case O_equal: ! 522: resultP->X_add_number = ! 523: (resultP->X_add_number == ! 524: right.X_add_number); ! 525: break; ! 526: ! 527: case O_not_equal: ! 528: resultP->X_add_number = ! 529: (resultP->X_add_number != ! 530: right.X_add_number); ! 531: break; ! 532: ! 533: default: ! 534: BAD_CASE( op_left ); ! 535: break; ! 536: } /* switch(op_left) */ ! 537: } ! 538: } /* If we have to force need_pass_2 */ ! 539: } /* If operator was + */ ! 540: op_left = op_right; ! 541: } /* While next operator is >= this rank */ ! 542: return(resultP->X_seg); ! 543: } ! 544: ! 545: /* ! 546: * Summary of operand(). ! 547: * ! 548: * in: Input_line_pointer points to 1st char of operand, which may ! 549: * be a space. ! 550: * ! 551: * out: A expressionS. X_seg determines how to understand the rest of the ! 552: * expressionS. ! 553: * The operand may have been empty: in this case X_seg == SEG_NONE. ! 554: * Input_line_pointer -> (next non-blank) char after operand. ! 555: * ! 556: */ ! 557: static ! 558: segT ! 559: operand( ! 560: expressionS *expressionP) ! 561: { ! 562: char c, q; ! 563: char *name; /* points to name of symbol */ ! 564: struct symbol *symbolP; /* Points to symbol */ ! 565: ! 566: ! 567: SKIP_WHITESPACE(); /* Leading whitespace is part of operand. */ ! 568: c = *input_line_pointer++;/* Input_line_pointer -> past char in c. */ ! 569: ! 570: if(isdigit(c)){ ! 571: valueT number; /* offset or (absolute) value */ ! 572: int digit; /* value of next digit in current radix */ ! 573: /* invented for humans only, hope */ ! 574: /* optimising compiler flushes it! */ ! 575: int radix; /* 8, 10 or 16 */ ! 576: /* 0 means we saw start of a floating- */ ! 577: /* point constant. */ ! 578: int maxdig; /* Highest permitted digit value. */ ! 579: int too_many_digits;/* If we see >= this number of */ ! 580: /* digits, assume it is a bignum. */ ! 581: char *digit_2; /* -> 2nd digit of number. */ ! 582: int small; /* TRUE if fits in 32 bits. */ ! 583: int force_bignum; /* TRUE if number is 0xb... */ ! 584: ! 585: force_bignum = FALSE; ! 586: /* ! 587: * These two initiaizations are to shut up compiler warning as the ! 588: * may be used with out being set. There used only if radix != 0 ! 589: * when the number is not a floating-point number. ! 590: */ ! 591: maxdig = 0; ! 592: too_many_digits = 0; ! 593: ! 594: if(c == '0'){ /* non-decimal radix */ ! 595: c = *input_line_pointer++; ! 596: if(c == 'x' || c=='X'){ ! 597: c = *input_line_pointer++; /* read past "0x" or "0X" */ ! 598: maxdig = 16; ! 599: radix = 16; ! 600: too_many_digits = 9; ! 601: } ! 602: /* ! 603: * If we have "0b" and some hex digits then treat it as a hex ! 604: * number and return a bignum. This is for hex immediate ! 605: * bit-patterns for floating-point immediate constants. ! 606: */ ! 607: else if((c == 'b' || c == 'B') && ! 608: (*input_line_pointer != '\0') && ! 609: strchr("0123456789abcdefABCDEF", ! 610: *input_line_pointer) != NULL){ ! 611: force_bignum = TRUE; ! 612: c = *input_line_pointer++; /* read past "0b" or "0B" */ ! 613: maxdig = 16; ! 614: radix = 16; ! 615: too_many_digits = 9; ! 616: } ! 617: else{ ! 618: /* ! 619: * If it says '0f' and the line ends or it DOESN'T look like ! 620: * a floating point #, its a local label ref. ! 621: */ ! 622: if(c == 'f' && ! 623: (*input_line_pointer == '\0' || ! 624: (strchr("+-.0123456789", *input_line_pointer) == NULL && ! 625: strchr(md_EXP_CHARS, *input_line_pointer) == NULL) )){ ! 626: maxdig = 10; ! 627: radix = 10; ! 628: too_many_digits = 11; ! 629: c = '0'; ! 630: input_line_pointer -= 2; ! 631: } ! 632: else if(c != '\0' && strchr(md_FLT_CHARS, c) != NULL){ ! 633: radix = 0;/* Start of floating-point constant. */ ! 634: /* input_line_pointer -> 1st char of number */ ! 635: expressionP->X_add_number = ! 636: - (isupper(c) ? tolower(c) : c); ! 637: } ! 638: else{ /* By elimination, assume octal radix. */ ! 639: radix = 8; ! 640: maxdig = 10; /* Un*x sux. Compatibility. */ ! 641: too_many_digits = 11; ! 642: } ! 643: } ! 644: /* c == char after "0" or "0x" or "0X" or "0e" etc.*/ ! 645: } ! 646: else{ ! 647: maxdig = 10; ! 648: radix = 10; ! 649: too_many_digits = 11; ! 650: } ! 651: if(radix != 0){ /* Fixed-point integer constant. */ ! 652: /* May be bignum, or may fit in 32 bits. */ ! 653: /* ! 654: * Most numbers fit into 32 bits, and we want this case to be ! 655: * fast. So we pretend it will fit into 32 bits. If, after ! 656: * making up a 32 bit number, we realize that we have scanned ! 657: * more digits than comfortably fit into 32 bits, we re-scan the ! 658: * digits coding them into a bignum. For decimal and octal ! 659: * numbers we are conservative: some numbers may be assumed ! 660: * bignums when in fact they do fit into 32 bits. Numbers of ! 661: * any radix can have excess leading zeros: we strive to ! 662: * recognise this and cast them back into 32 bits. We must ! 663: * check that the bignum really is more than 32 bits, and ! 664: * change it back to a 32-bit number if it fits. The number we ! 665: * are looking for is expected to be positive, but if it fits ! 666: * into 32 bits as an unsigned number, we let it be a 32-bit ! 667: * number. The cavalier approach is for speed in ordinary cases. ! 668: */ ! 669: digit_2 = input_line_pointer; ! 670: for(number = 0; ! 671: (digit = hex_value[(int)c]) < maxdig; ! 672: c = *input_line_pointer++){ ! 673: number = number * radix + digit; ! 674: } ! 675: /* c contains character after number. */ ! 676: /* Input_line_pointer -> char after c. */ ! 677: small = input_line_pointer - digit_2 < too_many_digits; ! 678: if(force_bignum == TRUE) ! 679: small = FALSE; ! 680: if(small == FALSE){ ! 681: /* ! 682: * Manufacture a bignum. ! 683: */ ! 684: /* -> high order littlenum of the bignum. */ ! 685: LITTLENUM_TYPE *leader; ! 686: /* -> littlenum we are frobbing now. */ ! 687: LITTLENUM_TYPE *pointer; ! 688: long carry; ! 689: ! 690: leader = generic_bignum; ! 691: generic_bignum [0] = 0; ! 692: /* We could just use digit_2, but lets be mnemonic. */ ! 693: input_line_pointer = --digit_2; /* -> 1st digit. */ ! 694: c = *input_line_pointer++; ! 695: for( ; ! 696: (carry = hex_value[(int)c]) < maxdig; ! 697: c = * input_line_pointer++){ ! 698: for(pointer = generic_bignum; ! 699: pointer <= leader; ! 700: pointer++){ ! 701: long work; ! 702: ! 703: work = carry + radix * *pointer; ! 704: *pointer = work & LITTLENUM_MASK; ! 705: carry = work >> LITTLENUM_NUMBER_OF_BITS; ! 706: } ! 707: if(carry){ ! 708: if(leader < generic_bignum + ! 709: SIZE_OF_LARGE_NUMBER - 1){ ! 710: /* Room to grow a longer bignum. */ ! 711: *++leader = carry; ! 712: } ! 713: } ! 714: } ! 715: /* Again, C is char after number, */ ! 716: /* input_line_pointer -> after C. */ ! 717: /* know(BITS_PER_INT == 32); */ ! 718: know(LITTLENUM_NUMBER_OF_BITS == 16); ! 719: /* Hence the constant "2" in the next line. */ ! 720: if(leader < generic_bignum + 2 && force_bignum == FALSE) ! 721: { /* Will fit into 32 bits. */ ! 722: number = ((generic_bignum[1] & LITTLENUM_MASK) << ! 723: LITTLENUM_NUMBER_OF_BITS) | ! 724: (generic_bignum[0] & LITTLENUM_MASK); ! 725: small = TRUE; ! 726: } ! 727: else{ ! 728: /* Number of littlenums in the bignum. */ ! 729: number = leader - generic_bignum + 1; ! 730: } ! 731: } ! 732: if(small){ ! 733: /* ! 734: * Here with number, in correct radix. c is the next char. ! 735: * Note that unlike Un*x, we allow "011f" "0x9f" to both ! 736: * mean the same as the (conventional) "9f". This is simply ! 737: * easier than checking for strict canonical form. ! 738: */ ! 739: if(number < 10){ ! 740: if(c == 'b'){ ! 741: /* ! 742: * Backward ref to local label. ! 743: * Because it is backward, expect it to be DEFINED. ! 744: */ ! 745: /* ! 746: * Construct a local label. ! 747: */ ! 748: name = local_label_name((int)number, 0); ! 749: symbolP = symbol_table_lookup(name); ! 750: if((symbolP != NULL) && ! 751: (symbolP->sy_type & N_TYPE) != N_UNDF){ ! 752: /* Expected path: symbol defined. */ ! 753: /* Local labels are never absolute. Don't waste ! 754: time checking absoluteness. */ ! 755: know((symbolP->sy_type & N_TYPE) == N_SECT); ! 756: expressionP->X_add_symbol = symbolP; ! 757: expressionP->X_add_number = 0; ! 758: expressionP->X_seg = SEG_SECT; ! 759: } ! 760: else{ /* Either not seen or not defined. */ ! 761: as_warn("Backw. ref to unknown label \"%d:\", 0" ! 762: " assumed.", number); ! 763: expressionP->X_add_number = 0; ! 764: expressionP->X_seg = SEG_ABSOLUTE; ! 765: } ! 766: } ! 767: else if(c == 'f'){ ! 768: /* ! 769: * Forward reference. Expect symbol to be ! 770: * undefined or unknown. Undefined: seen it ! 771: * before. Unknown: never seen it in this pass. ! 772: * Construct a local label name, then an ! 773: * undefined symbol. Don't create a XSEG frag ! 774: * for it: caller may do that. ! 775: * Just return it as never seen before. ! 776: */ ! 777: name = local_label_name((int)number, 1); ! 778: symbolP = symbol_table_lookup(name); ! 779: if(symbolP != NULL){ ! 780: /* We have no need to check symbol ! 781: properties. */ ! 782: know((symbolP->sy_type & N_TYPE) == N_UNDF || ! 783: (symbolP->sy_type & N_TYPE) == N_SECT); ! 784: } ! 785: else{ ! 786: symbolP = symbol_new(name, N_UNDF, 0,0,0, ! 787: &zero_address_frag); ! 788: symbol_table_insert(symbolP); ! 789: } ! 790: expressionP->X_add_symbol = symbolP; ! 791: expressionP->X_seg = SEG_UNKNOWN; ! 792: expressionP->X_subtract_symbol = NULL; ! 793: expressionP->X_add_number = 0; ! 794: } ! 795: else{ /* Really a number, not a local label. */ ! 796: expressionP->X_add_number = number; ! 797: expressionP->X_seg = SEG_ABSOLUTE; ! 798: input_line_pointer--; /* restore following char */ ! 799: } ! 800: } ! 801: else{ /* a number >= 10 */ ! 802: expressionP->X_add_number = number; ! 803: expressionP->X_seg = SEG_ABSOLUTE; ! 804: input_line_pointer--; /* restore following char */ ! 805: } ! 806: } /* not a small number encode returning a bignum */ ! 807: else{ ! 808: expressionP->X_add_number = number; ! 809: expressionP->X_seg = SEG_BIG; ! 810: input_line_pointer--; /* -> char following number. */ ! 811: } /* if (small) */ ! 812: } /* (If integer constant) */ ! 813: else{ /* input_line_pointer -> floating-point constant. */ ! 814: ! 815: int error_code; ! 816: ! 817: error_code = atof_generic(&input_line_pointer, ".", md_EXP_CHARS, ! 818: &generic_floating_point_number); ! 819: ! 820: if(error_code){ ! 821: if(error_code == ERROR_EXPONENT_OVERFLOW){ ! 822: as_warn("Bad floating-point constant: exponent " ! 823: "overflow, probably assembling junk" ); ! 824: } ! 825: else{ ! 826: as_warn("Bad floating-point constant: unknown error " ! 827: "code=%d.", error_code); ! 828: } ! 829: } ! 830: expressionP->X_seg = SEG_BIG; ! 831: /* input_line_pointer -> just after constant, */ ! 832: /* which may point to whitespace. */ ! 833: know(expressionP->X_add_number < 0); ! 834: /* < 0 means "floating point". */ ! 835: } /* if (not floating-point constant) */ ! 836: } ! 837: else if(c == '.' && !is_part_of_name(*input_line_pointer)){ ! 838: /* ! 839: JF: '.' is pseudo symbol with value of current location in current ! 840: segment. . . ! 841: */ ! 842: symbolP = symbol_new("L0\001", ! 843: N_SECT, ! 844: frchain_now->frch_nsect, ! 845: 0, ! 846: (valueT)(obstack_next_free(&frags) - ! 847: frag_now->fr_literal), ! 848: frag_now); ! 849: expressionP->X_add_number = 0; ! 850: expressionP->X_add_symbol = symbolP; ! 851: expressionP->X_seg = SEG_SECT; ! 852: } ! 853: /* here if did not begin with a digit */ ! 854: else if(is_name_beginner(c) || c == '"'){ ! 855: /* ! 856: * Identifier begins here. ! 857: * This is kludged for speed, so code is repeated. ! 858: */ ! 859: q = c; ! 860: if(q == '"') ! 861: name = input_line_pointer-- ; ! 862: else ! 863: name = -- input_line_pointer; ! 864: c = get_symbol_end(); ! 865: symbolP = symbol_table_lookup(name); ! 866: if(symbolP != NULL){ ! 867: /* ! 868: * If we have an absolute symbol, then we know it's value now. ! 869: */ ! 870: segT seg; ! 871: ! 872: seg = N_TYPE_seg[(int)symbolP->sy_type & N_TYPE]; ! 873: expressionP->X_seg = seg; ! 874: if(seg == SEG_ABSOLUTE){ ! 875: expressionP->X_add_number = symbolP->sy_value; ! 876: } ! 877: else{ ! 878: expressionP->X_add_number = 0; ! 879: expressionP->X_add_symbol = symbolP; ! 880: } ! 881: } ! 882: else{ ! 883: symbolP = symbol_new(name, N_UNDF, 0,0,0, &zero_address_frag); ! 884: expressionP->X_add_symbol = symbolP; ! 885: expressionP->X_add_number = 0; ! 886: expressionP->X_seg = SEG_UNKNOWN; ! 887: symbol_table_insert(symbolP); ! 888: } ! 889: *input_line_pointer = c; ! 890: if(q == '"') ! 891: input_line_pointer[-1] = '"'; ! 892: expressionP->X_subtract_symbol = NULL; ! 893: } ! 894: /* didn't begin with digit & not a name */ ! 895: else if (c == '('){ ! 896: (void)expression(expressionP); ! 897: /* Expression() will pass trailing whitespace */ ! 898: if(*input_line_pointer++ != ')'){ ! 899: as_warn("Missing ')' assumed"); ! 900: input_line_pointer--; ! 901: } ! 902: /* here with input_line_pointer -> char after "(...)" */ ! 903: } ! 904: /* unary operator: hope for SEG_ABSOLUTE */ ! 905: else if(c == '~' || c == '-' || c == '!'){ ! 906: switch(operand(expressionP)){ ! 907: case SEG_ABSOLUTE: ! 908: /* input_line_pointer -> char after operand */ ! 909: if(c == '-' ){ ! 910: /* ! 911: * Notice: '-' may overflow: no warning is given. This is ! 912: * compatible with other people's assemblers. ! 913: */ ! 914: expressionP->X_add_number = - expressionP->X_add_number; ! 915: } ! 916: else if(c == '!'){ ! 917: expressionP->X_add_number = ! expressionP->X_add_number; ! 918: } ! 919: else{ ! 920: expressionP->X_add_number = ~ expressionP->X_add_number; ! 921: } ! 922: break; ! 923: case SEG_SECT: ! 924: case SEG_UNKNOWN: ! 925: if(c == '-'){ /* JF I hope this hack works */ ! 926: expressionP->X_subtract_symbol = expressionP->X_add_symbol; ! 927: expressionP->X_add_symbol = 0; ! 928: expressionP->X_seg = SEG_DIFFSECT; ! 929: break; ! 930: } ! 931: default: /* unary on non-absolute is unsuported */ ! 932: as_warn("Unary operator %c ignored because bad operand follows", ! 933: c); ! 934: break; ! 935: /* Expression undisturbed from operand(). */ ! 936: } ! 937: } ! 938: /* ! 939: * Warning: to conform to other people's assemblers NO ESCAPEMENT is ! 940: * permitted for a single quote. The next character, parity errors and ! 941: * all, is taken as the value of the operand. VERY KINKY. ! 942: */ ! 943: else if(c == '\''){ ! 944: expressionP->X_add_number = *input_line_pointer++; ! 945: expressionP->X_seg = SEG_ABSOLUTE; ! 946: } ! 947: /* can't imagine any other kind of operand */ ! 948: else{ ! 949: expressionP->X_seg = SEG_NONE; ! 950: input_line_pointer--; ! 951: } ! 952: /* ! 953: * It is more 'efficient' to clean up the expressions when they are ! 954: * created. Doing it here saves lines of code. ! 955: */ ! 956: clean_up_expression(expressionP); ! 957: SKIP_WHITESPACE(); /* -> 1st char after operand. */ ! 958: know(*input_line_pointer != ' '); ! 959: return(expressionP->X_seg); ! 960: } ! 961: ! 962: /* Internal. Simplify a struct expression for use by expr() */ ! 963: ! 964: /* ! 965: * In: address of a expressionS. ! 966: * The X_seg field of the expressionS may only take certain values. ! 967: * Now, we permit SEG_NONE to make code smaller & faster. ! 968: * Elsewise we waste time special-case testing. Sigh. ! 969: * Out: expressionS may have been modified: ! 970: * 'foo-foo' symbol references cancelled to 0, ! 971: * which changes X_seg from SEG_DIFFSECT to SEG_ABSOLUTE; ! 972: * Unused fields zeroed to help expr(). ! 973: */ ! 974: static ! 975: void ! 976: clean_up_expression( ! 977: expressionS *expressionP) ! 978: { ! 979: switch(expressionP->X_seg){ ! 980: case SEG_NONE: ! 981: expressionP->X_add_symbol = NULL; ! 982: expressionP->X_subtract_symbol = NULL; ! 983: expressionP->X_add_number = 0; ! 984: break; ! 985: ! 986: case SEG_BIG: ! 987: case SEG_ABSOLUTE: ! 988: expressionP->X_subtract_symbol = NULL; ! 989: expressionP->X_add_symbol = NULL; ! 990: break; ! 991: ! 992: case SEG_SECT: ! 993: case SEG_UNKNOWN: ! 994: expressionP->X_subtract_symbol = NULL; ! 995: break; ! 996: ! 997: case SEG_DIFFSECT: ! 998: /* ! 999: * It does not hurt to 'cancel' NULL==NULL ! 1000: * when comparing symbols for 'eq'ness. ! 1001: * It is faster to re-cancel them to NULL ! 1002: * than to check for this special case. ! 1003: */ ! 1004: if(expressionP->X_subtract_symbol == expressionP->X_add_symbol){ ! 1005: expressionP->X_subtract_symbol = NULL; ! 1006: expressionP->X_add_symbol = NULL; ! 1007: expressionP->X_seg = SEG_ABSOLUTE; ! 1008: } ! 1009: break; ! 1010: ! 1011: default: ! 1012: BAD_CASE(expressionP->X_seg); ! 1013: break; ! 1014: } ! 1015: } ! 1016: ! 1017: /* ! 1018: * expr_part () ! 1019: * ! 1020: * Internal. Made a function because this code is used in 2 places. ! 1021: * Generate error or correct X_?????_symbol of expressionS. ! 1022: */ ! 1023: ! 1024: /* ! 1025: Combine and subsume symbol2 into symbol1 where the symbols come from ! 1026: expression's add or subtract symbols. ! 1027: The combining always occurs even if it would be an error. ! 1028: Either symbol maybe NULL which means there is no symbol. ! 1029: In that case symbol1 is set to the non NULL symbol. ! 1030: If both are NULL then SEG_ABSOLUTE is returned. ! 1031: Either symbol maybe undefined. ! 1032: The only combinations that are not errors are when one symbol does not exist. ! 1033: if one symbol is undefined and the other doesn't exist SEG_UNKNOWN is ! 1034: returned. ! 1035: For errant combinations symbol1 is set to NULL and SEG_ABSOLUTE (or -1 ! 1036: (SEG_PASS1) when one of the symbols is undefined and the other exists) ! 1037: ! 1038: * symbol_1 += symbol_2 ... well ... sort of. ! 1039: * symbol_1 -= symbol_2 ... well ... sort of. ! 1040: */ ! 1041: ! 1042: static ! 1043: segT ! 1044: expr_part( ! 1045: struct symbol **symbol_1_PP, ! 1046: struct symbol *symbol_2_P) ! 1047: { ! 1048: segT return_value; ! 1049: ! 1050: /* The symbols can't be N_ABS as they are in expressions and whould just have ! 1051: their value copied into the X_add_number part. */ ! 1052: know( (*symbol_1_PP) == NULL || ! 1053: ((*symbol_1_PP)->sy_type & N_TYPE) == N_SECT || ! 1054: ((*symbol_1_PP)->sy_type & N_TYPE) == N_UNDF); ! 1055: ! 1056: know( symbol_2_P == NULL || ! 1057: (symbol_2_P->sy_type & N_TYPE) == N_SECT || ! 1058: (symbol_2_P->sy_type & N_TYPE) == N_UNDF); ! 1059: ! 1060: /* check to see if there is a symbol1 */ ! 1061: if(*symbol_1_PP != NULL){ ! 1062: /* there is a symbol1 */ ! 1063: ! 1064: /* check to see if symbol1 is undefined */ ! 1065: if(((*symbol_1_PP)->sy_type & N_TYPE) == N_UNDF){ ! 1066: /* symbol1 is undefined */ ! 1067: ! 1068: /* check to see if there is a symbol2 */ ! 1069: if(symbol_2_P != NULL){ ! 1070: /* symbol1 is undefined and there is a symbol2 */ ! 1071: *symbol_1_PP = NULL; ! 1072: return_value = -1; ! 1073: } ! 1074: else{ ! 1075: /* symbol1 is undefined and there is no symbol2 */ ! 1076: return_value = SEG_UNKNOWN; ! 1077: } ! 1078: } ! 1079: else{ ! 1080: /* there is a defined symbol1 */ ! 1081: ! 1082: /* check to see if there is a symbol2 */ ! 1083: if(symbol_2_P != NULL){ ! 1084: /* there is a symbol2 */ ! 1085: ! 1086: /* check to see if symbol2 is undefined */ ! 1087: if((symbol_2_P->sy_type & N_TYPE) == N_UNDF){ ! 1088: /* symbol2 is undefined and symbol1 is defined */ ! 1089: *symbol_1_PP = NULL; ! 1090: return_value = -1; ! 1091: } ! 1092: else{ ! 1093: /* symbol1 is defined and symbol2 is defined */ ! 1094: /* + {symbol1} + {symbol2} or */ ! 1095: /* - {symbol1} - {symbol2} */ ! 1096: as_warn("Expression too complex, 2 symbols forgotten: " ! 1097: "\"%s\" \"%s\"", (*symbol_1_PP)->sy_name, ! 1098: symbol_2_P->sy_name); ! 1099: *symbol_1_PP = NULL; ! 1100: return_value = SEG_ABSOLUTE; ! 1101: } ! 1102: } ! 1103: else{ ! 1104: /* symbol1 is defined and there is no symbol2 */ ! 1105: return_value = N_TYPE_seg[(*symbol_1_PP)->sy_type & N_TYPE]; ! 1106: } ! 1107: } ! 1108: } ! 1109: else{ ! 1110: /* there is no symbol1 */ ! 1111: ! 1112: /* check to see if there is a symbol2 */ ! 1113: if(symbol_2_P != NULL){ ! 1114: /* symbol2 is defined and there is no symbol1 */ ! 1115: *symbol_1_PP = symbol_2_P; ! 1116: return_value = N_TYPE_seg[(symbol_2_P)->sy_type & N_TYPE]; ! 1117: } ! 1118: else{ ! 1119: /* there is no symbol1 or symbol2 */ ! 1120: /* ??? why not SEG_UNKNOWN or SEG_NONE */ ! 1121: return_value = SEG_ABSOLUTE; ! 1122: } ! 1123: } ! 1124: ! 1125: know(return_value == SEG_ABSOLUTE || ! 1126: return_value == SEG_SECT || ! 1127: return_value == SEG_UNKNOWN || ! 1128: return_value == -1); ! 1129: know((*symbol_1_PP) == NULL || ! 1130: ((*symbol_1_PP)->sy_type & N_TYPE) == ! 1131: seg_N_TYPE[(int)return_value]); ! 1132: ! 1133: return(return_value); ! 1134: } ! 1135: ! 1136: /* ! 1137: * DJA -- Here we make a last ditch effort to turn expressions into ! 1138: * absolutes. This is particularly useful for doing arithemtic ! 1139: * on already declared labels, for example in going through the ! 1140: * following table the moveq can really be evaluated. ! 1141: * ! 1142: * start: .word 1 ! 1143: * .word 2 ! 1144: * .word 3 ! 1145: * end: ! 1146: * lea start,a0 ! 1147: * moveq #((end-start) / 2) + 1,d0 ! 1148: * loop: cmpw d1,a0@+ ! 1149: * dbra d0,loop ! 1150: */ ! 1151: segT /* Return expressionP->X_seg. */ ! 1152: try_to_make_absolute( ! 1153: expressionS *expressionP) /* Deliver result here. */ ! 1154: { ! 1155: symbolS *add_symbol; ! 1156: symbolS *subtract_symbol; ! 1157: ! 1158: if(expressionP->X_seg == SEG_DIFFSECT){ ! 1159: ! 1160: add_symbol = expressionP->X_add_symbol; ! 1161: if(add_symbol == NULL) ! 1162: goto giveup; ! 1163: if((add_symbol->sy_type & N_TYPE) != N_SECT) ! 1164: goto giveup; ! 1165: ! 1166: subtract_symbol = expressionP->X_subtract_symbol; ! 1167: if(subtract_symbol == NULL) ! 1168: goto giveup; ! 1169: if((subtract_symbol->sy_type & N_TYPE) != N_SECT) ! 1170: goto giveup; ! 1171: ! 1172: if(add_symbol->sy_frag == subtract_symbol->sy_frag){ ! 1173: if(add_symbol->sy_frag != NULL && ! 1174: expressionP->X_add_number + ! 1175: (int)add_symbol->sy_value - ! 1176: (int)subtract_symbol->sy_value >= 0){ ! 1177: expressionP->X_add_number += add_symbol->sy_value - ! 1178: subtract_symbol->sy_value; ! 1179: expressionP->X_seg = SEG_ABSOLUTE; ! 1180: expressionP->X_add_symbol = NULL; ! 1181: expressionP->X_subtract_symbol = NULL; ! 1182: ! 1183: } ! 1184: } ! 1185: else{ ! 1186: /* ! 1187: * This logic works only if the chain of frags can't later be ! 1188: * separated by scattered loading. To make sure that this can't ! 1189: * happen we would have to make sure all symbols associated with ! 1190: * frags in the chain are of the Lx form and the -L flag is not ! 1191: * see so they will not appear in the output (if they are not in ! 1192: * the output then the link editor can't separate the chain of ! 1193: * frags by scattered loading). Since this code does not make ! 1194: * sure of this it is broken. But this is a known bug in the ! 1195: * NeXT 3.2 and earilier releases so this code is if'ed ! 1196: * !flagseen['k'] which will make it compatable with 3.2 and ! 1197: * previous releases. ! 1198: */ ! 1199: if(!flagseen['k']){ ! 1200: /* ! 1201: * Try to see if the chain of frags between the subtract ! 1202: * symbol and the add symbol is made up of only rs_fill and ! 1203: * rs_align frags and then calculate the difference. This ! 1204: * will always work on RISC machines since they won't have ! 1205: * any machine dependent frags of variable length in the ! 1206: * chain. ! 1207: */ ! 1208: unsigned long size, fail; ! 1209: struct frag *frag; ! 1210: ! 1211: if(add_symbol->sy_frag != NULL && ! 1212: subtract_symbol->sy_frag != NULL){ ! 1213: fail = 0; ! 1214: size = 0; ! 1215: frag = subtract_symbol->sy_frag; ! 1216: while(!fail && frag != NULL && ! 1217: frag != add_symbol->sy_frag){ ! 1218: if(frag->fr_type == rs_align) ! 1219: size = round(size + frag->fr_fix, ! 1220: 1 << frag->fr_offset); ! 1221: else if(frag->fr_type == rs_fill) ! 1222: size += frag->fr_fix + ! 1223: frag->fr_var * frag->fr_offset; ! 1224: else ! 1225: fail = 1; ! 1226: frag = frag->fr_next; ! 1227: } ! 1228: ! 1229: if(!fail && frag == add_symbol->sy_frag){ ! 1230: expressionP->X_add_number = size + ! 1231: add_symbol->sy_value - ! 1232: subtract_symbol->sy_value; ! 1233: expressionP->X_seg = SEG_ABSOLUTE; ! 1234: expressionP->X_add_symbol = NULL; ! 1235: expressionP->X_subtract_symbol = NULL; ! 1236: } ! 1237: } ! 1238: } ! 1239: } ! 1240: } ! 1241: giveup: ! 1242: ! 1243: return(expressionP->X_seg); ! 1244: } ! 1245: ! 1246: /* ! 1247: * two_char_op_encoding() return the operator type for two character operators. ! 1248: * The first_op_char is part of a two character operator and this routine is ! 1249: * then used to determine the operator type looking at the second character. ! 1250: */ ! 1251: static ! 1252: operatorT ! 1253: two_char_op_encoding( ! 1254: char first_op_char) ! 1255: { ! 1256: char second_op_char; ! 1257: ! 1258: second_op_char = input_line_pointer[1]; ! 1259: switch(first_op_char){ ! 1260: case '<': ! 1261: if(second_op_char == '<') ! 1262: return(O_left_shift); ! 1263: if(second_op_char == '=') ! 1264: return(O_less_than_or_equal); ! 1265: if(second_op_char == '>') ! 1266: return(O_not_equal); ! 1267: return(O_less_than); ! 1268: case '>': ! 1269: if(second_op_char == '>') ! 1270: return(O_right_shift); ! 1271: if(second_op_char == '=') ! 1272: return(O_greater_than_or_equal); ! 1273: return(O_greater_than); ! 1274: case '=': ! 1275: if(second_op_char == '=') ! 1276: return(O_equal); ! 1277: return(O_illegal); ! 1278: case '!': ! 1279: if(second_op_char == '=') ! 1280: return(O_not_equal); ! 1281: return O_not_equal; ! 1282: default: ! 1283: BAD_CASE(first_op_char); ! 1284: return O_illegal; ! 1285: } ! 1286: } ! 1287: ! 1288: /* ! 1289: * get_symbol_end() ! 1290: * ! 1291: * This lives here because it belongs equally in expr.c & read.c. ! 1292: * Expr.c is just a branch office read.c anyway, and putting it ! 1293: * here lessens the crowd at read.c. ! 1294: * ! 1295: * Assume input_line_pointer is at start of symbol name. ! 1296: * Advance input_line_pointer past symbol name. ! 1297: * Turn that character into a '\0', returning its former value. ! 1298: * This allows a string compare (RMS wants symbol names to be strings) ! 1299: * of the symbol name. ! 1300: * There will always be a char following symbol name, because all good ! 1301: * lines end in end-of-line. ! 1302: */ ! 1303: char ! 1304: get_symbol_end( ! 1305: void) ! 1306: { ! 1307: register char c; ! 1308: ! 1309: /* ! 1310: * Symbol names are allowed to have surrounding ""s so that names can ! 1311: * have any characters in them (including spacesi, colons, etc). This ! 1312: * is done so names like "[Foo bar:fuz:]" can be used as symbol names. ! 1313: */ ! 1314: if(*input_line_pointer == '"'){ ! 1315: input_line_pointer++; ! 1316: do{ ! 1317: c = *input_line_pointer++ ; ! 1318: }while(c != '"' && c != '\0' && c != '\n'); ! 1319: if(c == '"'){ ! 1320: *(input_line_pointer - 1) = 0; ! 1321: c = *input_line_pointer++; ! 1322: } ! 1323: } ! 1324: else{ ! 1325: while(is_part_of_name(c = *input_line_pointer++)) ! 1326: ; ! 1327: } ! 1328: *--input_line_pointer = 0; ! 1329: return(c); ! 1330: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.