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 5fdc884e71
commit 94bfeec588
20 changed files with 232 additions and 153 deletions

View File

@ -29,11 +29,9 @@ import java.util.zip.CRC32;
*/
@SuppressWarnings("StringConcatenationInsideStringBufferAppend")
public class ConfigDefinition {
public static final String EOL = "\n";
private static final String SIGNATURE_HASH = "SIGNATURE_HASH";
public static String MESSAGE;
public static String TOOL = "(unknown script)";
private static final String ROM_RAIDER_XML_TEMPLATE = "rusefi_template.xml";
public static final String KEY_DEFINITION = "-definition";
private static final String KEY_ROMRAIDER_INPUT = "-romraider";
@ -66,10 +64,6 @@ public class ConfigDefinition {
public static boolean needZeroInit = true;
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) {
try {
doJob(args);
@ -127,7 +121,7 @@ public class ConfigDefinition {
String key = args[i];
switch (key) {
case "-tool":
ConfigDefinition.TOOL = args[i + 1];
ToolUtil.TOOL = args[i + 1];
break;
case KEY_DEFINITION:
definitionInputFile = args[i + 1];
@ -240,12 +234,12 @@ public class ConfigDefinition {
handleFiringOrder(firingEnumFileName, state.variableRegistry);
MESSAGE = getGeneratedAutomaticallyTag() + definitionInputFile + " " + new Date();
MESSAGE = ToolUtil.getGeneratedAutomaticallyTag() + definitionInputFile + " " + new Date();
SystemOut.println("Reading definition from " + definitionInputFile);
for (String prependFile : prependFiles)
readPrependValues(state.variableRegistry, prependFile);
state.variableRegistry.readPrependValues(prependFile);
if (yamlFiles != null) {
processYamls(state.variableRegistry, yamlFiles, state);
@ -267,8 +261,8 @@ public class ConfigDefinition {
parseState.setDefinitionPolicy(Definition.OverwritePolicy.IgnoreNew);
//for (String prependFile : prependFiles) {
// TODO: fix signature define file parsing
//parseFile(listener, prependFile);
// TODO: fix signature define file parsing
//parseFile(listener, prependFile);
//}
}
@ -299,7 +293,7 @@ public class ConfigDefinition {
VariableRegistry tmpRegistry = new VariableRegistry();
// store the CRC32 as a built-in variable
tmpRegistry.register(SIGNATURE_HASH, "" + crc32);
readPrependValues(tmpRegistry, signaturePrependFile);
tmpRegistry.readPrependValues(signaturePrependFile);
destinations.add(new SignatureConsumer(signatureDestination, tmpRegistry));
}
if (needToUpdateOtherFiles) {
@ -329,7 +323,7 @@ public class ConfigDefinition {
if (destCDefinesFileName != null && needToUpdateOtherFiles)
state.variableRegistry.writeDefinesToFile(destCDefinesFileName);
writeDefinesToFile(state.variableRegistry, destCDefinesFileName);
if (romRaiderDestination != null && romRaiderInputFile != null && needToUpdateOtherFiles) {
processTextTemplate(state, romRaiderInputFile, romRaiderDestination);
@ -376,22 +370,6 @@ public class ConfigDefinition {
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 {
ArrayList<Map<String, Object>> listPins = new ArrayList<>();
for (File yamlFile : yamlFiles) {
@ -524,7 +502,7 @@ public class ConfigDefinition {
SystemOut.println("Reading from " + inputFileName);
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);
@ -534,30 +512,19 @@ public class ConfigDefinition {
String line;
while ((line = fr.readLine()) != null) {
line = state.variableRegistry.applyVariables(line);
fw.write(line + ConfigDefinition.EOL);
fw.write(line + ToolUtil.EOL);
}
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) {
String start = "\t/**";
String packedComment = packComment(comment, "\t");
String unitsComment = units.isEmpty() ? "" : "\t" + units + EOL;
return start + EOL +
String unitsComment = units.isEmpty() ? "" : "\t" + units + ToolUtil.EOL;
return start + ToolUtil.EOL +
packedComment +
unitsComment +
"\t * offset " + currentOffset + EOL + "\t */" + EOL;
"\t * offset " + currentOffset + ToolUtil.EOL + "\t */" + ToolUtil.EOL;
}
public static String packComment(String comment, String linePrefix) {
@ -567,7 +534,7 @@ public class ConfigDefinition {
return "";
String result = "";
for (String line : comment.split("\\\\n")) {
result += linePrefix + " * " + line + EOL;
result += linePrefix + " * " + line + ToolUtil.EOL;
}
return result;
}
@ -579,28 +546,6 @@ public class ConfigDefinition {
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 {
File file = new File(fileName);
byte[] fileContent = Files.readAllBytes(file.toPath());
@ -614,6 +559,16 @@ public class ConfigDefinition {
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 {
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)");
public static final char TS_COMMENT_TAG = '+';
public static final String ENUM_SUFFIX = "_enum";
public static final String VOID_NAME = "";
public static final String BOOLEAN_T = "boolean";
public static final String DIRECTIVE_T = "directive";

View File

@ -21,13 +21,11 @@ import static com.rusefi.ConfigField.BOOLEAN_T;
*/
public class ReaderState {
public static final String BIT = "bit";
public static final String DEFINE = "#define";
private static final String CUSTOM = "custom";
private static final String END_STRUCT = "end_struct";
private static final String STRUCT_NO_PREFIX = "struct_no_prefix ";
private static final String STRUCT = "struct ";
private static final String DEFINE_CONSTRUCTOR = "define_constructor";
public static final char MULT_TOKEN = '*';
public final Stack<ConfigStructure> stack = new Stack<>();
public final Map<String, Integer> tsCustomSize = new HashMap<>();
public final Map<String, String> tsCustomLine = new HashMap<>();
@ -61,14 +59,6 @@ public class ReaderState {
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 {
Map<String, EnumsReader.EnumState> newEnums = EnumsReader.readStatic(reader);
@ -129,7 +119,7 @@ public class ReaderState {
customSize = customSize.replaceAll("x", "*");
line = variableRegistry.applyVariables(line);
int multPosition = customSize.indexOf(MULT_TOKEN);
int multPosition = customSize.indexOf(VariableRegistry.MULT_TOKEN);
if (multPosition != -1) {
String firstPart = customSize.substring(0, multPosition).trim();
int first;
@ -169,11 +159,11 @@ public class ReaderState {
String line;
while ((line = definitionReader.readLine()) != null) {
lineIndex++;
line = ConfigDefinition.trimLine(line);
line = ToolUtil.trimLine(line);
/**
* we should ignore empty lines and comments
*/
if (isEmptyDefinitionLine(line))
if (ToolUtil.isEmptyDefinitionLine(line))
continue;
if (line.startsWith(STRUCT)) {
@ -186,15 +176,15 @@ public class ReaderState {
} else if (line.startsWith(BIT)) {
handleBitLine(this, line);
} else if (ConfigDefinition.startsWithToken(line, CUSTOM)) {
} else if (ToolUtil.startsWithToken(line, CUSTOM)) {
handleCustomLine(line);
} else if (ConfigDefinition.startsWithToken(line, DEFINE)) {
} else if (ToolUtil.startsWithToken(line, VariableRegistry.DEFINE)) {
/**
* for example
* #define CLT_CURVE_SIZE 16
*/
ConfigDefinition.processDefine(variableRegistry, line.substring(DEFINE.length()).trim());
variableRegistry.processDefine(line.substring(VariableRegistry.DEFINE.length()).trim());
} else {
if (stack.isEmpty())
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 static com.rusefi.ConfigDefinition.EOL;
import static com.rusefi.ToolUtil.EOL;
public abstract class BaseCHeaderConsumer implements ConfigurationConsumer {
private static final String BOOLEAN_TYPE = "bool";

View File

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

View File

@ -2,12 +2,13 @@ package com.rusefi.output;
import com.rusefi.ConfigDefinition;
import com.rusefi.ReaderState;
import com.rusefi.ToolUtil;
import com.rusefi.util.LazyFile;
import java.io.IOException;
import java.util.Arrays;
import static com.rusefi.ConfigDefinition.EOL;
import static com.rusefi.ToolUtil.EOL;
public class FileFsioSettingsConsumer extends FsioSettingsConsumer {
private final LazyFile enumFile;
@ -30,7 +31,7 @@ public class FileFsioSettingsConsumer extends FsioSettingsConsumer {
@Override
public void startFile() {
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);
}
}

View File

@ -2,12 +2,13 @@ package com.rusefi.output;
import com.rusefi.ConfigDefinition;
import com.rusefi.ReaderState;
import com.rusefi.ToolUtil;
import com.rusefi.util.LazyFile;
import java.io.File;
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
@ -27,11 +28,11 @@ public class FileJavaFieldsConsumer extends JavaFieldsConsumer {
@Override
public void startFile() {
javaFields.write("package " + JAVA_PACKAGE + ";" + ConfigDefinition.EOL + ConfigDefinition.EOL);
javaFields.write("// this file " + ConfigDefinition.MESSAGE + ConfigDefinition.EOL + EOL);
javaFields.write("package " + JAVA_PACKAGE + ";" + ToolUtil.EOL + ToolUtil.EOL);
javaFields.write("// this file " + ConfigDefinition.MESSAGE + ToolUtil.EOL + EOL);
javaFields.write("// by " + getClass() + EOL);
javaFields.write("import com.rusefi.config.*;" + EOL + EOL);
javaFields.write("public class " + className + " {" + ConfigDefinition.EOL);
javaFields.write("public class " + className + " {" + ToolUtil.EOL);
}
@Override
@ -42,7 +43,7 @@ public class FileJavaFieldsConsumer extends JavaFieldsConsumer {
allFields.append("\t};" + EOL);
javaFields.write(allFields.toString());
javaFields.write("}" + ConfigDefinition.EOL);
javaFields.write("}" + ToolUtil.EOL);
javaFields.close();
}
}

View File

@ -9,7 +9,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static com.rusefi.ConfigDefinition.EOL;
import static com.rusefi.ToolUtil.EOL;
public abstract class JavaFieldsConsumer implements ConfigurationConsumer {
// todo: why is this field 'static'?
@ -74,7 +74,7 @@ public abstract class JavaFieldsConsumer implements ConfigurationConsumer {
writeJavaFieldName(nameWithPrefix, tsPosition);
javaFieldsWriter.write("FieldType.FLOAT);" + EOL);
} 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())) {
javaEnums.add(configField.getType());

View File

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

View File

@ -9,7 +9,7 @@ import com.rusefi.util.SystemOut;
import java.io.*;
import static com.rusefi.util.IoUtils.CHARSET;
import static com.rusefi.ConfigDefinition.EOL;
import static com.rusefi.ToolUtil.EOL;
public class TSProjectConsumer implements ConfigurationConsumer {
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 {
tsHeader.write(tsContent.getPrefix());
tsHeader.write("; " + CONFIG_DEFINITION_START + ConfigDefinition.EOL);
tsHeader.write("; this section " + ConfigDefinition.MESSAGE + ConfigDefinition.EOL + ConfigDefinition.EOL);
tsHeader.write("pageSize = " + totalTsSize + ConfigDefinition.EOL);
tsHeader.write("page = 1" + ConfigDefinition.EOL);
tsHeader.write("; " + CONFIG_DEFINITION_START + ToolUtil.EOL);
tsHeader.write("; this section " + ConfigDefinition.MESSAGE + ToolUtil.EOL + ToolUtil.EOL);
tsHeader.write("pageSize = " + totalTsSize + ToolUtil.EOL);
tsHeader.write("page = 1" + ToolUtil.EOL);
tsHeader.write(fieldsSection);
if (settingContextHelp.length() > 0) {
tsHeader.write("[" + SETTING_CONTEXT_HELP + "]" + ConfigDefinition.EOL);
tsHeader.write(settingContextHelp.toString() + ConfigDefinition.EOL + ConfigDefinition.EOL);
tsHeader.write("; " + SETTING_CONTEXT_HELP_END + ConfigDefinition.EOL);
tsHeader.write("[" + SETTING_CONTEXT_HELP + "]" + ToolUtil.EOL);
tsHeader.write(settingContextHelp.toString() + ToolUtil.EOL + ToolUtil.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.close();
}
@ -218,10 +218,10 @@ public class TSProjectConsumer implements ConfigurationConsumer {
line = state.variableRegistry.applyVariables(line);
if (isBeforeStartTag)
prefix.append(line + ConfigDefinition.EOL);
prefix.append(line + ToolUtil.EOL);
if (isAfterEndTag)
postfix.append(state.variableRegistry.applyVariables(line) + ConfigDefinition.EOL);
postfix.append(state.variableRegistry.applyVariables(line) + ToolUtil.EOL);
}
r.close();
return new TsFileContent(prefix.toString(), postfix.toString());

View File

@ -1,6 +1,5 @@
package com.rusefi.test;
import com.rusefi.ConfigDefinition;
import com.rusefi.EnumsReader;
import com.rusefi.VariableRegistry;
import org.junit.Test;
@ -21,7 +20,7 @@ public class ConfigDefinitionTest {
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");

View File

@ -118,7 +118,7 @@ public class ConfigFieldParserTest {
@Test(expected = IllegalStateException.class)
public void invalidDefine() throws IOException {
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" +
"";
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<>();
@NotNull
static List<Value> getSortedByOrder(Map<String, Value> brain_pin_e) {
Set<Value> byOrdinal = new TreeSet<>(Comparator.comparingInt(Value::getIntValue));
static List<Value> getSortedByOrder(VariableRegistry registry, Map<String, Value> brain_pin_e) {
Set<Value> byOrdinal = new TreeSet<>(Comparator.comparingInt(value -> value.getIntValueMaybeResolve(registry)));
byOrdinal.addAll(brain_pin_e.values());
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_OUTPUT = "-outputPath";
private final static String KEY_OUTPUT_FILE = "-generatedFile";
private static final String KEY_DEFINITION = "-definition";
public static String fileSuffix = "enums";
private String[] args;
private String outputPath;
private List<String> definitionInputFiles = new ArrayList<>();
private List<String> inputFiles = new ArrayList<>();
private String inputPath = ".";
@ -34,6 +36,10 @@ class InvokeReader {
return inputPath;
}
public List<String> getDefinitionInputFiles() {
return definitionInputFiles;
}
public String getOutputPath() {
return outputPath;
}
@ -46,15 +52,23 @@ class InvokeReader {
outputPath = null;
for (int i = 0; i < args.length - 1; i += 2) {
String key = args[i];
if (key.equals(KEY_INPUT_PATH)) {
inputPath = Objects.requireNonNull(args[i + 1], KEY_INPUT_PATH);
} else if (key.equals(EnumToString.KEY_ENUM_INPUT_FILE)) {
String headerInputFile = args[i + 1];
inputFiles.add(headerInputFile);
} else if (key.equals(KEY_OUTPUT_FILE)) {
fileSuffix = args[i + 1];
} else if (key.equals(KEY_OUTPUT)) {
outputPath = args[i + 1];
switch (key) {
case KEY_DEFINITION:
definitionInputFiles.add(args[i + 1]);
break;
case KEY_INPUT_PATH:
inputPath = Objects.requireNonNull(args[i + 1], KEY_INPUT_PATH);
break;
case EnumToString.KEY_ENUM_INPUT_FILE:
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;

View File

@ -18,6 +18,10 @@ public class ToJavaEnum {
EnumsReader enumsReader = new EnumsReader();
VariableRegistry registry = new VariableRegistry();
for (String fileName : invokeReader.getDefinitionInputFiles())
registry.readPrependValues(fileName);
for (String inputFile : invokeReader.getInputFiles()) {
File f = new File(invokeReader.getInputPath() + File.separator + inputFile);
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()) {
String java = generate(e.getKey(), e.getValue());
String java = generate(registry, e.getKey(), e.getValue());
String fullFileName = outputPath + File.separator + e.getKey() + ".java";
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");
sb.append("//auto-generated by ToJavaEnum.java\n\n\n\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) {
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;
import com.rusefi.enum_reader.Value;
import com.rusefi.util.LazyFile;
import com.rusefi.util.SystemOut;
import org.jetbrains.annotations.Nullable;
import java.io.BufferedReader;
import java.io.FileReader;
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.Pattern;
import static com.rusefi.ConfigDefinition.EOL;
import static com.rusefi.ReaderState.MULT_TOKEN;
/**
* 3/30/2015
*/
@ -20,9 +21,11 @@ public class VariableRegistry {
public static final String _16_HEX_SUFFIX = "_16_hex";
public static final String _HEX_SUFFIX = "_hex";
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 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: 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> 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")) {
// multi-lines are not supported in C headers
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;
@ -149,7 +191,7 @@ public class VariableRegistry {
if (value.trim().startsWith(HEX_PREFIX)) {
int intValue = Integer.parseInt(value.trim().substring(HEX_PREFIX.length()), 16);
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;
}
@ -158,18 +200,18 @@ public class VariableRegistry {
SystemOut.println("key [" + var + "] value: " + intValue);
intValues.put(var, intValue);
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) {
SystemOut.println("Not an integer: " + value);
if (!var.trim().endsWith(ConfigField.ENUM_SUFFIX)) {
if (!var.trim().endsWith(ENUM_SUFFIX)) {
if (isQuoted(value, '"')) {
// 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, '\'')) {
// 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);
registerHex(var + CHAR_SUFFIX, charValue);
doRegister(var + CHAR_SUFFIX, Character.toString(charValue));
@ -205,16 +247,6 @@ public class VariableRegistry {
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() {
StringBuilder sb = new StringBuilder();
for (String value : cAllDefinitions.values())

View File

@ -1,5 +1,7 @@
package com.rusefi.enum_reader;
import com.rusefi.VariableRegistry;
public class Value implements Comparable<Value> {
private final String name;
private final String value;
@ -33,4 +35,13 @@ public class Value implements Comparable<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");
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());
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" +
"//auto-generated by ToJavaEnum.java\n" +
@ -178,4 +179,28 @@ public class EnumToStringTest {
" return NULL;\n" +
"}\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);
}
}
}