You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by hu...@apache.org on 2021/02/18 11:05:49 UTC

[plc4x] 01/01: Add support for variable strings and enum discriminators.

This is an automated email from the ASF dual-hosted git repository.

hutcheb pushed a commit to branch feature/string_enum_mspec
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit f42c2f60120540f5590ebf736fa07dccfdd28451
Author: hutcheb <be...@gmail.com>
AuthorDate: Thu Feb 18 05:38:02 2021 -0500

    Add support for variable strings and enum discriminators.
---
 .../language/java/JavaLanguageTemplateHelper.java  |  4 +--
 .../main/resources/templates/java/io-template.ftlh | 19 +++++++++++--
 .../resources/templates/java/pojo-template.ftlh    | 33 ++++++++++++++++++----
 .../plugins/codegenerator/language/mspec/MSpec.g4  | 14 ++++-----
 .../mspec/parser/MessageFormatListener.java        |  8 ++++--
 .../src/test/resources/mspec.example               |  7 +++++
 pom.xml                                            |  2 +-
 .../ads/src/main/resources/protocols/ads/ads.mspec | 12 ++++----
 .../src/main/resources/protocols/can/canopen.mspec |  6 ++--
 .../resources/protocols/knxnetip/knxnetip.mspec    |  2 +-
 protocols/knxnetip/src/main/xslt/knx-types.xsl     | 16 +++++------
 .../src/main/resources/protocols/opcua/opcua.mspec |  4 +--
 .../s7/src/main/resources/protocols/s7/s7.mspec    | 14 ++++-----
 .../resources/protocols/simulated/simulated.mspec  |  8 +++---
 14 files changed, 97 insertions(+), 52 deletions(-)

diff --git a/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java b/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
index 820bce2..fa7e36f 100644
--- a/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
+++ b/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
@@ -353,7 +353,7 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
             }
             case STRING: {
                 StringTypeReference stringTypeReference = (StringTypeReference) simpleTypeReference;
-                return "io.readString(" + stringTypeReference.getSizeInBits() + ", \"" +
+                return "io.readString(" + stringTypeReference.getLength() + ", \"" +
                     stringTypeReference.getEncoding() + "\")";
             }
         }
@@ -412,7 +412,7 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
             }
             case STRING: {
                 StringTypeReference stringTypeReference = (StringTypeReference) simpleTypeReference;
-                return "io.writeString(" + stringTypeReference.getSizeInBits() + ", \"" +
+                return "io.writeString(" + stringTypeReference.getLength() + ", \"" +
                     stringTypeReference.getEncoding() + "\", (String) " + fieldName + ")";
             }
         }
diff --git a/build-utils/language-java/src/main/resources/templates/java/io-template.ftlh b/build-utils/language-java/src/main/resources/templates/java/io-template.ftlh
index bc15070..99b1963 100644
--- a/build-utils/language-java/src/main/resources/templates/java/io-template.ftlh
+++ b/build-utils/language-java/src/main/resources/templates/java/io-template.ftlh
@@ -246,7 +246,12 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO<
         <#assign simpleTypeReference = discriminatorField.type>
 
         // Discriminator Field (${discriminatorField.name}) (Used as input to a switch field)
-        ${helper.getLanguageTypeNameForField(field)} ${discriminatorField.name} = ${helper.getReadBufferReadMethodCall(simpleTypeReference)};
+        <#if helper.isEnumField(field)>
+            ${helper.getLanguageTypeNameForField(field)} ${discriminatorField.name} = ${helper.getLanguageTypeNameForField(discriminatorField)}.enumForValue(${helper.getReadBufferReadMethodCall(helper.getEnumBaseTypeReference(discriminatorField.type))});
+        <#else>
+            ${helper.getLanguageTypeNameForField(field)} ${discriminatorField.name} = <#if helper.isSimpleTypeReference(discriminatorField.type)>${helper.getReadBufferReadMethodCall(discriminatorField.type)}<#else>${discriminatorField.type.name}IO.staticParse(io<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(discriminatorField.type, parserArgument?index), true)}) (${helper.toParseExpression(discrim [...]
+        </#if>
+
         <#break>
     <#case "enum">
         <#assign enumField = field>
@@ -468,7 +473,17 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO<
 
         // Discriminator Field (${discriminatorField.name}) (Used as input to a switch field)
         ${helper.getLanguageTypeNameForField(field)} ${discriminatorField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${discriminatorField.name?cap_first}();
-        ${helper.getWriteBufferWriteMethodCall(simpleTypeReference, "(" + discriminatorField.name + ")")};
+        <#if helper.isSimpleTypeReference(discriminatorField.type)>
+            <#assign simpleTypeReference = discriminatorField.type>
+            ${helper.getWriteBufferWriteMethodCall(simpleTypeReference, "(" + discriminatorField.name + ")")};
+        <#else>
+            <#assign complexTypeReference = discriminatorField.type>
+            <#if helper.isEnumField(field)>
+                ${helper.getWriteBufferWriteMethodCall(helper.getEnumBaseTypeReference(discriminatorField.type), "(" + discriminatorField.name + ".getValue())")};
+            <#else>
+                ${complexTypeReference.name}IO.staticSerialize(io, ${discriminatorField.name});
+            </#if>
+        </#if>
         <#break>
     <#case "enum">
         <#assign enumField = field>
diff --git a/build-utils/language-java/src/main/resources/templates/java/pojo-template.ftlh b/build-utils/language-java/src/main/resources/templates/java/pojo-template.ftlh
index 7e1dd9f..42e77e6 100644
--- a/build-utils/language-java/src/main/resources/templates/java/pojo-template.ftlh
+++ b/build-utils/language-java/src/main/resources/templates/java/pojo-template.ftlh
@@ -95,7 +95,7 @@ public<#if helper.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${
         <#if !helper.isNonDiscriminatorField(discriminatorName)>
     @JsonIgnore
     public ${helper.getLanguageTypeNameForTypeReference(helper.getDiscriminatorTypes()[discriminatorName])} get${discriminatorName?cap_first}() {
-        return <#if discriminatorValue??>${discriminatorValue}<#else>${helper.getNullValueForTypeReference(helper.getDiscriminatorTypes()[discriminatorName])}</#if>;
+        return <#if helper.getLanguageTypeNameForTypeReference(helper.getDiscriminatorTypes()[discriminatorName]) = "String"><#if discriminatorValue??>"${discriminatorValue}"<#else>${helper.getNullValueForTypeReference(helper.getDiscriminatorTypes()[discriminatorName])}</#if><#else><#if discriminatorValue??>${discriminatorValue}<#else>${helper.getNullValueForTypeReference(helper.getDiscriminatorTypes()[discriminatorName])}</#if></#if>;
     }
         </#if>
     </#list>
@@ -202,10 +202,21 @@ public<#if helper.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${
         <#break>
     <#case "discriminator">
         <#assign discriminatorField = field>
-        <#assign simpleTypeReference = discriminatorField.type>
 
         // Discriminator Field (${discriminatorField.name})
-        lengthInBits += ${simpleTypeReference.sizeInBits};
+        <#if helper.isSimpleTypeReference(discriminatorField.type)>
+            <#if helper.getLanguageTypeNameForTypeReference(discriminatorField.type) = "String">
+                <#assign simpleTypeReference = discriminatorField.type>
+                lengthInBits += ${simpleTypeReference.getLength()};
+            <#else>
+                <#assign simpleTypeReference = discriminatorField.type>
+                lengthInBits += ${simpleTypeReference.sizeInBits};
+            </#if>
+        <#elseif helper.isEnumField(field)>
+            lengthInBits += ${helper.getEnumBaseTypeReference(discriminatorField.type).sizeInBits};
+        <#else>
+            lengthInBits += ${discriminatorField.name}.getLengthInBits();
+        </#if>
         <#break>
     <#case "enum">
         <#assign enumField = field>
@@ -238,8 +249,13 @@ public<#if helper.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${
         // Optional Field (${optionalField.name})
         if(${optionalField.name} != null) {
         <#if helper.isSimpleTypeReference(optionalField.type)>
-            <#assign simpleTypeReference = optionalField.type>
-            lengthInBits += ${simpleTypeReference.sizeInBits};
+            <#if helper.getLanguageTypeNameForTypeReference(optionalField.type) = "String">
+                <#assign simpleTypeReference = optionalField.type>
+    lengthInBits += ${simpleTypeReference.getLength()};
+            <#else>
+                <#assign simpleTypeReference = optionalField.type>
+    lengthInBits += ${simpleTypeReference.sizeInBits};
+            </#if>
         <#elseif helper.isEnumField(field)>
             lengthInBits += ${helper.getEnumBaseTypeReference(optionalField.type).sizeInBits};
         <#else>
@@ -270,8 +286,13 @@ public<#if helper.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${
 
         // Simple field (${simpleField.name})
         <#if helper.isSimpleTypeReference(simpleField.type)>
-            <#assign simpleTypeReference = simpleField.type>
+                <#if helper.getLanguageTypeNameForTypeReference(simpleField.type) = "String">
+                    <#assign simpleTypeReference = simpleField.type>
+        lengthInBits += ${simpleTypeReference.getLength()};
+                <#else>
+                    <#assign simpleTypeReference = simpleField.type>
         lengthInBits += ${simpleTypeReference.sizeInBits};
+                </#if>
         <#elseif helper.isEnumField(field)>
         lengthInBits += ${helper.getEnumBaseTypeReference(simpleField.type).sizeInBits};
         <#else>
diff --git a/build-utils/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/MSpec.g4 b/build-utils/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/MSpec.g4
index add3267..560e74d 100644
--- a/build-utils/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/MSpec.g4
+++ b/build-utils/protocol-base-mspec/src/main/antlr4/org/apache/plc4x/plugins/codegenerator/language/mspec/MSpec.g4
@@ -76,7 +76,7 @@ constField
  ;
 
 discriminatorField
- : 'discriminator' type=dataType name=idExpression
+ : 'discriminator' type=typeReference name=idExpression
  ;
 
 enumField
@@ -138,7 +138,7 @@ dataType
  | base='uint' size=INTEGER_LITERAL
  | base='float' exponent=INTEGER_LITERAL '.' mantissa=INTEGER_LITERAL
  | base='ufloat' exponent=INTEGER_LITERAL '.' mantissa=INTEGER_LITERAL
- | base='string' (size=INTEGER_LITERAL)? (encoding=idExpression)?
+ | base='string' length=expression (encoding=idExpression)?
  | base='time'
  | base='date'
  | base='dateTime'
@@ -162,10 +162,7 @@ multipleExpressions
 
 innerExpression
  : BOOLEAN_LITERAL
- | HEX_LITERAL
- | INTEGER_LITERAL
- | STRING_LITERAL
- // Explicitlx allow the loop type keywords in expressions
+ // Explicitly allow the loop type keywords in expressions
  | ARRAY_LOOP_TYPE
  | IDENTIFIER_LITERAL ('(' (innerExpression (',' innerExpression)* )? ')')? ('[' innerExpression ']')?
  | innerExpression '.' innerExpression // Field Reference or method call
@@ -175,11 +172,14 @@ innerExpression
  | '(' innerExpression ')'
  | '"' innerExpression '"'
  | '!' innerExpression
+ | HEX_LITERAL
+ | INTEGER_LITERAL
+ | STRING_LITERAL
  ;
 
 idExpression
  : TICK id=IDENTIFIER_LITERAL TICK
- // Explicitlx allow the loop type keywords in id-expressions
+ // Explicitly allow the loop type keywords in id-expressions
  | TICK id=ARRAY_LOOP_TYPE TICK
  ;
 
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
index 251e09d..826b7c3 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
@@ -42,6 +42,8 @@ import java.util.*;
 
 public class MessageFormatListener extends MSpecBaseListener {
 
+
+
     private Deque<List<Field>> parserContexts;
 
     private Deque<List<EnumValue>> enumContexts;
@@ -185,7 +187,7 @@ public class MessageFormatListener extends MSpecBaseListener {
 
     @Override
     public void enterDiscriminatorField(MSpecParser.DiscriminatorFieldContext ctx) {
-        SimpleTypeReference type = getSimpleTypeReference(ctx.type);
+        TypeReference type = getTypeReference(ctx.type);
         String name = getIdString(ctx.name);
         Field field = new DefaultDiscriminatorField(null, type, name);
         if (parserContexts.peek() != null) {
@@ -437,8 +439,8 @@ public class MessageFormatListener extends MSpecBaseListener {
         SimpleTypeReference.SimpleBaseType simpleBaseType =
             SimpleTypeReference.SimpleBaseType.valueOf(ctx.base.getText().toUpperCase());
         // String types need an additional "encoding" field and an optional size.
-        if (simpleBaseType == SimpleTypeReference.SimpleBaseType.STRING) {
-            int size = (ctx.size != null) ? Integer.parseInt(ctx.size.getText()) : -1;
+        if(simpleBaseType == SimpleTypeReference.SimpleBaseType.STRING) {
+            String size = ctx.length.getText().substring( 1, ctx.length.getText().length() - 1 );
             String encoding = (ctx.encoding != null) ? ctx.encoding.getText() : "UTF-8";
             return new DefaultStringTypeReference(simpleBaseType, size, encoding);
         }
diff --git a/build-utils/protocol-base-mspec/src/test/resources/mspec.example b/build-utils/protocol-base-mspec/src/test/resources/mspec.example
index 9cb94d8..5e24015 100644
--- a/build-utils/protocol-base-mspec/src/test/resources/mspec.example
+++ b/build-utils/protocol-base-mspec/src/test/resources/mspec.example
@@ -355,4 +355,11 @@
     [simple uint 32 'sampleSize']
     // n Bytes	Data
     [array int 8 'data' count 'sampleSize']
+]
+
+//Specific Case for variable string length
+[type 'VariableStringType'
+    //Confirm implicit can be used in string length
+    [implicit uint 32 'stringLength' 'stringValue.lengthInBytes']
+    [simple string 'stringLength' 'stringValue']
 ]
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 9fdbb3c..6189924 100644
--- a/pom.xml
+++ b/pom.xml
@@ -100,7 +100,7 @@
     <!-- Exclude all generated code -->
     <sonar.exclusions>**/generated-sources</sonar.exclusions>
 
-    <plc4x-code-generation.version>1.4.0</plc4x-code-generation.version>
+    <plc4x-code-generation.version>1.5.0-SNAPSHOT</plc4x-code-generation.version>
 
     <antlr.version>4.9.1</antlr.version>
     <apiguardian.version>1.1.0</apiguardian.version>
diff --git a/protocols/ads/src/main/resources/protocols/ads/ads.mspec b/protocols/ads/src/main/resources/protocols/ads/ads.mspec
index 5392351..380a7b8 100644
--- a/protocols/ads/src/main/resources/protocols/ads/ads.mspec
+++ b/protocols/ads/src/main/resources/protocols/ads/ads.mspec
@@ -386,7 +386,7 @@
     [array int 8 'data' count 'sampleSize']
 ]
 
-[dataIo 'DataItem' [string 'dataFormatName', int 32 'stringLength']
+[dataIo 'DataItem' [string '-1' 'dataFormatName', int 32 'stringLength']
     [typeSwitch 'dataFormatName'
         // -----------------------------------------
         // Bit
@@ -458,16 +458,16 @@
         // Characters & Strings
         // -----------------------------------------
         ['IEC61131_CHAR' STRING
-//            [simple string 8 'UTF-8' 'value']
+//            [simple string '8' 'UTF-8' 'value']
         ]
         ['IEC61131_WCHAR' STRING
-//            [simple string 16 'UTF-16' 'value']
+//            [simple string '16' 'UTF-16' 'value']
         ]
         ['IEC61131_STRING' STRING
-            [manual   string  'UTF-8' 'value' 'STATIC_CALL("org.apache.plc4x.java.ads.utils.StaticHelper.parseAmsString", io, stringLength, _type.encoding)' 'STATIC_CALL("org.apache.plc4x.java.ads.utils.StaticHelper.serializeAmsString", io, _value, stringLength, _type.encoding)' 'stringLength + 1']
+            [manual   string '-1' 'UTF-8' 'value' 'STATIC_CALL("org.apache.plc4x.java.ads.utils.StaticHelper.parseAmsString", io, stringLength, _type.encoding)' 'STATIC_CALL("org.apache.plc4x.java.ads.utils.StaticHelper.serializeAmsString", io, _value, stringLength, _type.encoding)' 'stringLength + 1']
         ]
         ['IEC61131_WSTRING' STRING
-            [manual string 'UTF-16' 'value' 'STATIC_CALL("org.apache.plc4x.java.ads.utils.StaticHelper.parseAmsString", io, stringLength, _type.encoding)' 'STATIC_CALL("org.apache.plc4x.java.ads.utils.StaticHelper.serializeAmsString", io, _value, stringLength, _type.encoding)' '(stringLength * 2) + 2']
+            [manual string '-1' 'UTF-16' 'value' 'STATIC_CALL("org.apache.plc4x.java.ads.utils.StaticHelper.parseAmsString", io, stringLength, _type.encoding)' 'STATIC_CALL("org.apache.plc4x.java.ads.utils.StaticHelper.serializeAmsString", io, _value, stringLength, _type.encoding)' '(stringLength * 2) + 2']
         ]
 
         // -----------------------------------------
@@ -496,7 +496,7 @@
     ]
 ]
 
-[enum 'AdsDataType' [uint 8 'numBytes', string 'dataFormatName']
+[enum 'AdsDataType' [uint 8 'numBytes', string '-1' 'dataFormatName']
     [BOOL       ['1', 'IEC61131_BOOL']]
     [BIT        ['1', 'IEC61131_BOOL']]
     [BIT8       ['1', 'IEC61131_BOOL']]
diff --git a/protocols/canopen/src/main/resources/protocols/can/canopen.mspec b/protocols/canopen/src/main/resources/protocols/can/canopen.mspec
index a266552..b645173 100644
--- a/protocols/canopen/src/main/resources/protocols/can/canopen.mspec
+++ b/protocols/canopen/src/main/resources/protocols/can/canopen.mspec
@@ -333,13 +333,13 @@
             [array int 8 'value' length 'size']
         ]
         ['CANOpenDataType.OCTET_STRING' STRING
-            [manual string 'UTF-8' 'value'
+            [manual string '-1' 'UTF-8' 'value'
                 'STATIC_CALL("org.apache.plc4x.java.canopen.helper.CANOpenHelper.parseString", io, size, _type.encoding)'
                 'STATIC_CALL("org.apache.plc4x.java.canopen.helper.CANOpenHelper.serializeString", io, _value, _type.encoding)' '_value.length * 8'
             ]
         ]
         ['CANOpenDataType.VISIBLE_STRING' STRING
-            [manual string 'UTF-8' 'value'
+            [manual string '-1' 'UTF-8' 'value'
                 'STATIC_CALL("org.apache.plc4x.java.canopen.helper.CANOpenHelper.parseString", io, size, _type.encoding)'
                 'STATIC_CALL("org.apache.plc4x.java.canopen.helper.CANOpenHelper.serializeString", io, _value, _type.encoding)' '_value.length * 8'
             ]
@@ -347,7 +347,7 @@
         //CANOpenDataType.TIME_OF_DAY' CANOpenTime
         //CANOpenDataType.TIME_DIFFERENCE' CANOpenTime
         ['CANOpenDataType.UNICODE_STRING' STRING
-            [manual string 'UTF-8' 'value'
+            [manual string '-1' 'UTF-8' 'value'
                 'STATIC_CALL("org.apache.plc4x.java.canopen.helper.CANOpenHelper.parseString", io, size, _type.encoding)'
                 'STATIC_CALL("org.apache.plc4x.java.canopen.helper.CANOpenHelper.serializeString", io, _value, _type.encoding)' '_value.length'
             ]
diff --git a/protocols/knxnetip/src/main/resources/protocols/knxnetip/knxnetip.mspec b/protocols/knxnetip/src/main/resources/protocols/knxnetip/knxnetip.mspec
index b5c3470..1573be5 100644
--- a/protocols/knxnetip/src/main/resources/protocols/knxnetip/knxnetip.mspec
+++ b/protocols/knxnetip/src/main/resources/protocols/knxnetip/knxnetip.mspec
@@ -658,7 +658,7 @@
     ['0x20' MEDIUM_KNX_IP]
 ]
 
-[enum uint 8 'SupportedPhysicalMedia' [string 'description',                                                    bit 'knxSupport']
+[enum uint 8 'SupportedPhysicalMedia' [string '-1' 'description',                                           bit 'knxSupport']
     ['0x00' OTHER                     ['used_for_undefined_physical_medium',                                    'true']]
     ['0x01' OIL_METER                 ['measures_volume_of_oil',                                                'true']]
     ['0x02' ELECTRICITY_METER         ['measures_electric_energy',                                              'true']]
diff --git a/protocols/knxnetip/src/main/xslt/knx-types.xsl b/protocols/knxnetip/src/main/xslt/knx-types.xsl
index 55f7144..78b7573 100644
--- a/protocols/knxnetip/src/main/xslt/knx-types.xsl
+++ b/protocols/knxnetip/src/main/xslt/knx-types.xsl
@@ -47,7 +47,7 @@
 // specific language governing permissions and limitations
 // under the License.
 //
-[enum uint 16 'KnxDatapointMainType' [uint 16 'number', uint 8 'sizeInBits', string 'name']
+[enum uint 16 'KnxDatapointMainType' [uint 16 'number', uint 8 'sizeInBits', string '-1' 'name']
     ['0' DPT_UNKNOWN ['0', '0', '"Unknown Datapoint Type"']]
     // Begin: Some typed needed to support all IEC types on KNX (Which the standard generally doesn't support)
     ['1' DPT_64_BIT_SET ['0', '64', '"Unknown Datapoint Type"']]
@@ -59,7 +59,7 @@
     <xsl:apply-templates select="knx:KNX/knx:MasterData/knx:DatapointTypes/knx:DatapointType"/>
 ]
 
-[enum uint 32 'KnxDatapointType' [uint 16 'number', KnxDatapointMainType 'datapointMainType', string 'name']
+[enum uint 32 'KnxDatapointType' [uint 16 'number', KnxDatapointMainType 'datapointMainType', string '-1' 'name']
     ['0' DPT_UNKNOWN    ['0', 'KnxDatapointMainType.DPT_UNKNOWN',               '"Unknown Datapoint Subtype"']]
     // Begin: Some typed needed to support all IEC types on KNX (Which the standard generally doesn't support)
     ['1' BOOL           ['0', 'KnxDatapointMainType.DPT_1_BIT',                 '"BOOL"']]
@@ -92,23 +92,23 @@
         <xsl:apply-templates select="knx:KNX/knx:MasterData/knx:DatapointTypes/knx:DatapointType/knx:DatapointSubtypes/knx:DatapointSubtype"/>
 ]
 
-[enum uint 16 'KnxInterfaceObjectType' [string 'code', string 'name']
+[enum uint 16 'KnxInterfaceObjectType' [string '-1' 'code', string '-1' 'name']
     ['0' OT_UNKNOWN ['U', '"Unknown Interface Object Type"']]
     ['1' OT_GENERAL ['G', '"General Interface Object Type"']]
     <xsl:apply-templates select="knx:KNX/knx:MasterData/knx:InterfaceObjectTypes/knx:InterfaceObjectType"/>
 ]
 
-[enum uint 32 'KnxInterfaceObjectProperty' [uint 8 'propertyId', KnxInterfaceObjectType 'objectType', KnxPropertyDataType 'propertyDataType', string 'name']
+[enum uint 32 'KnxInterfaceObjectProperty' [uint 8 'propertyId', KnxInterfaceObjectType 'objectType', KnxPropertyDataType 'propertyDataType', string '-1' 'name']
     ['0' PID_UNKNOWN    ['0', 'KnxInterfaceObjectType.OT_UNKNOWN', 'KnxPropertyDataType.PDT_UNKNOWN', '"Unknown Interface Object Property"']]
     <xsl:apply-templates select="knx:KNX/knx:MasterData/knx:InterfaceObjectProperties/knx:InterfaceObjectProperty"/>
 ]
 
-[enum uint 8 'KnxPropertyDataType' [uint 8 'number', uint 8 'sizeInBytes', string 'name']
+[enum uint 8 'KnxPropertyDataType' [uint 8 'number', uint 8 'sizeInBytes', string '-1' 'name']
     ['0' PDT_UNKNOWN    ['0', '0',  '"Unknown Property Data Type"']]
     <xsl:apply-templates select="knx:KNX/knx:MasterData/knx:PropertyDataTypes/knx:PropertyDataType"/>
 ]
 
-[enum uint 16 'KnxManufacturer' [uint 16 'number', string 'name']
+[enum uint 16 'KnxManufacturer' [uint 16 'number', string '-1' 'name']
     ['0' M_UNKNOWN ['0', '"Unknown Manufacturer"']]
     <xsl:apply-templates select="knx:KNX/knx:MasterData/knx:Manufacturers/knx:Manufacturer"/>
 ]
@@ -446,7 +446,7 @@
                     </xsl:choose>
                 </xsl:variable>
             [reserved uint 8   '0x0']
-            [simple   string <xsl:value-of select="$datapointSubtype/knx:Format/knx:String/@Width"/> '<xsl:value-of select="$encoding"/>' 'value']
+            [simple   string '<xsl:value-of select="$datapointSubtype/knx:Format/knx:String/@Width"/>' '<xsl:value-of select="$encoding"/>' 'value']
             </xsl:when>
             <xsl:when test="$datapointSubtype/knx:Format/knx:UnsignedInteger">
                 <xsl:choose>
@@ -525,7 +525,7 @@
                         <xsl:when test="$field/@Encoding = 'iso-8859-1'">ISO-8859-1</xsl:when>
                     </xsl:choose>
                 </xsl:variable>
-                string <xsl:value-of select="$field/@Width"/> '<xsl:value-of select="$encoding"/>'</xsl:when>
+                string '<xsl:value-of select="$field/@Width"/>' '<xsl:value-of select="$encoding"/>'</xsl:when>
             <xsl:when test="name($field) = 'UnsignedInteger'">uint <xsl:value-of select="$field/@Width"/></xsl:when>
             <xsl:when test="name($field) = 'SignedInteger'">int <xsl:value-of select="$field/@Width"/></xsl:when>
             <xsl:when test="name($field) = 'Float'">
diff --git a/protocols/opcua/src/main/resources/protocols/opcua/opcua.mspec b/protocols/opcua/src/main/resources/protocols/opcua/opcua.mspec
index b715a6a..4cabc75 100644
--- a/protocols/opcua/src/main/resources/protocols/opcua/opcua.mspec
+++ b/protocols/opcua/src/main/resources/protocols/opcua/opcua.mspec
@@ -19,7 +19,7 @@
 
 // Remark: The different fields are encoded in Big-endian.
 
-[enum string 'OpcuaDataType'
+[enum string '-1' 'OpcuaDataType'
     ['IEC61131_NULL' NULL ]
     ['IEC61131_BOOL' BOOL ]
     ['IEC61131_BYTE' BYTE ]
@@ -51,7 +51,7 @@
 ]
 
 
-[enum string 'OpcuaIdentifierType'
+[enum string '-1' 'OpcuaIdentifierType'
     ['s' STRING_IDENTIFIER]
     ['i' NUMBER_IDENTIFIER]
     ['g' GUID_IDENTIFIER]
diff --git a/protocols/s7/src/main/resources/protocols/s7/s7.mspec b/protocols/s7/src/main/resources/protocols/s7/s7.mspec
index 38dcb47..53df26d 100644
--- a/protocols/s7/src/main/resources/protocols/s7/s7.mspec
+++ b/protocols/s7/src/main/resources/protocols/s7/s7.mspec
@@ -258,7 +258,7 @@
     ]
 ]
 
-[dataIo 'DataItem' [string 'dataProtocolId', int 32 'stringLength']
+[dataIo 'DataItem' [string '-1' 'dataProtocolId', int 32 'stringLength']
     [typeSwitch 'dataProtocolId'
         // -----------------------------------------
         // Bit
@@ -334,16 +334,16 @@
         // Characters & Strings
         // -----------------------------------------
         ['IEC61131_CHAR' CHAR
-            [manual string 'UTF-8' 'value'  'STATIC_CALL("org.apache.plc4x.java.s7.utils.StaticHelper.parseS7Char", io, _type.encoding)' 'STATIC_CALL("org.apache.plc4x.java.s7.utils.StaticHelper.serializeS7Char", io, _value, _type.encoding)' '1']
+            [manual string '-1' 'UTF-8' 'value'  'STATIC_CALL("org.apache.plc4x.java.s7.utils.StaticHelper.parseS7Char", io, _type.encoding)' 'STATIC_CALL("org.apache.plc4x.java.s7.utils.StaticHelper.serializeS7Char", io, _value, _type.encoding)' '1']
         ]
         ['IEC61131_WCHAR' CHAR
-            [manual string 'UTF-16' 'value' 'STATIC_CALL("org.apache.plc4x.java.s7.utils.StaticHelper.parseS7Char", io, _type.encoding)' 'STATIC_CALL("org.apache.plc4x.java.s7.utils.StaticHelper.serializeS7Char", io, _value, _type.encoding)' '2']
+            [manual string '-1' 'UTF-16' 'value' 'STATIC_CALL("org.apache.plc4x.java.s7.utils.StaticHelper.parseS7Char", io, _type.encoding)' 'STATIC_CALL("org.apache.plc4x.java.s7.utils.StaticHelper.serializeS7Char", io, _value, _type.encoding)' '2']
         ]
         ['IEC61131_STRING' STRING
-            [manual string 'UTF-8' 'value'  'STATIC_CALL("org.apache.plc4x.java.s7.utils.StaticHelper.parseS7String", io, stringLength, _type.encoding)' 'STATIC_CALL("org.apache.plc4x.java.s7.utils.StaticHelper.serializeS7String", io, _value, stringLength, _type.encoding)' '_value.length + 2']
+            [manual string '-1' 'UTF-8' 'value'  'STATIC_CALL("org.apache.plc4x.java.s7.utils.StaticHelper.parseS7String", io, stringLength, _type.encoding)' 'STATIC_CALL("org.apache.plc4x.java.s7.utils.StaticHelper.serializeS7String", io, _value, stringLength, _type.encoding)' '_value.length + 2']
         ]
         ['IEC61131_WSTRING' STRING
-            [manual string 'UTF-16' 'value' 'STATIC_CALL("org.apache.plc4x.java.s7.utils.StaticHelper.parseS7String", io, stringLength, _type.encoding)' 'STATIC_CALL("org.apache.plc4x.java.s7.utils.StaticHelper.serializeS7String", io, _value, stringLength, _type.encoding)' '(_value.length * 2) + 2']
+            [manual string '-1' 'UTF-16' 'value' 'STATIC_CALL("org.apache.plc4x.java.s7.utils.StaticHelper.parseS7String", io, stringLength, _type.encoding)' 'STATIC_CALL("org.apache.plc4x.java.s7.utils.StaticHelper.serializeS7String", io, _value, stringLength, _type.encoding)' '(_value.length * 2) + 2']
         ]
 
         // -----------------------------------------
@@ -416,7 +416,7 @@
     ['0x03' OTHERS  ]
 ]
 
-[enum int 8 'TransportSize'  [uint 8 'code', uint 8 'shortName', uint 8 'sizeInBytes', TransportSize 'baseType', DataTransportSize 'dataTransportSize', string 'dataProtocolId' , bit 'supported_S7_300', bit 'supported_S7_400', bit 'supported_S7_1200', bit 'supported_S7_1500', bit 'supported_LOGO']
+[enum int 8 'TransportSize'  [uint 8 'code', uint 8 'shortName', uint 8 'sizeInBytes', TransportSize 'baseType', DataTransportSize 'dataTransportSize', string '-1' 'dataProtocolId', bit 'supported_S7_300', bit 'supported_S7_400', bit 'supported_S7_1200', bit 'supported_S7_1500', bit 'supported_LOGO']
     // Bit Strings
     ['0x01' BOOL             ['0x01'       , 'X'               , '1'                 , 'null'                  , 'DataTransportSize.BIT'              , 'IEC61131_BOOL'         , 'true'                , 'true'                , 'true'                 , 'true'                 , 'true'              ]]
     ['0x02' BYTE             ['0x02'       , 'B'               , '1'                 , 'null'                  , 'DataTransportSize.BYTE_WORD_DWORD'  , 'IEC61131_BYTE'         , 'true'                , 'true'                , 'true'                 , 'true'                 , 'true'              ]]
@@ -457,7 +457,7 @@
     ['0x1B' DT               ['0x0F'       , 'X'               , '12'                , 'null'                  , 'null'                               , 'IEC61131_DATE_AND_TIME', 'true'                , 'true'                , 'false'                , 'true'                 , 'false'             ]]
 ]
 
-[enum uint 8 'MemoryArea'             [string 24 'shortName']
+[enum uint 8 'MemoryArea'             [string '24' 'shortName']
     ['0x1C' COUNTERS                 ['C']]
     ['0x1D' TIMERS                   ['T']]
     ['0x80' DIRECT_PERIPHERAL_ACCESS ['D']]
diff --git a/protocols/simulated/src/main/resources/protocols/simulated/simulated.mspec b/protocols/simulated/src/main/resources/protocols/simulated/simulated.mspec
index e27fefd..b4f1c75 100644
--- a/protocols/simulated/src/main/resources/protocols/simulated/simulated.mspec
+++ b/protocols/simulated/src/main/resources/protocols/simulated/simulated.mspec
@@ -19,7 +19,7 @@
 
 // Remark: The different fields are encoded in Big-endian.
 
-[dataIo 'DataItem' [string 'dataType', uint 16 'numberOfValues']
+[dataIo 'DataItem' [string '-1' 'dataType', uint 16 'numberOfValues']
     [typeSwitch 'dataType','numberOfValues'
         ['IEC61131_BOOL','1' BOOL
             [simple   bit    'value']
@@ -124,15 +124,15 @@
             [array uint 16 'value' count 'numberOfValues']
         ]
         ['IEC61131_STRING' STRING
-            [manual string 'UTF-8' 'value' 'STATIC_CALL("org.apache.plc4x.java.simulated.utils.StaticHelper.parsePascalString", io, _type.encoding)' 'STATIC_CALL("org.apache.plc4x.java.simulated.utils.StaticHelper.serializePascalString", io, _value, _type.encoding)' '_value.length + 2']
+            [manual string '-1' 'UTF-8' 'value' 'STATIC_CALL("org.apache.plc4x.java.simulated.utils.StaticHelper.parsePascalString", io, _type.encoding)' 'STATIC_CALL("org.apache.plc4x.java.simulated.utils.StaticHelper.serializePascalString", io, _value, _type.encoding)' '_value.length + 2']
         ]
         ['IEC61131_WSTRING' STRING
-            [manual string 'UTF-16' 'value''STATIC_CALL("org.apache.plc4x.java.simulated.utils.StaticHelper.parsePascalString", io, _type.encoding)' 'STATIC_CALL("org.apache.plc4x.java.simulated.utils.StaticHelper.serializePascalString", io, _value, _type.encoding)' '(_value.length * 2) + 2']
+            [manual string '-1' 'UTF-16' 'value''STATIC_CALL("org.apache.plc4x.java.simulated.utils.StaticHelper.parsePascalString", io, _type.encoding)' 'STATIC_CALL("org.apache.plc4x.java.simulated.utils.StaticHelper.serializePascalString", io, _value, _type.encoding)' '(_value.length * 2) + 2']
         ]
     ]
 ]
 
-[enum string 'SimulatedDataTypeSizes' [uint 8 'dataTypeSize']
+[enum string '-1' 'SimulatedDataTypeSizes' [uint 8 'dataTypeSize']
     ['IEC61131_BOOL' BOOL ['1']]
     ['IEC61131_BYTE' BYTE ['1']]
     ['IEC61131_WORD' WORD ['2']]