resourceSetProvider;
+
+// Sample to use for testing
+// var model = '''
+// define space register size=2 type=register_space wordsize=1 default;
+// define register offset=0 size=1 [ Z C N V ];
+//
+// define token instr(16)
+// op = (0,15)
+// reg = (0,1)
+// cc = (2,3)
+// ;
+//
+// attach variables [ reg ] [ Z C N V ];
+//
+// macro a() {
+// Z = 1;
+// }
+//
+// CC: "ne" is cc=0x1 { local tmp = !Z; C = 1; tmp = C; export tmp; }
+// CC: "lt" is cc=0x2 { local tmp = N != V; export tmp; }
+// CC: "lt" is cc=0x2 { local tmp:1 = N != V; export tmp; }
+// CC: "lt" is cc=0x2 { tmp:1 = N != V; export tmp; }
+// CC: "lt" is cc=0x2 { tmp:1 = N != V; export tmp; tmp = 1; }
+//
+// :mov reg,N is op=0 & CC & N & reg { tmp:1 = CC; reg = tmp; }
+// '''.parse
+
+ @Test def void testReferences() {
+ // tmp should not resolve
+ var model = '''
+ define space register size=2 type=register_space wordsize=1 default;
+ define register offset=0 size=1 [ Z C N V ];
+
+ define token instr(16)
+ op = (0,15)
+ reg = (0,1)
+ cc = (2,3)
+ ;
+
+ attach variables [ reg ] [ Z C N V ];
+
+ :mov reg,N is op=0 & C & N & reg { tmp:1 = 1; }
+
+ :mov reg,N is op=0 & C & N & reg { tmp = C; }
+ '''.parse
+
+ assertError(model,
+ SleighPackage::eINSTANCE.getassignSym(),
+ Diagnostic.LINKING_DIAGNOSTIC, 311, 3,
+ "Couldn't resolve reference to lhsvarnode 'tmp'."
+ )
+
+ // tmp should not resolve
+ model = '''
+ define space register size=2 type=register_space wordsize=1 default;
+ define register offset=0 size=1 [ Z C N V ];
+
+ define token instr(16)
+ op = (0,15)
+ reg = (0,1)
+ cc = (2,3)
+ ;
+
+ attach variables [ reg ] [ Z C N V ];
+
+ :mov reg,N is op=0 & C & N & reg { tmp:1 = 1; }
+
+ :mov reg,N is op=0 & C & N & reg { reg = tmp; }
+ '''.parse
+
+ assertError(model,
+ SleighPackage::eINSTANCE.getexprSym(),
+ Diagnostic.LINKING_DIAGNOSTIC, 314, 3,
+ "Couldn't resolve reference to EObject 'tmp'."
+ )
+ }
+
+ @Test def void testMacroReferences() {
+ var model = '''
+ define space register size=2 type=register_space wordsize=1 default;
+ define register offset=0 size=1 [ Z C N V ];
+
+ define token instr(16)
+ op = (0,15)
+ reg = (0,1)
+ cc = (2,3)
+ ;
+
+ attach variables [ reg ] [ Z C N V ];
+
+ macro macro_a(arg1,arg2) {
+ local foo = 1;
+ foo = (~foo & foo | foo) << foo;
+ Z = 1;
+ arg1 = 3;
+ arg2 = foo;
+ }
+
+ :mov reg,N,op is op=0 & N & reg & op & op=1 {
+ tmp:1 = 1;
+ tmp2:1 = reg(4);
+ macro_a(reg,tmp);
+ }
+ '''.parse
+ model.assertNoErrors
+ }
+
+
+ @Test def void testBadAliasReferences() {
+ var model = '''
+ define space register size=2 type=register_space wordsize=1 default;
+
+ define token instr(16)
+ op = (0,15)
+ reg = (0,1)
+ cc = (2,3)
+ ;
+
+ :mov AliasRef is op=0 & AliasRef [ AliasRef = inst_next; ] { tmp:1 = AliasRef; } #AliasRef in constraint
+ '''.parse
+
+ assertError(model,
+ SleighPackage::eINSTANCE.getconstraint(),
+ Diagnostic.LINKING_DIAGNOSTIC, 164,8,
+ "Couldn't resolve reference to EObject 'AliasRef'."
+ )
+
+ model = '''
+ define space register size=2 type=register_space wordsize=1 default;
+
+ define token instr(16)
+ op = (0,15)
+ reg = (0,1)
+ cc = (2,3)
+ ;
+
+ AliasRef: "empty" is op=0 {}
+
+ :mov AliasRef is op=0 [ AliasRef = inst_next; ] { tmp:1 = AliasRef; } #AliasRef in constraint
+ '''.parse
+
+ var references = EcoreUtil.UsageCrossReferencer.find(model.elements)
+
+ references.forEach[p1, p2 |
+ System.out.println(p1 + " -> " + p2)
+ ]
+ }
+
+ @Test def void testAliasRefOverrid() {
+
+ var XtextResourceSet resourceSet = resourceSetProvider.get();
+
+ parser.parse("REGGsrc: reg is reg { export reg; } ", resourceSet)
+
+ var model = parser.parse('''
+ define space register size=2 type=register_space wordsize=1 default;
+ define register offset=0 size=1 [ Z C N V ];
+ define register offset=100 size=1 [ contReg ];
+
+ define token instr(16)
+ op = (0,15)
+ reg = (0,1)
+ cc = (2,3)
+ ;
+
+ define context contReg
+ contFlag = (0,0)
+ ;
+
+ attach variables [ reg ] [ Z C N V ];
+
+ macro a(arg1,arg2) {
+ local foo = 1;
+ foo = (~foo & foo | foo) << foo;
+ Z = 1;
+ arg1 = 3;
+ arg2 = foo;
+ }
+
+ CC: "ne" is cc=0x1 { local tmp = !Z; C = 1; tmp = C; export tmp; }
+ CC: "lt" is cc=0x2 { local tmp = N != V; export tmp; }
+ CC: "lt" is cc=0x2 { local tmp:1 = N != V; export tmp; }
+ CC: "lt" is cc=0x2 { tmp:1 = N != V; export tmp; }
+ CC: "lt" is cc=0x2 { tmp:1 = N != V; export tmp; tmp = 1; }
+
+ :mov reg,N,op is op=0 & CC & N & reg & op & op=1 { tmp:1 = CC; reg = tmp; }
+
+ :mov REGGsrc,N,op is op=0 & CC & N & reg & REGGsrc & op & op=1 { REGGsrc = op; }
+
+ Dest: loc is op=0 [ loc = inst_next; ] { export loc; }
+ :jmp Dest is Dest { call Dest; }
+
+ :set reg is contFlag=0 & op=0 [ contFlag = 1; ] {}
+ ''', resourceSet)
+ model.assertNoErrors;
+
+ var references = EcoreUtil.UsageCrossReferencer.find(model.elements)
+
+ references.forEach[p1, p2 |
+ System.out.println(p1 + " -> " + p2)
+ ]
+
+
+//
+// model.eAllContents.filter[elem |
+// elem instanceof SUBTABLESYM
+// ].forEach[
+// elem | var list = elem.eCrossReferences; System.out.println(list)
+// ]
+//
+// // now need to verify xref of reg,N,op are not aliases in the match or pcode
+// var refs = model.eCrossReferences;
+// refs.forEach[
+// element | println(element);
+// ]
+//
+ // need to verify that an alias in the context var stays as an alias var
+ // unless it is also a global symbol
+ }
+
+ @Test def void testContextAliasRef() {
+
+ var XtextResourceSet resourceSet = resourceSetProvider.get();
+
+ parser.parse("REGGsrc: reg is reg { export reg; } ", resourceSet)
+
+ var model = parser.parse('''
+ define space register size=2 type=register_space wordsize=1 default;
+ define register offset=0 size=1 [ Z C N V ];
+ define register offset=100 size=1 [ contReg ];
+
+ define token instr(16)
+ op = (0,15)
+ reg = (0,1)
+ cc = (2,3)
+ ;
+
+ define context contReg
+ contFlag = (0,0)
+ cont2 = (1,1)
+ ;
+
+ attach variables [ reg ] [ Z C N V ];
+
+
+ #:mov reg,N,op,vis is op=0 & N & reg & op & op=1 [ vis = op << 20; ] { tmp:1 = vis reg = tmp; }
+
+ #:mov reg,N,op,vis is op=0 & N & reg & op & op=1 [ vis = op << 20; contFlag=op; cont2=contFlag; ] { tmp:1 = vis; reg = tmp; }
+
+ :mov reg,vis is op=0 & reg [ vis = 20; contFlag=vis; ] { tmp:1 = vis; reg = tmp; }
+
+ ''', resourceSet)
+ model.assertNoErrors;
+
+ var references = EcoreUtil.UsageCrossReferencer.find(model.elements)
+
+ references.forEach[p1, p2 |
+ System.out.println(p1 + " -> " + p2)
+ ]
+ }
+}
\ No newline at end of file
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui.tests/META-INF/MANIFEST.MF b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui.tests/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..f700b7eb73
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui.tests/META-INF/MANIFEST.MF
@@ -0,0 +1,18 @@
+Manifest-Version: 1.0
+Automatic-Module-Name: ghidra.xtext.sleigh.ui.tests
+Bundle-ManifestVersion: 2
+Bundle-Name: ghidra.xtext.sleigh.ui.tests
+Bundle-Vendor: My Company
+Bundle-Version: 1.0.0.qualifier
+Bundle-SymbolicName: ghidra.xtext.sleigh.ui.tests; singleton:=true
+Bundle-ActivationPolicy: lazy
+Require-Bundle: ghidra.xtext.sleigh.ui,
+ org.junit.jupiter.api;bundle-version="[5.0.0,6.0.0)",
+ org.eclipse.xtext.testing,
+ org.eclipse.xtext.xbase.testing,
+ org.eclipse.xtext.junit4,
+ org.eclipse.xtext.xbase.junit,
+ org.eclipse.core.runtime,
+ org.eclipse.ui.workbench;resolution:=optional
+Bundle-RequiredExecutionEnvironment: JavaSE-11
+Export-Package: ghidra.xtext.sleigh.ui.tests;x-internal=true
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui.tests/build.properties b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui.tests/build.properties
new file mode 100644
index 0000000000..5c6bbf99f0
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui.tests/build.properties
@@ -0,0 +1,6 @@
+source.. = src/,\
+ src-gen/,\
+ xtend-gen/
+bin.includes = .,\
+ META-INF/
+bin.excludes = **/*.xtend
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/META-INF/MANIFEST.MF b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..1fa442904a
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/META-INF/MANIFEST.MF
@@ -0,0 +1,26 @@
+Manifest-Version: 1.0
+Automatic-Module-Name: ghidra.xtext.sleigh.ui
+Bundle-ManifestVersion: 2
+Bundle-Name: ghidra.xtext.sleigh.ui
+Bundle-Vendor: My Company
+Bundle-Version: 1.0.0.qualifier
+Bundle-SymbolicName: ghidra.xtext.sleigh.ui; singleton:=true
+Bundle-ActivationPolicy: lazy
+Require-Bundle: ghidra.xtext.sleigh,
+ ghidra.xtext.sleigh.ide,
+ org.eclipse.xtext.ui,
+ org.eclipse.xtext.ui.shared,
+ org.eclipse.xtext.ui.codetemplates.ui,
+ org.eclipse.ui.editors;bundle-version="3.5.0",
+ org.eclipse.ui.ide;bundle-version="3.5.0",
+ org.eclipse.ui,
+ org.eclipse.compare,
+ org.eclipse.xtext.builder,
+ org.eclipse.xtext.xbase.lib;bundle-version="2.14.0",
+ org.eclipse.xtend.lib;bundle-version="2.14.0";resolution:=optional
+Import-Package: org.apache.log4j
+Bundle-RequiredExecutionEnvironment: JavaSE-11
+Export-Package: ghidra.xtext.sleigh.ui.internal,
+ ghidra.xtext.sleigh.ui.contentassist,
+ ghidra.xtext.sleigh.ui.quickfix
+Bundle-Activator: ghidra.xtext.sleigh.ui.internal.SleighActivator
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/build.properties b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/build.properties
new file mode 100644
index 0000000000..323f56c513
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/build.properties
@@ -0,0 +1,7 @@
+source.. = src/,\
+ src-gen/,\
+ xtend-gen/
+bin.includes = .,\
+ META-INF/,\
+ plugin.xml
+bin.excludes = **/*.xtend
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/plugin.xml b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/plugin.xml
new file mode 100644
index 0000000000..7ab07ef916
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/plugin.xml
@@ -0,0 +1,513 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/ConsoleLineTracker.java b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/ConsoleLineTracker.java
new file mode 100644
index 0000000000..1a1a035b80
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/ConsoleLineTracker.java
@@ -0,0 +1,43 @@
+/* ###
+ * 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.
+ */
+package ghidra.xtext.sleigh.ui;
+
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.debug.ui.console.IConsole;
+import org.eclipse.debug.ui.console.IConsoleLineTracker;
+import org.eclipse.jface.text.IRegion;
+
+public class ConsoleLineTracker implements IConsoleLineTracker {
+
+ @Override
+ public void init(IConsole console) {
+ IProcess process = console.getProcess();
+
+ System.out.println(process.getLabel());
+ }
+
+ @Override
+ public void lineAppended(IRegion line) {
+ System.out.println(line.toString());
+ }
+
+ @Override
+ public void dispose() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/SleighEObjectHoverProvider.xtend b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/SleighEObjectHoverProvider.xtend
new file mode 100644
index 0000000000..bee9abe17f
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/SleighEObjectHoverProvider.xtend
@@ -0,0 +1,202 @@
+/* ###
+ * 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.
+ */
+package ghidra.xtext.sleigh.ui
+
+import ghidra.xtext.sleigh.sleigh.DefineSym
+import ghidra.xtext.sleigh.sleigh.SUBTABLESYM
+import ghidra.xtext.sleigh.sleigh.aliasSym
+import ghidra.xtext.sleigh.sleigh.integerValue
+import ghidra.xtext.sleigh.sleigh.macroDefine
+import ghidra.xtext.sleigh.sleigh.printpiece
+import ghidra.xtext.sleigh.sleigh.subconstructor
+import java.math.BigInteger
+import org.eclipse.emf.common.util.EList
+import org.eclipse.emf.ecore.EObject
+import org.eclipse.xtext.conversion.ValueConverterException
+import org.eclipse.xtext.nodemodel.util.NodeModelUtils
+import org.eclipse.xtext.ui.editor.hover.html.DefaultEObjectHoverProvider
+import org.eclipse.xtext.util.Strings
+
+class SleighEObjectHoverProvider extends DefaultEObjectHoverProvider {
+
+ EObject model
+
+ override boolean hasHover(EObject o) {
+ if (o instanceof integerValue) { return true; }
+ return super.hasHover(o)
+ }
+
+ override String getFirstLine(EObject o) {
+ var label = getLabel(o);
+ var str = o.eClass().getName();
+ if (label == null) {
+ str += "";
+ } else {
+ str = " " + label + "";
+ }
+ return str;
+ }
+
+ override String getLabel(EObject element) {
+ switch element {
+ DefineSym:
+ return " " + element.name + ""
+ default:
+ return super.getLabel(element)
+ }
+ }
+
+ override String getDocumentation(EObject element) {
+ switch element {
+ DefineSym:
+ return getDefineSymText(element)
+ SUBTABLESYM:
+ return getSubTableText(element)
+ aliasSym:
+ return getSubTableText(element)
+ integerValue:
+ return getIntegerFormats(element)
+ default:
+ return super.getDocumentation(element)
+ }
+ }
+
+ def getIntegerFormats(integerValue value) {
+ var retStr = "";
+ var valueOf = getIntValue(value)
+
+ retStr = retStr + "" + "0b" + valueOf.toString(2) + "
\n"
+ retStr = retStr + "" + "0x" + valueOf.toString(16) + "
\n"
+ retStr = retStr + "" + " " + valueOf.toString(10) + "
\n"
+
+ if (retStr.length == 0) {
+ return value.value;
+ }
+ return retStr;
+ }
+
+ def getIntValue(integerValue value) {
+ var parseString = value.value;
+ var string = value.value
+ if (Strings.isEmpty(parseString))
+ throw new NumberFormatException("Couldn't convert empty string to an int value.");
+ try {
+ var radix = 10;
+ if (parseString.startsWith("0x") || parseString.startsWith("0X")) {
+ parseString = string.substring(2);
+ radix=16;
+ }
+ if (parseString.startsWith("0b") || parseString.startsWith("0B")) {
+ parseString = string.substring(2);
+ radix=2;
+ }
+ return new BigInteger(parseString,radix);
+ } catch (NumberFormatException e) {
+ throw new NumberFormatException("Couldn't convert '" + string + "' to a BigInteger value.");
+ }
+ }
+
+ def getDefineSymText(DefineSym element) {
+ var retStr = "";
+ model = element.eResource.contents.get(0);
+ var macDefs = model.eAllContents.filter(typeof(macroDefine));
+ var len = "";
+ while (macDefs.hasNext) {
+ var next = macDefs.next;
+ if (next.defineType.equals("@define")) {
+ if (next.definename.name == element.name) {
+ retStr = retStr + "" + next.value + "
\n"
+ }
+ }
+ }
+ if (retStr.length == 0) {
+ return element.name;
+ }
+ return retStr;
+ }
+
+ def getSubTableText(SUBTABLESYM element) {
+ var retStr = "";
+ model = element.eResource.contents.get(0);
+ var subs = model.eAllContents.filter(typeof(subconstructor));
+ var len = "";
+ while (subs.hasNext) {
+ var next = subs.next;
+ if (next.tableName.name == element.name) {
+ retStr = retStr + "" + formatString(next.print.printpieces) +
+ " is " + formatConstraintString(next.match.constraints) + "
\n"
+ }
+ }
+ if (retStr.length == 0) {
+ return element.name;
+ }
+ return retStr;
+ }
+
+ def getSubTableText(aliasSym element) {
+ var retStr = "";
+ model = element.eResource.contents.get(0);
+ var subs = model.eAllContents.filter(typeof(subconstructor));
+ while (subs.hasNext) {
+ var next = subs.next;
+ if (next.tableName.name == element.sym) {
+ retStr = retStr + "" + formatString(next.print.printpieces) +
+ " is " + formatConstraintString(next.match.constraints) + "
\n"
+ }
+ }
+ if (retStr.length != 0) {
+ return retStr;
+ }
+ var macDefs = model.eAllContents.filter(typeof(macroDefine));
+ while (macDefs.hasNext) {
+ var next = macDefs.next;
+ if (next.defineType.equals("@define")) {
+ if (next.definename.name == element.sym) {
+ retStr = retStr + "" + next.value + "
\n"
+ }
+ }
+ }
+ if (retStr.length == 0) {
+ return element.sym;
+ }
+ return retStr;
+ }
+
+ def String formatString(EList list) {
+ var str = "";
+ var iter = list.iterator;
+ while (iter.hasNext) {
+ var piece = iter.next;
+ if (piece.str == null) {
+ if (piece.sym != null) {
+ str += piece.sym.sym;
+ } else {
+ str = '{empty}'
+ }
+ } else {
+ str += piece.str;
+ }
+ }
+ str += ""
+ str
+ }
+
+ def String formatConstraintString(EObject o) {
+ var node = NodeModelUtils.getNode(o);
+ return node.text
+ }
+
+}
\ No newline at end of file
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/SleighHighlightingCalculator.java b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/SleighHighlightingCalculator.java
new file mode 100644
index 0000000000..368f30290f
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/SleighHighlightingCalculator.java
@@ -0,0 +1,238 @@
+/* ###
+ * 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.
+ */
+package ghidra.xtext.sleigh.ui;
+
+import static org.eclipse.xtext.ui.editor.syntaxcoloring.DefaultHighlightingConfiguration.COMMENT_ID;
+import static org.eclipse.xtext.ui.editor.syntaxcoloring.DefaultHighlightingConfiguration.KEYWORD_ID;
+import static ghidra.xtext.sleigh.ui.SleighHighlightingConfiguration.CONTEXTFIELD;
+import static ghidra.xtext.sleigh.ui.SleighHighlightingConfiguration.LOCAL;
+import static ghidra.xtext.sleigh.ui.SleighHighlightingConfiguration.PRINTPIECE;
+import static ghidra.xtext.sleigh.ui.SleighHighlightingConfiguration.SUBTABLE;
+import static ghidra.xtext.sleigh.ui.SleighHighlightingConfiguration.TOKENFIELD;
+import static ghidra.xtext.sleigh.ui.SleighHighlightingConfiguration.VARIABLE;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.xtext.CrossReference;
+import org.eclipse.xtext.impl.TerminalRuleImpl;
+import org.eclipse.xtext.nodemodel.BidiIterator;
+import org.eclipse.xtext.nodemodel.BidiTreeIterator;
+import org.eclipse.xtext.nodemodel.INode;
+import org.eclipse.xtext.nodemodel.impl.HiddenLeafNode;
+import org.eclipse.xtext.nodemodel.impl.LeafNode;
+import org.eclipse.xtext.resource.XtextResource;
+import org.eclipse.xtext.util.CancelIndicator;
+import org.eclipse.xtext.ide.editor.syntaxcoloring.DefaultSemanticHighlightingCalculator;
+import org.eclipse.xtext.ide.editor.syntaxcoloring.IHighlightedPositionAcceptor;
+
+import ghidra.xtext.sleigh.sleigh.CONTEXTSYM;
+import ghidra.xtext.sleigh.sleigh.LOCALSYM;
+import ghidra.xtext.sleigh.sleigh.SUBTABLESYM;
+import ghidra.xtext.sleigh.sleigh.TOKENSYM;
+import ghidra.xtext.sleigh.sleigh.VARSYM;
+import ghidra.xtext.sleigh.sleigh.aliasSym;
+import ghidra.xtext.sleigh.sleigh.anysymbol;
+import ghidra.xtext.sleigh.sleigh.assignSym;
+import ghidra.xtext.sleigh.sleigh.constraint;
+import ghidra.xtext.sleigh.sleigh.exprSym;
+import ghidra.xtext.sleigh.sleigh.fielddef;
+import ghidra.xtext.sleigh.sleigh.isKeyword;
+import ghidra.xtext.sleigh.sleigh.pexprSym;
+import ghidra.xtext.sleigh.sleigh.printpiece;
+import ghidra.xtext.sleigh.sleigh.valuepart;
+import ghidra.xtext.sleigh.sleigh.varpart;
+
+public class SleighHighlightingCalculator extends DefaultSemanticHighlightingCalculator {
+
+ @Override
+ public void provideHighlightingFor(XtextResource resource, IHighlightedPositionAcceptor acceptor,
+ CancelIndicator cancelIndicator) {
+
+ if (resource == null || resource.getParseResult() == null)
+ return;
+
+ super.provideHighlightingFor(resource, acceptor, cancelIndicator);
+
+ INode root = resource.getParseResult().getRootNode();
+ BidiTreeIterator it = root.getAsTreeIterable().iterator();
+ while (it.hasNext()) {
+ INode node = it.next();
+ EObject grammarElement = node.getGrammarElement();
+ EObject semanticElement = node.getSemanticElement();
+ printNodeInfo(node, grammarElement, semanticElement);
+
+// if (node instanceof CompositeNodeWithSemanticElement
+// && semanticElement instanceof contextfielddef) {
+// setStyles(acceptor, it, CONTEXTFIELD, "GROUP", CONTEXTFIELD);
+// setStyles(acceptor, node.getAsTreeIterable().reverse()
+// .iterator(), null, CONTEXTFIELD);
+// } else
+ if (semanticElement instanceof VARSYM) {
+ setNodeStyle(acceptor, node, VARIABLE);
+// } else if (grammarElement instanceof Keyword) {
+// setStyles(acceptor, it, KEYWORD_ID);
+ } else if (semanticElement instanceof CONTEXTSYM) {
+ setNodeStyle(acceptor, node, CONTEXTFIELD);
+ } else if (semanticElement instanceof LOCALSYM) {
+ setNodeStyle(acceptor, node, LOCAL);
+ } else if (semanticElement instanceof TOKENSYM) {
+ setNodeStyle(acceptor, node, TOKENFIELD);
+ } else if (semanticElement instanceof fielddef) {
+ setNodeStyle(acceptor, node, TOKENFIELD);
+ } else if (semanticElement instanceof anysymbol) {
+ setStyle(acceptor, node, semanticElement);
+ } else if (grammarElement instanceof CrossReference) {
+ CrossReference defn = (CrossReference) grammarElement;
+ EObject semElem = semanticElement;
+ if (semElem instanceof varpart || semElem instanceof valuepart) {
+ setNodeStyle(acceptor, node, VARIABLE);
+ } else if (semElem instanceof LOCALSYM) {
+ setNodeStyle(acceptor, node, LOCAL);
+ } else if (semElem instanceof exprSym) {
+ exprSym sym = (exprSym) semElem;
+ EObject vnode = sym.getVnode();
+ if (vnode != null) {
+ setStyle(acceptor, node, vnode);
+ } else {
+ // System.out.println(" exprSym--" + semElem);
+ }
+ } else if (semElem instanceof assignSym) {
+ // TODO: Causing a lazy linking error sometimes
+ // Possibly something wrong with the grammer for [lhsvarnode]
+ // ERROR org.eclipse.xtext.linking.lazy.LazyLinkingResource - An element of type ghidra.xtext.sleigh.sleigh.impl.aliasSymImpl is not assignable to the reference assignSym.symref
+ assignSym sym = (assignSym) semElem;
+ EObject vnode = sym.getSymref();
+ if (vnode != null) {
+ setStyle(acceptor, node, vnode);
+ } else {
+ // System.out.println(" exprSym--" + semElem);
+ }
+ }
+ else if (semElem instanceof constraint) {
+ constraint sym = (constraint) semElem;
+ EObject vnode = sym.getSym();
+ if (vnode != null) {
+ setStyle(acceptor, node, vnode);
+ } else {
+ // System.out.println(" exprSym--" + semElem);
+ }
+ }
+ else if (semElem instanceof pexprSym) {
+ pexprSym sym = (pexprSym) semElem;
+ EObject vnode = sym.getSym();
+ if (vnode != null) {
+ setStyle(acceptor, node, vnode);
+ } else {
+ // System.out.println(" exprSym--" + semElem);
+ }
+ }
+ else if (semElem instanceof aliasSym) {
+ System.out.println(" semElem="+semElem);
+ }
+ else {
+ // System.out.println(" semElem="+semElem);
+ }
+ } else if (semanticElement instanceof isKeyword) {
+ setStyles(acceptor, it, KEYWORD_ID);
+ } else if (semanticElement instanceof aliasSym && semanticElement.eContainer() instanceof printpiece) {
+ setStyles(acceptor, it, PRINTPIECE);
+ } else if (semanticElement instanceof printpiece) {
+ setStyles(acceptor, it, PRINTPIECE);
+ } else if (node instanceof HiddenLeafNode
+ && grammarElement instanceof TerminalRuleImpl) {
+ processHiddenNode(acceptor, (HiddenLeafNode) node);
+ }
+
+
+ }
+ }
+
+ private void setStyle(IHighlightedPositionAcceptor acceptor, INode n, EObject vnode) {
+ if (vnode instanceof LOCALSYM) {
+ setNodeStyle(acceptor, n, LOCAL);
+ } else if (vnode instanceof VARSYM) {
+ setNodeStyle(acceptor, n, VARIABLE);
+ } else if (vnode instanceof SUBTABLESYM) {
+ setNodeStyle(acceptor, n, SUBTABLE);
+ } else if (vnode instanceof fielddef) {
+ setNodeStyle(acceptor, n, TOKENFIELD);
+ } else {
+ // System.out.println(" symtype = " + vnode);
+ }
+ }
+
+ private void setNodeStyle(IHighlightedPositionAcceptor acceptor, INode n, String styleName) {
+ acceptor.addPosition(n.getOffset(), n.getLength(), styleName);
+ }
+
+ private void printNodeInfo(INode node, EObject grammarElement,
+ EObject semanticElement) {
+ String grammar = "";
+ String semantic = "";
+
+ if (grammarElement != null) {
+ grammar = grammarElement.getClass().getSimpleName();
+ }
+ if (semanticElement != null) {
+ semantic = semanticElement.getClass().getSimpleName();
+ }
+ if (grammarElement instanceof TerminalRuleImpl) return;
+ if (! (node instanceof LeafNode)) return;
+// System.err.println( "Node: " + node.getClass().getSimpleName() +
+// "\t\t\t\t" + grammar + " =\t\t\t\t" + semantic + "\"" + node.getText() + "\"");
+ }
+
+ void setStyles(IHighlightedPositionAcceptor acceptor,
+ BidiIterator it, String... styles) {
+ for (String s : styles) {
+ if (!it.hasNext())
+ return;
+ INode n = skipWhiteSpace(acceptor, it);
+ if (n != null && s != null)
+ acceptor.addPosition(n.getOffset(), n.getLength(), s);
+ }
+ }
+
+ INode skipWhiteSpace(IHighlightedPositionAcceptor acceptor,
+ BidiIterator it) {
+ INode n = null;
+ while (it.hasNext()
+ && (n = it.next()).getClass() == HiddenLeafNode.class)
+ processHiddenNode(acceptor, (HiddenLeafNode) n);
+ return n;
+ }
+
+ INode skipWhiteSpaceBackwards(IHighlightedPositionAcceptor acceptor,
+ BidiIterator it) {
+ INode n = null;
+ while (it.hasPrevious()
+ && (n = it.previous()).getClass() == HiddenLeafNode.class)
+ processHiddenNode(acceptor, (HiddenLeafNode) n);
+ return n;
+ }
+
+ void processHiddenNode(IHighlightedPositionAcceptor acceptor,
+ HiddenLeafNode node) {
+ if (node.getGrammarElement() instanceof TerminalRuleImpl) {
+ TerminalRuleImpl ge = (TerminalRuleImpl) node.getGrammarElement();
+ String name = ge.getName();
+ if (name.equalsIgnoreCase("PDL_COMMENT") || name.equalsIgnoreCase("ML_COMMENT") || name.equalsIgnoreCase("SL_COMMENT")) {
+ acceptor.addPosition(node.getOffset(), node.getLength(), COMMENT_ID);
+ }
+ }
+
+ }
+
+}
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/SleighHighlightingConfiguration.java b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/SleighHighlightingConfiguration.java
new file mode 100644
index 0000000000..eb1d54dac4
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/SleighHighlightingConfiguration.java
@@ -0,0 +1,61 @@
+/* ###
+ * 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.
+ */
+package ghidra.xtext.sleigh.ui;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.xtext.ui.editor.syntaxcoloring.DefaultHighlightingConfiguration;
+import org.eclipse.xtext.ui.editor.syntaxcoloring.IHighlightingConfigurationAcceptor;
+import org.eclipse.xtext.ui.editor.utils.TextStyle;
+
+public class SleighHighlightingConfiguration extends DefaultHighlightingConfiguration {
+ // provide an id string for the highlighting calculator
+ public static final String CONTEXTFIELD = "Context Field";
+ public static final String TOKENFIELD = "Token Field";
+ public static final String SYMBOL = "Symbol";
+ public static final String VARIABLE = "Variable";
+ public static final String ATTACHEDSYM = "Attached Symbol";
+ public static final String PRINTPIECE = "Print Piece";
+ public static final String LOCAL = "Local Symbol";
+ public static final String SUBTABLE = "SubTable";
+
+ public void configure(IHighlightingConfigurationAcceptor acceptor) {
+ super.configure(acceptor);
+ addType(acceptor, CONTEXTFIELD, 50, 50, 0, SWT.ITALIC);
+ addType(acceptor, TOKENFIELD, 50, 50, 0, SWT.NORMAL);
+ addType(acceptor, SYMBOL, 50, 50, 50, TextStyle.DEFAULT_FONT_STYLE);
+ addType(acceptor, VARIABLE, 106, 62, 63, SWT.BOLD);
+ addType(acceptor, ATTACHEDSYM, 50, 50, 50, SWT.BOLD);
+ addType(acceptor, PRINTPIECE, 0,0,255, SWT.BOLD);
+ addType(acceptor, LOCAL, 40,40,40, SWT.ITALIC);
+ addType(acceptor, SUBTABLE, 192, 82, 5, SWT.NORMAL);
+ }
+
+ public void addType(IHighlightingConfigurationAcceptor acceptor, String s,
+ int r, int g, int b, int style) {
+ addType(acceptor, s, new RGB(r,g,b), style);
+ }
+
+ public void addType(IHighlightingConfigurationAcceptor acceptor, String s,
+ RGB rgb, int style) {
+ TextStyle textStyle = new TextStyle();
+ textStyle.setBackgroundColor(new RGB(255, 255, 255));
+ textStyle.setColor(rgb);
+ textStyle.setStyle(style);
+ acceptor.acceptDefaultHighlighting(s, s, textStyle);
+ }
+
+}
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/SleighTextEditComposer.xtend b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/SleighTextEditComposer.xtend
new file mode 100644
index 0000000000..d3deb8a5b0
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/SleighTextEditComposer.xtend
@@ -0,0 +1,11 @@
+package ghidra.xtext.sleigh.ui
+
+import org.eclipse.xtext.resource.SaveOptions
+import org.eclipse.xtext.ui.editor.model.edit.DefaultTextEditComposer
+
+class SleighTextEditComposer extends DefaultTextEditComposer {
+
+ override SaveOptions getSaveOptions() {
+ return SaveOptions.newBuilder().format().getOptions();
+ }
+}
\ No newline at end of file
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/SleighUiModule.xtend b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/SleighUiModule.xtend
new file mode 100644
index 0000000000..d7c14006c7
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/SleighUiModule.xtend
@@ -0,0 +1,53 @@
+/* ###
+ * 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.
+ */
+package ghidra.xtext.sleigh.ui
+
+import com.google.inject.Binder
+import ghidra.xtext.sleigh.ui.labeling.SleighLabelProvider
+import org.eclipse.jface.viewers.ILabelProvider
+import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
+import org.eclipse.xtext.ide.editor.syntaxcoloring.ISemanticHighlightingCalculator
+import org.eclipse.xtext.ui.editor.contentassist.ContentProposalLabelProvider
+import org.eclipse.xtext.ui.editor.hover.IEObjectHoverProvider
+import org.eclipse.xtext.ui.editor.model.edit.ITextEditComposer
+import org.eclipse.xtext.ui.editor.syntaxcoloring.IHighlightingConfiguration
+
+/**
+ * Use this class to register components to be used within the Eclipse IDE.
+ */
+@FinalFieldsConstructor
+class SleighUiModule extends AbstractSleighUiModule {
+
+ override void configureContentProposalLabelProvider(Binder binder) {
+ binder.bind(ILabelProvider).annotatedWith(ContentProposalLabelProvider).to(SleighLabelProvider);
+ }
+
+ def Class extends IHighlightingConfiguration> bindIHighlightingConfiguration() {
+ return SleighHighlightingConfiguration
+ }
+
+ def Class extends ISemanticHighlightingCalculator> bindISemanticHighlightingCalculator() {
+ return SleighHighlightingCalculator
+ }
+
+ def Class extends IEObjectHoverProvider> bindIEObjectHoverProvider() {
+ return SleighEObjectHoverProvider
+ }
+
+ def Class extends ITextEditComposer> bindITextEditComposer() {
+ return SleighTextEditComposer
+ }
+}
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/contentassist/SleighProposalProvider.xtend b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/contentassist/SleighProposalProvider.xtend
new file mode 100644
index 0000000000..1850198edf
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/contentassist/SleighProposalProvider.xtend
@@ -0,0 +1,24 @@
+/* ###
+ * 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.
+ */
+package ghidra.xtext.sleigh.ui.contentassist
+
+
+/**
+ * See https://www.eclipse.org/Xtext/documentation/304_ide_concepts.html#content-assist
+ * on how to customize the content assistant.
+ */
+class SleighProposalProvider extends AbstractSleighProposalProvider {
+}
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/labeling/SleighDescriptionLabelProvider.xtend b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/labeling/SleighDescriptionLabelProvider.xtend
new file mode 100644
index 0000000000..6e4b038557
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/labeling/SleighDescriptionLabelProvider.xtend
@@ -0,0 +1,83 @@
+/* ###
+ * 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.
+ */
+package ghidra.xtext.sleigh.ui.labeling
+
+import com.google.inject.Inject
+import org.eclipse.emf.ecore.EObject
+import org.eclipse.emf.ecore.resource.ResourceSet
+import org.eclipse.xtext.nodemodel.util.NodeModelUtils
+import org.eclipse.xtext.resource.IEObjectDescription
+import org.eclipse.xtext.resource.IReferenceDescription
+import org.eclipse.xtext.ui.label.DefaultDescriptionLabelProvider
+import ghidra.xtext.sleigh.sleigh.exportStmt
+import ghidra.xtext.sleigh.sleigh.pequation
+import ghidra.xtext.sleigh.sleigh.statement
+
+/**
+ * Provides labels for IEObjectDescriptions and IResourceDescriptions.
+ *
+ * See https://www.eclipse.org/Xtext/documentation/304_ide_concepts.html#label-provider
+ */
+
+/**
+ * Provides labels for a IEObjectDescriptions and IResourceDescriptions.
+ *
+ * see http://www.eclipse.org/Xtext/documentation.html#labelProvider
+ */
+class SleighDescriptionLabelProvider extends DefaultDescriptionLabelProvider {
+
+ @Inject ResourceSet rdp
+
+ // Labels and icons can be computed like this:
+ override String getText(Object element) {
+ var ele = element;
+
+ if (element instanceof IReferenceDescription) {
+ var o = rdp.getEObject(element.sourceEObjectUri,true);
+ if (o != null){
+ return containerLine(o);
+ }
+ return element.EReference.name
+ }
+ return super.getText(ele);
+ }
+
+ def String containerLine(EObject o) {
+ var c = o;
+ var text = NodeModelUtils.getNode(o).text
+ while (c.eContainer != null) {
+ if (c instanceof pequation) {
+ return NodeModelUtils.getNode(c).text
+ }
+ if (c instanceof statement ||
+ c instanceof exportStmt
+ ) {
+ text = NodeModelUtils.getNode(c).text
+ text = text.trim()
+ return text
+ }
+ c = c.eContainer
+ }
+ return text
+ }
+ override text(IEObjectDescription ele) {
+ return super.text(ele);
+ }
+
+ override image(IEObjectDescription ele) {
+ ele.EClass.name + '.gif'
+ }
+}
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/labeling/SleighLabelProvider.xtend b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/labeling/SleighLabelProvider.xtend
new file mode 100644
index 0000000000..50db77194d
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/labeling/SleighLabelProvider.xtend
@@ -0,0 +1,248 @@
+/* ###
+ * 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.
+ */
+package ghidra.xtext.sleigh.ui.labeling
+
+import com.google.inject.Inject
+import java.util.Iterator
+import org.eclipse.emf.common.util.EList
+import org.eclipse.emf.ecore.EObject
+import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider
+import org.eclipse.jface.viewers.StyledString
+import org.eclipse.xtext.naming.IQualifiedNameProvider
+import org.eclipse.xtext.naming.QualifiedName
+import org.eclipse.xtext.ui.label.DefaultEObjectLabelProvider
+import ghidra.xtext.sleigh.sleigh.DefineSym
+import ghidra.xtext.sleigh.sleigh.SUBTABLESYM
+import ghidra.xtext.sleigh.sleigh.VARSYM
+import ghidra.xtext.sleigh.sleigh.baseconstructor
+import ghidra.xtext.sleigh.sleigh.constraint
+import ghidra.xtext.sleigh.sleigh.constructprint
+import ghidra.xtext.sleigh.sleigh.contextfielddef
+import ghidra.xtext.sleigh.sleigh.fielddef
+import ghidra.xtext.sleigh.sleigh.integerValue
+import ghidra.xtext.sleigh.sleigh.macroDefine
+import ghidra.xtext.sleigh.sleigh.printpiece
+import ghidra.xtext.sleigh.sleigh.subconstructor
+import ghidra.xtext.sleigh.sleigh.varattach
+import ghidra.xtext.sleigh.sleigh.varnodedef
+
+import static extension org.eclipse.emf.ecore.util.EcoreUtil.*
+import static extension org.eclipse.xtext.EcoreUtil2.*
+
+/**
+ * Provides labels for EObjects.
+ *
+ * See https://www.eclipse.org/Xtext/documentation/304_ide_concepts.html#label-provider
+ */
+class SleighLabelProvider extends DefaultEObjectLabelProvider {
+ @Inject
+ new(AdapterFactoryLabelProvider delegate) {
+ super(delegate);
+ }
+
+ @Inject
+ private IQualifiedNameProvider nameProvider;
+
+ QualifiedName qn
+
+ EObject model
+
+ Iterator varatt
+
+ def String text(EObject eObject) {
+ qn = nameProvider.getFullyQualifiedName(eObject);
+ if(qn == null) {
+ return getObjectText(eObject);
+ }
+
+ return qn.toString();
+ }
+
+ def String getObjectText(EObject element) {
+ switch element {
+ macroDefine:
+ element.defineType // + element.definename.name + " = " + element.value
+ VARSYM:
+ element.name + " : " + getSizeStr((element.eContainer.eContainer as varnodedef).size)
+ SUBTABLESYM:
+ element.name
+ contextfielddef:
+ element.name
+ fielddef:
+ element.name
+ subconstructor:
+ doGetText(element.tableName) + ':'
+ baseconstructor:
+ ':' + doGetText(element.print)
+ constructprint:
+ formatString(element.printpieces)
+ constraint:
+ element.eClass.baseName
+ default: {
+ //System.out.println(element.class.simpleName)
+ element.class.simpleName
+ }
+ }
+ }
+
+ String possible;
+
+ def getfielddefText(fielddef element) {
+ // find all var attaches and display possible names
+ var len = getVarAttachesForElement(element)
+ return convertToStyledString('field ' + element.name).append(
+ " " + len + " " + ' (' + element.start.value + ',' + element.end.value + ')' +
+ (if(element.isSigned()) ' signed' else ''), StyledString::QUALIFIER_STYLER).append("\n\n" + possible);
+ }
+
+ def getcontextfielddefText(contextfielddef element) {
+ // find all var attaches and display possible names
+ var len = getVarAttachesForElement(element)
+ // is in a context, put out the name
+ return convertToStyledString('context ' + element.name).append(
+ " " + len + " " + ' (' + element.start.value + ',' + element.end.value + ')' +
+ (if(element.isSigned()) ' signed' else ''), StyledString::QUALIFIER_STYLER).append("\n\n" + possible);
+ }
+
+ protected def String getVarAttachesForElement(EObject element) {
+ model = element.eResource.contents.get(0);
+ varatt = model.eAllContents.filter(typeof(varattach));
+ possible = "";
+ var len = "";
+ while (varatt.hasNext) {
+ var next = varatt.next;
+ var vlist = next.valuelist.valuelist.listIterator;
+ while (vlist.hasNext) {
+ var v = vlist.next;
+ if (v.sym.equals(element)) {
+ var viter = next.vlist.varDefList.iterator;
+ possible = "attached to: "
+ while (viter.hasNext) {
+ var varname = viter.next;
+ var vref = varname.varpart;
+ if (vref != null) {
+ var vdef = vref.getContainerOfType(typeof(varnodedef));
+ if (vdef != null) {
+ var size = vdef.size.value;
+ len = size; // works even if is a $Define
+ }
+ possible = possible + vref.name + " ";
+ }
+ }
+ }
+ }
+ }
+ len
+ }
+
+ def getDefineSymText(DefineSym element) {
+ // find all var attaches and display possible names
+ var retStr = "";
+ model = element.eResource.contents.get(0);
+ var macDefs = model.eAllContents.filter(typeof(macroDefine));
+ possible = "";
+ var len = "";
+ while (macDefs.hasNext) {
+ var next = macDefs.next;
+ if (next.defineType.equals("@define")) {
+ if (next.definename.name == element.name) {
+ retStr = retStr + next.value + "\r\n"
+ }
+ }
+ }
+ if (retStr.length == 0) {
+ return super.doGetText(element);
+ }
+ return retStr;
+ }
+
+ override protected doGetText(Object element) {
+ if(element == null) return null;
+ // System.out.println("Label:" + element.class.baseName + " : " + element);
+ switch element {
+ macroDefine:
+ element.defineType // + element.definename.name + " = " + element.value
+ VARSYM:
+ element.name + " : " + getSizeStr((element.getContainerOfType(typeof(varnodedef))).size)
+ SUBTABLESYM:
+ element.name
+ contextfielddef:
+ getcontextfielddefText(element)
+ fielddef:
+ getfielddefText(element)
+ subconstructor:
+ doGetText(element.tableName) + ':'
+ baseconstructor:
+ ':' + doGetText(element.print)
+ constructprint:
+ formatString(element.printpieces)
+ constraint:
+ doGetText(element.sym)
+ DefineSym:
+ getDefineSymText(element)
+ default:
+ super.doGetText(element)
+ }
+ }
+
+ def getSizeStr(integerValue size) {
+ if (size.value != null) {
+ return size.value
+ }
+ if (size.sym != null) {
+ return size.sym.getText
+ }
+ return "?"
+ }
+
+ def getBaseName(Object element) {
+ element.class.name.substring(element.class.name.lastIndexOf('.') + 1)
+ }
+
+ def String formatString(EList list) {
+ var str = "";
+ var iter = list.iterator;
+ while (iter.hasNext) {
+ var piece = iter.next;
+ if (piece.str == null) {
+ if (piece.sym != null) {
+ str += piece.sym.sym;
+ } else {
+ str = '{empty}'
+ }
+ } else {
+ str += piece.str;
+ }
+ }
+ str
+ }
+
+ override protected doGetImage(Object element) {
+ // icons are stored in the 'icons' folder of this project.
+ // when adding such a folder, don't forget to add it to the 'bin.includes' section in the build.properties
+ switch element {
+// fielddef:
+// 'F-blue.png'
+// contextfielddef:
+// 'C-blue.png'
+// VARSYM:
+// 'F-blue.png'
+ default:
+ super.doGetImage(element)
+ }
+ }
+}
+
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/outline/SleighOutlineTreeProvider.xtend b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/outline/SleighOutlineTreeProvider.xtend
new file mode 100644
index 0000000000..dcb991bea8
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/outline/SleighOutlineTreeProvider.xtend
@@ -0,0 +1,82 @@
+/* ###
+ * 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.
+ */
+package ghidra.xtext.sleigh.ui.outline
+
+import java.util.ArrayList
+import org.eclipse.emf.ecore.EObject
+import org.eclipse.xtext.ui.editor.model.IXtextDocument
+import org.eclipse.xtext.ui.editor.outline.IOutlineNode
+import org.eclipse.xtext.ui.editor.outline.impl.DefaultOutlineTreeProvider
+import org.eclipse.xtext.util.concurrent.IUnitOfWork
+
+/**
+ * Customization of the default outline structure.
+ *
+ * See https://www.eclipse.org/Xtext/documentation/310_eclipse_support.html#outline
+ */
+class SleighOutlineTreeProvider extends DefaultOutlineTreeProvider {
+
+ // This controls the size of the outline
+ // Displaying the outline can be expensive
+ // TODO: figure out performance issue, possibly carefully
+ // building the outline based on Sleigh ideas not pure grammer
+
+ override createRoot(IXtextDocument document) {
+ if (document.numberOfLines < 100) {
+ super.createRoot(document);
+ } else {
+ new IOutlineNode() {
+
+ override getChildren() {
+ new ArrayList();
+ }
+
+ override getFullTextRegion() {
+ throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ }
+
+ override getImage() {
+ return null
+ }
+
+ override getParent() {
+ return null
+ }
+
+ override getSignificantTextRegion() {
+ throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ }
+
+ override getText() {
+ return "suppressed outline"
+ }
+
+ override hasChildren() {
+ return false
+ }
+
+ override getAdapter(Class adapter) {
+ throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ }
+
+ override readOnly(IUnitOfWork work) {
+ throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ }
+
+ }
+ }
+ }
+}
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/quickfix/SleighQuickfixProvider.xtend b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/quickfix/SleighQuickfixProvider.xtend
new file mode 100644
index 0000000000..3fb7075042
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/quickfix/SleighQuickfixProvider.xtend
@@ -0,0 +1,323 @@
+/* ###
+ * 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.
+ */
+package ghidra.xtext.sleigh.ui.quickfix
+
+import org.eclipse.emf.ecore.EObject
+import org.eclipse.emf.ecore.util.EcoreUtil
+import org.eclipse.xtext.EcoreUtil2
+import org.eclipse.xtext.diagnostics.Diagnostic
+import org.eclipse.xtext.resource.XtextResource
+import org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider
+import org.eclipse.xtext.ui.editor.quickfix.Fix
+import org.eclipse.xtext.ui.editor.quickfix.IssueResolutionAcceptor
+import org.eclipse.xtext.util.concurrent.IUnitOfWork
+import org.eclipse.xtext.validation.Issue
+import ghidra.xtext.sleigh.sleigh.Expression
+import ghidra.xtext.sleigh.sleigh.LOCALSYM
+import ghidra.xtext.sleigh.sleigh.Model
+import ghidra.xtext.sleigh.sleigh.SleighFactory
+import ghidra.xtext.sleigh.sleigh.VARSYM
+import ghidra.xtext.sleigh.sleigh.constraint
+import ghidra.xtext.sleigh.sleigh.constructor
+import ghidra.xtext.sleigh.sleigh.exprSym
+import ghidra.xtext.sleigh.sleigh.fielddef
+import ghidra.xtext.sleigh.sleigh.integerValue
+import ghidra.xtext.sleigh.sleigh.lhsvarnode
+import ghidra.xtext.sleigh.sleigh.localDefine
+import ghidra.xtext.sleigh.sleigh.macroOrPcode
+import ghidra.xtext.sleigh.sleigh.statement
+import ghidra.xtext.sleigh.sleigh.tokendef
+import ghidra.xtext.sleigh.sleigh.varattach
+import ghidra.xtext.sleigh.sleigh.varnodedef
+import ghidra.xtext.sleigh.sleigh.vnoderef
+
+import static extension org.eclipse.emf.ecore.util.EcoreUtil.*
+import static extension org.eclipse.xtext.EcoreUtil2.*
+
+/**
+ * Custom quickfixes.
+ *
+ * See https://www.eclipse.org/Xtext/documentation/310_eclipse_support.html#quick-fixes
+ */
+class SleighQuickfixProvider extends DefaultQuickfixProvider {
+
+ @Fix(Diagnostic::LINKING_DIAGNOSTIC)
+ def void createMissingVariable(Issue issue, IssueResolutionAcceptor acceptor) {
+ var message = issue.message;
+ var to = getToName(message);
+ var linkName = getLinkName(message);
+ var sname = macroOrPcode.simpleName.toString();
+ switch (to) {
+ case macroOrPcode.simpleName:
+ missingPseudoOp(issue, acceptor, to, linkName)
+ case lhsvarnode.simpleName:
+ createLocalVarnode(issue, acceptor, to, linkName)
+ case EObject.simpleName:
+ missingEObjectLink(issue, acceptor, to, linkName)
+ }
+ }
+
+ def missingPseudoOp(Issue issue, IssueResolutionAcceptor acceptor, String to, String linkName) {
+ acceptor.accept(
+ issue,
+ "Create pcodeop '" + linkName + "'",
+ "Create pcodeop '" + linkName + "'",
+ "",
+ [ element, context |
+ val currentEntity = EcoreUtil2.getContainerOfType(element,constructor)
+ val model = currentEntity.eContainer as Model
+ val newdef = SleighFactory::eINSTANCE.createpcodeopdef() => [
+ ops.add(SleighFactory::eINSTANCE.createUSEROPSYM() => [
+ name = context.xtextDocument.get(issue.offset, issue.length)
+ ])
+ ];
+ model.elements.add(model.elements.indexOf(currentEntity), newdef)
+ ]
+ );
+ }
+
+ def missingEObjectLink(Issue issue, IssueResolutionAcceptor acceptor, String to, String linkName) {
+ val modificationContext = getModificationContextFactory().createModificationContext(issue);
+ val xtextDocument = modificationContext.getXtextDocument();
+ xtextDocument.readOnly(
+ new IUnitOfWork.Void() {
+
+ override process(XtextResource state) throws Exception {
+ var cause = state.getResourceSet().getEObject(issue.getUriToProblem(), false);
+ if (cause instanceof constraint) {
+ missingConstraint(issue, acceptor, to, linkName, cause)
+ missingSubConstructor(issue, acceptor, to, linkName, cause)
+ }
+// switch cause {
+// case constraint:
+//
+// default: {
+// var x = cause
+// }
+// }
+ }
+ }
+ )
+ }
+
+ def missingConstraint(Issue issue, IssueResolutionAcceptor acceptor, String to, String linkName, EObject cause) {
+ acceptor.accept(
+ issue,
+ "Create fieldef '" + linkName + "'",
+ "Create fieldef '" + linkName + "'",
+ "",
+ [ element, context |
+ var root = EcoreUtil2.getRootContainer(cause) as Model;
+ // find fielddef
+ var tokendefs = root.getAllContentsOfType(typeof(tokendef))
+ if(tokendefs.size <= 0) return;
+ var tokendef = tokendefs.get(0);
+
+ // if found, put at end
+ val newfielddef = SleighFactory::eINSTANCE.createfielddef() => [
+ name = linkName
+ // TODO: try to figure out start/end
+ // TODO: ask start / end
+ start = SleighFactory.eINSTANCE.createintegerValue() => [
+ value = '0';
+ ]
+ end = SleighFactory.eINSTANCE.createintegerValue() => [
+ value = '0';
+ ]
+ ];
+ // add
+ tokendef.fields.tokens.add(newfielddef)
+ ]
+ );
+ }
+
+ def missingSubConstructor(Issue issue, IssueResolutionAcceptor acceptor, String to, String linkName, EObject cause) {
+ acceptor.accept(
+ issue,
+ "Create SubConstruct '" + linkName + "'",
+ "Create SubConstruct '" + linkName + "'",
+ "",
+ [ element, context |
+ var model = cause.rootContainer as Model;
+
+ var container = EcoreUtil2.getContainerOfType(cause, constructor)
+
+ // create subconstructor template
+ val sub = SleighFactory::eINSTANCE.createsubconstructor() => [
+ tableName = SleighFactory.eINSTANCE.createSUBTABLESYM() => [
+ name = linkName;
+ ]
+ print = SleighFactory.eINSTANCE.createconstructprint() => [
+ var pp = SleighFactory.eINSTANCE.createprintpiece() => [
+ str = ""
+ ]
+ printpieces.add(pp)
+ is = SleighFactory.eINSTANCE.createisKeyword() => []
+ ]
+ match = SleighFactory.eINSTANCE.createpequation() => [
+ constraints = SleighFactory.eINSTANCE.createconstraint() => [
+ isepsilon = true
+ ]
+ ]
+ body = SleighFactory.eINSTANCE.creatertlbody() => [
+ unimpl = true
+ ]
+ ];
+ // add before this instance
+ model.elements.add(model.elements.indexOf(container), sub)
+ ]
+ );
+ }
+
+ def createLocalVarnode(Issue issue, IssueResolutionAcceptor acceptor, String to, String linkName) {
+ acceptor.accept(
+ issue,
+ "Create local '" + linkName + "'",
+ "Create local '" + linkName + "'",
+ "",
+ [ element, context |
+ // find size of first element if it can
+ val s = findElementSize(element);
+ if (s == null) {
+ val newdef = SleighFactory::eINSTANCE.createassignSym() => [
+ local = SleighFactory::eINSTANCE.createlocalDefine() => [
+ sym = SleighFactory.eINSTANCE.createLOCALSYM() => [
+ name = linkName;
+ ]
+ ]
+ ];
+ element.replace(newdef);
+ } else {
+ val newdef = SleighFactory::eINSTANCE.createassignSym() => [
+ local = SleighFactory::eINSTANCE.createlocalDefine() => [
+ sym = SleighFactory.eINSTANCE.createLOCALSYM() => [
+ name = linkName;
+ ]
+ size = SleighFactory.eINSTANCE.createintegerValue() => [
+ value = s.value;
+ sym = s.sym;
+ ]
+ ]
+ ];
+ element.replace(newdef);
+ }
+ ]
+ );
+ }
+
+ def integerValue findElementSize(EObject element) {
+ val currentEntity = EcoreUtil2.getContainerOfType(element, statement)
+ val rhs = currentEntity.rhs;
+ val s = findSize(rhs);
+ return s;
+ }
+
+ var integerValue len;
+
+ def integerValue findSize(Expression rhs) {
+ len = null;
+ if (rhs instanceof exprSym) {
+ return getExprSymLength(rhs);
+ }
+ var vlist = rhs.getAllContentsOfType(typeof(exprSym));
+ vlist.forEach [ it |
+ getExprSymLength(it)
+ ]
+ return len;
+ }
+
+ def getExprSymLength(exprSym sym) {
+ var node = sym.vnode;
+ switch node {
+ VARSYM: {
+ var def = node.getContainerOfType(typeof(varnodedef));
+ if (def != null && def.size != null) {
+ if (len == null) {
+ len = def.size;
+ }
+ } else if (len != def.size) {
+ len = null;
+ }
+ }
+ fielddef: {
+ len = findVarAttachLen(node);
+ }
+ LOCALSYM: {
+ var ldef = node.getContainerOfType(typeof(localDefine));
+ if (ldef != null && ldef.size != null) {
+ if (len == null) {
+ len = ldef.size;
+ }
+ } else if (len != ldef.size) {
+ len = null;
+ }
+ }
+ }
+ }
+
+ def integerValue findVarAttachLen(fielddef fdef) {
+ // find all var attaches and display possible names
+ var model = fdef.eResource.contents.get(0);
+ var varatt = model.eAllContents.filter(typeof(varattach));
+ while (varatt.hasNext) {
+ var next = varatt.next;
+ var vlist = next.valuelist.valuelist.listIterator;
+ while (vlist.hasNext) {
+ var v = vlist.next;
+ if (v.sym.equals(fdef)) {
+ var viter = next.vlist.varDefList.iterator;
+ while (viter.hasNext) {
+ var varname = viter.next;
+ var vref = varname.varpart;
+ if (vref != null) {
+ var vdef = vref.getContainerOfType(typeof(varnodedef));
+ if (vdef != null) {
+ var size = vdef.size;
+ return size;
+ }
+ }
+ }
+ }
+ }
+
+ }
+ return null;
+ }
+
+ def findVnodeSize(vnoderef ref) {
+ System.out.println(' printit ' + ref.ID);
+ }
+
+ def String getLinkName(String str) {
+ var end = str.lastIndexOf('\'')
+ var start = str.lastIndexOf('\'', end - 1)
+ return str.substring(start + 1, end)
+ }
+
+ def String getToName(String str) {
+ val refString = "reference to ";
+
+ var index = str.indexOf(refString);
+ if (index == -1) {
+ return null;
+ }
+ var start = index + refString.length;
+ var refStr = str.substring(start);
+ refStr = refStr.substring(0, refStr.indexOf(' '));
+ return refStr;
+ }
+
+}
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/.launch/Generate Sleigh (sleigh) Language Infrastructure.launch b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/.launch/Generate Sleigh (sleigh) Language Infrastructure.launch
new file mode 100644
index 0000000000..0eef2d27b4
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/.launch/Generate Sleigh (sleigh) Language Infrastructure.launch
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/.launch/Launch Runtime Eclipse.launch b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/.launch/Launch Runtime Eclipse.launch
new file mode 100644
index 0000000000..e03e3b4d49
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/.launch/Launch Runtime Eclipse.launch
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/META-INF/MANIFEST.MF b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..9128be7ba4
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/META-INF/MANIFEST.MF
@@ -0,0 +1,31 @@
+Manifest-Version: 1.0
+Automatic-Module-Name: ghidra.xtext.sleigh
+Bundle-ManifestVersion: 2
+Bundle-Name: ghidra.xtext.sleigh
+Bundle-Vendor: My Company
+Bundle-Version: 1.0.0.qualifier
+Bundle-SymbolicName: ghidra.xtext.sleigh; singleton:=true
+Bundle-ActivationPolicy: lazy
+Require-Bundle: org.eclipse.xtext,
+ org.eclipse.xtext.xbase,
+ org.eclipse.equinox.common;bundle-version="3.5.0",
+ org.eclipse.emf.ecore,
+ org.eclipse.xtext.xbase.lib;bundle-version="2.14.0",
+ org.eclipse.xtext.util,
+ org.eclipse.emf.common,
+ org.eclipse.xtend.lib;bundle-version="2.14.0",
+ org.antlr.runtime;bundle-version="[3.2.0,3.2.1)"
+Bundle-RequiredExecutionEnvironment: JavaSE-11
+Export-Package: ghidra.xtext.sleigh.formatting2,
+ ghidra.xtext.sleigh,
+ ghidra.xtext.sleigh.sleigh.impl,
+ ghidra.xtext.sleigh.validation,
+ ghidra.xtext.sleigh.scoping,
+ ghidra.xtext.sleigh.sleigh,
+ ghidra.xtext.sleigh.serializer,
+ ghidra.xtext.sleigh.parser.antlr.internal,
+ ghidra.xtext.sleigh.services,
+ ghidra.xtext.sleigh.sleigh.util,
+ ghidra.xtext.sleigh.generator,
+ ghidra.xtext.sleigh.parser.antlr
+Import-Package: org.apache.log4j
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/build.properties b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/build.properties
new file mode 100644
index 0000000000..18d540bf6c
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/build.properties
@@ -0,0 +1,20 @@
+source.. = src/,\
+ src-gen/,\
+ xtend-gen/
+bin.includes = model/generated/,\
+ .,\
+ META-INF/,\
+ plugin.xml
+bin.excludes = **/*.mwe2,\
+ **/*.xtend
+additional.bundles = org.eclipse.xtext.xbase,\
+ org.eclipse.xtext.common.types,\
+ org.eclipse.xtext.xtext.generator,\
+ org.eclipse.emf.codegen.ecore,\
+ org.eclipse.emf.mwe.utils,\
+ org.eclipse.emf.mwe2.launch,\
+ org.eclipse.emf.mwe2.lib,\
+ org.objectweb.asm,\
+ org.apache.commons.logging,\
+ org.apache.log4j,\
+ com.ibm.icu
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/plugin.xml b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/plugin.xml
new file mode 100644
index 0000000000..26c699fb0e
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/plugin.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/GenerateSleigh.mwe2 b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/GenerateSleigh.mwe2
new file mode 100644
index 0000000000..b23e05b85b
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/GenerateSleigh.mwe2
@@ -0,0 +1,58 @@
+module ghidra.xtext.sleigh.GenerateSleigh
+
+import org.eclipse.xtext.xtext.generator.*
+import org.eclipse.xtext.xtext.generator.model.project.*
+
+var rootPath = ".."
+
+Workflow {
+
+ component = XtextGenerator {
+ configuration = {
+ project = StandardProjectConfig {
+ baseName = "ghidra.xtext.sleigh"
+ rootPath = rootPath
+ runtimeTest = {
+ enabled = true
+ }
+ eclipsePlugin = {
+ enabled = true
+ }
+ eclipsePluginTest = {
+ enabled = true
+ }
+ createEclipseMetaData = true
+ }
+ code = {
+ encoding = "UTF-8"
+ lineDelimiter = "\n"
+ fileHeader = "/*\n * generated by Xtext \${version}\n */"
+ }
+ }
+ language = StandardLanguage {
+ name = "ghidra.xtext.sleigh.Sleigh"
+ fileExtensions = "slaspec,sinc"
+
+ serializer = {
+ generateStub = false
+ }
+ validator = {
+ // composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator"
+ // Generates checks for @Deprecated grammar annotations, an IssueProvider and a corresponding PropertyPage
+ generateDeprecationValidation = true
+ }
+ fragment = ui.labeling.LabelProviderFragment2 {}
+
+ fragment = formatting.Formatter2Fragment2 {}
+
+ fragment = ui.quickfix.QuickfixProviderFragment2 {}
+
+ // enable rename refactoring
+ fragment = ui.refactoring.RefactorElementNameFragment2 {}
+
+ junitSupport = {
+ junitVersion = "5"
+ }
+ }
+ }
+}
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/Sleigh.xtext b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/Sleigh.xtext
new file mode 100644
index 0000000000..d5d22878df
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/Sleigh.xtext
@@ -0,0 +1,1142 @@
+/* ###
+ * 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.
+ */
+
+grammar ghidra.xtext.sleigh.Sleigh hidden(WS, ML_COMMENT, SL_COMMENT)
+
+generate sleigh "http://www.xtext.ghidra/sleigh/Sleigh"
+
+import "http://www.eclipse.org/emf/2002/Ecore" as ecore
+
+Model:
+ elements+=spec*;
+
+Import:
+ '@include' importURI = STRING;
+
+macroDefine :
+ defineType='@define' definename=DefineSym value=DefineValue
+ |
+ defineType='@if' tests=DefineTest
+ |
+ defineType='@ifdef' sym=DefineSym
+ |
+ defineType='@ifndef' sym=DefineSym
+ |
+ defineType='@elif' ( (isdefined+=IsDefined (OP_BOOL_OR isdefined+=IsDefined )*) | (symref=DefineSym OP_EQUAL value=STRING))
+ |
+ defineType='@else'
+ |
+ defineType='@endif'
+;
+
+IsDefined:
+ 'defined' '(' DefineSym')'
+;
+
+DefineTest:
+ ( '(' test=DefineTest ')'
+ | symref=DefineSym OP_EQUAL value=(STRING|intvalue|ID)
+ | isdefined=IsDefined ) ( (OP_BOOL_AND andtest=DefineTest) | (OP_BOOL_OR ortest=DefineTest) )?
+;
+
+
+DefineValue:
+// STRING | ( sym=[constraintsym] | OP_AND | OP_OR | ';' | '...' | '(' | ')' | '=' | '<' | '>' | OP_LESSEQUAL| OP_GREATEQUAL )+
+ STRING | intvalue // | ( OP_AND | OP_OR | ';' | '...' | '(' | ')' | '=' | '<' | '>' /* | OP_LESSEQUAL | OP_GREATEQUAL */ )+
+;
+
+spec:
+ iswith?='with' withTableName+=(SUBTABLESYM)* ':' withmatch+=pequation '{' elements+=spec+ '}'
+ | Import
+ | macroDefine
+ | endiandef
+ | aligndef
+ | definition
+ | constructorlike
+;
+
+endiandef :
+ 'define' 'endian' '=' (is_big?='big' | is_little?='little' | is_define=DefineUsage) ';'
+;
+
+definition :
+ tokendef
+ | contextdef
+ | spacedef
+ | varnodedef
+ | bitrangedef
+ | pcodeopdef
+ | valueattach
+ | nameattach
+ | varattach
+// // | error ';'
+;
+//
+constructorlike:
+ constructor
+ | macrodef
+ //| error '}' // { slgh->resetConstructors(); }
+;
+//
+//
+aligndef :
+ 'define' 'alignment' '=' align=integerValue ';' // { slgh->setAlignment(*$4); delete $4; }
+;
+
+tokendef :
+ 'define' 'token' ID '(' size=integerValue ')' fields=tokenprop ';' // {}
+;
+//
+tokenprop:
+ tokens+=(
+ fielddef
+ // Don't like allowing macros use internal to blocks...
+ | macroUse)+ // { $$ = slgh->defineToken($3,$5); }
+;
+
+contextdef:
+ ('define' 'context' name=[VARSYM]) fields=contextprop ';' // {}
+;
+
+contextprop :
+ {contextDefs}
+ (contextDefs+=(
+ contextfielddef
+ // Don't like allowing macros use internal to blocks...
+ |macroUse
+ ))*
+;
+
+fielddef:
+ name=ID '=' '(' start=integerValue ',' end=integerValue ')' (signed?='signed' | hex?='hex' | dec?='dec')* //{ $$ = new FieldQuality($1 $4 $6); }
+;
+
+macroUse:
+ define=macroDefine
+;
+
+contextfielddef:
+ name=ID '=' '(' start=integerValue ',' end=integerValue ')' (signed?='signed' | noflow?='noflow' | hex?='hex' | dec?='dec')*
+;
+
+spacedef:
+ spaceprop ';'
+;
+
+spaceprop :
+ 'define' 'space' space=SPACESYM
+ (('type' '=' isram?='ram_space'
+ | 'type' '=' isregister?='register_space'
+ | 'size' '=' size=integerValue
+ | 'wordsize' '=' wordsize=integerValue
+ | isdefault?='default'))*
+;
+
+varnodedef :
+ 'define' (space=[SPACESYM] | define=DefineUsage) 'offset' '=' offset=integerValue 'size' '=' size=integerValue vars=vardeflist ';'
+;
+
+vardeflist:
+ '[' varDefList += vardef+ ']'
+ | varDefList += vardef
+;
+
+vardef:
+ varname=VARSYM
+ | isempty?=EMPTYVARSYM
+ | macroUse
+;
+
+bitrangedef :
+ 'define' 'bitrange' list=bitrangelist ';';
+
+bitrangelist:
+ bitrangeEntries+=bitrangesingle+
+ // | bitrangelist bitrangesingle;
+;
+
+bitrangesingle:
+ name=ID '=' vnode=[VARSYM] '[' start=integerValue ',' end=integerValue ']'
+;
+
+pcodeopdef :
+ 'define' 'pcodeop' ops+=(USEROPSYM)+ ';'
+;
+
+valueattach :
+ 'attach' 'values' valuelist=valuesymlist blist=intblist ';'
+;
+
+nameattach :
+ 'attach' 'names' valuelist=namesymlist slist=anystringlist ';'
+;
+
+varattach :
+ 'attach' 'variables' valuelist=varsymlist vlist=varlist ';'
+;
+
+macrodef:
+ 'macro' name=QualifiedName '(' args=oplist ')' body=rtlbody
+;
+
+QualifiedName: ID ('.' ID)* ;
+
+
+rtlbody:
+ '{' body=xrtl '}'
+ | unimpl?='unimpl'
+;
+
+constructor:
+ baseconstructor | subconstructor
+;
+
+baseconstructor:
+ ':' print=constructprint match=pequation (cblock=contextblock)? body=rtlbody
+;
+
+subconstructor:
+ tableName=SUBTABLESYM ':' print=constructprint match=pequation (cblock=contextblock)? body=rtlbody // { slgh->buildConstructor($1,$3,$4,$5); }
+;
+
+constructprint:
+ {constructprint}
+ printpieces+=(printpiece)* is=isKeyword
+;
+
+isKeyword: {isKeyword} 'is';
+
+printpiece:
+ str=OP_XOR | str=STRING | str=charsymbol | sym=aliasSym | str=Keywords
+;
+
+Keywords:
+ 'call' | 'if' | 'define' | 'goto' | 'return' | 'offset' | 'size' | 'round' | 'abs' | 'dec' | 'instruction'
+;
+
+aliasSymID:
+ aliasSym
+;
+
+aliasSym:
+ sym=ID
+;
+
+subconstructdef:
+ SUBTABLESYM
+;
+
+pexpression :
+ pexprAdd;
+
+pexprAdd:
+ pexprSub ({pexprAdd.left=current} op='+' right=pexprSub)*;
+
+pexprSub:
+ pexprMult ({pexprSub.left=current} op='-' right=pexprMult)*;
+
+pexprMult:
+ pexprLeft ({pexprMult.left=current} op='*' right=pexprLeft)*;
+
+pexprLeft:
+ pexprRight ({pexprLeft.left=current} op=OP_LEFT right=pexprRight)*;
+
+pexprRight:
+ pexprAnd ({pexprRight.left=current} op=OP_RIGHT right=pexprAnd)*;
+
+pexprAnd:
+ pexprOr ({pexprAnd.left=current} (op=OP_DAND | op=OP_AND) right=pexprOr)*;
+
+pexprOr:
+ pexprXor ({pexprOr.left=current} (op=OP_DOR | op=OP_OR) right=pexprXor)*;
+
+pexprXor:
+ pexprDiv ({pexprXor.left=current} (op=OP_DXOR | op=OP_XOR) right=pexprDiv)*;
+
+pexprDiv:
+ pexprNegate ({pexprDiv.left=current} op='/' right=pexprNegate)*;
+
+pexprNegate:
+ pexprInvert | ({pexprNegate} op='-' left=pexprInvert);
+
+pexprInvert:
+ singlePexpression | ({pexprInvert} op='~' left=singlePexpression);
+
+singlePexpression:
+ intval=integerValue // { $$ = new ConstantValue(*$1); delete $1; }
+ | is_instruction?='instruction'
+ | is_epsilon?='epsilon'
+ | sym=pexprSym
+ | is_paren='(' right=pexpression ')'
+;
+
+constraintPexpression :
+ constraintAdd;
+
+constraintAdd:
+ constraintSub ({constraintAdd.left=current} op='+' right=constraintSub)*;
+
+constraintSub:
+ constraintMult ({constraintSub.left=current} op='-' right=constraintMult)*;
+
+constraintMult:
+ constraintLeft ({constraintMult.left=current} op='*' right=constraintLeft)*;
+
+constraintLeft:
+ constraintRight ({constraintLeft.left=current} op=OP_LEFT right=constraintRight)*;
+
+constraintRight:
+ constraintAnd ({constraintRight.left=current} op=OP_RIGHT right=constraintAnd)*;
+
+constraintAnd:
+ constraintOr ({constraintAnd.left=current} (op=OP_DAND) right=constraintOr)*;
+
+constraintOr:
+ constraintXor ({constraintOr.left=current} (op=OP_DOR) right=constraintXor)*;
+
+constraintXor:
+ constraintDiv ({constraintXor.left=current} (op=OP_DXOR) right=constraintDiv)*;
+
+constraintDiv:
+ constraintNegate ({constraintDiv.left=current} op='/' right=constraintNegate)*;
+
+constraintNegate:
+ constraintInvert | ({constraintNegate} op='-' expr=constraintInvert)
+;
+
+constraintInvert:
+ constraintSinglePexpression | ({constraintInvert} op='~' expr=constraintSinglePexpression)
+;
+
+constraintSinglePexpression:
+ intval=integerValue
+ | is_instruction?='instruction'
+ | is_epsilon?='epsilon'
+ | sym=pexprSym
+ | is_subexpr='(' right=constraintPexpression ')'
+;
+
+
+pexprSym:
+ inst_start?='inst_start' | inst_next?='inst_next' | sym=[specificsymbol]
+;
+
+pequation :
+ constraints=pNextSet
+;
+
+
+pNextSet:
+ pAnd ({pNextSet.left=current} op=';' right=pAnd)*;
+
+pAnd:
+ pOr ({pAnd.left=current} op=OP_AND right=pOr)*;
+
+pOr:
+ elleqRight ({pOr.left=current} op=OP_OR right=elleqRight)*;
+
+elleqRight:
+ elleqLeft ({elleqRight.left=current} op='...')?;
+
+elleqLeft:
+ ('...')? atomic;
+
+elleq:
+ ('...') atomic
+ | atomic ('...')
+;
+
+atomic:
+ constraint
+ | define=DefineUsage
+ | '(' right=pequation ')'
+;
+
+constraint:
+ sym=[constraintvalue] compareOp='=' value=constraintPexpression
+ | sym=[constraintvalue] compareOp=OP_NOTEQUAL value=constraintPexpression
+ | sym=[constraintvalue] compareOp='<' value=constraintPexpression
+ | sym=[constraintvalue] compareOp=OP_LESSEQUAL value=constraintPexpression
+ | sym=[constraintvalue] compareOp='>' value=constraintPexpression
+ | sym=[constraintvalue] compareOp=OP_GREATEQUAL value=constraintPexpression
+ | sym=[constraintsym]
+ | isinstruction?='instruction'
+ | isepsilon?='epsilon'
+;
+
+constraintvalue:
+ OPERANDSYM
+ | VALUESYM
+ | CONTEXTSYM
+ | NAMESYM
+ | VARLISTSYM
+;
+
+constraintsym:
+ OPERANDSYM
+ | SUBTABLESYM
+ | CONTEXTSYM
+ | NAMESYM
+ | VARLISTSYM
+;
+
+contextblock:
+ ('[' block=contextlist ']')
+;
+
+contextlist:
+ (entry+=contextentry ';')+;
+
+contextentry:
+ (lhs=[consymref] '=' rhs=pexpression)
+ | ('globalset' '(' tsym=globalLoc ',' csym=[CONTEXTSYM] ')')
+ | 'local' OPERANDSYM '=' rhs=pexpression
+;
+
+globalLoc:
+ inst_start?=STARTSYM | inst_next?=ENDSYM | tsym=[globalLocRef]
+;
+
+globalLocRef:
+ // familysymbol
+ VALUESYM
+ | CONTEXTSYM
+ | NAMESYM
+ | VARLISTSYM
+ // specificsymbol
+ | VARSYM
+ | LOCALSYM
+ | CONTEXTSYM | TOKENSYM // should really be special, must appear in match pattern
+ | SPECSYM
+ | OPERANDSYM
+ | STARTSYM
+ | ENDSYM
+ | SUBTABLESYM
+ | aliasSym
+;
+
+consymref:
+ CONTEXTSYM | OPERANDSYM | aliasSym
+;
+
+section_def:
+ OP_LEFT SECTIONSYM OP_RIGHT
+;
+
+
+xrtl:
+ statements=rtlmid
+ ( export=exportStmt (additionalStatements=rtlmid))?
+;
+
+exportStmt:
+ 'export' (resultsize=sizedstar)? result=exportedSym ';'
+;
+
+exportedSym:
+ symref=[exportvarnode]
+ | is_start?='inst_start'
+ | is_next?='inst_next'
+ | isaddrof?=OP_AND varnode=varnode
+ | isaddrof?=OP_AND sizeOpColon size=integerValue varnode=varnode
+ | const=integerValue sizeOpColon size=integerValue
+ | define=DefineUsage
+;
+
+sizeOpColon:
+ ':'
+;
+
+rtlmid:
+ {rtlmid}
+ (rtllist+=statement | macro+=macroUse)*
+ // Don't like allowing macros use internal to blocks...
+;
+
+statement :
+ section_name=section_def
+ | lhs=assignSym '=' rhs=expr semi=';'
+ | ldef=localDefine semi=';'
+ | ptrsize=sizedstar lhsexpr=expr '=' rhs=expr semi=';'
+ | lhs=assignSym '[' start=integerValue ',' end=integerValue ']' '=' rhs=expr semi=';'
+ | isbuild?='build' (is_instr?='instruction' | def=[SUBTABLESYM]) semi=';'
+ | iscross?='crossbuild' crossvnode=varnode ',' (crossname=[SECTIONSYM] | crossstring=STRING) semi=';'
+ | isdelay?='delayslot' '(' delayslot=integerValue ')' semi=';'
+ | isgoto?='goto' dest=jumpdest semi=';'
+ | isif?='if' ifexpr=expr 'goto' dest=jumpdest semi=';'
+ | isgoto?='goto' '[' gotodest=expr ']' semi=';'
+ | iscall?='call' dest=jumpdest semi=';'
+ | iscallind?='call' '[' dest=expr ']' semi=';'
+ | isreturn?='return' semi=';'
+ | isreturn?='return' '[' dest=expr ']' semi=';'
+ | macro=[macroOrPcode] args=paramlist semi=';'
+ | label=label
+;
+
+assignSym:
+ symref=[lhsvarnode] | local=localDefine | define=DefineUsage
+;
+
+localDefine:
+ 'local' sym=LOCALSYM | 'local'? sym=LOCALSYM sizeOpColon size=integerValue
+// hasLocalDef?='local' sym=LOCALSYM | hasLocalDef?='local'? sym=LOCALSYM sizeOpColon size=integerValue
+;
+
+macroOrPcode:
+ MACROSYM
+ | USEROPSYM
+ | BITSYM
+ | VARSYM
+ | LOCALSYM
+ | SPECSYM
+ | OPERANDSYM
+ | SUBTABLESYM
+ | MACROPARAMSYM
+ | TOKENSYM // allow subpiece
+ | aliasSym
+;
+
+expr returns Expression:
+ exprAdd;
+
+exprAdd returns Expression:
+ exprMinus ({exprrAdd.left=current} '+' right=exprMinus)*;
+
+exprMinus returns Expression:
+ exprEqual ({exprMinus.left=current} '-' right=exprEqual)*;
+
+exprEqual returns Expression:
+ exprNotEqual ({exprEqual.left=current} OP_EQUAL right=exprNotEqual)*;
+
+exprNotEqual returns Expression:
+ exprLess ({exprNotEqual.left=current} OP_NOTEQUAL right=exprLess)*;
+
+exprLess returns Expression:
+ exprGtEqual ({exprLess.left=current} '<' right=exprGtEqual)*;
+
+exprGtEqual returns Expression:
+ exprLtEqual ({exprGtEqual.left=current} OP_GREATEQUAL right=exprLtEqual)*;
+
+exprLtEqual returns Expression:
+ exprGt ({exprLtEqual.left=current} OP_LESSEQUAL right=exprGt)*;
+
+exprGt returns Expression:
+ exprSLess ({exprGt.left=current} '>' right=exprSLess)*;
+
+exprSLess returns Expression:
+ exprSGtEqual ({exprSLess.left=current} OP_SLESS right=exprSGtEqual)*;
+
+exprSGtEqual returns Expression:
+ exprSLtEqual ({exprSGtEqual.left=current} OP_SGREATEQUAL right=exprSLtEqual)*;
+
+exprSLtEqual returns Expression:
+ exprSGt ({exprSLtEqual.left=current} OP_SLESSEQUAL right=exprSGt)*;
+
+exprSGt returns Expression:
+ exprXor ({exprSGt.left=current} OP_SGREAT right=exprXor)*;
+
+exprXor returns Expression:
+ exprAnd ({exprXor.left=current} OP_XOR right=exprAnd)*;
+
+exprAnd returns Expression:
+ exprOr ({exprAnd.left=current} OP_AND right=exprOr)*;
+
+exprOr returns Expression:
+ exprLeft ({exprOr.left=current} OP_OR right=exprLeft)*;
+
+exprLeft returns Expression:
+ exprRight ({exprLeft.left=current} OP_LEFT right=exprRight)*;
+
+exprRight returns Expression:
+ exprSRight ({exprRight.left=current} OP_RIGHT right=exprSRight)*;
+
+exprSRight returns Expression:
+ exprMult ({exprSRight.left=current} OP_SRIGHT right=exprMult)*;
+
+exprMult returns Expression:
+ exprDiv ({exprMult.left=current} '*' right=exprDiv)*;
+
+exprDiv returns Expression:
+ exprSDiv ({exprDiv.left=current} '/' right=exprSDiv)*;
+
+exprSDiv returns Expression:
+ exprRem ({exprSDiv.left=current} OP_SDIV right=exprRem)*;
+
+exprRem returns Expression:
+ exprSRem ({exprRem.left=current} '%' right=exprSRem)*;
+
+exprSRem returns Expression:
+ exprBoolXor ({exprSRem.left=current} OP_SREM right=exprBoolXor)*;
+
+exprBoolXor returns Expression:
+ exprBoolAnd ({exprBoolXor.left=current} OP_BOOL_XOR right=exprBoolAnd)*;
+
+exprBoolAnd returns Expression:
+ exprBoolOr ({exprBoolAnd.left=current} OP_BOOL_AND right=exprBoolOr)*;
+
+exprBoolOr returns Expression:
+ exprFEqual ({exprBoolOr.left=current} OP_BOOL_OR right=exprFEqual)*;
+
+exprFEqual returns Expression:
+ exprFNotEqual ({exprFEqual.left=current} OP_FEQUAL right=exprFNotEqual)*;
+
+exprFNotEqual returns Expression:
+ exprFLess ({exprFNotEqual.left=current} OP_FNOTEQUAL right=exprFLess)*;
+
+exprFLess returns Expression:
+ exprFGt ({exprFLess.left=current} OP_FLESS right=exprFGt)*;
+
+exprFGt returns Expression:
+ exprFLessEqual ({exprFGt.left=current} OP_FGREAT right=exprFLessEqual)*;
+
+exprFLessEqual returns Expression:
+ exprFGtEqual ({exprFLessEqual.left=current} OP_FLESSEQUAL right=exprFGtEqual)*;
+
+exprFGtEqual returns Expression:
+ exprFAdd ({exprFGtEqual.left=current} OP_FGREATEQUAL right=exprFAdd)*;
+
+exprFAdd returns Expression:
+ exprFSub ( {exprFAdd.left=current} OP_FADD right=exprFSub)*;
+
+exprFSub returns Expression:
+ exprFMult ({exprFSub.left=current} OP_FSUB right=exprFMult)*;
+
+exprFMult returns Expression:
+ exprFDiv ({exprFMult.left=current} OP_FMULT right=exprFDiv)*;
+
+exprFDiv returns Expression:
+ exprNegate ({exprFDiv.left=current} OP_FDIV right=exprNegate)*;
+
+exprNegate returns Expression:
+ exprFNegate | ({exprNegate} '-' expr=exprFNegate)
+;
+
+exprFNegate returns Expression:
+ exprInvert | ({exprFNegate} OP_FSUB expr=exprInvert)
+;
+
+exprInvert returns Expression:
+ exprNot | ({exprNegate} '~' expr=exprNot)
+;
+
+exprNot returns Expression:
+ exprLoad | ({exprNegate} '!' expr=exprLoad)
+;
+
+exprLoad returns Expression:
+ exprSingle | ({exprLoad} loc=sizedstar expr=exprSingle)
+;
+
+exprSingle returns Expression:
+ vnode=exprSym
+ | '(' right=expr ')'
+ | pcodeop='unordered' '(' op1=expr ',' op2=expr ')'
+ | pcodeop='abs' '(' right=expr ')'
+ | pcodeop='sqrt' '(' right=expr ')'
+ | pcodeop='sext' '(' right=expr ')'
+ | pcodeop='zext' '(' right=expr ')'
+ | pcodeop='carry' '(' op1=expr ',' op2=expr ')'
+ | pcodeop='scarry' '(' op1=expr ',' op2=expr ')'
+ | pcodeop='sborrow' '(' op1=expr ',' op2=expr ')'
+ | pcodeop='float2float' '(' op1=expr ')'
+ | pcodeop='int2float' '(' op1=expr ')'
+ | pcodeop='nan' '(' op1=expr ')'
+ | pcodeop='trunc' '(' op1=expr ')'
+ | pcodeop='ceil' '(' op1=expr ')'
+ | pcodeop='floor' '(' op1=expr ')'
+ | pcodeop='round' '(' op1=expr ')'
+ | pcodeop='cpool' '(' op1=expr ',' op2=expr ',' op3=expr ')'
+ | pcodeop='newobject' '(' op1=newObjParams ')'
+ | op=[macroOrPcode] op1=paramlist
+;
+
+newObjParams:
+ ((parameters+=expr) (',' parameters+=expr)*)
+;
+
+exprSym:
+ vnode=[vnoderef]
+ | vnode=[specificsymbol] sizeOpColon size=integerValue
+ | vnode=[specificsymbol] '[' start=integerValue ',' end=integerValue ']'
+ | inode=integervarnode
+;
+
+vnoderef:
+ BITSYM
+ | VARSYM
+ | LOCALSYM
+ | SPECSYM
+ | OPERANDSYM
+ | assignSym
+ | aliasSym
+;
+
+
+sizedstar:
+ '*' '[' space=spacename ']' sizeOpColon size=integerValue
+ | '*' '[' space=spacename']'
+ | '*' sizeOpColon size=integerValue
+ | isdefault?='*'
+;
+
+spacename:
+ const?='const' | space=[SPACESYM]
+;
+
+jumpdest:
+ inst_start=STARTSYM
+ | inst_end=ENDSYM
+ | const=integerValue
+ | const=integerValue '[' space=spacename ']'
+ | dest=[SUBTABLESYM]
+ | label='<' dest=[label] '>'
+;
+
+varnode:
+ val=[specificsymbol]
+ | integervarnode
+;
+
+integervarnode:
+ reladdr=STARTSYM
+ | reladdr=ENDSYM
+ | const=integerValue
+ | const=integerValue sizeOpColon size=integerValue
+ | isaddrof=OP_AND vnode=[specificsymbol]
+ | isaddrof=OP_AND sizeOpColon size=integerValue (inode=instSymbol | vnode=[specificsymbol])
+;
+
+instSymbol:
+ STARTSYM | ENDSYM
+;
+
+lhsvarnode:
+ VARSYM
+ // have to be crossed checked another way | VARLISTSYM
+ | CONTEXTSYM | TOKENSYM
+ | SPECSYM
+ | OPERANDSYM
+ | BITSYM
+ | LOCALSYM
+ | SUBTABLESYM
+ | MACROPARAMSYM
+;
+
+label:
+ '<' name=ID '>'
+;
+
+exportvarnode:
+ VARSYM
+ | SUBTABLESYM
+ | SPECSYM
+ | OPERANDSYM
+ | STARTSYM
+ | ENDSYM
+ // These will need to be checked for valid VARLIST tokens
+ | CONTEXTSYM | TOKENSYM
+ | LOCALSYM
+ | assignSym
+ | aliasSym
+;
+
+familysymbol:
+ VALUESYM
+ | CONTEXTSYM
+ | NAMESYM
+ | VARLISTSYM
+;
+
+specificsymbol:
+ VARSYM
+ | LOCALSYM
+ | CONTEXTSYM | TOKENSYM // should really be special, must appear in match pattern
+ | SPECSYM
+ | OPERANDSYM
+ | STARTSYM
+ | ENDSYM
+ | SUBTABLESYM
+ | MACROPARAMSYM
+ | aliasSym
+ ;
+
+//specificsymbol:
+// (vardef | contextfielddef | bitrange | MACROSYM)
+// | sym=[SPECSYM]
+// | sym=[OPERANDSYM]
+// | sym=[STARTSYM]
+// | sym=[ENDSYM]
+//;
+
+intblist:
+ {intblist} '[' args+=intbpart+ ']'
+ | args+= intbpart
+;
+
+intbpart:
+ value=integerValue
+ | isnegative?='-' value=integerValue
+ | isempty?=EMPTYVARSYM
+;
+
+anystringlist:
+ '[' namelist+=anystringpart+ ']'
+;
+
+anystringpart:
+ str = STRING
+ | sym = STRINGNAME
+ | isempty?=EMPTYVARSYM
+;
+
+STRINGNAME:
+ name=ID;
+
+valuesymlist:
+ '[' valuelist+=valuepart+ ']'
+ | value=valuepart
+;
+
+valuepart:
+ VALUESYM;
+
+VALUESYM:
+ sym=[mapdef]
+;
+
+namesymlist:
+ '[' valuelist+=NAMESYM+ ']'
+ | value=NAMESYM // { $$ = new vector; $$->push back($1); }
+// | value=[CONTEXTSYM] // { $$ = new vector; $$->push_back($1); }
+;
+
+NAMESYM:
+ sym=[mapdef]
+;
+
+varsymlist:
+ '[' valuelist+=valuepartdef+ ']'
+ | valuelist+=valuepartdef
+;
+
+valuepartdef:
+ sym=[mapdef]
+;
+
+VARLISTSYM:
+ name=ID
+;
+
+mapdef:
+ TOKENSYM | CONTEXTSYM
+;
+
+varlist:
+ '[' varDefList+=varpart+ ']'
+ | varDefList+=varpart
+;
+
+varpart:
+ varpart=[VARSYM] | hasunder?=EMPTYVARSYM // TODO: somehow '_' is OK at head of STRING?
+ | macroUse
+;
+
+paramlist:
+ {paramlist}
+ '(' ((parameters+=expr)? (',' parameters+=expr)*) ')'
+;
+
+oplist:
+ {oplist}
+ ((args+=MACROPARAMSYM (',' args+=MACROPARAMSYM)*))?
+;
+
+MACROPARAMSYM:
+ name=ID;
+
+anysymbol:
+ sym=SPACESYM
+ | sym=SECTIONSYM
+ | sym=TOKENSYM
+ | sym=USEROPSYM
+ | sym=MACROSYM
+ | sym=SUBTABLESYM
+ | sym=VALUESYM
+// | sym=VALUEMAPSYM
+ | sym=CONTEXTSYM
+ | sym=NAMESYM
+ | sym=VARNODESYM
+ | sym=VARLISTSYM
+ | sym=OPERANDSYM
+ | sym=STARTSYM
+ | sym=ENDSYM
+ | sym=BITSYM
+ | sym=LOCALSYM
+ | sym=MACROPARAMSYM
+;
+
+LOCALSYM:
+ name=ID;
+
+SPACESYM:
+ spacesymbol;
+
+spacesymbol:
+ name=ID;
+
+SECTIONSYM:
+ sectionsymbol;
+
+sectionsymbol:
+ name=ID;
+
+VarnodeSymbol:
+ VARSYM;
+
+VARSYM:
+ name=ID;
+
+TOKENGROUPSYM:
+ tokengroup;
+
+tokengroup:
+ ID;
+
+USEROPSYM:
+ name=ID;
+
+TOKENSYM:
+ fielddef;
+
+CONTEXTSYM:
+ contextfielddef;
+
+VARNODESYM:
+ varsymbol;
+
+varsymbol:
+ name=ID;
+
+EMPTYVARSYM:
+ '_'
+;
+
+BITSYM:
+ bitrangesingle;
+
+SPECSYM:
+ specsymbol;
+
+specsymbol:
+ name=ID;
+
+OPERANDSYM:
+ name=ID;
+
+STARTSYM:
+ name='inst_start';
+
+startsymbol:
+ name=ID;
+
+ENDSYM:
+ name='inst_next';
+
+endsymbol:
+ name=ID;
+
+MACROSYM:
+ macrodef;
+
+LABELSYM:
+ labelsymbol;
+
+labelsymbol:
+ name=ID;
+
+SUBTABLESYM:
+ name=ID;
+
+
+charsymbol:
+ ('!' | '@' | '#' | '$' | '%' | OP_AND | '*' | '(' | ')' | '-' | '=' | '+' | '[' | ']' | '{' | '}' | OP_OR | ';' | ':' | '<'
+ | '>' | '?' | ',' | '/' | NUMVAL );
+
+DefineSym:
+ name=ID;
+
+DefineUsage:
+ '$' '(' symref=[DefineSym] ')'
+;
+
+integerValue:
+ value=intvalue | sym=DefineUsage
+ ;
+
+intvalue:
+ HEXVAL | BINVAL | NUMVAL
+ ;
+
+terminal NUMVAL returns ecore::EBigInteger:
+ (DIGIT)+
+;
+
+terminal HEXVAL returns ecore::EBigInteger:
+ '0x' HEX_DIGIT+
+;
+
+terminal fragment HEX_DIGIT:
+ (DIGIT | 'a'..'f' | 'A'..'F')
+;
+
+terminal BINVAL returns ecore::EBigInteger:
+ '0b' BIN_DIGIT+
+;
+
+terminal fragment BIN_DIGIT:
+ ('0' | '1')
+;
+
+terminal fragment DIGIT:
+ ('0'..'9')
+;
+
+//terminal MACRO_KEY:
+////macro {BEGIN(macroblock); return MACRO_KEY; }
+// 'macro';
+//
+//terminal DEFINE_KEY:
+// 'define';
+// define { BEGIN(defblock); return DEFINE_KEY; }
+
+
+//terminal ATTACH_KEY:
+//// 'attach' { BEGIN(defblock); slgh->calcContextLayout(); return ATTACH_KEY; }
+// 'attach';
+terminal ID returns ecore::EString:
+//[a-zA-Z_.][a-zA-Z0-9_.]* { return find_symbol(); } { return yytext[0]; }
+ ('a'..'z' | 'A'..'Z' | '.' | '_') ('a'..'z' | 'A'..'Z' | '.' | '_' | '0'..'9')*;
+
+terminal OP_RIGHT:
+ '>>';
+
+terminal OP_LEFT:
+ '<<';
+
+terminal OP_NOTEQUAL:
+ '!=';
+
+terminal OP_LESSEQUAL:
+ '<=';
+
+terminal OP_GREATEQUAL:
+ '>=';
+
+terminal OP_DAND:
+ '$and';
+
+terminal OP_DOR:
+ '$or';
+
+terminal OP_DXOR:
+ '$xor';
+
+terminal OP_AND:
+ '&';
+
+terminal OP_OR:
+ '|';
+
+terminal OP_XOR:
+ '^';
+
+terminal OP_BOOL_OR:
+ '||';
+
+terminal OP_BOOL_AND:
+ '&&';
+
+terminal OP_BOOL_XOR:
+ '^^';
+
+terminal OP_EQUAL:
+ '==';
+
+terminal OP_SDIV:
+ 's/';
+
+terminal OP_SREM:
+ 's%';
+
+terminal OP_SRIGHT:
+ 's>>';
+
+terminal OP_SLESS:
+ 's<';
+
+terminal OP_SGREAT:
+ 's>';
+
+terminal OP_SLESSEQUAL:
+ 's<=';
+
+terminal OP_SGREATEQUAL:
+ 's>=';
+
+terminal OP_FADD:
+ 'f+';
+
+terminal OP_FSUB:
+ 'f-';
+
+terminal OP_FMULT:
+ 'f*';
+
+terminal OP_FDIV:
+ 'f/';
+
+terminal OP_FEQUAL:
+ 'f==';
+
+terminal OP_FNOTEQUAL:
+ 'f!=';
+
+terminal OP_FLESS:
+ 'f<';
+
+terminal OP_FGREAT:
+ 'f>';
+
+terminal OP_FLESSEQUAL:
+ 'f<=';
+
+terminal OP_FGREATEQUAL:
+ 'f>=';
+
+terminal STRING :
+ '"' ( '\\' . /* 'b'|'t'|'n'|'f'|'r'|'u'|'"'|"'"|'\\' */ | !('\\'|'"') )* '"' |
+ "'" ( '\\' . /* 'b'|'t'|'n'|'f'|'r'|'u'|'"'|"'"|'\\' */ | !('\\'|"'") )* "'"
+ ;
+terminal ML_COMMENT : '/*' -> '*/';
+terminal SL_COMMENT : '#' !('\n'|'\r')* ('\r'? '\n')?;
+
+terminal WS : (' '|'\t'|'\r'|'\n')+;
+
+//terminal ANY_OTHER: .;
+//
+//terminal DEFINENAME: 'synthetic:DEFINENAME';
+//terminal BEGINDEFINE: 'synthetic:BEGINDEFINE';
+//terminal ENDDEFINE: 'synthetic:ENDDEFINE';
\ No newline at end of file
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/SleighRuntimeModule.xtend b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/SleighRuntimeModule.xtend
new file mode 100644
index 0000000000..f74d164dee
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/SleighRuntimeModule.xtend
@@ -0,0 +1,23 @@
+/* ###
+ * 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.
+ */
+package ghidra.xtext.sleigh
+
+
+/**
+ * Use this class to register components to be used at runtime / without the Equinox extension registry.
+ */
+class SleighRuntimeModule extends AbstractSleighRuntimeModule {
+}
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/SleighStandaloneSetup.xtend b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/SleighStandaloneSetup.xtend
new file mode 100644
index 0000000000..d18900e600
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/SleighStandaloneSetup.xtend
@@ -0,0 +1,27 @@
+/* ###
+ * 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.
+ */
+package ghidra.xtext.sleigh
+
+
+/**
+ * Initialization support for running Xtext languages without Equinox extension registry.
+ */
+class SleighStandaloneSetup extends SleighStandaloneSetupGenerated {
+
+ def static void doSetup() {
+ new SleighStandaloneSetup().createInjectorAndDoEMFRegistration()
+ }
+}
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/converter/IntValueConverter.java b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/converter/IntValueConverter.java
new file mode 100644
index 0000000000..be2a598caf
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/converter/IntValueConverter.java
@@ -0,0 +1,67 @@
+/* ###
+ * 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.
+ */
+package ghidra.xtext.sleigh.converter;
+
+import java.math.BigInteger;
+import java.util.Map;
+
+import org.antlr.runtime.Token;
+import org.antlr.runtime.TokenSource;
+import org.eclipse.xtext.AbstractRule;
+import org.eclipse.xtext.conversion.ValueConverterException;
+import org.eclipse.xtext.conversion.impl.AbstractLexerBasedConverter;
+import org.eclipse.xtext.nodemodel.INode;
+import org.eclipse.xtext.parser.antlr.ITokenDefProvider;
+import org.eclipse.xtext.parser.antlr.Lexer;
+import org.eclipse.xtext.util.Strings;
+
+import com.google.inject.Provider;
+
+public class IntValueConverter extends AbstractLexerBasedConverter {
+
+ @Override
+ protected String toEscapedString(BigInteger value) {
+ return value.toString();
+ }
+
+ @Override
+ protected void assertValidValue(BigInteger value) {
+ super.assertValidValue(value);
+ if (value.compareTo(BigInteger.ZERO) < 0)
+ throw new ValueConverterException(getRuleName() + "-value may not be negative (value: " + value + ").", null, null);
+ }
+
+ public BigInteger toValue(String string, INode node) {
+ if (Strings.isEmpty(string))
+ throw new ValueConverterException("Couldn't convert empty string to an int value.", node, null);
+ try {
+ String parseString = string;
+ int radix = 10;
+ if (parseString.startsWith("0x") || parseString.startsWith("0X")) {
+ parseString = string.substring(2);
+ radix=16;
+ }
+ if (parseString.startsWith("0b") || parseString.startsWith("0B")) {
+ parseString = string.substring(2);
+ radix=2;
+ }
+ return new BigInteger(parseString,radix);
+ } catch (NumberFormatException e) {
+ throw new ValueConverterException("Couldn't convert '" + string + "' to a BigInteger value.", node, e);
+ }
+ }
+
+}
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/converter/SleighValueConverter.java b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/converter/SleighValueConverter.java
new file mode 100644
index 0000000000..69a28301eb
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/converter/SleighValueConverter.java
@@ -0,0 +1,55 @@
+/* ###
+ * 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.
+ */
+package ghidra.xtext.sleigh.converter;
+
+import java.math.BigInteger;
+
+import org.eclipse.xtext.common.services.DefaultTerminalConverters;
+import org.eclipse.xtext.conversion.IValueConverter;
+import org.eclipse.xtext.conversion.ValueConverter;
+import org.eclipse.xtext.conversion.ValueConverterException;
+import org.eclipse.xtext.conversion.impl.INTValueConverter;
+import org.eclipse.xtext.nodemodel.INode;
+import org.eclipse.xtext.util.Strings;
+
+import com.google.inject.Inject;
+
+public class SleighValueConverter extends DefaultTerminalConverters {
+
+ @Inject
+ private IntValueConverter hexValueConverter;
+
+ @ValueConverter(rule = "HEXVAL")
+ public IValueConverter HEXVAL() {
+ return hexValueConverter;
+ }
+
+ @Inject
+ private IntValueConverter numValueConverter;
+
+ @ValueConverter(rule = "NUMVAL")
+ public IValueConverter NUMVAL() {
+ return numValueConverter;
+ }
+
+ @Inject
+ private IntValueConverter binValueConverter;
+
+ @ValueConverter(rule = "BINVAL")
+ public IValueConverter BINVAL() {
+ return binValueConverter;
+ }
+}
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/formatting2/SleighFormatter.xtend b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/formatting2/SleighFormatter.xtend
new file mode 100644
index 0000000000..2f157db10a
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/formatting2/SleighFormatter.xtend
@@ -0,0 +1,1234 @@
+/* ###
+ * 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.
+ */
+package ghidra.xtext.sleigh.formatting2
+
+import com.google.common.base.Strings
+import com.google.inject.Inject
+import ghidra.xtext.sleigh.services.SleighGrammarAccess
+import ghidra.xtext.sleigh.sleigh.DefineTest
+import ghidra.xtext.sleigh.sleigh.Expression
+import ghidra.xtext.sleigh.sleigh.MACROPARAMSYM
+import ghidra.xtext.sleigh.sleigh.Model
+import ghidra.xtext.sleigh.sleigh.NAMESYM
+import ghidra.xtext.sleigh.sleigh.OPERANDSYM
+import ghidra.xtext.sleigh.sleigh.USEROPSYM
+import ghidra.xtext.sleigh.sleigh.aligndef
+import ghidra.xtext.sleigh.sleigh.anystringlist
+import ghidra.xtext.sleigh.sleigh.anystringpart
+import ghidra.xtext.sleigh.sleigh.anysymbol
+import ghidra.xtext.sleigh.sleigh.assignSym
+import ghidra.xtext.sleigh.sleigh.atomic
+import ghidra.xtext.sleigh.sleigh.baseconstructor
+import ghidra.xtext.sleigh.sleigh.bitrangedef
+import ghidra.xtext.sleigh.sleigh.bitrangelist
+import ghidra.xtext.sleigh.sleigh.bitrangesingle
+import ghidra.xtext.sleigh.sleigh.constraint
+import ghidra.xtext.sleigh.sleigh.constraintAdd
+import ghidra.xtext.sleigh.sleigh.constraintAnd
+import ghidra.xtext.sleigh.sleigh.constraintDiv
+import ghidra.xtext.sleigh.sleigh.constraintInvert
+import ghidra.xtext.sleigh.sleigh.constraintLeft
+import ghidra.xtext.sleigh.sleigh.constraintMult
+import ghidra.xtext.sleigh.sleigh.constraintNegate
+import ghidra.xtext.sleigh.sleigh.constraintOr
+import ghidra.xtext.sleigh.sleigh.constraintRight
+import ghidra.xtext.sleigh.sleigh.constraintSinglePexpression
+import ghidra.xtext.sleigh.sleigh.constraintSub
+import ghidra.xtext.sleigh.sleigh.constraintXor
+import ghidra.xtext.sleigh.sleigh.constructprint
+import ghidra.xtext.sleigh.sleigh.contextDefs
+import ghidra.xtext.sleigh.sleigh.contextblock
+import ghidra.xtext.sleigh.sleigh.contextdef
+import ghidra.xtext.sleigh.sleigh.contextentry
+import ghidra.xtext.sleigh.sleigh.contextfielddef
+import ghidra.xtext.sleigh.sleigh.contextlist
+import ghidra.xtext.sleigh.sleigh.elleqRight
+import ghidra.xtext.sleigh.sleigh.endiandef
+import ghidra.xtext.sleigh.sleigh.exportStmt
+import ghidra.xtext.sleigh.sleigh.exportedSym
+import ghidra.xtext.sleigh.sleigh.exprAnd
+import ghidra.xtext.sleigh.sleigh.exprBoolAnd
+import ghidra.xtext.sleigh.sleigh.exprBoolOr
+import ghidra.xtext.sleigh.sleigh.exprBoolXor
+import ghidra.xtext.sleigh.sleigh.exprDiv
+import ghidra.xtext.sleigh.sleigh.exprEqual
+import ghidra.xtext.sleigh.sleigh.exprFAdd
+import ghidra.xtext.sleigh.sleigh.exprFDiv
+import ghidra.xtext.sleigh.sleigh.exprFEqual
+import ghidra.xtext.sleigh.sleigh.exprFGt
+import ghidra.xtext.sleigh.sleigh.exprFGtEqual
+import ghidra.xtext.sleigh.sleigh.exprFLess
+import ghidra.xtext.sleigh.sleigh.exprFLessEqual
+import ghidra.xtext.sleigh.sleigh.exprFMult
+import ghidra.xtext.sleigh.sleigh.exprFNegate
+import ghidra.xtext.sleigh.sleigh.exprFNotEqual
+import ghidra.xtext.sleigh.sleigh.exprFSub
+import ghidra.xtext.sleigh.sleigh.exprGt
+import ghidra.xtext.sleigh.sleigh.exprGtEqual
+import ghidra.xtext.sleigh.sleigh.exprLeft
+import ghidra.xtext.sleigh.sleigh.exprLess
+import ghidra.xtext.sleigh.sleigh.exprLoad
+import ghidra.xtext.sleigh.sleigh.exprLtEqual
+import ghidra.xtext.sleigh.sleigh.exprMinus
+import ghidra.xtext.sleigh.sleigh.exprMult
+import ghidra.xtext.sleigh.sleigh.exprNegate
+import ghidra.xtext.sleigh.sleigh.exprNotEqual
+import ghidra.xtext.sleigh.sleigh.exprOr
+import ghidra.xtext.sleigh.sleigh.exprRem
+import ghidra.xtext.sleigh.sleigh.exprRight
+import ghidra.xtext.sleigh.sleigh.exprSDiv
+import ghidra.xtext.sleigh.sleigh.exprSGt
+import ghidra.xtext.sleigh.sleigh.exprSGtEqual
+import ghidra.xtext.sleigh.sleigh.exprSLess
+import ghidra.xtext.sleigh.sleigh.exprSLtEqual
+import ghidra.xtext.sleigh.sleigh.exprSRem
+import ghidra.xtext.sleigh.sleigh.exprSRight
+import ghidra.xtext.sleigh.sleigh.exprSym
+import ghidra.xtext.sleigh.sleigh.exprXor
+import ghidra.xtext.sleigh.sleigh.exprrAdd
+import ghidra.xtext.sleigh.sleigh.fielddef
+import ghidra.xtext.sleigh.sleigh.intblist
+import ghidra.xtext.sleigh.sleigh.intbpart
+import ghidra.xtext.sleigh.sleigh.integerValue
+import ghidra.xtext.sleigh.sleigh.integervarnode
+import ghidra.xtext.sleigh.sleigh.jumpdest
+import ghidra.xtext.sleigh.sleigh.localDefine
+import ghidra.xtext.sleigh.sleigh.macroDefine
+import ghidra.xtext.sleigh.sleigh.macroUse
+import ghidra.xtext.sleigh.sleigh.macrodef
+import ghidra.xtext.sleigh.sleigh.nameattach
+import ghidra.xtext.sleigh.sleigh.namesymlist
+import ghidra.xtext.sleigh.sleigh.oplist
+import ghidra.xtext.sleigh.sleigh.pAnd
+import ghidra.xtext.sleigh.sleigh.pNextSet
+import ghidra.xtext.sleigh.sleigh.pOr
+import ghidra.xtext.sleigh.sleigh.paramlist
+import ghidra.xtext.sleigh.sleigh.pcodeopdef
+import ghidra.xtext.sleigh.sleigh.pequation
+import ghidra.xtext.sleigh.sleigh.pexprAdd
+import ghidra.xtext.sleigh.sleigh.pexprAnd
+import ghidra.xtext.sleigh.sleigh.pexprDiv
+import ghidra.xtext.sleigh.sleigh.pexprInvert
+import ghidra.xtext.sleigh.sleigh.pexprLeft
+import ghidra.xtext.sleigh.sleigh.pexprMult
+import ghidra.xtext.sleigh.sleigh.pexprNegate
+import ghidra.xtext.sleigh.sleigh.pexprOr
+import ghidra.xtext.sleigh.sleigh.pexprRight
+import ghidra.xtext.sleigh.sleigh.pexprSub
+import ghidra.xtext.sleigh.sleigh.pexprXor
+import ghidra.xtext.sleigh.sleigh.printpiece
+import ghidra.xtext.sleigh.sleigh.rtlbody
+import ghidra.xtext.sleigh.sleigh.rtlmid
+import ghidra.xtext.sleigh.sleigh.singlePexpression
+import ghidra.xtext.sleigh.sleigh.sizedstar
+import ghidra.xtext.sleigh.sleigh.spaceprop
+import ghidra.xtext.sleigh.sleigh.statement
+import ghidra.xtext.sleigh.sleigh.subconstructor
+import ghidra.xtext.sleigh.sleigh.tokendef
+import ghidra.xtext.sleigh.sleigh.tokenprop
+import ghidra.xtext.sleigh.sleigh.valueattach
+import ghidra.xtext.sleigh.sleigh.valuepart
+import ghidra.xtext.sleigh.sleigh.valuepartdef
+import ghidra.xtext.sleigh.sleigh.valuesymlist
+import ghidra.xtext.sleigh.sleigh.varattach
+import ghidra.xtext.sleigh.sleigh.vardef
+import ghidra.xtext.sleigh.sleigh.vardeflist
+import ghidra.xtext.sleigh.sleigh.varlist
+import ghidra.xtext.sleigh.sleigh.varnodedef
+import ghidra.xtext.sleigh.sleigh.varpart
+import ghidra.xtext.sleigh.sleigh.varsymlist
+import ghidra.xtext.sleigh.sleigh.xrtl
+import org.eclipse.emf.ecore.EObject
+import org.eclipse.xtext.formatting2.AbstractFormatter2
+import org.eclipse.xtext.formatting2.IFormattableDocument
+
+class SleighFormatter extends AbstractFormatter2 {
+ @Inject extension SleighGrammarAccess
+
+ var constructorPrintLenMap = newHashMap("" -> 0)
+ var constructorPatternLenMap = newHashMap("" -> 0)
+ var constructorContextLenMap = newHashMap("" -> 0)
+
+ def dispatch void format(Model model, extension IFormattableDocument document) {
+ constructorPrintLenMap = newHashMap("" -> 0); // map names to printpiece
+ constructorPatternLenMap = newHashMap("" -> 0); // map names to pattern len
+ constructorContextLenMap = newHashMap("" -> 0); // map names to context len
+
+ var EObject prev;
+ for (spec : model.elements) {
+ if (prev !== null) {
+ if (!spec.class.equals(prev.class) && !(prev instanceof macroDefine)) {
+ prev.append[newLines = 2 priority = 2]
+ }
+ }
+ format(spec, document);
+
+ prev = spec;
+ }
+
+ // For Debugging formatting
+ // println(regionAccess.toString())
+ var constructors = model.eAllContents.filter(typeof(subconstructor))
+ var lastName = ""
+ while (constructors.hasNext()) {
+ var constLike = constructors.next()
+ var name = constLike.tableName.name
+ // TODO: make preference for max IS column
+ var is = constLike.print.is
+
+ var printRegion = constLike.print.regionForEObject;
+ // if print region is, good
+ if (printRegion !== null) {
+
+ var matchLen = 0;
+ var matchOffset = 0;
+ if (constLike.match.constraints.immediatelyPreceding !== null) {
+ var matchRegion = constLike.match.constraints.regionForEObject;
+ matchLen = matchRegion.length;
+ matchOffset = matchRegion.offset;
+ } else {
+ var matchRegion = constLike.match.regionForEObject;
+ matchLen = matchRegion.length;
+ matchOffset = matchRegion.offset;
+ }
+
+ var contextLen = 0;
+ if (constLike.cblock.immediatelyPreceding !== null) {
+ if (constLike.cblock !== null) {
+ contextLen = constLike.cblock.regionForEObject.length
+ }
+ }
+
+ var truncName = stripDigit(name);
+ val printMaxLen = constructorPrintLenMap.get(truncName)
+ val contextMaxLen = constructorContextLenMap.get(truncName)
+ val matchMaxLen = constructorPatternLenMap.get(truncName)
+
+ var printRegionlen = printRegion.length;
+ var isprlen = is.regionFor.keyword('is').previousHiddenRegion.length
+ if (printRegionlen == 2) {
+ // region is just 'is' empty print piece
+ isprlen = 0
+ printRegionlen = 1
+ }
+
+ var totalLen = name.length + printRegionlen - isprlen
+ if (totalLen < printMaxLen) {
+ // put the space before the 'is'
+ val prLen = totalLen;
+ is.prepend[space = Strings.repeat(" ", printMaxLen - prLen + 2)]
+ totalLen += (printMaxLen - prLen) + 2;
+ } else {
+ is.prepend[space = ' ']
+ totalLen += 2;
+ }
+ totalLen += matchLen + contextLen;
+ val maxLBLen = printMaxLen + matchMaxLen + contextMaxLen + 2
+ if (totalLen < maxLBLen && maxLBLen < 120) {
+ val prLen = totalLen
+ constLike.getBody().regionFor.keyword("{").prepend [
+ priority = 1
+ space = Strings.repeat(" ", maxLBLen - prLen + 1)
+ ]
+ } else {
+ constLike.getBody().regionFor.keyword("{").prepend[priority = 1 space = ' ']
+ }
+ // if different subtable name, add 2 newlines
+ if (!lastName.equals(truncName)) {
+ constLike.prepend[newLines = 2 priority = 1]
+ }
+ lastName = truncName;
+ }
+ }
+
+ var baseconstructors = model.eAllContents.filter(typeof(baseconstructor))
+ var name = "" // name of BaseConstructors
+ val printMaxLen = constructorPrintLenMap.get(name)
+ while (baseconstructors.hasNext()) {
+ var constLike = baseconstructors.next()
+ var is = constLike.print.is
+ var printRegion = constLike.print.regionForEObject;
+ if (printRegion !== null) {
+ var totalLen = name.length + 1 + printRegion.length -
+ is.regionFor.keyword('is').previousHiddenRegion.length
+ if (totalLen < printMaxLen) {
+ // put the space before the 'is'
+ val prLen = totalLen;
+ is.prepend[space = Strings.repeat(" ", printMaxLen - prLen)]
+ totalLen += (printMaxLen - prLen) + 3;
+ } else if (totalLen > printMaxLen) {
+ is.prepend[space = ' ']
+ totalLen += 3;
+ }
+ }
+ }
+ }
+
+ def void computePrintLength(String name, constructprint print) {
+ var truncName = stripDigit(name);
+
+ // length before the 'is'
+ var prLen = constructorPrintLenMap.getOrDefault(truncName, Integer.valueOf(0))
+ var is = print.is
+ var printRegion = print.regionForEObject;
+ var baseLen = 0;
+ // if print region is not empty
+ if (printRegion !== null) {
+ val curPrLen = printRegion.length
+ val curPrWhiteSpace = is.regionFor.keyword('is').previousHiddenRegion
+ baseLen = name.toString.length + curPrLen - curPrWhiteSpace.length
+ }
+ if(baseLen > 40) baseLen = 0;
+ if(baseLen >= prLen) constructorPrintLenMap.put(truncName, baseLen)
+ }
+
+ def stripDigit(String str) {
+ var retStr = str;
+ while (Character.isDigit(retStr.charAt(retStr.length - 1))) {
+ retStr = retStr.substring(0, retStr.length - 1)
+ }
+ return retStr;
+ }
+
+ def void computeMatchLength(String name, pequation match, contextblock context) {
+ var truncName = stripDigit(name);
+
+ // length of match pattern
+ var allMatchLen = constructorPatternLenMap.getOrDefault(truncName, Integer.valueOf(0))
+ if (match === null || match.constraints === null) {
+ return; // something wrong with syntax, can't format
+ }
+ var matchLen = 0;
+ var matchOffset = 0;
+ if (match.constraints !== null && match.constraints.immediatelyPreceding !== null) {
+ var matchRegion = match.constraints.regionForEObject;
+ matchLen = matchRegion.length;
+ matchOffset = matchRegion.offset;
+ } else {
+ var matchRegion = match.regionForEObject;
+ matchLen = matchRegion.length;
+ matchOffset = matchRegion.offset;
+ }
+ if(matchLen >= allMatchLen) constructorPatternLenMap.put(truncName, matchLen)
+
+ // length of context block
+ var allContextLen = constructorContextLenMap.getOrDefault(truncName, Integer.valueOf(0))
+ var contextLen = 0;
+ if (context !== null && context.immediatelyPreceding !== null) {
+ var contextRegion = context.regionForEObject;
+ contextLen = contextRegion.length;
+ if(matchOffset == 0) contextLen = 0;
+ }
+ if(contextLen >= allContextLen) constructorContextLenMap.put(truncName, contextLen)
+ }
+
+ def dispatch void format(macroDefine macroDefine, extension IFormattableDocument document) {
+ macroDefine.definename.format
+ macroDefine.tests.format
+ macroDefine.sym.format
+ for (isDefined : macroDefine.isdefined) {
+ isDefined.format
+ }
+ macroDefine.symref.format
+ }
+
+ def dispatch void format(DefineTest definetest, extension IFormattableDocument document) {
+ format(definetest.getTest(), document);
+ format(definetest.getSymref(), document);
+ format(definetest.getIsdefined(), document);
+ format(definetest.getAndtest(), document);
+ format(definetest.getOrtest(), document);
+ }
+
+ def dispatch void format(endiandef endiandef, extension IFormattableDocument document) {
+ format(endiandef.getIs_define(), document);
+ }
+
+ def dispatch void format(aligndef aligndef, extension IFormattableDocument document) {
+ format(aligndef.getAlign(), document);
+ }
+
+ def dispatch void format(tokendef tokendef, extension IFormattableDocument document) {
+ tokendef.surround[setNewLines(1, 2, 3)]
+ format(tokendef.getSize(), document);
+ format(tokendef.getFields(), document);
+ tokendef.regionFor.keyword(";").prepend[newLine]
+ }
+
+ var maxTokenNameLen = 0;
+ var maxStartLen = 0;
+ var maxEndLen = 0;
+ var maxFound = false;
+ var maxtag = 0;
+
+ def dispatch void format(tokenprop tokenprop, extension IFormattableDocument document) {
+ maxTokenNameLen = 0
+ maxStartLen = 0
+ maxEndLen = 0
+ maxFound = false
+ maxtag = 0
+ for (EObject tokens : tokenprop.getTokens()) {
+ format(tokens, document);
+ }
+ maxFound = true
+ for (EObject tokens : tokenprop.getTokens()) {
+ format(tokens, document);
+ }
+ }
+
+ def dispatch void format(contextdef contextdef, extension IFormattableDocument document) {
+ format(contextdef.getFields(), document);
+ }
+
+ def dispatch void format(contextDefs contextdefs, extension IFormattableDocument document) {
+ maxTokenNameLen = 0
+ maxStartLen = 0
+ maxEndLen = 0
+ maxFound = false
+ maxtag = 0
+ for (EObject contextDefs : contextdefs.getContextDefs()) {
+ format(contextDefs, document);
+ }
+ maxFound = true
+ for (EObject contextDefs : contextdefs.getContextDefs()) {
+ format(contextDefs, document);
+ }
+ }
+
+ def dispatch void format(fielddef fielddef, extension IFormattableDocument document) {
+ format(fielddef.getStart(), document);
+ format(fielddef.getEnd(), document);
+ val len = fielddef.name.length
+ val slen = fielddef.start.value.length
+ val elen = fielddef.end.value.length
+ val hastag = fielddef.signed || fielddef.hex || fielddef.dec;
+ if (maxFound) {
+ val padlen = maxTokenNameLen - len + 1;
+ fielddef.prepend[setNewLines(1, 1, 2)].surround[indent]
+ fielddef.regionFor.keyword("=").prepend[space = Strings.repeat(" ", padlen)]
+ fielddef.regionFor.keyword("(").append[space = Strings.repeat(" ", maxStartLen - slen)]
+ fielddef.regionFor.keyword(",").append[space = Strings.repeat(" ", maxEndLen - elen)].prepend[noSpace]
+
+ if (!hastag) {
+ fielddef.regionFor.keyword(")").prepend[noSpace].append[space = Strings.repeat(" ", maxtag + 1)]
+ } else {
+ fielddef.regionFor.keyword(")").prepend[noSpace]
+ }
+ fielddef.regionFor.keyword("=").append[space = " "]
+ fielddef.regionFor.keyword("signed").prepend[oneSpace]
+ } else if (len > maxTokenNameLen) {
+ maxTokenNameLen = len
+ }
+ if (maxStartLen < slen) {
+ maxStartLen = slen
+ }
+ if (maxEndLen < elen) {
+ maxEndLen = elen
+ }
+ if (fielddef.signed) {
+ maxtag = 6;
+ } else if (fielddef.hex || fielddef.dec) {
+ maxtag = 3;
+ }
+ }
+
+ def dispatch void format(macroUse macrouse, extension IFormattableDocument document) {
+ format(macrouse.getDefine(), document);
+ }
+
+ def dispatch void format(contextfielddef contextfielddef, extension IFormattableDocument document) {
+ format(contextfielddef.getStart(), document);
+ format(contextfielddef.getEnd(), document);
+ val len = contextfielddef.name.length
+ val slen = contextfielddef.start.value.length
+ val elen = contextfielddef.end.value.length
+ val hastag = contextfielddef.signed || contextfielddef.noflow || contextfielddef.hex || contextfielddef.dec;
+ if (maxFound) {
+ val padlen = maxTokenNameLen - len + 1;
+ contextfielddef.prepend[setNewLines(1, 1, 2)].surround[indent]
+ contextfielddef.regionFor.keyword("=").prepend[space = Strings.repeat(" ", padlen)]
+ contextfielddef.regionFor.keyword("(").append[space = Strings.repeat(" ", maxStartLen - slen)]
+ contextfielddef.regionFor.keyword(",").append[space = Strings.repeat(" ", maxEndLen - elen)].prepend [
+ noSpace
+ ]
+ contextfielddef.regionFor.keyword(")").prepend[noSpace]
+ contextfielddef.regionFor.keyword("=").append[space = " "]
+ contextfielddef.regionFor.keyword("signed").prepend[oneSpace]
+ contextfielddef.regionFor.keyword("noflow").prepend[oneSpace]
+ if (!hastag) {
+ contextfielddef.regionFor.keyword(")").prepend[noSpace].append[space = Strings.repeat(" ", maxtag + 1)]
+ } else {
+ contextfielddef.regionFor.keyword(")").prepend[noSpace]
+ }
+ } else if (len > maxTokenNameLen) {
+ maxTokenNameLen = len
+ }
+ if (maxStartLen < slen) {
+ maxStartLen = slen
+ }
+ if (maxEndLen < elen) {
+ maxEndLen = elen
+ }
+ if (contextfielddef.signed || contextfielddef.noflow) {
+ maxtag = 6;
+ } else if (contextfielddef.hex || contextfielddef.dec) {
+ maxtag = 3;
+ }
+ }
+
+ def dispatch void format(spaceprop spaceprop, extension IFormattableDocument document) {
+ format(spaceprop.getSpace(), document);
+ format(spaceprop.getSize(), document);
+ format(spaceprop.getWordsize(), document);
+ }
+
+ def dispatch void format(varnodedef varnodedef, extension IFormattableDocument document) {
+ format(varnodedef.getOffset(), document);
+ format(varnodedef.getSize(), document);
+ format(varnodedef.getVars(), document);
+ }
+
+ def dispatch void format(vardeflist vars, extension IFormattableDocument document) {
+ for (vardef varDefList : vars.getVarDefList()) {
+ format(varDefList, document);
+ }
+ // format multi-line variable attach definitions
+ if (vars.isMultiline) {
+ var open = vars.regionFor.keyword('[')
+ var close = vars.regionFor.keyword(']')
+ interior(open, close)[indent]
+ open.append[newLine]
+ close.prepend[newLine]
+ var vlist = vars.varDefList;
+ var maxLen = 0;
+ for (v : vlist) {
+ var len = 1;
+ if (!v.isIsempty) {
+ len = v.varname.name.length;
+ }
+ if (len > maxLen) {
+ maxLen = len;
+ }
+ }
+ if(maxLen > 20) maxLen = 20;
+ var previousLen = 0;
+ for (v : vlist) {
+ var len = 1;
+ if (!v.isIsempty) {
+ len = v.varname.name.length;
+ }
+
+ if (v.nextHiddenRegion !== null && v.nextHiddenRegion.isMultiline) {
+ v.append[newLine]
+ }
+ if (previousLen != 0) {
+ val prevLen = previousLen
+ v.prepend[space = Strings.repeat(" ", prevLen)]
+ previousLen = 0
+ }
+ if (v.isIsempty) {
+ previousLen = maxLen - 1 + 1;
+ } else if (len < maxLen) {
+ val spaceLen = maxLen - len + 1;
+ previousLen = spaceLen;
+ // v.append[space = Strings.repeat(" ", spaceLen)]
+ } else {
+ previousLen = 1;
+ }
+ }
+ }
+ }
+
+ def dispatch void format(vardef vardef, extension IFormattableDocument document) {
+ format(vardef.getVarname(), document);
+ }
+
+ def dispatch void format(bitrangedef bitrangedef, extension IFormattableDocument document) {
+ format(bitrangedef.getList(), document);
+ }
+
+ def dispatch void format(bitrangelist bitrangelist, extension IFormattableDocument document) {
+ for (bitrangesingle bitrangeEntries : bitrangelist.getBitrangeEntries()) {
+ format(bitrangeEntries, document);
+ }
+ }
+
+ def dispatch void format(bitrangesingle bitrangesingle, extension IFormattableDocument document) {
+ format(bitrangesingle.getStart(), document);
+ format(bitrangesingle.getEnd(), document);
+ }
+
+ def dispatch void format(pcodeopdef pcodeopdef, extension IFormattableDocument document) {
+ for (USEROPSYM ops : pcodeopdef.getOps()) {
+ format(ops, document);
+ }
+ pcodeopdef.regionFor.keyword(";").prepend[noSpace]
+// pcodeopdef.surround[setNewLines(1,2,3)]
+ }
+
+ def dispatch void format(valueattach valueattach, extension IFormattableDocument document) {
+ format(valueattach.getValuelist(), document);
+ format(valueattach.getBlist(), document);
+ }
+
+ def dispatch void format(nameattach nameattach, extension IFormattableDocument document) {
+ format(nameattach.getValuelist(), document);
+ format(nameattach.getSlist(), document);
+ }
+
+ def dispatch void format(varattach varattach, extension IFormattableDocument document) {
+ format(varattach.getValuelist(), document);
+ format(varattach.getVlist(), document);
+ }
+
+ def dispatch void format(macrodef macrodef, extension IFormattableDocument document) {
+ format(macrodef.getArgs(), document);
+ format(macrodef.getBody(), document);
+ }
+
+ def dispatch void format(rtlbody rtlbody, extension IFormattableDocument document) {
+ var body = rtlbody.getBody();
+
+ if (body !== null) {
+ format(body, document);
+ }
+
+ var open = rtlbody.regionFor.keyword('{')
+ var close = rtlbody.regionFor.keyword('}')
+ interior(open, close)[indent priority=3]
+
+ if (rtlbody.isMultiline) {
+ open.prepend[oneSpace]
+ close.prepend[newLine]
+ }
+
+ if (rtlbody.isUnimpl) {
+ rtlbody.prepend[newLine indent priority=3]
+ }
+ }
+
+ def dispatch void format(baseconstructor baseconstructor, extension IFormattableDocument document) {
+ baseconstructor.regionFor.keyword(":").append[noSpace]
+
+ format(baseconstructor.getPrint(), document);
+ format(baseconstructor.getMatch(), document);
+ format(baseconstructor.cblock, document);
+ format(baseconstructor.getBody(), document);
+
+ var allBaseLen = constructorPrintLenMap.getOrDefault("", Integer.valueOf(0))
+ var is = baseconstructor.print.is
+ var printRegion = baseconstructor.print.regionForEObject;
+ // if print region is bad, need to bail
+ if (printRegion === null) {
+ return
+ }
+ var baseLen = printRegion.length - is.regionFor.keyword('is').previousHiddenRegion.length
+ if(baseLen > 40) baseLen = 0;
+ if(baseLen >= allBaseLen) constructorPrintLenMap.put("", baseLen)
+
+ }
+
+ def dispatch void format(subconstructor sub, extension IFormattableDocument document) {
+ sub.regionFor.keyword(":").prepend[noSpace]
+
+ //sub.surround[setNewLines(1, 2, 3)]
+
+ format(sub.tableName, document);
+ format(sub.print, document);
+ format(sub.match, document);
+ format(sub.cblock, document);
+ format(sub.body, document);
+
+ // format short body, long bodies, force to newline, full formating
+ var open = sub.body.regionFor.keyword('{')
+ var close = sub.body.regionFor.keyword('}')
+ var body = sub.body;
+ var bodyLen = 3
+ if (open !== null && close !== null) {
+ bodyLen = body.regionForEObject.length;
+ if (!sub.body.isMultiline) {
+ open.prepend[newLines = 0].append[oneSpace]
+ close.prepend[oneSpace]
+ body.body.statements.rtllist.forEach [
+ regionFor.keywords(';').forEach[it.prepend[space = ''].append[space = ' ']]
+ ]
+ body.body.export.regionFor.keywords(';').forEach [
+ it.prepend[space = ''].append[space = ' ']
+ ]
+ body.body.statements.rtllist.forEach [
+ regionFor.keywords(';').forEach[it.prepend[space = ''].append[space = ' ']]
+ ]
+ } else if (sub.body.body.regionForEObject.length > 0 && sub.body.body.isMultiline) {
+ body.body.statements.rtllist.forEach [
+ regionFor.keywords(';').forEach [
+ if (it.nextHiddenRegion !== null && it.nextHiddenRegion.isMultiline) {
+ it.append[newLine]
+ } else {
+ it.append[space = ' ']
+ }
+ ]
+ ]
+ body.body.export.regionFor.keywords(';').forEach [
+ if (it.nextHiddenRegion !== null && it.nextHiddenRegion.isMultiline) {
+ it.append[newLine]
+ } else {
+ it.append[space = ' ']
+ }
+ ]
+ body.body.statements.rtllist.forEach [
+ if (it.nextHiddenRegion !== null && it.nextHiddenRegion.isMultiline) {
+ it.append[newLine]
+ } else {
+ it.append[space = ' ']
+ }
+ ]
+ }
+ }
+
+ // length of printpiece
+ computePrintLength(sub.tableName.name, sub.print);
+
+ // length of match pattern
+ computeMatchLength(sub.tableName.name, sub.match, sub.cblock);
+ }
+
+ def dispatch void format(constructprint constructprint, extension IFormattableDocument document) {
+ for (printpiece printpieces : constructprint.getPrintpieces()) {
+ format(printpieces, document);
+ }
+ format(constructprint.getIs(), document);
+ }
+
+ def dispatch void format(printpiece printpiece, extension IFormattableDocument document) {
+ format(printpiece.getSym(), document);
+ }
+
+ def dispatch void format(pexprAdd pexpradd, extension IFormattableDocument document) {
+ format(pexpradd.getRight(), document);
+ format(pexpradd.getLeft(), document);
+ }
+
+ def dispatch void format(pexprSub pexprsub, extension IFormattableDocument document) {
+ format(pexprsub.getRight(), document);
+ format(pexprsub.getLeft(), document);
+ }
+
+ def dispatch void format(pexprMult pexprmult, extension IFormattableDocument document) {
+ format(pexprmult.getRight(), document);
+ format(pexprmult.getLeft(), document);
+ }
+
+ def dispatch void format(pexprLeft pexprleft, extension IFormattableDocument document) {
+ format(pexprleft.getRight(), document);
+ format(pexprleft.getLeft(), document);
+ }
+
+ def dispatch void format(pexprRight pexprright, extension IFormattableDocument document) {
+ format(pexprright.getRight(), document);
+ format(pexprright.getLeft(), document);
+ }
+
+ def dispatch void format(pexprAnd pexprand, extension IFormattableDocument document) {
+ format(pexprand.getRight(), document);
+ format(pexprand.getLeft(), document);
+ }
+
+ def dispatch void format(pexprOr pexpror, extension IFormattableDocument document) {
+ format(pexpror.getRight(), document);
+ format(pexpror.getLeft(), document);
+ }
+
+ def dispatch void format(pexprXor pexprxor, extension IFormattableDocument document) {
+ format(pexprxor.getRight(), document);
+ format(pexprxor.getLeft(), document);
+ }
+
+ def dispatch void format(pexprDiv pexprdiv, extension IFormattableDocument document) {
+ format(pexprdiv.getRight(), document);
+ format(pexprdiv.getLeft(), document);
+ }
+
+ def dispatch void format(pexprNegate pexprnegate, extension IFormattableDocument document) {
+ format(pexprnegate.getLeft(), document);
+ }
+
+ def dispatch void format(pexprInvert pexprinvert, extension IFormattableDocument document) {
+ format(pexprinvert.getLeft(), document);
+ }
+
+ def dispatch void format(singlePexpression singlepexpression, extension IFormattableDocument document) {
+ format(singlepexpression.getIntval(), document);
+ format(singlepexpression.getSym(), document);
+ format(singlepexpression.getRight(), document);
+ }
+
+ def dispatch void format(constraintAdd constraintadd, extension IFormattableDocument document) {
+ format(constraintadd.getRight(), document);
+ format(constraintadd.getLeft(), document);
+ }
+
+ def dispatch void format(constraintSub constraintsub, extension IFormattableDocument document) {
+ format(constraintsub.getRight(), document);
+ format(constraintsub.getLeft(), document);
+ }
+
+ def dispatch void format(constraintMult constraintmult, extension IFormattableDocument document) {
+ format(constraintmult.getRight(), document);
+ format(constraintmult.getLeft(), document);
+ }
+
+ def dispatch void format(constraintLeft constraintleft, extension IFormattableDocument document) {
+ format(constraintleft.getRight(), document);
+ format(constraintleft.getLeft(), document);
+ }
+
+ def dispatch void format(constraintRight constraintright, extension IFormattableDocument document) {
+ format(constraintright.getRight(), document);
+ format(constraintright.getLeft(), document);
+ }
+
+ def dispatch void format(constraintAnd constraintand, extension IFormattableDocument document) {
+ format(constraintand.getRight(), document);
+ format(constraintand.getLeft(), document);
+ }
+
+ def dispatch void format(constraintOr constraintor, extension IFormattableDocument document) {
+ format(constraintor.getRight(), document);
+ format(constraintor.getLeft(), document);
+ }
+
+ def dispatch void format(constraintXor constraintxor, extension IFormattableDocument document) {
+ format(constraintxor.getRight(), document);
+ format(constraintxor.getLeft(), document);
+ }
+
+ def dispatch void format(constraintDiv constraintdiv, extension IFormattableDocument document) {
+ format(constraintdiv.getRight(), document);
+ format(constraintdiv.getLeft(), document);
+ }
+
+ def dispatch void format(constraintNegate constraintnegate, extension IFormattableDocument document) {
+ format(constraintnegate.getExpr(), document);
+ }
+
+ def dispatch void format(constraintInvert constraintinvert, extension IFormattableDocument document) {
+ format(constraintinvert.getExpr(), document);
+ }
+
+ def dispatch void format(constraintSinglePexpression constraintsinglepexpression,
+ extension IFormattableDocument document) {
+ format(constraintsinglepexpression.getIntval(), document);
+ format(constraintsinglepexpression.getSym(), document);
+ format(constraintsinglepexpression.getRight(), document);
+ }
+
+ def dispatch void format(pequation pequation, extension IFormattableDocument document) {
+ format(pequation.getConstraints(), document);
+ }
+
+ def dispatch void format(pNextSet pnextset, extension IFormattableDocument document) {
+ format(pnextset.getRight(), document);
+ format(pnextset.getLeft(), document);
+ }
+
+ def dispatch void format(pAnd pand, extension IFormattableDocument document) {
+ format(pand.getRight(), document);
+ format(pand.getLeft(), document);
+ }
+
+ def dispatch void format(pOr por, extension IFormattableDocument document) {
+ format(por.getRight(), document);
+ format(por.getLeft(), document);
+ }
+
+ def dispatch void format(atomic atomic, extension IFormattableDocument document) {
+ format(atomic.getDefine(), document);
+ format(atomic.getRight(), document);
+ }
+
+ def dispatch void format(constraint constraint, extension IFormattableDocument document) {
+ format(constraint.getValue(), document);
+ }
+
+ def dispatch void format(contextblock contextblock, extension IFormattableDocument document) {
+ format(contextblock.getBlock(), document);
+ }
+
+ def dispatch void format(contextlist contextlist, extension IFormattableDocument document) {
+ for (contextentry entry : contextlist.getEntry()) {
+ format(entry, document);
+ }
+ }
+
+ def dispatch void format(contextentry contextentry, extension IFormattableDocument document) {
+ format(contextentry.getRhs(), document);
+ format(contextentry.getTsym(), document);
+ }
+
+ def dispatch void format(OPERANDSYM operandsym, extension IFormattableDocument document) {
+ format(operandsym.getRhs(), document);
+ }
+
+ def dispatch void format(xrtl xrtl, extension IFormattableDocument document) {
+ format(xrtl.getStatements(), document);
+ format(xrtl.getExport(), document);
+ format(xrtl.getAdditionalStatements(), document);
+ }
+
+ def dispatch void format(exportStmt exportstmt, extension IFormattableDocument document) {
+ format(exportstmt.getResultsize(), document);
+ format(exportstmt.getResult(), document);
+ }
+
+ def dispatch void format(exportedSym exportedsym, extension IFormattableDocument document) {
+ format(exportedsym.getVarnode(), document);
+ format(exportedsym.getSize(), document);
+ format(exportedsym.getConst(), document);
+ }
+
+ def dispatch void format(rtlmid rtlmid, extension IFormattableDocument document) {
+ for (statement rtllist : rtlmid.getRtllist()) {
+ format(rtllist, document);
+ }
+ for (macroUse macro : rtlmid.getMacro()) {
+ format(macro, document);
+ }
+ }
+
+ def dispatch void format(statement statement, extension IFormattableDocument document) {
+ statement.prepend[setNewLines(0,1,2)]
+ format(statement.getSection_name(), document);
+ format(statement.getLhs(), document);
+ format(statement.getRhs(), document);
+ format(statement.getPtrsize(), document);
+ format(statement.getLhsexpr(), document);
+ format(statement.getStart(), document);
+ format(statement.getEnd(), document);
+ format(statement.getCrossvnode(), document);
+ format(statement.getDelayslot(), document);
+ format(statement.getDest(), document);
+ format(statement.getIfexpr(), document);
+ format(statement.getGotodest(), document);
+ format(statement.getArgs(), document);
+ format(statement.getLabel(), document);
+ }
+
+ def dispatch void format(assignSym assignsym, extension IFormattableDocument document) {
+ format(assignsym.getLocal(), document);
+ format(assignsym.getDefine(), document);
+ }
+
+ def dispatch void format(localDefine localdefine, extension IFormattableDocument document) {
+ format(localdefine.getSym(), document);
+ format(localdefine.getSize(), document);
+ }
+
+ def dispatch void format(exprrAdd exprradd, extension IFormattableDocument document) {
+ format(exprradd.getRight(), document);
+ format(exprradd.getLeft(), document);
+ }
+
+ def dispatch void format(exprMinus exprminus, extension IFormattableDocument document) {
+ format(exprminus.getRight(), document);
+ format(exprminus.getLeft(), document);
+ }
+
+ def dispatch void format(exprEqual exprequal, extension IFormattableDocument document) {
+ format(exprequal.getRight(), document);
+ format(exprequal.getLeft(), document);
+ }
+
+ def dispatch void format(exprNotEqual exprnotequal, extension IFormattableDocument document) {
+ format(exprnotequal.getRight(), document);
+ format(exprnotequal.getLeft(), document);
+ }
+
+ def dispatch void format(exprLess exprless, extension IFormattableDocument document) {
+ format(exprless.getRight(), document);
+ format(exprless.getLeft(), document);
+ }
+
+ def dispatch void format(exprGtEqual exprgtequal, extension IFormattableDocument document) {
+ format(exprgtequal.getRight(), document);
+ format(exprgtequal.getLeft(), document);
+ }
+
+ def dispatch void format(exprLtEqual exprltequal, extension IFormattableDocument document) {
+ format(exprltequal.getRight(), document);
+ format(exprltequal.getLeft(), document);
+ }
+
+ def dispatch void format(exprGt exprgt, extension IFormattableDocument document) {
+ format(exprgt.getRight(), document);
+ format(exprgt.getLeft(), document);
+ }
+
+ def dispatch void format(exprSLess exprsless, extension IFormattableDocument document) {
+ format(exprsless.getRight(), document);
+ format(exprsless.getLeft(), document);
+ }
+
+ def dispatch void format(exprSGtEqual exprsgtequal, extension IFormattableDocument document) {
+ format(exprsgtequal.getRight(), document);
+ format(exprsgtequal.getLeft(), document);
+ }
+
+ def dispatch void format(exprSLtEqual exprsltequal, extension IFormattableDocument document) {
+ format(exprsltequal.getRight(), document);
+ format(exprsltequal.getLeft(), document);
+ }
+
+ def dispatch void format(exprSGt exprsgt, extension IFormattableDocument document) {
+ format(exprsgt.getRight(), document);
+ format(exprsgt.getLeft(), document);
+ }
+
+ def dispatch void format(exprXor exprxor, extension IFormattableDocument document) {
+ format(exprxor.getRight(), document);
+ format(exprxor.getLeft(), document);
+ }
+
+ def dispatch void format(exprAnd exprand, extension IFormattableDocument document) {
+ format(exprand.getRight(), document);
+ format(exprand.getLeft(), document);
+ }
+
+ def dispatch void format(exprOr expror, extension IFormattableDocument document) {
+ format(expror.getRight(), document);
+ format(expror.getLeft(), document);
+ }
+
+ def dispatch void format(exprLeft exprleft, extension IFormattableDocument document) {
+ format(exprleft.getRight(), document);
+ format(exprleft.getLeft(), document);
+ }
+
+ def dispatch void format(exprRight exprright, extension IFormattableDocument document) {
+ format(exprright.getRight(), document);
+ format(exprright.getLeft(), document);
+ }
+
+ def dispatch void format(exprSRight exprsright, extension IFormattableDocument document) {
+ format(exprsright.getRight(), document);
+ format(exprsright.getLeft(), document);
+ }
+
+ def dispatch void format(exprMult exprmult, extension IFormattableDocument document) {
+ format(exprmult.getRight(), document);
+ format(exprmult.getLeft(), document);
+ }
+
+ def dispatch void format(exprDiv exprdiv, extension IFormattableDocument document) {
+ format(exprdiv.getRight(), document);
+ format(exprdiv.getLeft(), document);
+ }
+
+ def dispatch void format(exprSDiv exprsdiv, extension IFormattableDocument document) {
+ format(exprsdiv.getRight(), document);
+ format(exprsdiv.getLeft(), document);
+ }
+
+ def dispatch void format(exprRem exprrem, extension IFormattableDocument document) {
+ format(exprrem.getRight(), document);
+ format(exprrem.getLeft(), document);
+ }
+
+ def dispatch void format(exprSRem exprsrem, extension IFormattableDocument document) {
+ format(exprsrem.getRight(), document);
+ format(exprsrem.getLeft(), document);
+ }
+
+ def dispatch void format(exprBoolXor exprboolxor, extension IFormattableDocument document) {
+ format(exprboolxor.getRight(), document);
+ format(exprboolxor.getLeft(), document);
+ }
+
+ def dispatch void format(exprBoolAnd exprbooland, extension IFormattableDocument document) {
+ format(exprbooland.getRight(), document);
+ format(exprbooland.getLeft(), document);
+ }
+
+ def dispatch void format(exprBoolOr exprboolor, extension IFormattableDocument document) {
+ format(exprboolor.getRight(), document);
+ format(exprboolor.getLeft(), document);
+ }
+
+ def dispatch void format(exprFEqual exprfequal, extension IFormattableDocument document) {
+ format(exprfequal.getRight(), document);
+ format(exprfequal.getLeft(), document);
+ }
+
+ def dispatch void format(exprFNotEqual exprfnotequal, extension IFormattableDocument document) {
+ format(exprfnotequal.getRight(), document);
+ format(exprfnotequal.getLeft(), document);
+ }
+
+ def dispatch void format(exprFLess exprfless, extension IFormattableDocument document) {
+ format(exprfless.getRight(), document);
+ format(exprfless.getLeft(), document);
+ }
+
+ def dispatch void format(exprFGt exprfgt, extension IFormattableDocument document) {
+ format(exprfgt.getRight(), document);
+ format(exprfgt.getLeft(), document);
+ }
+
+ def dispatch void format(exprFLessEqual exprflessequal, extension IFormattableDocument document) {
+ format(exprflessequal.getRight(), document);
+ format(exprflessequal.getLeft(), document);
+ }
+
+ def dispatch void format(exprFGtEqual exprfgtequal, extension IFormattableDocument document) {
+ format(exprfgtequal.getRight(), document);
+ format(exprfgtequal.getLeft(), document);
+ }
+
+ def dispatch void format(exprFAdd exprfadd, extension IFormattableDocument document) {
+ format(exprfadd.getRight(), document);
+ format(exprfadd.getLeft(), document);
+ }
+
+ def dispatch void format(exprFSub exprfsub, extension IFormattableDocument document) {
+ format(exprfsub.getRight(), document);
+ format(exprfsub.getLeft(), document);
+ }
+
+ def dispatch void format(exprFMult exprfmult, extension IFormattableDocument document) {
+ format(exprfmult.getRight(), document);
+ format(exprfmult.getLeft(), document);
+ }
+
+ def dispatch void format(exprFDiv exprfdiv, extension IFormattableDocument document) {
+ format(exprfdiv.getRight(), document);
+ format(exprfdiv.getLeft(), document);
+ }
+
+ def dispatch void format(exprNegate exprnegate, extension IFormattableDocument document) {
+ format(exprnegate.getExpr(), document);
+ }
+
+ def dispatch void format(exprFNegate exprfnegate, extension IFormattableDocument document) {
+ format(exprfnegate.getExpr(), document);
+ }
+
+ def dispatch void format(exprLoad exprload, extension IFormattableDocument document) {
+ format(exprload.getLoc(), document);
+ format(exprload.getExpr(), document);
+ }
+
+ def dispatch void format(Expression expression, extension IFormattableDocument document) {
+ format(expression.getVnode(), document);
+ format(expression.getRight(), document);
+ format(expression.getOp1(), document);
+ format(expression.getOp2(), document);
+ }
+
+ def dispatch void format(exprSym exprsym, extension IFormattableDocument document) {
+ format(exprsym.getSize(), document);
+ format(exprsym.getStart(), document);
+ format(exprsym.getEnd(), document);
+ format(exprsym.getInode(), document);
+ }
+
+ def dispatch void format(sizedstar sizedstar, extension IFormattableDocument document) {
+ format(sizedstar.getSpace(), document);
+ format(sizedstar.getSize(), document);
+ }
+
+ def dispatch void format(jumpdest jumpdest, extension IFormattableDocument document) {
+ format(jumpdest.getInst_start(), document);
+ format(jumpdest.getInst_end(), document);
+ format(jumpdest.getConst(), document);
+ format(jumpdest.getSpace(), document);
+ }
+
+ def dispatch void format(integervarnode integervarnode, extension IFormattableDocument document) {
+ format(integervarnode.getReladdr(), document);
+ format(integervarnode.getConst(), document);
+ format(integervarnode.getSize(), document);
+ format(integervarnode.getInode(), document);
+ }
+
+ def dispatch void format(intblist intblist, extension IFormattableDocument document) {
+ for (intbpart args : intblist.getArgs()) {
+ format(args, document);
+ }
+ }
+
+ def dispatch void format(intbpart intbpart, extension IFormattableDocument document) {
+ format(intbpart.getValue(), document);
+ }
+
+ def dispatch void format(anystringlist anystringlist, extension IFormattableDocument document) {
+ for (anystringpart namelist : anystringlist.getNamelist()) {
+ format(namelist, document);
+ }
+ }
+
+ def dispatch void format(anystringpart anystringpart, extension IFormattableDocument document) {
+ format(anystringpart.getSym(), document);
+ }
+
+ def dispatch void format(valuesymlist valuesymlist, extension IFormattableDocument document) {
+ for (valuepart valuelist : valuesymlist.getValuelist()) {
+ format(valuelist, document);
+ }
+ format(valuesymlist.getValue(), document);
+ }
+
+ def dispatch void format(namesymlist namesymlist, extension IFormattableDocument document) {
+ for (NAMESYM valuelist : namesymlist.getValuelist()) {
+ format(valuelist, document);
+ }
+ format(namesymlist.getValue(), document);
+ }
+
+ def dispatch void format(varsymlist varsymlist, extension IFormattableDocument document) {
+ for (valuepartdef valuelist : varsymlist.getValuelist()) {
+ format(valuelist, document);
+ }
+ }
+
+ def dispatch void format(varlist varlist, extension IFormattableDocument document) {
+ for (varpart varDefList : varlist.getVarDefList()) {
+ format(varDefList, document);
+ }
+ }
+
+ def dispatch void format(paramlist paramlist, extension IFormattableDocument document) {
+ for (Expression parameters : paramlist.getParameters()) {
+ format(parameters, document);
+ }
+ }
+
+ def dispatch void format(oplist oplist, extension IFormattableDocument document) {
+ for (MACROPARAMSYM args : oplist.getArgs()) {
+ format(args, document);
+ }
+ }
+
+ def dispatch void format(anysymbol anysymbol, extension IFormattableDocument document) {
+ format(anysymbol.getSym(), document);
+ }
+
+ def dispatch void format(integerValue integervalue, extension IFormattableDocument document) {
+ format(integervalue.getSym(), document);
+ }
+
+ def dispatch void format(elleqRight elleqright, extension IFormattableDocument document) {
+ format(elleqright.getLeft(), document);
+ }
+}
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/generator/SleighGenerator.xtend b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/generator/SleighGenerator.xtend
new file mode 100644
index 0000000000..20d6025615
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/generator/SleighGenerator.xtend
@@ -0,0 +1,32 @@
+/* ###
+ * 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.
+ */
+package ghidra.xtext.sleigh.generator
+
+import org.eclipse.emf.ecore.resource.Resource
+import org.eclipse.xtext.generator.AbstractGenerator
+import org.eclipse.xtext.generator.IFileSystemAccess2
+import org.eclipse.xtext.generator.IGeneratorContext
+
+/**
+ * Generates code from your model files on save.
+ *
+ * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#code-generation
+ */
+class SleighGenerator extends AbstractGenerator {
+
+ override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) {
+ }
+}
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/scoping/SleighScopeProvider.xtend b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/scoping/SleighScopeProvider.xtend
new file mode 100644
index 0000000000..67078b6bff
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/scoping/SleighScopeProvider.xtend
@@ -0,0 +1,237 @@
+/* ###
+ * 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.
+ */
+package ghidra.xtext.sleigh.scoping
+
+
+import com.google.common.base.Function
+import com.google.common.base.Predicate
+import java.util.ArrayList
+import java.util.List
+import org.eclipse.emf.ecore.EObject
+import org.eclipse.emf.ecore.EReference
+import org.eclipse.xtext.naming.QualifiedName
+import org.eclipse.xtext.resource.IEObjectDescription
+import org.eclipse.xtext.scoping.IScope
+import org.eclipse.xtext.scoping.Scopes
+import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider
+import org.eclipse.xtext.scoping.impl.FilteringScope
+import org.eclipse.xtext.scoping.impl.ScopeBasedSelectable
+import org.eclipse.xtext.scoping.impl.SelectableBasedScope
+import ghidra.xtext.sleigh.sleigh.LOCALSYM
+import ghidra.xtext.sleigh.sleigh.aliasSym
+import ghidra.xtext.sleigh.sleigh.assignSym
+import ghidra.xtext.sleigh.sleigh.constraint
+import ghidra.xtext.sleigh.sleigh.constructor
+import ghidra.xtext.sleigh.sleigh.contextblock
+import ghidra.xtext.sleigh.sleigh.contextentry
+import ghidra.xtext.sleigh.sleigh.exportedSym
+import ghidra.xtext.sleigh.sleigh.exprSym
+import ghidra.xtext.sleigh.sleigh.globalLoc
+import ghidra.xtext.sleigh.sleigh.macrodef
+import ghidra.xtext.sleigh.sleigh.pexprSym
+import ghidra.xtext.sleigh.sleigh.rtlbody
+import ghidra.xtext.sleigh.sleigh.rtlmid
+import ghidra.xtext.sleigh.sleigh.statement
+import ghidra.xtext.sleigh.sleigh.xrtl
+
+import static extension org.eclipse.xtext.EcoreUtil2.*
+
+/**
+ * This class contains custom scoping description.
+ *
+ * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#scoping
+ * on how and when to use it.
+ */
+public class SleighScopeProvider extends AbstractDeclarativeScopeProvider {
+
+ override getScope(EObject context, EReference ref) {
+ //System.out.println(context.class.name + " - " + ref.name + " : ")
+ var scope = super.getScope(context, ref)
+ //System.out.println(" " + scope.toString)
+ return scope
+ }
+
+ def IScope scope_assignSym_symref(assignSym context, EReference eReference) {
+ var localScope = context.eContainer.symbolsDefinedBefore(context)
+ var cont = context.getContainerOfType(typeof(rtlbody));
+ var superscope = super.getDelegate().getScope(cont, eReference)
+ return createFilteredLocalScope(superscope, localScope, eReference)
+ }
+
+ def IScope scope_exprSym_vnode(exprSym context, EReference eReference) {
+ var localScope = context.eContainer.symbolsDefinedBefore(context)
+ var cont = context.getContainerOfType(typeof(rtlbody));
+ var superscope = super.getDelegate().getScope(cont, eReference)
+ return createFilteredLocalScope(superscope, localScope, eReference)
+ }
+
+ def IScope scope_exportedSym_symref(exportedSym context, EReference eReference) {
+ var localScope = context.eContainer.symbolsDefinedBefore(context)
+ var cont = context.getContainerOfType(typeof(rtlbody));
+ var superscope = super.getDelegate().getScope(cont, eReference)
+ createFilteredLocalScope(superscope, localScope, eReference)
+ }
+
+
+ def IScope scope_pexprSym_sym(pexprSym context, EReference eReference) {
+ var localScope = context.eContainer.symbolsDefinedBefore(context)
+ var cont = context.getContainerOfType(typeof(constructor));
+ var superscope = super.getDelegate().getScope(cont, eReference)
+ createFilteredLocalScope(superscope, localScope, eReference)
+ }
+
+
+ def IScope scope_constraint_sym(constraint context, EReference eReference) {
+ var cont = context.getContainerOfType(typeof(constructor));
+ var superscope = super.getDelegate().getScope(cont, eReference)
+ var scope= createFilteredLocalScope(superscope, IScope.NULLSCOPE, eReference)
+ scope
+ }
+
+ def IScope scope_aliasSym_symref(aliasSym context, EReference eReference) {
+ var cont = context.getContainerOfType(typeof(constructor));
+ var localScope = printPieceScope(cont,IScope.NULLSCOPE);
+ localScope
+ }
+
+ def IScope scope_contextentry_lhs(contextentry context, EReference eReference) {
+ var cont = context.getContainerOfType(typeof(constructor));
+ var localScope = printPieceScope(cont,IScope.NULLSCOPE);
+ var superscope = super.getDelegate().getScope(cont, eReference)
+ createFilteredLocalScope(superscope, localScope, eReference)
+ }
+
+ def IScope scope_globalLoc_tsym(globalLoc context, EReference eReference) {
+ var cont = context.getContainerOfType(typeof(constructor));
+ var localScope = printPieceScope(cont,IScope.NULLSCOPE);
+ var superscope = super.getDelegate().getScope(cont, eReference)
+ createFilteredLocalScope(superscope, localScope, eReference)
+ }
+
+ def IScope createFilteredLocalScope(IScope supscope, IScope localScope, EReference eReference) {
+ var filtscope = new FilteringScope(supscope, new Predicate() {
+ override apply(IEObjectDescription input) {
+ val sym = input.getEObjectOrProxy()
+ var notAliasOrLocal = !((sym instanceof LOCALSYM) || (sym instanceof aliasSym))
+ return notAliasOrLocal
+ }
+ });
+
+ // Do scope in reverse, aliasSyms are just and alias, choose global scope over alias
+ // The global scope has all LOCALSYM and aliasSym filtered out.
+ // This may not be the most efficient method, but works.
+ // Also for LOCALSYM, a Global sym may shadow it. Not quite right
+ // Should really be (LOCALSYM, Global(outerscope), AliasSym)
+ var scope = SelectableBasedScope.createScope(localScope, new ScopeBasedSelectable(filtscope),
+ eReference.getEReferenceType(), false)
+ scope
+ }
+
+ def dispatch IScope symbolsDefinedBefore(EObject context, EObject o) {
+ context.eContainer.symbolsDefinedBefore(o)
+ }
+
+ def dispatch IScope symbolsDefinedBefore(macrodef context, EObject o) {
+ Scopes::scopeFor(
+ context.args.args,
+ context.symbolsDefinedBefore(o.eContainer)
+ )
+ }
+
+ def dispatch IScope symbolsDefinedBefore(constructor s, EObject o) {
+ var scope = Scopes::scopeFor(s.eContents)
+ printPieceScope(s,scope);
+ }
+
+ def dispatch IScope symbolsDefinedBefore(contextblock s, EObject o) {
+ var scope = Scopes::scopeFor(s.eContents, s.eContainer.symbolsDefinedBefore(o.eContainer))
+ var cont = s.getContainerOfType(typeof(constructor))
+ printPieceScope(cont,scope);
+ }
+
+ def dispatch IScope symbolsDefinedBefore(rtlbody b, EObject o) {
+ var scope = Scopes::scopeFor(
+ b.body.statements.rtllist.variablesDeclaredBefore(o)
+ )
+ var cont = b.getContainerOfType(typeof(constructor));
+ printPieceScope(cont,scope);
+ }
+
+ def dispatch IScope symbolsDefinedBefore(rtlmid b, EObject o) {
+ return symbolsDefinedBefore(b.eContainer, o);
+ }
+
+ def dispatch IScope symbolsDefinedBefore(xrtl b, EObject o) {
+ var syms = b.statements.rtllist.variablesDeclaredBefore(null);
+ if (b.additionalStatements != null) {
+ syms.addAll(b.additionalStatements.rtllist.variablesDeclaredBefore(null))
+ }
+ var scope = Scopes::scopeFor(syms)
+ var cont = b.getContainerOfType(typeof(constructor));
+ printPieceScope(cont,scope);
+ }
+
+ // Create a scope for all ID symbols in printpiece
+ def printPieceScope(constructor cont, IScope outerScope) {
+ if (cont == null) return outerScope
+ var vars = cont.variablesDeclaredIn()
+ var q = QualifiedName.wrapper(new Function() {
+
+ override apply(aliasSym input) {
+ if (input == null) return null;
+ input.sym
+ }
+ })
+ var localScope = Scopes.scopeFor(vars, q, outerScope)
+ localScope
+ }
+
+ // things in context block must be in printpieces
+ def private variablesDeclaredIn(constructor b) {
+ var iter = b.print.printpieces.iterator;
+ var List list = new ArrayList();
+ while (iter.hasNext) {
+ var piece = iter.next;
+ if (piece.sym instanceof aliasSym) {
+ list.add(piece.sym)
+ }
+ }
+ return list
+ }
+
+ def private variablesDeclaredBefore(List list, EObject o) {
+ var end = list.size - 1;
+ if (o != null) {
+ end = list.indexOf(o);
+ }
+ val sublist = list.subList(0, end + 1);
+ var iter = sublist.iterator;
+ var List locList = new ArrayList();
+ while (iter.hasNext) {
+ var obj = iter.next;
+ if (obj instanceof statement) {
+ var stmt = obj as statement;
+ if (stmt.lhs != null && stmt.lhs.local != null && stmt.lhs.local.sym instanceof LOCALSYM) {
+ locList.add(stmt.lhs.local.sym as LOCALSYM);
+ }
+ if (stmt.ldef != null && stmt.ldef.sym instanceof LOCALSYM) {
+ locList.add(stmt.ldef.sym as LOCALSYM);
+ }
+ }
+ }
+ return locList;
+ }
+}
diff --git a/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/validation/SleighValidator.xtend b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/validation/SleighValidator.xtend
new file mode 100644
index 0000000000..b2e46bbd62
--- /dev/null
+++ b/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/validation/SleighValidator.xtend
@@ -0,0 +1,169 @@
+/* ###
+ * 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.
+ */
+package ghidra.xtext.sleigh.validation
+
+
+
+import java.util.HashMap
+import java.util.HashSet
+import org.eclipse.xtext.validation.Check
+import ghidra.xtext.sleigh.sleigh.Model
+import ghidra.xtext.sleigh.sleigh.SleighPackage
+import ghidra.xtext.sleigh.sleigh.VARSYM
+import ghidra.xtext.sleigh.sleigh.constraint
+import ghidra.xtext.sleigh.sleigh.contextdef
+import ghidra.xtext.sleigh.sleigh.contextfielddef
+import ghidra.xtext.sleigh.sleigh.fielddef
+import ghidra.xtext.sleigh.sleigh.tokendef
+import ghidra.xtext.sleigh.sleigh.vardef
+import ghidra.xtext.sleigh.sleigh.varnodedef
+
+import static extension org.eclipse.emf.ecore.util.EcoreUtil.*
+import static extension org.eclipse.xtext.EcoreUtil2.*
+
+/**
+ * This class contains custom validation rules.
+ *
+ * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#validation
+ */
+class SleighValidator extends AbstractSleighValidator {
+
+ var HashMap