diff options
Diffstat (limited to 'java/src/main/java/io/trygvis/ld/ElfinfoGnuLdListener.java')
-rw-r--r-- | java/src/main/java/io/trygvis/ld/ElfinfoGnuLdListener.java | 170 |
1 files changed, 170 insertions, 0 deletions
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; + } +} |