Browse Source

NodesetCompiler use Byte array instead of string (#1621)

* Use byte array instead of string

fixes #1254

The huge strings are changed as arrays of ASCII values of each element inside for ByteArrays. And also some implementations are done due to task.

* Remove max-string-length parameter for nodeset compiler

* Flush nodeset generated file to avoid buffer race conditions

* Use global variables for byte array to improve performance
Yekta Nizamoğlu 6 years ago
parent
commit
8158f37248

+ 0 - 8
CMakeLists.txt

@@ -739,13 +739,6 @@ add_dependencies(open62541-amalgamation-header open62541-generator-types)
 add_dependencies(open62541-amalgamation-source open62541-generator-types
                  open62541-generator-transport open62541-generator-statuscode)
 
-
-set(NODESET_MAX_STR_LEN 0)
-if(MSVC)
-    # Visual Studio has a maximum string length of 65535 bytes
-    set(NODESET_MAX_STR_LEN 65535)
-endif()
-
 if(NOT UA_NODESET_ENCODE_BINARY_SIZE)
     set(UA_NODESET_ENCODE_BINARY_SIZE 32000)
 endif()
@@ -757,7 +750,6 @@ add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_namespace0.c
                    COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset_compiler.py
                            --generate-ns0
                            --internal-headers
-                           --max-string-length=${NODESET_MAX_STR_LEN}
                            --encode-binary-size=${UA_NODESET_ENCODE_BINARY_SIZE}
                            --ignore ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/NodeID_NS0_Base.txt
                            --xml ${UA_FILE_NS0}

+ 1 - 1
doc/nodeset_compiler.rst

@@ -212,7 +212,7 @@ Take the previous snippet and save it to a file ``myNS.xml``. To compile this no
                                [--generate-ns0] [--internal-headers]
                                [-b <blacklistFile>] [-i <ignoreFile>]
                                [-t <typesArray>]
-                               [--max-string-length MAX_STRING_LENGTH] [-v]
+                               [-v]
                                <outputFile>
 
     positional arguments:

+ 12 - 2
tools/nodeset_compiler/backend_open62541.py

@@ -23,6 +23,7 @@ import string
 from os.path import basename
 import logging
 import codecs
+import os
 try:
     from StringIO import StringIO
 except ImportError:
@@ -130,7 +131,7 @@ def sortNodes(nodeset):
 # Generate C Code #
 ###################
 
-def generateOpen62541Code(nodeset, outfilename, generate_ns0=False, internal_headers=False, typesArray=[], max_string_length=0, encode_binary_size=32000):
+def generateOpen62541Code(nodeset, outfilename, generate_ns0=False, internal_headers=False, typesArray=[], encode_binary_size=32000):
     outfilebase = basename(outfilename)
     # Printing functions
     outfileh = codecs.open(outfilename + ".h", r"w+", encoding='utf-8')
@@ -234,12 +235,16 @@ extern UA_StatusCode %s(UA_Server *server);
         parentref = node.popParentRef(parentreftypes)
         if not node.hidden:
             writec("\n/* " + str(node.displayName) + " - " + str(node.id) + " */")
-            code = generateNodeCode_begin(node, nodeset, max_string_length, generate_ns0, parentref, encode_binary_size)
+            code_global = []
+            code = generateNodeCode_begin(node, nodeset, generate_ns0, parentref, encode_binary_size, code_global)
             if code is None:
                 writec("/* Ignored. No parent */")
                 nodeset.hide_node(node.id)
                 continue
             else:
+                if len(code_global) > 0:
+                    writec("\n".join(code_global))
+                    writec("\n")
                 writec("\nstatic UA_StatusCode function_" + outfilebase + "_" + str(functionNumber) + "_begin(UA_Server *server, UA_UInt16* ns) {")
                 if isinstance(node, MethodNode):
                     writec("#ifdef UA_ENABLE_METHODCALLS")
@@ -295,10 +300,15 @@ UA_StatusCode retVal = UA_STATUSCODE_GOOD;""" % (outfilebase))
         writec("retVal |= function_" + outfilebase + "_" + str(i) + "_finish(server, ns);")
 
     writec("return retVal;\n}")
+    outfileh.flush()
+    os.fsync(outfileh)
     outfileh.close()
     fullCode = outfilec.getvalue()
     outfilec.close()
 
     outfilec = codecs.open(outfilename + ".c", r"w+", encoding='utf-8')
     outfilec.write(fullCode)
+    outfilec.flush()
+    os.fsync(outfilec)
     outfilec.close()
+

+ 33 - 29
tools/nodeset_compiler/backend_open62541_datatypes.py

@@ -14,18 +14,13 @@ def generateBooleanCode(value):
 def makeCLiteral(value):
     return value.replace('\\', r'\\\\').replace('\n', r'\\n').replace('\r', r'')
 
-def splitStringLiterals(value, splitLength=500, max_string_length=0):
+def splitStringLiterals(value, splitLength=500):
     """
     Split a string literal longer than splitLength into smaller literals.
     E.g. "Some very long text" will be split into "Some ver" "y long te" "xt"
     On VS2008 there is a maximum allowed length of a single string literal.
-    If maxLength is set and the string is longer than maxLength, then an
-    empty string will be returned.
     """
     value = value.strip()
-    if max_string_length > 0 and len(value) > max_string_length:
-        logger.info("String is longer than {}. Returning empty string.".format(max_string_length))
-        return "\"\""
     if len(value) < splitLength or splitLength == 0:
         return "\"" + value.replace('"', r'\"') + "\""
     ret = ""
@@ -36,27 +31,33 @@ def splitStringLiterals(value, splitLength=500, max_string_length=0):
     ret += "\"" + tmp.replace('"', r'\"') + "\" "
     return ret
 
-def generateStringCode(value, alloc=False, max_string_length=0):
+def generateStringCode(value, alloc=False):
     value = makeCLiteral(value)
-    return u"UA_STRING{}({})".format("_ALLOC" if alloc else "", splitStringLiterals(value, max_string_length=max_string_length))
+    return u"UA_STRING{}({})".format("_ALLOC" if alloc else "", splitStringLiterals(value))
 
-def generateXmlElementCode(value, alloc=False, max_string_length=0):
+def generateXmlElementCode(value, alloc=False):
     value = makeCLiteral(value)
-    return u"UA_XMLELEMENT{}({})".format("_ALLOC" if alloc else "", splitStringLiterals(value, max_string_length=max_string_length))
+    return u"UA_XMLELEMENT{}({})".format("_ALLOC" if alloc else "", splitStringLiterals(value))
 
-def generateByteStringCode(value, alloc=False, max_string_length=0):
-    value = makeCLiteral(value)
-    return u"UA_BYTESTRING{}({})".format("_ALLOC" if alloc else "", splitStringLiterals(value, max_string_length=max_string_length))
+def generateByteStringCode(value, valueName, global_var_code):
+    asciiarray = [ord(c) for c in value.strip()]
+    asciiarraystr = str(asciiarray).rstrip(']').lstrip('[')
+    global_var_code.append("static const UA_Byte {instance}_byteArray[{len}] = {{{data}}};".format(
+        len=len(asciiarray), data=asciiarraystr, instance=valueName
+    ))
+    # Cast away const with '(UA_Byte *)(void*)(uintptr_t)' since we know that UA_Server_addNode_begin will copy the content
+    return "{instance}->length = {len};\n{instance}->data = (UA_Byte *)(void*)(uintptr_t){instance}_byteArray;"\
+                                                .format(len=len(asciiarray), instance=valueName)
 
-def generateLocalizedTextCode(value, alloc=False, max_string_length=0):
+def generateLocalizedTextCode(value, alloc=False):
     vt = makeCLiteral(value.text)
     return u"UA_LOCALIZEDTEXT{}(\"{}\", {})".format("_ALLOC" if alloc else "", value.locale,
-                                                   splitStringLiterals(vt, max_string_length=max_string_length))
+                                                   splitStringLiterals(vt))
 
-def generateQualifiedNameCode(value, alloc=False, max_string_length=0):
+def generateQualifiedNameCode(value, alloc=False,):
     vn = makeCLiteral(value.name)
     return u"UA_QUALIFIEDNAME{}(ns[{}], {})".format("_ALLOC" if alloc else "",
-                                                     str(value.ns), splitStringLiterals(vn, max_string_length=max_string_length))
+                                                     str(value.ns), splitStringLiterals(vn))
 
 def generateNodeIdCode(value):
     if not value:
@@ -81,26 +82,29 @@ def generateDateTimeCode(value):
     mSecsSinceEpoch = int((value - epoch).total_seconds() * 1000.0)
     return "( (UA_DateTime)(" + str(mSecsSinceEpoch) + " * UA_DATETIME_MSEC) + UA_DATETIME_UNIX_EPOCH)"
 
-def generateNodeValueCode(node, instanceName, asIndirect=False, max_string_length=0):
+def generateNodeValueCode(prepend , node, instanceName, valueName, global_var_code, asIndirect=False):
     if type(node) in [Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Float, Double]:
-        return "(UA_" + node.__class__.__name__ + ") " + str(node.value)
+        return prepend + "(UA_" + node.__class__.__name__ + ") " + str(node.value) + ";"
     elif type(node) == String:
-        return generateStringCode(node.value, alloc=asIndirect, max_string_length=max_string_length)
+        return prepend + generateStringCode(node.value, alloc=asIndirect) + ";"
     elif type(node) == XmlElement:
-        return generateXmlElementCode(node.value, alloc=asIndirect, max_string_length=max_string_length)
+        return prepend + generateXmlElementCode(node.value, alloc=asIndirect) + ";"
     elif type(node) == ByteString:
         # replace whitespaces between tags and remove newlines
-        return "UA_BYTESTRING_NULL" if not node.value else generateByteStringCode(re.sub(r">\s*<", "><", re.sub(r"[\r\n]+", "", node.value)), alloc=asIndirect, max_string_length=max_string_length)
+        return prepend + "UA_BYTESTRING_NULL;" if not node.value else generateByteStringCode(
+            re.sub(r">\s*<", "><", re.sub(r"[\r\n]+", "", node.value)), valueName, global_var_code)
+        # the replacements done here is just for the array form can be workable in C code. It doesn't couses any problem
+        # because the core data used here is already in byte form. So, there is no way we disturb it.
     elif type(node) == LocalizedText:
-        return generateLocalizedTextCode(node, alloc=asIndirect, max_string_length=max_string_length)
+        return prepend + generateLocalizedTextCode(node, alloc=asIndirect) + ";"
     elif type(node) == NodeId:
-        return generateNodeIdCode(node)
+        return prepend + generateNodeIdCode(node) + ";"
     elif type(node) == ExpandedNodeId:
-        return generateExpandedNodeIdCode(node)
+        return prepend + generateExpandedNodeIdCode(node) + ";"
     elif type(node) == DateTime:
-        return generateDateTimeCode(node.value)
+        return prepend + generateDateTimeCode(node.value) + ";"
     elif type(node) == QualifiedName:
-        return generateQualifiedNameCode(node.value, alloc=asIndirect, max_string_length=max_string_length)
+        return prepend + generateQualifiedNameCode(node.value, alloc=asIndirect) + ";"
     elif type(node) == StatusCode:
         raise Exception("generateNodeValueCode for type " + node.__class__.name + " not implemented")
     elif type(node) == DiagnosticInfo:
@@ -109,5 +113,5 @@ def generateNodeValueCode(node, instanceName, asIndirect=False, max_string_lengt
         raise Exception("generateNodeValueCode for type " + node.__class__.name + " not implemented")
     elif type(node) == ExtensionObject:
         if asIndirect == False:
-            return "*" + str(instanceName)
-        return str(instanceName)
+            return prepend + "*" + str(instanceName) + ";"
+        return prepend + str(instanceName) + ";"

+ 48 - 37
tools/nodeset_compiler/backend_open62541_nodes.py

@@ -72,9 +72,10 @@ def generateObjectNodeCode(node):
         code.append("attr.eventNotifier = true;")
     return code
 
-def generateVariableNodeCode(node, nodeset, max_string_length, encode_binary_size):
+def generateVariableNodeCode(node, nodeset, encode_binary_size):
     code = []
     codeCleanup = []
+    codeGlobal = []
     code.append("UA_VariableAttributes attr = UA_VariableAttributes_default;")
     if node.historizing:
         code.append("attr.historizing = true;")
@@ -111,19 +112,21 @@ def generateVariableNodeCode(node, nodeset, max_string_length, encode_binary_siz
 
             if dataTypeNode.isEncodable():
                 if node.value is not None:
-                    [code1, codeCleanup1] = generateValueCode(node.value, nodeset.nodes[node.id], nodeset, max_string_length=max_string_length, encode_binary_size=encode_binary_size)
+                    [code1, codeCleanup1, codeGlobal1] = generateValueCode(node.value, nodeset.nodes[node.id], nodeset, encode_binary_size=encode_binary_size)
                     code += code1
                     codeCleanup += codeCleanup1
+                    codeGlobal += codeGlobal1
                     if node.valueRank > 0 and len(node.arrayDimensions) == node.valueRank:
                         code.append("attr.value.arrayDimensionsSize = attr.arrayDimensionsSize;")
                         code.append("attr.value.arrayDimensions = attr.arrayDimensions;")
                 else:
                     code += generateValueCodeDummy(dataTypeNode, nodeset.nodes[node.id], nodeset)
-    return [code, codeCleanup]
+    return [code, codeCleanup, codeGlobal]
 
-def generateVariableTypeNodeCode(node, nodeset, max_string_length, encode_binary_size):
+def generateVariableTypeNodeCode(node, nodeset, encode_binary_size):
     code = []
     codeCleanup = []
+    codeGlobal = []
     code.append("UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;")
     if node.historizing:
         code.append("attr.historizing = true;")
@@ -140,14 +143,15 @@ def generateVariableTypeNodeCode(node, nodeset, max_string_length, encode_binary
             code.append("attr.dataType = %s;" % generateNodeIdCode(dataTypeNode.id))
             if dataTypeNode.isEncodable():
                 if node.value is not None:
-                    [code1, codeCleanup1] = generateValueCode(node.value, nodeset.nodes[node.id], nodeset, max_string_length, encode_binary_size)
+                    [code1, codeCleanup1, codeGlobal1] = generateValueCode(node.value, nodeset.nodes[node.id], nodeset, encode_binary_size)
                     code += code1
                     codeCleanup += codeCleanup1
+                    codeGlobal += codeGlobal1
                 else:
                     code += generateValueCodeDummy(dataTypeNode, nodeset.nodes[node.id], nodeset)
-    return [code, codeCleanup]
+    return [code, codeCleanup, codeGlobal]
 
-def generateExtensionObjectSubtypeCode(node, parent, nodeset, recursionDepth=0, arrayIndex=0, max_string_length=0, encode_binary_size=32000):
+def generateExtensionObjectSubtypeCode(node, parent, nodeset, global_var_code, recursionDepth=0, arrayIndex=0, encode_binary_size=32000):
     code = [""]
     codeCleanup = [""]
 
@@ -185,8 +189,9 @@ def generateExtensionObjectSubtypeCode(node, parent, nodeset, recursionDepth=0,
             "Encoding of field " + subv.alias + " is " + str(subv.encodingRule) + "defined by " + str(encField))
         # Check if this is an array
         if encField[2] == 0:
-            code.append(instanceName + "_struct." + subv.alias + " = " +
-                        generateNodeValueCode(subv, instanceName, asIndirect=False, max_string_length=max_string_length) + ";")
+            valueName = instanceName + "_struct." + subv.alias
+            code.append(generateNodeValueCode(valueName + " = " ,
+                        subv, instanceName,valueName, global_var_code, asIndirect=False))
         else:
             if isinstance(subv, list):
                 # this is an array
@@ -199,8 +204,9 @@ def generateExtensionObjectSubtypeCode(node, parent, nodeset, recursionDepth=0,
                 for subvidx in range(0, len(subv)):
                     subvv = subv[subvidx]
                     logger.debug("  " + str(subvidx) + " " + str(subvv))
-                    code.append(instanceName + "_struct." + subv.alias + "[" + str(
-                        subvidx) + "] = " + generateNodeValueCode(subvv, instanceName, max_string_length=max_string_length) + ";")
+                    valueName = instanceName + "_struct." + subv.alias + "[" + str(
+                        subvidx) + "]"
+                    code.append(generateNodeValueCode(valueName + " = ", subvv, instanceName, valueName, global_var_code))
                 code.append("}")
             else:
                 code.append(instanceName + "_struct." + subv.alias + "Size = 1;")
@@ -208,9 +214,9 @@ def generateExtensionObjectSubtypeCode(node, parent, nodeset, recursionDepth=0,
                     "{0}_struct.{1} = (UA_{2}*) UA_malloc(sizeof(UA_{2}));".format(
                         instanceName, subv.alias, subv.__class__.__name__))
                 codeCleanup.append("UA_free({0}_struct.{1});".format(instanceName, subv.alias))
-
-                code.append(instanceName + "_struct." + subv.alias + "[0]  = " +
-                            generateNodeValueCode(subv, instanceName, asIndirect=True, max_string_length=max_string_length) + ";")
+                valueName = instanceName + "_struct." + subv.alias + "[0]"
+                code.append(generateNodeValueCode(valueName + " = ",
+                            subv, instanceName, valueName, global_var_code, asIndirect=True))
 
     # Allocate some memory
     code.append("UA_ExtensionObject *" + instanceName + " =  UA_ExtensionObject_new();")
@@ -295,9 +301,10 @@ def getTypesArrayForValue(nodeset, value):
     return "&" + typesArray + "[" + typesArray + "_" + \
                     value.__class__.__name__.upper() + "]"
 
-def generateValueCode(node, parentNode, nodeset, bootstrapping=True, max_string_length=0, encode_binary_size=32000):
+def generateValueCode(node, parentNode, nodeset, bootstrapping=True, encode_binary_size=32000):
     code = []
     codeCleanup = []
+    codeGlobal = []
     valueName = generateNodeIdPrintable(parentNode) + "_variant_DataContents"
 
     # node.value either contains a list of multiple identical BUILTINTYPES, or it
@@ -330,8 +337,8 @@ def generateValueCode(node, parentNode, nodeset, bootstrapping=True, max_string_
             if isinstance(node.value[0], ExtensionObject):
                 for idx, v in enumerate(node.value):
                     logger.debug("Building extObj array index " + str(idx))
-                    [code1, codeCleanup1] = generateExtensionObjectSubtypeCode(v, parent=parentNode, nodeset=nodeset, arrayIndex=idx, max_string_length=max_string_length,
-                                                                               encode_binary_size=encode_binary_size)
+                    [code1, codeCleanup1] = generateExtensionObjectSubtypeCode(v, parent=parentNode, nodeset=nodeset, arrayIndex=idx,
+                                                                               encode_binary_size=encode_binary_size, global_var_code=codeGlobal)
                     code = code + code1
                     codeCleanup = codeCleanup + codeCleanup1
             code.append("UA_" + node.value[0].__class__.__name__ + " " + valueName + "[" + str(len(node.value)) + "];")
@@ -339,15 +346,15 @@ def generateValueCode(node, parentNode, nodeset, bootstrapping=True, max_string_
                 for idx, v in enumerate(node.value):
                     logger.debug("Printing extObj array index " + str(idx))
                     instanceName = generateNodeValueInstanceName(v, parentNode, 0, idx)
-                    code.append(
-                        valueName + "[" + str(idx) + "] = " +
-                        generateNodeValueCode(v, instanceName, max_string_length=max_string_length) + ";")
+                    code.append(generateNodeValueCode(
+                        valueName + "[" + str(idx) + "] = ",
+                        v, instanceName, valueName, codeGlobal))
                     # code.append("UA_free(&" +valueName + "[" + str(idx) + "]);")
             else:
                 for idx, v in enumerate(node.value):
                     instanceName = generateNodeValueInstanceName(v, parentNode, 0, idx)
-                    code.append(
-                        valueName + "[" + str(idx) + "] = " + generateNodeValueCode(v, instanceName, max_string_length=max_string_length) + ";")
+                    code.append(generateNodeValueCode(
+                        valueName + "[" + str(idx) + "] = " , v, instanceName, valueName, codeGlobal))
             code.append("UA_Variant_setArray(&attr.value, &" + valueName +
                         ", (UA_Int32) " + str(len(node.value)) + ", " +
                         getTypesArrayForValue(nodeset, node.value[0]) + ");")
@@ -362,14 +369,14 @@ def generateValueCode(node, parentNode, nodeset, bootstrapping=True, max_string_
         else:
             # The following strategy applies to all other types, in particular strings and numerics.
             if isinstance(node.value[0], ExtensionObject):
-                [code1, codeCleanup1] = generateExtensionObjectSubtypeCode(node.value[0], parent=parentNode, nodeset=nodeset, max_string_length=max_string_length,
-                                                                           encode_binary_size=encode_binary_size)
+                [code1, codeCleanup1] = generateExtensionObjectSubtypeCode(node.value[0], parent=parentNode, nodeset=nodeset,
+                                                                           encode_binary_size=encode_binary_size, global_var_code=codeGlobal)
                 code = code + code1
                 codeCleanup = codeCleanup + codeCleanup1
             instanceName = generateNodeValueInstanceName(node.value[0], parentNode, 0, 0)
             if isinstance(node.value[0], ExtensionObject):
-                code.append("UA_" + node.value[0].__class__.__name__ + " *" + valueName + " = " +
-                            generateNodeValueCode(node.value[0], instanceName, max_string_length=max_string_length) + ";")
+                code.append(generateNodeValueCode("UA_" + node.value[0].__class__.__name__ + " *" + valueName + " = " ,
+                            node.value[0], instanceName, valueName, codeGlobal))
                 code.append(
                     "UA_Variant_setScalar(&attr.value, " + valueName + ", " +
                     getTypesArrayForValue(nodeset, node.value[0]) + ");")
@@ -379,13 +386,17 @@ def generateValueCode(node, parentNode, nodeset, bootstrapping=True, max_string_
             else:
                 code.append("UA_" + node.value[0].__class__.__name__ + " *" + valueName + " =  UA_" + node.value[
                     0].__class__.__name__ + "_new();")
-                code.append("*" + valueName + " = " + generateNodeValueCode(node.value[0], instanceName, asIndirect=True, max_string_length=max_string_length) + ";")
+                code.append(generateNodeValueCode("*" + valueName + " = " , node.value[0], instanceName, valueName, codeGlobal, asIndirect=True))
                 code.append(
                         "UA_Variant_setScalar(&attr.value, " + valueName + ", " +
                         getTypesArrayForValue(nodeset, node.value[0]) + ");")
+                if node.value[0].__class__.__name__ == "ByteString":
+                    # The data is on the stack, not heap, so we can not delete the ByteString
+                    codeCleanup.append("{}->data = NULL;".format(valueName))
+                    codeCleanup.append("{}->length = 0;".format(valueName))
                 codeCleanup.append("UA_{0}_delete({1});".format(
                     node.value[0].__class__.__name__, valueName))
-    return [code, codeCleanup]
+    return [code, codeCleanup, codeGlobal]
 
 def generateMethodNodeCode(node):
     code = []
@@ -432,7 +443,7 @@ def generateSubtypeOfDefinitionCode(node):
             return generateNodeIdCode(ref.target)
     return "UA_NODEID_NULL"
 
-def generateNodeCode_begin(node, nodeset, max_string_length, generate_ns0, parentref, encode_binary_size):
+def generateNodeCode_begin(node, nodeset, generate_ns0, parentref, encode_binary_size, code_global):
     code = []
     codeCleanup = []
     code.append("UA_StatusCode retVal = UA_STATUSCODE_GOOD;")
@@ -443,13 +454,15 @@ def generateNodeCode_begin(node, nodeset, max_string_length, generate_ns0, paren
     elif isinstance(node, ObjectNode):
         code.extend(generateObjectNodeCode(node))
     elif isinstance(node, VariableNode) and not isinstance(node, VariableTypeNode):
-        [code1, codeCleanup1] = generateVariableNodeCode(node, nodeset, max_string_length, encode_binary_size)
+        [code1, codeCleanup1, codeGlobal1] = generateVariableNodeCode(node, nodeset, encode_binary_size)
         code.extend(code1)
         codeCleanup.extend(codeCleanup1)
+        code_global.extend(codeGlobal1)
     elif isinstance(node, VariableTypeNode):
-        [code1, codeCleanup1] = generateVariableTypeNodeCode(node, nodeset, max_string_length, encode_binary_size)
+        [code1, codeCleanup1, codeGlobal1] = generateVariableTypeNodeCode(node, nodeset, encode_binary_size)
         code.extend(code1)
         codeCleanup.extend(codeCleanup1)
+        code_global.extend(codeGlobal1)
     elif isinstance(node, MethodNode):
         code.extend(generateMethodNodeCode(node))
     elif isinstance(node, ObjectTypeNode):
@@ -458,11 +471,9 @@ def generateNodeCode_begin(node, nodeset, max_string_length, generate_ns0, paren
         code.extend(generateDataTypeNodeCode(node))
     elif isinstance(node, ViewNode):
         code.extend(generateViewNodeCode(node))
-    code.append("attr.displayName = " + generateLocalizedTextCode(node.displayName, alloc=False,
-                                                                  max_string_length=max_string_length) + ";")
+    code.append("attr.displayName = " + generateLocalizedTextCode(node.displayName, alloc=False) + ";")
     code.append("#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS")
-    code.append("attr.description = " + generateLocalizedTextCode(node.description, alloc=False,
-                                                                  max_string_length=max_string_length) + ";")
+    code.append("attr.description = " + generateLocalizedTextCode(node.description, alloc=False) + ";")
     code.append("#endif")
     code.append("attr.writeMask = %d;" % node.writeMask)
     code.append("attr.userWriteMask = %d;" % node.userWriteMask)
@@ -473,7 +484,7 @@ def generateNodeCode_begin(node, nodeset, max_string_length, generate_ns0, paren
     code.append(generateNodeIdCode(node.id) + ",")
     code.append(generateNodeIdCode(parentref.target) + ",")
     code.append(generateNodeIdCode(parentref.referenceType) + ",")
-    code.append(generateQualifiedNameCode(node.browseName, max_string_length=max_string_length) + ",")
+    code.append(generateQualifiedNameCode(node.browseName) + ",")
     if isinstance(node, VariableNode) or isinstance(node, ObjectNode):
         typeDefRef = node.popTypeDef()
         code.append(generateNodeIdCode(typeDefRef.target) + ",")
@@ -482,7 +493,7 @@ def generateNodeCode_begin(node, nodeset, max_string_length, generate_ns0, paren
     code.append("(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_{}ATTRIBUTES],NULL, NULL);".
                 format(node.__class__.__name__.upper().replace("NODE" ,"")))
     code.extend(codeCleanup)
-    
+
     return "\n".join(code)
 
 def generateNodeCode_finish(node):

+ 1 - 7
tools/nodeset_compiler/nodeset_compiler.py

@@ -82,12 +82,6 @@ parser.add_argument('-t', '--types-array',
                     default=[],
                     help='Types array for the given namespace. Can be used mutliple times to define (in the same order as the .xml files, first for --existing, then --xml) the type arrays')
 
-parser.add_argument('--max-string-length',
-                    type=int,
-                    dest="max_string_length",
-                    default=0,
-                    help='Maximum allowed length of a string literal. If longer, it will be set to an empty string')
-
 parser.add_argument('--encode-binary-size',
                     type=int,
                     dest="encode_binary_size",
@@ -188,5 +182,5 @@ ns.allocateVariables()
 
 # Create the C code with the open62541 backend of the compiler
 logger.info("Generating Code")
-generateOpen62541Code(ns, args.outputFile, args.generate_ns0, args.internal_headers, args.typesArray, args.max_string_length, args.encode_binary_size)
+generateOpen62541Code(ns, args.outputFile, args.generate_ns0, args.internal_headers, args.typesArray, args.encode_binary_size)
 logger.info("NodeSet generation code successfully printed")