aboutsummaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2016-07-26 00:22:55 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2016-07-26 00:22:55 +0200
commit128e53d220d97225803d61d86f8e43439563181d (patch)
treee0d5da8d666c54d1d17e64ee6f52af424129f90d /java
downloadkicad-utils-128e53d220d97225803d61d86f8e43439563181d.tar.gz
kicad-utils-128e53d220d97225803d61d86f8e43439563181d.tar.bz2
kicad-utils-128e53d220d97225803d61d86f8e43439563181d.tar.xz
kicad-utils-128e53d220d97225803d61d86f8e43439563181d.zip
WIP: kicad_gen is a util to generate schematic.h files from KiCAD netlist files.
Current code contains a lexer and parser for KiCAD's netlist files and code to build a tree of the netlist which can be used for generation. Contains CMake code for integrating the generation into CMake too.
Diffstat (limited to 'java')
-rw-r--r--java/pom.xml87
-rw-r--r--java/src/main/java/io/trygvis/ld/CollectingErrorListener.java17
-rw-r--r--java/src/main/java/io/trygvis/ld/ElfinfoExprVisitor.java318
-rw-r--r--java/src/main/java/io/trygvis/ld/ElfinfoGnuLdListener.java170
-rw-r--r--java/src/main/java/io/trygvis/ld/ElfinfoGnuLdVisitor.java75
-rw-r--r--java/src/main/java/io/trygvis/ld/LdLoader.java121
-rw-r--r--java/src/main/java/io/trygvis/ld/StringGnuLdVisitor.java59
7 files changed, 847 insertions, 0 deletions
diff --git a/java/pom.xml b/java/pom.xml
new file mode 100644
index 0000000..4821b17
--- /dev/null
+++ b/java/pom.xml
@@ -0,0 +1,87 @@
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>io.trygvis.kicad</groupId>
+ <artifactId>kicad-utils</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4</artifactId>
+ <version>${antlr4-runtime.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-runtime</artifactId>
+ <version>${antlr4-runtime.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ <version>3.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <properties>
+ <antlr4-runtime.version>4.5.3</antlr4-runtime.version>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-maven-plugin</artifactId>
+ <version>${antlr4-runtime.version}</version>
+ <executions>
+ <execution>
+ <id>gnu</id>
+ <goals>
+ <goal>antlr4</goal>
+ </goals>
+ <configuration>
+ <arguments>
+ <argument>-package</argument>
+ <argument>io.trygvis.ld.antlr</argument>
+ </arguments>
+ <includes>
+ <include>GnuLd*.g4</include>
+ </includes>
+ <sourceDirectory>.</sourceDirectory>
+ <outputDirectory>target/generated-sources/antlr4/io/trygvis/ld/antlr</outputDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>test1</id>
+ <goals>
+ <goal>antlr4</goal>
+ </goals>
+ <configuration>
+ <arguments>
+ <argument>-package</argument>
+ <argument>io.trygvis.ld.test1</argument>
+ </arguments>
+ <includes>
+ <include>**/Test1*.g4</include>
+ </includes>
+ <outputDirectory>target/generated-sources/antlr4/io/trygvis/ld/test1</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ <configuration>
+ <visitor>true</visitor>
+ <outputDirectory>target/generated-sources/antlr4</outputDirectory>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/java/src/main/java/io/trygvis/ld/CollectingErrorListener.java b/java/src/main/java/io/trygvis/ld/CollectingErrorListener.java
new file mode 100644
index 0000000..968a02b
--- /dev/null
+++ b/java/src/main/java/io/trygvis/ld/CollectingErrorListener.java
@@ -0,0 +1,17 @@
+package io.trygvis.ld;
+
+import org.antlr.v4.runtime.BaseErrorListener;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Recognizer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CollectingErrorListener extends BaseErrorListener {
+ public final List<String> errors = new ArrayList<>();
+
+ public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
+ String s = line + ":" + charPositionInLine + " " + msg;
+ errors.add(s);
+ }
+}
diff --git a/java/src/main/java/io/trygvis/ld/ElfinfoExprVisitor.java b/java/src/main/java/io/trygvis/ld/ElfinfoExprVisitor.java
new file mode 100644
index 0000000..af5bea5
--- /dev/null
+++ b/java/src/main/java/io/trygvis/ld/ElfinfoExprVisitor.java
@@ -0,0 +1,318 @@
+package io.trygvis.ld;
+
+import io.trygvis.ld.antlr.GnuLdParser;
+import io.trygvis.ld.antlr.GnuLdParserBaseVisitor;
+import org.antlr.v4.runtime.tree.ParseTreeProperty;
+
+import java.math.BigInteger;
+
+class ElfinfoExprVisitor extends GnuLdParserBaseVisitor<ElfinfoExprVisitor> {
+ private BigInteger value;
+ private ParseTreeProperty<BigInteger> es = new ParseTreeProperty<>();
+
+ public static BigInteger evaluate(GnuLdParser.Mustbe_expContext ctx) {
+ ElfinfoExprVisitor v = new ElfinfoExprVisitor();
+ v.visitMustbe_exp(ctx);
+ return v.value();
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpLt(GnuLdParser.ExpLtContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpBlock(GnuLdParser.ExpBlockContext ctx) {
+ return visitChildren(ctx);
+
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpAbsolute(GnuLdParser.ExpAbsoluteContext ctx) {
+ return visitChildren(ctx);
+
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpLog2ceil(GnuLdParser.ExpLog2ceilContext ctx) {
+ return visitChildren(ctx);
+
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpAddr(GnuLdParser.ExpAddrContext ctx) {
+ return visitChildren(ctx);
+
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpDataSegmentEnd(GnuLdParser.ExpDataSegmentEndContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpSub(GnuLdParser.ExpSubContext ctx) {
+ System.out.println("ElfinfoExprVisitor.visitExpSub");
+
+ ElfinfoExprVisitor ret = visitChildren(ctx);
+ BigInteger a = es.removeFrom(ctx.exp(0));
+ BigInteger b = es.removeFrom(ctx.exp(1));
+
+ BigInteger x = a.subtract(b);
+
+ es.put(ctx, x);
+ return ret;
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpDefined(GnuLdParser.ExpDefinedContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpMod(GnuLdParser.ExpModContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpInvert(GnuLdParser.ExpInvertContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpAlign(GnuLdParser.ExpAlignContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpMul(GnuLdParser.ExpMulContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpAnd(GnuLdParser.ExpAndContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpXor(GnuLdParser.ExpXorContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpParen(GnuLdParser.ExpParenContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpMinus(GnuLdParser.ExpMinusContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpDiv(GnuLdParser.ExpDivContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpGe(GnuLdParser.ExpGeContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpMin(GnuLdParser.ExpMinContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpAlignK(GnuLdParser.ExpAlignKContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpNegate(GnuLdParser.ExpNegateContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpName(GnuLdParser.ExpNameContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpOr(GnuLdParser.ExpOrContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpTrinary(GnuLdParser.ExpTrinaryContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpOror(GnuLdParser.ExpOrorContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpDataSegmentAlign(GnuLdParser.ExpDataSegmentAlignContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpLengthExp(GnuLdParser.ExpLengthExpContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpAdd(GnuLdParser.ExpAddContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpLoadaddr(GnuLdParser.ExpLoadaddrContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpGt(GnuLdParser.ExpGtContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpOrigin(GnuLdParser.ExpOriginContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpEq(GnuLdParser.ExpEqContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpMax(GnuLdParser.ExpMaxContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpLshift(GnuLdParser.ExpLshiftContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpSizeofHeaders(GnuLdParser.ExpSizeofHeadersContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpLe(GnuLdParser.ExpLeContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpNe(GnuLdParser.ExpNeContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpAndand(GnuLdParser.ExpAndandContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpRshift(GnuLdParser.ExpRshiftContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpNextParen(GnuLdParser.ExpNextParenContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpAlignof(GnuLdParser.ExpAlignofContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpSegmentStart(GnuLdParser.ExpSegmentStartContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpInt(GnuLdParser.ExpIntContext ctx) {
+ System.out.println("ElfinfoExprVisitor.visitExpInt");
+
+ BigInteger i = parseInt(ctx.INT().getText());
+ es.put(ctx, i);
+
+ return this;
+ }
+
+ public static BigInteger parseInt(String str) {
+ str = str.toLowerCase();
+ int base = 10;
+ if (str.startsWith("0x")) {
+ base = 16;
+ str = str.substring(2);
+ }
+
+ int factor = 1;
+ if (str.endsWith("k")) {
+ factor = 1024;
+ str = str.substring(0, str.length() - 1);
+ } else if (str.endsWith("k")) {
+ factor = 1024 * 1024;
+ str = str.substring(0, str.length() - 1);
+ }
+
+ BigInteger i = new BigInteger(str, base);
+ if (factor > 1) {
+ i = i.multiply(BigInteger.valueOf(factor));
+ }
+ return i;
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpConstant(GnuLdParser.ExpConstantContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpPlus(GnuLdParser.ExpPlusContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpSizeof(GnuLdParser.ExpSizeofContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpDataSegmentRelRoEnd(GnuLdParser.ExpDataSegmentRelRoEndContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpAssert(GnuLdParser.ExpAssertContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitMustbe_exp(GnuLdParser.Mustbe_expContext ctx) {
+ ElfinfoExprVisitor ret = visitChildren(ctx);
+
+ value = es.removeFrom(ctx.exp());
+ es.put(ctx, value);
+
+ return ret;
+ }
+
+ public BigInteger value() {
+ if (value != null) {
+ return value;
+ }
+
+ throw new RuntimeException("Something bad happened, probably an unevaluated expression part.");
+ }
+}
diff --git a/java/src/main/java/io/trygvis/ld/ElfinfoGnuLdListener.java b/java/src/main/java/io/trygvis/ld/ElfinfoGnuLdListener.java
new file mode 100644
index 0000000..fe40547
--- /dev/null
+++ b/java/src/main/java/io/trygvis/ld/ElfinfoGnuLdListener.java
@@ -0,0 +1,170 @@
+package io.trygvis.ld;
+
+import io.trygvis.ld.antlr.GnuLdParser;
+import io.trygvis.ld.antlr.GnuLdParserBaseListener;
+import org.antlr.v4.runtime.tree.ParseTreeProperty;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+class ElfinfoGnuLdListener extends GnuLdParserBaseListener {
+ public List<LdLoader.MemoryArea> memoryAreas = new ArrayList<>();
+
+ private final ParseTreeProperty<BigInteger> expr = new ParseTreeProperty<>();
+
+ @Override
+ public void exitExpInt(GnuLdParser.ExpIntContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitExpInt: ctx.INT().getText() = " + ctx.INT().getText());
+ expr.put(ctx, ElfinfoExprVisitor.parseInt(ctx.INT().getText()));
+ }
+
+ @Override
+ public void exitExpSub(GnuLdParser.ExpSubContext ctx) {
+ BigInteger a = expr.get(ctx.exp(0));
+ BigInteger b = expr.get(ctx.exp(1));
+ BigInteger x = a.subtract(b);
+ expr.put(ctx, x);
+ }
+
+ @Override
+ public void exitExpAdd(GnuLdParser.ExpAddContext ctx) {
+ BigInteger a = expr.get(ctx.exp(0));
+ BigInteger b = expr.get(ctx.exp(1));
+ BigInteger x = a.add(b);
+ expr.put(ctx, x);
+ }
+
+ @Override
+ public void exitExpName(GnuLdParser.ExpNameContext ctx) {
+ expr.put(ctx, BigInteger.ZERO);
+ }
+
+ @Override
+ public void exitExpAddr(GnuLdParser.ExpAddrContext ctx) {
+ expr.put(ctx, BigInteger.ZERO);
+ }
+
+ @Override
+ public void exitExpSizeof(GnuLdParser.ExpSizeofContext ctx) {
+ expr.put(ctx, BigInteger.ZERO);
+ }
+
+ @Override
+ public void exitExpLengthExp(GnuLdParser.ExpLengthExpContext ctx) {
+ LdLoader.MemoryArea ma = getMemoryArea(ctx.NAME().getText());
+// System.out.println("ma.length = " + ma.length);
+ expr.put(ctx, ma.length);
+ }
+
+ @Override
+ public void exitExpOrigin(GnuLdParser.ExpOriginContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitExpOrigin: " + ctx.getText());
+ LdLoader.MemoryArea ma = getMemoryArea(ctx.NAME().getText());
+// System.out.println("ma.origin = " + ma.origin);
+ expr.put(ctx, ma.origin);
+ }
+
+ private LdLoader.MemoryArea getMemoryArea(String name) {
+ LdLoader.MemoryArea m = null;
+ for (LdLoader.MemoryArea ma : memoryAreas) {
+ if (ma.name.equals(name)) {
+ m = ma;
+ }
+ }
+ if (m == null) {
+ throw new RuntimeException("No such memory area: " + name);
+ }
+ return m;
+ }
+
+ @Override
+ public void enterMustbe_exp(GnuLdParser.Mustbe_expContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.enterMustbe_exp");
+ }
+
+ @Override
+ public void exitMustbe_exp(GnuLdParser.Mustbe_expContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitMustbe_exp");
+
+ expr.put(ctx, expr.get(ctx.exp()));
+ }
+
+
+ @Override
+ public void enterOrigin_spec(GnuLdParser.Origin_specContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.enterOrigin_spec");
+ }
+
+ @Override
+ public void exitOrigin_spec(GnuLdParser.Origin_specContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitOrigin_spec");
+ }
+
+ @Override
+ public void enterLength_spec(GnuLdParser.Length_specContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.enterLength_spec");
+ }
+
+ @Override
+ public void exitLength_spec(GnuLdParser.Length_specContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitLength_spec");
+ }
+
+ @Override
+ public void enterMemory_spec(GnuLdParser.Memory_specContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.enterMemory_spec");
+ }
+
+ @Override
+ public void exitMemory_spec(GnuLdParser.Memory_specContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitMemory_spec");
+ LdLoader.MemoryArea ma = new LdLoader.MemoryArea();
+ ma.name = ctx.NAME().getText();
+ ma.attributes = attributes;
+// System.out.println("ctx.origin_spec() = " + ctx.origin_spec());
+ ma.origin = expr.get(ctx.origin_spec().mustbe_exp());
+ ma.length = expr.get(ctx.length_spec().mustbe_exp());
+ System.out.println(ma);
+ memoryAreas.add(ma);
+ }
+
+ LdLoader.MemoryAttribute attribute;
+ boolean attributesInverted;
+ Set<LdLoader.MemoryAttribute> attributes;
+
+ @Override
+ public void exitAttributes_opt(GnuLdParser.Attributes_optContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitAttributes_opt");
+ attributes = new HashSet<>();
+ }
+
+ @Override
+ public void enterAttributeInverted(GnuLdParser.AttributeInvertedContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.enterAttributeInverted");
+
+ if (!attributes.isEmpty()) {
+ throw new RuntimeException("Attributes for memory areas can only be attributesInverted (with '!') as the first character in a specification; foo(!rw), not foo(x!rw).");
+ }
+// String name = ctx.name().getText();
+ String name = ctx.NAME().getText();
+// System.out.println("ctx.ATTRIBUTE().getText() = " + name);
+
+ attributesInverted = true;
+ }
+
+ @Override
+ public void enterAttributeNormal(GnuLdParser.AttributeNormalContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.enterAttributeNormal");
+
+ String name = ctx.NAME().getText();
+// System.out.println("ctx.ATTRIBUTE().getText() = " + name);
+ for (int i = 0; i < name.length(); i++) {
+ attribute = LdLoader.MemoryAttribute.valueOf(String.valueOf(Character.toUpperCase(name.charAt(i))));
+ attributes.add(attribute);
+ }
+ attributesInverted = false;
+ }
+}
diff --git a/java/src/main/java/io/trygvis/ld/ElfinfoGnuLdVisitor.java b/java/src/main/java/io/trygvis/ld/ElfinfoGnuLdVisitor.java
new file mode 100644
index 0000000..3062aad
--- /dev/null
+++ b/java/src/main/java/io/trygvis/ld/ElfinfoGnuLdVisitor.java
@@ -0,0 +1,75 @@
+package io.trygvis.ld;
+
+import io.trygvis.ld.antlr.GnuLdParser;
+import io.trygvis.ld.antlr.GnuLdParserBaseVisitor;
+import org.antlr.v4.runtime.tree.ParseTreeProperty;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class ElfinfoGnuLdVisitor extends GnuLdParserBaseVisitor<ElfinfoGnuLdVisitor> {
+ public List<LdLoader.MemoryArea> memoryAreas = new ArrayList<>();
+
+ ParseTreeProperty<BigInteger> es = new ParseTreeProperty<>();
+
+ @Override
+ public ElfinfoGnuLdVisitor visitMemory_spec(GnuLdParser.Memory_specContext ctx) {
+ System.out.println("ElfinfoGnuLdBaseVisitor.visitMemory_spec");
+ visitChildren(ctx);
+
+ if (attributesInverted) {
+ // not quite sure how this is supposed to work yet
+ throw new RuntimeException("Inverted memory region attributes is not implemented yet.");
+ }
+
+ LdLoader.MemoryArea ma = new LdLoader.MemoryArea();
+ ma.name = ctx.NAME().getText();
+ ma.attributes = attributes;
+ ma.origin = ElfinfoExprVisitor.evaluate(ctx.origin_spec().mustbe_exp());
+ ma.length = ElfinfoExprVisitor.evaluate(ctx.length_spec().mustbe_exp());
+ System.out.println(ma);
+ memoryAreas.add(ma);
+ return this;
+ }
+
+ LdLoader.MemoryAttribute attribute;
+ boolean attributesInverted;
+ Set<LdLoader.MemoryAttribute> attributes;
+
+ @Override
+ public ElfinfoGnuLdVisitor visitAttributes_opt(GnuLdParser.Attributes_optContext ctx) {
+ System.out.println("ElfinfoGnuLdBaseVisitor.visitAttributes_opt");
+ attributes = new HashSet<>();
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoGnuLdVisitor visitAttributeNormal(GnuLdParser.AttributeNormalContext ctx) {
+ System.out.println("ElfinfoGnuLdBaseVisitor.visitAttributeNormal");
+ String name = ctx.NAME().getText();
+ System.out.println("ctx.ATTRIBUTE().getText() = " + name);
+ for (int i = 0; i < name.length(); i++) {
+ attribute = LdLoader.MemoryAttribute.valueOf(String.valueOf(Character.toUpperCase(name.charAt(i))));
+ attributes.add(attribute);
+ }
+ attributesInverted = false;
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoGnuLdVisitor visitAttributeInverted(GnuLdParser.AttributeInvertedContext ctx) {
+ System.out.println("ElfinfoGnuLdBaseVisitor.visitAttributeInverted");
+ if (!attributes.isEmpty()) {
+ throw new RuntimeException("Attributes for memory areas can only be attributesInverted (with '!') as the first character in a specification; foo(!rw), not foo(x!rw).");
+ }
+// String name = ctx.name().getText();
+ String name = ctx.NAME().getText();
+ System.out.println("ctx.ATTRIBUTE().getText() = " + name);
+
+ attributesInverted = true;
+ return visitChildren(ctx);
+ }
+}
diff --git a/java/src/main/java/io/trygvis/ld/LdLoader.java b/java/src/main/java/io/trygvis/ld/LdLoader.java
new file mode 100644
index 0000000..0b71720
--- /dev/null
+++ b/java/src/main/java/io/trygvis/ld/LdLoader.java
@@ -0,0 +1,121 @@
+package io.trygvis.ld;
+
+import io.trygvis.ld.antlr.GnuLdLexer;
+import io.trygvis.ld.antlr.GnuLdParser;
+import org.antlr.v4.runtime.ANTLRFileStream;
+import org.antlr.v4.runtime.BufferedTokenStream;
+import org.antlr.v4.runtime.ConsoleErrorListener;
+
+import java.io.File;
+import java.math.BigInteger;
+import java.util.List;
+import java.util.Set;
+
+public class LdLoader {
+
+ public final List<MemoryArea> memoryAreas;
+
+ public LdLoader(List<MemoryArea> memoryAreas) {
+ this.memoryAreas = memoryAreas;
+ }
+
+ public enum MemoryAttribute {
+ R, W, X, A, I,
+ }
+
+ public static class MemoryArea {
+ private final BigInteger MEGA = BigInteger.valueOf(1024 * 1024);
+ private final BigInteger KILO = BigInteger.valueOf(1024);
+
+ String name;
+ BigInteger origin;
+ BigInteger length;
+ Set<MemoryAttribute> attributes;
+
+ @Override
+ public String toString() {
+ return "MemoryArea{" +
+ "name='" + name + '\'' +
+ ", origin=" + origin +
+ ", length=" + length +
+ ", attributes='" + attributes + '\'' +
+ '}';
+ }
+
+ public String prettyOrigin() {
+ if (origin == null) {
+ return "";
+ }
+ String hex = origin.toString(16);
+
+ return "0x" + ("00000000").substring(0, 8 - hex.length()) + hex;
+ }
+
+ public String prettyLength() {
+ if (length == null) {
+ return "";
+ }
+
+ if (length.compareTo(MEGA) >= 0 && length.mod(MEGA).equals(BigInteger.ZERO)) {
+ return length.divide(MEGA) + "M";
+ }
+
+ if (length.compareTo(KILO) >= 0 && length.mod(KILO).equals(BigInteger.ZERO)) {
+ return length.divide(KILO) + "k";
+ }
+
+ return String.valueOf(length);
+ }
+
+ public String prettyAttributes() {
+ String s = "";
+ for (MemoryAttribute attribute : attributes) {
+ s += attribute.name().toLowerCase();
+ }
+ return s;
+ }
+ }
+
+ public static LdLoader load(File path) throws Exception {
+ GnuLdLexer lexer = new GnuLdLexer(new ANTLRFileStream(path.getAbsolutePath()));
+ BufferedTokenStream tokens = new BufferedTokenStream(lexer);
+ GnuLdParser parser = new GnuLdParser(tokens);
+ parser.setBuildParseTree(true);
+ parser.removeErrorListeners();
+ ConsoleErrorListener errorListener = new ConsoleErrorListener();
+ parser.addErrorListener(errorListener);
+ CollectingErrorListener collectingErrorListener = new CollectingErrorListener();
+ parser.addErrorListener(collectingErrorListener);
+
+ ElfinfoGnuLdListener listener = new ElfinfoGnuLdListener();
+ parser.addParseListener(listener);
+
+ GnuLdParser.FileContext file = parser.file();
+
+ if (parser.getNumberOfSyntaxErrors() > 0) {
+ throw new ParseErrorException(lexer, tokens, parser, collectingErrorListener.errors
+ );
+ }
+
+// ElfinfoGnuLdVisitor visitor = new ElfinfoGnuLdVisitor();
+// visitor.visit(file);
+
+// return new LdLoader(visitor.memoryAreas);
+ return new LdLoader(listener.memoryAreas);
+ }
+
+ public static class ParseErrorException extends Exception {
+ public final GnuLdLexer lexer;
+ public final BufferedTokenStream tokens;
+ public final GnuLdParser parser;
+ public final List<String> errors;
+
+ public ParseErrorException(GnuLdLexer lexer, BufferedTokenStream tokens, GnuLdParser parser, List<String> errors) {
+ this.lexer = lexer;
+ this.tokens = tokens;
+ this.parser = parser;
+ this.errors = errors;
+ }
+ }
+
+}
diff --git a/java/src/main/java/io/trygvis/ld/StringGnuLdVisitor.java b/java/src/main/java/io/trygvis/ld/StringGnuLdVisitor.java
new file mode 100644
index 0000000..a975497
--- /dev/null
+++ b/java/src/main/java/io/trygvis/ld/StringGnuLdVisitor.java
@@ -0,0 +1,59 @@
+package io.trygvis.ld;
+
+import io.trygvis.ld.antlr.GnuLdParserBaseVisitor;
+import io.trygvis.ld.antlr.GnuLdParser;
+import org.antlr.v4.runtime.tree.ParseTree;
+
+import java.util.List;
+
+class StringGnuLdVisitor extends GnuLdParserBaseVisitor<String> {
+
+// public static String parseName(GnuLdParser.NameContext ctx) {
+// return "";
+// }
+
+ /*
+ public static String parseName(GnuLdParser.NameContext ctx) {
+ StringGnuLdVisitor v = new StringGnuLdVisitor();
+ return v.visit(ctx);
+ }
+
+ private StringBuilder string = new StringBuilder();
+
+ @Override
+ public String visitNamePlain(GnuLdParser.NamePlainContext ctx) {
+ System.out.println("NameTest.visitNamePlain");
+ String s = ctx.NAME().getText();
+ string.append(s);
+ return s;
+ }
+
+// @Override
+// public String visitName_or_space(GnuLdParser.Name_or_spaceContext ctx) {
+// System.out.println("StringGnuLdBaseVisitor.visitName_or_space");
+//
+// TerminalNode name = ctx.NAME();
+// String s = name != null ? name.getText() : " ";
+// string.append(s);
+// return s;
+// }
+
+ @Override
+ public String visitNameQuoted(GnuLdParser.NameQuotedContext ctx) {
+ System.out.println("StringGnuLdBaseVisitor.visitNameQuoted");
+ List<ParseTree> children = ctx.children;
+ System.out.println("children.size()) = " + children.size());
+
+ String s = "";
+ for (int i = 1; i < children.size() - 1; i++) {
+ ParseTree part = children.get(i);
+ System.out.println("part.getText() = " + part.getText());
+ s += part.getText();
+ }
+
+ return s;
+//
+// return visitChildren(ctx);
+ }
+ */
+}