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 memoryAreas = new ArrayList<>(); private final ParseTreeProperty 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 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; } }