📄 sesl_expr.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 "sesl_lib.h"#include "sesl_expr.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 special);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; SESL_ADDR temp_addr; 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 (!(temp_addr = SESL_Line2Addr(ename, fname, line))) { return SYM_ERROR; } if (!(pip->sym = SESL_CreateSymbol(pip->execname, temp_addr, "int"))) { return SYM_ERROR; } pip->value = SESL_GetAddress(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; } pip->value = SESL_GetAddress(pip->sym); 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; } 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->sym = SESL_Index(pip->sym, val); pip->value = SESL_GetAddress(pip->sym); } else if (pip->str[0] == ':') { char *symb; pip->str++; if (SESL_GetType(pip->sym) != SESL_TYPE_FUNC) { SymReportError("can't use \":\" operator on non-procedure", NULL); return SYM_ERROR; } if (!(symb = SymParseString(pip,0))) { return SYM_ERROR; } if (!strcmp(symb, "START")) { } else if (!strcmp(symb, "STARTOPT")) { pip->sym = SESL_Index(pip->sym, 12); pip->value = SESL_GetAddress(pip->sym); } else if (!strcmp(symb, "END")) { pip->sym = SESL_Index(pip->sym, ((long)SESL_GetSize(pip->sym))-4); pip->value = SESL_GetAddress(pip->sym); } else if ((pip->sym = SESL_FindInBlock(pip->sym, symb))) { if (SESL_GetType(pip->sym) != SESL_TYPE_LABEL) { SymReportError("symbol is not a label", NULL); return SYM_ERROR; } pip->value = SESL_GetAddress(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,0))) { return SYM_ERROR; } if (!(pip->sym = SESL_LookupSymbol(pip->execname, pip->srcfile, symb))) { SymReportError("SESL_LookupSymbol returned failure", NULL); return SYM_ERROR; } st = SESL_GetType(pip->sym); if ((st == SESL_TYPE_FUNC) || (st == SESL_TYPE_LABEL) || (st == SESL_TYPE_ARRAY)) { pip->constant = 1; } else { pip->constant = 0; } pip->value = SESL_GetAddress(pip->sym); } else if (isdigit(pip->str[0])) { char *symb; Reg val; if ((SymParseInt(&(pip->str), &val)) != SYM_OK) { return SYM_ERROR; } if (!(pip->sym = SESL_CreateSymbol(pip->execname, val, "int"))) { return SYM_ERROR; } pip->value = SESL_GetAddress(pip->sym); pip->constant = 1; } else { SymReportError("syntax error, expected \".\" or \"->\"", NULL); return SYM_ERROR; } return SYM_OK;}int SymParseField(ParseInfo *pip){ char *symb; int st; while (SESL_CanDereference(pip->sym)) { if (SymDeref(pip) != SYM_OK) { return SYM_ERROR; } } st = SESL_GetType(pip->sym); if ((st != SESL_TYPE_STRUCT) && (st != SESL_TYPE_UNION)) { SymReportError("expected a structure", NULL); return SYM_ERROR; } ASSERT(!pip->constant); if (!(symb = SymParseString(pip,0))) { return SYM_ERROR; } if (!(pip->sym = SESL_FindMember(pip->sym, symb))) { return SYM_ERROR; } st = SESL_GetType(pip->sym); if (st == SESL_TYPE_ARRAY) pip->constant = 1; else ASSERT(st != SESL_TYPE_FUNC); pip->value = SESL_GetAddress(pip->sym); return SYM_OK;}int SymDeref(ParseInfo *pip){ Reg_s value = 0; int st; st = SESL_GetType(pip->sym); pip->value = SESL_GetAddress(pip->sym); if (st == SESL_TYPE_PTR) { if (pip->constant) { pip->constant = 0; if (!(pip->sym = SESL_Dereference(pip->sym, pip->value))) { return SYM_ERROR; } } 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; } if (sizeof(value) == 4) pip->value = BE2HO_4(value); else if (sizeof(value) == 8) pip->value = BE2HO_8(value); else ASSERT(0); if (!(pip->sym = SESL_Dereference(pip->sym, pip->value))) { return SYM_ERROR; } } } else if (st == SESL_TYPE_ARRAY) { ASSERT(pip->constant); pip->constant = 0; if (!(pip->sym = SESL_Dereference(pip->sym, pip->value))) { return SYM_ERROR; } } else { SymReportError("array or pointer expected", NULL); return SYM_ERROR; } ASSERT(!pip->constant); st = SESL_GetType(pip->sym); if (st == SESL_TYPE_ARRAY) pip->constant = 1; else ASSERT(st != SESL_TYPE_FUNC); pip->value = SESL_GetAddress(pip->sym); return SYM_OK;}int SymParseTypeCast(ParseInfo *pip){ char *str; char *name = ""; char *scan; int level, i; int types[6]; 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++; str = SymParseString(pip,1); if (!strlen(str) || (pip->str[0] != ')')) { SymReportError("Syntax error in type cast", NULL); return SYM_ERROR; } pip->str++; if (SymParseExpr(pip) != SYM_OK) { SymReportError("Attempt to cast bad expression.", NULL); return SYM_ERROR; } if (!(pip->sym = SESL_Cast(pip->execname, pip->sym, str))) { return SYM_ERROR; } pip->value = SESL_GetAddress(pip->sym); return SYM_OK;}int SymParseInt(char **str, Reg *val){ while (**str == ' ') { (*str)++; } if (isdigit(**str)) { uint64 val64; char *tmpstr = *str;#if defined(__alpha) || defined(i386) val64 = strtoul(*str, &tmpstr, 0);#else val64 = strtoull(*str, &tmpstr, 0);#endif if ((val64 == 0) && (*str == tmpstr)) { return SYM_ERROR; } *val = val64; *str = tmpstr; while (**str == ' ') { (*str)++; } } else { SymReportError("expected an int, got \"", str, "\"", NULL); return SYM_ERROR; } return SYM_OK;}char *SymParseString(ParseInfo *pip, int special){ static char buf[BUFFER_SIZE]; char *dst = buf; while (isalnum(*(pip->str)) || (*(pip->str) == '_') || (*(pip->str) == ' ') || (*(pip->str) == '*')) { if (!special && ((*(pip->str) == ' ') || (*(pip->str) == '*'))) break; 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 + -