📄 symexpr.c
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees * of Leland Stanford Junior University. * * This file is part of the SimOS distribution. * See LICENSE file for terms of the license. * */#include <stdlib.h>#include <stdio.h>#include <ctype.h>#include <string.h>#include "cpu_interface.h"#include "symbols.h"#include "symfile.h"#include "symexpr.h"#include "sim_error.h"/* CFL: * * top = exec:src:expr | exec:src:int * expr = *expr | &expr | (typecast) int | term * term = term.string | term->string | term[ int ] | term < int > | atom * atom = (expr) | string */#define MAX_STR_LEN 256#define BUFFER_SIZE 64int SymParseExpr(ParseInfo *pip);int SymParseTerm(ParseInfo *pip);int SymParseAtom(ParseInfo *pip);int SymParseField(ParseInfo *pip);int SymDeref(ParseInfo *pip);int SymParseTypeCast(ParseInfo *pip);char *SymParseString(ParseInfo *pip);int SymParseInt(char **str, Reg *val);static char ename[MAX_STR_LEN];static char fname[MAX_STR_LEN];int SymParse(char *symexpr, ParseInfo *pip){ int offset; char *str = symexpr; int line; if (sscanf(str, "%[^:]%n", ename, &offset) != 1) { ename[0] = '\0'; } else { str += offset; } if (*str++ != ':') { SymReportError("syntax error parsing execname", NULL); return SYM_ERROR; } if (sscanf(str, "%[^:]%n", fname, &offset) != 1) { fname[0] = '\0'; } else { str += offset; } if (*str++ != ':') { SymReportError("syntax error parsing source file name", NULL); return SYM_ERROR; } if (isdigit(*str)) { /* must be a line number */ if (sscanf(str, "%i%n", &line, &offset) != 1) { SymReportError("expected a line number, got \"", str, "\"", NULL); return SYM_ERROR; } if ((str[0] == '0') && (str[1] == '\0')) { ASSERT(line == 0); ASSERT(offset == 2); /* WAR bug in scanf */ offset = 1; } str += offset; if (SymLine2Addr(ename, fname, line, &(pip->sym)) != SYM_OK) { return SYM_ERROR; } pip->value = SymValue(&(pip->sym)); pip->constant = 1; } else { pip->execname = ename; pip->srcfile = fname; pip->str = str; pip->internal = (!strcmp(ename, "SIMOS"));#ifdef __alpha if (pip->internal) { return SYM_ERROR; }#endif if (SymParseExpr(pip) != SYM_OK) { return SYM_ERROR; } str = pip->str; } if (*str != '\0') { SymReportError("extra characters at end of expression\"", str, "\"", NULL); return SYM_ERROR; } return SYM_OK;}int SymParseExpr(ParseInfo *pip){ int code; if (pip->str[0] == '*') { pip->str++; if ((code = SymParseExpr(pip)) != SYM_OK) { return code; } if ((code = SymDeref(pip)) != SYM_OK) { return code; } } else if (pip->str[0] == '&') { pip->str++; if ((code = SymParseExpr(pip)) != SYM_OK) { return code; } if (pip->constant) { SymReportError("cannot take address of address", NULL); return SYM_ERROR; } SymMakeAddr(&pip->sym); pip->constant = 1; } else if (pip->str[0] == '(') { /* * OK here is the problem. This could be either a type cast or a * sub-expression. The way to figure this out is to read to the * matching end paren and see if the next token is anything but a * ".", "->", or a "[". We will just let SymParseTypeCast figure * it all out. */ return SymParseTypeCast(pip); } else { return SymParseTerm(pip); } return SYM_OK;}int SymParseTerm(ParseInfo *pip){ int code; if ((code = SymParseAtom(pip)) != SYM_OK) { return code; } while (1) { if (pip->str[0] == '.') { pip->str++; if ((code = SymParseField(pip)) != SYM_OK) { return code; } } else if ((pip->str[0] == '-') && (pip->str[1] == '>')) { pip->str += 2; if ((code = SymDeref(pip)) != SYM_OK) { return code; } if ((code = SymParseField(pip)) != SYM_OK) { return code; } } else if ((pip->str[0] == '[') || (pip->str[0] == '<')) { Reg val; pip->str++; if ((code = SymDeref(pip)) != SYM_OK) { return code; } if ((code = SymParseInt(&(pip->str), &val)) != SYM_OK) { return code; } if ((pip->str[0] != ']') && (pip->str[0] != '>')) { SymReportError("\"]\" or \">\" expected", NULL); return SYM_ERROR; } pip->str++; pip->value += val * SymSize(&(pip->sym)); } else if (pip->str[0] == ':') { char *symb; pip->str++; if (SymType(&(pip->sym), SYM_RESOLVE) != tProc) { SymReportError("can't use \":\" operator on non-procedure", NULL); return SYM_ERROR; } if (!(symb = SymParseString(pip))) { return SYM_ERROR; } if (!strcmp(symb, "START")) { } else if (!strcmp(symb, "STARTOPT")) { pip->value += 12; } else if (!strcmp(symb, "END")) { pip->value += SymSize(&(pip->sym)) - 4; } else if (SymFind(&(pip->sym), symb, 0) == SYM_OK) { if (SymType(&(pip->sym), SYM_RESOLVE) != tLabel) { SymReportError("symbol is not a label", NULL); return SYM_ERROR; } pip->value = SymValue(&(pip->sym)); } else { SymReportError("No such label in procedure", NULL); return SYM_ERROR; } return SYM_OK; } else { return SYM_OK; } } return SYM_OK;}int SymParseAtom(ParseInfo *pip){ int code; int st; if (pip->str[0] == '(') { pip->str++; if ((code = SymParseExpr(pip)) != SYM_OK) { return code; } if (pip->str[0] != ')') { SymReportError("\")\" expected", NULL); return SYM_ERROR; } pip->str++; } else if (isalpha(pip->str[0]) || (pip->str[0] == '_')) { char *symb; if (!(symb = SymParseString(pip))) { return SYM_ERROR; } #ifdef DWARF2 if (Dwarf_SymLookup(pip->execname, pip->srcfile, symb, 0, &(pip->sym)) != SYM_OK) { return SYM_ERROR; }#else if (SymLookup(pip->execname, pip->srcfile, symb, 0, &(pip->sym)) != SYM_OK) { return SYM_ERROR; }#endif st = SymType(&(pip->sym), SYM_RESOLVE); if ((st == tProc) || (st == tArray) || (st == tLabel)) { pip->constant = 1; } else { pip->constant = 0; } pip->value = SymValue(&(pip->sym)); } else { SymReportError("syntax error, expected \".\" or \"->\"", NULL); return SYM_ERROR; } return SYM_OK;}int SymParseField(ParseInfo *pip){ char *symb; int st; st = SymType(&(pip->sym), SYM_RESOLVE); if ((st != tStruct) && (st != tUnion)) { SymReportError("expected a structure", NULL); return SYM_ERROR; } ASSERT(!pip->constant); if (SymSubtype(&(pip->sym), SYM_RESOLVE) != SYM_OK) { return SYM_ERROR; } st = SymType(&(pip->sym), SYM_RESOLVE); if ((st != tStructDef) && (st != tUnionDef)) { ASSERT(0); return SYM_ERROR; } if (!(symb = SymParseString(pip))) { return SYM_ERROR; } if (SymFind(&(pip->sym), symb, 0) != SYM_OK) { return SYM_ERROR; } st = SymType(&(pip->sym), SYM_RESOLVE); if (st == tArray) { pip->constant = 1; } else { ASSERT(st != tProc); } /* it seems all fields are in bit width */ ASSERT(!(SymValue(&(pip->sym)) % 8)); pip->value += SymValue(&(pip->sym)) / 8; return SYM_OK;}int SymDeref(ParseInfo *pip){ Reg_s value = 0; int st; st = SymType(&(pip->sym), SYM_RESOLVE); if (st == tPtr) { if (pip->constant) { pip->constant = 0; } else if (pip->internal) { /* * XXX chances are that this is broken * XXX for some configurations */#ifdef __alpha ASSERT (0);#else pip->value = *(Reg_s*)pip->value;#endif } else { if (CPUVec.GetMemory(CPUVec.CurrentCpuNum(), pip->value, sizeof(value), (char *)&value) != SUCCESS) { SymReportError("addr not mapped", NULL); return SYM_ERROR; } pip->value = BE2HO_4(value); } } else if ((st == tAddr) || (st == tArray)) { ASSERT(pip->constant); pip->constant = 0; } else { SymReportError("array or pointer expected", NULL); return SYM_ERROR; } ASSERT(!pip->constant); if (SymSubtype(&(pip->sym), SYM_RESOLVE) != SYM_OK) { return SYM_ERROR; } st = SymType(&(pip->sym), SYM_RESOLVE); if (st == tArray) { pip->constant = 1; } else { ASSERT(st != tProc); } return SYM_OK;}/* * Type cast */static char *btNames[] = { "char", "uchar", "short", "ushort", "int", "uint", "long", "ulong", "float", "double", "struct", "union", "enum"};static int btTypes[] = { tChar, tUChar, tShort, tUShort, tInt, tUInt, tLong, tULong, tFloat, tDouble, tStruct, tUnion, tEnum};#define NUM_BTS (sizeof(btNames)/sizeof(char*))int SymParseTypeCast(ParseInfo *pip){ char *str; char *name = ""; char *scan; int level, i; int types[6]; int nextt; int bt; ASSERT(pip->str[0] == '('); /* check if it is a typecast */ for (level=1, scan=pip->str+1; level && *scan; scan++) { if (*scan == '(') { level++; } else if (*scan == ')') { level--; } } if ((*scan == '.') || (*scan == '[') || (*scan == '<') || (*scan == ')') || (*scan == '\0') || ((*scan == '-') && (*(scan+1) == '>'))) { /* not a typecast - oh well just parse it as a term */ return SymParseTerm(pip); } /* its a type cast */ pip->str++; nextt = 0; str = SymParseString(pip); bt = -1; for (i=0; i<NUM_BTS; i++) { if (!strcmp(str, btNames[i])) { bt = btTypes[i]; break; } } if (i == NUM_BTS) { name = str; bt = tTypedef; } else if ((bt == tStruct) || (bt == tUnion) || (bt == tEnum)) { while (*pip->str == ' ') { pip->str++; } name = SymParseString(pip); } else { name = ""; } while (1) { while (*pip->str == ' ') { pip->str++; } if (pip->str[0] == '*') { types[nextt++] = tPtr; pip->str++; } else { break; } } types[nextt++] = bt; types[nextt++] = tNil; if ((types[0] != tPtr) && !((types[0] >= tChar) && (types[0] <= tDouble))) { SymReportError("Can only cast to pointer or basic type", NULL); return SYM_ERROR; } if (pip->str[0] != ')') { SymReportError("Syntax error in type cast", NULL); return SYM_ERROR; } pip->str++; if (SymParseInt(&(pip->str), &(pip->value)) == SYM_OK) { pip->constant = 1; } else { SymReportError("Only type casting hard coded constants suported so far. Sorry.", NULL); return SYM_ERROR;#ifdef notdef /* XXX fix */ if ((code = SymParseExpr(pip)) != SYM_OK) { return code; } pip->constant = 0;#endif }#ifdef DWARF2_not if (Dwarf_SymTypeCast(pip->execname, pip->srcfile, types, name, &(pip->sym)) != SYM_OK) { return SYM_ERROR; }#else if (SymTypeCast(pip->execname, pip->srcfile, types, name, &(pip->sym)) != SYM_OK) { return SYM_ERROR; }#endif return SYM_OK;}int SymParseInt(char **str, Reg *val){ int offset; while (**str == ' ') { (*str)++; } if (isdigit(**str)) { int i; uint64 val64=0;#ifdef __alpha i = sscanf(*str, "%li%n", &val64, &offset);#else i = sscanf(*str, "%lli%n", &val64, &offset);#endif *val = val64; if (i != 1) { return SYM_ERROR; } *str += offset; while (**str == ' ') { (*str)++; } } else { SymReportError("expected an int, got \"", str, "\"", NULL); return SYM_ERROR; } return SYM_OK;}char *SymParseString(ParseInfo *pip){ static char buf[BUFFER_SIZE]; char *dst = buf; while (isalnum(*(pip->str)) || (*(pip->str) == '_')) { if ((dst - buf) == (BUFFER_SIZE-1)) { SymReportError("symbol overflowed internal buffers (internal error)", NULL); return NULL; } *dst++ = *(pip->str)++; } *dst = '\0'; if (!buf[0]) { SymReportError("expected a string", NULL); } return buf;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -