📄 c-exp.y
字号:
switch (c = *tokstart) { case 0: return 0; case ' ': case '\t': case '\n': lexptr++; goto retry; case '\'': /* We either have a character constant ('0' or '\177' for example) or we have a quoted symbol reference ('foo(int,int)' in C++ for example). */ lexptr++; c = *lexptr++; if (c == '\\') c = parse_escape (&lexptr); yylval.lval = c; c = *lexptr++; if (c != '\'') { namelen = skip_quoted (tokstart) - tokstart; if (namelen > 2) { lexptr = tokstart + namelen; namelen -= 2; tokstart++; goto tryname; } error ("Invalid character constant."); } return CHAR; case '(': paren_depth++; lexptr++; return c; case ')': if (paren_depth == 0) return 0; paren_depth--; lexptr++; return c; case ',': if (comma_terminates && paren_depth == 0) return 0; lexptr++; return c; case '.': /* Might be a floating point number. */ if (lexptr[1] < '0' || lexptr[1] > '9') goto symbol; /* Nope, must be a symbol. */ /* FALL THRU into number case. */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { /* It's a number. */ int got_dot = 0, got_e = 0, toktype; register char *p = tokstart; int hex = input_radix > 10; if (c == '0' && (p[1] == 'x' || p[1] == 'X')) { p += 2; hex = 1; } else if (c == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D')) { p += 2; hex = 0; } for (;; ++p) { if (!hex && !got_e && (*p == 'e' || *p == 'E')) got_dot = got_e = 1; else if (!hex && !got_dot && *p == '.') got_dot = 1; else if (got_e && (p[-1] == 'e' || p[-1] == 'E') && (*p == '-' || *p == '+')) /* This is the sign of the exponent, not the end of the number. */ continue; /* We will take any letters or digits. parse_number will complain if past the radix, or if L or U are not final. */ else if ((*p < '0' || *p > '9') && ((*p < 'a' || *p > 'z') && (*p < 'A' || *p > 'Z'))) break; } toktype = parse_number (tokstart, p - tokstart, got_dot|got_e, &yylval); if (toktype == ERROR) { char *err_copy = (char *) alloca (p - tokstart + 1); memcpy (err_copy, tokstart, p - tokstart); err_copy[p - tokstart] = 0; error ("Invalid number \"%s\".", err_copy); } lexptr = p; return toktype; } case '+': case '-': case '*': case '/': case '%': case '|': case '&': case '^': case '~': case '!': case '@': case '<': case '>': case '[': case ']': case '?': case ':': case '=': case '{': case '}': symbol: lexptr++; return c; case '"': for (namelen = 1; (c = tokstart[namelen]) != '"'; namelen++) if (c == '\\') { c = tokstart[++namelen]; if (c >= '0' && c <= '9') { c = tokstart[++namelen]; if (c >= '0' && c <= '9') c = tokstart[++namelen]; } } yylval.sval.ptr = tokstart + 1; yylval.sval.length = namelen - 1; lexptr += namelen + 1; return STRING; } if (!(c == '_' || c == '$' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) /* We must have come across a bad character (e.g. ';'). */ error ("Invalid character '%c' in expression.", c); /* It's a name. See how long it is. */ namelen = 0; for (c = tokstart[namelen]; (c == '_' || c == '$' || (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); c = tokstart[++namelen]) ; /* The token "if" terminates the expression and is NOT removed from the input stream. */ if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f') { return 0; } lexptr += namelen; /* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1) and $$digits (equivalent to $<-digits> if you could type that). Make token type LAST, and put the number (the digits) in yylval. */ tryname: if (*tokstart == '$') { register int negate = 0; c = 1; /* Double dollar means negate the number and add -1 as well. Thus $$ alone means -1. */ if (namelen >= 2 && tokstart[1] == '$') { negate = 1; c = 2; } if (c == namelen) { /* Just dollars (one or two) */ yylval.lval = - negate; return LAST; } /* Is the rest of the token digits? */ for (; c < namelen; c++) if (!(tokstart[c] >= '0' && tokstart[c] <= '9')) break; if (c == namelen) { yylval.lval = atoi (tokstart + 1 + negate); if (negate) yylval.lval = - yylval.lval; return LAST; } } /* Handle tokens that refer to machine registers: $ followed by a register name. */ if (*tokstart == '$') { for (c = 0; c < NUM_REGS; c++) if (namelen - 1 == strlen (reg_names[c]) && !strncmp (tokstart + 1, reg_names[c], namelen - 1)) { yylval.lval = c; return REGNAME; } for (c = 0; c < num_std_regs; c++) if (namelen - 1 == strlen (std_regs[c].name) && !strncmp (tokstart + 1, std_regs[c].name, namelen - 1)) { yylval.lval = std_regs[c].regnum; return REGNAME; } } /* Catch specific keywords. Should be done with a data structure. */ switch (namelen) { case 8: if (!strncmp (tokstart, "unsigned", 8)) return UNSIGNED; if (current_language->la_language == language_cplus && !strncmp (tokstart, "template", 8)) return TEMPLATE; if (!strncmp (tokstart, "volatile", 8)) return VOLATILE_KEYWORD; break; case 6: if (!strncmp (tokstart, "struct", 6)) return STRUCT; if (!strncmp (tokstart, "signed", 6)) return SIGNED_KEYWORD; if (!strncmp (tokstart, "sizeof", 6)) return SIZEOF; break; case 5: if (current_language->la_language == language_cplus && !strncmp (tokstart, "class", 5)) return CLASS; if (!strncmp (tokstart, "union", 5)) return UNION; if (!strncmp (tokstart, "short", 5)) return SHORT; if (!strncmp (tokstart, "const", 5)) return CONST_KEYWORD; break; case 4: if (!strncmp (tokstart, "enum", 4)) return ENUM; if (!strncmp (tokstart, "long", 4)) return LONG; if (current_language->la_language == language_cplus && !strncmp (tokstart, "this", 4)) { static const char this_name[] = { CPLUS_MARKER, 't', 'h', 'i', 's', '\0' }; if (lookup_symbol (this_name, expression_context_block, VAR_NAMESPACE, 0, NULL)) return THIS; } break; case 3: if (!strncmp (tokstart, "int", 3)) return INT_KEYWORD; break; default: break; } yylval.sval.ptr = tokstart; yylval.sval.length = namelen; /* Any other names starting in $ are debugger internal variables. */ if (*tokstart == '$') { yylval.ivar = lookup_internalvar (copy_name (yylval.sval) + 1); return VARIABLE; } /* Use token-type BLOCKNAME for symbols that happen to be defined as functions or symtabs. If this is not so, then ... Use token-type TYPENAME for symbols that happen to be defined currently as names of types; NAME for other symbols. The caller is not constrained to care about the distinction. */ { char *tmp = copy_name (yylval.sval); struct symbol *sym; int is_a_field_of_this = 0; int hextype; sym = lookup_symbol (tmp, expression_context_block, VAR_NAMESPACE, current_language->la_language == language_cplus ? &is_a_field_of_this : NULL, NULL); if ((sym && SYMBOL_CLASS (sym) == LOC_BLOCK) || lookup_partial_symtab (tmp)) { yylval.ssym.sym = sym; yylval.ssym.is_a_field_of_this = is_a_field_of_this; return BLOCKNAME; } if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF) { yylval.tsym.type = SYMBOL_TYPE (sym); return TYPENAME; } if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0) return TYPENAME; /* Input names that aren't symbols but ARE valid hex numbers, when the input radix permits them, can be names or numbers depending on the parse. Note we support radixes > 16 here. */ if (!sym && ((tokstart[0] >= 'a' && tokstart[0] < 'a' + input_radix - 10) || (tokstart[0] >= 'A' && tokstart[0] < 'A' + input_radix - 10))) { YYSTYPE newlval; /* Its value is ignored. */ hextype = parse_number (tokstart, namelen, 0, &newlval); if (hextype == INT) { yylval.ssym.sym = sym; yylval.ssym.is_a_field_of_this = is_a_field_of_this; return NAME_OR_INT; } if (hextype == UINT) { yylval.ssym.sym = sym; yylval.ssym.is_a_field_of_this = is_a_field_of_this; return NAME_OR_UINT; } } /* Any other kind of symbol */ yylval.ssym.sym = sym; yylval.ssym.is_a_field_of_this = is_a_field_of_this; return NAME; }}voidyyerror (msg) char *msg;{ error (msg ? msg : "Invalid syntax in expression.");}/* Table mapping opcodes into strings for printing operators and precedences of the operators. */const static struct op_print c_op_print_tab[] = { {",", BINOP_COMMA, PREC_COMMA, 0}, {"=", BINOP_ASSIGN, PREC_ASSIGN, 1}, {"||", BINOP_OR, PREC_OR, 0}, {"&&", BINOP_AND, PREC_AND, 0}, {"|", BINOP_LOGIOR, PREC_LOGIOR, 0}, {"&", BINOP_LOGAND, PREC_LOGAND, 0}, {"^", BINOP_LOGXOR, PREC_LOGXOR, 0}, {"==", BINOP_EQUAL, PREC_EQUAL, 0}, {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0}, {"<=", BINOP_LEQ, PREC_ORDER, 0}, {">=", BINOP_GEQ, PREC_ORDER, 0}, {">", BINOP_GTR, PREC_ORDER, 0}, {"<", BINOP_LESS, PREC_ORDER, 0}, {">>", BINOP_RSH, PREC_SHIFT, 0}, {"<<", BINOP_LSH, PREC_SHIFT, 0}, {"+", BINOP_ADD, PREC_ADD, 0}, {"-", BINOP_SUB, PREC_ADD, 0}, {"*", BINOP_MUL, PREC_MUL, 0}, {"/", BINOP_DIV, PREC_MUL, 0}, {"%", BINOP_REM, PREC_MUL, 0}, {"@", BINOP_REPEAT, PREC_REPEAT, 0}, {"-", UNOP_NEG, PREC_PREFIX, 0}, {"!", UNOP_ZEROP, PREC_PREFIX, 0}, {"~", UNOP_LOGNOT, PREC_PREFIX, 0}, {"*", UNOP_IND, PREC_PREFIX, 0}, {"&", UNOP_ADDR, PREC_PREFIX, 0}, {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0}, {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0}, {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0}, /* C++ */ {"::", BINOP_SCOPE, PREC_PREFIX, 0},};/* These variables point to the objects representing the predefined C data types. */struct type *builtin_type_void;struct type *builtin_type_char;struct type *builtin_type_short;struct type *builtin_type_int;struct type *builtin_type_long;struct type *builtin_type_long_long;struct type *builtin_type_signed_char;struct type *builtin_type_unsigned_char;struct type *builtin_type_unsigned_short;struct type *builtin_type_unsigned_int;struct type *builtin_type_unsigned_long;struct type *builtin_type_unsigned_long_long;struct type *builtin_type_float;struct type *builtin_type_double;struct type *builtin_type_long_double;struct type *builtin_type_complex;struct type *builtin_type_double_complex;struct type ** const (c_builtin_types[]) = { &builtin_type_int, &builtin_type_long, &builtin_type_short, &builtin_type_char, &builtin_type_float, &builtin_type_double, &builtin_type_void, &builtin_type_long_long, &builtin_type_signed_char, &builtin_type_unsigned_char, &builtin_type_unsigned_short, &builtin_type_unsigned_int, &builtin_type_unsigned_long, &builtin_type_unsigned_long_long, &builtin_type_long_double, &builtin_type_complex, &builtin_type_double_complex, 0};const struct language_defn c_language_defn = { "c", /* Language name */ language_c, c_builtin_types, range_check_off, type_check_off, c_parse, c_error, &BUILTIN_TYPE_LONGEST, /* longest signed integral type */ &BUILTIN_TYPE_UNSIGNED_LONGEST,/* longest unsigned integral type */ &builtin_type_double, /* longest floating point type */ /*FIXME*/ "0x%x", "0x%", "x", /* Hex format, prefix, suffix */ "0%o", "0%", "o", /* Octal format, prefix, suffix */ c_op_print_tab, /* expression operators for printing */ LANG_MAGIC};const struct language_defn cplus_language_defn = { "c++", /* Language name */ language_cplus, c_builtin_types, range_check_off, type_check_off, c_parse, c_error, &BUILTIN_TYPE_LONGEST, /* longest signed integral type */ &BUILTIN_TYPE_UNSIGNED_LONGEST,/* longest unsigned integral type */ &builtin_type_double, /* longest floating point type */ /*FIXME*/ "0x%x", "0x%", "x", /* Hex format, prefix, suffix */ "0%o", "0%", "o", /* Octal format, prefix, suffix */ c_op_print_tab, /* expression operators for printing */ LANG_MAGIC};void_initialize_c_exp (){ builtin_type_void = init_type (TYPE_CODE_VOID, 1, 0, "void", (struct objfile *) NULL); builtin_type_char = init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, 0, "char", (struct objfile *) NULL); builtin_type_signed_char = init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, TYPE_FLAG_SIGNED, "signed char", (struct objfile *) NULL); builtin_type_unsigned_char = init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, TYPE_FLAG_UNSIGNED, "unsigned char", (struct objfile *) NULL); builtin_type_short = init_type (TYPE_CODE_INT, TARGET_SHORT_BIT / TARGET_CHAR_BIT, 0, "short", (struct objfile *) NULL); builtin_type_unsigned_short = init_type (TYPE_CODE_INT, TARGET_SHORT_BIT / TARGET_CHAR_BIT, TYPE_FLAG_UNSIGNED, "unsigned short", (struct objfile *) NULL); builtin_type_int = init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT, 0, "int", (struct objfile *) NULL); builtin_type_unsigned_int = init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT, TYPE_FLAG_UNSIGNED, "unsigned int", (struct objfile *) NULL); builtin_type_long = init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT, 0, "long", (struct objfile *) NULL); builtin_type_unsigned_long = init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT, TYPE_FLAG_UNSIGNED, "unsigned long", (struct objfile *) NULL); builtin_type_long_long = init_type (TYPE_CODE_INT, TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT, 0, "long long", (struct objfile *) NULL); builtin_type_unsigned_long_long = init_type (TYPE_CODE_INT, TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT, TYPE_FLAG_UNSIGNED, "unsigned long long", (struct objfile *) NULL); builtin_type_float = init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT, 0, "float", (struct objfile *) NULL); builtin_type_double = init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT, 0, "double", (struct objfile *) NULL); builtin_type_long_double = init_type (TYPE_CODE_FLT, TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT, 0, "long double", (struct objfile *) NULL); builtin_type_complex = init_type (TYPE_CODE_FLT, TARGET_COMPLEX_BIT / TARGET_CHAR_BIT, 0, "complex", (struct objfile *) NULL); builtin_type_double_complex = init_type (TYPE_CODE_FLT, TARGET_DOUBLE_COMPLEX_BIT / TARGET_CHAR_BIT, 0, "double complex", (struct objfile *) NULL); add_language (&c_language_defn); add_language (&cplus_language_defn);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -