diff --git a/Ghidra/Features/Base/data/typeinfo/generic/generic_clib.gdt b/Ghidra/Features/Base/data/typeinfo/generic/generic_clib.gdt
index 4dad0502af..b5399bdd0c 100644
Binary files a/Ghidra/Features/Base/data/typeinfo/generic/generic_clib.gdt and b/Ghidra/Features/Base/data/typeinfo/generic/generic_clib.gdt differ
diff --git a/Ghidra/Features/Base/data/typeinfo/generic/generic_clib_64.gdt b/Ghidra/Features/Base/data/typeinfo/generic/generic_clib_64.gdt
index 5669acb4f1..18cfbb8c9c 100644
Binary files a/Ghidra/Features/Base/data/typeinfo/generic/generic_clib_64.gdt and b/Ghidra/Features/Base/data/typeinfo/generic/generic_clib_64.gdt differ
diff --git a/Ghidra/Features/Base/data/typeinfo/win32/windows_vs12_32.gdt b/Ghidra/Features/Base/data/typeinfo/win32/windows_vs12_32.gdt
index f5eeb6f54f..c34d8e0b13 100644
Binary files a/Ghidra/Features/Base/data/typeinfo/win32/windows_vs12_32.gdt and b/Ghidra/Features/Base/data/typeinfo/win32/windows_vs12_32.gdt differ
diff --git a/Ghidra/Features/Base/data/typeinfo/win32/windows_vs12_64.gdt b/Ghidra/Features/Base/data/typeinfo/win32/windows_vs12_64.gdt
index 37eb0ab301..5ed3b70894 100644
Binary files a/Ghidra/Features/Base/data/typeinfo/win32/windows_vs12_64.gdt and b/Ghidra/Features/Base/data/typeinfo/win32/windows_vs12_64.gdt differ
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/function/CallDepthChangeInfo.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/function/CallDepthChangeInfo.java
index 2097ce1bf8..6116ed5393 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/function/CallDepthChangeInfo.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/function/CallDepthChangeInfo.java
@@ -169,22 +169,6 @@ public class CallDepthChangeInfo {
followFlows(func, restrictSet, monitor);
-// try {
-// CodeBlockIterator cbIter = new SimpleBlockModel(program).getCodeBlocksContaining(body, monitor);
-// while (cbIter.hasNext()) {
-// CodeBlock block = cbIter.next();
-// codeBlocks.add(block);
-// if (block.getFlowType().isCall()) {
-// Instruction instr = program.getListing()
-// .getInstructionContaining(block.getMaxAddress());
-// if (instr != null) {
-// callLocs.add(instr.getMinAddress());
-// }
-// }
-// }
-// computeDepthChange(monitor);
-// } catch (UncomputableStackDepthException e) {
-// }
}
public int getCallChange(Address addr) {
@@ -236,8 +220,7 @@ public class CallDepthChangeInfo {
* depth cannot be determined, then return that the stack depth change is
* unknown.
*
- * @param instr
- * instruction to analyze
+ * @param instr instruction to analyze
*
* @return int change to stack depth if it can be determined,
* Function.UNKNOWN_STACK_DEPTH_CHANGE otherwise.
@@ -413,21 +396,6 @@ public class CallDepthChangeInfo {
return false;
}
- /**
- * Get the default/assumed stack depth change for this language
- *
- * @param depth stack depth to return if the default is unknown for the language
- * @return
- */
- private int getDefaultStackDepthChange(int depth) {
- PrototypeModel defaultModel = program.getCompilerSpec().getDefaultCallingConvention();
- int callStackMod = defaultModel.getExtrapop();
- int callStackShift = defaultModel.getStackshift();
- if (callStackMod != PrototypeModel.UNKNOWN_EXTRAPOP && callStackShift >= 0) {
- return callStackShift - callStackMod;
- }
- return depth;
- }
/**
* Gets the stack depth change value that has been set at the indicated address.
@@ -507,132 +475,6 @@ public class CallDepthChangeInfo {
return ipm.getPropertyIterator(addressSet);
}
- /**
- * Do a better job of tracking the stack by attempting to follow the data
- * flow of the stack pointer as it moves in and out of other variables.
- *
- * @param program1 -
- * program containing the function to analyze
- * @param func -
- * function to analyze stack pointer references
- */
- public int smoothDepth(Program program1, Function func, TaskMonitor monitor) {
- if (trans.supportsPcode()) {
- return smoothPcodeDepth(program1, func, monitor);
- }
-
- int returnStackDepth = Function.INVALID_STACK_DEPTH_CHANGE;
-
- // terminal points
- ArrayList
terminalPoints = new ArrayList(); // list of points that are
- // terminal to this function
-
- Stack st = new Stack();
- st.push(func.getEntryPoint());
- st.push(new Integer(0));
- st.push(Boolean.TRUE);
- ProcessorContextImpl procContext = new ProcessorContextImpl(program.getLanguage());
-
- AddressSet undone = new AddressSet(func.getBody());
- AddressSet badStackSet = new AddressSet(undone);
- while (!st.empty()) {
- Boolean stackOK = (Boolean) st.pop();
- int stackPointerDepth = ((Integer) st.pop()).intValue();
- Address loc = (Address) st.pop();
-
- if (!undone.contains(loc)) {
- continue;
- }
- // remove instruction from address set
- undone.deleteRange(loc, loc);
-
- Instruction instr = program1.getListing().getInstructionAt(loc);
- if (instr == null) {
- continue;
- }
-
- if (stackOK == Boolean.TRUE) {
- this.setDepth(instr, stackPointerDepth);
- }
-
- // check for a frame setup
-// if (checkFrameSetup(instr, stackPointerDepth, procContext)) {
-// isFrameBased = true;
-// }
-
- // process any stack pointer manipulations
- int instrChangeDepth =
- this.getInstructionStackDepthChange(instr, procContext, stackPointerDepth);
- if (instrChangeDepth != Function.UNKNOWN_STACK_DEPTH_CHANGE &&
- instrChangeDepth != Function.INVALID_STACK_DEPTH_CHANGE) {
- stackPointerDepth += instrChangeDepth;
- }
- else {
- stackOK = Boolean.FALSE;
- }
-
- // if stack is OK at this instruction, remove from the bad stack set
- if (stackOK == Boolean.TRUE) {
- badStackSet.deleteRange(instr.getMinAddress(), instr.getMaxAddress());
- }
-
- // push any control flows that are still in address set
- FlowType flow = instr.getFlowType();
- if (!flow.isCall()) {
- Address[] flows = instr.getFlows();
- for (Address flow2 : flows) {
- st.push(flow2);
- st.push(new Integer(stackPointerDepth));
- st.push(stackOK);
- }
- }
- else {
- // see if the info structure has the call depth
- int callStackChange = getCallChange(instr.getMinAddress());
- if (callStackChange == Function.UNKNOWN_STACK_DEPTH_CHANGE ||
- callStackChange == Function.INVALID_STACK_DEPTH_CHANGE) {
- stackOK = Boolean.FALSE;
- }
- else if (stackOK == Boolean.TRUE) {
- stackPointerDepth += callStackChange;
- }
- }
- Address fallThru = instr.getFallThrough();
- if (fallThru != null) {
- st.push(fallThru);
- st.push(new Integer(stackPointerDepth));
- st.push(stackOK);
- }
- if (flow.isTerminal()) {
- int instrPurge =
- getInstructionStackDepthChange(instr, procContext, returnStackDepth);
- if (stackOK.booleanValue()) {
- returnStackDepth = stackPointerDepth - instrPurge;
- }
- else {
- returnStackDepth = -instrPurge;
- terminalPoints.add(instr.getMinAddress());
- }
-// if (instr.getScalar(0) != null) {
-// returnStackDepth = (int) -instr.getScalar(0)
-// .getSignedValue();
-// } else {
-// if (stackOK == Boolean.TRUE) {
-// returnStackDepth = stackPointerDepth;
-// } else {
-// terminalPoints.add(instr.getMinAddress());
-// }
-// }
- }
- }
-
- // if (processTerminal) {
- // backPropogateStackDepth(program, func, badStackSet, this,
- // procContext, terminalPoints, monitor);
- // }
-
- return returnStackDepth;
- }
/**
* Follow the flows of the subroutine, accumulating information about the
@@ -642,7 +484,7 @@ public class CallDepthChangeInfo {
* function to analyze
* @param monitor
* monitor to provide feedback and cancel
- * @throws CancelledException
+ * @throws CancelledException if monitor canceled
*/
private void followFlows(Function func, AddressSetView restrictSet, TaskMonitor monitor)
throws CancelledException {
@@ -668,16 +510,16 @@ public class CallDepthChangeInfo {
Varnode stackValue = null;
try {
stackValue = context.getValue(stackRegVarnode, true, this);
+
+ if (stackValue != null && context.isSymbol(stackValue) && context.isStackSymbolicSpace(stackValue)) {
+ int stackPointerDepth = (int) stackValue.getOffset();
+ setDepth(instr, stackPointerDepth);
+ }
}
catch (NotFoundException e) {
+ // ignore
}
- //Varnode stackValue = context.getRegisterVarnodeValue(stackReg, instr.getMinAddress(), true);
- if (stackValue != null && context.isSymbol(stackValue) &&
- stackValue.getAddress().getAddressSpace().getName().equals(
- stackReg.getName())) {
- int stackPointerDepth = (int) stackValue.getOffset();
- setDepth(instr, stackPointerDepth);
- }
+
return false;
}
@@ -713,9 +555,9 @@ public class CallDepthChangeInfo {
private void checkForStackOffset(VarnodeContext context, Instruction instr,
Address address, int opIndex) {
- AddressSpace space = address.getAddressSpace();
- if (space.getName().startsWith("track_") ||
- space.getName().equals(stackReg.getName())) {
+ String spaceName = address.getAddressSpace().getName();
+ if (spaceName.startsWith("track_") || context.isStackSpaceName(spaceName)) {
+ // TODO: what to do on a Symbolic reference
}
}
};
@@ -735,55 +577,6 @@ public class CallDepthChangeInfo {
return;
}
-// /**
-// * Checks the indicated function in the program to determine if it is a jump thunk
-// * through a function pointer.
-// * @param func the function to check
-// * @param monitor status monitor for indicating progress and allowing cancel.
-// * @return true if check if this is a jump thunk through a function pointer
-// */
-// private boolean checkThunk(Function func, TaskMonitor monitor) {
-// Instruction instr = program.getListing().getInstructionAt(func.getEntryPoint());
-// if (instr == null) {
-// return false;
-// }
-//
-// FlowType type = instr.getFlowType();
-// if (!type.isJump() || !type.isComputed()) {
-// return false;
-// }
-//
-// Address flows[] = instr.getFlows();
-// if (flows != null && flows.length > 0) {
-// return false;
-// }
-//
-// Reference refs[] = instr.getReferencesFrom();
-// if (refs == null || refs.length == 0) {
-// return false;
-// }
-//
-// Function indirFunc = program.getFunctionManager().getFunctionAt(refs[0].getToAddress());
-// FunctionSignature fsig = null;
-// int purge = Function.UNKNOWN_STACK_DEPTH_CHANGE;
-// if (indirFunc != null) {
-// fsig = indirFunc.getSignature();
-// purge = indirFunc.getStackPurgeSize();
-// }
-// else {
-// Data data = program.getListing().getDataAt(refs[0].getToAddress());
-// if (data != null && data.isPointer() &&
-// data.getDataType() instanceof FunctionDefinition) {
-// FunctionDefinition fdef = (FunctionDefinition) data.getDataType();
-// fsig = fdef;
-// }
-// }
-// if (fsig == null) {
-// return false;
-// }
-// func.setStackPurgeSize(purge);
-// return true;
-// }
public int getStackPurge() {
return stackPurge;
@@ -882,170 +675,4 @@ public class CallDepthChangeInfo {
public String getRegValueRepresentation(Address addr, Register reg) {
return symEval.getRegisterValueRepresentation(addr, reg);
}
-
- /**
- * Create locals and parameters based on references involving purely the
- * stack pointer. Pushes, Pops, and arithmetic manipulation of the stack
- * pointer must be tracked.
- *
- * @param program1 -
- * program containing the function to analyze
- * @param func -
- * function to analyze stack pointer references
- */
- private int smoothPcodeDepth(Program program1, Function func, TaskMonitor monitor) {
-
- int returnStackDepth = Function.INVALID_STACK_DEPTH_CHANGE;
-
- ArrayList terminalPoints = new ArrayList(); // list of points that are
- // terminal to this function
-
- Stack st = new Stack();
- st.push(func.getEntryPoint());
- st.push(Integer.valueOf(0));
- st.push(Boolean.TRUE);
- ProcessorContextImpl procContext = new ProcessorContextImpl(program.getLanguage());
-
- AddressSet undone = new AddressSet(func.getBody());
- AddressSet badStackSet = new AddressSet(undone);
- while (!st.empty()) {
- Boolean stackOK = (Boolean) st.pop();
- int stackPointerDepth = ((Integer) st.pop()).intValue();
- Address loc = (Address) st.pop();
-
- if (!undone.contains(loc)) {
- continue;
- }
- // remove instruction from address set
- undone.deleteRange(loc, loc);
-
- Instruction instr = program1.getListing().getInstructionAt(loc);
- if (instr == null) {
- continue;
- }
-
- if (stackOK == Boolean.TRUE) {
- this.setDepth(instr, stackPointerDepth);
- }
-
- // check for a frame setup
-// if (checkFrameSetup(instr, stackPointerDepth, procContext)) {
-// isFrameBased = true;
-// }
-
- // process any stack pointer manipulations
- int instrChangeDepth =
- this.getInstructionStackDepthChange(instr, procContext, stackPointerDepth);
- if (instrChangeDepth != Function.UNKNOWN_STACK_DEPTH_CHANGE) {
- stackPointerDepth += instrChangeDepth;
- }
- else {
- stackOK = Boolean.FALSE;
- }
-
- // if stack is OK at this instruction, remove from the bad stack set
- if (stackOK == Boolean.TRUE) {
- badStackSet.deleteRange(instr.getMinAddress(), instr.getMaxAddress());
- }
-
- // push any control flows that are still in address set
- FlowType flow = instr.getFlowType();
- if (!flow.isCall()) {
- Address[] flows = instr.getFlows();
- for (Address flow2 : flows) {
- st.push(flow2);
- st.push(Integer.valueOf(stackPointerDepth));
- st.push(stackOK);
- }
- }
- else {
- // see if the info structure has the call depth
- int callStackChange = getCallPurge(instr);
- if (callStackChange == Function.UNKNOWN_STACK_DEPTH_CHANGE) {
- callStackChange = this.getCallChange(instr.getMinAddress());
- }
- if (callStackChange == Function.UNKNOWN_STACK_DEPTH_CHANGE) {
- stackOK = Boolean.FALSE;
- }
- else if (stackOK == Boolean.TRUE) {
- stackPointerDepth += callStackChange;
- }
- }
- Address fallThru = instr.getFallThrough();
- if (fallThru != null) {
- st.push(fallThru);
- st.push(new Integer(stackPointerDepth));
- st.push(stackOK);
- }
- if (flow.isTerminal()) {
- if (stackOK == Boolean.TRUE) {
- returnStackDepth = stackPointerDepth;
- }
- else {
- if (instr.getScalar(0) != null) {
- returnStackDepth = (int) instr.getScalar(0).getSignedValue();
- }
- else {
- terminalPoints.add(instr.getMinAddress());
- }
- }
- }
- }
-
- // if (processTerminal) {
- // backPropogateStackDepth(program, func, badStackSet, this,
- // procContext, terminalPoints, monitor);
- // }
-
- return returnStackDepth;
- }
-
- /**
- * @param instr
- */
- private int getCallPurge(Instruction instr) {
-
- // see if there is an override at this address
- Integer override = overrideMap.get(instr.getMinAddress());
- if (override != null) {
- return override.intValue();
- }
-
- FlowType fType = instr.getFlowType();
- Address[] flows;
- if (fType.isComputed()) {
- Reference refs[] = instr.getReferencesFrom();
- flows = new Address[refs.length];
- for (int ri = 0; ri < refs.length; ri++) {
- Data data = program.getListing().getDataAt(refs[ri].getToAddress());
- if (data != null && data.isPointer()) {
- Reference pointerRef = data.getPrimaryReference(0);
- if (pointerRef != null) {
- flows[ri] = pointerRef.getToAddress();
- }
- }
- }
- }
- else {
- flows = instr.getFlows();
- }
-
- // try to find a call destination that the stack frame is known
- for (Address flow : flows) {
- if (flow == null) {
- continue;
- }
- Function func = program.getListing().getFunctionAt(flow);
- if (func != null) {
- int purge = func.getStackPurgeSize();
- if (func.isStackPurgeSizeValid() && purge != Function.UNKNOWN_STACK_DEPTH_CHANGE &&
- purge != Function.INVALID_STACK_DEPTH_CHANGE) {
- return purge;
- }
- }
- }
-
- return getDefaultStackDepthChange(Function.UNKNOWN_STACK_DEPTH_CHANGE);
- }
-
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/function/NewFunctionStackAnalysisCmd.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/function/NewFunctionStackAnalysisCmd.java
index 5458cbc354..b5111d8a58 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/function/NewFunctionStackAnalysisCmd.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/function/NewFunctionStackAnalysisCmd.java
@@ -298,7 +298,7 @@ public class NewFunctionStackAnalysisCmd extends BackgroundCommand {
Address address, int opIndex) {
AddressSpace space = address.getAddressSpace();
String spaceName = space.getName();
- if (spaceName.startsWith("track_") || spaceName.equals(stackReg.getName())) {
+ if (spaceName.startsWith("track_") || context.isStackSpaceName(spaceName)) {
if (opIndex == -1) {
opIndex = getStackOpIndex(context, instr, (int) address.getOffset());
// if didn't get the right opIndex, and has a delayslot, check for good stack ref
@@ -576,7 +576,7 @@ public class NewFunctionStackAnalysisCmd extends BackgroundCommand {
continue;
}
String spaceName = vnode.getAddress().getAddressSpace().getName();
- if (spaceName.startsWith("track_") || spaceName.equals(stackReg.getName())) {
+ if (spaceName.startsWith("track_") || context.isStackSpaceName(spaceName)) {
// opLocation = opIndex;
local_offset += (int) vnode.getOffset();
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/StackDepthFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/StackDepthFieldFactory.java
index 64c4168c84..a55b564afd 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/StackDepthFieldFactory.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/StackDepthFieldFactory.java
@@ -89,7 +89,7 @@ public class StackDepthFieldFactory extends FieldFactory {
//Register stackReg = cu.getProgram().getCompilerSpec().getStackPointer();
int depthChange = depth.getDepth(cu.getMinAddress());
- String depthString = getDepthString(depthChange);
+ String depthString = getDepthString(depthChange, cu.isInDelaySlot());
// This can be used to display the value of any register symbolically flowing over the program.
// depthString = depth.getRegValueRepresentation(cu.getMinAddress(), cu.getProgram().getRegister("ESP"));
@@ -113,8 +113,13 @@ public class StackDepthFieldFactory extends FieldFactory {
* @param depthChange
* @return
*/
- private String getDepthString(int depthChange) {
+ private String getDepthString(int depthChange, boolean isInDelaySlot) {
+ if (isInDelaySlot) {
+ return ""; // if in delayslot, stack changes will be on main instruction
+ }
+
String stringDepth = "- ? -";
+
if (depthChange != Function.UNKNOWN_STACK_DEPTH_CHANGE &&
depthChange != Function.INVALID_STACK_DEPTH_CHANGE) {
if (depthChange > 0) {
@@ -129,6 +134,7 @@ public class StackDepthFieldFactory extends FieldFactory {
stringDepth = filler.substring(len) + stringDepth;
}
}
+
return stringDepth;
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/cparser/CPP/DefineTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/cparser/CPP/DefineTable.java
index 6525339e69..83b0573965 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/cparser/CPP/DefineTable.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/cparser/CPP/DefineTable.java
@@ -27,6 +27,8 @@ import ghidra.util.Msg;
*
*/
public class DefineTable {
+ private static final int ARBITRARY_MAX_REPLACEMENTS = 900000;
+
// Hastable for storing #defs
Hashtable defs = new Hashtable();
@@ -267,40 +269,32 @@ public class DefineTable {
* return a string with all the macros substitute starting at pos in the input string.
* @param image string to expand
* @param pos position within string to start expanding
- * @return
+ * @return string with all substitutions applied
*/
private String macroSub(String image, int pos, ArrayList sublist) {
int replaceCount = 0;
StringBuffer buf = new StringBuffer(image);
+ int lastReplPos = pos;
- // don't replace an infinite number of times.
- //HashMap lastReplStrings = new HashMap();
- while (pos < buf.length() && replaceCount < 900000) {
+ // don't replace an infinite number of times. Fail safe for possible ininite loop
+ while (pos < buf.length() && replaceCount < ARBITRARY_MAX_REPLACEMENTS) {
+ // clear list of used macros when move past replacement area
+ if (pos == lastReplPos) {
+ sublist = new ArrayList (); // ok to clear list of used macro names
+ }
String defName = getDefineAt(buf, pos);
if (shouldReplace(buf, defName, pos)) {
// stop recursion on the same replacement string
-// if (lastReplStrings.containsKey(defName)) {
-// int lastpos = lastReplStrings.get(defName);
-// Vector argv = getArgs(defName);
-// // if it has no args, don't replace already replaced.
-// if (argv == null && pos < lastpos) {
-// System.out.println("Already did : " + defName);
-// System.out.println(" No repl at " + pos + " lastpos " + lastpos + " : " + buf);
-// pos++;
-// continue;
-// }
-// lastReplStrings.remove(defName);
-// }
- int newpos = replace(buf, defName, pos, sublist);
- // is there a replacement string
- if (newpos == -1) {
+ int replPos = replace(buf, defName, pos, sublist);
+
+ if (replPos == -1) {
+ // if no replacement string, move on
pos++;
}
else {
- //System.err.println(" replace " + defName + " with " + buf.substring(pos,newpos));
- //lastReplStrings.put(defName,pos + defName.length());
- pos = newpos;
+ // replaced text, update the last place a replacement was made
+ lastReplPos = replPos;
replaceCount++;
}
}
@@ -308,7 +302,7 @@ public class DefineTable {
pos++;
}
}
- if (replaceCount >= 100000) {
+ if (replaceCount >= ARBITRARY_MAX_REPLACEMENTS) {
System.err.println(" replace " + image + " hit limit");
}
return buf.toString();
@@ -319,7 +313,6 @@ public class DefineTable {
return false;
}
- //String nextRepl = "";
int currIndex = buf.indexOf(defName, pos);
if (currIndex < 0) {
return false; // nothing to replace
@@ -342,25 +335,6 @@ public class DefineTable {
return false; // no need to replace
}
-// // check that macro argv arguments match
-// Vector argv = getArgs(defName);
-// if (argv != null && argv.size() > 0) {
-// // need to scan carefully, and recursively
-// // there shouldn't be so many globals...
-// // could be screwed up by so many things
-// String parms = getParams(buf, currIndex + defName.length(),
-// (char) 0);
-//
-// int parmslen = parms.length();
-// if (parmslen < 2) {
-// return false;
-// }
-// parms = parms.trim();
-// if (!parms.startsWith("(") || !parms.endsWith(")")) {
-// return false;
-// }
-// }
-
return true;
}
@@ -423,19 +397,9 @@ public class DefineTable {
replacedSubpieceLen += parmslen;
}
- // you may add an else if{} block to warn of malformed macros
- // but the actual culprit may be the Define() non-terminal
- //if (replString != null)
- // nextRepl += replString;
- sublist = new ArrayList(sublist);
sublist.add(currKey);
- String newReplString = macroSub(replacementString, 0, sublist);
- if (newReplString != null) {
- replacementString = newReplString;
- }
buf.replace(currIndex, currIndex + replacedSubpieceLen, replacementString);
- //nextRepl += image.substring(currIndex + currKey.length());
return currIndex + replacementString.length();
}
@@ -543,19 +507,25 @@ public class DefineTable {
if (pos >= len) {
return "";
}
+
char ch = buf.charAt(pos);
+ char lastChar = 0;
boolean hitQuote = false;
+ boolean hitTick = false;
while (pos < len) {
ch = buf.charAt(pos++);
- if (ch == '"') {
+ if (ch == '"' && lastChar != '\\') {
hitQuote = !hitQuote;
}
- if (!hitQuote && ch == endChar && depth == 0) {
+ if (ch == '\'' && lastChar != '\\') {
+ hitTick = !hitTick;
+ }
+ if (!(hitQuote||hitTick) && ch == endChar && depth == 0) {
pos--;
break;
}
- if (!hitQuote && ch == ')') {
+ if (!(hitQuote||hitTick) && ch == ')') {
depth--;
if (depth == 0 && endChar == 0) {
break;
@@ -566,9 +536,10 @@ public class DefineTable {
break;
}
}
- if (!hitQuote && ch == '(') {
+ if (!(hitQuote||hitTick) && ch == '(') {
depth++;
}
+ lastChar = ch;
}
return buf.substring(start, pos);
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java b/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java
index f918feadc9..24392535e9 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java
@@ -316,6 +316,9 @@ public class VarnodeContext implements ProcessorContext {
private void setupValidSymbolicStackNames(Program program) {
// figure out what register is used for stack values
Register stackRegister = getStackRegister();
+ if (stackRegister == null) {
+ return;
+ }
validSymbolicStackNames.add(stackRegister.getName());
List childRegisters = stackRegister.getChildRegisters();
@@ -325,13 +328,27 @@ public class VarnodeContext implements ProcessorContext {
}
/**
- * Return true if this varnode is stored in the symbolic stack space
+ * Check if varnode is in the stack space
+ *
+ * @param varnode varnode to check
+ *
+ * @return true if this varnode is stored in the symbolic stack space
*/
public boolean isStackSymbolicSpace(Varnode varnode) {
// symbolic spaces are off of a register, find the space
AddressSpace regSpace = addrFactory.getAddressSpace(varnode.getSpace());
- return validSymbolicStackNames.contains(regSpace.getName());
+ return isStackSpaceName(regSpace.getName());
+ }
+
+ /**
+ * Check if spaceName is associated with the stack
+ *
+ * @param spaceName of address space to check
+ * @return true if spaceName is associated with the stack space
+ */
+ public boolean isStackSpaceName(String spaceName) {
+ return validSymbolicStackNames.contains(spaceName);
}
/**
diff --git a/Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/C/C.jj b/Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/C/C.jj
index 035c5c9665..d7de5bf506 100644
--- a/Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/C/C.jj
+++ b/Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/C/C.jj
@@ -52,8 +52,22 @@
*/
+
+
options {
+ // Methods and class variables should not be static to allow multiple parsers to be in use.
+ // This is at the expense of some speed.
STATIC= false;
+
+ // Don't interpret unicode escape sequences, they can appear in embedded text in macros and strings,
+ // which if interpreted can mess up parsing if they are pre-interpreted by the input stream.
+ JAVA_UNICODE_ESCAPE = false;
+
+ // However, if the file has real embedded unicode characters, such as some microsoft header files,
+ // they need to be read correctly by the parser. An example is the embedded code at the beginning
+ // of a file that states that it is in unicode. The characters might be all ascii, which for parsing
+ // purposes is most likely the case.
+ UNICODE_INPUT = true;
}
@@ -89,9 +103,12 @@ public class CParser {
private Map enums = new HashMap();
private Map declarations = new HashMap();
+
+ private Map internalTypes = new HashMap();
private DataType lastDataType = null;
private boolean storeNewDT = true;
+ private String possiblyUndefinedType = null;
DataTypeManager dtMgr = null;
private DataTypeManager[] subDTMgrs = new DataTypeManager[0];
@@ -181,7 +198,7 @@ public class CParser {
}
}
- dt = new TypedefDataType(type, dt);
+ dt = new TypedefDataType(CategoryPath.ROOT, type, dt, dtMgr);
dt = addDef(types, type, dt);
return dt;
}
@@ -223,6 +240,7 @@ public class CParser {
return dt;
}
+ possiblyUndefinedType = type;
return null;
}
@@ -320,6 +338,20 @@ public class CParser {
table.put(name, dt);
return dt;
}
+
+ // resolve data types using data type manager so that data organization is considered
+ //
+ private DataType resolveInternal(DataType datatype) {
+ DataType existingDT = internalTypes.get(datatype.getName());
+ if (existingDT != null) {
+ return existingDT;
+ }
+ existingDT = datatype.copy(dtMgr);
+
+ internalTypes.put(datatype.getName(), existingDT);
+
+ return existingDT;
+ }
// rename a data type in the given table
@@ -440,7 +472,7 @@ public class CParser {
if (currentFuncDT != null) {
return currentFuncDT;
}
- return new FunctionDefinitionDataType(ANONYMOUS_FUNC_PREFIX+func_cnt++);
+ return new FunctionDefinitionDataType(CategoryPath.ROOT, ANONYMOUS_FUNC_PREFIX+func_cnt++, dtMgr);
}
private void checkReturnDataType(DataType retDT) throws ParseException {
@@ -688,7 +720,9 @@ public class CParser {
if (headerFileName != null) {
parseMessage += " in " + headerFileName + " near line " + subLinenum + "\n";
}
+ parseMessage += "Error: " + e.getMessage() + "\n";
parseMessage += " near token: " + e.currentToken + "\n";
+ parseMessage += "Possibly Undefined : " + possiblyUndefinedType + "\n";
parseMessage += " Last Valid Datatype: "
+ (lastDataType == null ? "- none -" : lastDataType.getDisplayName()) + "\n";
parseMessage += " Check around CParserPlugin.out around line: "
@@ -800,7 +834,9 @@ TOKEN_MGR_DECLS :
SKIP :
{
- " "
+ "\ufeff" // BOM character at beginning of file
+ |
+ " "
|
"\f"
|
@@ -1262,7 +1298,7 @@ DataType ObjcDef() : {
{
( nameTok= ) ( | | )* ( | )
{
- return addTypedef(nameTok.image, VoidDataType.dataType);
+ return addTypedef(nameTok.image, resolveInternal(VoidDataType.dataType));
}
}
@@ -1381,33 +1417,33 @@ Declaration BuiltInTypeSpecifier(Declaration dec) : {
}
{
(
- { dec.setDataType(VoidDataType.dataType); }
+ { dec.setDataType(resolveInternal(VoidDataType.dataType)); }
|
{ dt = dec.getDataType();
if (dt != null) {
- if (dt == UnsignedIntegerDataType.dataType) {
- dt = UnsignedCharDataType.dataType;
- } else if (dt == IntegerDataType.dataType) {
- dt = CharDataType.dataType;
+ if (dt == resolveInternal(UnsignedIntegerDataType.dataType)) {
+ dt = resolveInternal(UnsignedCharDataType.dataType);
+ } else if (dt == resolveInternal(IntegerDataType.dataType)) {
+ dt = resolveInternal(CharDataType.dataType);
} else {
throw new ParseException("Bad datatype " + dt + " char");
}
}
else {
- dt = CharDataType.dataType;
+ dt = resolveInternal(CharDataType.dataType);
}
dec.setDataType(dt);
}
|
- { dec.setDataType(WideCharDataType.dataType); }
+ { dec.setDataType(resolveInternal(WideCharDataType.dataType)); }
|
{ dt = dec.getDataType();
if (dt == null) {
- dt = ShortDataType.dataType;
- } else if (dt == UnsignedIntegerDataType.dataType) {
- dt = UnsignedShortDataType.dataType;
- } else if (dt == IntegerDataType.dataType) {
- dt = ShortDataType.dataType;
+ dt = resolveInternal(ShortDataType.dataType);
+ } else if (dt == resolveInternal(UnsignedIntegerDataType.dataType)) {
+ dt = resolveInternal(UnsignedShortDataType.dataType);
+ } else if (dt == resolveInternal(IntegerDataType.dataType)) {
+ dt = resolveInternal(ShortDataType.dataType);
} else {
throw new ParseException("Bad datatype " + dt + " short");
}
@@ -1420,21 +1456,21 @@ Declaration BuiltInTypeSpecifier(Declaration dec) : {
|
{ dt = dec.getDataType();
if (dt == null ) {
- dec.setDataType(IntegerDataType.dataType);
+ dec.setDataType(resolveInternal(IntegerDataType.dataType));
}
}
|
{ dt = dec.getDataType();
if ( dt == null) {
- dt = LongDataType.dataType;
- } else if ( dt == UnsignedIntegerDataType.dataType) {
- dt = UnsignedLongDataType.dataType;
- } else if (dt == IntegerDataType.dataType) {
- dt = LongDataType.dataType;
- } else if (dt == LongDataType.dataType) {
- dt = LongLongDataType.dataType;
- } else if (dt == UnsignedLongDataType.dataType) {
- dt = UnsignedLongLongDataType.dataType;
+ dt = resolveInternal(LongDataType.dataType);
+ } else if ( dt == resolveInternal(UnsignedIntegerDataType.dataType)) {
+ dt = resolveInternal(UnsignedLongDataType.dataType);
+ } else if (dt == resolveInternal(IntegerDataType.dataType)) {
+ dt = resolveInternal(LongDataType.dataType);
+ } else if (dt == resolveInternal(LongDataType.dataType)) {
+ dt = resolveInternal(LongLongDataType.dataType);
+ } else if (dt == resolveInternal(UnsignedLongDataType.dataType)) {
+ dt = resolveInternal(UnsignedLongLongDataType.dataType);
} else {
throw new ParseException("Bad datatype " + dt + " long");
}
@@ -1447,20 +1483,20 @@ Declaration BuiltInTypeSpecifier(Declaration dec) : {
|
{ dt = dec.getDataType();
if ( dt == null) {
- dt = FloatDataType.dataType;
- } else if ( dt == LongDataType.dataType) {
- dt = DoubleDataType.dataType;
+ dt = resolveInternal(FloatDataType.dataType);
+ } else if ( dt == resolveInternal(LongDataType.dataType)) {
+ dt = resolveInternal(DoubleDataType.dataType);
} else {
throw new ParseException("Bad datatype " + dt + " long");
}
dec.setDataType(dt);
}
|
- { dec.setDataType(new DoubleDataType()); }
+ { dec.setDataType(resolveInternal(DoubleDataType.dataType)); }
|
{ dt = dec.getDataType();
if ( dt == null) {
- dt = IntegerDataType.dataType;
+ dt = resolveInternal(IntegerDataType.dataType);
} else {
// data type already set, don't do anything?
dt = dt;
@@ -1475,13 +1511,13 @@ Declaration BuiltInTypeSpecifier(Declaration dec) : {
|
{ dt = dec.getDataType();
if ( dt == null) {
- dt = UnsignedIntegerDataType.dataType;
- } else if (dt == ShortDataType.dataType) {
- dt = UnsignedShortDataType.dataType;
- } else if (dt == LongDataType.dataType) {
- dt = UnsignedLongDataType.dataType;
- } else if (dt == LongLongDataType.dataType) {
- dt = UnsignedLongLongDataType.dataType;
+ dt = resolveInternal(UnsignedIntegerDataType.dataType);
+ } else if (dt == resolveInternal(ShortDataType.dataType)) {
+ dt = resolveInternal(UnsignedShortDataType.dataType);
+ } else if (dt == resolveInternal(LongDataType.dataType)) {
+ dt = resolveInternal(UnsignedLongDataType.dataType);
+ } else if (dt == resolveInternal(LongLongDataType.dataType)) {
+ dt = resolveInternal(UnsignedLongLongDataType.dataType);
} else {
throw new ParseException("Bad datatype " + dt + " unsigned");
}
@@ -1492,13 +1528,13 @@ Declaration BuiltInTypeSpecifier(Declaration dec) : {
dec = BuiltInDeclarationSpecifier(dec)
]
|
- { dec.setDataType(SignedByteDataType.dataType); }
+ { dec.setDataType(resolveInternal(SignedByteDataType.dataType)); }
|
- { dec.setDataType(ShortDataType.dataType); }
+ { dec.setDataType(resolveInternal(ShortDataType.dataType)); }
|
- { dec.setDataType(IntegerDataType.dataType); }
+ { dec.setDataType(resolveInternal(IntegerDataType.dataType)); }
|
- { dec.setDataType(LongLongDataType.dataType); }
+ { dec.setDataType(resolveInternal(LongLongDataType.dataType)); }
)
{
return dec;
@@ -1631,8 +1667,7 @@ void PragmaSpecifier() : {
packSize = popPack(ID);
newPackVal = null;
}
- else if (ds1.image.equals("push")) {
- // push current and set value
+ else if (ds1.image.equals("push") && ds2 != null) {
try {
// check if second arg is an integer
int ival = Integer.parseInt(ds2.image);
@@ -1750,7 +1785,7 @@ DataType StructOrUnionSpecifier() : {
Composite StructOrUnion() : {Composite comp;}
{
(
- ( DeclSpec() )* { comp = new StructureDataType(ANONYMOUS_STRUCT_PREFIX + cnt++, 0);
+ ( DeclSpec() | PragmaSpec() )* { comp = new StructureDataType(CategoryPath.ROOT, ANONYMOUS_STRUCT_PREFIX + cnt++, 0, dtMgr);
// Always set the packing, because by default structures should be aligned
if (packSize > 0) {
@@ -1762,7 +1797,7 @@ Composite StructOrUnion() : {Composite comp;}
}
|
- ( DeclSpec() )* { comp = new UnionDataType(ANONYMOUS_UNION_PREFIX + cnt++);
+ ( DeclSpec() )* { comp = new UnionDataType(CategoryPath.ROOT, ANONYMOUS_UNION_PREFIX + cnt++, dtMgr);
// Always set the packing, because by default structures should be aligned
if (packSize > 0) {
@@ -1821,6 +1856,7 @@ void StructDeclaration(Composite comp, CompositeHandler compositeHandler) : {
}
{
LineDef() |
+ PragmaSpec() |
(
[ dt = SpecifierQualifierList() ]
[
@@ -1928,7 +1964,7 @@ DataType EnumSpecifier() : {
[ t= ] "{" list= EnumeratorList() "}"
{
String enumName= (t != null ? t.image : ("enum_" + cnt++));
- EnumDataType enuum= new EnumDataType(enumName, 4);
+ EnumDataType enuum= new EnumDataType(CategoryPath.ROOT, enumName, 4, dtMgr);
for (EnumMember member : list) {
try {
enuum.add(member.name, member.value);
@@ -2147,7 +2183,7 @@ Declaration ParameterTypeList(FunctionDefinitionDataType funcDT, DataType retDT)
{
checkReturnDataType(retDT);
if (funcDT == null) {
- funcDT= new FunctionDefinitionDataType(ANONYMOUS_FUNC_PREFIX);
+ funcDT= new FunctionDefinitionDataType(CategoryPath.ROOT, ANONYMOUS_FUNC_PREFIX, dtMgr);
}
funcDT.setVarArgs(varargs!=null);
ParameterDefinition[] variables= new ParameterDefinition[list.size()];
@@ -2260,13 +2296,13 @@ void Designator() : { }
"."
}
-DataType TypeName() : {
- Declaration dt = null;
+Declaration TypeName() : {
+ Declaration dec = null;
}
{
- dt = SpecifierQualifierList() [ AbstractDeclarator(new Declaration()) ]
+ dec = SpecifierQualifierList() [ dec = AbstractDeclarator(new Declaration(dec)) ]
{
- return dt.getDataType();
+ return dec;
}
}
@@ -2608,9 +2644,10 @@ Object CastExpression() : {
}
Object UnaryExpression() : {
- DataType dt = null;
Object obj = null;
Token op = null;
+ Token id = null;
+ Declaration dec = null;
}
{
(
@@ -2633,13 +2670,19 @@ Object UnaryExpression() : {
|
(
- "(" (dt = TypeName() | | obj = ConstantExpression() ) ")"
+ "(" ( dec = TypeName() | id = | obj = ConstantExpression() ) ")"
{
- if (dt != null) {
- obj = Long.valueOf(dt.getLength());
- } else if (obj != null && obj instanceof String) {
+ if (obj != null && obj instanceof String) {
obj = Long.valueOf(((String) obj).length() - 1); // will include "" plus \0
}
+ else if (dec != null) {
+ obj = Long.valueOf(dec.getDataType().getLength());
+ }
+ else if (id != null) {
+ // TODO: try to look up the type of the identifier
+ // TODO: Throw error if identifier is not defined
+ // may need to actually track declarations!
+ }
}
)
)
diff --git a/Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/CPP/CPP.jj b/Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/CPP/CPP.jj
index 329e74345c..3b895cb664 100644
--- a/Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/CPP/CPP.jj
+++ b/Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/CPP/CPP.jj
@@ -99,9 +99,10 @@
The NoMas() non-terminal unwinds the rather deep match.
*/
-options{
+options {
STATIC = false;
- JAVA_UNICODE_ESCAPE=true;
+ JAVA_UNICODE_ESCAPE = false;
+ UNICODE_INPUT = true;
}
PARSER_BEGIN(PreProcessor)
@@ -165,6 +166,38 @@ public class PreProcessor {
boolean contradict;
boolean emitExecSave;
int comparison;
+
+ ArrayList appendList = new ArrayList();
+ ArrayList expandList = new ArrayList();
+
+ void append(String str, boolean expand) {
+ if (image != null & image.length()>0) {
+ appendList.add(image);
+ expandList.add(true);
+ image = null;
+ }
+ int endIndex = appendList.size() - 1;
+ if (endIndex >= 0 && (str.strip().length()==0 || expand == expandList.get(endIndex)) ) {
+ // just add to the last image so it can expand properly
+ String lastStr = appendList.remove(endIndex);
+ expand = expandList.remove(endIndex);
+ str = lastStr + str;
+ }
+
+ appendList.add(str);
+ expandList.add(expand);
+ }
+
+ void append(PPToken tok, boolean expand) {
+ if (tok.image != null && tok.image.length() > 0) {
+ append(tok.image, expand);
+ return;
+ }
+ int cnt = 0;
+ for (String string : appendList) {
+ append(string, expandList.get(cnt));
+ }
+ }
void setTruth(boolean truth) {
this.truth = truth;
@@ -363,6 +396,67 @@ public class PreProcessor {
return comparison;
}
+ PPToken computeBinary(Token op, PPToken val2) {
+ BigInteger tvalue = BigInteger.ZERO;
+ BigInteger result = BigInteger.ZERO;
+ BigInteger vvalue = BigInteger.ZERO;
+ try {
+ tvalue = getLongValue(getDef(this).image);
+ vvalue = getLongValue(getDef(val2).image);
+ }
+ catch (Exception e) {
+ }
+ switch (op.kind) {
+ case MINUS:
+ result = tvalue.subtract(vvalue);
+ break;
+ case PLUS:
+ result = tvalue.add(vvalue);
+ break;
+ case TIMES:
+ result = tvalue.multiply(vvalue);
+ break;
+ case AND:
+ result = tvalue.and(vvalue);
+ break;
+ case OR:
+ result = tvalue.or(vvalue);
+ break;
+ case RSH:
+ result = tvalue.shiftRight(vvalue.intValue());
+ break;
+ case LSH:
+ result = tvalue.shiftLeft(vvalue.intValue());
+ break;
+ }
+ PPToken t = new PPToken(result.toString());
+ t.kind = NUMERIC;
+ t.setTruth(result != BigInteger.ZERO);
+ return t;
+ }
+
+ PPToken computeUnary(Token op) {
+ BigInteger tvalue = BigInteger.ZERO;
+ BigInteger result = BigInteger.ZERO;
+ try {
+ tvalue = getLongValue(getDef(this).image);
+ }
+ catch (Exception e) {
+ }
+ switch (op.kind) {
+ case MINUS:
+ result = tvalue.negate();
+ break;
+ case NOT:
+ result = (BigInteger.ZERO.equals(tvalue) ? BigInteger.ZERO : BigInteger.ONE);
+ break;
+ }
+ PPToken t = new PPToken(result.toString());
+ t.kind = NUMERIC;
+ t.setTruth(!BigInteger.ZERO.equals(result));
+ return t;
+ }
+
boolean getEmitSave() {
return emitExecSave;
}
@@ -400,10 +494,24 @@ public class PreProcessor {
image = buf.toString();
}
- void emit() {
- image = defs.expand(image, true);
- print(image);
- }
+ void emit(boolean expand) {
+ if (expand && appendList.isEmpty()) {
+ image = defs.expand(image, true);
+ } else {
+ int cnt = 0;
+ for (String string : appendList) {
+ if (expand && expandList.get(cnt++)) {
+ image += defs.expand(string, true);
+ } else {
+ image += string;
+ }
+ }
+ }
+ if (image.length() == 1 && image.startsWith("\n")) {
+ image = (!emitExecSwitch ? "////\n" : "\n");
+ }
+ print(image);
+ }
}
@@ -453,22 +561,36 @@ public class PreProcessor {
public DefineTable getDefinitions() {
return defs;
}
-
- // Get a def from the manifest constant list, from a defined string
+
+ // Get a def from the manifest constant list, from a defined string
public PPToken getDef(PPToken def) {
- if (verboseLevel == 6 || verboseLevel == 5 || verboseLevel == 4
- || verboseLevel == 3)
- println("Defs: containsKey: " + def.image + " = "
- + defs.containsKey(def.image));
+ if (verboseLevel == 6 || verboseLevel == 5 || verboseLevel == 4 || verboseLevel == 3)
+ println("Defs: containsKey: " + def.image + " = " + defs.containsKey(def.image));
PPToken pt = defs.get(def.image);
if (pt != null && pt.image.length() > 0) {
- pt.image = defs.expand(pt.image, false);
- } else {
- // no Def, it is what it is!
- pt = def;
- }
+ String expanded = defs.expand(pt.image, false);
+ pt = new PPToken(pt);
+ pt.image = expanded;
+ }
+ else {
+ // no Def, it is what it is!
+ pt = def;
+ }
return pt;
}
+
+ // Get a define definition by name from the list
+ public String getDef(String name) {
+ PPToken pt = defs.get(name);
+ String val = name;
+ if (pt != null && pt.image.length() > 0) {
+ val = defs.expand(pt.image, false);
+ }
+ else {
+ // no Def, it is what it is!
+ }
+ return val;
+ }
// Add a def to the manifest constant list
private void setDef(PPToken def) {
@@ -621,16 +743,14 @@ public class PreProcessor {
// check if this has already been done
Integer val = alreadyDone.get(incFile.getAbsolutePath());
- if (val != null) {
- if (val.intValue() > 2) {
- // silently don't parse this file, should already be done.
- return;
- }
- } else {
- val = new Integer(0);
+ if (val == null) {
+ val = Integer.valueOf(0);
}
- alreadyDone.put(incFile.getAbsolutePath(),
- Integer.valueOf(val.intValue() + 1));
+ // Must parse headers multiple times, MS uses headers to set pack()
+ // still useful for debugging
+
+ val = val + 1;
+ alreadyDone.put(incFile.getAbsolutePath(), val);
fileStack.push(incFile.getAbsolutePath());
parser = new PreProcessor(this);
@@ -907,6 +1027,18 @@ public class PreProcessor {
private void addFile(String file) {
files.put(file, Boolean.TRUE);
}
+
+ private void printCommentedLines(boolean emitSwitch, String line, String state) {
+ StringBuffer buf = new StringBuffer("///");
+ buf.append(emitSwitch ? " " : "/" );
+ buf.append(line);
+ if (emitSwitch) {
+ buf.append(" ===" + state);
+ }
+ buf.append("\n");
+ print(buf.toString());
+ // "#else if " + t.image + (emitExecSwitch == false ? "" : " ===" + t.getTruth()) + "\n"
+ }
// Print String
private void print(String text) {
@@ -1203,13 +1335,13 @@ PARSER_END(PreProcessor)
void Input() :
{
- boolean b = true;
+ PPToken b;
int conditionDepth=execStack.size();
PPToken ppt = new PPToken("\n#line 1: \""+curFileStackTop()+"\"\n");
- ppt.emit();
+ ppt.emit(false);
}
{
- ( b=TranslationUnit(){if (b==false) break;})*
+ ( b=TranslationUnit(){if (b.getTruth()==false) break;})*
{
if (conditionDepth!=execStack.size()) {
Msg.error(this, "Imbalance in sequence/nesting of compile-time conditions/logic in input file "+curFileStackTop());
@@ -1220,16 +1352,16 @@ void Input() :
emitExecSwitch = olde.getEmitSave();
}
}
- //We're out of translation units
+ // Out of translation units
return;
}
}
-boolean TranslationUnit() : {boolean b = true;}
+PPToken TranslationUnit() : {PPToken b;}
{
- (LOOKAHEAD(2)b=Group(){if (b==false) break;})+{return b;}
+ (LOOKAHEAD(2) b=Group() {if (b.getTruth()==false) break;})+{return b;}
}
void NoMas() : {}
@@ -1237,35 +1369,35 @@ void NoMas() : {}
}
-boolean Group() : {boolean b = true;}
+PPToken Group() : {PPToken b;}
{
LOOKAHEAD(2) b=GroupPart(){ return b;} |
- (LOOKAHEAD(2) b=IFSection(){if (b==false) return b;})+{return b;}
+ (LOOKAHEAD(2) b=IFSection(){if (b.getTruth()==false) return b;})+{return b;}
}
-boolean GroupPart() : {boolean b = true;PPToken t,u=new PPToken("");Token v=new Token();v.image="";}
+PPToken GroupPart() : { PPToken t,u=new PPToken("");Token v=new Token();v.image="";}
{
(LOOKAHEAD(2)
(t=Text()
- (v={u.image+=v.image;})*
+ // (v={u.image+=v.image;})*
){
/* ==>> HERE IS WHERE WE EMIT <<=== */
- t.image+=u.image;
- if (emitExecSwitch==true) t.emit();
+ // t.append(u.image, true);
+ if (emitExecSwitch==true) { t.emit(true); } else t.emit(false);
t.image="";
u.image="";
}
)+
- {return b;}
- // MJT {return Group();}
- | LOOKAHEAD(3)(LOOKAHEAD(2)b=IFSection() {return b;})+
- | b=ControlLine(){return b;}
+ { t.setTruth(true); return t;}
+ | LOOKAHEAD(3)(LOOKAHEAD(2)t=IFSection() {return t;})+
+ | t=ControlLine(){return t;}
}
-boolean ControlLine() : {PPToken t = null, u = null; boolean b = true;Vector vals = new Vector();}
+PPToken ControlLine() : {PPToken t = new PPToken(""), u = null; Vector vals = new Vector();}
{
- (LOOKAHEAD(2)t=Define() |
+ (LOOKAHEAD(2)
+ Define() |
Include() |
UnDef() |
Pragma() |
@@ -1274,27 +1406,31 @@ boolean ControlLine() : {PPToken t = null, u = null; boolean b = true;Vector val
Info() |
LineInfo() ){
if (vals!=null&&vals.size()==0) vals = null;
- return true;
+ t.setTruth(true);
+ return t;
} |
NoMas(){
- return false;
+ t.setTruth(false);
+ return t;
}
}
-boolean IFSection() : {boolean b;}
+PPToken IFSection() : {PPToken ifg, group;}
{
- b=IFGroup(){
- //emitExecSwitch = b;
- return GroupPart();
+ ifg = IFGroup()
+ {
+ group = GroupPart();
+ return group;
}
}
-boolean IFGroup() : {PPToken t, e, olde;boolean b, c;}
+PPToken IFGroup() : { PPToken t, e, olde; }
{
(e=If() t=IfCondition(){
e.setEmitSave(emitExecSwitch);
e.setTruth(t.getTruth());
execStack.push(e);
+ printCommentedLines(emitExecSwitch, "#if " + t.image, "" + t.getTruth());
if (emitExecSwitch==true) emitExecSwitch = e.getTruth();
if (verboseLevel==6||verboseLevel==7) {
println("["+execStack.size()+"]"+"If "+t.getTruth()+" : "+emitExecSwitch);
@@ -1308,6 +1444,7 @@ boolean IFGroup() : {PPToken t, e, olde;boolean b, c;}
}
olde = (PPToken) execStack.pop();
emitExecSwitch = olde.getEmitSave();
+ printCommentedLines(emitExecSwitch, "#else if " + t.image, "" + t.getTruth());
e.setEmitSave(emitExecSwitch);
if (!olde.getTruth() && emitExecSwitch==true)
emitExecSwitch = e.getTruth();
@@ -1322,6 +1459,7 @@ boolean IFGroup() : {PPToken t, e, olde;boolean b, c;}
e=IfDef() t=IfDefExpr() {
t.setEmitSave(emitExecSwitch);
execStack.push(t);
+ printCommentedLines(emitExecSwitch, "#ifdef " + t.image, "" + t.getTruth());
if (emitExecSwitch==true) emitExecSwitch = t.getTruth();
if (verboseLevel==6||verboseLevel==7) {
println("["+execStack.size()+"]"+"IfDef "+t.getTruth()+" : "+emitExecSwitch);
@@ -1330,6 +1468,7 @@ boolean IFGroup() : {PPToken t, e, olde;boolean b, c;}
e=IfNDef() t=IfNDefExpr() {
t.setEmitSave(emitExecSwitch);
execStack.push(t);
+ printCommentedLines(emitExecSwitch, "#ifndef " + t.image, "" + t.getTruth());
if (emitExecSwitch==true) emitExecSwitch = t.getTruth();
if (verboseLevel==6||verboseLevel==7) {
println("["+execStack.size()+"]"+"IfNDef "+t.getTruth()+" : "+emitExecSwitch);
@@ -1342,6 +1481,7 @@ boolean IFGroup() : {PPToken t, e, olde;boolean b, c;}
}
olde = (PPToken) execStack.pop();
emitExecSwitch = olde.getEmitSave();
+ printCommentedLines(emitExecSwitch, "#else", "" + t.getTruth());
t.setEmitSave(emitExecSwitch);
if (emitExecSwitch && olde.getTruth()) emitExecSwitch = false;
execStack.push(t);
@@ -1355,16 +1495,15 @@ boolean IFGroup() : {PPToken t, e, olde;boolean b, c;}
throw new ParseException(curFileStackTop()+"'"+t.beginLine+"Unbalanced IF directive detected");
}
olde = (PPToken) execStack.pop();
- emitExecSwitch = olde.getEmitSave();
+ boolean newExecSwitch = olde.getEmitSave();
+ printCommentedLines(newExecSwitch, "#endif", "" + emitExecSwitch);
+ emitExecSwitch = newExecSwitch;
if (verboseLevel==6||verboseLevel==7) {
println("["+execStack.size()+"]"+curFileStackTop()+"'"+t.beginLine+": Endif "+" : "+emitExecSwitch);
}
- //if (execStack.size()>0) t.setTruth(((PPToken)execStack.peek()).getTruth());
- //else t.setTruth(true);
- //emitExecSwitch = t.getEmitSave();
}
- ){return t.getTruth();}
+ ) { return t; }
}
@@ -1471,18 +1610,23 @@ PPToken Define() : {Token t,u=null,v=null,w=null,x=null;Vector dargs = new Vecto
if (u!=null&&v!=null) {
PPToken pv=new PPToken(v);
setMacro(pt,dargs,pv);
+ printCommentedLines(emitExecSwitch, "#define " + pt.image + "("+dargs+") " + pv.image, "" + "DEFINED");
} else if (u==null&&v==null) {
setDef(pt);
+ printCommentedLines(emitExecSwitch, "#define " + pt.image, "" + "DEFINED");
} else if (v!=null) {
PPToken pv=new PPToken(v);
setDef(pt,pv);
+ printCommentedLines(emitExecSwitch, "#define " + pt.image + " " + pv.image, "" + "DEFINED");
} else if (u!=null) {
if (dargs.size()>0) {
PPToken pv=new PPToken("");
setMacro(pt,dargs,pv);
+ printCommentedLines(emitExecSwitch, "#define " + pt.image + "("+dargs+") " + pv.image, "" + "DEFINED");
} else {
PPToken pu=new PPToken(u);
setDef(pt,pu);
+ printCommentedLines(emitExecSwitch, "#define " + pt.image + " " + pu.image, "" + "DEFINED");
}
}
} else {
@@ -1660,29 +1804,27 @@ PPToken QuotedValue() :
}
PPToken Text() :
-{Token u, t = new Token(); StringBuffer buf = new StringBuffer(); t.image="";}
+{Token u, nl, t = new Token(); PPToken buf = new PPToken(""); t.image="";}
{
( LOOKAHEAD(3)
- (LOOKAHEAD(2)(u={if (emitExecSwitch==true) buf.append(u.image);}
-// [LOOKAHEAD(2)u=NewLines(){if (emitExecSwitch==true) buf.append(u.image);}]|
- (LOOKAHEAD(2)u=NewLines(){if (emitExecSwitch==true) buf.append(u.image);})*|
+ (LOOKAHEAD(2)(u={ if (emitExecSwitch==true) buf.append(u.image,true); else buf.append("//// " + u.image, false); }
+ (LOOKAHEAD(2)nl=NewLines(){if (emitExecSwitch==true) buf.append(nl.image,false); else buf.append((u.image.length() == 0 ? "//// " : "") + nl.image, false); } )*|
- u={if (emitExecSwitch==true) buf.append(u.image);})
- [LOOKAHEAD(2)u=NewLines(){if (emitExecSwitch==true) buf.append(u.image);}]
- [LOOKAHEAD(2)u=QuotedText(){if (emitExecSwitch==true) buf.append(u.image);}]
- [LOOKAHEAD(2)u={if (emitExecSwitch==true) buf.append(u.image);}
-// [LOOKAHEAD(2)u=NewLines(){if (emitExecSwitch==true) buf.append(u.image);}]])+|
- (LOOKAHEAD(2)u=NewLines(){if (emitExecSwitch==true) buf.append(u.image);})*])+|
+ u={if (emitExecSwitch==true) buf.append(u.image,true);} )
+ [LOOKAHEAD(2)u=NewLines(){ if (emitExecSwitch==true) buf.append(u.image,false); }]
+ [LOOKAHEAD(2)u=QuotedText(){if (emitExecSwitch==true) buf.append(u.image,true);}]
+ [LOOKAHEAD(2)u={if (emitExecSwitch==true) buf.append(u.image, true); }
+ (LOOKAHEAD(2)u=NewLines(){ if (emitExecSwitch==true) buf.append(u.image, false);})*])+|
- (LOOKAHEAD(2)(u=QuotedText(){if (emitExecSwitch==true) buf.append(u.image);}
- [LOOKAHEAD(2)u=NewLines(){if (emitExecSwitch==true) buf.append(u.image);}]|
- u={if (emitExecSwitch==true) buf.append(u.image);})
- [LOOKAHEAD(2)t=NewLines(){if (emitExecSwitch==true) buf.append(u.image);}]
- [LOOKAHEAD(2)u={if (emitExecSwitch==true) buf.append(u.image);}]
- [LOOKAHEAD(2)u=NewLines(){if (emitExecSwitch==true) buf.append(u.image);}])+ |
+ (LOOKAHEAD(2)(u=QuotedText(){if (emitExecSwitch==true) buf.append(u.image,true);}
+ [LOOKAHEAD(2)u=NewLines(){ if (emitExecSwitch==true) buf.append(u.image,false); }]|
+ u={if (emitExecSwitch==true) buf.append(u.image,true);})
+ [LOOKAHEAD(2)t=NewLines(){ if (emitExecSwitch==true) buf.append(t.image,false); }]
+ [LOOKAHEAD(2)u={if (emitExecSwitch==true) buf.append(u.image,true);}]
+ [LOOKAHEAD(2)u=NewLines(){ if (emitExecSwitch==true) buf.append(u.image,false); }])+ |
- u=NewLines(){if (emitExecSwitch==true) buf.append(u.image);}
- ){return new PPToken(buf.toString());}
+ u=NewLines(){ if (emitExecSwitch==true) buf.append(u.image,false); }
+ ) { return buf;}
}
@@ -1693,12 +1835,19 @@ PPToken NewLines() :
// the rest are fluff to emulate real preprocessor output
// #if and #def newlines have been returned to their skip sections
(
- t= |
- t= |
- t= |
- t= |
+ t= | // general newline
+// t= | // newline coming from /* */ // stripped for now
+ t= | // newline coming from //
+ t= |
+ t= |
+ t= |
+ t= |
+ t= |
+ t= |
+ t= |
+ t= |
t=
- ){return new PPToken(t);}
+ ) {return new PPToken(t);}
}
PPToken QuotedText() :
@@ -1724,7 +1873,7 @@ PPToken CompoundAndExpression() :
{
t=ConditionalExpression()
( LOOKAHEAD(2)
- u=And(){
+ u=LogAnd(){
if (verboseLevel()==7) print(u.image);
}
v=ConditionalExpression(){
@@ -1738,7 +1887,7 @@ PPToken CompoundOrExpression() :
{
t=ConditionalExpression()
( LOOKAHEAD(2)
- u=Or(){
+ u=LogOr(){
if (verboseLevel()==7) print(u.image);
}
v=ConditionalExpression(){
@@ -1764,7 +1913,7 @@ PPToken LogicalOrExpression() :
{
(t=LogicalAndExpression()
(LOOKAHEAD(2)
- u=Or(){
+ u=LogOr(){
if (verboseLevel()==7) print(u.image);
}
v=LogicalAndExpression(){
@@ -1779,7 +1928,7 @@ PPToken LogicalAndExpression() :
{
(t=EqualityExpression()
( LOOKAHEAD(2)
- u=And(){
+ u=LogAnd(){
if (verboseLevel()==7) print(u.image);
}
v=EqualityExpression(){
@@ -1863,63 +2012,6 @@ PPToken RelationalExpression() :
){return t;}
}
-
-PPToken GreaterThanExpression() :
-{PPToken t,u,v;}
-{ (
- t=LogNegation()
- (u=GreaterThan(){
- if (verboseLevel()==7) print(u.image);
- }
- v=LogNegation(){
- try {
- t.setTruth(t.compareTo(v)>0);
- } catch (NumberFormatException exc) {
- t.setTruth(false);
- }
- if (verboseLevel()==7) print(": ");
- }
- )*
- ){return t;}
-}
-
-
-PPToken GreaterThanOrEqualExpression() :
-{PPToken t,u,v;}
-{ t=GreaterThanExpression()
- ( u=GreaterThanOrEqual(){
- if (verboseLevel()==7) print(u.image);
- }
- v=GreaterThanExpression(){
- try {
- t.setTruth(t.compareTo(v)>=0);
- } catch (NumberFormatException exc) {
- t.setTruth(false);
- }
- if (verboseLevel()==7) print(": ");
- }
- )*{return t;}
-}
-
-
-
-PPToken LessThanOrEqualExpression() :
-{PPToken t,u,v;}
-{ t=GreaterThanOrEqualExpression()
- ( u=LessThanOrEqual(){
- if (verboseLevel()==7) print(u.image);
- }
- v=GreaterThanOrEqualExpression(){
- try {
- t.setTruth(t.compareTo(v)<=0);
- } catch (NumberFormatException exc) {
- t.setTruth(false);
- }
- if (verboseLevel()==7) print(": ");
- }
- )*{return t;}
-}
-
PPToken LessExpression() :
{PPToken t,u,v;}
{ t=LessThanOrEqualExpression()
@@ -1938,16 +2030,70 @@ PPToken LessExpression() :
)*{return t;}
}
-PPToken Or() :
-{Token t;PPToken pt;}
-{
- t= {return new PPToken(t);}
+PPToken LessThanOrEqualExpression() :
+{PPToken t,u,v;}
+{ t=GreaterThanOrEqualExpression()
+ ( u=LessThanOrEqual(){
+ if (verboseLevel()==7) print(u.image);
+ }
+ v=GreaterThanOrEqualExpression(){
+ try {
+ t.setTruth(t.compareTo(v)<=0);
+ } catch (NumberFormatException exc) {
+ t.setTruth(false);
+ }
+ if (verboseLevel()==7) print(": ");
+ }
+ )*{return t;}
}
-PPToken And() :
+PPToken GreaterThanOrEqualExpression() :
+{PPToken t,u,v;}
+{ t=GreaterThanExpression()
+ ( u=GreaterThanOrEqual(){
+ if (verboseLevel()==7) print(u.image);
+ }
+ v=GreaterThanExpression(){
+ try {
+ t.setTruth(t.compareTo(v)>=0);
+ } catch (NumberFormatException exc) {
+ t.setTruth(false);
+ }
+ if (verboseLevel()==7) print(": ");
+ }
+ )*{return t;}
+}
+
+PPToken GreaterThanExpression() :
+{PPToken t,u,v;}
+{ (
+ t=Expression()
+ (u=GreaterThan(){
+ if (verboseLevel()==7) print(u.image);
+ }
+ v=Expression(){
+ try {
+ t.setTruth(t.compareTo(v)>0);
+ } catch (NumberFormatException exc) {
+ t.setTruth(false);
+ }
+ if (verboseLevel()==7) print(": ");
+ }
+ )*
+ ){return t;}
+}
+
+
+PPToken LogOr() :
{Token t;PPToken pt;}
{
- t= {return new PPToken(t);}
+ t= {return new PPToken(t);}
+}
+
+PPToken LogAnd() :
+{Token t;PPToken pt;}
+{
+ t= {return new PPToken(t);}
}
PPToken EqualTo() :
@@ -1998,44 +2144,6 @@ PPToken ElseMark() :
t= {return new PPToken(t);}
}
-PPToken LogNegation() :
-{Token t; PPToken pt=null; boolean negate=false;}
-{
- (t={
- negate = true;
- if (verboseLevel()==7) print(t.image);
- })*
- pt=Expression(){
- if (negate==true) pt.setContra(true);
- }
- {return pt;}
-}
-
-PPToken Negation() :
-{Token t; PPToken pt=null; boolean negate=false;}
-{
- (t={
- negate = true;
- if (verboseLevel()==7) print(t.image);
- })*
- pt=Expression(){
- if (negate==true) {
- BigInteger tvalue = BigInteger.ZERO;
- BigInteger result = BigInteger.ZERO;
- try {
- tvalue = getLongValue(this.getDef(pt).image);
- }
- catch (Exception e) {
- }
- result = tvalue.negate();
- pt = new PPToken(pt);
- pt.image = result.toString();
- pt.kind = NUMERIC;
- pt.setTruth(!result.equals(BigInteger.ZERO));
- }
- }
- {return pt;}
-}
PPToken Assertion() :
{Token t; PPToken pt=null; boolean checkDefined = false; }
@@ -2044,7 +2152,7 @@ PPToken Assertion() :
pt=Expression()
{
pt = new PPToken(pt);
- pt.setTruth(isDef(pt));
+ pt.setTruth(isDef(pt) || (pt.kind == FP_NUMERIC || pt.kind == NUMERIC)); // numbers are always defined
return pt;
})
|
@@ -2057,72 +2165,126 @@ PPToken Assertion() :
}
PPToken Expression() :
-{Token op; PPToken t,v,pt;}
+{ PPToken obj = null; }
{
- t=ValueExpression()
- (LOOKAHEAD(3)
- op=SubtractFrom()
- v=ValueExpression()
- {
- BigInteger tvalue = BigInteger.ZERO;
- BigInteger result = BigInteger.ZERO;
- BigInteger vvalue = BigInteger.ZERO;
- try {
- tvalue = getLongValue(this.getDef(t).image);
- vvalue = getLongValue(this.getDef(v).image);
- }
- catch (Exception e) {
- }
- switch (op.kind) {
- case MINUS:
- result = tvalue.subtract(vvalue);
- break;
- case PLUS:
- result = tvalue.add(vvalue);
- break;
- case TIMES:
- result = tvalue.multiply(vvalue);
- break;
- case LOG_AND:
- result = tvalue.and(vvalue);
- break;
- case LOG_OR:
- result = tvalue.or(vvalue);
- break;
- case RSH:
- result = tvalue.shiftRight(vvalue.intValue());
- break;
- case LSH:
- result = tvalue.shiftLeft(vvalue.intValue());
- break;
- }
- t.image = result.toString();
- t.kind = NUMERIC;
- t.setTruth(result != BigInteger.ZERO);
- }
- )* {return new PPToken(t);}
+ obj = InclusiveORExpression()
+ {
+ return obj;
+ }
+}
+
+
+PPToken InclusiveORExpression() : {
+ PPToken obj = null, obj2 = null; Token op=null;
+}
+{
+ obj = ExclusiveORExpression() ( LOOKAHEAD(2) op=< OR > obj2=ExclusiveORExpression() { obj = obj.computeBinary(op, obj2); } ) *
+ {
+ return obj;
+ }
+}
+
+PPToken ExclusiveORExpression() : {
+ PPToken obj = null, obj2 = null; Token op=null;
+}
+{
+ obj = ANDExpression() ( LOOKAHEAD(2) op=< XOR > obj2=ANDExpression() { obj = obj.computeBinary(op, obj2); } ) *
+ {
+ return obj;
+ }
+}
+
+PPToken ANDExpression() : {
+ PPToken obj = null, obj2 = null; Token op=null;
+}
+{
+ obj = ShiftExpression() ( LOOKAHEAD(2) op=< AND > obj2=ShiftExpression() { obj = obj.computeBinary(op, obj2); } ) *
+ {
+ return obj;
+ }
+}
+
+PPToken ShiftExpression() : {
+ PPToken obj = null, obj2 = null; Token op=null;
+}
+{
+ obj = AdditiveExpression()
+ ( LOOKAHEAD(2) (op=< LSH > | op=< RSH > ) obj2 = AdditiveExpression()
+ { obj = obj.computeBinary(op, obj2); }
+ ) *
+ {
+ return obj;
+ }
+}
+
+PPToken AdditiveExpression() : {
+ PPToken obj = null, obj2 = null; Token op=null;
+}
+{
+ obj = MultiplicativeExpression()
+ ( LOOKAHEAD(2) ( op=< PLUS > | op=< MINUS >) obj2 = MultiplicativeExpression()
+ { obj = obj.computeBinary(op, obj2); }
+ ) *
+ {
+ return obj;
+ }
+}
+
+PPToken MultiplicativeExpression() : {
+ PPToken obj = null, obj2 = null; Token op=null;
+}
+{
+ obj = UnaryExpression()
+ ( LOOKAHEAD(2) ( op=< TIMES > | op=< DIVIDE > | op= < MOD > ) obj2 = UnaryExpression()
+ { obj = obj.computeBinary(op, obj2); }
+ ) *
+ {
+ return obj;
+ }
}
-PPToken SubtractFrom() :
-{Token t;PPToken pt;}
+PPToken UnaryExpression() : {
+ PPToken obj = null;
+ Token op = null;
+}
{
- (t= | t= | t= | t= | t= | t= | t= )
- {return new PPToken(t);}
+ (
+ LOOKAHEAD(3)
+ obj = LogNegation()
+ |
+ < PLUS > obj=LogNegation()
+ |
+ op=< MINUS > obj=LogNegation() { obj = obj.computeUnary(op); }
+ )
+ {
+ return obj;
+ }
+}
+
+PPToken LogNegation() :
+{Token t; PPToken pt=null; boolean negate=false;}
+{
+ (t={
+ negate = true;
+ if (verboseLevel()==7) print(t.image);
+ })*
+ pt=ValueExpression(){
+ if (negate==true) pt.setContra(true);
+ }
+ {return pt;}
}
PPToken ValueExpression() :
{Token t;Token v;PPToken pt;PPToken tv=null;
- Token u=null;Vector dargs = new Vector(); boolean negation=false; boolean positive=false; }
+ Token u=null;Vector dargs = new Vector(); }
{
(
LOOKAHEAD(2)
- (( {negation=true;} | { positive=true;} )? t= | t= | t= | t= ) {
+ (t= | t= | t= | t= ) {
if (verboseLevel()==7) print(t.image);
pt=new PPToken(t);
- if (negation) { pt.image = "-" + pt.image; }
- if (positive) { pt.image = "+" + pt.image; }
if (pt.compareToZero()==0) pt.setTruth(false);
else pt.setTruth(true);
return pt;
@@ -2136,15 +2298,15 @@ PPToken ValueExpression() :
return pt;
}
|
- ( {negation=true;} | { positive=true;} )? (t=- ) [LOOKAHEAD(4)
((u=- | u=
) {dargs.add(u);})+ ] {
+ (t=- ) [ LOOKAHEAD(4)
((tv=Expression()) {dargs.add(tv);})+ ] {
if (verboseLevel()==7) print(t.image);
pt=new PPToken(t);
if (dargs.size() > 0) {
pt.image += "(";
- Enumeration denum = dargs.elements();
+ Enumeration denum = dargs.elements();
int index = 0;
while (denum.hasMoreElements()) {
- Token atok = (Token) denum.nextElement();
+ PPToken atok = (PPToken) denum.nextElement();
if (index++ != 0) {
pt.image += ",";
}
@@ -2157,8 +2319,6 @@ PPToken ValueExpression() :
// The expanded macro text can't be injected into the parse stream
// try parsing the expression with an internal simple expression
// parser that can handle equality expressions
- if (negation) { pt.image = "-" + pt.image; }
- if (positive) { pt.image = "+" + pt.image; }
Long val = AddressEvaluator.evaluateToLong(pt.image);
if (val != null) {
pt.image = val.toString();
@@ -2176,13 +2336,13 @@ PPToken ValueExpression() :
if (!pt.image.equals(tv.image)) {
tv.image = defs.expand(tv.image, true);
tv.kind = getNumericType(tv.image);
-
}
- if (negation) { tv.image = "-" + tv.image; }
- if (positive) { tv.image = "+" + tv.image; }
+
Long val = AddressEvaluator.evaluateToLong(tv.image);
pt.setTruth(true);
if (val != null) {
+ pt.image = val.toString();
+ pt.kind = NUMERIC;
if (val == 0) {
pt.setTruth(false);
}
@@ -2195,6 +2355,7 @@ PPToken ValueExpression() :
return pt;
}
)
+
}
// LEXICAL SCANNER SECTION
@@ -2206,20 +2367,43 @@ TOKEN_MGR_DECLS :
SKIP:
{
+ <_BOM: "\ufeff" > | // beginning of file BOM for UTF8
<_CTRL: ()* ()* > : DIRECTIVE |
<_XSYM: > : XSYMLINK |
-// <_LCMT: ()* () > : LINECOMMENT |
-// <_CMT: ()* () > : COMMENT |
- <_LCMT: "//" (~["\n","\r"])* ("\n"|"\r"|"\r\n")> |
- <_CMT: () (~["*"])* "*" ("*" | ~["*","/"] (~["*"])* "*")* "/" > |
- <_BLANKLINE: ()+ > : DEFAULT
-
+ <_BLANKLINE: ()+ >
}
-SPECIAL_TOKEN :
+
+//MORE:
+SKIP:
{
- <_LINECOMMENT: "//" (~["\n","\r"])* ("\n"|"\r"|"\r\n")> |
- <_COMMENT: () (~["*"])* "*" ("*" | ~["*","/"] (~["*"])* "*")* "/" >
+ <_LCMT: "//" > : SpecialEOLComment |
+ <_CMT: () > : SpecialBlockComment
+}
+
+
+TOKEN :
+{
+ > : DEFAULT
+}
+
+//MORE:
+SKIP :
+{
+ <(~[])>
+}
+
+
+SKIP :
+{
+ > : DEFAULT
+}
+
+
+// MORE:
+SKIP:
+{
+ <(~[])>
}
@@ -2231,13 +2415,15 @@ TOKEN:
<#_GT: ">" > |
<#_LE: "<=" > |
<#_GE: ">=" > |
- <#_AND: "&&" > |
- <#_LOG_AND: "&" > |
- <#_OR: "||" > |
- <#_LOG_OR: "|" > |
+ <#_AND: "&" > |
+ <#_LOG_AND: "&&" > |
+ <#_OR: "|" > |
+ <#_XOR: "^" > |
+ <#_LOG_OR: "||" > |
<#_LSH: "<<" > |
<#_RSH: ">>" > |
<#_MINUS: "-" > |
+ <#_PERCENT: "%" > |
<#_PLUS: "+" > |
<#_QMARK: "?" > |
<#_COLON: ":" > |
@@ -2317,15 +2503,12 @@ SKIP:
"undef" : UNDEFINE
|
"line" : LINE
- |
- > : DEFAULT
| // former IF states
<_WSP0: > : DIRECTIVE |
<_COD1: > : DIRECTIVE |
<_WSP2: > : DIRECTIVE |
: DIRECTIVE |
<_LCMT0: > : LINECOMMENT |
- > : DEFAULT |
<_CMT0: > : DIRECTIVECOMMENT
}
@@ -2351,12 +2534,15 @@ TOKEN : {
> |
> |
> |
+ > |
> |
> |
> |
> |
> |
> |
+ > |
+ > |
> |
> |
> |
@@ -2365,7 +2551,8 @@ TOKEN : {
)+ > |
|
> { parenNesting++; } : DIRECTIVE |
- > { parenNesting--; } : DIRECTIVE
+ > { parenNesting--; } : DIRECTIVE |
+ > : DEFAULT
}
@@ -2383,7 +2570,6 @@ SKIP : {
<_INCCP: > : DIRECTIVE |
<_INCOP: > : INCDEF |
<_INCSTANDARD: <_LT> (~["\n","\r",">",")","("])* <_GT> > : INCDEF
-// > : DEFAULT
}
//
@@ -2457,26 +2643,26 @@ SKIP : {
TOKEN : {
- ( | ( "/" ) )+ > : DEFAULT
+ ( | ( "/" ) )+ > : DEFAULT |
+ > : DEFAULT
}
SKIP : {
<_LCMT20: > : LINECOMMENT |
- <_WSP3: > : IFDEF |
- > : DEFAULT
+ <_WSP3: > : IFDEF
}
TOKEN : {
- ( | ( "/" ) )+ > : DEFAULT
+ ( | ( "/" ) )+ > : DEFAULT |
+ > : DEFAULT
}
SKIP : {
<_LCMT21: > : LINECOMMENT |
- <_WSP4: > : IFNDEF |
- > : DEFAULT
+ <_WSP4: > : IFNDEF
}
@@ -2515,13 +2701,13 @@ SKIP : {
SKIP : {
- >: DEFAULT |
<_LEADIN1: ()+> : UNDEFINE
}
TOKEN : {
- > : DEFAULT
+ > : DEFAULT |
+ >: DEFAULT
}
@@ -2533,14 +2719,14 @@ SKIP : {
SKIP : {
"(" : MACROARGS |
")" : MACROVALS |
- > : DEFAULT |
<_WSP7: > : RVALUES |
<_CODC: > : RVALUES
}
TOKEN : {
-
+ |
+ > : DEFAULT
}
diff --git a/Ghidra/Features/Base/src/test/java/ghidra/app/util/cparser/CParserTest.java b/Ghidra/Features/Base/src/test/java/ghidra/app/util/cparser/CParserTest.java
index 1ff332295a..f61baba65c 100644
--- a/Ghidra/Features/Base/src/test/java/ghidra/app/util/cparser/CParserTest.java
+++ b/Ghidra/Features/Base/src/test/java/ghidra/app/util/cparser/CParserTest.java
@@ -124,12 +124,6 @@ public class CParserTest extends AbstractGenericTest {
return dtm;
}
- @Test
- public void testPreProcessor() throws Exception {
- // TODO: parse a header file with lots of CPP defines, etc
- // TODO: Do a simple parse to make sure the data came out correctly
- }
-
@Test
public void testHeaderParsing() throws Exception {
// Uncomment to save the parse results to a GDT file to check out
@@ -154,6 +148,11 @@ public class CParserTest extends AbstractGenericTest {
DataType dt;
String str;
+ dt = dtMgr.getDataType(new CategoryPath("/"), "_IO_FILE_complete");
+ Structure sldt = (Structure) dt;
+ DataTypeComponent data3 = sldt.getComponent(2);
+ assertEquals("Computed Array correct", 40, data3.getLength());
+
dt = dtMgr.getDataType(new CategoryPath("/"), "fnptr"); // typedef int (*fnptr)(struct fstruct);
// "fnptr" named typedef of pointer to "int fnptr(fstruct )" --- should an anonymous function name be used?
diff --git a/Ghidra/Features/Base/src/test/java/ghidra/app/util/cparser/PreProcessorTest.java b/Ghidra/Features/Base/src/test/java/ghidra/app/util/cparser/PreProcessorTest.java
index 118ee3088c..7a29cb859b 100644
--- a/Ghidra/Features/Base/src/test/java/ghidra/app/util/cparser/PreProcessorTest.java
+++ b/Ghidra/Features/Base/src/test/java/ghidra/app/util/cparser/PreProcessorTest.java
@@ -20,24 +20,44 @@ import static org.junit.Assert.*;
import java.io.ByteArrayOutputStream;
import java.net.URL;
-import org.junit.Test;
+import org.junit.*;
import generic.test.AbstractGenericTest;
+import ghidra.app.util.cparser.CPP.ParseException;
import ghidra.app.util.cparser.CPP.PreProcessor;
import ghidra.program.model.data.*;
import ghidra.program.model.data.Enum;
public class PreProcessorTest extends AbstractGenericTest {
+ private static String resourceName = "PreProcessorTest.h";
+ private static CategoryPath path = new CategoryPath(new CategoryPath("/PreProcessorTest.h"), "defines");
+
+ // must get rid of after all tests
+ private static StandAloneDataTypeManager dtMgr;
+ private static ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ private static PreProcessor parser;
+
+ long value;
+ String defname;
public PreProcessorTest() {
super();
}
- @Test
- public void testHeaderParsing() throws Exception {
- PreProcessor parser = new PreProcessor();
+ @BeforeClass
+ public static void init() {
+ URL url = PreProcessorTest.class.getResource(resourceName);
+
+ String[] args = new String[] {"-I"+url.getPath()+"/..","-DFROM_ARG_VALUE=300", "-DFROM_ARG_DEF", "-DFROM_ARG_EMPTY=\"\""};
+ parser = null;
+ try {
+ parser = new PreProcessor(args);
+ }
+ catch (ParseException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
parser.setOutputStream(baos);
//// String[] args = new String[] {"-I/local/VisualStudio/Windows/v7.0a/Include", "-I/local/VisualStudio/VS12/include", "-D_WIN32", "-D_CRT_SECURE_NO_WARNINGS"};
@@ -53,14 +73,25 @@ public class PreProcessorTest extends AbstractGenericTest {
//// fullName = "adoguids.h";
//// parser.parse(fullName);
- String resourceName = "PreProcessorTest.h";
- URL url = PreProcessorTest.class.getResource(resourceName);
-
parser.parse(url.getFile());
// Uncomment to print out parse results
- System.err.println(baos.toString());
+ // System.err.println(baos.toString());
+ dtMgr = new StandAloneDataTypeManager("parsed");
+ parser.getDefinitions().populateDefineEquates(dtMgr);
+ }
+
+ @AfterClass
+ public static void destroy() {
+ dtMgr = null;
+ baos = null;
+ parser = null;
+ }
+
+ @Test
+ public void testHeaderParsed() throws Exception {
+
String results = baos.toString("ASCII");
int end = results.lastIndexOf(";") + 1;
String endStr = results.substring(end - 9, end);
@@ -68,15 +99,15 @@ public class PreProcessorTest extends AbstractGenericTest {
assertTrue("macro expansion _fpl(bob) failed ", results
.indexOf("extern int __declspec(\"fp(\\\"l\\\", \" #bob \")\") __ifplbob;") != -1);
+ }
+
+ @Test
+ public void testDefines() throws Exception {
+ long value;
+ String defname;
- StandAloneDataTypeManager dtMgr = new StandAloneDataTypeManager("parsed");
- parser.getDefinitions().populateDefineEquates(dtMgr);
-
- CategoryPath path = new CategoryPath("/PreProcessorTest.h");
- path = new CategoryPath(path, "defines");
-
- long value = 32516;
- String defname = "DefVal1";
+ value = 32516;
+ defname = "DefVal1";
checkDefine(dtMgr, path, value, defname);
value = 0x06010000 + 0xf1;
@@ -129,10 +160,145 @@ public class PreProcessorTest extends AbstractGenericTest {
defname = "isDefineOnValue";
value = 1;
checkDefine(dtMgr, path, value, defname);
+
+ defname = "DID_EXPANSION";
+ value = 1;
+ checkDefine(dtMgr, path, value, defname);
defname = "BIGNUM";
value = 64 * 16 + 16;
checkDefine(dtMgr, path, value, defname);
+
+ defname = "NEWLINETEST1";
+ value = 1;
+ checkDefine(dtMgr, path, value, defname);
+
+ defname = "NEWLINETEST2";
+ value = 2;
+ checkDefine(dtMgr, path, value, defname);
+
+ defname = "NEWLINETEST3";
+ value = 3;
+ checkDefine(dtMgr, path, value, defname);
+
+
+ defname = "SEPERATORC";
+ String defval = parser.getDef(defname);
+ assertEquals(defval, "','");
+ }
+
+ @Test
+ public void testDefinesArgValue() {
+ defname = "DID_ARG_VALUE";
+ value = 1;
+ checkDefine(dtMgr, path, value, defname);
+
+ // This is from a -D arg define, not from a file
+ CategoryPath argCategoryPath = new CategoryPath(CategoryPath.ROOT, "defines");
+ defname = "FROM_ARG_VALUE";
+ value = 300;
+ checkDefine(dtMgr, argCategoryPath, value, defname);
+ }
+
+ @Test
+ public void testDefinesArgEmpty() {
+ defname = "DID_ARG_EMPTY";
+ value = 1;
+ checkDefine(dtMgr, path, value, defname);
+ }
+
+ @Test
+ public void testDefinesArgDef() {
+ defname = "DID_ARG_DEF";
+ value = 1;
+ checkDefine(dtMgr, path, value, defname);
+ }
+
+ @Test
+ public void testDefinesArgIsDefValue() {
+ defname = "DID_ARG_ISDEF_VALUE";
+ value = 1;
+ checkDefine(dtMgr, path, value, defname);
+ }
+
+ @Test
+ public void testDefinesArgIsDefEmpty() {
+ defname = "DID_ARG_ISDEF_EMPTY";
+ value = 1;
+ checkDefine(dtMgr, path, value, defname);
+ }
+
+ @Test
+ public void testDefinesArgIsDefDef() {
+ defname = "DID_ARG_ISDEF_DEF";
+ value = 1;
+ checkDefine(dtMgr, path, value, defname);
+ }
+
+ @Test
+ public void testFileDefinesValue() {
+ defname = "DID_FILE_VALUE";
+ value = 1;
+ checkDefine(dtMgr, path, value, defname);
+ }
+
+ @Test
+ public void testDefinesFileEmpty() {
+ defname = "DID_FILE_EMPTY";
+ value = 1;
+ checkDefine(dtMgr, path, value, defname);
+ }
+
+ @Test
+ public void testDefinesFileDef() {
+ defname = "DID_FILE_DEF";
+ value = 1;
+ checkDefine(dtMgr, path, value, defname);
+ }
+
+ @Test
+ public void testDefinesFileIsDefValue() {
+ defname = "DID_FILE_ISDEF_VALUE";
+ value = 1;
+ checkDefine(dtMgr, path, value, defname);
+ }
+
+ @Test
+ public void testDefinesFileIsDefEmpty() {
+ defname = "DID_FILE_ISDEF_EMPTY";
+ value = 1;
+ checkDefine(dtMgr, path, value, defname);
+ }
+
+ @Test
+ public void testDefinesFileIsDefDef() {
+ defname = "DID_FILE_ISDEF_DEF";
+ value = 1;
+ checkDefine(dtMgr, path, value, defname);
+ }
+
+ @Test
+ public void testMultipleInclude() {
+ defname = "INCLUDE1";
+ String defval = parser.getDef(defname);
+ assertNotNull("Had 1 duplicate include", defval);
+
+ defname = "INCLUDE2";
+ defval = parser.getDef(defname);
+ assertNotNull("Had 2 duplicate include", defval);
+
+ defname = "INCLUDE3";
+ defval = parser.getDef(defname);
+ assertNotNull("Had 3 duplicate include", defval);
+
+ defname = "INCLUDE4";
+ defval = parser.getDef(defname);
+ assertNotNull("Had 4 duplicate include", defval);
+
+ defname = "INCLUDE5";
+ defval = parser.getDef(defname);
+ // if a define is not defined, getDef() returns name of define as value
+ assertEquals("No INCLUDE5 define", "INCLUDE5", defval);
}
private void checkDefine(StandAloneDataTypeManager dtMgr, CategoryPath path, long value,
diff --git a/Ghidra/Features/Base/src/test/resources/ghidra/app/util/cparser/CParserTest.h b/Ghidra/Features/Base/src/test/resources/ghidra/app/util/cparser/CParserTest.h
index cbcdc9ba78..3c40dc41de 100644
--- a/Ghidra/Features/Base/src/test/resources/ghidra/app/util/cparser/CParserTest.h
+++ b/Ghidra/Features/Base/src/test/resources/ghidra/app/util/cparser/CParserTest.h
@@ -18,6 +18,26 @@
** Some data types are checked. More checking of the parsed information would be beneficial at some point.
**/
+ void blarg(int *);
+
+ void * foo;
+
+ typedef void *bar;
+
+ typedef int size_t;
+ typedef int pid_t;
+
+
+
+ struct _IO_FILE_complete
+{
+ size_t __pad5;
+ int _mode;
+ /* Make sure we don't get into trouble again. */
+ char _unused2[15 * sizeof (int) - 4 * sizeof (void **) - sizeof (size_t)];
+};
+
+
/**
** use of long as an attribute
@@ -60,7 +80,7 @@ int (__stdcall * GetSectionBlock) (
#pragma pack(push, 4)
__pragma(pack(push, MyName, 8))
-struct packed8 {
+struct __declspec(align(16)) __pragma(warning(push)) __pragma(warning(disable:4845)) __declspec(no_init_all) __pragma(warning(pop)) packed8 {
char a;
short b;
int c;
@@ -91,6 +111,10 @@ struct packed1 {
char a;
};
+#pragma pack(push);
+#pragma pack(1);
+#pragma pack(pop);
+
#pragma pack(); // reset to none
struct packed_none {
diff --git a/Ghidra/Features/Base/src/test/resources/ghidra/app/util/cparser/PreProcessorTest.h b/Ghidra/Features/Base/src/test/resources/ghidra/app/util/cparser/PreProcessorTest.h
index ceecb60cfc..48846d6434 100644
--- a/Ghidra/Features/Base/src/test/resources/ghidra/app/util/cparser/PreProcessorTest.h
+++ b/Ghidra/Features/Base/src/test/resources/ghidra/app/util/cparser/PreProcessorTest.h
@@ -13,8 +13,125 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
+ /* definition coming from -D, should evaluate to true */
+ #if FROM_ARG_VALUE
+ #define DID_ARG_VALUE 1
+ #endif
+
+ #if FROM_ARG_DEF
+ #define DID_ARG_DEF 1
+ #endif
+
+ #if FROM_ARG_EMPTY
+ #define DID_ARG_EMPTY 1
+ #endif
+
+ #if defined(FROM_ARG_VALUE)
+ #define DID_ARG_ISDEF_VALUE 1
+ #endif
+
+ #if defined(FROM_ARG_DEF)
+ #define DID_ARG_ISDEF_DEF 1
+ #endif
+
+ #if defined(FROM_ARG_EMPTY)
+ #define DID_ARG_ISDEF_EMPTY 1
+ #endif
+
+
+
+ /* Defined checks from file */
+ #define FROM_FILE_VALUE 300
+ #define FROM_FILE_EMPTY ""
+ #define FROM_FILE_DEF
+
+ #if FROM_FILE_VALUE
+ #define DID_FILE_VALUE 1
+ #endif
+
+ #if FROM_FILE_EMPTY
+ #define DID_FILE_EMPTY 1
+ #endif
+
+ #if FROM_FILE_DEF
+ #define DID_FILE_DEF 1
+ #endif
+
+ #if defined(FROM_FILE_VALUE)
+ #define DID_FILE_ISDEF_VALUE 1
+ #endif
+
+ #if defined(FROM_FILE_EMPTY)
+ #define DID_FILE_ISDEF_EMPTY 1
+ #endif
+
+ #if defined(FROM_FILE_DEF)
+ #define DID_FILE_ISDEF_DEF 1
+ #endif
+
+#include "multinclude.h"
+
+#include "multinclude.h"
+
+#include "multinclude.h"
+
+#include "multinclude.h"
+
+#define __TEXT(quote) quote
+
+#define TEXT(quote) __TEXT(quote)
+
+ #define SEPERATORC TEXT(',')
+
+ #define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length))
+
+ #define ZeroMemory RtlZeroMemory
+
+
+#define foo ZeroMemory(&Filter->gf_group, sizeof(Filter->gf_group));
+
+int foo;
+
+
#pragma once
+#define PTYPE 4
+
+#define TYPE2 2 /* 2 */
+#define TYPE3 3 /* 3 */
+#define TYPE4 4 /* 4 */
+#define TYPE5 5 /* 5 */
+#define TYPE6 6 /* 6 */
+
+#ifndef P1
+#define P1 \
+ (PTYPE == TYPE3 || \
+ PTYPE == TYPE4 || \
+ PTYPE == TYPE5 )
+#endif
+
+
+#ifndef P2
+#define P2 \
+ (PTYPE == TYPE5 || \
+ PTYPE == TYPE6)
+#endif
+
+#ifndef P3
+#define P3 \
+ (PTYPE == TYPE1 || \
+ PTYPE == TYPE5 )
+#endif
+
+#define PPTYPE(Partition) (Partition)
+
+#if PPTYPE(P1 | P2 | P3)
+#define DID_EXPANSION 1
+#else
+#define DID_EXPANSION 0
+#endif
+
#ifndef _CRTIMP
#define _VCRT_DEFINED_CRTIMP
@@ -39,6 +156,8 @@
#error "Too many fish"
#define TOO_MANY_FISH 0
int TooManyFish;
+#else
+int NotEnoughFish;
#endif
#define TEST1 one
@@ -98,10 +217,10 @@ int TEST_FAILED;
#define AVERSION enum AVERSION
AVERSION
{
- AVERSION_5 = 1,
- AVERSION_6,
- AVERSION_7,
- AVERSION_8,
+ AVERSION_5 = 1, // version 5
+ AVERSION_6, // version 6
+ AVERSION_7, // version 7
+ AVERSION_8, // version 9
};
#define Group(a,b)
@@ -146,7 +265,9 @@ _fpl(bob)
EXTERN_C const GUID DECLSPEC_SELECTANY name \
= { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
-BUILD_GUID(LIBID_ADO20,0x##00000200,0x##0000,0x##0010,0x##80,0x##00,0x##00,0x##AA,0x##00,0x##6D,0x##2E,0x##A4)
+BUILD_GUID(LIBID_ADO20,0x##00000200,0x##0000,
+ 0x##0010,0x##80,0x##00,0x##00,
+ 0x##AA,0x##00,0x##6D,0x##2E,0x##A4)
#define ___POSIX_C_DEPRECATED_STARTING_199506L
@@ -276,5 +397,26 @@ int does_not_has_include();
# include_next
#endif
+#if 0
+#define NEWLINETEST1 0 // uh oh
+#else
+#define NEWLINETEST1 1 // strange
+#endif
+
+#define NEWLINETEST2 2 /* Comment with */
+/* linefeed */
+#define NEWLINETEST3 3
+
+// Should be blank line below
+#define AVALUE 1
+// Should be blank line above
+
+// 5 blank lines below
+#if 0
+#define BVALUE 0
+#else
+#define BVALUE 2
+#endif
+// 5 blank lines above
theEnd();
diff --git a/Ghidra/Features/Base/src/test/resources/ghidra/app/util/cparser/multinclude.h b/Ghidra/Features/Base/src/test/resources/ghidra/app/util/cparser/multinclude.h
new file mode 100644
index 0000000000..d9df9c33f3
--- /dev/null
+++ b/Ghidra/Features/Base/src/test/resources/ghidra/app/util/cparser/multinclude.h
@@ -0,0 +1,34 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef INCLUDE1
+#define INCLUDE1
+#pragma pack(push,1)
+
+#else if !defined(INCLUDE2)
+#define INCLUDE2
+#pragma pack(push, 2)
+
+#else if !defined(INCLUDE3)
+#define INCLUDE3
+#pragma pack(push, 4)
+
+#else if !defined(INCLUDE4)
+#define INCLUDE4
+#pragma pack(push, 8)
+
+#else
+#define INCLUDE5 // never gets to this
+#endif
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/AddressEvaluator.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/AddressEvaluator.java
index e4bed3eb98..c5df6c6cc9 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/AddressEvaluator.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/AddressEvaluator.java
@@ -56,7 +56,7 @@ public class AddressEvaluator {
}
else if (obj instanceof Long) {
try {
- return af.getDefaultAddressSpace().getAddress(((Long) obj).longValue());
+ return af.getDefaultAddressSpace().getAddress(((Long) obj).longValue(), true);
}
catch (Exception e) {
// ignore
@@ -100,7 +100,7 @@ public class AddressEvaluator {
}
// = must be followed by =, others can be followed
- if (tok.equals("=") || tok.equals("!") || tok.equals("<") || tok.equals(">")) {
+ if ("=!<>|&".contains(tok)) {
lookahead = parser.nextToken();
tok = checkDoubleToken(tok, lookahead);
// if tok is now longer, consumed lookahead
@@ -151,6 +151,18 @@ public class AddressEvaluator {
return "!=";
}
break;
+
+ case "|":
+ if (lookahead.equals("|")) {
+ return "||";
+ }
+ break;
+
+ case "&":
+ if (lookahead.equals("&")) {
+ return "&&";
+ }
+ break;
}
return tok;
@@ -365,6 +377,14 @@ public class AddressEvaluator {
if (!evaluateOperator(list, Operator.LESSEQUALS, Operator.GREATEREQUALS)) {
return null;
}
+
+ if (!evaluateOperator(list, Operator.LOG_AND, null)) {
+ return null;
+ }
+
+ if (!evaluateOperator(list, Operator.LOG_OR, null)) {
+ return null;
+ }
if (list.size() != 1) {
return null;
@@ -498,6 +518,18 @@ public class AddressEvaluator {
return diff > 0L ? 1L : 0L;
}
}
+ else if (op == Operator.LOG_AND) {
+ if ((v1 instanceof Long) && (v2 instanceof Long)) {
+ boolean test = (((Long) v1).longValue()) != 0 && (((Long) v2).longValue()) != 0;
+ return test ? 1L : 0L;
+ }
+ }
+ else if (op == Operator.LOG_OR) {
+ if ((v1 instanceof Long) && (v2 instanceof Long)) {
+ boolean test = (((Long) v1).longValue()) != 0 || (((Long) v2).longValue()) != 0;
+ return test ? 1L : 0L;
+ }
+ }
return null;
}
@@ -544,6 +576,8 @@ class Operator {
static Operator RIGHTSHIFT = new Operator(">>");
static Operator LEFT_PAREN = new Operator("(");
static Operator RIGHT_PAREN = new Operator(")");
+ static Operator LOG_OR = new Operator("||");
+ static Operator LOG_AND = new Operator("&&");
static Operator EQUALS = new Operator("==");
static Operator NOTEQUALS = new Operator("!=");
static Operator LESS = new Operator("<");
@@ -622,6 +656,12 @@ class Operator {
else if (tok.equals(">=")) {
return GREATEREQUALS;
}
+ else if (tok.equals("||")) {
+ return LOG_OR;
+ }
+ else if (tok.equals("&&")) {
+ return LOG_AND;
+ }
return null;
}
}