//-------------------------------------------------------------------------------------------------- // // @ CopyRight Roberti & Parau Enterprises, Inc. 2021-2023 // // This work is licensed under the Creative Commons Attribution-NoDerivatives 4.0 International License. // To view a copy of this license, visit http://creativecommons.org/licenses/by-nd/4.0/ // or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. // //-------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------- // // Expression token class // //------------------------------------------------------------------------------------------------- package framework; import java.util.*; import java.math.BigInteger; import java.math.MathContext; import java.math.BigDecimal; import java.lang.reflect.*; public class DVExpression { protected DVExpression(DVStatements.Statement owner) { this.owner= owner; } // // Add operator token // protected void addPostfixOperatorToken(OperType operType) { ExprToken t= new ExprToken(TokenType.OPERATOR, null); t.operType= operType; t.operPriority= DVExpression.operPriority[t.operType.ordinal()]; t.operLeftAssociation= DVExpression.operLeftAssociation[t.operType.ordinal()]; this.exprList.add(t); } protected void addOperatorToken(Token parseToken, OperType operType) { ExprToken t= new ExprToken(TokenType.OPERATOR, parseToken); t.operType= operType; t.operPriority= DVExpression.operPriority[t.operType.ordinal()]; t.operLeftAssociation= DVExpression.operLeftAssociation[t.operType.ordinal()]; // // Handle right parenthesis // if (t.operType == OperType.RPAREN) { while (this.exprStack.peekFirst().operType != OperType.LPAREN) this.exprList.add(this.exprStack.pop()); this.exprStack.pop(); return; } // // Transfer any operator of higher/equal priority to the list // if (t.operType != OperType.LPAREN) while (this.exprStack.peekFirst() != null && (t.operPriority < this.exprStack.peekFirst().operPriority || (t.operPriority == this.exprStack.peekFirst().operPriority && t.operLeftAssociation))) this.exprList.add(this.exprStack.pop()); // // Finally push this operator in the stack // this.exprStack.push(t); } // // Add base symbol // protected void addBaseSymbolToken(Token parseToken) { ExprToken t= new ExprToken(TokenType.BASE_SYMBOL, parseToken); t.baseID= parseToken.image.substring(0, parseToken.image.indexOf(':')); t.symbol= this.owner.getSymbols().getSymbol( parseToken.image.substring(parseToken.image.indexOf(':')+1)); this.exprList.add(t); } // // Add qualified symbol token // protected void addQualifiedSymbolToken(Token parseToken) { ExprToken t= new ExprToken(TokenType.SYMBOL, parseToken); t.qualifier= parseToken.image.substring(parseToken.image.indexOf('@')); t.symbol= this.owner.getSymbols().getSymbol( parseToken.image.substring(0, parseToken.image.indexOf('@'))); this.exprList.add(t); } // // Add symbol // protected void addSymbolToken(Token parseToken, DVSymbols.SymbolComponent component) { if (parseToken != null) { int x; if ((x= parseToken.image.indexOf(".$")) > 0) parseToken.image= parseToken.image.substring(0, x); } this.addSymbolToken(parseToken, this.owner.getSymbols().getSymbol(parseToken.image), component); } protected void addSymbolToken(DVSymbols.Symbol symbol, DVSymbols.SymbolComponent component) { this.addSymbolToken(null, symbol, component); } protected void addSymbolToken(Token parseToken, DVSymbols.Symbol symbol, DVSymbols.SymbolComponent component) { ExprToken t= new ExprToken(TokenType.SYMBOL, parseToken); t.symbol= symbol; t.symbolComponent= component; this.exprList.add(t); if (parseToken != null) t.symbol.addReference(this.owner); } // // Add counter value // protected void addCounterToken(Token parseToken) { if (owner.ownerSection != null) { this.exprList.add(new ExprToken(owner.symbol, DVSymbols.SymbolComponent.VALUE)); return; } DVStatements.Statement prevStmt= owner.getPrevSectStatement(); if (prevStmt == null) { owner.putError("Program Counter used in expression but no Section or MMap is active"); return; } this.exprList.add(new ExprToken(prevStmt.symbol, DVSymbols.SymbolComponent.VALUE)); this.exprList.add(new ExprToken(prevStmt.symbol, DVSymbols.SymbolComponent.LENGTH)); this.exprList.add(new ExprToken(prevStmt.symbol, DVSymbols.SymbolComponent.REPL)); this.exprList.add(new ExprToken(OperType.MULTIPLY)); this.exprList.add(new ExprToken(OperType.PLUS)); } // // Add float constant token // protected void addFloatToken(Token parseToken) throws ParseException { ExprToken t= new ExprToken(TokenType.FLOAT, parseToken); boolean errFlag= false; try { t.floatConstant= new BigDecimal(parseToken.image); } catch(Exception e) { errFlag= true; } if (errFlag) { this.owner.putError(String.format( "Exponent too large for floatig point constant on line %d " + "column %d", parseToken.beginLine, parseToken.beginColumn)); return; } this.exprList.add(t); } // // Add integer constant token // protected void addIntegerToken(Token parseToken) { ExprToken t= new ExprToken(TokenType.ABSOLUTE, parseToken); t.intConstant= new BigInteger(parseToken.image); this.exprList.add(t); } protected void addIntegerToken(BigInteger value) { ExprToken t= new ExprToken(TokenType.ABSOLUTE, null); t.intConstant= value; this.exprList.add(t); } // // Add hex constant token // protected void addHexToken(Token parseToken) { ExprToken t= new ExprToken(TokenType.ABSOLUTE, parseToken); t.intConstant= new BigInteger(parseToken.image.substring(2).replace("_", ""), 16); this.exprList.add(t); } // // Add hex constant token // protected void addBinToken(Token parseToken) { ExprToken t= new ExprToken(TokenType.ABSOLUTE, parseToken); t.intConstant= new BigInteger(parseToken.image.substring(2).replace("_", ""), 2); this.exprList.add(t); } // // Add char constant token // protected void addCharToken(Token parseToken) { short code; char ec= parseToken.image.charAt(1); if (ec == '\\') { ec= parseToken.image.charAt(2); if (ec == 'x') code= Short.parseShort(parseToken.image.substring(3, 5)); else code= DVExpression.escapeCharCode[DVExpression.escapeChar.indexOf(ec)]; } else code= (short) ec; ExprToken t= new ExprToken(TokenType.ABSOLUTE, parseToken); t.intConstant= BigInteger.valueOf(code); this.exprList.add(t); } // // Add offset integer token // protected void addOffsetIntegerToken(DVSections.Section offsetSection, BigInteger value) { ExprToken t= new ExprToken(TokenType.OFFSET, null); t.intConstant= value; t.offsetRecordList= new ArrayList(); t.offsetRecordList.add(new OffsetRecord(offsetSection, 1)); this.exprList.add(t); } // // Add string constant token // protected String addStringToken(Token parseToken) { ExprToken t= new ExprToken(TokenType.STRING, parseToken); try { t.stringConstant= DVUtil.unescapeString(parseToken.image.substring(1, parseToken.image.length()-1)); } catch(Exception e) { return e.getMessage(); } this.exprList.add(t); return null; } // // End of expression processing // protected void expressionEnd() { while (! this.exprStack.isEmpty()) this.exprList.add(this.exprStack.pop()); } // // Concatenate expression with add operator // protected DVExpression addExpression(DVExpression expr) { if (expr.exprList.isEmpty()) return this; boolean emptyFlag= this.isEmpty(); for (ExprToken t : expr.exprList) this.exprList.add(t); if (!emptyFlag) this.addPostfixOperatorToken(OperType.PLUS); return this; } // // Concatenate expression with add operator // protected DVExpression maxExpression(DVExpression expr) { if (expr.exprList.isEmpty()) return this; boolean emptyFlag= this.isEmpty(); for (ExprToken t : expr.exprList) this.exprList.add(t); if (!emptyFlag) this.addPostfixOperatorToken(OperType.MAX); return this; } // // Check if expression is empty // public boolean isEmpty() { return this.exprList.isEmpty(); } // // Check if expression is single symbol // protected ExprToken getFirstTokenIfSingle() { if (this.isEmpty() || this.exprList.size() > 1) return null; return this.exprList.peekFirst(); } // // Set dependencies of a value expressions // protected void setValueDependencies(DVSymbols.Symbol symbol) { this.owner.logTrace("--- Set value dependencies - Symbol: " + symbol.name); for (ExprToken t : this.exprList) { if (t.type != TokenType.SYMBOL || t.symbol.isExternal || t.symbol.isCommon) continue; if (t.symbolComponent == DVSymbols.SymbolComponent.VALUE) { t.symbol.setValueValueDependency(symbol); this.owner.logTrace("--- Value Symbol: " + t.symbol.name); } else if (t.symbolComponent == DVSymbols.SymbolComponent.REPL || t.symbolComponent == DVSymbols.SymbolComponent.SIZE) { t.symbol.setReplValueDependency(symbol); this.owner.logTrace("--- Repl Symbol: " + t.symbol.name); } } } // // Set dependencies of a repl expressions // protected void setReplDependencies(DVSymbols.Symbol symbol) { for (ExprToken t : this.exprList) { if (t.type != TokenType.SYMBOL) continue; if (t.symbolComponent == DVSymbols.SymbolComponent.VALUE) t.symbol.setValueReplDependency(symbol); else if (t.symbolComponent == DVSymbols.SymbolComponent.REPL || t.symbolComponent == DVSymbols.SymbolComponent.SIZE) t.symbol.setReplReplDependency(symbol); } } // // Get symbol in section based on offset, length and repl of // preceding symbol // protected static DVExpression getNewSymbolValueExpression( DVSymbols.Symbol lastSymbol, DVSymbols.Symbol newSymbol) { DVExpression expr= new DVExpression(newSymbol.owner); expr.addSymbolToken(lastSymbol, DVSymbols.SymbolComponent.VALUE); expr.addSymbolToken(lastSymbol, DVSymbols.SymbolComponent.LENGTH); expr.addSymbolToken(lastSymbol, DVSymbols.SymbolComponent.REPL); expr.addPostfixOperatorToken(OperType.MULTIPLY); expr.addPostfixOperatorToken(OperType.PLUS); if (newSymbol.align != null) { expr.addIntegerToken(newSymbol.align); expr.addPostfixOperatorToken(OperType.ALIGN); } return expr; } // // Get value of symbol end // protected static DVExpression getEndValueExpression(DVStatements.Statement owner) { DVExpression expr= new DVExpression(owner); DVSymbols.Symbol symbol= owner.symbol; expr.addSymbolToken(symbol, DVSymbols.SymbolComponent.VALUE); expr.addSymbolToken(symbol, DVSymbols.SymbolComponent.LENGTH); expr.addSymbolToken(symbol, DVSymbols.SymbolComponent.REPL); expr.addPostfixOperatorToken(OperType.MULTIPLY); expr.addPostfixOperatorToken(OperType.PLUS); return expr; } // // Get a new expression with one constant // protected static DVExpression getConstantExpression(BigInteger value, DVStatements.Statement owner) { DVExpression expr= new DVExpression(owner); expr.addIntegerToken(value); return expr; } // // Get a new constant ABSOLUTE expression token // public static DVExpression.ExprToken getConstantExprToken(BigInteger value, DVStatements.Statement owner) { DVExpression expr= getConstantExpression(value, owner); expr.addIntegerToken(value); return expr.getFirstExprToken(); } // // Get a new expression with one OFFSET constant // protected static DVExpression getOffsetConstantExpression(DVStatements.Statement owner, DVSections.Section offsetSection, BigInteger offset) { DVExpression expr= new DVExpression(owner); expr.addOffsetIntegerToken(offsetSection, offset); return expr; } // // Return first expression token in expression // protected ExprToken getFirstExprToken() { return this.exprList.peek(); } // // Set symbol references // protected void setSymbolReferences(DVStatements.Statement statement) { for (ExprToken t : this.exprList){ if (t.type == DVExpression.TokenType.SYMBOL) t.symbol.addReference(statement); } } // // List expression tokens for debugging // protected void list(String title) { System.out.println("--- Start expression dump: " + title); for (ExprToken t : this.exprList) { if (t.type == DVExpression.TokenType.SYMBOL) { DVSymbols.Symbol s= t.symbol; System.out.format(" Token type: SYMBOL %s - Comp: %s -> ", s.name, t.symbolComponent.name()); if (t.symbolComponent == DVSymbols.SymbolComponent.VALUE) System.out.format("%s\n", s.resultValue != null && s.resultValue.intConstant != null ? s.resultValue.intConstant : "N/A"); else if (t.symbolComponent == DVSymbols.SymbolComponent.REPL) System.out.format("%s\n", s.resultRepl != null && s.resultRepl.intConstant != null ? s.resultRepl.intConstant : "N/A"); else if (t.symbolComponent == DVSymbols.SymbolComponent.LENGTH) System.out.format("%s\n", s.length != null ? s.length : "N/A"); else System.out.format("%s\n", s.resultValue != null && s.resultValue.intConstant != null && s.resultRepl != null && s.resultRepl.intConstant != null ? s.resultValue.intConstant.multiply(s.resultRepl.intConstant).toString() : "N/A"); } else if (t.type == DVExpression.TokenType.OPERATOR) System.out.format(" Token type: OPERATOR %s\n", t.operType.name()); else System.out.format(" Token type: %s %s\n", t.type.name(), (t.intConstant == null ? "N/A" : t.intConstant.toString())); } } // // Dump expression tokens in output listing // protected void dump() { this.owner.logMsg("--- Start expression dump"); for (ExprToken t : this.exprList) { if (t.type == DVExpression.TokenType.SYMBOL) this.owner.logMsg(String.format(" Token type: SYMBOL %s %s %s %s\n", t.symbol.name, (t.symbol.resultValue != null && t.symbol.resultValue.intConstant != null ? t.symbol.resultValue.intConstant.toString() : "N/A"), (t.symbol.resultRepl != null && t.symbol.resultRepl.intConstant != null ? t.symbol.resultRepl.intConstant.toString() : "N/A"), (t.symbol.length != null ? t.symbol.length.toString() : "N/A"))); else if (t.type == DVExpression.TokenType.OPERATOR) this.owner.logMsg(String.format(" Token type: OPERATOR %s\n", t.operType.name())); else this.owner.logMsg(String.format(" Token type: %s %s\n", t.type.name(), (t.intConstant == null ? "N/A" : t.intConstant.toString()))); } this.owner.logMsg(" - End Expression Dump"); } // // Evaluate the expression // protected ExprToken evaluate(boolean isRepl) { ExprToken operatorToken= null, v1= null, v2= null, v3; ExprToken externalSymbolToken= null; Exception operatorException= null; Method operatorMethod= null; // // Check if expression is empty - set result to NULL if so // if (this.exprList.size() == 0) return null; LinkedList tokenList= new LinkedList(this.exprList); this.exprStack.clear(); v1= this.getFirstExprToken(); if (v1 != null && v1.type == TokenType.SYMBOL && (v1.symbol.isExternal || v1.symbol.isCommon || v1.qualifier != null || (v1.symbol.owner != null && v1.symbol.owner.ownerSection != null && this.owner.ownerSection != null && v1.symbol.owner.ownerSection.type != DVSections.SectionType.MMAP && v1.symbol.owner.ownerSection != this.owner.ownerSection))) { if (v1.qualifier == null && v1.symbolComponent != DVSymbols.SymbolComponent.VALUE) { owner.putError("Symbol [" + v1.symbol.name + "] is EXTERNAL or COMMON with component [" + v1.symbolComponent.name() + "] - only [VALUE] is allowed" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } this.owner.logTrace(String.format("-------- External symbol %s\n", v1.symbol.name)); this.owner.logTrace(String.format(" %b %b\n", v1.symbol.isExternal, v1.symbol.isCommon)); this.owner.logTrace(String.format(" %s\n", this.owner.ownerSection)); externalSymbolToken= new ExprToken(TokenType.EXTERNAL_VALUE, v1.parseToken); externalSymbolToken.symbol= v1.symbol; externalSymbolToken.qualifier= v1.qualifier; externalSymbolToken.symbolComponent= v1.symbolComponent; v1= tokenList.pop(); v2= new ExprToken(TokenType.EXTERNAL_ZERO); v2.intConstant= BigInteger.ZERO; tokenList.push(v2); } // // Evaluate all tokens in expression list // while (! tokenList.isEmpty()) { operatorMethod= null; operatorException= null; v1= tokenList.pop(); v2= null; // // If SYMBOL convert to constant // if (v1.type == TokenType.SYMBOL) { if (v1.symbol.isExternal || v1.symbol.isCommon || v1.qualifier != null || (v1.symbol.owner != null && v1.symbol.owner.ownerSection != null && this.owner.ownerSection != null && v1.symbol.owner.ownerSection != this.owner.ownerSection && v1.symbol.owner.ownerSection.type != DVSections.SectionType.MMAP && v1.symbolComponent == DVSymbols.SymbolComponent.VALUE)) { owner.putError("Symbol [" + v1.symbol.name + "] is external to current section or relocation qualified and " + "is not first token in expression" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } if (v1.symbolComponent == DVSymbols.SymbolComponent.VALUE) { if (v1.symbol.resultValue == null) { owner.putError("Unresolved symbol [" + v1.symbol.name + "] Value" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } this.exprStack.push(v1.symbol.resultValue); } else if (v1.symbolComponent == DVSymbols.SymbolComponent.REPL || v1.symbolComponent == DVSymbols.SymbolComponent.SIZE) { if (v1.symbol.resultRepl == null) { owner.putError("Unresolved symbol [" + v1.symbol.name + "] Repl" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } if (v1.symbolComponent == DVSymbols.SymbolComponent.REPL) { ExprToken t= new ExprToken(TokenType.DISPLACEMENT); t.intConstant= v1.symbol.resultRepl.intConstant; this.exprStack.push(t); } else { ExprToken t= new ExprToken(TokenType.DISPLACEMENT); t.intConstant= v1.symbol.resultRepl.intConstant.multiply(v1.symbol.length); this.exprStack.push(t); } } else { v3= new ExprToken(TokenType.DISPLACEMENT, null); v3.intConstant= v1.symbol.length; this.exprStack.push(v3); } continue; } // // If BASE SYMBOL convert to BASE DISPLACEMENT // if (v1.type == TokenType.BASE_SYMBOL) { if (v1.symbol.resultValue.type != TokenType.OFFSET) { owner.putError(String.format("Symbol [%s] in BASE:SYMBOL does not resolve to OFFSET\n", v1.symbol.name)); return null; } v3= new ExprToken(TokenType.BASE_DISPLACEMENT, v1.parseToken); v3.baseID= v1.baseID; v3.baseSection= v1.symbol.owner.ownerSection; v3.intConstant= v1.symbol.resultValue.intConstant; v3.baseRegisterValue= null; this.exprStack.push(v3); continue; } // // Copy to stack if not operator // if (v1.type != TokenType.OPERATOR) { this.exprStack.push(v1); continue; } // // Get one value from the expression stack // if (this.exprStack.size() == 0) { owner.putError("Expression Software Error - Data Stack Empty when Data Expected\n" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } operatorToken= v1; v1= this.exprStack.pop(); // // Handle unary operators // if (OneParmOperator.contains(operatorToken.operType)) { v1= v1.clone(); if (v1.type == TokenType.STRING) { owner.putError("No unary operator can be used on STRING" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } if (operatorToken.operType == OperType.UPLUS){ this.exprStack.push(v1); continue; } if (v1.type == TokenType.BASE_DISPLACEMENT) { owner.putError("Invalid unary operator for integer of type BASE_DISPLACEMENT" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } if ((v1.type == TokenType.OFFSET || v1.type == TokenType.FLOAT) && operatorToken.operType != OperType.UMINUS) { owner.putError("Invalid unary operator for integer of type OFFSET or for FLOAT" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } if (v1.type == TokenType.OFFSET) v1.switchOffsetRecordSign(); else { try { if (v1.type == TokenType.FLOAT) { if ((operatorMethod= bDOper[operatorToken.operType.ordinal()]) == null) { owner.putError("Unary operator not allowed for given value type" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } v1.floatConstant= (BigDecimal) operatorMethod.invoke(null, v1.floatConstant); } else { if ((operatorMethod= bIOper[operatorToken.operType.ordinal()]) == null) { owner.putError("Unary operator not allowed for given value type" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } v1.intConstant= (BigInteger) operatorMethod.invoke(null, v1.intConstant); } } catch(Exception e) { operatorException= e; } } if (operatorException != null) { owner.putError("Operator Exception" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } this.exprStack.push(v1); continue; } // // Get second operand // v2= v1; if (this.exprStack.size() == 0) { owner.putError("+++ Software error in postfix expression" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } v1= exprStack.pop(); // // Handle binary operators // // // Pre-process special case EXTERNAL_ZERO // if (v1.type == TokenType.EXTERNAL_ZERO) { if (operatorToken.operType != OperType.PLUS && operatorToken.operType != OperType.MINUS) { owner.putError("Binary operator following external symbol can only be PLUS or MINUS"); return null; } v1= new ExprToken(TokenType.ABSOLUTE); v1.intConstant= BigInteger.ZERO; } // // Handle string binary operator // if (v1.type == TokenType.STRING || v2.type == TokenType.STRING) { if (v1.type != TokenType.STRING || v2.type != TokenType.STRING || operatorToken.operType != OperType.PLUS) { owner.putError("Binary operator is not PLUS or is operating on a STRING and NON-STRING" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } v3= new ExprToken(TokenType.STRING); v3.stringConstant= v1.stringConstant+v2.stringConstant; this.exprStack.push(v3); continue; } // // Handle BASE_DISPLACEMENT // if (v1.type == TokenType.BASE_DISPLACEMENT) { owner.putError("BASE_DISPLACEMENT cannot be the second operand of any binary operator"); return null; } if (v1.type == TokenType.BASE_DISPLACEMENT) { if (operatorToken.operType != OperType.PLUS && operatorToken.operType != OperType.MINUS) { owner.putError("Bianry operator following BASE_DISPLACEMENT token must be PLUS or MINUS"); return null; } if (! INT_VALUE.contains(v2.type)) { owner.putError("Second operand for bianry operation to first operand BASE_DISPLACEMENT does not resolve to ABSOLUTE or DISPLACEMENT"); return null; } v3= new ExprToken(TokenType.BASE_DISPLACEMENT, null); v3.baseID= v1.baseID; v3.baseRegisterValue= v1.baseRegisterValue; v3.baseSection= v1.baseSection; operatorMethod= bIBIOper[operatorToken.operType.ordinal()]; } // // Handle OFFSET operations // else if (v1.type == TokenType.OFFSET || v2.type == TokenType.OFFSET) { if (v1.type == TokenType.FLOAT || v2.type == TokenType.FLOAT) { owner.putError("Binary operator cannot be used between OFFSET and FLOAT" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } if (operatorToken.operType != OperType.PLUS && operatorToken.operType != OperType.MINUS && operatorToken.operType != OperType.MAX && operatorToken.operType != OperType.ALIGN) { owner.putError("Binary operator following OFFSETs can only be PLUS, MINUS, MAX or ALIGN"); return null; } if (operatorToken.operType == OperType.ALIGN && v2.type != TokenType.ABSOLUTE) { owner.putError("Operator ALIGN requires second operand to be ABSOLUTE" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } if (operatorToken.operType == OperType.MAX && (v1.type != TokenType.OFFSET || v2.type != TokenType.OFFSET)) { owner.putError("Operator MAX requires both operands to be OFFSET" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } if (v1.type != TokenType.OFFSET) v3= v2.clone(); else if (v2.type != TokenType.OFFSET) v3= v1.clone(); else if (operatorToken.operType == OperType.MAX) v3= v1.clone(); else v3= mergeOffsetRecord(v1, v2, operatorToken.operType); operatorMethod= bIBIOper[operatorToken.operType.ordinal()]; } // // Handle FLOAT operations // else if (v1.type == TokenType.FLOAT || v2.type == TokenType.FLOAT) { if (v1.type != TokenType.ABSOLUTE && v2.type != TokenType.FLOAT) { owner.putError("FLOAT type can be binary operated only with another FLOAT or ABSOLUTE type" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } v3= new ExprToken(TokenType.FLOAT, null); if (v1.type == TokenType.FLOAT && v2.type == TokenType.FLOAT) operatorMethod= bDBDOper[operatorToken.operType.ordinal()]; else if (v1.type == TokenType.FLOAT) operatorMethod= bDBIOper[operatorToken.operType.ordinal()]; else operatorMethod= bIBDOper[operatorToken.operType.ordinal()]; if (operatorMethod.getReturnType() == BigInteger.class) v3= new ExprToken(TokenType.ABSOLUTE, null); else v3= new ExprToken(TokenType.FLOAT, null); } // // Handle ABSOLUTE/DISPLACEMENT operations // else if(INT_VALUE.contains(v1.type) && INT_VALUE.contains(v2.type)) { if (operatorToken.operType == OperType.ALIGN || operatorToken.operType == OperType.MAX) { owner.putError("Operators ALIGN and MAX require first operand to be type OFFSET" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } if (v1.type == TokenType.DISPLACEMENT || v2.type == TokenType.DISPLACEMENT) v3= new ExprToken(TokenType.DISPLACEMENT, null); else v3= new ExprToken(TokenType.ABSOLUTE, null); if ((v3.baseRegisterValue= v1.baseRegisterValue) == null) v3.baseRegisterValue= v2.baseRegisterValue; operatorMethod= bIBIOper[operatorToken.operType.ordinal()]; } // // Something went wrong // else { owner.putError("Unexpected expression token encountered" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } // // Call binary operator method // if (operatorMethod == null) { owner.putError("Binary operator not allowed for given value types" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } operatorException= null; try { if (v3.type == TokenType.FLOAT) { if (v1.type != TokenType.FLOAT) v3.floatConstant= (BigDecimal) operatorMethod.invoke(null, v1.intConstant, v2.floatConstant); else if(v2.type != TokenType.FLOAT) v3.floatConstant= (BigDecimal) operatorMethod.invoke(null, v1.floatConstant, v2.intConstant); else v3.floatConstant= (BigDecimal) operatorMethod.invoke(null, v1.floatConstant, v2.floatConstant); } else v3.intConstant= (BigInteger) operatorMethod.invoke(null, v1.intConstant, v2.intConstant); } catch(Exception e) { operatorException= e; } if (operatorException != null) { owner.putError("Call exception" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } this.exprStack.push(v3); continue; } // // Check if one token only left in stack // if (this.exprStack.size() == 1) { v1= this.exprStack.peek(); if (isRepl && ! INT_VALUE.contains(v1.type)) { owner.putError("Result for REPL must be of type ABSOLUTE or DISPLACEMENT" + evalDump(null, null, null, null, null, null)); return null; } if (externalSymbolToken != null) { if (v1.type != TokenType.EXTERNAL_ZERO && ! INT_VALUE.contains(v1.type)) { owner.putError("Expression starting with external symbol must resolve to ABSOLUTE or DISPLACEMENT" + evalDump(null, null, null, null, null, null)); return null; } externalSymbolToken.intConstant= v1.intConstant; return externalSymbolToken; } if (v1.type != TokenType.OFFSET) return v1; if (v1.offsetRecordList.size() > 1) { owner.putError("Multiple OFFSET components in final result" + evalDump(null, null, null, null, null, null)); return null; } return v1; } owner.putError("Operator missing - value stack contains more than one value" + evalDump(tokenList, operatorToken, operatorMethod, v1, v2, operatorException)); return null; } // // Dump expression token list // protected void dumpTokenList(String title, LinkedList tokenList) { String msg= "\n" + title + "\n"; for (ExprToken t : tokenList) msg+= formatToken(t, " "); System.err.println(msg); } // // Dump expression list for debugging // protected void dump(String title) { owner.logMsg(title + evalDump(null, null, null, null, null, null)); } // // Return a string with fill dump of evaluation in progress // private String evalDump(LinkedList tokenList, ExprToken operToken, Method operMethod, ExprToken v1, ExprToken v2, Exception e) { String ret= ""; if (operToken != null) ret+= "\n--Operator Token" + formatToken(operToken, " "); if (v1 != null) ret+= "\n--First Operand Token" + formatToken(v1, " "); if (v2 != null) ret+= "\n--Second Operand Token" + formatToken(v2, " "); ret+= "\n--Original Postfix Expression Content"; for (ExprToken t : this.exprList) ret+= formatToken(t, " "); ret+= "\n--Value Stack Content"; for (ExprToken t : this.exprStack) ret+= formatToken(t, " "); if (tokenList != null) { ret+= "\n--Unprocessed Postfix Expression Content"; for (ExprToken t : tokenList) ret+= formatToken(t, " "); } if (e != null) { ret+= "\n--Operator Exception\n"; String msg= e.getMessage(); if (msg != null) while (msg.length() > 0) { int x= msg.indexOf("\n"); if (x < 0) { ret+= " " + msg + "\n"; msg= ""; } else { ret+= " " + msg.substring(0, x+1); msg= msg.substring(x+1); } } } if (operMethod != null) ret+= String.format("--Operator Method Name [%s]", operMethod.getName()); return ret + "\n"; } // // Return a string with expression token formatted // private String formatToken(ExprToken t, String prefix) { String ret= "\n" + prefix; if (t.parseToken == null) ret+= "------- Generated Token -------- "; else { ret+= String.format("Line [%12s] Column [%4d] ", this.owner.lines[t.parseToken.beginLine-1].lineNo, t.parseToken.beginColumn); } ret+= String.format("Token Type [%-12s] ", t.type.name()); switch(t.type) { case OPERATOR : ret+= String.format("Operator Type [%-12s]", t.operType.name()); break; case OFFSET : case DISPLACEMENT : case ABSOLUTE : case EXTERNAL_ZERO : ret+= String.format("Value [%s]", t.intConstant.toString()); if (t.type == TokenType.ABSOLUTE) break; if (t.type == TokenType.DISPLACEMENT) { if (t.baseRegisterValue != null) ret+= String.format(" Base Register Value [%s]", t.baseRegisterValue.toString()); else ret+= " Base Regster Value [*** None ***]"; break; } if (t.offsetRecordList != null) { ret+= "\n" + prefix + "--Offset records for Token"; for (OffsetRecord offRec : t.offsetRecordList) { ret+= "\n" + prefix + String.format(" Section [%s] Sign Add[%d]", offRec.section.owner.symbol.name, offRec.signAdd); // offRec.ownerSection.name.image, offRec.sign); } } break; case FLOAT : ret+= String.format("Value [%s] ", t.floatConstant.toString()); break; case STRING : ret+= String.format("Value [%s]", t.stringConstant); break; case SYMBOL : ret+= String.format("Component [%s] Symbol [%s]", t.symbolComponent == null ? "NULL" : t.symbolComponent.name(), t.symbol.name); break; case BASE_SYMBOL : ret+= String.format("ID@Symbol [%s]", t.parseToken.image); break; case BASE_DISPLACEMENT : ret+= String.format("BaseID [%s] Base Register [%s] Base Displacement [%s] Base Section [%s]", (t.baseID != null ? t.baseID : "N/A"), t.baseRegisterValue, t.intConstant.toString(16), t.baseSection.getName()); case EXTERNAL_VALUE : case EXTERNAL_SIZE : ret+= "Symbol[@qualifier] [" + t.parseToken.image + "]"; default : ; } return ret; } // // Expression token sub-class // public class ExprToken implements Cloneable { protected ExprToken(TokenType type, Token parseToken) { this.type= type; this.parseToken= parseToken; } protected ExprToken(TokenType type) { this.type= type; this.parseToken= null; } protected ExprToken(OperType operType) { this.type= TokenType.OPERATOR; this.parseToken= null; this.operType= operType; } protected ExprToken(DVSymbols.Symbol symbol, DVSymbols.SymbolComponent symbolComponent) { this.type= TokenType.SYMBOL; this.parseToken= null; this.symbol= symbol; this.symbolComponent= symbolComponent; } // // Clone expression token // protected ExprToken clone() { ExprToken t= new ExprToken(this.type, this.parseToken); t.intConstant= this.intConstant; t.floatConstant= this.floatConstant; t.stringConstant= this.stringConstant; t.symbol= this.symbol; t.symbolComponent= this.symbolComponent; if (this.offsetRecordList != null) { t.offsetRecordList= new ArrayList(); for (OffsetRecord offRec : this.offsetRecordList) t.offsetRecordList.add(new OffsetRecord(offRec.section, offRec.signAdd)); } t.qualifier= this.qualifier; t.baseID= this.baseID; t.baseSection= this.baseSection; t.baseRegisterValue= this.baseRegisterValue; t.operType= this.operType; t.operPriority= this.operPriority; t.operLeftAssociation= this.operLeftAssociation; return t; } // // Switch sign of offset record signAdd // protected void switchOffsetRecordSign() { for (OffsetRecord offRec : this.offsetRecordList) offRec.signAdd= -offRec.signAdd; } // // Return value of token in string format base on type // protected String getValue() { if (this.type == TokenType.STRING) return "\"" + DVUtil.escapeString(this.stringConstant) + "\""; else if (this.type == TokenType.FLOAT) return this.floatConstant.toString(); else if (INT_VALUE.contains(this.type) || this.type == TokenType.OFFSET) return this.intConstant.toString(); else return "Invalid type: " + this.type.name(); } // // Expression token getter methods // public TokenType getType() { return this.type; } public BigInteger getIntConstant() { return this.intConstant; } public BigDecimal getFloatConstant() { return this.floatConstant; } public String getStringConstant() { return this.stringConstant; } public DVSymbols.Symbol getSymbol() { return this.symbol; } public DVSymbols.SymbolComponent getSymbolComponent() { return this.symbolComponent; } public String getQualifier() { return this.qualifier; } public DVSections.Section getOffsetSection() { return this.offsetRecordList.get(0).section; } public String getBaseID() { return this.baseID; } public DVSections.Section getBaseSection() { return this.baseSection; } public BigInteger getBaseRegisterValue() { return this.baseRegisterValue; } // // Expression token class variables // protected final TokenType type; protected final Token parseToken; // // Constant section // protected BigInteger intConstant= null; protected BigDecimal floatConstant= null; protected String stringConstant= null; // // Symbols // protected DVSymbols.Symbol symbol= null; protected DVSymbols.SymbolComponent symbolComponent; // // Offset sign // protected ArrayList offsetRecordList= null; protected String qualifier; // // Base/Symbol // protected String baseID= null; protected DVSections.Section baseSection; protected BigInteger baseRegisterValue= null; // // Operator section // protected OperType operType; protected int operPriority; protected boolean operLeftAssociation; } // // Merge offset records of two tokens // protected ExprToken mergeOffsetRecord(ExprToken t1, ExprToken t2, OperType operType) { ExprToken t3= t1.clone(); outer: for (OffsetRecord t2OffRec : t2.offsetRecordList) { for (OffsetRecord t3OffRec : t3.offsetRecordList) { if (t2OffRec.section == t3OffRec.section) { t3OffRec.signAdd+= (operType == OperType.PLUS ? 1 : -1)*t2OffRec.signAdd; if (t3OffRec.signAdd == 0) t3.offsetRecordList.remove(t3OffRec); continue outer; } } t3.offsetRecordList.add(new OffsetRecord(t2OffRec.section, (operType == OperType.PLUS ? 1 : -1)*t2OffRec.signAdd)); } if (t3.offsetRecordList.size() == 0) return new ExprToken(TokenType.DISPLACEMENT); return t3; } // // Attribute of offset constant sub-class // class OffsetRecord { protected OffsetRecord(DVSections.Section section, int signAdd) { this.section= section; this.signAdd= signAdd; } protected DVSections.Section section; protected int signAdd; } // // Class fields // private final DVStatements.Statement owner; private final LinkedList exprList= new LinkedList(); private final LinkedList exprStack= new LinkedList(); private static final String escapeChar= "0btnvfr\"\'\\"; private static final short[] escapeCharCode= { 0x00, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x22, 0x27, 0x5C }; // // Enumerators // public enum TokenType { OPERATOR, OFFSET, DISPLACEMENT, ABSOLUTE, FLOAT, STRING, SYMBOL, BASE_SYMBOL, BASE_DISPLACEMENT, EXTERNAL_SIZE, EXTERNAL_VALUE, EXTERNAL_ZERO } public static Set INT_VALUE= EnumSet.of(TokenType.ABSOLUTE, TokenType.DISPLACEMENT); protected enum OperType { RPAREN, UPLUS, UMINUS, BNOT, LNOT, POWER, MULTIPLY, DIVIDE, REMINDER, PLUS, MINUS, SHIFTLEFT, SHIFTRIGHT, GT, LT, GE, LE, EQ, NE, BAND, BXOR, BOR, LAND, LOR, LPAREN, ALIGN, // ALIGN and MAX used only internally - priority unused - set to -1 MAX } private static final Set OneParmOperator= EnumSet.of( OperType.UPLUS, OperType.UMINUS, OperType.BNOT, OperType.LNOT); private static final int[] operPriority= { 13, 12, 12, 12, 12, 11, 10, 10, 10, 9, 9, 8, 8, 7, 7, 7, 7, 6, 6, 5, 4, 3, 2, 1, 0, -1, -1 }; private static final boolean[] operLeftAssociation= { true, true, true, true, true, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true }; // // Math context for BigDecimal operations // public static final MathContext floatMC= new MathContext(35+10); // // Static fields used to define expression operators // private static final Method[] bIOper; private static final Method[] bIBIOper; private static final Method[] bIBDOper; private static final Method[] bDOper; private static final Method[] bDBDOper; private static final Method[] bDBIOper; static { Method[] bi= null; Method[] bibi= null; Method[] bibd= null; Method[] bd= null; Method[] bdbd= null; Method[] bdbi= null; try { bi= new Method[] { null, // RPAREN DVExpression.class.getDeclaredMethod("bIUPLUS", new Class[] {BigInteger.class}), // UPLUS DVExpression.class.getDeclaredMethod("bIUMINUS", new Class[] {BigInteger.class}), // UMINUS DVExpression.class.getDeclaredMethod("bIBNOT", new Class[] {BigInteger.class}), // BNOT DVExpression.class.getDeclaredMethod("bILNOT", new Class[] {BigInteger.class}), // LNOT null, // POWER null, // MULTIPLY null, // DIVIDE null, // REMINDER null, // PLUS null, // MINUS null, // SHIFTLEFT null, // SHIFTRIGHT null, // GT null, // LT null, // GE null, // LE null, // EQ null, // NE null, // BAND null, // BXOR null, // BOR null, // LAND null, // LOR null, // LPAREN null, // ALIGN null // MAX }; bibi= new Method[] { null, // RPAREN null, // UPLUS null, // UMINUS null, // BNOT null, // LNOT DVExpression.class.getDeclaredMethod("bIBIPOWER", new Class[] {BigInteger.class, BigInteger.class}), // POWER DVExpression.class.getDeclaredMethod("bIBIMULTIPLY", new Class[] {BigInteger.class, BigInteger.class}), // MULTIPLY DVExpression.class.getDeclaredMethod("bIBIDIVIDE", new Class[] {BigInteger.class, BigInteger.class}), // DIVIDE DVExpression.class.getDeclaredMethod("bIBIREMINDER", new Class[] {BigInteger.class, BigInteger.class}), // REMINDER DVExpression.class.getDeclaredMethod("bIBIPLUS", new Class[] {BigInteger.class, BigInteger.class}), // PLUS DVExpression.class.getDeclaredMethod("bIBIMINUS", new Class[] {BigInteger.class, BigInteger.class}), // MINUS DVExpression.class.getDeclaredMethod("bIBISHIFTLEFT", new Class[] {BigInteger.class, BigInteger.class}), // SHIFTLEFT DVExpression.class.getDeclaredMethod("bIBISHIFTRIGHT", new Class[] {BigInteger.class, BigInteger.class}), // SHIFTRIGHT DVExpression.class.getDeclaredMethod("bIBIGT", new Class[] {BigInteger.class, BigInteger.class}), // GT DVExpression.class.getDeclaredMethod("bIBILT", new Class[] {BigInteger.class, BigInteger.class}), // LT DVExpression.class.getDeclaredMethod("bIBIGE", new Class[] {BigInteger.class, BigInteger.class}), // GE DVExpression.class.getDeclaredMethod("bIBILE", new Class[] {BigInteger.class, BigInteger.class}), // LE DVExpression.class.getDeclaredMethod("bIBIEQ", new Class[] {BigInteger.class, BigInteger.class}), // EQ DVExpression.class.getDeclaredMethod("bIBINE", new Class[] {BigInteger.class, BigInteger.class}), // NE DVExpression.class.getDeclaredMethod("bIBIBAND", new Class[] {BigInteger.class, BigInteger.class}), // BAND DVExpression.class.getDeclaredMethod("bIBIBXOR", new Class[] {BigInteger.class, BigInteger.class}), // BXOR DVExpression.class.getDeclaredMethod("bIBIBOR", new Class[] {BigInteger.class, BigInteger.class}), // BOR DVExpression.class.getDeclaredMethod("bIBILAND", new Class[] {BigInteger.class, BigInteger.class}), // LAND DVExpression.class.getDeclaredMethod("bIBILOR", new Class[] {BigInteger.class, BigInteger.class}), // LOR null, // LPAREN DVExpression.class.getDeclaredMethod("bIBIALIGN", new Class[] {BigInteger.class, BigInteger.class}), // ALIGN DVExpression.class.getDeclaredMethod("bIBIMAX", new Class[] {BigInteger.class, BigInteger.class}) // MAX }; bibd= new Method[] { null, // RPAREN null, // UPLUS null, // UMINUS null, // BNOT null, // LNOT null, // POWER DVExpression.class.getDeclaredMethod("bIBDMULTIPLY", new Class[] {BigInteger.class, BigDecimal.class}), // MULTIPLY DVExpression.class.getDeclaredMethod("bIBDDIVIDE", new Class[] {BigInteger.class, BigDecimal.class}), // DIVIDE null, // REMINDER DVExpression.class.getDeclaredMethod("bIBDPLUS", new Class[] {BigInteger.class, BigDecimal.class}), // PLUS DVExpression.class.getDeclaredMethod("bIBDMINUS", new Class[] {BigInteger.class, BigDecimal.class}), // MINUS null, // SHIFTLEFT null, // SHIFTRIGHT DVExpression.class.getDeclaredMethod("bIBDGT", new Class[] {BigInteger.class, BigDecimal.class}), // GT DVExpression.class.getDeclaredMethod("bIBDLT", new Class[] {BigInteger.class, BigDecimal.class}), // LT DVExpression.class.getDeclaredMethod("bIBDGE", new Class[] {BigInteger.class, BigDecimal.class}), // GE DVExpression.class.getDeclaredMethod("bIBDLE", new Class[] {BigInteger.class, BigDecimal.class}), // LE DVExpression.class.getDeclaredMethod("bIBDEQ", new Class[] {BigInteger.class, BigDecimal.class}), // EQ DVExpression.class.getDeclaredMethod("bIBDNE", new Class[] {BigInteger.class, BigDecimal.class}), // NE null, // BAND null, // BXOR null, // BOR null, // LAND null, // LOR null, // LPAREN null, // ALIGN null // MAX }; bd= new Method[] { null, // RPAREN DVExpression.class.getDeclaredMethod("bDUPLUS", new Class[] {BigDecimal.class}), // UPLUS DVExpression.class.getDeclaredMethod("bDUMINUS", new Class[] {BigDecimal.class}), // UMINUS null, // BNOT null, // LNOT null, // POWER null, // MULTIPLY null, // DIVIDE null, // REMINDER null, // PLUS null, // MINUS null, // SHIFTLEFT null, // SHIFTRIGHT null, // GT null, // LT null, // GE null, // LE null, // EQ null, // NE null, // BAND null, // BXOR null, // BOR null, // LAND null, // LOR null, // LPAREN null, // ALIGN null // MAX }; bdbd= new Method[] { null, // RPAREN null, // UPLUS null, // UMINUS null, // BNOT null, // LNOT null, // POWER DVExpression.class.getDeclaredMethod("bDBDMULTIPLY", new Class[] {BigDecimal.class, BigDecimal.class}), // MULTIPLY DVExpression.class.getDeclaredMethod("bDBDDIVIDE", new Class[] {BigDecimal.class, BigDecimal.class}), // DIVIDE null, // REMINDER DVExpression.class.getDeclaredMethod("bDBDPLUS", new Class[] {BigDecimal.class, BigDecimal.class}), // PLUS DVExpression.class.getDeclaredMethod("bDBDMINUS", new Class[] {BigDecimal.class, BigDecimal.class}), // MINUS null, // SHIFTLEFT null, // SHIFTRIGHT DVExpression.class.getDeclaredMethod("bDBDGT", new Class[] {BigDecimal.class, BigDecimal.class}), // GT DVExpression.class.getDeclaredMethod("bDBDLT", new Class[] {BigDecimal.class, BigDecimal.class}), // LT DVExpression.class.getDeclaredMethod("bDBDGE", new Class[] {BigDecimal.class, BigDecimal.class}), // GE DVExpression.class.getDeclaredMethod("bDBDLE", new Class[] {BigDecimal.class, BigDecimal.class}), // LE DVExpression.class.getDeclaredMethod("bDBDEQ", new Class[] {BigDecimal.class, BigDecimal.class}), // EQ DVExpression.class.getDeclaredMethod("bDBDNE", new Class[] {BigDecimal.class, BigDecimal.class}), // NE null, // BAND null, // BXOR null, // BOR null, // LAND null, // LOR null, // LPAREN null, // ALIGN null // MAX }; bdbi= new Method[] { null, // RPAREN null, // UPLUS null, // UMINUS null, // BNOT null, // LNOT DVExpression.class.getDeclaredMethod("bDBIPOWER", new Class[] {BigDecimal.class, BigInteger.class}), // POWER DVExpression.class.getDeclaredMethod("bDBIMULTIPLY", new Class[] {BigDecimal.class, BigInteger.class}), // MULTIPLY DVExpression.class.getDeclaredMethod("bDBIDIVIDE", new Class[] {BigDecimal.class, BigInteger.class}), // DIVIDE null, // REMINDER DVExpression.class.getDeclaredMethod("bDBIPLUS", new Class[] {BigDecimal.class, BigInteger.class}), // PLUS DVExpression.class.getDeclaredMethod("bDBIMINUS", new Class[] {BigDecimal.class, BigInteger.class}), // MINUS null, // SHIFTLEFT null, // SHIFTRIGHT DVExpression.class.getDeclaredMethod("bDBIGT", new Class[] {BigDecimal.class, BigInteger.class}), // GT DVExpression.class.getDeclaredMethod("bDBILT", new Class[] {BigDecimal.class, BigInteger.class}), // LT DVExpression.class.getDeclaredMethod("bDBIGE", new Class[] {BigDecimal.class, BigInteger.class}), // GE DVExpression.class.getDeclaredMethod("bDBILE", new Class[] {BigDecimal.class, BigInteger.class}), // LE DVExpression.class.getDeclaredMethod("bDBIEQ", new Class[] {BigDecimal.class, BigInteger.class}), // EQ DVExpression.class.getDeclaredMethod("bDBINE", new Class[] {BigDecimal.class, BigInteger.class}), // NE null, // BAND null, // BXOR null, // BOR null, // LAND null, // LOR null, // LPAREN null, // ALIGN null // MAX }; } catch (NoSuchMethodException e) { System.err.println("Expression Class initialization failed due to exception\n" + DVUtil.formatException("Initialization Exception: ", e) + "\n"); throw new RuntimeException(e); } bIOper= bi; bIBIOper= bibi; bIBDOper= bibd; bDOper= bd; bDBDOper= bdbd; bDBIOper= bdbi; } // // BigInteger static methods // private static BigInteger bIUPLUS(BigInteger v1) { return v1; } private static BigInteger bIUMINUS(BigInteger v1) { return v1.negate(); } private static BigInteger bIBNOT(BigInteger v1) { return v1.not(); } private static BigInteger bILNOT(BigInteger v1) { return (v1.compareTo(BigInteger.ZERO) == 0) ? BigInteger.ZERO : BigInteger.ONE; } // // BigInteger - BigInteger static methods // private static BigInteger bIBIPOWER(BigInteger v1, BigInteger v2) { return v1.pow(v2.intValue()); } private static BigInteger bIBIMULTIPLY(BigInteger v1, BigInteger v2) { return v1.multiply(v2); } private static BigInteger bIBIDIVIDE(BigInteger v1, BigInteger v2) { return v1.divide(v2); } private static BigInteger bIBIREMINDER(BigInteger v1, BigInteger v2) { return v1.mod(v2); } private static BigInteger bIBIPLUS(BigInteger v1, BigInteger v2) { return v1.add(v2); } private static BigInteger bIBIMINUS(BigInteger v1, BigInteger v2) { return v1.subtract(v2); } private static BigInteger bIBISHIFTLEFT(BigInteger v1, BigInteger v2) { return v1.shiftLeft(v2.intValue()); } private static BigInteger bIBISHIFTRIGHT(BigInteger v1, BigInteger v2) { return v1.shiftRight(v2.intValue()); } private static BigInteger bIBIGT(BigInteger v1, BigInteger v2) { return (v1.compareTo(v2) > 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bIBILT(BigInteger v1, BigInteger v2) { return (v1.compareTo(v2) < 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bIBIGE(BigInteger v1, BigInteger v2) { return (v1.compareTo(v2) >= 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bIBILE(BigInteger v1, BigInteger v2) { return (v1.compareTo(v2) <= 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bIBIEQ(BigInteger v1, BigInteger v2) { return (v1.compareTo(v2) == 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bIBINE(BigInteger v1, BigInteger v2) { return (v1.compareTo(v2) != 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bIBIBAND(BigInteger v1, BigInteger v2) { return v1.and(v2); } private static BigInteger bIBIBXOR(BigInteger v1, BigInteger v2) { return v1.xor(v2); } private static BigInteger bIBIBOR(BigInteger v1, BigInteger v2) { return v1.or(v2); } private static BigInteger bIBILAND(BigInteger v1, BigInteger v2) { return ((v1.compareTo(BigInteger.ZERO) != 0) && (v2.compareTo(BigInteger.ZERO) != 0)) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bIBILOR(BigInteger v1, BigInteger v2) { return ((v1.compareTo(BigInteger.ZERO) != 0) || (v2.compareTo(BigInteger.ZERO) != 0)) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bIBIMAX(BigInteger v1, BigInteger v2) { return v1.max(v2); } private static BigInteger bIBIALIGN(BigInteger v1, BigInteger v2) { return v1.add(v2.subtract(BigInteger.ONE)).divide(v2).multiply(v2); } // // BigInteger - BigDecimal static methods // private static BigDecimal bIBDMULTIPLY(BigInteger v1, BigDecimal v2) { return (new BigDecimal(v1, floatMC)).multiply(v2, floatMC); } private static BigDecimal bIBDDIVIDE(BigInteger v1, BigDecimal v2) { return (new BigDecimal(v1, floatMC)).divide(v2, floatMC); } private static BigDecimal bIBDPLUS(BigInteger v1, BigDecimal v2) { return (new BigDecimal(v1, floatMC)).add(v2, floatMC); } private static BigDecimal bIBDMINUS(BigInteger v1, BigDecimal v2) { return (new BigDecimal(v1, floatMC)).subtract(v2, floatMC); } private static BigInteger bIBDGT(BigInteger v1, BigDecimal v2) { return ((new BigDecimal(v1, floatMC)).compareTo(v2) > 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bIBDLT(BigInteger v1, BigDecimal v2) { return ((new BigDecimal(v1, floatMC)).compareTo(v2) < 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bIBDGE(BigInteger v1, BigDecimal v2) { return ((new BigDecimal(v1, floatMC)).compareTo(v2) >= 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bIBDLE(BigInteger v1, BigDecimal v2) { return ((new BigDecimal(v1, floatMC)).compareTo(v2) <= 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bIBDEQ(BigInteger v1, BigDecimal v2) { return ((new BigDecimal(v1, floatMC)).compareTo(v2) == 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bIBDNE(BigInteger v1, BigDecimal v2) { return ((new BigDecimal(v1, floatMC)).compareTo(v2) != 0) ? BigInteger.ONE : BigInteger.ZERO; } // // BigDecimal only static methods // private static BigDecimal bDUPLUS(BigDecimal v1) { return v1; } private static BigDecimal bDUMINUS(BigDecimal v1) { return v1.negate(floatMC); } // // BigDecimal - BigDecimal static methods // private static BigDecimal bDBDMULTIPLY(BigDecimal v1, BigDecimal v2) { return v1.multiply(v2, floatMC); } private static BigDecimal bDBDDIVIDE(BigDecimal v1, BigDecimal v2) { return v1.divide(v2, floatMC); } private static BigDecimal bDBDPLUS(BigDecimal v1, BigDecimal v2) { return v1.add(v2, floatMC); } private static BigDecimal bDBDMINUS(BigDecimal v1, BigDecimal v2) { return v1.subtract(v2, floatMC); } private static BigInteger bDBDGT(BigDecimal v1, BigDecimal v2) { return (v1.compareTo(v2) > 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bDBDLT(BigDecimal v1, BigDecimal v2) { return (v1.compareTo(v2) < 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bDBDGE(BigDecimal v1, BigDecimal v2) { return (v1.compareTo(v2) >= 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bDBDLE(BigDecimal v1, BigDecimal v2) { return (v1.compareTo(v2) <= 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bDBDEQ(BigDecimal v1, BigDecimal v2) { return (v1.compareTo(v2) == 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bDBDNE(BigDecimal v1, BigDecimal v2) { return (v1.compareTo(v2) != 0) ? BigInteger.ONE : BigInteger.ZERO; } // // BigDecimal - BigInteger static methods // private static BigDecimal bDBIPOWER(BigDecimal v1, BigInteger v2) { return v1.pow(v2.intValue(), floatMC); } private static BigDecimal bDBIMULTIPLY(BigDecimal v1, BigInteger v2) { return v1.multiply(new BigDecimal(v2, floatMC), floatMC); } private static BigDecimal bDBIDIVIDE(BigDecimal v1, BigInteger v2) { return v1.divide(new BigDecimal(v2, floatMC), floatMC); } private static BigDecimal bDBIPLUS(BigDecimal v1, BigInteger v2) { return v1.add(new BigDecimal(v2, floatMC), floatMC); } private static BigDecimal bDBIMINUS(BigDecimal v1, BigInteger v2) { return v1.subtract(new BigDecimal(v2, floatMC), floatMC); } private static BigInteger bDBIGT(BigDecimal v1, BigInteger v2) { return (v1.compareTo(new BigDecimal(v2)) > 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bDBILT(BigDecimal v1, BigInteger v2) { return (v1.compareTo(new BigDecimal(v2)) < 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bDBIGE(BigDecimal v1, BigInteger v2) { return (v1.compareTo(new BigDecimal(v2)) >= 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bDBILE(BigDecimal v1, BigInteger v2) { return (v1.compareTo(new BigDecimal(v2)) <= 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bDBIEQ(BigDecimal v1, BigInteger v2) { return (v1.compareTo(new BigDecimal(v2)) == 0) ? BigInteger.ONE : BigInteger.ZERO; } private static BigInteger bDBINE(BigDecimal v1, BigInteger v2) { return (v1.compareTo(new BigDecimal(v2)) != 0) ? BigInteger.ONE : BigInteger.ZERO; } }