generate java enum from C enum? generate both C and java from yaml? #2102

This commit is contained in:
rusefillc 2021-10-23 22:34:08 -04:00
parent a6097a4c35
commit 6e909d4467
20 changed files with 232 additions and 153 deletions

View File

@ -29,11 +29,9 @@ import java.util.zip.CRC32;
*/ */
@SuppressWarnings("StringConcatenationInsideStringBufferAppend") @SuppressWarnings("StringConcatenationInsideStringBufferAppend")
public class ConfigDefinition { public class ConfigDefinition {
public static final String EOL = "\n";
private static final String SIGNATURE_HASH = "SIGNATURE_HASH"; private static final String SIGNATURE_HASH = "SIGNATURE_HASH";
public static String MESSAGE; public static String MESSAGE;
public static String TOOL = "(unknown script)";
private static final String ROM_RAIDER_XML_TEMPLATE = "rusefi_template.xml"; private static final String ROM_RAIDER_XML_TEMPLATE = "rusefi_template.xml";
public static final String KEY_DEFINITION = "-definition"; public static final String KEY_DEFINITION = "-definition";
private static final String KEY_ROMRAIDER_INPUT = "-romraider"; private static final String KEY_ROMRAIDER_INPUT = "-romraider";
@ -66,10 +64,6 @@ public class ConfigDefinition {
public static boolean needZeroInit = true; public static boolean needZeroInit = true;
public static String definitionInputFile = null; public static String definitionInputFile = null;
public static String getGeneratedAutomaticallyTag() {
return LazyFile.LAZY_FILE_TAG + "ConfigDefinition.jar based on " + TOOL + " ";
}
public static void main(String[] args) { public static void main(String[] args) {
try { try {
doJob(args); doJob(args);
@ -127,7 +121,7 @@ public class ConfigDefinition {
String key = args[i]; String key = args[i];
switch (key) { switch (key) {
case "-tool": case "-tool":
ConfigDefinition.TOOL = args[i + 1]; ToolUtil.TOOL = args[i + 1];
break; break;
case KEY_DEFINITION: case KEY_DEFINITION:
definitionInputFile = args[i + 1]; definitionInputFile = args[i + 1];
@ -240,12 +234,12 @@ public class ConfigDefinition {
handleFiringOrder(firingEnumFileName, state.variableRegistry); handleFiringOrder(firingEnumFileName, state.variableRegistry);
MESSAGE = getGeneratedAutomaticallyTag() + definitionInputFile + " " + new Date(); MESSAGE = ToolUtil.getGeneratedAutomaticallyTag() + definitionInputFile + " " + new Date();
SystemOut.println("Reading definition from " + definitionInputFile); SystemOut.println("Reading definition from " + definitionInputFile);
for (String prependFile : prependFiles) for (String prependFile : prependFiles)
readPrependValues(state.variableRegistry, prependFile); state.variableRegistry.readPrependValues(prependFile);
if (yamlFiles != null) { if (yamlFiles != null) {
processYamls(state.variableRegistry, yamlFiles, state); processYamls(state.variableRegistry, yamlFiles, state);
@ -267,8 +261,8 @@ public class ConfigDefinition {
parseState.setDefinitionPolicy(Definition.OverwritePolicy.IgnoreNew); parseState.setDefinitionPolicy(Definition.OverwritePolicy.IgnoreNew);
//for (String prependFile : prependFiles) { //for (String prependFile : prependFiles) {
// TODO: fix signature define file parsing // TODO: fix signature define file parsing
//parseFile(listener, prependFile); //parseFile(listener, prependFile);
//} //}
} }
@ -299,7 +293,7 @@ public class ConfigDefinition {
VariableRegistry tmpRegistry = new VariableRegistry(); VariableRegistry tmpRegistry = new VariableRegistry();
// store the CRC32 as a built-in variable // store the CRC32 as a built-in variable
tmpRegistry.register(SIGNATURE_HASH, "" + crc32); tmpRegistry.register(SIGNATURE_HASH, "" + crc32);
readPrependValues(tmpRegistry, signaturePrependFile); tmpRegistry.readPrependValues(signaturePrependFile);
destinations.add(new SignatureConsumer(signatureDestination, tmpRegistry)); destinations.add(new SignatureConsumer(signatureDestination, tmpRegistry));
} }
if (needToUpdateOtherFiles) { if (needToUpdateOtherFiles) {
@ -329,7 +323,7 @@ public class ConfigDefinition {
if (destCDefinesFileName != null && needToUpdateOtherFiles) if (destCDefinesFileName != null && needToUpdateOtherFiles)
state.variableRegistry.writeDefinesToFile(destCDefinesFileName); writeDefinesToFile(state.variableRegistry, destCDefinesFileName);
if (romRaiderDestination != null && romRaiderInputFile != null && needToUpdateOtherFiles) { if (romRaiderDestination != null && romRaiderInputFile != null && needToUpdateOtherFiles) {
processTextTemplate(state, romRaiderInputFile, romRaiderDestination); processTextTemplate(state, romRaiderInputFile, romRaiderDestination);
@ -376,22 +370,6 @@ public class ConfigDefinition {
return needToUpdateTsFiles; return needToUpdateTsFiles;
} }
public static void readPrependValues(VariableRegistry registry, String prependFile) throws IOException {
BufferedReader definitionReader = new BufferedReader(new FileReader(prependFile));
String line;
while ((line = definitionReader.readLine()) != null) {
line = trimLine(line);
/**
* we should ignore empty lines and comments
*/
if (ReaderState.isEmptyDefinitionLine(line))
continue;
if (startsWithToken(line, ReaderState.DEFINE)) {
processDefine(registry, line.substring(ReaderState.DEFINE.length()).trim());
}
}
}
public static void processYamls(VariableRegistry registry, File[] yamlFiles, ReaderState state) throws IOException { public static void processYamls(VariableRegistry registry, File[] yamlFiles, ReaderState state) throws IOException {
ArrayList<Map<String, Object>> listPins = new ArrayList<>(); ArrayList<Map<String, Object>> listPins = new ArrayList<>();
for (File yamlFile : yamlFiles) { for (File yamlFile : yamlFiles) {
@ -524,7 +502,7 @@ public class ConfigDefinition {
SystemOut.println("Reading from " + inputFileName); SystemOut.println("Reading from " + inputFileName);
SystemOut.println("Writing to " + outputFileName); SystemOut.println("Writing to " + outputFileName);
state.variableRegistry.put("generator_message", ConfigDefinition.getGeneratedAutomaticallyTag() + new Date()); state.variableRegistry.put("generator_message", ToolUtil.getGeneratedAutomaticallyTag() + new Date());
File inputFile = new File(inputFileName); File inputFile = new File(inputFileName);
@ -534,30 +512,19 @@ public class ConfigDefinition {
String line; String line;
while ((line = fr.readLine()) != null) { while ((line = fr.readLine()) != null) {
line = state.variableRegistry.applyVariables(line); line = state.variableRegistry.applyVariables(line);
fw.write(line + ConfigDefinition.EOL); fw.write(line + ToolUtil.EOL);
} }
fw.close(); fw.close();
} }
static String trimLine(String line) {
line = line.trim();
line = line.replaceAll("\\s+", " ");
return line;
}
static boolean startsWithToken(String line, String token) {
return line.startsWith(token + " ") || line.startsWith(token + "\t");
}
public static String getComment(String comment, int currentOffset, String units) { public static String getComment(String comment, int currentOffset, String units) {
String start = "\t/**"; String start = "\t/**";
String packedComment = packComment(comment, "\t"); String packedComment = packComment(comment, "\t");
String unitsComment = units.isEmpty() ? "" : "\t" + units + EOL; String unitsComment = units.isEmpty() ? "" : "\t" + units + ToolUtil.EOL;
return start + EOL + return start + ToolUtil.EOL +
packedComment + packedComment +
unitsComment + unitsComment +
"\t * offset " + currentOffset + EOL + "\t */" + EOL; "\t * offset " + currentOffset + ToolUtil.EOL + "\t */" + ToolUtil.EOL;
} }
public static String packComment(String comment, String linePrefix) { public static String packComment(String comment, String linePrefix) {
@ -567,7 +534,7 @@ public class ConfigDefinition {
return ""; return "";
String result = ""; String result = "";
for (String line : comment.split("\\\\n")) { for (String line : comment.split("\\\\n")) {
result += linePrefix + " * " + line + EOL; result += linePrefix + " * " + line + ToolUtil.EOL;
} }
return result; return result;
} }
@ -579,28 +546,6 @@ public class ConfigDefinition {
return Integer.parseInt(s); return Integer.parseInt(s);
} }
static void processDefine(VariableRegistry registry, String line) {
int index = line.indexOf(' ');
String name;
if (index == -1) {
name = line;
line = "";
} else {
name = line.substring(0, index);
line = line.substring(index).trim();
}
if (VariableRegistry.isNumeric(line)) {
int v = Integer.parseInt(line);
registry.register(name, v);
} else {
if (line.contains(" ") && !VariableRegistry.isQuoted(line, '\"') && !VariableRegistry.isQuoted(line, '\'')) {
throw new IllegalStateException("Unexpected space in unquoted " + line);
}
registry.register(name, line);
}
}
private static long getCrc32(String fileName) throws IOException { private static long getCrc32(String fileName) throws IOException {
File file = new File(fileName); File file = new File(fileName);
byte[] fileContent = Files.readAllBytes(file.toPath()); byte[] fileContent = Files.readAllBytes(file.toPath());
@ -614,6 +559,16 @@ public class ConfigDefinition {
return c.getValue(); return c.getValue();
} }
public static void writeDefinesToFile(VariableRegistry variableRegistry, String fileName) throws IOException {
SystemOut.println("Writing to " + fileName);
LazyFile cHeader = new LazyFile(fileName);
cHeader.write("//\n// " + ToolUtil.getGeneratedAutomaticallyTag() + definitionInputFile + "\n//\n\n");
cHeader.write(variableRegistry.getDefinesSection());
cHeader.close();
}
public static class RusefiParseErrorStrategy extends DefaultErrorStrategy { public static class RusefiParseErrorStrategy extends DefaultErrorStrategy {
private boolean hadError = false; private boolean hadError = false;

View File

@ -24,7 +24,6 @@ public class ConfigField {
private static final Pattern DIRECTIVE = Pattern.compile("#(if\\s" + namePattern + "|else|elif\\s\" + namePattern + \"|endif)"); private static final Pattern DIRECTIVE = Pattern.compile("#(if\\s" + namePattern + "|else|elif\\s\" + namePattern + \"|endif)");
public static final char TS_COMMENT_TAG = '+'; public static final char TS_COMMENT_TAG = '+';
public static final String ENUM_SUFFIX = "_enum";
public static final String VOID_NAME = ""; public static final String VOID_NAME = "";
public static final String BOOLEAN_T = "boolean"; public static final String BOOLEAN_T = "boolean";
public static final String DIRECTIVE_T = "directive"; public static final String DIRECTIVE_T = "directive";

View File

@ -21,13 +21,11 @@ import static com.rusefi.ConfigField.BOOLEAN_T;
*/ */
public class ReaderState { public class ReaderState {
public static final String BIT = "bit"; public static final String BIT = "bit";
public static final String DEFINE = "#define";
private static final String CUSTOM = "custom"; private static final String CUSTOM = "custom";
private static final String END_STRUCT = "end_struct"; private static final String END_STRUCT = "end_struct";
private static final String STRUCT_NO_PREFIX = "struct_no_prefix "; private static final String STRUCT_NO_PREFIX = "struct_no_prefix ";
private static final String STRUCT = "struct "; private static final String STRUCT = "struct ";
private static final String DEFINE_CONSTRUCTOR = "define_constructor"; private static final String DEFINE_CONSTRUCTOR = "define_constructor";
public static final char MULT_TOKEN = '*';
public final Stack<ConfigStructure> stack = new Stack<>(); public final Stack<ConfigStructure> stack = new Stack<>();
public final Map<String, Integer> tsCustomSize = new HashMap<>(); public final Map<String, Integer> tsCustomSize = new HashMap<>();
public final Map<String, String> tsCustomLine = new HashMap<>(); public final Map<String, String> tsCustomLine = new HashMap<>();
@ -61,14 +59,6 @@ public class ReaderState {
structure.addBitField(bitField); structure.addBitField(bitField);
} }
static boolean isEmptyDefinitionLine(String line) {
/**
* historically somehow '!' was the start of comment line
* '//' is the later added alternative.
*/
return line.length() == 0 || line.startsWith("!") || line.startsWith("//");
}
public void read(Reader reader) throws IOException { public void read(Reader reader) throws IOException {
Map<String, EnumsReader.EnumState> newEnums = EnumsReader.readStatic(reader); Map<String, EnumsReader.EnumState> newEnums = EnumsReader.readStatic(reader);
@ -129,7 +119,7 @@ public class ReaderState {
customSize = customSize.replaceAll("x", "*"); customSize = customSize.replaceAll("x", "*");
line = variableRegistry.applyVariables(line); line = variableRegistry.applyVariables(line);
int multPosition = customSize.indexOf(MULT_TOKEN); int multPosition = customSize.indexOf(VariableRegistry.MULT_TOKEN);
if (multPosition != -1) { if (multPosition != -1) {
String firstPart = customSize.substring(0, multPosition).trim(); String firstPart = customSize.substring(0, multPosition).trim();
int first; int first;
@ -169,11 +159,11 @@ public class ReaderState {
String line; String line;
while ((line = definitionReader.readLine()) != null) { while ((line = definitionReader.readLine()) != null) {
lineIndex++; lineIndex++;
line = ConfigDefinition.trimLine(line); line = ToolUtil.trimLine(line);
/** /**
* we should ignore empty lines and comments * we should ignore empty lines and comments
*/ */
if (isEmptyDefinitionLine(line)) if (ToolUtil.isEmptyDefinitionLine(line))
continue; continue;
if (line.startsWith(STRUCT)) { if (line.startsWith(STRUCT)) {
@ -186,15 +176,15 @@ public class ReaderState {
} else if (line.startsWith(BIT)) { } else if (line.startsWith(BIT)) {
handleBitLine(this, line); handleBitLine(this, line);
} else if (ConfigDefinition.startsWithToken(line, CUSTOM)) { } else if (ToolUtil.startsWithToken(line, CUSTOM)) {
handleCustomLine(line); handleCustomLine(line);
} else if (ConfigDefinition.startsWithToken(line, DEFINE)) { } else if (ToolUtil.startsWithToken(line, VariableRegistry.DEFINE)) {
/** /**
* for example * for example
* #define CLT_CURVE_SIZE 16 * #define CLT_CURVE_SIZE 16
*/ */
ConfigDefinition.processDefine(variableRegistry, line.substring(DEFINE.length()).trim()); variableRegistry.processDefine(line.substring(VariableRegistry.DEFINE.length()).trim());
} else { } else {
if (stack.isEmpty()) if (stack.isEmpty())
throw new IllegalStateException("Expected to be within structure at line " + lineIndex + ": " + line); throw new IllegalStateException("Expected to be within structure at line " + lineIndex + ": " + line);

View File

@ -2,7 +2,7 @@ package com.rusefi.output;
import com.rusefi.*; import com.rusefi.*;
import static com.rusefi.ConfigDefinition.EOL; import static com.rusefi.ToolUtil.EOL;
public abstract class BaseCHeaderConsumer implements ConfigurationConsumer { public abstract class BaseCHeaderConsumer implements ConfigurationConsumer {
private static final String BOOLEAN_TYPE = "bool"; private static final String BOOLEAN_TYPE = "bool";

View File

@ -6,7 +6,7 @@ import com.rusefi.util.SystemOut;
import java.io.IOException; import java.io.IOException;
import static com.rusefi.ConfigDefinition.EOL; import static com.rusefi.ToolUtil.EOL;
/** /**
* Configuration consumer which writes C header file * Configuration consumer which writes C header file

View File

@ -2,12 +2,13 @@ package com.rusefi.output;
import com.rusefi.ConfigDefinition; import com.rusefi.ConfigDefinition;
import com.rusefi.ReaderState; import com.rusefi.ReaderState;
import com.rusefi.ToolUtil;
import com.rusefi.util.LazyFile; import com.rusefi.util.LazyFile;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import static com.rusefi.ConfigDefinition.EOL; import static com.rusefi.ToolUtil.EOL;
public class FileFsioSettingsConsumer extends FsioSettingsConsumer { public class FileFsioSettingsConsumer extends FsioSettingsConsumer {
private final LazyFile enumFile; private final LazyFile enumFile;
@ -30,7 +31,7 @@ public class FileFsioSettingsConsumer extends FsioSettingsConsumer {
@Override @Override
public void startFile() { public void startFile() {
for (LazyFile file : Arrays.asList(enumFile, gettersFile, stringsFile, namesFile)) { for (LazyFile file : Arrays.asList(enumFile, gettersFile, stringsFile, namesFile)) {
file.write("// this file " + ConfigDefinition.MESSAGE + ConfigDefinition.EOL + EOL); file.write("// this file " + ConfigDefinition.MESSAGE + ToolUtil.EOL + EOL);
file.write("// by " + getClass() + EOL); file.write("// by " + getClass() + EOL);
} }
} }

View File

@ -2,12 +2,13 @@ package com.rusefi.output;
import com.rusefi.ConfigDefinition; import com.rusefi.ConfigDefinition;
import com.rusefi.ReaderState; import com.rusefi.ReaderState;
import com.rusefi.ToolUtil;
import com.rusefi.util.LazyFile; import com.rusefi.util.LazyFile;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import static com.rusefi.ConfigDefinition.EOL; import static com.rusefi.ToolUtil.EOL;
/** /**
* This class generates java representation of rusEfi data structures used by rusEfi console * This class generates java representation of rusEfi data structures used by rusEfi console
@ -27,11 +28,11 @@ public class FileJavaFieldsConsumer extends JavaFieldsConsumer {
@Override @Override
public void startFile() { public void startFile() {
javaFields.write("package " + JAVA_PACKAGE + ";" + ConfigDefinition.EOL + ConfigDefinition.EOL); javaFields.write("package " + JAVA_PACKAGE + ";" + ToolUtil.EOL + ToolUtil.EOL);
javaFields.write("// this file " + ConfigDefinition.MESSAGE + ConfigDefinition.EOL + EOL); javaFields.write("// this file " + ConfigDefinition.MESSAGE + ToolUtil.EOL + EOL);
javaFields.write("// by " + getClass() + EOL); javaFields.write("// by " + getClass() + EOL);
javaFields.write("import com.rusefi.config.*;" + EOL + EOL); javaFields.write("import com.rusefi.config.*;" + EOL + EOL);
javaFields.write("public class " + className + " {" + ConfigDefinition.EOL); javaFields.write("public class " + className + " {" + ToolUtil.EOL);
} }
@Override @Override
@ -42,7 +43,7 @@ public class FileJavaFieldsConsumer extends JavaFieldsConsumer {
allFields.append("\t};" + EOL); allFields.append("\t};" + EOL);
javaFields.write(allFields.toString()); javaFields.write(allFields.toString());
javaFields.write("}" + ConfigDefinition.EOL); javaFields.write("}" + ToolUtil.EOL);
javaFields.close(); javaFields.close();
} }
} }

View File

@ -9,7 +9,7 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import static com.rusefi.ConfigDefinition.EOL; import static com.rusefi.ToolUtil.EOL;
public abstract class JavaFieldsConsumer implements ConfigurationConsumer { public abstract class JavaFieldsConsumer implements ConfigurationConsumer {
// todo: why is this field 'static'? // todo: why is this field 'static'?
@ -74,7 +74,7 @@ public abstract class JavaFieldsConsumer implements ConfigurationConsumer {
writeJavaFieldName(nameWithPrefix, tsPosition); writeJavaFieldName(nameWithPrefix, tsPosition);
javaFieldsWriter.write("FieldType.FLOAT);" + EOL); javaFieldsWriter.write("FieldType.FLOAT);" + EOL);
} else { } else {
String enumOptions = state.variableRegistry.get(configField.getType() + ConfigField.ENUM_SUFFIX); String enumOptions = state.variableRegistry.get(configField.getType() + VariableRegistry.ENUM_SUFFIX);
if (enumOptions != null && !javaEnums.contains(configField.getType())) { if (enumOptions != null && !javaEnums.contains(configField.getType())) {
javaEnums.add(configField.getType()); javaEnums.add(configField.getType());

View File

@ -1,13 +1,10 @@
package com.rusefi.output; package com.rusefi.output;
import com.rusefi.*; import com.rusefi.*;
import com.rusefi.util.LazyFile;
import com.rusefi.util.SystemOut; import com.rusefi.util.SystemOut;
import java.io.IOException; import java.io.IOException;
import static com.rusefi.ConfigDefinition.EOL;
/** /**
* Configuration consumer which writes Signature header file * Configuration consumer which writes Signature header file
*/ */
@ -27,7 +24,7 @@ public class SignatureConsumer implements ConfigurationConsumer {
@Override @Override
public void handleEndStruct(ConfigStructure structure) throws IOException { public void handleEndStruct(ConfigStructure structure) throws IOException {
registry.writeDefinesToFile(destHeader); ConfigDefinition.writeDefinesToFile(registry, destHeader);
} }
@Override @Override

View File

@ -9,7 +9,7 @@ import com.rusefi.util.SystemOut;
import java.io.*; import java.io.*;
import static com.rusefi.util.IoUtils.CHARSET; import static com.rusefi.util.IoUtils.CHARSET;
import static com.rusefi.ConfigDefinition.EOL; import static com.rusefi.ToolUtil.EOL;
public class TSProjectConsumer implements ConfigurationConsumer { public class TSProjectConsumer implements ConfigurationConsumer {
private static final String TS_FILE_INPUT_NAME = "rusefi.input"; private static final String TS_FILE_INPUT_NAME = "rusefi.input";
@ -167,17 +167,17 @@ public class TSProjectConsumer implements ConfigurationConsumer {
protected void writeContent(String fieldsSection, TsFileContent tsContent, Output tsHeader) throws IOException { protected void writeContent(String fieldsSection, TsFileContent tsContent, Output tsHeader) throws IOException {
tsHeader.write(tsContent.getPrefix()); tsHeader.write(tsContent.getPrefix());
tsHeader.write("; " + CONFIG_DEFINITION_START + ConfigDefinition.EOL); tsHeader.write("; " + CONFIG_DEFINITION_START + ToolUtil.EOL);
tsHeader.write("; this section " + ConfigDefinition.MESSAGE + ConfigDefinition.EOL + ConfigDefinition.EOL); tsHeader.write("; this section " + ConfigDefinition.MESSAGE + ToolUtil.EOL + ToolUtil.EOL);
tsHeader.write("pageSize = " + totalTsSize + ConfigDefinition.EOL); tsHeader.write("pageSize = " + totalTsSize + ToolUtil.EOL);
tsHeader.write("page = 1" + ConfigDefinition.EOL); tsHeader.write("page = 1" + ToolUtil.EOL);
tsHeader.write(fieldsSection); tsHeader.write(fieldsSection);
if (settingContextHelp.length() > 0) { if (settingContextHelp.length() > 0) {
tsHeader.write("[" + SETTING_CONTEXT_HELP + "]" + ConfigDefinition.EOL); tsHeader.write("[" + SETTING_CONTEXT_HELP + "]" + ToolUtil.EOL);
tsHeader.write(settingContextHelp.toString() + ConfigDefinition.EOL + ConfigDefinition.EOL); tsHeader.write(settingContextHelp.toString() + ToolUtil.EOL + ToolUtil.EOL);
tsHeader.write("; " + SETTING_CONTEXT_HELP_END + ConfigDefinition.EOL); tsHeader.write("; " + SETTING_CONTEXT_HELP_END + ToolUtil.EOL);
} }
tsHeader.write("; " + CONFIG_DEFINITION_END + ConfigDefinition.EOL); tsHeader.write("; " + CONFIG_DEFINITION_END + ToolUtil.EOL);
tsHeader.write(tsContent.getPostfix()); tsHeader.write(tsContent.getPostfix());
tsHeader.close(); tsHeader.close();
} }
@ -218,10 +218,10 @@ public class TSProjectConsumer implements ConfigurationConsumer {
line = state.variableRegistry.applyVariables(line); line = state.variableRegistry.applyVariables(line);
if (isBeforeStartTag) if (isBeforeStartTag)
prefix.append(line + ConfigDefinition.EOL); prefix.append(line + ToolUtil.EOL);
if (isAfterEndTag) if (isAfterEndTag)
postfix.append(state.variableRegistry.applyVariables(line) + ConfigDefinition.EOL); postfix.append(state.variableRegistry.applyVariables(line) + ToolUtil.EOL);
} }
r.close(); r.close();
return new TsFileContent(prefix.toString(), postfix.toString()); return new TsFileContent(prefix.toString(), postfix.toString());

View File

@ -1,6 +1,5 @@
package com.rusefi.test; package com.rusefi.test;
import com.rusefi.ConfigDefinition;
import com.rusefi.EnumsReader; import com.rusefi.EnumsReader;
import com.rusefi.VariableRegistry; import com.rusefi.VariableRegistry;
import org.junit.Test; import org.junit.Test;
@ -21,7 +20,7 @@ public class ConfigDefinitionTest {
VariableRegistry variableRegistry = new VariableRegistry(); VariableRegistry variableRegistry = new VariableRegistry();
ConfigDefinition.readPrependValues(variableRegistry, FIRMWARE + File.separator + "integration/rusefi_config.txt"); variableRegistry.readPrependValues(FIRMWARE + File.separator + "integration/rusefi_config.txt");
String sb = variableRegistry.getEnumOptionsForTunerStudio(enumsReader, "engine_type_e"); String sb = variableRegistry.getEnumOptionsForTunerStudio(enumsReader, "engine_type_e");

View File

@ -118,7 +118,7 @@ public class ConfigFieldParserTest {
@Test(expected = IllegalStateException.class) @Test(expected = IllegalStateException.class)
public void invalidDefine() throws IOException { public void invalidDefine() throws IOException {
String test = "struct pid_s\n" + String test = "struct pid_s\n" +
ReaderState.DEFINE + " show show_Hellen121vag_presets true\n" + VariableRegistry.DEFINE + " show show_Hellen121vag_presets true\n" +
"end_struct\n" + "end_struct\n" +
""; "";
BufferedReader reader = new BufferedReader(new StringReader(test)); BufferedReader reader = new BufferedReader(new StringReader(test));

Binary file not shown.

View File

@ -14,8 +14,8 @@ public class EnumsReader {
protected final Map<String, EnumState> enums = new TreeMap<>(); protected final Map<String, EnumState> enums = new TreeMap<>();
@NotNull @NotNull
static List<Value> getSortedByOrder(Map<String, Value> brain_pin_e) { static List<Value> getSortedByOrder(VariableRegistry registry, Map<String, Value> brain_pin_e) {
Set<Value> byOrdinal = new TreeSet<>(Comparator.comparingInt(Value::getIntValue)); Set<Value> byOrdinal = new TreeSet<>(Comparator.comparingInt(value -> value.getIntValueMaybeResolve(registry)));
byOrdinal.addAll(brain_pin_e.values()); byOrdinal.addAll(brain_pin_e.values());
return new ArrayList<>(byOrdinal); return new ArrayList<>(byOrdinal);
} }

View File

@ -11,10 +11,12 @@ class InvokeReader {
private final static String KEY_INPUT_PATH = "-enumInputPath"; private final static String KEY_INPUT_PATH = "-enumInputPath";
private final static String KEY_OUTPUT = "-outputPath"; private final static String KEY_OUTPUT = "-outputPath";
private final static String KEY_OUTPUT_FILE = "-generatedFile"; private final static String KEY_OUTPUT_FILE = "-generatedFile";
private static final String KEY_DEFINITION = "-definition";
public static String fileSuffix = "enums"; public static String fileSuffix = "enums";
private String[] args; private String[] args;
private String outputPath; private String outputPath;
private List<String> definitionInputFiles = new ArrayList<>();
private List<String> inputFiles = new ArrayList<>(); private List<String> inputFiles = new ArrayList<>();
private String inputPath = "."; private String inputPath = ".";
@ -34,6 +36,10 @@ class InvokeReader {
return inputPath; return inputPath;
} }
public List<String> getDefinitionInputFiles() {
return definitionInputFiles;
}
public String getOutputPath() { public String getOutputPath() {
return outputPath; return outputPath;
} }
@ -46,15 +52,23 @@ class InvokeReader {
outputPath = null; outputPath = null;
for (int i = 0; i < args.length - 1; i += 2) { for (int i = 0; i < args.length - 1; i += 2) {
String key = args[i]; String key = args[i];
if (key.equals(KEY_INPUT_PATH)) { switch (key) {
inputPath = Objects.requireNonNull(args[i + 1], KEY_INPUT_PATH); case KEY_DEFINITION:
} else if (key.equals(EnumToString.KEY_ENUM_INPUT_FILE)) { definitionInputFiles.add(args[i + 1]);
String headerInputFile = args[i + 1]; break;
inputFiles.add(headerInputFile); case KEY_INPUT_PATH:
} else if (key.equals(KEY_OUTPUT_FILE)) { inputPath = Objects.requireNonNull(args[i + 1], KEY_INPUT_PATH);
fileSuffix = args[i + 1]; break;
} else if (key.equals(KEY_OUTPUT)) { case EnumToString.KEY_ENUM_INPUT_FILE:
outputPath = args[i + 1]; String headerInputFile = args[i + 1];
inputFiles.add(headerInputFile);
break;
case KEY_OUTPUT_FILE:
fileSuffix = args[i + 1];
break;
case KEY_OUTPUT:
outputPath = args[i + 1];
break;
} }
} }
return this; return this;

View File

@ -18,6 +18,10 @@ public class ToJavaEnum {
EnumsReader enumsReader = new EnumsReader(); EnumsReader enumsReader = new EnumsReader();
VariableRegistry registry = new VariableRegistry();
for (String fileName : invokeReader.getDefinitionInputFiles())
registry.readPrependValues(fileName);
for (String inputFile : invokeReader.getInputFiles()) { for (String inputFile : invokeReader.getInputFiles()) {
File f = new File(invokeReader.getInputPath() + File.separator + inputFile); File f = new File(invokeReader.getInputPath() + File.separator + inputFile);
SystemOut.println("Reading enums from " + f); SystemOut.println("Reading enums from " + f);
@ -26,7 +30,7 @@ public class ToJavaEnum {
} }
for (Map.Entry<String /*enum name*/, EnumsReader.EnumState> e : enumsReader.getEnums().entrySet()) { for (Map.Entry<String /*enum name*/, EnumsReader.EnumState> e : enumsReader.getEnums().entrySet()) {
String java = generate(e.getKey(), e.getValue()); String java = generate(registry, e.getKey(), e.getValue());
String fullFileName = outputPath + File.separator + e.getKey() + ".java"; String fullFileName = outputPath + File.separator + e.getKey() + ".java";
BufferedWriter br = new BufferedWriter(new FileWriter(fullFileName)); BufferedWriter br = new BufferedWriter(new FileWriter(fullFileName));
@ -35,12 +39,12 @@ public class ToJavaEnum {
} }
} }
public static String generate(String key, EnumsReader.EnumState enumState) { public static String generate(VariableRegistry registry, String key, EnumsReader.EnumState enumState) {
StringBuilder sb = new StringBuilder("package com.rusefi.enums;\n"); StringBuilder sb = new StringBuilder("package com.rusefi.enums;\n");
sb.append("//auto-generated by ToJavaEnum.java\n\n\n\n"); sb.append("//auto-generated by ToJavaEnum.java\n\n\n\n");
sb.append("public enum " + key + " {\n"); sb.append("public enum " + key + " {\n");
List<Value> sorted = EnumsReader.getSortedByOrder(enumState.values); List<Value> sorted = EnumsReader.getSortedByOrder(registry, enumState.values);
for (Value value : sorted) { for (Value value : sorted) {
sb.append("\t" + value.getName() + ",\n"); sb.append("\t" + value.getName() + ",\n");

View File

@ -0,0 +1,51 @@
package com.rusefi;
import com.rusefi.util.LazyFile;
import java.net.URISyntaxException;
public class ToolUtil {
public static final String EOL = "\n";
public static String TOOL = "(unknown script)";
static String getJarFileName() {
try {
// Get path of the JAR file
String jarPath = VariableRegistry.class
.getProtectionDomain()
.getCodeSource()
.getLocation()
.toURI()
.getPath();
System.out.println("JAR Path : " + jarPath);
// Get name of the JAR file
return jarPath.substring(jarPath.lastIndexOf("/") + 1);
} catch (URISyntaxException e) {
return "(unknown jar)";
}
}
public static String getGeneratedAutomaticallyTag() {
return LazyFile.LAZY_FILE_TAG + getJarFileName() + " based on " + TOOL + " ";
}
static boolean isEmptyDefinitionLine(String line) {
/**
* historically somehow '!' was the start of comment line
* '//' is the later added alternative.
*/
return line.length() == 0 || line.startsWith("!") || line.startsWith("//");
}
static boolean startsWithToken(String line, String token) {
return line.startsWith(token + " ") || line.startsWith(token + "\t");
}
static String trimLine(String line) {
line = line.trim();
line = line.replaceAll("\\s+", " ");
return line;
}
}

View File

@ -1,18 +1,19 @@
package com.rusefi; package com.rusefi;
import com.rusefi.enum_reader.Value; import com.rusefi.enum_reader.Value;
import com.rusefi.util.LazyFile;
import com.rusefi.util.SystemOut; import com.rusefi.util.SystemOut;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.io.Reader;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import static com.rusefi.ConfigDefinition.EOL;
import static com.rusefi.ReaderState.MULT_TOKEN;
/** /**
* 3/30/2015 * 3/30/2015
*/ */
@ -20,9 +21,11 @@ public class VariableRegistry {
public static final String _16_HEX_SUFFIX = "_16_hex"; public static final String _16_HEX_SUFFIX = "_16_hex";
public static final String _HEX_SUFFIX = "_hex"; public static final String _HEX_SUFFIX = "_hex";
public static final String CHAR_SUFFIX = "_char"; public static final String CHAR_SUFFIX = "_char";
public static final String ENUM_SUFFIX = "_enum";
public static final char MULT_TOKEN = '*';
public static final String DEFINE = "#define";
private static final String HEX_PREFIX = "0x"; private static final String HEX_PREFIX = "0x";
private final TreeMap<String, String> data = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); private final TreeMap<String, String> data = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
public static final VariableRegistry INSTANCE = new VariableRegistry();
// todo: smarter regex! See TsWriter.VAR which is a bit better but still not perfect // todo: smarter regex! See TsWriter.VAR which is a bit better but still not perfect
// todo: https://github.com/rusefi/rusefi/issues/3053 ? // todo: https://github.com/rusefi/rusefi/issues/3053 ?
@ -33,7 +36,46 @@ public class VariableRegistry {
private final Map<String, String> cAllDefinitions = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); private final Map<String, String> cAllDefinitions = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
private final Map<String, String> javaDefinitions = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); private final Map<String, String> javaDefinitions = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
public VariableRegistry() { public void readPrependValues(String prependFile) throws IOException {
readPrependValues(new FileReader(prependFile));
}
public void readPrependValues(Reader fileReader) throws IOException {
BufferedReader definitionReader = new BufferedReader(fileReader);
String line;
while ((line = definitionReader.readLine()) != null) {
line = ToolUtil.trimLine(line);
/**
* we should ignore empty lines and comments
*/
if (ToolUtil.isEmptyDefinitionLine(line))
continue;
if (ToolUtil.startsWithToken(line, DEFINE)) {
processDefine(line.substring(DEFINE.length()).trim());
}
}
}
void processDefine(String line) {
int index = line.indexOf(' ');
String name;
if (index == -1) {
name = line;
line = "";
} else {
name = line.substring(0, index);
line = line.substring(index).trim();
}
if (isNumeric(line)) {
int v = Integer.parseInt(line);
register(name, v);
} else {
if (line.contains(" ") && !isQuoted(line, '\"') && !isQuoted(line, '\'')) {
throw new IllegalStateException("Unexpected space in unquoted " + line);
}
register(name, line);
}
} }
/** /**
@ -129,7 +171,7 @@ public class VariableRegistry {
if (!value.contains("\n")) { if (!value.contains("\n")) {
// multi-lines are not supported in C headers // multi-lines are not supported in C headers
if (!var.endsWith(_16_HEX_SUFFIX) && !var.endsWith(_HEX_SUFFIX)) { if (!var.endsWith(_16_HEX_SUFFIX) && !var.endsWith(_HEX_SUFFIX)) {
cAllDefinitions.put(var, "#define " + var + " " + value + EOL); cAllDefinitions.put(var, "#define " + var + " " + value + ToolUtil.EOL);
} }
} }
return value; return value;
@ -149,7 +191,7 @@ public class VariableRegistry {
if (value.trim().startsWith(HEX_PREFIX)) { if (value.trim().startsWith(HEX_PREFIX)) {
int intValue = Integer.parseInt(value.trim().substring(HEX_PREFIX.length()), 16); int intValue = Integer.parseInt(value.trim().substring(HEX_PREFIX.length()), 16);
intValues.put(var, intValue); intValues.put(var, intValue);
javaDefinitions.put(var, "\tpublic static final int " + var + " = " + value + ";" + EOL); javaDefinitions.put(var, "\tpublic static final int " + var + " = " + value + ";" + ToolUtil.EOL);
return; return;
} }
@ -158,18 +200,18 @@ public class VariableRegistry {
SystemOut.println("key [" + var + "] value: " + intValue); SystemOut.println("key [" + var + "] value: " + intValue);
intValues.put(var, intValue); intValues.put(var, intValue);
if (!var.endsWith(_HEX_SUFFIX)) { if (!var.endsWith(_HEX_SUFFIX)) {
javaDefinitions.put(var, "\tpublic static final int " + var + " = " + intValue + ";" + EOL); javaDefinitions.put(var, "\tpublic static final int " + var + " = " + intValue + ";" + ToolUtil.EOL);
} }
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
SystemOut.println("Not an integer: " + value); SystemOut.println("Not an integer: " + value);
if (!var.trim().endsWith(ConfigField.ENUM_SUFFIX)) { if (!var.trim().endsWith(ENUM_SUFFIX)) {
if (isQuoted(value, '"')) { if (isQuoted(value, '"')) {
// quoted and not with enum suffix means plain string define statement // quoted and not with enum suffix means plain string define statement
javaDefinitions.put(var, "\tpublic static final String " + var + " = " + value + ";" + EOL); javaDefinitions.put(var, "\tpublic static final String " + var + " = " + value + ";" + ToolUtil.EOL);
} else if (isQuoted(value, '\'')) { } else if (isQuoted(value, '\'')) {
// quoted and not with enum suffix means plain string define statement // quoted and not with enum suffix means plain string define statement
javaDefinitions.put(var, "\tpublic static final char " + var + " = " + value + ";" + EOL); javaDefinitions.put(var, "\tpublic static final char " + var + " = " + value + ";" + ToolUtil.EOL);
char charValue = value.charAt(1); char charValue = value.charAt(1);
registerHex(var + CHAR_SUFFIX, charValue); registerHex(var + CHAR_SUFFIX, charValue);
doRegister(var + CHAR_SUFFIX, Character.toString(charValue)); doRegister(var + CHAR_SUFFIX, Character.toString(charValue));
@ -205,16 +247,6 @@ public class VariableRegistry {
register(name + _16_HEX_SUFFIX, _16_hex); register(name + _16_HEX_SUFFIX, _16_hex);
} }
public void writeDefinesToFile(String fileName) throws IOException {
SystemOut.println("Writing to " + fileName);
LazyFile cHeader = new LazyFile(fileName);
cHeader.write("//\n// " + ConfigDefinition.getGeneratedAutomaticallyTag() + ConfigDefinition.definitionInputFile + "\n//\n\n");
cHeader.write(getDefinesSection());
cHeader.close();
}
public String getDefinesSection() { public String getDefinesSection() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (String value : cAllDefinitions.values()) for (String value : cAllDefinitions.values())

View File

@ -1,5 +1,7 @@
package com.rusefi.enum_reader; package com.rusefi.enum_reader;
import com.rusefi.VariableRegistry;
public class Value implements Comparable<Value> { public class Value implements Comparable<Value> {
private final String name; private final String name;
private final String value; private final String value;
@ -33,4 +35,13 @@ public class Value implements Comparable<Value> {
", value='" + value + '\'' + ", value='" + value + '\'' +
'}'; '}';
} }
public int getIntValueMaybeResolve(VariableRegistry registry) {
try {
return getIntValue();
} catch (NumberFormatException e) {
String resolvedValue = registry.get(value);
return Integer.parseInt(resolvedValue);
}
}
} }

View File

@ -118,12 +118,13 @@ public class EnumToStringTest {
EnumsReader.EnumState brain_pin_e = enumsReader.getEnums().get("brain_pin_e"); EnumsReader.EnumState brain_pin_e = enumsReader.getEnums().get("brain_pin_e");
assertEquals(2, brain_pin_e.values.get("GPIO_HEX").getIntValue()); assertEquals(2, brain_pin_e.values.get("GPIO_HEX").getIntValue());
List<Value> listByOrdinal = EnumsReader.getSortedByOrder(brain_pin_e.values); VariableRegistry registry = new VariableRegistry();
List<Value> listByOrdinal = EnumsReader.getSortedByOrder(registry, brain_pin_e.values);
assertEquals(0, listByOrdinal.get(0).getIntValue()); assertEquals(0, listByOrdinal.get(0).getIntValue());
for (Map.Entry<String /*enum name*/, EnumsReader.EnumState> e : enumsReader.getEnums().entrySet()) { for (Map.Entry<String /*enum name*/, EnumsReader.EnumState> e : enumsReader.getEnums().entrySet()) {
String a = new ToJavaEnum().generate(e.getKey(), e.getValue()); String a = ToJavaEnum.generate(registry, e.getKey(), e.getValue());
assertEquals("package com.rusefi.enums;\n" + assertEquals("package com.rusefi.enums;\n" +
"//auto-generated by ToJavaEnum.java\n" + "//auto-generated by ToJavaEnum.java\n" +
@ -178,4 +179,28 @@ public class EnumToStringTest {
" return NULL;\n" + " return NULL;\n" +
"}\n", enumToString.getCppFileContent()); "}\n", enumToString.getCppFileContent());
} }
@Test
public void testWithInput() throws IOException {
final StringReader reader = new StringReader(
"typedef enum {\n" +
"\tGPIO_UNASSIGNED = XXXX,\n" +
"}brain_pin_e; // hello");
VariableRegistry registry = new VariableRegistry();
registry.readPrependValues(new StringReader("#define XXXX 12"));
EnumsReader enumsReader = new EnumsReader().read(reader);
for (Map.Entry<String /*enum name*/, EnumsReader.EnumState> e : enumsReader.getEnums().entrySet()) {
String java = ToJavaEnum.generate(registry, e.getKey(), e.getValue());
assertEquals("package com.rusefi.enums;\n" +
"//auto-generated by ToJavaEnum.java\n" +
"\n" +
"\n" +
"\n" +
"public enum brain_pin_e {\n" +
"\tGPIO_UNASSIGNED,\n" +
"}\n", java);
}
}
} }