expr.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,924 行 · 第 1/4 页
C
1,924 行
} else if (!small) { /* We saw a lot of digits. manufacture a bignum the hard way. */ LITTLENUM_TYPE *leader; /* -> high order littlenum of the bignum. */ LITTLENUM_TYPE *pointer; /* -> littlenum we are frobbing now. */ long carry; leader = generic_bignum; generic_bignum[0] = 0; generic_bignum[1] = 0; generic_bignum[2] = 0; generic_bignum[3] = 0; input_line_pointer = start; /* -> 1st digit. */ c = *input_line_pointer++; for (; (carry = hex_value (c)) < maxdig; c = *input_line_pointer++) { for (pointer = generic_bignum; pointer <= leader; pointer++) { long work; work = carry + radix * *pointer; *pointer = work & LITTLENUM_MASK; carry = work >> LITTLENUM_NUMBER_OF_BITS; } if (carry) { if (leader < generic_bignum + SIZE_OF_LARGE_NUMBER - 1) { /* Room to grow a longer bignum. */ *++leader = carry; } } } /* Again, c is char after number. */ /* input_line_pointer -> after c. */ know (LITTLENUM_NUMBER_OF_BITS == 16); if (leader < generic_bignum + 2) { /* Will fit into 32 bits. */ number = generic_bignum_to_int32 (); small = 1; }#ifdef BFD64 else if (leader < generic_bignum + 4) { /* Will fit into 64 bits. */ number = generic_bignum_to_int64 (); small = 1; }#endif else { /* Number of littlenums in the bignum. */ number = leader - generic_bignum + 1; } } if ((NUMBERS_WITH_SUFFIX || flag_m68k_mri) && suffix != NULL && input_line_pointer - 1 == suffix) c = *input_line_pointer++; if (small) { /* Here with number, in correct radix. c is the next char. Note that unlike un*x, we allow "011f" "0x9f" to both mean the same as the (conventional) "9f". This is simply easier than checking for strict canonical form. Syntax sux! */ if (LOCAL_LABELS_FB && c == 'b') { /* Backward ref to local label. Because it is backward, expect it to be defined. */ /* Construct a local label. */ name = fb_label_name ((int) number, 0); /* Seen before, or symbol is defined: OK. */ symbolP = symbol_find (name); if ((symbolP != NULL) && (S_IS_DEFINED (symbolP))) { /* Local labels are never absolute. Don't waste time checking absoluteness. */ know (SEG_NORMAL (S_GET_SEGMENT (symbolP))); expressionP->X_op = O_symbol; expressionP->X_add_symbol = symbolP; } else { /* Either not seen or not defined. */ /* @@ Should print out the original string instead of the parsed number. */ as_bad (_("backw. ref to unknown label \"%d:\", 0 assumed."), (int) number); expressionP->X_op = O_constant; } expressionP->X_add_number = 0; } /* case 'b' */ else if (LOCAL_LABELS_FB && c == 'f') { /* Forward reference. Expect symbol to be undefined or unknown. undefined: seen it before. unknown: never seen it before. Construct a local label name, then an undefined symbol. Don't create a xseg frag for it: caller may do that. Just return it as never seen before. */ name = fb_label_name ((int) number, 1); symbolP = symbol_find_or_make (name); /* We have no need to check symbol properties. */#ifndef many_segments /* Since "know" puts its arg into a "string", we can't have newlines in the argument. */ know (S_GET_SEGMENT (symbolP) == undefined_section || S_GET_SEGMENT (symbolP) == text_section || S_GET_SEGMENT (symbolP) == data_section);#endif expressionP->X_op = O_symbol; expressionP->X_add_symbol = symbolP; expressionP->X_add_number = 0; } /* case 'f' */ else if (LOCAL_LABELS_DOLLAR && c == '$') { /* If the dollar label is *currently* defined, then this is just another reference to it. If it is not *currently* defined, then this is a fresh instantiation of that number, so create it. */ if (dollar_label_defined ((long) number)) { name = dollar_label_name ((long) number, 0); symbolP = symbol_find (name); know (symbolP != NULL); } else { name = dollar_label_name ((long) number, 1); symbolP = symbol_find_or_make (name); } expressionP->X_op = O_symbol; expressionP->X_add_symbol = symbolP; expressionP->X_add_number = 0; } /* case '$' */ else { expressionP->X_op = O_constant;#ifdef TARGET_WORD_SIZE /* Sign extend NUMBER. */ number |= (-(number >> (TARGET_WORD_SIZE - 1))) << (TARGET_WORD_SIZE - 1);#endif expressionP->X_add_number = number; input_line_pointer--; /* Restore following character. */ } /* Really just a number. */ } else { /* Not a small number. */ expressionP->X_op = O_big; expressionP->X_add_number = number; /* Number of littlenums. */ input_line_pointer--; /* -> char following number. */ }}/* Parse an MRI multi character constant. */static voidmri_char_constant (expressionP) expressionS *expressionP;{ int i; if (*input_line_pointer == '\'' && input_line_pointer[1] != '\'') { expressionP->X_op = O_constant; expressionP->X_add_number = 0; return; } /* In order to get the correct byte ordering, we must build the number in reverse. */ for (i = SIZE_OF_LARGE_NUMBER - 1; i >= 0; i--) { int j; generic_bignum[i] = 0; for (j = 0; j < CHARS_PER_LITTLENUM; j++) { if (*input_line_pointer == '\'') { if (input_line_pointer[1] != '\'') break; ++input_line_pointer; } generic_bignum[i] <<= 8; generic_bignum[i] += *input_line_pointer; ++input_line_pointer; } if (i < SIZE_OF_LARGE_NUMBER - 1) { /* If there is more than one littlenum, left justify the last one to make it match the earlier ones. If there is only one, we can just use the value directly. */ for (; j < CHARS_PER_LITTLENUM; j++) generic_bignum[i] <<= 8; } if (*input_line_pointer == '\'' && input_line_pointer[1] != '\'') break; } if (i < 0) { as_bad (_("Character constant too large")); i = 0; } if (i > 0) { int c; int j; c = SIZE_OF_LARGE_NUMBER - i; for (j = 0; j < c; j++) generic_bignum[j] = generic_bignum[i + j]; i = c; } know (LITTLENUM_NUMBER_OF_BITS == 16); if (i > 2) { expressionP->X_op = O_big; expressionP->X_add_number = i; } else { expressionP->X_op = O_constant; if (i < 2) expressionP->X_add_number = generic_bignum[0] & LITTLENUM_MASK; else expressionP->X_add_number = (((generic_bignum[1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS) | (generic_bignum[0] & LITTLENUM_MASK)); } /* Skip the final closing quote. */ ++input_line_pointer;}/* Return an expression representing the current location. This handles the magic symbol `.'. */static voidcurrent_location (expressionp) expressionS *expressionp;{ if (now_seg == absolute_section) { expressionp->X_op = O_constant; expressionp->X_add_number = abs_section_offset; } else { symbolS *symbolp; symbolp = symbol_new (FAKE_LABEL_NAME, now_seg, (valueT) frag_now_fix (), frag_now); expressionp->X_op = O_symbol; expressionp->X_add_symbol = symbolp; expressionp->X_add_number = 0; }}/* In: Input_line_pointer points to 1st char of operand, which may be a space. Out: A expressionS. The operand may have been empty: in this case X_op == O_absent. Input_line_pointer->(next non-blank) char after operand. */static segToperand (expressionP) expressionS *expressionP;{ char c; symbolS *symbolP; /* Points to symbol. */ char *name; /* Points to name of symbol. */ segT segment; /* All integers are regarded as unsigned unless they are negated. This is because the only thing which cares whether a number is unsigned is the code in emit_expr which extends constants into bignums. It should only sign extend negative numbers, so that something like ``.quad 0x80000000'' is not sign extended even though it appears negative if valueT is 32 bits. */ expressionP->X_unsigned = 1; /* Digits, assume it is a bignum. */ SKIP_WHITESPACE (); /* Leading whitespace is part of operand. */ c = *input_line_pointer++; /* input_line_pointer -> past char in c. */ if (is_end_of_line[(unsigned char) c]) goto eol; switch (c) { case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': input_line_pointer--; integer_constant ((NUMBERS_WITH_SUFFIX || flag_m68k_mri) ? 0 : 10, expressionP); break;#ifdef LITERAL_PREFIXDOLLAR_HEX case '$': integer_constant (16, expressionP); break;#endif#ifdef LITERAL_PREFIXPERCENT_BIN case '%': integer_constant (2, expressionP); break;#endif case '0': /* Non-decimal radix. */ if (NUMBERS_WITH_SUFFIX || flag_m68k_mri) { char *s; /* Check for a hex constant. */ for (s = input_line_pointer; hex_p (*s); s++) ; if (*s == 'h' || *s == 'H') { --input_line_pointer; integer_constant (0, expressionP); break; } } c = *input_line_pointer; switch (c) { case 'o': case 'O': case 'q': case 'Q': case '8': case '9': if (NUMBERS_WITH_SUFFIX || flag_m68k_mri) { integer_constant (0, expressionP); break; } /* Fall through. */ default: default_case: if (c && strchr (FLT_CHARS, c)) { input_line_pointer++; floating_constant (expressionP); expressionP->X_add_number = - (isupper ((unsigned char) c) ? tolower (c) : c); } else { /* The string was only zero. */ expressionP->X_op = O_constant; expressionP->X_add_number = 0; } break; case 'x': case 'X': if (flag_m68k_mri) goto default_case; input_line_pointer++; integer_constant (16, expressionP); break; case 'b': if (LOCAL_LABELS_FB && ! (flag_m68k_mri || NUMBERS_WITH_SUFFIX)) { /* This code used to check for '+' and '-' here, and, in some conditions, fall through to call integer_constant. However, that didn't make sense, as integer_constant only accepts digits. */ /* Some of our code elsewhere does permit digits greater than the expected base; for consistency, do the same here. */ if (input_line_pointer[1] < '0' || input_line_pointer[1] > '9') { /* Parse this as a back reference to label 0. */ input_line_pointer--; integer_constant (10, expressionP); break; } /* Otherwise, parse this as a binary number. */ } /* Fall through. */ case 'B': input_line_pointer++; if (flag_m68k_mri || NUMBERS_WITH_SUFFIX) goto default_case; integer_constant (2, expressionP); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': integer_constant ((flag_m68k_mri || NUMBERS_WITH_SUFFIX) ? 0 : 8, expressionP); break; case 'f': if (LOCAL_LABELS_FB) { /* If it says "0f" and it could possibly be a floating point number, make it one. Otherwise, make it a local label, and try to deal with parsing the rest later. */ if (!input_line_pointer[1] || (is_end_of_line[0xff & input_line_pointer[1]]) || strchr (FLT_CHARS, 'f') == NULL) goto is_0f_label; { char *cp = input_line_pointer + 1; int r = atof_generic (&cp, ".", EXP_CHARS, &generic_floating_point_number); switch (r) { case 0: case ERROR_EXPONENT_OVERFLOW: if (*cp == 'f' || *cp == 'b') /* Looks like a difference expression. */ goto is_0f_label; else if (cp == input_line_pointer + 1) /* No characters has been accepted -- looks like end of operand. */ goto is_0f_label; else goto is_0f_float; default: as_fatal (_("expr.c(operand): bad atof_generic return val %d"), r); } } /* Okay, now we've sorted it out. We resume at one of these two labels, depending on what we've decided we're probably looking at. */ is_0f_label: input_line_pointer--; integer_constant (10, expressionP); break;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?