diff --git a/java_tools/ConfigDefinition.jar b/java_tools/ConfigDefinition.jar index 72dbe6cd99..1991d4b8d3 100644 Binary files a/java_tools/ConfigDefinition.jar and b/java_tools/ConfigDefinition.jar differ diff --git a/java_tools/configuration_definition/src/com/rusefi/ConfigDefinition.java b/java_tools/configuration_definition/src/com/rusefi/ConfigDefinition.java index 64e088845f..9691e2bce5 100644 --- a/java_tools/configuration_definition/src/com/rusefi/ConfigDefinition.java +++ b/java_tools/configuration_definition/src/com/rusefi/ConfigDefinition.java @@ -256,7 +256,10 @@ public class ConfigDefinition { // First process yaml files //processYamls(listener, yamlFiles); - // First load prepend files + // Process firing order enum + handleFiringOrder(firingEnumFileName, listener); + + // Load prepend files { // Ignore duplicates of definitions made during prepend phase listener.setDefinitionPolicy(Definition.OverwritePolicy.IgnoreNew); @@ -344,6 +347,13 @@ public class ConfigDefinition { } } + private static void handleFiringOrder(String firingEnumFileName, ParseState parser) throws IOException { + if (firingEnumFileName != null) { + SystemOut.println("Reading firing from " + firingEnumFileName); + parser.addDefinition("FIRINGORDER", FiringOrderTSLogic.invoke(firingEnumFileName), Definition.OverwritePolicy.NotAllowed); + } + } + private static long signatureHash(String tsPath, List inputAllFiles) throws IOException { // get CRC32 of given input files long crc32 = 0; diff --git a/java_tools/configuration_definition/src/com/rusefi/newparse/ParseState.java b/java_tools/configuration_definition/src/com/rusefi/newparse/ParseState.java index c25d9f193e..ca3016996d 100644 --- a/java_tools/configuration_definition/src/com/rusefi/newparse/ParseState.java +++ b/java_tools/configuration_definition/src/com/rusefi/newparse/ParseState.java @@ -10,6 +10,7 @@ import org.jetbrains.annotations.Nullable; import java.io.PrintStream; import java.util.*; +import java.util.regex.Pattern; import java.util.stream.Collectors; public class ParseState extends RusefiConfigGrammarBaseListener { @@ -91,7 +92,7 @@ public class ParseState extends RusefiConfigGrammarBaseListener { } public void addDefinition(String name, Object value, Definition.OverwritePolicy overwritePolicy) { - Definition existingDefinition = definitions.getOrDefault(name, null); + Definition existingDefinition = this.definitions.getOrDefault(name, null); if (existingDefinition != null) { switch (existingDefinition.overwritePolicy) { @@ -108,16 +109,29 @@ public class ParseState extends RusefiConfigGrammarBaseListener { definitions.put(name, new Definition(name, value, overwritePolicy)); } + public Definition findDefinition(String name) { + return this.definitions.getOrDefault(name, null); + } + public void setDefinitionPolicy(Definition.OverwritePolicy policy) { this.definitionOverwritePolicy = policy; } + private static final Pattern CHAR_LITERAL = Pattern.compile("'.'"); + + private void handleIntDefinition(String name, int value) { + addDefinition(name, value); + + // Also add ints as 16b hex + addDefinition(name + "_16_hex", String.format("\\\\x%02x\\\\x%02x", (value >> 8) & 0xFF, value & 0xFF)); + } + @Override public void exitDefinition(RusefiConfigGrammarParser.DefinitionContext ctx) { String name = ctx.identifier().getText(); if (ctx.integer() != null) { - addDefinition(name, Integer.parseInt(ctx.integer().getText())); + handleIntDefinition(name, Integer.parseInt(ctx.integer().getText())); } else if (ctx.floatNum() != null) { addDefinition(name, Double.parseDouble(ctx.floatNum().getText())); } else if (ctx.numexpr() != null) { @@ -126,14 +140,20 @@ public class ParseState extends RusefiConfigGrammarBaseListener { if (Math.abs(floored - evalResult) < 0.001) { // value is an int, process as such - addDefinition(name, (int)floored); + handleIntDefinition(name, (int)floored); } else { // Value is a double, add it addDefinition(name, evalResult); } } else { // glue the list of definitions back together - addDefinition(name, ctx.restOfLine().getText()); + String defText = ctx.restOfLine().getText(); + addDefinition(name, defText); + + // If the definition matches a char literal, add a special definition for that + if (CHAR_LITERAL.matcher(defText).find()) { + addDefinition(name + "_char", defText.charAt(1)); + } } } diff --git a/java_tools/configuration_definition/src/com/rusefi/newparse/outputs/TsWriter.java b/java_tools/configuration_definition/src/com/rusefi/newparse/outputs/TsWriter.java index 3c596ca483..716dc576de 100644 --- a/java_tools/configuration_definition/src/com/rusefi/newparse/outputs/TsWriter.java +++ b/java_tools/configuration_definition/src/com/rusefi/newparse/outputs/TsWriter.java @@ -2,18 +2,69 @@ package com.rusefi.newparse.outputs; import com.rusefi.newparse.ParseState; import com.rusefi.newparse.layout.StructLayout; +import com.rusefi.newparse.parsing.Definition; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.PrintStream; +import java.io.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class TsWriter { - public void writeTunerstudio(ParseState parser, String inputFile, String outputFile) throws FileNotFoundException { - // Write to file! + // matches strings in the form of @@MY_var_123@@ + private static final Pattern VAR = Pattern.compile("@@([a-zA-Z0-9_]+?)@@"); + + private static final Pattern OPTIONAL_LINE = Pattern.compile("@@if_([a-zA-Z0-9_]+)"); + + public void writeTunerstudio(ParseState parser, String inputFile, String outputFile) throws FileNotFoundException, IOException { + BufferedReader is = new BufferedReader(new FileReader(inputFile)); PrintStream ps = new PrintStream(new FileOutputStream(outputFile)); - writeLayoutAndComments(parser, ps); + // TODO: handle signature + parser.addDefinition("TS_SIGNATURE", "sig", Definition.OverwritePolicy.NotAllowed); + while (is.ready()) { + String line = is.readLine(); + + if (line.contains("CONFIG_DEFINITION_START")) { + writeLayoutAndComments(parser, ps); + continue; + } + + // Check if this line has a "skip me" suffix + Matcher match = OPTIONAL_LINE.matcher(line); + if (match.find()) { + String varName = match.group(1); + + Definition def = parser.findDefinition(varName); + + if (def == null || def.toString().equals("false")) { + // Definition was missing or false, skip this line + continue; + } + + // Delete that part of the line + line = line.replace(match.group(0), ""); + } + + // While there is a line to replace, do it + while (line.contains("@@")) { + match = VAR.matcher(line); + + if (!match.find()) { + throw new RuntimeException("Failed to resolve definition in line: " + line); + } + + String varName = match.group(1); + Definition def = parser.findDefinition(varName); + line = line.replaceAll(match.group(0), def != null ? def.toString() : "MISSING DEFINITION"); + } + + // TODO: remove extra whitespace from the line + + // Copy the line to the output stream + ps.println(line); + } + + is.close(); ps.close(); } @@ -22,8 +73,11 @@ public class TsWriter { TsMetadata meta = new TsMetadata(); // Print configuration layout + int size = root.getSize(); + ps.println("pageSize = " + size); + ps.println("page = 1"); root.writeTunerstudioLayout(ps, meta); - ps.println("; total TS size = " + root.getSize()); + ps.println("; total TS size = " + size); // Print context help ps.println("[SettingContextHelp]"); diff --git a/java_tools/configuration_definition/src/com/rusefi/newparse/parsing/Definition.java b/java_tools/configuration_definition/src/com/rusefi/newparse/parsing/Definition.java index ccd1dbc884..089d9c387b 100644 --- a/java_tools/configuration_definition/src/com/rusefi/newparse/parsing/Definition.java +++ b/java_tools/configuration_definition/src/com/rusefi/newparse/parsing/Definition.java @@ -28,4 +28,9 @@ public class Definition { return ((Integer)this.value).doubleValue(); } } + + @Override + public String toString() { + return this.value.toString(); + } }