diff --git a/java_tools/ConfigDefinition.jar b/java_tools/ConfigDefinition.jar index 6821a9a236..aaf6327cc2 100644 Binary files a/java_tools/ConfigDefinition.jar and b/java_tools/ConfigDefinition.jar differ diff --git a/java_tools/configuration_definition/src/main/java/com/rusefi/ldmp/LiveDataProcessor.java b/java_tools/configuration_definition/src/main/java/com/rusefi/ldmp/LiveDataProcessor.java index 1f0a834e75..54dbca8916 100644 --- a/java_tools/configuration_definition/src/main/java/com/rusefi/ldmp/LiveDataProcessor.java +++ b/java_tools/configuration_definition/src/main/java/com/rusefi/ldmp/LiveDataProcessor.java @@ -7,11 +7,11 @@ import com.rusefi.RusefiParseErrorStrategy; import com.rusefi.newparse.ParseState; import com.rusefi.newparse.outputs.CStructWriter; +import com.rusefi.newparse.outputs.JavaFieldsWriter; import com.rusefi.newparse.outputs.OutputChannelWriter; import com.rusefi.newparse.outputs.SdLogWriter; import com.rusefi.newparse.parsing.Definition; import com.rusefi.output.*; -import com.rusefi.util.LazyFile; import org.yaml.snakeyaml.Yaml; import java.io.File; @@ -88,7 +88,7 @@ private int handleYaml(Map data) throws IOException { int startingPosition = outputChannelWriter.getSize(); log.info("Starting " + name + " at " + startingPosition + " with [" + conditional + "]"); - baseAddressCHeader.append("#define " + name.toUpperCase() + "_BASE_ADDRESS " + startingPosition + "\n"); + baseAddressCHeader.append("#define ").append(name.toUpperCase()).append("_BASE_ADDRESS ").append(startingPosition).append("\n"); ReaderStateImpl state = new ReaderStateImpl(); state.setDefinitionInputFile(folder + File.separator + name + ".txt"); @@ -99,17 +99,11 @@ private int handleYaml(Map data) throws IOException { state.addPrepend(prepend); String cHeaderDestination = folder + File.separator + name + "_generated.h"; - int baseOffset = outputChannelWriter.getSize(); - - if (javaName != null) { - state.addDestination(new FileJavaFieldsConsumer(state, "../java_console/models/src/main/java/com/rusefi/config/generated/" + javaName, baseOffset)); - } - if (constexpr != null) { outputValueConsumer.currentSectionPrefix = constexpr; outputValueConsumer.conditional = conditional; outputValueConsumer.isPtr = isPtr; - state.addDestination(outputValueConsumer::handleEndStruct); + state.addDestination(outputValueConsumer); } { @@ -126,17 +120,24 @@ private int handleYaml(Map data) throws IOException { CStructWriter cStructs = new CStructWriter(); cStructs.writeCStructs(parseState, cHeaderDestination); - if (outputNames.length == 0) { + if (javaName != null) { + JavaFieldsWriter javaWriter = new JavaFieldsWriter("../java_console/models/src/main/java/com/rusefi/config/generated/" + javaName, outputChannelWriter.getSize()); + javaWriter.writeDefinitions(parseState.getDefinitions()); + javaWriter.writeFields(parseState); + javaWriter.finish(); + } + + if (outputNames.length == 0) { outputChannelWriter.writeOutputChannels(parseState, null); - } else { - for (String outputName : outputNames) { - outputChannelWriter.writeOutputChannels(parseState, outputName); - } - } - - if (constexpr != null) { - sdLogWriter.writeSdLogs(parseState, constexpr + (isPtr ? "->" : ".")); - } + } else { + for (String outputName : outputNames) { + outputChannelWriter.writeOutputChannels(parseState, outputName); + } + } + + if (constexpr != null) { + sdLogWriter.writeSdLogs(parseState, constexpr + (isPtr ? "->" : ".")); + } } state.doJob(); diff --git a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/ParseState.java b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/ParseState.java index 291626cab3..cccdc11fdc 100644 --- a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/ParseState.java +++ b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/ParseState.java @@ -54,6 +54,10 @@ public ParseState(EnumsReader enumsReader) { } } + public Map getDefinitions() { + return definitions; + } + private void handleIntDefinition(String name, int value) { addDefinition(name, value); diff --git a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/outputs/JavaFieldsWriter.java b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/outputs/JavaFieldsWriter.java index 8701a89fd1..befafdc06e 100644 --- a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/outputs/JavaFieldsWriter.java +++ b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/outputs/JavaFieldsWriter.java @@ -1,25 +1,160 @@ package com.rusefi.newparse.outputs; +import com.rusefi.VariableRegistry; import com.rusefi.newparse.ParseState; -import com.rusefi.newparse.layout.StructLayout; +import com.rusefi.newparse.layout.*; +import com.rusefi.newparse.parsing.Definition; import com.rusefi.newparse.parsing.Struct; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.PrintStream; +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Comparator; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; public class JavaFieldsWriter { private final PrintStream ps; - public JavaFieldsWriter(String outputFile, String javaConstants) throws FileNotFoundException { - this.ps = new PrintStreamAlwaysUnix(new FileOutputStream(outputFile)); + private final int baseOffset; - ps.println(javaConstants); + public JavaFieldsWriter(final String outputFile, int baseOffset) throws IOException { + ps = new PrintStreamAlwaysUnix(Files.newOutputStream(Paths.get(outputFile))); + this.baseOffset = baseOffset; + + String className = new File(outputFile).getName(); + ps.println("package com.rusefi.config.generated;"); + ps.println(); + ps.println("import com.rusefi.config.*;"); + ps.println(); + ps.println("public class " + className.substring(0, className.indexOf('.')) + " {"); + } + + public void finish() { + ps.println("}"); + ps.close(); + } + + public void writeDefinitions(final Map defs) { + Stream> sortedDefs = defs.entrySet().stream().sorted(Map.Entry.comparingByKey()); + + for (final Map.Entry d : sortedDefs.collect(Collectors.toList())) { + String name = d.getKey(); + + if (name.endsWith(VariableRegistry._16_HEX_SUFFIX) || name.endsWith(VariableRegistry._HEX_SUFFIX)) { + continue; + } + + ps.print("\tpublic static final "); + + if (d.getValue().isInteger()) { + ps.print("int " + d.getKey() + " = " + d.getValue().asInt()); + } else if (d.getValue().isNumeric()) { + ps.print("double " + d.getKey() + " = " + d.getValue().asDouble()); + } else { + ps.print("String " + d.getKey() + " = " + d.getValue().toString()); + } + + ps.println(";"); + } } - public void writeJavaFields(ParseState parser) { + public void writeFields(ParseState parser) { + // Assume the last struct is the one we want... Struct s = parser.getStructs().get(parser.getStructs().size() - 1); StructLayout sl = new StructLayout(0, "root", s); + + JavaFieldVisitor visitor = new JavaFieldVisitor(); + StructNamePrefixer prefixer = new StructNamePrefixer('_'); + + visitor.visitRoot(sl, ps, prefixer); + } + + private class JavaFieldVisitor extends ILayoutVisitor { + public void visitRoot(StructLayout sl, PrintStream ps, StructNamePrefixer prefixer) { + sl.children.forEach(c -> c.visit(this, ps, prefixer, 0, new int[0])); + } + + public void visit(StructLayout struct, PrintStream ps, StructNamePrefixer prefixer, int offsetAdd, int[] arrayDims) { + if (arrayDims.length == 0) { + visit(struct, ps, prefixer, offsetAdd, struct.name.toUpperCase()); + } else if (arrayDims.length == 1) { + int elementOffset = offsetAdd + struct.offset; + for (int i = 0; i < arrayDims[0]; i++) { + visit(struct, ps, prefixer, elementOffset, struct.name.toUpperCase() + (i + 1)); + elementOffset += struct.size; + } + } else { + throw new IllegalStateException("Java fields don't support multi dimension arrays of structs"); + } + } + + private String toJavaType(String tsType) { + switch (tsType) { + case "S08": + case "U08": return "INT8"; + case "S16": + case "U16": return "INT16"; + case "S32": + case "U32": return "INT"; + case "F32": return "FLOAT"; + } + + throw new IllegalArgumentException("toJavaType didn't understand " + tsType); + } + + private void visit(ScalarLayout scalar, PrintStream ps, StructNamePrefixer prefixer, int offsetAdd, int idx) { + String name = prefixer.get(scalar.name.toUpperCase()); + if (idx != -1) { + name = name + idx; + } + + ps.print("\tpublic static final Field "); + ps.print(name); + ps.print(" = Field.create(\""); + ps.print(name); + ps.print("\", "); + ps.print(scalar.offset + offsetAdd); + ps.print(", FieldType."); + ps.print(toJavaType(scalar.type.tsType)); + + // if (scalar.options.scale != 1) { + if (!scalar.type.tsType.equals("F32")) { + ps.print(").setScale("); + ps.print(scalar.options.scale); + } + + ps.print(").setBaseOffset("); + + // TODO + ps.print(baseOffset); + + ps.println(");"); + } + + public void visit(ScalarLayout scalar, PrintStream ps, StructNamePrefixer prefixer, int offsetAdd, int[] arrayDims) { + if (arrayDims.length == 0) { + visit(scalar, ps, prefixer, offsetAdd, -1); + } else if (arrayDims.length == 1) { + int elementOffset = offsetAdd; + + for (int i = 0; i < arrayDims[0]; i++) { + visit(scalar, ps, prefixer, elementOffset, i + 1); + elementOffset += scalar.type.size; + } + } else { + throw new IllegalStateException("Output channels don't support multi dimension arrays"); + } + } + + public void visit(BitGroupLayout bitGroup, PrintStream ps, StructNamePrefixer prefixer, int offsetAdd, int[] arrayDims) { + } + + @Override + public void visit(UnusedLayout struct, PrintStream ps, StructNamePrefixer prefixer, int offsetAdd, int[] arrayDims) { + // Do nothing + } } } diff --git a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/parsing/Definition.java b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/parsing/Definition.java index 089d9c387b..fb327778b7 100644 --- a/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/parsing/Definition.java +++ b/java_tools/configuration_definition/src/main/java/com/rusefi/newparse/parsing/Definition.java @@ -21,6 +21,10 @@ public boolean isNumeric() { return this.value instanceof Double || this.value instanceof Integer; } + public boolean isInteger() { + return this.value instanceof Integer; + } + public double asDouble() { if (this.value instanceof Double) { return ((Double)this.value); @@ -29,6 +33,10 @@ public double asDouble() { } } + public int asInt() { + return (Integer)this.value; + } + @Override public String toString() { return this.value.toString();