Added support for evaluating references (ie, expressions in braces, addresses in brackets)
This commit is contained in:
parent
1d448f14ee
commit
fb62277ea0
1 changed files with 80 additions and 42 deletions
|
|
@ -2540,6 +2540,12 @@ if (DEBUGGER) {
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
Debugger.prototype.replaceRegs = function(s) {
|
Debugger.prototype.replaceRegs = function(s) {
|
||||||
|
/*
|
||||||
|
* Replace any references first; this means that register references inside the reference
|
||||||
|
* do NOT need to be prefixed with '%'.
|
||||||
|
*/
|
||||||
|
s = this.parseReference(s);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Replace every %XX (or %XXX), where XX (or XXX) is a register, with the register's value.
|
* Replace every %XX (or %XXX), where XX (or XXX) is a register, with the register's value.
|
||||||
*/
|
*/
|
||||||
|
|
@ -4460,57 +4466,89 @@ if (DEBUGGER) {
|
||||||
*/
|
*/
|
||||||
Debugger.prototype.parseExpression = function(sExp, fPrint)
|
Debugger.prototype.parseExpression = function(sExp, fPrint)
|
||||||
{
|
{
|
||||||
var i = 0, value;
|
var value;
|
||||||
var fError = false;
|
|
||||||
var sExpOrig = sExp;
|
if (sExp) {
|
||||||
var aVals = [], aOps = [];
|
sExp = this.parseReference(sExp);
|
||||||
/*
|
|
||||||
* All browsers (including, I believe, IE9 and up) support the following idiosyncrasy of a regexp split():
|
var i = 0;
|
||||||
* when the regexp uses a capturing pattern, the resulting array will include entries for all the pattern
|
var fError = false;
|
||||||
* matches along with the non-matches. This effectively means that, in the set of expressions that we
|
var sExpOrig = sExp;
|
||||||
* support, all even entries in asValues will contain "values" and all odd entries will contain "operators".
|
var aVals = [], aOps = [];
|
||||||
*
|
/*
|
||||||
* And although I tried to list the supported operators in "precedential" order, bitwise operators must
|
* All browsers (including, I believe, IE9 and up) support the following idiosyncrasy of a regexp split():
|
||||||
* be out-of-order so that we don't mistakenly match either '>' or '<' when they're part of '>>' or '<<'.
|
* when the regexp uses a capturing pattern, the resulting array will include entries for all the pattern
|
||||||
*/
|
* matches along with the non-matches. This effectively means that, in the set of expressions that we
|
||||||
var regExp = /(\|\||&&|\||^|&|!=|==|>=|>>>|>>|>|<=|<<|<|-|\+|%|\/|\*)/;
|
* support, all even entries in asValues will contain "values" and all odd entries will contain "operators".
|
||||||
var asValues = sExp.split(regExp);
|
*
|
||||||
while (i < asValues.length) {
|
* And although I tried to list the supported operators in "precedential" order, bitwise operators must
|
||||||
var sValue = asValues[i++];
|
* be out-of-order so that we don't mistakenly match either '>' or '<' when they're part of '>>' or '<<'.
|
||||||
var cchValue = sValue.length;
|
*/
|
||||||
var s = str.trim(sValue);
|
var regExp = /(\|\||&&|\||^|&|!=|==|>=|>>>|>>|>|<=|<<|<|-|\+|%|\/|\*)/;
|
||||||
if (!s) {
|
var asValues = sExp.split(regExp);
|
||||||
|
while (i < asValues.length) {
|
||||||
|
var sValue = asValues[i++];
|
||||||
|
var cchValue = sValue.length;
|
||||||
|
var s = str.trim(sValue);
|
||||||
|
if (!s) {
|
||||||
|
fError = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var v = this.parseValue(s, null, fPrint === false);
|
||||||
|
if (v === undefined) {
|
||||||
|
fError = true;
|
||||||
|
fPrint = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
aVals.push(v);
|
||||||
|
if (i == asValues.length) break;
|
||||||
|
var sOp = asValues[i++], cchOp = sOp.length;
|
||||||
|
this.assert(Debugger.aBinOpPrecedence[sOp] != null);
|
||||||
|
if (aOps.length && Debugger.aBinOpPrecedence[sOp] < Debugger.aBinOpPrecedence[aOps[aOps.length-1]]) {
|
||||||
|
this.evalExpression(aVals, aOps, 1);
|
||||||
|
}
|
||||||
|
aOps.push(sOp);
|
||||||
|
sExp = sExp.substr(cchValue + cchOp);
|
||||||
|
}
|
||||||
|
if (!this.evalExpression(aVals, aOps) || aVals.length != 1) {
|
||||||
fError = true;
|
fError = true;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
var v = this.parseValue(s, null, fPrint === false);
|
if (!fError) {
|
||||||
if (v === undefined) {
|
value = aVals.pop();
|
||||||
fError = true;
|
if (fPrint) this.printValue(null, value);
|
||||||
fPrint = false;
|
} else {
|
||||||
break;
|
if (fPrint) this.println("error parsing '" + sExpOrig + "' at character " + (sExpOrig.length - sExp.length));
|
||||||
}
|
}
|
||||||
aVals.push(v);
|
|
||||||
if (i == asValues.length) break;
|
|
||||||
var sOp = asValues[i++], cchOp = sOp.length;
|
|
||||||
this.assert(Debugger.aBinOpPrecedence[sOp] != null);
|
|
||||||
if (aOps.length && Debugger.aBinOpPrecedence[sOp] < Debugger.aBinOpPrecedence[aOps[aOps.length-1]]) {
|
|
||||||
this.evalExpression(aVals, aOps, 1);
|
|
||||||
}
|
|
||||||
aOps.push(sOp);
|
|
||||||
sExp = sExp.substr(cchValue + cchOp);
|
|
||||||
}
|
|
||||||
if (!this.evalExpression(aVals, aOps) || aVals.length != 1) {
|
|
||||||
fError = true;
|
|
||||||
}
|
|
||||||
if (!fError) {
|
|
||||||
value = aVals.pop();
|
|
||||||
if (fPrint) this.printValue(null, value);
|
|
||||||
} else {
|
|
||||||
if (fPrint) this.println("error parsing '" + sExpOrig + "' at character " + (sExpOrig.length - sExp.length));
|
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parseReference(sValue)
|
||||||
|
*
|
||||||
|
* Returns the given string with any "{expression}" sequences replaced with the value of the expression,
|
||||||
|
* and any "[address]" references replaced with the contents of the address. Expressions are parsed BEFORE
|
||||||
|
* addresses.
|
||||||
|
*
|
||||||
|
* @this {Debugger}
|
||||||
|
* @param {string} sValue
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
Debugger.prototype.parseReference = function(sValue)
|
||||||
|
{
|
||||||
|
var a;
|
||||||
|
while (a = sValue.match(/\{(.*)\}/)) {
|
||||||
|
var value = this.parseExpression(a[1]);
|
||||||
|
sValue = sValue.replace('{' + a[1] + '}', value != null? str.toHex(value) : "undefined");
|
||||||
|
}
|
||||||
|
while (a = sValue.match(/\[(.*)\]/)) {
|
||||||
|
var sAddr = this.parseReference(a[1]); // take care of any inner references, too
|
||||||
|
var dbgAddr = this.parseAddr(sAddr);
|
||||||
|
sValue = sValue.replace('[' + a[1] + ']', dbgAddr? str.toHex(this.getWord(dbgAddr), dbgAddr.fData32? 8 : 4) : "undefined");
|
||||||
|
}
|
||||||
|
return sValue;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* parseValue(sValue, sName, fQuiet)
|
* parseValue(sValue, sName, fQuiet)
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue