refactoring - splitting class a bit
This commit is contained in:
parent
7e72bfbc62
commit
261276448a
Binary file not shown.
|
@ -1,24 +1,14 @@
|
||||||
package com.rusefi;
|
package com.rusefi;
|
||||||
|
|
||||||
import com.rusefi.enum_reader.Value;
|
|
||||||
import com.rusefi.generated.RusefiConfigGrammarLexer;
|
|
||||||
import com.rusefi.generated.RusefiConfigGrammarParser;
|
|
||||||
import com.rusefi.newparse.ParseState;
|
import com.rusefi.newparse.ParseState;
|
||||||
import com.rusefi.newparse.parsing.Definition;
|
import com.rusefi.newparse.parsing.Definition;
|
||||||
import com.rusefi.output.*;
|
import com.rusefi.output.*;
|
||||||
import com.rusefi.util.IoUtils;
|
import com.rusefi.util.IoUtils;
|
||||||
import com.rusefi.util.LazyFile;
|
import com.rusefi.util.LazyFile;
|
||||||
import com.rusefi.util.SystemOut;
|
import com.rusefi.util.SystemOut;
|
||||||
import org.antlr.v4.runtime.*;
|
|
||||||
import org.antlr.v4.runtime.tree.ParseTree;
|
|
||||||
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
|
||||||
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
|
||||||
import org.yaml.snakeyaml.Yaml;
|
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.zip.CRC32;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Andrey Belomutskiy, (c) 2013-2020
|
* Andrey Belomutskiy, (c) 2013-2020
|
||||||
|
@ -28,7 +18,7 @@ import java.util.zip.CRC32;
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("StringConcatenationInsideStringBufferAppend")
|
@SuppressWarnings("StringConcatenationInsideStringBufferAppend")
|
||||||
public class ConfigDefinition {
|
public class ConfigDefinition {
|
||||||
private static final String SIGNATURE_HASH = "SIGNATURE_HASH";
|
static final String SIGNATURE_HASH = "SIGNATURE_HASH";
|
||||||
private static String TS_OUTPUTS_DESTINATION = null;
|
private static String TS_OUTPUTS_DESTINATION = null;
|
||||||
public static String MESSAGE;
|
public static String MESSAGE;
|
||||||
|
|
||||||
|
@ -96,7 +86,7 @@ public class ConfigDefinition {
|
||||||
String signaturePrependFile = null;
|
String signaturePrependFile = null;
|
||||||
List<String> enumInputFiles = new ArrayList<>();
|
List<String> enumInputFiles = new ArrayList<>();
|
||||||
CHeaderConsumer.withC_Defines = true;
|
CHeaderConsumer.withC_Defines = true;
|
||||||
File[] yamlFiles = null;
|
File[] boardYamlFiles = null;
|
||||||
|
|
||||||
// used to update other files
|
// used to update other files
|
||||||
List<String> inputFiles = new ArrayList<>();
|
List<String> inputFiles = new ArrayList<>();
|
||||||
|
@ -147,7 +137,7 @@ public class ConfigDefinition {
|
||||||
String keyName = args[i + 1];
|
String keyName = args[i + 1];
|
||||||
// yes, we take three parameters here thus pre-increment!
|
// yes, we take three parameters here thus pre-increment!
|
||||||
String fileName = args[++i + 1];
|
String fileName = args[++i + 1];
|
||||||
state.variableRegistry.register(keyName, readFile(fileName));
|
state.variableRegistry.register(keyName, IoUtil.readFile(fileName));
|
||||||
inputFiles.add(fileName);
|
inputFiles.add(fileName);
|
||||||
case KEY_FIRING:
|
case KEY_FIRING:
|
||||||
firingEnumFileName = args[i + 1];
|
firingEnumFileName = args[i + 1];
|
||||||
|
@ -184,9 +174,9 @@ public class ConfigDefinition {
|
||||||
String dirPath = "./config/boards/" + boardName + "/connectors";
|
String dirPath = "./config/boards/" + boardName + "/connectors";
|
||||||
File dirName = new File(dirPath);
|
File dirName = new File(dirPath);
|
||||||
FilenameFilter filter = (f, name) -> name.endsWith(".yaml");
|
FilenameFilter filter = (f, name) -> name.endsWith(".yaml");
|
||||||
yamlFiles = dirName.listFiles(filter);
|
boardYamlFiles = dirName.listFiles(filter);
|
||||||
if (yamlFiles != null) {
|
if (boardYamlFiles != null) {
|
||||||
for (File yamlFile : yamlFiles) {
|
for (File yamlFile : boardYamlFiles) {
|
||||||
inputFiles.add("config/boards/" + boardName + "/connectors/" + yamlFile.getName());
|
inputFiles.add("config/boards/" + boardName + "/connectors/" + yamlFile.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,7 +199,7 @@ public class ConfigDefinition {
|
||||||
|
|
||||||
ParseState parseState = new ParseState(state.enumsReader);
|
ParseState parseState = new ParseState(state.enumsReader);
|
||||||
// Add the variable for the config signature
|
// Add the variable for the config signature
|
||||||
long crc32 = signatureHash(state, parseState, tsInputFileFolder, inputFiles);
|
long crc32 = IoUtil.signatureHash(state, parseState, tsInputFileFolder, inputFiles);
|
||||||
|
|
||||||
handleFiringOrder(firingEnumFileName, state.variableRegistry, parseState);
|
handleFiringOrder(firingEnumFileName, state.variableRegistry, parseState);
|
||||||
|
|
||||||
|
@ -220,8 +210,8 @@ public class ConfigDefinition {
|
||||||
for (String prependFile : prependFiles)
|
for (String prependFile : prependFiles)
|
||||||
state.variableRegistry.readPrependValues(prependFile);
|
state.variableRegistry.readPrependValues(prependFile);
|
||||||
|
|
||||||
if (yamlFiles != null) {
|
if (boardYamlFiles != null) {
|
||||||
processYamls(state.variableRegistry, yamlFiles, state);
|
PinoutLogic.processYamls(state.variableRegistry, boardYamlFiles, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the input files
|
// Parse the input files
|
||||||
|
@ -235,7 +225,7 @@ public class ConfigDefinition {
|
||||||
parseState.setDefinitionPolicy(Definition.OverwritePolicy.IgnoreNew);
|
parseState.setDefinitionPolicy(Definition.OverwritePolicy.IgnoreNew);
|
||||||
|
|
||||||
for (String prependFile : prependFiles) {
|
for (String prependFile : prependFiles) {
|
||||||
parseFile(parseState.getListener(), prependFile);
|
RusefiParseErrorStrategy.parseDefinitionFile(parseState.getListener(), prependFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +233,7 @@ public class ConfigDefinition {
|
||||||
{
|
{
|
||||||
// don't allow duplicates in the main file
|
// don't allow duplicates in the main file
|
||||||
parseState.setDefinitionPolicy(Definition.OverwritePolicy.NotAllowed);
|
parseState.setDefinitionPolicy(Definition.OverwritePolicy.NotAllowed);
|
||||||
parseFile(parseState.getListener(), definitionInputFile);
|
RusefiParseErrorStrategy.parseDefinitionFile(parseState.getListener(), definitionInputFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write C structs
|
// Write C structs
|
||||||
|
@ -297,26 +287,6 @@ public class ConfigDefinition {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String readFile(String fileName) {
|
|
||||||
String line;
|
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
|
||||||
String ls = System.getProperty("line.separator");
|
|
||||||
try {
|
|
||||||
|
|
||||||
try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
|
|
||||||
while (true) {
|
|
||||||
if (!((line = reader.readLine()) != null)) break;
|
|
||||||
stringBuilder.append(line);
|
|
||||||
stringBuilder.append(ls);
|
|
||||||
}
|
|
||||||
|
|
||||||
return stringBuilder.toString();
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void handleFiringOrder(String firingEnumFileName, VariableRegistry variableRegistry, ParseState parseState) throws IOException {
|
private static void handleFiringOrder(String firingEnumFileName, VariableRegistry variableRegistry, ParseState parseState) throws IOException {
|
||||||
if (firingEnumFileName != null) {
|
if (firingEnumFileName != null) {
|
||||||
SystemOut.println("Reading firing from " + firingEnumFileName);
|
SystemOut.println("Reading firing from " + firingEnumFileName);
|
||||||
|
@ -326,158 +296,6 @@ public class ConfigDefinition {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long signatureHash(ReaderState state, ParseState parseState, String tsPath, List<String> inputAllFiles) throws IOException {
|
|
||||||
// get CRC32 of given input files
|
|
||||||
long crc32 = 0;
|
|
||||||
for (String iFile : inputAllFiles) {
|
|
||||||
long c = getCrc32(iFile) & 0xffffffffL;
|
|
||||||
SystemOut.println("CRC32 from " + iFile + " = " + c);
|
|
||||||
crc32 ^= c;
|
|
||||||
}
|
|
||||||
SystemOut.println("CRC32 from all input files = " + crc32);
|
|
||||||
// store the CRC32 as a built-in variable
|
|
||||||
|
|
||||||
// nasty trick - do not insert signature into live data files
|
|
||||||
if (tsPath != null) {
|
|
||||||
state.variableRegistry.register(SIGNATURE_HASH, "" + crc32);
|
|
||||||
parseState.addDefinition(SIGNATURE_HASH, Long.toString(crc32), Definition.OverwritePolicy.NotAllowed);
|
|
||||||
}
|
|
||||||
|
|
||||||
return crc32;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void processYamls(VariableRegistry registry, File[] yamlFiles, ReaderState state) throws IOException {
|
|
||||||
ArrayList<Map<String, Object>> listPins = new ArrayList<>();
|
|
||||||
for (File yamlFile : yamlFiles) {
|
|
||||||
processYamlFile(yamlFile, listPins);
|
|
||||||
}
|
|
||||||
registerPins(listPins, registry, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private static void processYamlFile(File yamlFile,
|
|
||||||
ArrayList<Map<String, Object>> listPins) throws IOException {
|
|
||||||
Yaml yaml = new Yaml();
|
|
||||||
Map<String, Object> yamlData = yaml.load(new FileReader(yamlFile));
|
|
||||||
if (yamlData == null) {
|
|
||||||
SystemOut.println("Null yaml for " + yamlFile);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<Map<String, Object>> data = (List<Map<String, Object>>) yamlData.get("pins");
|
|
||||||
if (data == null) {
|
|
||||||
SystemOut.println("Null yaml for " + yamlFile);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SystemOut.println(data);
|
|
||||||
Objects.requireNonNull(data, "data");
|
|
||||||
for (Map<String, Object> pin : data) {
|
|
||||||
ArrayList<Map<String, Object>> thisPinList = new ArrayList<>();
|
|
||||||
Object pinId = pin.get("id");
|
|
||||||
Object pinClass = pin.get("class");
|
|
||||||
Object pinName = pin.get("ts_name");
|
|
||||||
if (pinId == null || pinClass == null || pinName == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (pinId instanceof ArrayList) {
|
|
||||||
ArrayList<String> pinIds = (ArrayList<String>) pinId;
|
|
||||||
if (!(pinClass instanceof ArrayList))
|
|
||||||
throw new IllegalStateException("Expected multiple classes for " + pinIds);
|
|
||||||
for (int i = 0; i < pinIds.size(); i++) {
|
|
||||||
String id = pinIds.get(i);
|
|
||||||
addPinToList(listPins, thisPinList, id, pinName, ((ArrayList<String>) pinClass).get(i));
|
|
||||||
}
|
|
||||||
} else if (pinId instanceof String) {
|
|
||||||
if (((String) pinId).length() == 0) {
|
|
||||||
throw new IllegalStateException("Unexpected empty ID field");
|
|
||||||
}
|
|
||||||
addPinToList(listPins, thisPinList, pinId, pinName, pinClass);
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException("Unexpected type of ID field: " + pinId.getClass().getSimpleName());
|
|
||||||
}
|
|
||||||
listPins.addAll(thisPinList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addPinToList(ArrayList<Map<String, Object>> listPins, ArrayList<Map<String, Object>> thisPinList, Object id, Object pinName, Object pinClass) {
|
|
||||||
/*
|
|
||||||
This doesn't work as expected because it's possible that a board has multiple connector pins connected to the same MCU pin.
|
|
||||||
https://github.com/rusefi/rusefi/issues/2897
|
|
||||||
https://github.com/rusefi/rusefi/issues/2925
|
|
||||||
for (int i = 0; i < listPins.size(); i++) {
|
|
||||||
if (id.equals(listPins.get(i).get("id"))) {
|
|
||||||
throw new IllegalStateException("ID used multiple times: " + id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
Map<String, Object> thisPin = new HashMap<>();
|
|
||||||
thisPin.put("id", id);
|
|
||||||
thisPin.put("ts_name", pinName);
|
|
||||||
thisPin.put("class", pinClass);
|
|
||||||
thisPinList.add(thisPin);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void registerPins(ArrayList<Map<String, Object>> listPins, VariableRegistry registry, ReaderState state) {
|
|
||||||
if (listPins == null || listPins.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Map<String, ArrayList<String>> names = new HashMap<>();
|
|
||||||
names.put("outputs", new ArrayList<>());
|
|
||||||
names.put("analog_inputs", new ArrayList<>());
|
|
||||||
names.put("event_inputs", new ArrayList<>());
|
|
||||||
names.put("switch_inputs", new ArrayList<>());
|
|
||||||
for (int i = 0; i < listPins.size(); i++) {
|
|
||||||
String id = (String) listPins.get(i).get("id");
|
|
||||||
String className = (String) listPins.get(i).get("class");
|
|
||||||
ArrayList<String> classList = names.get(className);
|
|
||||||
if (classList == null) {
|
|
||||||
throw new IllegalStateException("Class not found: " + className);
|
|
||||||
}
|
|
||||||
PinType listPinType = PinType.find((String) listPins.get(i).get("class"));
|
|
||||||
String pinType = listPinType.getPinType();
|
|
||||||
EnumsReader.EnumState enumList = state.enumsReader.getEnums().get(pinType);
|
|
||||||
for (Map.Entry<String, Value> kv : enumList.entrySet()) {
|
|
||||||
if (kv.getKey().equals(id)) {
|
|
||||||
int index = kv.getValue().getIntValue();
|
|
||||||
classList.ensureCapacity(index + 1);
|
|
||||||
for (int ii = classList.size(); ii <= index; ii++) {
|
|
||||||
classList.add(null);
|
|
||||||
}
|
|
||||||
classList.set(index, (String) listPins.get(i).get("ts_name"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (Map.Entry<String, ArrayList<String>> kv : names.entrySet()) {
|
|
||||||
PinType namePinType = PinType.find(kv.getKey());
|
|
||||||
String outputEnumName = namePinType.getOutputEnumName();
|
|
||||||
String pinType = namePinType.getPinType();
|
|
||||||
String nothingName = namePinType.getNothingName();
|
|
||||||
EnumsReader.EnumState enumList = state.enumsReader.getEnums().get(pinType);
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
for (int i = 0; i < kv.getValue().size(); i++) {
|
|
||||||
if (sb.length() > 0)
|
|
||||||
sb.append(",");
|
|
||||||
String key = "";
|
|
||||||
for (Map.Entry<String, Value> entry : enumList.entrySet()) {
|
|
||||||
if (entry.getValue().getIntValue() == i) {
|
|
||||||
key = entry.getKey();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (key.equals(nothingName)) {
|
|
||||||
sb.append("\"NONE\"");
|
|
||||||
} else if (kv.getValue().get(i) == null) {
|
|
||||||
sb.append("\"INVALID\"");
|
|
||||||
} else {
|
|
||||||
sb.append("\"" + kv.getValue().get(i) + "\"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sb.length() > 0) {
|
|
||||||
registry.register(outputEnumName, sb.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void processTextTemplate(ReaderState state, String inputFileName, String outputFileName) throws IOException {
|
private static void processTextTemplate(ReaderState state, String inputFileName, String outputFileName) throws IOException {
|
||||||
SystemOut.println("Reading from " + inputFileName);
|
SystemOut.println("Reading from " + inputFileName);
|
||||||
SystemOut.println("Writing to " + outputFileName);
|
SystemOut.println("Writing to " + outputFileName);
|
||||||
|
@ -526,19 +344,6 @@ public class ConfigDefinition {
|
||||||
return Integer.parseInt(s);
|
return Integer.parseInt(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long getCrc32(String fileName) throws IOException {
|
|
||||||
File file = new File(fileName);
|
|
||||||
byte[] fileContent = Files.readAllBytes(file.toPath());
|
|
||||||
for (int i = 0; i < fileContent.length; i++) {
|
|
||||||
byte aByte = fileContent[i];
|
|
||||||
if (aByte == '\r')
|
|
||||||
throw new IllegalStateException("CR \\r 0x0D byte not allowed in cacheable content " + fileName + " at index=" + i);
|
|
||||||
}
|
|
||||||
CRC32 c = new CRC32();
|
|
||||||
c.update(fileContent, 0, fileContent.length);
|
|
||||||
return c.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void writeDefinesToFile(VariableRegistry variableRegistry, String fileName) throws IOException {
|
public static void writeDefinesToFile(VariableRegistry variableRegistry, String fileName) throws IOException {
|
||||||
|
|
||||||
SystemOut.println("Writing to " + fileName);
|
SystemOut.println("Writing to " + fileName);
|
||||||
|
@ -549,48 +354,4 @@ public class ConfigDefinition {
|
||||||
cHeader.close();
|
cHeader.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class RusefiParseErrorStrategy extends DefaultErrorStrategy {
|
|
||||||
private boolean hadError = false;
|
|
||||||
|
|
||||||
public boolean hadError() {
|
|
||||||
return this.hadError;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void recover(Parser recognizer, RecognitionException e) {
|
|
||||||
this.hadError = true;
|
|
||||||
|
|
||||||
super.recover(recognizer, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Token recoverInline(Parser recognizer) throws RecognitionException {
|
|
||||||
this.hadError = true;
|
|
||||||
|
|
||||||
return super.recoverInline(recognizer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void parseFile(ParseTreeListener listener, String filePath) throws IOException {
|
|
||||||
SystemOut.println("Parsing file (Antlr) " + filePath);
|
|
||||||
|
|
||||||
CharStream in = new ANTLRInputStream(new FileInputStream(filePath));
|
|
||||||
|
|
||||||
long start = System.nanoTime();
|
|
||||||
|
|
||||||
RusefiConfigGrammarParser parser = new RusefiConfigGrammarParser(new CommonTokenStream(new RusefiConfigGrammarLexer(in)));
|
|
||||||
|
|
||||||
RusefiParseErrorStrategy errorStrategy = new RusefiParseErrorStrategy();
|
|
||||||
parser.setErrorHandler(errorStrategy);
|
|
||||||
|
|
||||||
ParseTree tree = parser.content();
|
|
||||||
new ParseTreeWalker().walk(listener, tree);
|
|
||||||
double durationMs = (System.nanoTime() - start) / 1e6;
|
|
||||||
|
|
||||||
if (errorStrategy.hadError()) {
|
|
||||||
throw new RuntimeException("Parse failed, see error output above!");
|
|
||||||
}
|
|
||||||
|
|
||||||
SystemOut.println("Successfully parsed " + filePath + " in " + durationMs + "ms");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
package com.rusefi;
|
||||||
|
|
||||||
|
import com.rusefi.newparse.ParseState;
|
||||||
|
import com.rusefi.newparse.parsing.Definition;
|
||||||
|
import com.rusefi.util.SystemOut;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.zip.CRC32;
|
||||||
|
|
||||||
|
public class IoUtil {
|
||||||
|
static String readFile(String fileName) {
|
||||||
|
String line;
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
String ls = System.getProperty("line.separator");
|
||||||
|
try {
|
||||||
|
|
||||||
|
try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
|
||||||
|
while (true) {
|
||||||
|
if (!((line = reader.readLine()) != null)) break;
|
||||||
|
stringBuilder.append(line);
|
||||||
|
stringBuilder.append(ls);
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static long getCrc32(String fileName) throws IOException {
|
||||||
|
File file = new File(fileName);
|
||||||
|
byte[] fileContent = Files.readAllBytes(file.toPath());
|
||||||
|
for (int i = 0; i < fileContent.length; i++) {
|
||||||
|
byte aByte = fileContent[i];
|
||||||
|
if (aByte == '\r')
|
||||||
|
throw new IllegalStateException("CR \\r 0x0D byte not allowed in cacheable content " + fileName + " at index=" + i);
|
||||||
|
}
|
||||||
|
CRC32 c = new CRC32();
|
||||||
|
c.update(fileContent, 0, fileContent.length);
|
||||||
|
return c.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
static long signatureHash(ReaderState state, ParseState parseState, String tsPath, List<String> inputAllFiles) throws IOException {
|
||||||
|
// get CRC32 of given input files
|
||||||
|
long crc32 = 0;
|
||||||
|
for (String iFile : inputAllFiles) {
|
||||||
|
long c = getCrc32(iFile) & 0xffffffffL;
|
||||||
|
SystemOut.println("CRC32 from " + iFile + " = " + c);
|
||||||
|
crc32 ^= c;
|
||||||
|
}
|
||||||
|
SystemOut.println("CRC32 from all input files = " + crc32);
|
||||||
|
// store the CRC32 as a built-in variable
|
||||||
|
|
||||||
|
// nasty trick - do not insert signature into live data files
|
||||||
|
if (tsPath != null) {
|
||||||
|
state.variableRegistry.register(ConfigDefinition.SIGNATURE_HASH, "" + crc32);
|
||||||
|
parseState.addDefinition(ConfigDefinition.SIGNATURE_HASH, Long.toString(crc32), Definition.OverwritePolicy.NotAllowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
return crc32;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,144 @@
|
||||||
|
package com.rusefi;
|
||||||
|
|
||||||
|
import com.rusefi.enum_reader.Value;
|
||||||
|
import com.rusefi.util.SystemOut;
|
||||||
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class PinoutLogic {
|
||||||
|
public static void processYamls(VariableRegistry registry, File[] yamlFiles, ReaderState state) throws IOException {
|
||||||
|
ArrayList<Map<String, Object>> listPins = new ArrayList<>();
|
||||||
|
for (File yamlFile : yamlFiles) {
|
||||||
|
processYamlFile(yamlFile, listPins);
|
||||||
|
}
|
||||||
|
registerPins(listPins, registry, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void registerPins(ArrayList<Map<String, Object>> listPins, VariableRegistry registry, ReaderState state) {
|
||||||
|
if (listPins == null || listPins.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Map<String, ArrayList<String>> names = new HashMap<>();
|
||||||
|
names.put("outputs", new ArrayList<>());
|
||||||
|
names.put("analog_inputs", new ArrayList<>());
|
||||||
|
names.put("event_inputs", new ArrayList<>());
|
||||||
|
names.put("switch_inputs", new ArrayList<>());
|
||||||
|
for (int i = 0; i < listPins.size(); i++) {
|
||||||
|
String id = (String) listPins.get(i).get("id");
|
||||||
|
String className = (String) listPins.get(i).get("class");
|
||||||
|
ArrayList<String> classList = names.get(className);
|
||||||
|
if (classList == null) {
|
||||||
|
throw new IllegalStateException("Class not found: " + className);
|
||||||
|
}
|
||||||
|
PinType listPinType = PinType.find((String) listPins.get(i).get("class"));
|
||||||
|
String pinType = listPinType.getPinType();
|
||||||
|
EnumsReader.EnumState enumList = state.enumsReader.getEnums().get(pinType);
|
||||||
|
for (Map.Entry<String, Value> kv : enumList.entrySet()) {
|
||||||
|
if (kv.getKey().equals(id)) {
|
||||||
|
int index = kv.getValue().getIntValue();
|
||||||
|
classList.ensureCapacity(index + 1);
|
||||||
|
for (int ii = classList.size(); ii <= index; ii++) {
|
||||||
|
classList.add(null);
|
||||||
|
}
|
||||||
|
classList.set(index, (String) listPins.get(i).get("ts_name"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, ArrayList<String>> kv : names.entrySet()) {
|
||||||
|
PinType namePinType = PinType.find(kv.getKey());
|
||||||
|
String outputEnumName = namePinType.getOutputEnumName();
|
||||||
|
String pinType = namePinType.getPinType();
|
||||||
|
String nothingName = namePinType.getNothingName();
|
||||||
|
EnumsReader.EnumState enumList = state.enumsReader.getEnums().get(pinType);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < kv.getValue().size(); i++) {
|
||||||
|
if (sb.length() > 0)
|
||||||
|
sb.append(",");
|
||||||
|
String key = "";
|
||||||
|
for (Map.Entry<String, Value> entry : enumList.entrySet()) {
|
||||||
|
if (entry.getValue().getIntValue() == i) {
|
||||||
|
key = entry.getKey();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (key.equals(nothingName)) {
|
||||||
|
sb.append("\"NONE\"");
|
||||||
|
} else if (kv.getValue().get(i) == null) {
|
||||||
|
sb.append("\"INVALID\"");
|
||||||
|
} else {
|
||||||
|
sb.append("\"" + kv.getValue().get(i) + "\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sb.length() > 0) {
|
||||||
|
registry.register(outputEnumName, sb.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static void processYamlFile(File yamlFile,
|
||||||
|
ArrayList<Map<String, Object>> listPins) throws IOException {
|
||||||
|
Yaml yaml = new Yaml();
|
||||||
|
Map<String, Object> yamlData = yaml.load(new FileReader(yamlFile));
|
||||||
|
if (yamlData == null) {
|
||||||
|
SystemOut.println("Null yaml for " + yamlFile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<Map<String, Object>> data = (List<Map<String, Object>>) yamlData.get("pins");
|
||||||
|
if (data == null) {
|
||||||
|
SystemOut.println("Null yaml for " + yamlFile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SystemOut.println(data);
|
||||||
|
Objects.requireNonNull(data, "data");
|
||||||
|
for (Map<String, Object> pin : data) {
|
||||||
|
ArrayList<Map<String, Object>> thisPinList = new ArrayList<>();
|
||||||
|
Object pinId = pin.get("id");
|
||||||
|
Object pinClass = pin.get("class");
|
||||||
|
Object pinName = pin.get("ts_name");
|
||||||
|
if (pinId == null || pinClass == null || pinName == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (pinId instanceof ArrayList) {
|
||||||
|
ArrayList<String> pinIds = (ArrayList<String>) pinId;
|
||||||
|
if (!(pinClass instanceof ArrayList))
|
||||||
|
throw new IllegalStateException("Expected multiple classes for " + pinIds);
|
||||||
|
for (int i = 0; i < pinIds.size(); i++) {
|
||||||
|
String id = pinIds.get(i);
|
||||||
|
addPinToList(listPins, thisPinList, id, pinName, ((ArrayList<String>) pinClass).get(i));
|
||||||
|
}
|
||||||
|
} else if (pinId instanceof String) {
|
||||||
|
if (((String) pinId).length() == 0) {
|
||||||
|
throw new IllegalStateException("Unexpected empty ID field");
|
||||||
|
}
|
||||||
|
addPinToList(listPins, thisPinList, pinId, pinName, pinClass);
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Unexpected type of ID field: " + pinId.getClass().getSimpleName());
|
||||||
|
}
|
||||||
|
listPins.addAll(thisPinList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addPinToList(ArrayList<Map<String, Object>> listPins, ArrayList<Map<String, Object>> thisPinList, Object id, Object pinName, Object pinClass) {
|
||||||
|
/*
|
||||||
|
This doesn't work as expected because it's possible that a board has multiple connector pins connected to the same MCU pin.
|
||||||
|
https://github.com/rusefi/rusefi/issues/2897
|
||||||
|
https://github.com/rusefi/rusefi/issues/2925
|
||||||
|
for (int i = 0; i < listPins.size(); i++) {
|
||||||
|
if (id.equals(listPins.get(i).get("id"))) {
|
||||||
|
throw new IllegalStateException("ID used multiple times: " + id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
Map<String, Object> thisPin = new HashMap<>();
|
||||||
|
thisPin.put("id", id);
|
||||||
|
thisPin.put("ts_name", pinName);
|
||||||
|
thisPin.put("class", pinClass);
|
||||||
|
thisPinList.add(thisPin);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package com.rusefi;
|
||||||
|
|
||||||
|
import com.rusefi.generated.RusefiConfigGrammarLexer;
|
||||||
|
import com.rusefi.generated.RusefiConfigGrammarParser;
|
||||||
|
import com.rusefi.util.SystemOut;
|
||||||
|
import org.antlr.v4.runtime.*;
|
||||||
|
import org.antlr.v4.runtime.tree.ParseTree;
|
||||||
|
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
||||||
|
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class RusefiParseErrorStrategy extends DefaultErrorStrategy {
|
||||||
|
private boolean hadError = false;
|
||||||
|
|
||||||
|
static void parseDefinitionFile(ParseTreeListener listener, String filePath) throws IOException {
|
||||||
|
SystemOut.println("Parsing file (Antlr) " + filePath);
|
||||||
|
|
||||||
|
CharStream in = new ANTLRInputStream(new FileInputStream(filePath));
|
||||||
|
|
||||||
|
long start = System.nanoTime();
|
||||||
|
|
||||||
|
RusefiConfigGrammarParser parser = new RusefiConfigGrammarParser(new CommonTokenStream(new RusefiConfigGrammarLexer(in)));
|
||||||
|
|
||||||
|
RusefiParseErrorStrategy errorStrategy = new RusefiParseErrorStrategy();
|
||||||
|
parser.setErrorHandler(errorStrategy);
|
||||||
|
|
||||||
|
ParseTree tree = parser.content();
|
||||||
|
new ParseTreeWalker().walk(listener, tree);
|
||||||
|
double durationMs = (System.nanoTime() - start) / 1e6;
|
||||||
|
|
||||||
|
if (errorStrategy.hadError()) {
|
||||||
|
throw new RuntimeException("Parse failed, see error output above!");
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemOut.println("Successfully parsed " + filePath + " in " + durationMs + "ms");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hadError() {
|
||||||
|
return this.hadError;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recover(Parser recognizer, RecognitionException e) {
|
||||||
|
this.hadError = true;
|
||||||
|
|
||||||
|
super.recover(recognizer, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Token recoverInline(Parser recognizer) throws RecognitionException {
|
||||||
|
this.hadError = true;
|
||||||
|
|
||||||
|
return super.recoverInline(recognizer);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue