📄 sym.c
字号:
* analysis or executing an embedded command. In that case a * standard Tcl error is returned, using machPtr->interp->result to hold * an error message. In the event of a successful return, the token * and (possibly) number fields in infoPtr are updated to refer to * the next symbol in the expression string, and the expr field is * advanced. * * Side effects: * None. * *---------------------------------------------------------------------- */static intLex(infoPtr) register ExprInfo *infoPtr; /* Describes the state of the parse. */{ register char *p, c; /* * The next token is either: * (a) A number (convert it from ASCII to binary). * (b) A symbol name (lookup the symbol). * (c) Space (skip it). * (d) An operator (see what kind it is). */ p = infoPtr->expr; infoPtr->tokenChars = p; c = *p; while (isspace(c)) { p++; c = *p; } infoPtr->expr = p; if (!isascii(c)) { infoPtr->token = END; return TCL_OK; } if (c == '#') { if (((*(p+1) == '-') && (!isdigit(*(p+2)))) || (!isdigit(*(p+1)) && (*(p+1) != '-'))) { return TCL_ERROR; } infoPtr->token = NUMBER; infoPtr->number = strtol(p+1, &infoPtr->expr, 0); return TCL_OK; } if (isdigit(c)) { infoPtr->token = NUMBER; infoPtr->number = strtol(p, &infoPtr->expr, 0); return TCL_OK; } if (isalpha(c) || (c == '_')) { char savedChar; int result; for (p++; isalnum(*p) || (*p == '_') || (*p == '$'); p++) { /* Null loop body; just skip to end of symbol. */ } savedChar = *p; *p = 0; result = Sym_GetSym(infoPtr->machPtr, infoPtr->fileName, infoPtr->expr, 0, (unsigned int *) &infoPtr->number); if (result == SYM_NOT_FOUND) { if (infoPtr->ignoreUndef) { infoPtr->number = 0; } else { sprintf(infoPtr->machPtr->interp->result, "undefined symbol \"%.50s\"", infoPtr->expr); *p = savedChar; return TCL_ERROR; } } else if (result == SYM_AMBIGUOUS) { sprintf(infoPtr->machPtr->interp->result, "symbol \"%.50s\" multiply defined", infoPtr->expr); *p = savedChar; return TCL_ERROR; } else if (result == SYM_REG_NOT_OK) { sprintf(infoPtr->machPtr->interp->result, "can't use register name in expression"); *p = savedChar; return TCL_ERROR; } infoPtr->token = NUMBER; *p = savedChar; infoPtr->expr = p; return TCL_OK; } infoPtr->expr = p+1; switch (c) { case '(': infoPtr->token = OPEN_PAREN; return TCL_OK; case ')': infoPtr->token = CLOSE_PAREN; return TCL_OK; case '*': infoPtr->token = MULT; return TCL_OK; case '/': infoPtr->token = DIVIDE; return TCL_OK; case '%': infoPtr->token = MOD; return TCL_OK; case '+': infoPtr->token = PLUS; return TCL_OK; case '-': infoPtr->token = MINUS; return TCL_OK; case '<': if (p[1] == '<') { infoPtr->expr = p+2; infoPtr->token = LEFT_SHIFT; } else { infoPtr->token = END; } return TCL_OK; case '>': if (p[1] == '>') { infoPtr->expr = p+2; infoPtr->token = RIGHT_SHIFT; } else { infoPtr->token = END; } return TCL_OK; case '&': infoPtr->token = BIT_AND; return TCL_OK; case '^': infoPtr->token = BIT_XOR; return TCL_OK; case '|': infoPtr->token = BIT_OR; return TCL_OK; case '~': infoPtr->token = BIT_NOT; return TCL_OK; case 0: default: infoPtr->token = END; infoPtr->expr = p; return TCL_OK; }}/* *---------------------------------------------------------------------- * * GetValue -- * * Parse a "value" from the remainder of the expression in infoPtr. * * Results: * Normally TCL_OK is returned. The value of the parsed number is * returned in infoPtr->number. If an error occurred, then * interp->result contains an error message and TCL_ERROR is returned. * * Side effects: * Information gets parsed from the remaining expression, and the * expr and token and tokenChars fields in infoPtr get updated. * Information is parsed until either the end of the expression is * reached (null character or close paren), an error occurs, or a * binary operator is encountered with precedence <= prec. In any * of these cases, infoPtr->token will be left pointing to the token * AFTER the expression. * *---------------------------------------------------------------------- */static intGetValue(infoPtr, prec) register ExprInfo *infoPtr; /* Describes the state of the parse * just before the value (i.e. Lex * will be called to get first token * of value). */ int prec; /* Treat any un-parenthesized operator * with precedence <= this as the end * of the expression. */{ int result, operator, operand; int gotOp; /* Non-zero means already lexed the * operator (while picking up value * for unary operator). Don't lex * again. */ char *savedPtr; /* * There are two phases to this procedure. First, pick off an initial * value. Then, parse (binary operator, value) pairs until done. */ gotOp = 0; result = Lex(infoPtr); if (result != TCL_OK) { return result; } if (infoPtr->token == OPEN_PAREN) { /* * Parenthesized sub-expression. */ result = GetValue(infoPtr, -1); if (result != TCL_OK) { return result; } if (infoPtr->token != CLOSE_PAREN) { Tcl_Return(infoPtr->machPtr->interp, (char *) NULL, TCL_STATIC); sprintf(infoPtr->machPtr->interp->result, "unmatched parenthesis in expression"); return TCL_ERROR; } } else { if (infoPtr->token == MINUS) { infoPtr->token = UNARY_MINUS; } if (infoPtr->token >= UNARY_MINUS) { /* * Process unary operators. */ operator = infoPtr->token; savedPtr = infoPtr->expr; result = GetValue(infoPtr, exprPrecTable[infoPtr->token]); if (result != TCL_OK) { return result; } if (infoPtr->tokenChars == savedPtr) { sprintf(infoPtr->machPtr->interp->result, "missing value after operator in expression"); return TCL_ERROR; } switch (operator) { case UNARY_MINUS: infoPtr->number = -infoPtr->number; break; case BIT_NOT: infoPtr->number = ~infoPtr->number; break; } gotOp = 1; } else if (infoPtr->token != NUMBER) { return TCL_OK; } } /* * Got the first operand. Now fetch (operator, operand) pairs. */ if (!gotOp) { result = Lex(infoPtr); if (result != TCL_OK) { return result; } } while (1) { operand = infoPtr->number; operator = infoPtr->token; if ((operator < MULT) || (operator >= UNARY_MINUS)) { return TCL_OK; } if (exprPrecTable[operator] <= prec) { return TCL_OK; } savedPtr = infoPtr->expr; result = GetValue(infoPtr, exprPrecTable[operator]); if (infoPtr->tokenChars == savedPtr) { sprintf(infoPtr->machPtr->interp->result, "missing value after operator in expression"); return TCL_ERROR; } if (result != TCL_OK) { return result; } switch (operator) { case MULT: infoPtr->number = operand * infoPtr->number; break; case DIVIDE: if (infoPtr->number == 0) { Tcl_Return(infoPtr->machPtr->interp, "divide by zero in expression", TCL_STATIC); return TCL_ERROR; } infoPtr->number = operand / infoPtr->number; break; case MOD: if (infoPtr->number == 0) { Tcl_Return(infoPtr->machPtr->interp, "divide by zero in expression", TCL_STATIC); return TCL_ERROR; } infoPtr->number = operand % infoPtr->number; break; case PLUS: infoPtr->number = operand + infoPtr->number; break; case MINUS: infoPtr->number = operand - infoPtr->number; break; case LEFT_SHIFT: infoPtr->number = operand << infoPtr->number; break; case RIGHT_SHIFT: infoPtr->number = operand >> infoPtr->number; break; case BIT_AND: infoPtr->number = operand & infoPtr->number; break; case BIT_XOR: infoPtr->number = operand ^ infoPtr->number; break; case BIT_OR: infoPtr->number = operand | infoPtr->number; break; } }}/* *---------------------------------------------------------------------- * * Sym_EvalExpr -- * * Given an expression including symbol names and constants, compute * the value of the expression. * * Results: * The result is a standard Tcl return value. MachPtr's interp may * get a result added to it also. *valuePtr is modified to hold * the value of the expression, and *endPtr is modified to point to * the character that terminated the expression (i.e. the first * character not in the expression). If an error occurs, *endPtr * is set to exprString. * * Side effects: * None. * *---------------------------------------------------------------------- */intSym_EvalExpr(machPtr, fileName, exprString, ignoreUndef, valuePtr, endPtr) DLX *machPtr; /* Machine to manipulate. */ char *fileName; /* Name of file to use for symbol lookup. * See declaration of Sym_GetSym arg for more * information. */ char *exprString; /* Expression string to evaluate. */ int ignoreUndef; /* Non-zero means treat undefined symbols * as having address 0. */ int *valuePtr; /* Store the expression value here. */ char **endPtr; /* Store address of terminating character * here. */{ ExprInfo info; int result; info.machPtr = machPtr; info.fileName = fileName; info.ignoreUndef = ignoreUndef; info.expr = exprString; result = GetValue(&info, -1); if (result != TCL_OK) { *valuePtr = 0; *endPtr = exprString; return result; } *valuePtr = info.number; /* * If the expression contained no information at all, then * it's an error. */ if (info.tokenChars == exprString) { sprintf(machPtr->interp->result, "missing expression"); return TCL_ERROR; } /* * Skip over blank space at the end of the expression. */ while (isspace(*(info.tokenChars))) { info.tokenChars++; } *endPtr = info.tokenChars; return TCL_OK;}/* *---------------------------------------------------------------------- * * Sym_GetString -- * * Given an address, return a string describing the address. * * Results: * The return value is a textual description of address. If * possible, the address is identified symbolically (or with * an offset). In the worst case, it may simply be identified * with a hex address. * * Side effects: * None. * *---------------------------------------------------------------------- */char *Sym_GetString(machPtr, address) DLX *machPtr; /* Machine to manipulate. */ unsigned int address; /* Address for which an identifying string * is returned. */{ Tcl_HashSearch search; Tcl_HashEntry *hPtr; register Sym *symPtr; int distance, closestDistance; char *closestName; static char string[100]; closestDistance = 10000; closestName = NULL; for (hPtr = Tcl_FirstHashEntry(&machPtr->symbols, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { for (symPtr = (Sym *) Tcl_GetHashValue(hPtr); symPtr != NULL; symPtr = symPtr->nextPtr) { distance = address - symPtr->address; if ((distance < 0) || (distance >= closestDistance)) { continue; } if (distance == 0) { return hPtr->key.string; } closestDistance = distance; closestName = hPtr->key.string; } } if (closestName == NULL) { sprintf(string, "0x%x", address); } else { sprintf(string, "%.50s+0x%x", closestName, closestDistance); } return string;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -