We have to move either forward or backwards with newparse #4441

This commit is contained in:
rusefillc 2023-06-16 14:47:26 -04:00
parent 752a10ee05
commit 438155dcbb
19 changed files with 0 additions and 1145 deletions

View File

@ -6,5 +6,4 @@ import com.rusefi.newparse.parsing.Definition;
public interface DefinitionsState {
void addDefinition(VariableRegistry variableRegistry, String name, String value, Definition.OverwritePolicy overwritePolicy);
void setDefinitionPolicy(Definition.OverwritePolicy policy);
}

View File

@ -144,11 +144,6 @@ public class ParseState implements DefinitionsState {
addDefinition(name, value, definitionOverwritePolicy);
}
@Override
public void setDefinitionPolicy(Definition.OverwritePolicy policy) {
this.definitionOverwritePolicy = policy;
}
public ParseTreeListener getListener() {
return new RusefiConfigGrammarBaseListener() {
@ -204,63 +199,14 @@ public class ParseState implements DefinitionsState {
@Override
public void exitScalarTypedefSuffix(RusefiConfigGrammarParser.ScalarTypedefSuffixContext ctx) {
Type datatype = Type.findByTsType(ctx.Datatype().getText());
FieldOptions options = new FieldOptions();
handleFieldOptionsList(options, ctx.fieldOptionsList());
typedefs.put(typedefName, new ScalarTypedef(typedefName, datatype, options));
}
@Override
public void enterEnumTypedefSuffix(RusefiConfigGrammarParser.EnumTypedefSuffixContext ctx) {
int endBit = Integer.parseInt(ctx.integer(1).getText());
Type datatype = Type.findByTsType(ctx.Datatype().getText());
String rhs = ctx.enumRhs().getText();
String[] values = null;
if (rhs.startsWith("@@")) {
String defName = rhs.replaceAll("@", "");
if (defName.endsWith(AUTO_ENUM_SUFFIX)) {
// clip off the "_auto_enum" part
defName = defName.substring(0, defName.length() - 10);
values = resolveEnumValues(defName);
} else {
Definition def = definitions.get(defName);
if (def == null) {
throw new RuntimeException("couldn't find definition for " + rhs);
}
Object value = def.value;
if (!(value instanceof String)) {
throw new RuntimeException("Found definition for " + rhs + " but it wasn't a string as expected");
}
rhs = (String)value;
}
}
if (values == null) {
values = Arrays.stream(rhs.split(",")) // Split on commas
.map(String::trim) // trim whitespace
.map(s -> s.replaceAll("\"", "")) // Remove quotes
.toArray(String[]::new); // Convert back to array
}
typedefs.put(typedefName, new EnumTypedef(typedefName, datatype, endBit, values));
}
@Override
public void exitStringTypedefSuffix(RusefiConfigGrammarParser.StringTypedefSuffixContext ctx) {
Double stringLength = ParseState.this.evalResults.remove();
ParseState.this.typedefs.put(ParseState.this.typedefName, new StringTypedef(ParseState.this.typedefName, stringLength.intValue()));
}
@Override
@ -355,61 +301,6 @@ public class ParseState implements DefinitionsState {
@Override
public void exitScalarField(RusefiConfigGrammarParser.ScalarFieldContext ctx) {
String type = ctx.identifier(0).getText();
String name = ctx.identifier(1).getText();
boolean autoscale = ctx.Autoscale() != null;
// First check if this is an instance of a struct
if (structs.containsKey(type)) {
scope.structFields.add(new StructField(structs.get(type), name));
return;
}
// Check first if we have a typedef for this type
Typedef typedef = typedefs.get(type);
FieldOptions options = null;
if (typedef != null) {
if (typedef instanceof ScalarTypedef) {
ScalarTypedef scTypedef = (ScalarTypedef)typedef;
// Copy the typedef's options list - we don't want to edit it
options = scTypedef.options.copy();
// Switch to the "real" type, that is the typedef's type
type = scTypedef.type.cType;
} else if (typedef instanceof EnumTypedef) {
EnumTypedef bTypedef = (EnumTypedef) typedef;
options = new FieldOptions();
// Merge the read-in options list with the default from the typedef (if exists)
handleFieldOptionsList(options, ctx.fieldOptionsList());
scope.structFields.add(new EnumField(bTypedef.type, type, name, bTypedef.endBit, bTypedef.values, options));
return;
} else if (typedef instanceof StringTypedef) {
options = new FieldOptions();
handleFieldOptionsList(options, ctx.fieldOptionsList());
StringTypedef sTypedef = (StringTypedef) typedef;
scope.structFields.add(new StringField(name, sTypedef.size, options.comment));
return;
} else {
// TODO: throw
}
} else {
// If no typedef found, it MUST be a native type
if (!Type.findByCtype(type).isPresent()) {
throw new RuntimeException("didn't understand type " + type + " for element " + name);
}
// no typedef found, create new options list
options = new FieldOptions();
}
// Merge the read-in options list with the default from the typedef (if exists)
handleFieldOptionsList(options, ctx.fieldOptionsList());
scope.structFields.add(new ScalarField(Type.findByCtype(type).get(), name, options, autoscale));
}
@Override
@ -454,17 +345,8 @@ public class ParseState implements DefinitionsState {
public void exitArrayField(RusefiConfigGrammarParser.ArrayFieldContext ctx) {
}
private int[] arrayDim = null;
@Override
public void exitArrayLengthSpec(RusefiConfigGrammarParser.ArrayLengthSpecContext ctx) {
int arrayDim0 = evalResults.remove().intValue();
if (ctx.ArrayDimensionSeparator() != null) {
this.arrayDim = new int[] { arrayDim0, evalResults.remove().intValue() };
} else {
this.arrayDim = new int[] { arrayDim0 };
}
}
@Override

View File

@ -1,33 +0,0 @@
package com.rusefi.newparse.layout;
import com.rusefi.newparse.outputs.TsMetadata;
import com.rusefi.newparse.parsing.*;
import java.io.PrintStream;
public class ArrayIterateScalarLayout extends ArrayLayout {
public ArrayIterateScalarLayout(PrototypeField prototype, int[] length) {
super(prototype, length);
}
private void emitOne(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offset, int idx) {
// Set element's position within the array
this.prototypeLayout.setOffset(offset + this.prototypeLayout.getSize() * idx);
// Put a 1-based index on the end of the name to distinguish in TS
prefixer.setIndex(idx);
this.prototypeLayout.writeTunerstudioLayout(ps, meta, prefixer, 0);
prefixer.clearIndex();
}
@Override
protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) {
// Time to iterate: emit one scalar per array element, with the name modified accordingly
for (int i = 0; i < this.length[0]; i++) {
emitOne(ps, meta, prefixer, this.offset + offsetAdd, i);
}
}
// C layout is the same if iterated or not, use default implementation
}

View File

@ -1,33 +0,0 @@
package com.rusefi.newparse.layout;
import com.rusefi.newparse.outputs.TsMetadata;
import com.rusefi.newparse.parsing.*;
import java.io.PrintStream;
public class ArrayIterateStructLayout extends ArrayLayout {
public ArrayIterateStructLayout(StructField prototype, int[] length) {
super(prototype, length);
}
private void emitOne(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offset, int idx) {
// Set element's position within the array
int offsetAdd = offset + this.prototypeLayout.getSize() * idx;
// Put a 1-based index on the end of the name to distinguish in TS
prefixer.setIndex(idx);
this.prototypeLayout.writeTunerstudioLayout(ps, meta, prefixer, offsetAdd);
prefixer.clearIndex();
}
@Override
protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) {
// Time to iterate: emit one scalar per array element, with the name modified accordingly
for (int i = 0; i < this.length[0]; i++) {
emitOne(ps, meta, prefixer, this.offset + offsetAdd, i);
}
}
// C layout is the same if iterated or not, use default implementation
}

View File

@ -1,81 +0,0 @@
package com.rusefi.newparse.layout;
import com.rusefi.newparse.outputs.TsMetadata;
import com.rusefi.newparse.parsing.*;
import java.io.PrintStream;
public class ArrayLayout extends Layout {
protected final int[] length;
protected final Layout prototypeLayout;
public ArrayLayout(PrototypeField prototype, int[] length) {
this.length = length;
if (prototype instanceof ScalarField) {
prototypeLayout = new ScalarLayout((ScalarField)prototype);
} else if (prototype instanceof EnumField) {
prototypeLayout = new EnumLayout((EnumField) prototype);
} else if (prototype instanceof StringField) {
prototypeLayout = new StringLayout((StringField) prototype);
} else if (prototype instanceof StructField) {
StructField structPrototype = (StructField)prototype;
prototypeLayout = new StructLayout(0, prototype.name, structPrototype.struct);
} else {
throw new RuntimeException("unexpected field type during array layout");
}
}
@Override
public int getSize() {
int size = this.prototypeLayout.getSize();
for (int x : this.length) {
size *= x;
}
return size;
}
@Override
public int getAlignment() {
// Arrays only need to be aligned on the alignment of the element, not the whole array
return this.prototypeLayout.getAlignment();
}
@Override
public void setOffset(int offset) {
super.setOffset(offset);
this.prototypeLayout.setOffset(offset);
}
@Override
public void setOffsetWithinStruct(int offset) {
super.setOffsetWithinStruct(offset);
this.prototypeLayout.setOffsetWithinStruct(offset);
}
@Override
public String toString() {
return "Array of " + this.prototypeLayout + " length " + this.length[0] + " " + super.toString();
}
@Override
protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) {
this.prototypeLayout.writeTunerstudioLayout(ps, meta, prefixer, offsetAdd, this.length);
}
@Override
public void writeCLayout(PrintStream ps) {
// Skip zero length arrays, they may be used for padding
if (this.length[0] > 0) {
this.prototypeLayout.writeCLayout(ps, this.length);
}
}
@Override
protected void writeOutputChannelLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) {
this.prototypeLayout.writeOutputChannelLayout(ps, prefixer, offsetAdd, this.length);
}
}

View File

@ -1,110 +0,0 @@
package com.rusefi.newparse.layout;
import com.rusefi.newparse.outputs.TsMetadata;
import com.rusefi.newparse.parsing.BitGroup;
import java.io.PrintStream;
import java.util.List;
import java.util.stream.Collectors;
public class BitGroupLayout extends Layout {
private static class BitLayout {
public final String name;
public final String comment;
public final String trueValue;
public final String falseValue;
public BitLayout(String name, String comment, String trueValue, String falseValue) {
this.name = name;
this.comment = comment;
this.trueValue = trueValue;
this.falseValue = falseValue;
}
}
private final List<BitLayout> bits;
public BitGroupLayout(BitGroup bitGroup) {
int size = bitGroup.bitFields.size();
if (size > 32) {
throw new RuntimeException("tried to create bit group starting with " + bitGroup.bitFields.get(0).name + " but it contained " + size + " which is more than the maximum of 32.");
}
this.bits = bitGroup.bitFields.stream().map(bf -> new BitLayout(bf.name, bf.comment, bf.trueValue, bf.falseValue)).collect(Collectors.toList());
}
@Override
public int getSize() {
return 4;
}
@Override
public String toString() {
return "Bit group " + super.toString();
}
@Override
protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) {
int actualOffset = this.offset + offsetAdd;
for (int i = 0; i < bits.size(); i++) {
BitLayout bit = bits.get(i);
String name = prefixer.get(bit.name);
ps.print(name);
ps.print(" = bits, U32, ");
ps.print(actualOffset);
ps.print(", [");
ps.print(i + ":" + i);
ps.print("], " + bit.falseValue + ", " + bit.trueValue);
ps.println();
meta.addComment(name, bit.comment);
}
}
@Override
public void writeCLayout(PrintStream ps) {
// always emit all 32 bits
for (int i = 0; i < 32; i++) {
ps.print("\t/**\n\t");
if (i < bits.size()) {
BitLayout bit = this.bits.get(i);
if (bit.comment != null) {
ps.println(" * " + bit.comment.replaceAll("[+]", "").replaceAll(";", "").replace("\\n", "\n\t * "));
ps.print('\t');
}
ps.println("offset " + this.offsetWithinStruct + " bit " + i + " */");
ps.println("\tbool " + bit.name + " : 1 {};");
} else {
// Force pad out all bit groups to a full 32b/4B
ps.println("offset " + this.offsetWithinStruct + " bit " + i + " */");
ps.println("\tbool unusedBit_" + this.offsetWithinStruct + "_" + i + " : 1 {};");
}
}
}
protected void writeOutputChannelLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) {
int actualOffset = this.offset + offsetAdd;
for (int i = 0; i < bits.size(); i++) {
BitLayout bit = bits.get(i);
ps.print(prefixer.get(bit.name));
ps.print(" = bits, U32, ");
ps.print(actualOffset);
ps.print(", [");
ps.print(i + ":" + i);
ps.print("]");
ps.println();
}
}
}

View File

@ -1,86 +0,0 @@
package com.rusefi.newparse.layout;
import com.rusefi.newparse.outputs.TsMetadata;
import com.rusefi.newparse.parsing.EnumField;
import com.rusefi.newparse.parsing.FieldOptions;
import com.rusefi.newparse.parsing.Type;
import java.io.PrintStream;
public class EnumLayout extends Layout {
private final String name;
private final Type type;
private final String enumType;
private final int endBit;
private final String[] values;
private final FieldOptions options;
public EnumLayout(EnumField field) {
this.name = field.name;
this.type = field.type;
this.enumType = field.enumType;
this.endBit = field.endBit;
this.values = field.values;
this.options = field.options;
}
@Override
public int getSize() {
return this.type.size;
}
private static void writeEnumVal(PrintStream ps, String enumVal) {
ps.print('"');
ps.print(enumVal);
ps.print('"');
}
@Override
protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) {
String name = prefixer.get(this.name);
ps.print(name);
ps.print(" = bits, ");
ps.print(this.type.tsType);
ps.print(", ");
ps.print(this.offset + offsetAdd);
ps.print(", ");
ps.print("[0:");
ps.print(this.endBit);
ps.print("], ");
writeEnumVal(ps, this.values[0]);
for (int i = 1; i < this.values.length; i++) {
ps.print(", ");
writeEnumVal(ps, this.values[i]);
}
ps.println();
meta.addComment(name, this.options.comment);
}
@Override
public void writeCLayout(PrintStream ps) {
this.writeCOffsetHeader(ps, this.options.comment, this.options.units);
ps.println("\t" + this.enumType + " " + this.name + ";");
}
@Override
public void writeCLayout(PrintStream ps, int[] arrayLength) {
this.writeCOffsetHeader(ps, this.options.comment, this.options.units);
ps.println("\t" + this.enumType + " " + this.name + "[" + arrayLength[0] + "];");
}
@Override
protected void writeOutputChannelLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) {
// Output an enum as a scalar, since there's no TS support for enum output channels
ps.print(prefixer.get(name));
ps.print(" = scalar, ");
ps.print(this.type.tsType);
ps.print(", ");
ps.print(this.offset + offsetAdd);
ps.println(", \"\", 1, 0");
}
}

View File

@ -1,186 +0,0 @@
package com.rusefi.newparse.layout;
import com.rusefi.ConfigDefinition;
import com.rusefi.newparse.outputs.TsMetadata;
import com.rusefi.newparse.parsing.FieldOptions;
import com.rusefi.newparse.parsing.ScalarField;
import com.rusefi.newparse.parsing.Type;
import java.io.PrintStream;
public class ScalarLayout extends Layout {
public final String name;
private final Type type;
private final FieldOptions options;
private final boolean autoscale;
public ScalarLayout(ScalarField field) {
this.name = field.name;
this.options = field.options;
this.type = field.type;
this.autoscale = field.autoscale;
}
@Override
public int getSize() {
return this.type.size;
}
@Override
public String toString() {
return "Scalar " + type.cType + " " + super.toString();
}
private void printBeforeArrayLength(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, String fieldType, int offsetAdd) {
String name = prefixer.get(this.name);
ps.print(name);
ps.print(" = " + fieldType + ", ");
ps.print(this.type.tsType);
ps.print(", ");
ps.print(this.offset + offsetAdd);
ps.print(", ");
meta.addComment(name, this.options.comment);
}
private void printAfterArrayLength(PrintStream ps) {
options.printTsFormat(ps);
ps.println();
}
@Override
protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd, int[] arrayLength) {
if (arrayLength[0] == 0) {
// Skip zero length arrays, they may be used for dynamic padding but TS doesn't like them
return;
} else if (arrayLength[0] == 1) {
// For 1-length arrays, emit as a plain scalar instead
writeTunerstudioLayout(ps, meta, prefixer, offsetAdd);
return;
}
printBeforeArrayLength(ps, meta, prefixer, "array", offsetAdd);
ps.print("[");
ps.print(arrayLength[0]);
for (int i = 1; i < arrayLength.length; i++) {
if (arrayLength[i] == 1) {
continue;
}
ps.print('x');
ps.print(arrayLength[i]);
}
ps.print("], ");
printAfterArrayLength(ps);
}
@Override
protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) {
printBeforeArrayLength(ps, meta, prefixer, "scalar", offsetAdd);
printAfterArrayLength(ps);
}
private String makeScaleString() {
double scale = this.options.scale;
long mul, div;
if (scale < 1) {
mul = Math.round(1 / scale);
div = 1;
} else {
mul = 1;
div = Math.round(scale);
}
double actualScale = (double)mul / div;
if (mul < 1 || div < 1 || (Math.abs(scale - actualScale) < 0.0001)) {
throw new RuntimeException("assertion failure: scale string generation failure for " + this.name);
}
return mul + ", " + div;
}
@Override
public void writeCLayout(PrintStream ps) {
this.writeCOffsetHeader(ps, this.options.comment, this.options.units);
String cTypeName = this.type.cType.replaceAll("^int32_t$", "int");
if (this.autoscale) {
cTypeName = "scaled_channel<" + cTypeName + ", " + makeScaleString() + ">";
}
ps.print("\t" + cTypeName + " " + this.name);
if (ConfigDefinition.needZeroInit) {
ps.print(" = (" + this.type.cType.replaceAll("^int32_t$", "int") + ")0");
}
ps.println(";");
}
@Override
public void writeCLayout(PrintStream ps, int[] arrayLength) {
this.writeCOffsetHeader(ps, this.options.comment, this.options.units);
StringBuilder al = new StringBuilder();
al.append(arrayLength[0]);
for (int i = 1; i < arrayLength.length; i++) {
al.append("][");
al.append(arrayLength[i]);
}
String cTypeName = this.type.cType.replaceAll("^int32_t$", "int");
if (this.autoscale) {
cTypeName = "scaled_channel<" + cTypeName + ", " + makeScaleString() + ">";
}
ps.println("\t" + cTypeName + " " + this.name + "[" + al + "];");
}
private void writeOutputChannelLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd, String name) {
ps.print(prefixer.get(name));
//ps.print(" = " + fieldType + ", ");
ps.print(" = scalar, ");
ps.print(this.type.tsType);
ps.print(", ");
ps.print(this.offset + offsetAdd);
ps.print(", ");
ps.print(this.options.units);
ps.print(", ");
ps.print(FieldOptions.tryRound(this.options.scale));
ps.print(", ");
ps.print(FieldOptions.tryRound(this.options.offset));
ps.println();
}
@Override
protected void writeOutputChannelLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) {
writeOutputChannelLayout(ps, prefixer, offsetAdd, this.name);
}
@Override
protected void writeOutputChannelLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd, int[] arrayLength) {
if (arrayLength.length != 1) {
throw new IllegalStateException("Output channels don't support multi dimension arrays");
}
int elementOffset = offsetAdd;
for (int i = 0; i < arrayLength[0]; i++) {
writeOutputChannelLayout(ps, prefixer, elementOffset, this.name + (i + 1));
elementOffset += type.size;
}
}
}

View File

@ -1,62 +0,0 @@
package com.rusefi.newparse.layout;
import com.rusefi.newparse.outputs.TsMetadata;
import com.rusefi.newparse.parsing.StringField;
import java.io.PrintStream;
public class StringLayout extends Layout {
private final String name;
private final int size;
private final String comment;
public StringLayout(StringField field) {
this.name = field.name;
this.size = field.size;
this.comment = field.comment;
}
@Override
public int getSize() {
return this.size;
}
@Override
public int getAlignment() {
// char can be single aligned
return 1;
}
@Override
public String toString() {
return "String " + super.toString();
}
@Override
protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) {
String name = prefixer.get(this.name);
ps.print(name);
ps.print(" = string, ASCII, ");
ps.print(this.offset + offsetAdd);
ps.print(", ");
ps.print(size);
ps.println();
if (!this.comment.isEmpty()) {
meta.addComment(name, comment);
}
}
@Override
public void writeCLayout(PrintStream ps) {
this.writeCOffsetHeader(ps, null, null);
ps.println("\tchar " + this.name + "[" + this.size + "];");
}
@Override
public void writeCLayout(PrintStream ps, int[] arrayLength) {
this.writeCOffsetHeader(ps, null, null);
ps.println("\tchar " + this.name + "[" + arrayLength[0] + "][" + this.size + "];");
}
}

View File

@ -1,213 +0,0 @@
package com.rusefi.newparse.layout;
import com.rusefi.newparse.outputs.TsMetadata;
import com.rusefi.newparse.parsing.*;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
public class StructLayout extends Layout {
/*private*/public final List<Layout> children = new ArrayList<>();
public final String typeName;
private final String name;
private final String comment;
private final Boolean noPrefix;
private final int size;
private static int getAlignedOffset(int offset, int alignment) {
// Align each element to its own size
if ((offset % alignment) != 0) {
return offset + alignment - (offset % alignment);
} else {
return offset;
}
}
int padOffsetWithUnused(int offset, int align) {
int alignedOffset = getAlignedOffset(offset, align);
int needsUnused = alignedOffset - offset;
if (needsUnused > 0) {
UnusedLayout ul = new UnusedLayout(needsUnused);
ul.setOffset(offset);
ul.setOffsetWithinStruct(offset - this.offset);
children.add(ul);
return alignedOffset;
}
return offset;
}
public StructLayout(int offset, String name, Struct parsedStruct) {
setOffset(offset);
this.typeName = parsedStruct.name;
this.name = name;
this.comment = parsedStruct.comment;
this.noPrefix = parsedStruct.noPrefix;
int initialOffest = offset;
for (Field f : parsedStruct.fields) {
if (f instanceof ArrayField) {
ArrayField asf = (ArrayField)f;
// If not a scalar, you must iterate
assert(asf.prototype instanceof ScalarField || asf.iterate);
if (asf.iterate) {
if (asf.prototype instanceof StructField) {
// Struct: special case of a struct array
offset = addItem(offset, new ArrayIterateStructLayout((StructField)asf.prototype, asf.length));
} else {
// array of scalars (or enums)
offset = addItem(offset, new ArrayIterateScalarLayout(asf.prototype, asf.length));
}
} else /* not iterate */ {
// If not a scalar, you must iterate
assert(asf.prototype instanceof ScalarField);
ScalarField prototype = (ScalarField)asf.prototype;
offset = addItem(offset, new ArrayLayout(prototype, asf.length));
}
} else {
offset = addItem(offset, f);
}
}
// Structs are always a multiple of 4 bytes long, pad the end appropriately
offset = padOffsetWithUnused(offset, 4);
size = offset - initialOffest;
}
private int addItem(int offset, Field f) {
if (f instanceof StructField) {
// Special case for structs - we have to compute base offset first
StructField sf = (StructField) f;
return addStruct(offset, sf.struct, sf.name);
}
Layout l;
if (f instanceof ScalarField) {
l = new ScalarLayout((ScalarField)f);
} else if (f instanceof EnumField) {
l = new EnumLayout((EnumField)f);
} else if (f instanceof UnusedField) {
l = new UnusedLayout((UnusedField) f);
} else if (f instanceof BitGroup) {
l = new BitGroupLayout((BitGroup) f);
} else if (f instanceof StringField) {
l = new StringLayout((StringField) f);
} else if (f instanceof Union) {
l = new UnionLayout((Union)f);
} else {
throw new RuntimeException("unexpected field type during layout");
}
return addItem(offset, l);
}
private int addItem(int offset, Layout l) {
// Slide the offset up by the required alignment of this element
offset = padOffsetWithUnused(offset, l.getAlignment());
// place the element
l.setOffset(offset);
l.setOffsetWithinStruct(offset - this.offset);
children.add(l);
return offset + l.getSize();
}
private int addStruct(int offset, Struct struct, String name) {
offset = padOffsetWithUnused(offset, 4);
// Recurse and build this new struct
StructLayout sl = new StructLayout(offset, name, struct);
sl.setOffsetWithinStruct(offset - this.offset);
this.children.add(sl);
// Update offset with the struct size - it's guaranteed to be a multiple of 4 bytes
int structSize = sl.getSize();
return offset + structSize;
}
@Override
public int getSize() {
return this.size;
}
@Override
public int getAlignment() {
// All structs should be aligned on a 4 byte boundary
return 4;
}
@Override
public String toString() {
return "Struct " + this.typeName + " " + super.toString();
}
@Override
protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) {
if (!this.noPrefix) {
prefixer.push(this.name);
}
// print all children in sequence
this.children.forEach(c -> c.writeTunerstudioLayout(ps, meta, prefixer, offsetAdd));
if (!this.noPrefix) {
prefixer.pop();
}
}
@Override
public void writeCLayout(PrintStream ps) {
this.writeCOffsetHeader(ps, null, null);
ps.println("\t" + this.typeName + " " + this.name + ";");
}
@Override
public void writeCLayout(PrintStream ps, int[] arrayLength) {
this.writeCOffsetHeader(ps, null, null);
ps.println("\t" + this.typeName + " " + this.name + "[" + arrayLength[0] + "];");
}
public void writeCLayoutRoot(PrintStream ps) {
if (this.comment != null) {
ps.println("/**\n * @brief " + this.comment);
ps.println("*/");
}
ps.println("// start of " + this.typeName);
ps.println("struct " + this.typeName + " {");
this.children.forEach(c -> c.writeCLayout(ps));
ps.println("};");
ps.println("static_assert(sizeof(" + this.typeName + ") == " + getSize() + ");");
ps.println();
}
@Override
protected void writeOutputChannelLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) {
if (!this.noPrefix) {
prefixer.push(this.name);
}
this.children.forEach(c -> c.writeOutputChannelLayout(ps, prefixer, offsetAdd));
if (!this.noPrefix) {
prefixer.pop();
}
}
}

View File

@ -1,73 +0,0 @@
package com.rusefi.newparse.layout;
import com.rusefi.newparse.outputs.TsMetadata;
import com.rusefi.newparse.parsing.ArrayField;
import com.rusefi.newparse.parsing.Field;
import com.rusefi.newparse.parsing.ScalarField;
import com.rusefi.newparse.parsing.Union;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
public class UnionLayout extends Layout {
private final List<Layout> children = new ArrayList<>();
public UnionLayout(Union u) {
for (Field f : u.fields) {
// For every child, check if it is the largest, and grow if so
if (f instanceof ArrayField) {
ArrayField af = (ArrayField)f;
// we probably don't need union of iterate?
assert(!af.iterate);
ScalarField prototype = (ScalarField)af.prototype;
this.children.add(new ArrayLayout(prototype, af.length));
} else if (f instanceof ScalarField) {
this.children.add(new ScalarLayout((ScalarField)f));
} else {
throw new RuntimeException("Tried to create union with member type " + f.getClass().getSimpleName());
}
}
}
@Override
public void setOffset(int offset) {
super.setOffset(offset);
this.children.forEach(c -> c.setOffset(offset));
}
@Override
public void setOffsetWithinStruct(int offset) {
super.setOffsetWithinStruct(offset);
this.children.forEach(c -> c.setOffsetWithinStruct(offset));
}
@Override
public int getSize() {
return this.children.stream().map(Layout::getSize).max(Integer::compare).get();
}
@Override
public int getAlignment() {
// The alignment of the union is the largest alignment required by one of the members
return this.children.stream().map(Layout::getAlignment).max(Integer::compare).get();
}
@Override
protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) {
// Simply write out all children - no container necessary as fields can overlap in TS
this.children.forEach(c -> c.writeTunerstudioLayout(ps, meta, prefixer, offsetAdd));
}
@Override
public void writeCLayout(PrintStream ps) {
this.writeCOffsetHeader(ps, "union size " + this.getSize() + ", " + this.children.size() + " members", null);
// emit an anonymous union that contains all our members
ps.println("\tunion {");
this.children.forEach(c -> c.writeCLayout(ps));
ps.println("\t};");
}
}

View File

@ -1,44 +0,0 @@
package com.rusefi.newparse.layout;
import com.rusefi.newparse.outputs.TsMetadata;
import com.rusefi.newparse.parsing.UnusedField;
import java.io.PrintStream;
public class UnusedLayout extends Layout {
private final int size;
public UnusedLayout(int size) {
this.size = size;
}
public UnusedLayout(UnusedField field) {
this.size = field.size;
}
@Override
public int getSize() {
return this.size;
}
@Override
public int getAlignment() {
return 1;
}
@Override
public String toString() {
return "Unused " + super.toString();
}
@Override
protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) {
ps.println("; unused " + this.size + " bytes at offset " + (this.offset + offsetAdd));
}
@Override
public void writeCLayout(PrintStream ps) {
this.writeCOffsetHeader(ps, null, null);
ps.println("\tchar unused" + this.offsetWithinStruct + "[" + this.size + "];");
}
}

View File

@ -1,13 +0,0 @@
package com.rusefi.newparse.parsing;
public class ArrayField<PrototypeType extends PrototypeField> implements Field {
public final int[] length;
public final Boolean iterate;
public final PrototypeType prototype;
public ArrayField(PrototypeType prototype, int[] length, Boolean iterate) {
this.length = length;
this.iterate = iterate;
this.prototype = prototype;
}
}

View File

@ -1,24 +0,0 @@
package com.rusefi.newparse.parsing;
public class EnumField extends PrototypeField {
public final Type type;
public final String enumType;
public final int endBit;
public final String[] values;
public final FieldOptions options;
public EnumField(Type type, String enumType, String name, int endBit, String[] values, FieldOptions options) {
super(name);
this.type = type;
this.enumType = enumType;
this.endBit = endBit;
this.values = values;
this.options = options;
}
@Override
public String toString() {
return "enum " + type.cType + " " + this.name;
}
}

View File

@ -1,15 +0,0 @@
package com.rusefi.newparse.parsing;
public class EnumTypedef extends Typedef {
public final Type type;
public final int endBit;
public final String[] values;
public EnumTypedef(String name, Type type, int endBit, String[] values) {
super(name);
this.type = type;
this.endBit = endBit;
this.values = values;
}
}

View File

@ -1,9 +0,0 @@
package com.rusefi.newparse.parsing;
public abstract class PrototypeField implements Field {
public final String name;
protected PrototypeField(String name) {
this.name = name;
}
}

View File

@ -1,20 +0,0 @@
package com.rusefi.newparse.parsing;
public class ScalarField extends PrototypeField {
public final Type type;
public final FieldOptions options;
public final Boolean autoscale;
public ScalarField(Type type, String name, FieldOptions options, boolean autoscale) {
super(name);
this.type = type;
this.options = options;
this.autoscale = autoscale;
}
@Override
public String toString() {
return type.cType + " " + name;
}
}

View File

@ -1,13 +0,0 @@
package com.rusefi.newparse.parsing;
public class StringField extends PrototypeField {
public final int size;
public final String comment;
public StringField(String name, int size, String comment) {
super(name);
this.size = size;
this.comment = comment;
}
}

View File

@ -1,11 +0,0 @@
package com.rusefi.newparse.parsing;
public class StructField extends PrototypeField {
public final Struct struct;
public StructField(Struct struct, String name) {
super(name);
this.struct = struct;
}
}