|
@@ -20,7 +20,6 @@
|
|
|
|
|
|
from __future__ import print_function
|
|
|
import string
|
|
|
-from collections import deque
|
|
|
from os.path import basename
|
|
|
import logging
|
|
|
import codecs
|
|
@@ -36,123 +35,95 @@ from nodes import *
|
|
|
from nodeset import *
|
|
|
from backend_open62541_nodes import generateNodeCode_begin, generateNodeCode_finish, generateReferenceCode
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-def selectPrintRefs(nodeset, L, node):
|
|
|
- printRefs = []
|
|
|
- for ref in node.references:
|
|
|
- targetnode = nodeset.nodes[ref.target]
|
|
|
- if node.hidden and targetnode.hidden:
|
|
|
- continue
|
|
|
- if not targetnode.hidden and not targetnode in L:
|
|
|
- continue
|
|
|
- printRefs.append(ref)
|
|
|
- for ref in node.inverseReferences:
|
|
|
- targetnode = nodeset.nodes[ref.target]
|
|
|
- if node.hidden and targetnode.hidden:
|
|
|
- continue
|
|
|
- if not targetnode.hidden and not targetnode in L:
|
|
|
- continue
|
|
|
- printRefs.append(ref)
|
|
|
- return printRefs
|
|
|
-
|
|
|
-def addTypeRef(nodeset, type_refs, dataTypeId, referencedById):
|
|
|
- if not dataTypeId in type_refs:
|
|
|
- type_refs[dataTypeId] = [referencedById]
|
|
|
- else:
|
|
|
- type_refs[dataTypeId].append(referencedById)
|
|
|
+
|
|
|
+def sortNodes(nodeset):
|
|
|
|
|
|
+
|
|
|
+ for u in nodeset.nodes.values():
|
|
|
+ for ref in u.references:
|
|
|
+ back = Reference(ref.target, ref.referenceType, ref.source, not ref.isForward)
|
|
|
+ nodeset.nodes[ref.target].references.add(back)
|
|
|
|
|
|
-def reorderNodesMinDependencies(nodeset):
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
+ hasTypeDef = NodeId("ns=0;i=40")
|
|
|
+ for u in nodeset.nodes.values():
|
|
|
+ for ref in u.references:
|
|
|
+ if ref.referenceType == hasTypeDef:
|
|
|
+ ref.isForward = not ref.isForward
|
|
|
|
|
|
- relevant_types = nodeset.getRelevantOrderingReferences()
|
|
|
+
|
|
|
+ relevant_refs = nodeset.getRelevantOrderingReferences()
|
|
|
|
|
|
-
|
|
|
- in_degree = {u.id: 0 for u in nodeset.nodes.values()}
|
|
|
- dataType_refs = {}
|
|
|
- hiddenCount = 0
|
|
|
- for u in nodeset.nodes.values():
|
|
|
- if u.hidden:
|
|
|
- hiddenCount += 1
|
|
|
- continue
|
|
|
- hasTypeDef = None
|
|
|
+
|
|
|
+ L = [node for node in nodeset.nodes.values() if node.hidden]
|
|
|
+ R = {node.id: node for node in nodeset.nodes.values() if not node.hidden}
|
|
|
+ in_degree = {id: 0 for id in R.keys()}
|
|
|
+ for u in R.values():
|
|
|
for ref in u.references:
|
|
|
- if ref.referenceType.i == 40:
|
|
|
- hasTypeDef = ref.target
|
|
|
- elif (ref.referenceType in relevant_types and ref.isForward) and not nodeset.nodes[ref.target].hidden:
|
|
|
- in_degree[ref.target] += 1
|
|
|
- if hasTypeDef is not None and not nodeset.nodes[hasTypeDef].hidden:
|
|
|
-
|
|
|
+ if not ref.referenceType in relevant_refs:
|
|
|
+ continue
|
|
|
+ if nodeset.nodes[ref.target].hidden:
|
|
|
+ continue
|
|
|
+ if ref.isForward:
|
|
|
+ continue
|
|
|
in_degree[u.id] += 1
|
|
|
|
|
|
- if isinstance(u, VariableNode) and u.dataType is not None:
|
|
|
- dataTypeNode = nodeset.getDataTypeNode(u.dataType)
|
|
|
- if dataTypeNode is not None and not dataTypeNode.hidden:
|
|
|
-
|
|
|
- in_degree[u.id] += 1
|
|
|
-
|
|
|
- addTypeRef(nodeset, dataType_refs,dataTypeNode.id, u.id)
|
|
|
-
|
|
|
-
|
|
|
- Q = deque()
|
|
|
- for id in in_degree:
|
|
|
- if in_degree[id] == 0:
|
|
|
-
|
|
|
- n = nodeset.nodes[id]
|
|
|
- if isinstance(n, ReferenceTypeNode):
|
|
|
- Q.append(nodeset.nodes[id])
|
|
|
- else:
|
|
|
- Q.appendleft(nodeset.nodes[id])
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
|
|
|
- L = []
|
|
|
+ Q = {node for node in R.values() if in_degree[node.id] == 0 and
|
|
|
+ (isinstance(node, ReferenceTypeNode) or isinstance(node, DataTypeNode))}
|
|
|
while Q:
|
|
|
- u = Q.pop()
|
|
|
-
|
|
|
- u.printRefs = selectPrintRefs(nodeset, L, u)
|
|
|
- if u.hidden:
|
|
|
- continue
|
|
|
+ u = Q.pop()
|
|
|
+ L.append(u)
|
|
|
+ del R[u.id]
|
|
|
+
|
|
|
+ for ref in u.references:
|
|
|
+ if not ref.referenceType in relevant_refs:
|
|
|
+ continue
|
|
|
+ if nodeset.nodes[ref.target].hidden:
|
|
|
+ continue
|
|
|
+ if not ref.isForward:
|
|
|
+ continue
|
|
|
+ in_degree[ref.target] -= 1
|
|
|
+ if in_degree[ref.target] == 0:
|
|
|
+ Q.add(R[ref.target])
|
|
|
|
|
|
- L.append(u)
|
|
|
-
|
|
|
- if isinstance(u, DataTypeNode):
|
|
|
-
|
|
|
- if u.id in dataType_refs:
|
|
|
- for n in dataType_refs[u.id]:
|
|
|
- if not nodeset.nodes[n].hidden:
|
|
|
- in_degree[n] -= 1
|
|
|
- if in_degree[n] == 0:
|
|
|
- Q.append(nodeset.nodes[n])
|
|
|
- del dataType_refs[u.id]
|
|
|
-
|
|
|
- for ref in u.inverseReferences:
|
|
|
- if ref.referenceType.i == 40:
|
|
|
- if not nodeset.nodes[ref.target].hidden:
|
|
|
- in_degree[ref.target] -= 1
|
|
|
- if in_degree[ref.target] == 0:
|
|
|
- Q.append(nodeset.nodes[ref.target])
|
|
|
+
|
|
|
+ Q = {node for node in R.values() if in_degree[node.id] == 0}
|
|
|
+ while Q:
|
|
|
+ u = Q.pop()
|
|
|
+ L.append(u)
|
|
|
+ del R[u.id]
|
|
|
+
|
|
|
+ for ref in u.references:
|
|
|
+ if not ref.referenceType in relevant_refs:
|
|
|
+ continue
|
|
|
+ if nodeset.nodes[ref.target].hidden:
|
|
|
+ continue
|
|
|
+ if not ref.isForward:
|
|
|
+ continue
|
|
|
+ in_degree[ref.target] -= 1
|
|
|
+ if in_degree[ref.target] == 0:
|
|
|
+ Q.add(R[ref.target])
|
|
|
|
|
|
+
|
|
|
+ for u in nodeset.nodes.values():
|
|
|
for ref in u.references:
|
|
|
- if (ref.referenceType in relevant_types and ref.isForward):
|
|
|
- if not nodeset.nodes[ref.target].hidden:
|
|
|
- in_degree[ref.target] -= 1
|
|
|
- if in_degree[ref.target] == 0:
|
|
|
- Q.append(nodeset.nodes[ref.target])
|
|
|
+ if ref.referenceType == hasTypeDef:
|
|
|
+ ref.isForward = not ref.isForward
|
|
|
|
|
|
- if len(L) + hiddenCount != len(nodeset.nodes.values()):
|
|
|
+ if len(L) != len(nodeset.nodes.values()):
|
|
|
+ print(len(L))
|
|
|
stillOpen = ""
|
|
|
for id in in_degree:
|
|
|
if in_degree[id] == 0:
|
|
|
continue
|
|
|
node = nodeset.nodes[id]
|
|
|
- stillOpen += node.browseName.name + "/" + str(node.id) + " = " + str(in_degree[id]) + "\r\n"
|
|
|
+ stillOpen += node.browseName.name + "/" + str(node.id) + " = " + str(in_degree[id]) + \
|
|
|
+ " " + str(node.references) + "\r\n"
|
|
|
raise Exception("Node graph is circular on the specified references. Still open nodes:\r\n" + stillOpen)
|
|
|
return L
|
|
|
|
|
@@ -232,7 +203,7 @@ UA_findDataTypeByBinary(const UA_NodeId *typeId);
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
|
-
|
|
|
+
|
|
|
extern UA_StatusCode %s(UA_Server *server);
|
|
|
|
|
|
|
|
@@ -248,47 +219,57 @@ extern UA_StatusCode %s(UA_Server *server);
|
|
|
|
|
|
""" % (outfilebase))
|
|
|
|
|
|
- parentrefs = getSubTypesOf(nodeset, nodeset.getNodeByBrowseName("HierarchicalReferences"))
|
|
|
- parentrefs = list(map(lambda x: x.id, parentrefs))
|
|
|
-
|
|
|
|
|
|
logger.info("Reordering nodes for minimal dependencies during printing")
|
|
|
- sorted_nodes = reorderNodesMinDependencies(nodeset)
|
|
|
+ sorted_nodes = sortNodes(nodeset)
|
|
|
logger.info("Writing code for nodes and references")
|
|
|
-
|
|
|
functionNumber = 0
|
|
|
|
|
|
+ parentreftypes = getSubTypesOf(nodeset, nodeset.getNodeByBrowseName("HierarchicalReferences"))
|
|
|
+ parentreftypes = list(map(lambda x: x.id, parentreftypes))
|
|
|
+
|
|
|
+ printed_ids = set()
|
|
|
for node in sorted_nodes:
|
|
|
-
|
|
|
+ printed_ids.add(node.id)
|
|
|
+
|
|
|
+ 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, parentrefs)
|
|
|
+ code = generateNodeCode_begin(node, nodeset, max_string_length, generate_ns0, parentref)
|
|
|
if code is None:
|
|
|
writec("/* Ignored. No parent */")
|
|
|
nodeset.hide_node(node.id)
|
|
|
continue
|
|
|
else:
|
|
|
- writec("\nstatic UA_StatusCode function_" + outfilebase + "_" + str(functionNumber) + "_begin(UA_Server *server, UA_UInt16* ns) {\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")
|
|
|
writec(code)
|
|
|
|
|
|
|
|
|
- for ref in node.printRefs:
|
|
|
+ for ref in node.references:
|
|
|
+ if ref.target not in printed_ids:
|
|
|
+ continue
|
|
|
+ if node.hidden and nodeset.nodes[ref.target].hidden:
|
|
|
+ continue
|
|
|
writec(generateReferenceCode(ref))
|
|
|
-
|
|
|
+
|
|
|
+ if node.hidden:
|
|
|
+ continue
|
|
|
+
|
|
|
writec("return retVal;")
|
|
|
+
|
|
|
if isinstance(node, MethodNode):
|
|
|
writec("#else")
|
|
|
writec("return UA_STATUSCODE_GOOD;")
|
|
|
writec("#endif /* UA_ENABLE_METHODCALLS */")
|
|
|
writec("}");
|
|
|
|
|
|
- writec("\nstatic UA_StatusCode function_" + outfilebase + "_" + str(functionNumber) + "_finish(UA_Server *server, UA_UInt16* ns) {\n")
|
|
|
+ writec("\nstatic UA_StatusCode function_" + outfilebase + "_" + str(functionNumber) + "_finish(UA_Server *server, UA_UInt16* ns) {")
|
|
|
+
|
|
|
if isinstance(node, MethodNode):
|
|
|
writec("#ifdef UA_ENABLE_METHODCALLS")
|
|
|
- code = generateNodeCode_finish(node)
|
|
|
- writec("return " + code)
|
|
|
+ writec("return " + generateNodeCode_finish(node))
|
|
|
if isinstance(node, MethodNode):
|
|
|
writec("#else")
|
|
|
writec("return UA_STATUSCODE_GOOD;")
|
|
@@ -300,6 +281,7 @@ extern UA_StatusCode %s(UA_Server *server);
|
|
|
writec("""
|
|
|
UA_StatusCode %s(UA_Server *server) {
|
|
|
UA_StatusCode retVal = UA_STATUSCODE_GOOD;""" % (outfilebase))
|
|
|
+
|
|
|
|
|
|
writec("/* Use namespace ids generated by the server */")
|
|
|
writec("UA_UInt16 ns[" + str(len(nodeset.namespaces)) + "];")
|
|
@@ -310,7 +292,6 @@ UA_StatusCode retVal = UA_STATUSCODE_GOOD;""" % (outfilebase))
|
|
|
for i in range(0, functionNumber):
|
|
|
writec("retVal |= function_" + outfilebase + "_" + str(i) + "_begin(server, ns);")
|
|
|
|
|
|
-
|
|
|
for i in reversed(range(0, functionNumber)):
|
|
|
writec("retVal |= function_" + outfilebase + "_" + str(i) + "_finish(server, ns);")
|
|
|
|