📄 m2-exp.y
字号:
{ write_exp_elt_opcode (OP_LONG); write_exp_elt_type (builtin_type_int); write_exp_elt_longcst ((LONGEST) msymbol -> address); write_exp_elt_opcode (OP_LONG); write_exp_elt_opcode (UNOP_MEMVAL); if (msymbol -> type == mst_data || msymbol -> type == mst_bss) write_exp_elt_type (builtin_type_int); else if (msymbol -> type == mst_text) write_exp_elt_type (lookup_function_type (builtin_type_int)); else write_exp_elt_type (builtin_type_char); write_exp_elt_opcode (UNOP_MEMVAL); } else if (!have_full_symbols () && !have_partial_symbols ()) error ("No symbol table is loaded. Use the \"symbol-file\" command."); else error ("No symbol \"%s\" in current context.", copy_name ($1)); } } ;type : TYPENAME { $$ = lookup_typename (copy_name ($1), expression_context_block, 0); } ;%%#if 0 /* FIXME! */intoverflow(a,b) long a,b;{ return (MAX_OF_TYPE(builtin_type_m2_int) - b) < a;}intuoverflow(a,b) unsigned long a,b;{ return (MAX_OF_TYPE(builtin_type_m2_card) - b) < a;}#endif /* FIXME *//* Take care of parsing a number (anything that starts with a digit). Set yylval and return the token type; update lexptr. LEN is the number of characters in it. *//*** Needs some error checking for the float case ***/static intparse_number (olen) int olen;{ register char *p = lexptr; register LONGEST n = 0; register LONGEST prevn = 0; register int c,i,ischar=0; register int base = input_radix; register int len = olen; int unsigned_p = number_sign == 1 ? 1 : 0; if(p[len-1] == 'H') { base = 16; len--; } else if(p[len-1] == 'C' || p[len-1] == 'B') { base = 8; ischar = p[len-1] == 'C'; len--; } /* Scan the number */ for (c = 0; c < len; c++) { if (p[c] == '.' && base == 10) { /* It's a float since it contains a point. */ yylval.dval = atof (p); lexptr += len; return FLOAT; } if (p[c] == '.' && base != 10) error("Floating point numbers must be base 10."); if (base == 10 && (p[c] < '0' || p[c] > '9')) error("Invalid digit \'%c\' in number.",p[c]); } while (len-- > 0) { c = *p++; n *= base; if( base == 8 && (c == '8' || c == '9')) error("Invalid digit \'%c\' in octal number.",c); if (c >= '0' && c <= '9') i = c - '0'; else { if (base == 16 && c >= 'A' && c <= 'F') i = c - 'A' + 10; else return ERROR; } n+=i; if(i >= base) return ERROR; if(!unsigned_p && number_sign == 1 && (prevn >= n)) unsigned_p=1; /* Try something unsigned */ /* Don't do the range check if n==i and i==0, since that special case will give an overflow error. */ if(RANGE_CHECK && n!=i && i) { if((unsigned_p && (unsigned)prevn >= (unsigned)n) || ((!unsigned_p && number_sign==-1) && -prevn <= -n)) range_error("Overflow on numeric constant."); } prevn=n; } lexptr = p; if(*p == 'B' || *p == 'C' || *p == 'H') lexptr++; /* Advance past B,C or H */ if (ischar) { yylval.ulval = n; return CHAR; } else if ( unsigned_p && number_sign == 1) { yylval.ulval = n; return UINT; } else if((unsigned_p && (n<0))) { range_error("Overflow on numeric constant -- number too large."); /* But, this can return if range_check == range_warn. */ } yylval.lval = n; return INT;}/* Some tokens */static struct{ char name[4]; int token;} tokentab2[] ={ { {'<', '>'}, NOTEQUAL }, { {':', '='}, ASSIGN }, { {'<', '='}, LEQ }, { {'>', '='}, GEQ }, { {':', ':'}, COLONCOLON },};/* Some specific keywords */struct keyword { char keyw[10]; int token;};static struct keyword keytab[] ={ {"OR" , OROR }, {"IN", IN },/* Note space after IN */ {"AND", ANDAND }, {"ABS", ABS }, {"CHR", CHR }, {"DEC", DEC }, {"NOT", NOT }, {"DIV", DIV }, {"INC", INC }, {"MAX", MAX_FUNC }, {"MIN", MIN_FUNC }, {"MOD", MOD }, {"ODD", ODD }, {"CAP", CAP }, {"ORD", ORD }, {"VAL", VAL }, {"EXCL", EXCL }, {"HIGH", HIGH }, {"INCL", INCL }, {"SIZE", SIZE }, {"FLOAT", FLOAT_FUNC }, {"TRUNC", TRUNC },};/* Read one token, getting characters through lexptr. *//* This is where we will check to make sure that the language and the operators used are compatible */static intyylex (){ register int c; register int namelen; register int i; register char *tokstart; register char quote; retry: tokstart = lexptr; /* See if it is a special token of length 2 */ for( i = 0 ; i < sizeof tokentab2 / sizeof tokentab2[0] ; i++) if(!strncmp(tokentab2[i].name, tokstart, 2)) { lexptr += 2; return tokentab2[i].token; } switch (c = *tokstart) { case 0: return 0; case ' ': case '\t': case '\n': lexptr++; goto retry; 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') break; /* Falls into number code. */ else { lexptr++; return DOT; }/* These are character tokens that appear as-is in the YACC grammar */ case '+': case '-': case '*': case '/': case '^': case '<': case '>': case '[': case ']': case '=': case '{': case '}': case '#': case '@': case '~': case '&': lexptr++; return c; case '\'' : case '"': quote = c; for (namelen = 1; (c = tokstart[namelen]) != quote && c != '\0'; namelen++) if (c == '\\') { c = tokstart[++namelen]; if (c >= '0' && c <= '9') { c = tokstart[++namelen]; if (c >= '0' && c <= '9') c = tokstart[++namelen]; } } if(c != quote) error("Unterminated string or character constant."); yylval.sval.ptr = tokstart + 1; yylval.sval.length = namelen - 1; lexptr += namelen + 1; if(namelen == 2) /* Single character */ { yylval.ulval = tokstart[1]; return CHAR; } else return STRING; } /* Is it a number? */ /* Note: We have already dealt with the case of the token '.'. See case '.' above. */ if ((c >= '0' && c <= '9')) { /* It's a number. */ int got_dot = 0, got_e = 0; register char *p = tokstart; int toktype; for (++p ;; ++p) { if (!got_e && (*p == 'e' || *p == 'E')) got_dot = got_e = 1; else if (!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; else if ((*p < '0' || *p > '9') && (*p < 'A' || *p > 'F') && (*p != 'H')) /* Modula-2 hexadecimal number */ break; } toktype = parse_number (p - tokstart); 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; } 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. */ 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; } } /* Lookup special keywords */ for(i = 0 ; i < sizeof(keytab) / sizeof(keytab[0]) ; i++) if(namelen == strlen(keytab[i].keyw) && !strncmp(tokstart,keytab[i].keyw,namelen)) return keytab[i].token; yylval.sval.ptr = tokstart; yylval.sval.length = namelen; /* Any other names starting in $ are debugger internal variables. */ if (*tokstart == '$') { yylval.ivar = (struct internalvar *) lookup_internalvar (copy_name (yylval.sval) + 1); return INTERNAL_VAR; } /* Use token-type BLOCKNAME for symbols that happen to be defined as functions. 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; if (lookup_partial_symtab (tmp)) return BLOCKNAME; sym = lookup_symbol (tmp, expression_context_block, VAR_NAMESPACE, 0, NULL); if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK) return BLOCKNAME; if (lookup_typename (copy_name (yylval.sval), expression_context_block, 1)) return TYPENAME; if(sym) { switch(sym->class) { case LOC_STATIC: case LOC_REGISTER: case LOC_ARG: case LOC_REF_ARG: case LOC_REGPARM: case LOC_LOCAL: case LOC_LOCAL_ARG: case LOC_CONST: case LOC_CONST_BYTES: return NAME; case LOC_TYPEDEF: return TYPENAME; case LOC_BLOCK: return BLOCKNAME; case LOC_UNDEF: error("internal: Undefined class in m2lex()"); case LOC_LABEL: error("internal: Unforseen case in m2lex()"); } } else { /* Built-in BOOLEAN type. This is sort of a hack. */ if(!strncmp(tokstart,"TRUE",4)) { yylval.ulval = 1; return M2_TRUE; } else if(!strncmp(tokstart,"FALSE",5)) { yylval.ulval = 0; return M2_FALSE; } } /* Must be another type of name... */ return NAME; }}#if 0 /* Unused */static char *make_qualname(mod,ident) char *mod, *ident;{ char *new = xmalloc(strlen(mod)+strlen(ident)+2); strcpy(new,mod); strcat(new,"."); strcat(new,ident); return new;}#endif /* 0 */static voidyyerror(msg) char *msg; /* unused */{ printf("Parsing: %s\n",lexptr); if (yychar < 256) error("Invalid syntax in expression near character '%c'.",yychar); else error("Invalid syntax in expression");}/* Table of operators and their precedences for printing expressions. */const static struct op_print m2_op_print_tab[] = { {"+", BINOP_ADD, PREC_ADD, 0}, {"+", UNOP_PLUS, PREC_PREFIX, 0}, {"-", BINOP_SUB, PREC_ADD, 0}, {"-", UNOP_NEG, PREC_PREFIX, 0}, {"*", BINOP_MUL, PREC_MUL, 0}, {"/", BINOP_DIV, PREC_MUL, 0}, {"DIV", BINOP_INTDIV, PREC_MUL, 0}, {"MOD", BINOP_REM, PREC_MUL, 0}, {":=", BINOP_ASSIGN, PREC_ASSIGN, 1}, {"OR", BINOP_OR, PREC_OR, 0}, {"AND", BINOP_AND, PREC_AND, 0}, {"NOT", UNOP_ZEROP, PREC_PREFIX, 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}, {"^", UNOP_IND, PREC_PREFIX, 0}, {"@", BINOP_REPEAT, PREC_REPEAT, 0},};/* The built-in types of Modula-2. */struct type *builtin_type_m2_char;struct type *builtin_type_m2_int;struct type *builtin_type_m2_card;struct type *builtin_type_m2_real;struct type *builtin_type_m2_bool;struct type ** const (m2_builtin_types[]) = { &builtin_type_m2_char, &builtin_type_m2_int, &builtin_type_m2_card, &builtin_type_m2_real, &builtin_type_m2_bool, 0};const struct language_defn m2_language_defn = { "modula-2", language_m2, m2_builtin_types, range_check_on, type_check_on, m2_parse, /* parser */ m2_error, /* parser error function */ &builtin_type_m2_int, /* longest signed integral type */ &builtin_type_m2_card, /* longest unsigned integral type */ &builtin_type_m2_real, /* longest floating point type */ "0%XH", "0%", "XH", /* Hex format string, prefix, suffix */ "%oB", "%", "oB", /* Octal format string, prefix, suffix */ m2_op_print_tab, /* expression operators for printing */ LANG_MAGIC};/* Initialization for Modula-2 */void_initialize_m2_exp (){ /* Modula-2 "pervasive" types. NOTE: these can be redefined!!! */ builtin_type_m2_int = init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT, 0, "INTEGER", (struct objfile *) NULL); builtin_type_m2_card = init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT, TYPE_FLAG_UNSIGNED, "CARDINAL", (struct objfile *) NULL); builtin_type_m2_real = init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT, 0, "REAL", (struct objfile *) NULL); builtin_type_m2_char = init_type (TYPE_CODE_CHAR, TARGET_CHAR_BIT / TARGET_CHAR_BIT, TYPE_FLAG_UNSIGNED, "CHAR", (struct objfile *) NULL); builtin_type_m2_bool = init_type (TYPE_CODE_BOOL, TARGET_INT_BIT / TARGET_CHAR_BIT, TYPE_FLAG_UNSIGNED, "BOOLEAN", (struct objfile *) NULL); TYPE_NFIELDS(builtin_type_m2_bool) = 2; TYPE_FIELDS(builtin_type_m2_bool) = (struct field *) malloc (sizeof (struct field) * 2); TYPE_FIELD_BITPOS(builtin_type_m2_bool,0) = 0; TYPE_FIELD_NAME(builtin_type_m2_bool,0) = (char *)malloc(6); strcpy(TYPE_FIELD_NAME(builtin_type_m2_bool,0),"FALSE"); TYPE_FIELD_BITPOS(builtin_type_m2_bool,1) = 1; TYPE_FIELD_NAME(builtin_type_m2_bool,1) = (char *)malloc(5); strcpy(TYPE_FIELD_NAME(builtin_type_m2_bool,1),"TRUE"); add_language (&m2_language_defn);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -