Procházet zdrojové kódy

Merge remote-tracking branch 'origin/master' into connection_secureChannel

Conflicts:
	examples/src/opcuaServer.c
	src/Makefile.am
	src/ua_transport.c
	src/util/ua_list.c
FlorianPalm před 9 roky
rodič
revize
c7c8cee70b

+ 8 - 2
Makefile.am

@@ -7,7 +7,6 @@ else
 AM_CFLAGS += -fPIC
 endif
 
-
 if DEBUG
 AM_CFLAGS += -g3 -O0
 else
@@ -23,6 +22,13 @@ if MULTITHREADING
 AM_LDADD += -lpthread
 endif
 
+UA_ENCODING_AMOUNT = 1
+if UA_ENCODING_XML
+UA_ENCODING_AMOUNT := $$(echo $(UA_ENCODING_AMOUNT)+1 | bc)
+endif
+
+AM_CFLAGS += -D UA_ENCODING_AMOUNT=$(UA_ENCODING_AMOUNT)
+
 export GLOBAL_AM_CFLAGS = $(AM_CFLAGS)
 export GLOBAL_AM_LDADD = $(AM_LDADD)
 
@@ -46,4 +52,4 @@ endif
 
 if LUA_WRAPPER
 SUBDIRS += wrappers wrappers/lua
-endif
+endif

+ 24 - 18
configure.ac

@@ -6,8 +6,7 @@ AC_INIT(Open62541, 1.0)
 AC_CANONICAL_SYSTEM
 AM_INIT_AUTOMAKE([subdir-objects])
 AC_PROG_MAKE_SET
-#default CFLAGS is -g -02
-#reset it just to -g and make optimization dependend on --enable-debug
+# Default CFLAGS is -g -02. Set depending on debug flag.
 if test -z $CFLAGS; then
    CFLAGS=''
 fi
@@ -16,9 +15,9 @@ AC_PROG_CC
 AC_PROG_LN_S
 AM_PROG_CC_C_O
 AC_CHECK_LIB([m],[exp],,AC_MSG_ERROR([Libm missing]))
-AC_CHECK_LIB([expat],[XML_Parse],,AC_MSG_ERROR([Libexpat missing]))
-PKG_CHECK_MODULES([CHECK], [check >= 0.9.12],[have_check="yes"],AC_MSG_WARN([Check not found or check version lower than 0.9.12; cannot run unit tests!])
-[have_check="no"])
+PKG_CHECK_MODULES([CHECK], [check >= 0.9.12],[have_check="yes"],
+                  AC_MSG_WARN([Check not found or check version lower than 0.9.12; cannot run unit tests!])
+				  [have_check="no"])
 AM_CONDITIONAL([HAVE_CHECK], [test x"$have_check" = "xyes"])
 AM_CONDITIONAL([TARGET_WIN],[test "${host_os}" = "mingw32"])
 AM_CONDITIONAL([TARGET_LINUX],[test "${host_os}" = "linux-gnu" || test "${host_os}" = "linux"]) 
@@ -47,6 +46,26 @@ AM_CONDITIONAL(VERBOSE, test x"$verbose" = x"true")
 AM_COND_IF([VERBOSE],
     AC_DEFINE([VERBOSE])) #define VERBOSE is accessible from pre-processor
 
+#profile
+# 100: nano
+# 200: embedded
+# 900: all available features
+AC_ARG_ENABLE(profile,
+AS_HELP_STRING([--enable-profile], [select supported features, default: all]),
+	[case "${enableval}" in
+        	nano) profile=100;;
+            embedded) profile=200;;
+            all) profile=900;;
+            *) AC_MSG_ERROR([bad value ${enableval} for --enable-profile]);; 
+	esac],[profile=900])
+AC_DEFINE([PROFILE], [x"$profile"])
+
+#xml encoding
+AM_CONDITIONAL(UA_ENCODING_XML, test x"$profile" -ge 200)
+AM_COND_IF([UA_ENCODING_XML],
+    AC_DEFINE([UA_ENCODING_XML], [1])
+    AC_CHECK_LIB([expat],[XML_Parse],,AC_MSG_ERROR([Libexpat missing])))
+
 #multithreading
 AC_ARG_ENABLE(multithreading,
 AS_HELP_STRING([--enable-multithreading],
@@ -72,19 +91,6 @@ AS_HELP_STRING([--enable-coverage],
 AM_CONDITIONAL(COVERAGE, test x"$coverage" = x"true")
 AM_COND_IF([COVERAGE],
     AC_DEFINE([COVERAGE])) #define MULTITHREADING is accessible from pre-processor
-    
-#raspberry pi
-AC_ARG_ENABLE(raspi,
-AS_HELP_STRING([--enable-raspi],
-               [enable raspi, default: no]),
-	[case "${enableval}" in
-		yes) raspi=true ;;
-		no)  raspi=false ;;
-		*)   AC_MSG_ERROR([bad value ${enableval} for --enable-raspi]) ;; 
-	esac],[raspi=false])
-AM_CONDITIONAL(RASPI, test x"$raspi" = x"true")
-AM_COND_IF([RASPI],
-    AC_DEFINE([RASPI]))
 
 #doxygen start
 AC_ARG_ENABLE(doxygen,

+ 4 - 10
examples/src/Makefile.am

@@ -1,36 +1,30 @@
-bin_PROGRAMS = $(top_builddir)/bin/xml2ns0 
+bin_PROGRAMS =
 
+if UA_ENCODING_XML
+bin_PROGRAMS += $(top_builddir)/bin/xml2ns0 
 __top_builddir__bin_xml2ns0_SOURCES = xml2ns0.c
 __top_builddir__bin_xml2ns0_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include $(GLOBAL_AM_CFLAGS)
 __top_builddir__bin_xml2ns0_LDADD = $(top_builddir)/lib/libopen62541.a $(GLOBAL_AM_LDADD)
 __top_builddir__bin_xml2ns0_LDFLAGS = -lexpat
 
 bin_PROGRAMS += $(top_builddir)/bin/generateSam 
-
 __top_builddir__bin_generateSam_SOURCES = generateSam.c
 __top_builddir__bin_generateSam_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include $(GLOBAL_AM_CFLAGS)
 __top_builddir__bin_generateSam_LDADD = $(top_builddir)/lib/libopen62541.a $(GLOBAL_AM_LDADD)
 __top_builddir__bin_generateSam_LDFLAGS = -lexpat
-
-
+endif
 
 if MULTITHREADING
 bin_PROGRAMS += $(top_builddir)/bin/exampleServerMT 
-
 __top_builddir__bin_exampleServerMT_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include $(GLOBAL_AM_CFLAGS)
 __top_builddir__bin_exampleServerMT_SOURCES = opcuaServerMT.c networklayer.c
 __top_builddir__bin_exampleServerMT_LDADD= $(top_builddir)/lib/libopen62541.a $(GLOBAL_AM_LDADD)
-
 else
 bin_PROGRAMS += $(top_builddir)/bin/exampleServer $(top_builddir)/bin/exampleServerACPLT $(top_builddir)/bin/exampleServerMini
 
 __top_builddir__bin_exampleServer_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include $(GLOBAL_AM_CFLAGS)
 __top_builddir__bin_exampleServer_SOURCES = opcuaServer.c networklayer.c
 __top_builddir__bin_exampleServer_LDADD= $(top_builddir)/lib/libopen62541.a $(GLOBAL_AM_LDADD)
-if RASPI
-__top_builddir__bin_exampleServer_LDFLAGS = -lwiringPi
-__top_builddir__bin_exampleServer_SOURCES += raspberrypi_io.c
-endif
 
 __top_builddir__bin_exampleServerACPLT_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include $(GLOBAL_AM_CFLAGS)
 __top_builddir__bin_exampleServerACPLT_SOURCES = opcuaServerACPLT.c networklayer.c

+ 6 - 80
examples/src/opcuaServer.c

@@ -1,17 +1,3 @@
-/*
- ============================================================================
- Name        : opcuaServer.c
- Author      :
- Version     :
- Copyright   : Your copyright notice
- Description : lala
- ============================================================================
- */
-#ifdef RASPI
-	#define _POSIX_C_SOURCE 199309L //to use nanosleep
-	#include <pthread.h>
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -24,12 +10,15 @@
 #include <unistd.h>
 #include <time.h>
 #include <fcntl.h>
+<<<<<<< HEAD
 #include "ua_stack_channel_manager.h"
 #include "ua_stack_session_manager.h"
 
 #ifdef RASPI
 	#include "raspberrypi_io.h"
 #endif
+=======
+>>>>>>> origin/master
 
 
 UA_Int32 serverCallback(void * arg) {
@@ -45,81 +34,16 @@ UA_Int32 serverCallback(void * arg) {
 		((UA_ServerStatusDataType*)(((UA_VariableNode*)node)->value.data))->currentTime = UA_DateTime_now();
 	}
 
-	const UA_Node *foundNode1 = UA_NULL;
-
-	Namespace_Entry_Lock *lock;
-	//node which should be filled with data (float value)
-	UA_NodeId tmpNodeId1;
-
-
-	tmpNodeId1.encodingByte = UA_NODEIDTYPE_TWOBYTE;
-	tmpNodeId1.identifier.numeric = 108;
-	tmpNodeId1.namespace =  0;
-
-
-	if(Namespace_get(ns0,&tmpNodeId1, &foundNode1,&lock) != UA_SUCCESS){
-		return UA_ERROR;
-	}
-
-
-#ifdef RASPI
-#else
-	*((float*)((UA_VariableNode *)foundNode1)->value.data) = *((float*)((UA_VariableNode *)foundNode1)->value.data) + 0.2f;
-#endif
-
-
-
 	return UA_SUCCESS;
 }
 
-#ifdef RASPI
-
-static float sharedTemperature = 0;
-static UA_Boolean sharedLED1 = 0;
-static UA_Boolean sharedLED2 = 0;
-
-static void* ioloop(void* ptr){
-    {
-	if(initIO())
-	{
-		printf("ERROR while initializing the IO \n");
-	}
-	else
-	{
-	        struct timespec t = {0, 50*1000*1000};
-		int j = 0;
-		for(;j<25;j++){
-		writePin(j%2,0);
-		writePin((j+1)%2,2);
-		nanosleep(&t, NULL);
-		}
-		writePin(0,0);
-		writePin(0,2);
-
-		printf("IO successfully initalized \n");
-	}
-
-	printf("done - io init \n");
-
-  
-
-        struct timespec t = {0, 50*1000*1000};
-    	while(1){
-		readTemp(&sharedTemperature);
-		writePin(sharedLED1,0);
-		writePin(sharedLED2,2);
-		nanosleep(&t, NULL);
-    	}
-    }
-	return UA_NULL;
-}
-#endif
 
 int main(int argc, char** argv) {
 	appMockup_init();
 	NL_data* nl = NL_init(&NL_Description_TcpBinary,16664);
 
 	struct timeval tv = {1, 0}; // 1 second
+<<<<<<< HEAD
 #ifdef RASPI
   	Namespace* ns0 = (Namespace*)UA_indexedList_find(appMockup.namespaces, 0)->payload;
 		const UA_Node *foundNode1 = UA_NULL;
@@ -170,6 +94,8 @@ int main(int argc, char** argv) {
 	SL_ChannelManager_init(2,3600000, 873, 23, &nl->endpointUrl);
 	UA_SessionManager_init(2,300000,5);
 
+=======
+>>>>>>> origin/master
   	NL_msgLoop(nl, &tv, serverCallback, argv[0]);
 
 }

+ 0 - 65
examples/src/raspberrypi_io.c

@@ -1,65 +0,0 @@
-/*
- * raspberrypi_io.c
- *
- *  Created on: 23.06.2014
- *      Author: root
- */
-
-#include "raspberrypi_io.h"
-
-
-
-#ifdef RASPI
-static _Bool initialized = 0;
-int initIO()
-{
-	if (wiringPiSetup() == -1){
-		initialized = 0;
-		return 1;
-	}
-	initialized = 1;
-	return 0;
-}
-int readTemp(float *temp){
-	FILE *ptr_file;
-	char buf[1000];
-	char delimiter[] = "=";
-	char *ptr_temp;
-	long temperaturInmC;
-
-	ptr_file =fopen("/sys/bus/w1/devices/10-000802c607f3/w1_slave","r");
-	if (!ptr_file){
-		puts("ERROR: no sensor");
-		return 1;
-	}
-
-	fgets(buf, 1000, ptr_file);
-
-	fgets(buf, 1000, ptr_file);
-
-	ptr_temp = strtok(buf, (char*) delimiter);
-
-	ptr_temp = strtok((void*)0, (char*) delimiter);
-
-	temperaturInmC = atol(ptr_temp);
-
-	fclose(ptr_file);
-
-	*temp = (float)temperaturInmC/1000;
-	return 0;
-}
-
-int writePin(_Bool state, int pin){
-	if(initialized)
-	{
-		pinMode(0, OUTPUT);
-		if(state==(1==1)){
-			digitalWrite(pin, 1);
-		}else{
-			digitalWrite(pin, 0);
-		}
-		return 0;
-	}
-	return 1; //ERROR
-}
-#endif

+ 0 - 22
examples/src/raspberrypi_io.h

@@ -1,22 +0,0 @@
-/*
- * raspberrypi_io.h
- *
- *  Created on: 23.06.2014
- *      Author: root
- */
-
-#ifndef RASPBERRYPI_IO_H_
-#define RASPBERRYPI_IO_H_
-
-#include <wiringPi.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "string.h"
-int readTemp(float *temp);
-int writePin(_Bool state, int pin);
-int initIO();
-
-#endif /* RASPBERRYPI_IO_H_ */

+ 15 - 4
src/Makefile.am

@@ -7,7 +7,6 @@ libopen62541_la_LDFLAGS = -avoid-version -no-undefined
 libopen62541_la_SOURCES = ua_types.c \
 						  ua_types_encoding_binary.c \
 						  ua_types_generated.c \
-						  ua_types_encoding_xml.c \
 						  ua_namespace_0.c \
 						  util/ua_util.c \
 						  util/ua_list.c \
@@ -17,7 +16,6 @@ libopen62541_la_SOURCES = ua_types.c \
 						  ua_transport_binary.c \
 						  ua_transport_binary_secure.c \
 						  ua_namespace.c \
-						  ua_namespace_xml.c \
 						  ua_services_attribute.c \
 						  ua_services_session.c \
 						  ua_services_discovery.c \
@@ -26,6 +24,7 @@ libopen62541_la_SOURCES = ua_types.c \
 						  ua_services_view.c \
 						  ua_services_subscription.c\
 						  ua_services_monitoreditems.c\
+<<<<<<< HEAD
 						  ua_application.c \
 			              ua_stack_session.c\
 			              ua_stack_session_manager.c\
@@ -34,14 +33,26 @@ libopen62541_la_SOURCES = ua_types.c \
 						  ua_transport_connection_manager.c \
 						  ua_transport_connection.c\
 						  ua_xml.c
+=======
+						  ua_application.c
+
+WITH_XML =
+if UA_ENCODING_XML
+libopen62541_la_SOURCES += ua_types_encoding_xml.c \
+						   ua_namespace_xml.c \
+						   ua_xml.c
+WITH_XML = --with-xml
+endif
+
+>>>>>>> origin/master
 ua_types.c: ua_namespace_0.h
 ua_namespace_0.h: ua_types_generated.h
 
 ua_types_generated.c ua_types_generated.h: $(SCHEMA_DIR)/Opc.Ua.Types.bsd $(TOOL_DIR)/generate_builtin.py
-	python $(TOOL_DIR)/generate_builtin.py $(SCHEMA_DIR)/Opc.Ua.Types.bsd ua_types_generated
+	python $(TOOL_DIR)/generate_builtin.py $(SCHEMA_DIR)/Opc.Ua.Types.bsd ua_types_generated $(WITH_XML)
 
 ua_namespace_0.c ua_namespace_0.h: $(SCHEMA_DIR)/NodeIds.csv $(TOOL_DIR)/generate_namespace.py
-	python $(TOOL_DIR)/generate_namespace.py $(SCHEMA_DIR)/NodeIds.csv ua_namespace_0
+	python $(TOOL_DIR)/generate_namespace.py $(SCHEMA_DIR)/NodeIds.csv ua_namespace_0 $(WITH_XML)
 
 .PHONY: convenience-link clean-convenience-link
 

+ 6 - 1
src/ua_transport.c

@@ -440,8 +440,9 @@ UA_Int32 UA_SecureConversationMessageFooter_calcSizeBinary(UA_SecureConversation
 
 UA_Int32 UA_SecureConversationMessageFooter_encodeBinary(UA_SecureConversationMessageFooter const * src, UA_ByteString* dst, UA_UInt32 *offset) {
     	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_Array_encodeBinary(&src->padding,src->paddingSize,&UA_.types[UA_BYTE],dst,offset);
+	retval |= UA_Array_encodeBinary(src->padding,src->paddingSize,&UA_.types[UA_BYTE],dst,offset);
 	retval |= UA_Byte_encodeBinary(&src->signature,dst,offset);
+
 	return retval;
 }
 
@@ -481,8 +482,12 @@ UA_Int32 UA_SecureConversationMessageFooter_copy(const UA_SecureConversationMess
     	UA_Int32 retval = UA_SUCCESS;
 	memcpy(dst, src, sizeof(UA_SecureConversationMessageFooter));
 
+<<<<<<< HEAD
 	dst->padding = src->padding;
 	retval |= UA_Array_copy(&src->padding, src->paddingSize,&UA_.types[UA_BYTE],(void**)&dst->padding);
+=======
+	retval |= UA_Array_copy(src->padding, src->paddingSize,&UA_.types[UA_BYTE],(void**)&dst->padding);
+>>>>>>> origin/master
 	return retval;
 }
 

+ 4 - 4
src/ua_types.h

@@ -118,7 +118,7 @@ typedef struct UA_String UA_XmlElement;
 
 /** @brief An identifier for a node in the address space of an OPC UA Server. */
 typedef struct UA_NodeId {
-	UA_Byte encodingByte;       //enum BID_NodeIdEncodingValuesType
+	UA_Byte encodingByte;
 	UA_UInt16 namespace;
 	union {
 		UA_UInt32     numeric;
@@ -400,8 +400,8 @@ typedef struct UA_Encoding {
 	UA_decode   decode;
 } UA_Encoding;
 
-#define UA_ENCODING_BINARY 0
-#define UA_ENCODING_XML 1
+#define UA_ENCODING_BINARY 0 // Binary encoding is always available
+// #define UA_ENCODING_XML 1 // This is set by the build script.
 
 struct UA_VTable_Entry {
 	UA_NodeId  typeId;
@@ -418,7 +418,7 @@ struct UA_VTable_Entry {
 	UA_Boolean dynMembers;    // does the type contain members that are dynamically
 	                          // allocated (strings, ..)? Otherwise, the size on
 	                          // the wire == size in memory.
-	UA_Encoding encodings[2]; // binary, xml, ...
+	UA_Encoding encodings[UA_ENCODING_AMOUNT]; // binary, xml, ... UA_ENCODING_AMOUNT is set by the build script
 };
 
 typedef UA_Int32 (*UA_nodeIdToVTableIndex)(const UA_NodeId *id);

+ 9 - 0
src/util/ua_list.c

@@ -90,6 +90,9 @@ UA_Int32 UA_list_removeFirst(UA_list_List* list, UA_list_PayloadVisitor visitor)
 		}
 		UA_free(list->first);
 		list->first = temp;
+		if(temp){
+			temp->prev = UA_NULL;
+		}
 		list->size--;
 		if(list->size == 1){
 			list->last = temp;
@@ -116,7 +119,13 @@ UA_Int32 UA_list_removeLast(UA_list_List* list, UA_list_PayloadVisitor visitor){
 		UA_free(list->last);
 		temp->next = UA_NULL;
 		list->last = temp;
+<<<<<<< HEAD
 		list->last->next = UA_NULL;
+=======
+		if(temp){
+			temp->next = UA_NULL;
+		}
+>>>>>>> origin/master
 		list->size--;
 		if(list->size == 1){
 			list->first = temp;

+ 87 - 3
tests/check_builtin.c

@@ -1549,6 +1549,38 @@ START_TEST(UA_ApplicationDescription_copyShallWorkOnExample) {
 	UA_ApplicationDescription_deleteMembers(&copiedValue);
 }
 END_TEST
+START_TEST(UA_QualifiedName_copyShallWorkOnInputExample) {
+	// given
+	UA_String srcName = (UA_String){8, (UA_Byte*)"tEsT123!"};
+	UA_QualifiedName src = {5, srcName};
+
+	UA_QualifiedName dst;
+	UA_Int32 ret;
+
+	// when
+	ret = UA_QualifiedName_copy(&src, &dst);
+	// then
+	ck_assert_int_eq(ret, UA_SUCCESS);
+	ck_assert_int_eq('E', dst.name.data[1]);
+	ck_assert_int_eq('!', dst.name.data[7]);
+	ck_assert_int_eq(8, dst.name.length);
+	ck_assert_int_eq(5, dst.namespaceIndex);
+}
+END_TEST
+START_TEST(UA_QualifiedName_copyNULLInput) {
+	// given
+	UA_QualifiedName *src;
+	src = UA_NULL;
+
+	UA_QualifiedName dst;
+	UA_Int32 ret;
+
+	// when
+	ret = UA_QualifiedName_copy(src, &dst);
+	// then
+	ck_assert_int_eq(ret, UA_ERROR);
+}
+END_TEST
 START_TEST(UA_Guid_copyShallWorkOnInputExample) {
 	//given
 	const UA_Guid src = {3, 45, 1222, {8, 7, 6, 5, 4, 3, 2, 1}};
@@ -1582,6 +1614,56 @@ START_TEST(UA_Guid_copyWithNullArgumentShallReturn) {
 	//finally
 }
 END_TEST
+START_TEST(UA_LocalizedText_copycstringShallWorkOnInputExample) {
+	// given
+	const char src[7] = {'t', 'e', 'X', 't', '1', '2', '3'};
+
+	UA_LocalizedText dst;
+	UA_Int32 ret;
+
+	// when
+	ret = UA_LocalizedText_copycstring(src, &dst);
+	// then
+	ck_assert_int_eq(ret, UA_SUCCESS);
+	ck_assert_int_eq('E', dst.locale.data[0]);
+	ck_assert_int_eq('N', dst.locale.data[1]);
+	ck_assert_int_eq('1', dst.text.data[4]);
+	ck_assert_int_eq(2, dst.locale.length);
+	ck_assert_int_eq(7, dst.text.length);
+}
+END_TEST
+START_TEST(UA_LocalizedText_copycstringNULLInput) {
+	// given
+	const char src[7] = {'t', 'e', 'X', 't', '1', '2', '3'};
+
+	UA_LocalizedText *dst = UA_NULL;
+	UA_Int32 ret;
+
+	// when
+	ret = UA_LocalizedText_copycstring(src, dst);
+	// then
+	ck_assert_int_eq(ret, UA_ERROR);
+}
+END_TEST
+START_TEST(UA_DataValue_copyShallWorkOnInputExample) {
+	// given
+	UA_Variant srcVariant;
+	UA_Variant_init(&srcVariant);
+	UA_DataValue src = {5, srcVariant, 44, 4, 77, 58, 8};
+
+	UA_DataValue dst;
+	UA_Int32 ret;
+
+	// when
+	ret = UA_DataValue_copy(&src, &dst);
+	// then
+	ck_assert_int_eq(ret, UA_SUCCESS);
+	ck_assert_int_eq(5, dst.encodingMask);
+	ck_assert_int_eq(4, dst.sourceTimestamp);
+	ck_assert_int_eq(77, dst.sourcePicoseconds);
+	ck_assert_int_eq(8, dst.serverPicoseconds);
+}
+END_TEST
 START_TEST(UA_Variant_copyShallWorkOnSingleValueExample) {
 	//given
 	UA_String testString = (UA_String){5, (UA_Byte*)"OPCUA"};
@@ -1611,7 +1693,6 @@ START_TEST(UA_Variant_copyShallWorkOnSingleValueExample) {
 	UA_Variant_deleteMembers(&copiedValue);
 }
 END_TEST
-
 START_TEST(UA_Variant_copyShallWorkOn1DArrayExample) {
 	// given
 	UA_String *srcArray;
@@ -1658,7 +1739,6 @@ START_TEST(UA_Variant_copyShallWorkOn1DArrayExample) {
 	UA_Variant_deleteMembers(&copiedValue);
 }
 END_TEST
-
 START_TEST(UA_Variant_copyShallWorkOn2DArrayExample) {
 	// given
 	UA_Int32 *srcArray;
@@ -1836,9 +1916,13 @@ Suite *testSuite_builtin(void) {
 
 	tcase_add_test(tc_copy, UA_DiagnosticInfo_copyShallWorkOnExample);
 	tcase_add_test(tc_copy, UA_ApplicationDescription_copyShallWorkOnExample);
-
+	tcase_add_test(tc_copy, UA_QualifiedName_copyShallWorkOnInputExample);
+	tcase_add_test(tc_copy, UA_QualifiedName_copyNULLInput);
 	tcase_add_test(tc_copy, UA_Guid_copyWithNullArgumentShallReturn);
 	tcase_add_test(tc_copy, UA_Guid_copyShallWorkOnInputExample);
+	tcase_add_test(tc_copy, UA_LocalizedText_copycstringShallWorkOnInputExample);
+	tcase_add_test(tc_copy, UA_LocalizedText_copycstringNULLInput);
+	tcase_add_test(tc_copy, UA_DataValue_copyShallWorkOnInputExample);
 	suite_add_tcase(s, tc_copy);
 	return s;
 }

+ 31 - 2
tests/check_list.c

@@ -7,6 +7,10 @@
 UA_Int32 visit_count = 0;
 UA_Int32 free_count = 0;
 
+void elementVisitor(UA_list_Element* payload){
+	visit_count++;
+}
+
 void visitor(void* payload){
 	visit_count++;
 }
@@ -55,6 +59,9 @@ START_TEST(list_test_basic)
 	*payload = 1;
 	UA_list_addPayloadToBack(&list, payload);
 
+	ck_assert_int_eq(*(UA_Int32*)UA_list_getFirst(&list)->payload, 24);
+	ck_assert_int_eq(*(UA_Int32*)UA_list_getLast(&list)->payload, 1);
+
 	ck_assert_int_eq(list.size, 3);
 
 	UA_list_iteratePayload(&list, visitor);
@@ -94,7 +101,6 @@ void myAddPayloadVectorToFront(UA_list_List *list, UA_Int32 payloadValues[], UA_
 	}
 }
 
-
 START_TEST(addElementsShallResultInRespectiveSize)
 {
 	// given
@@ -154,7 +160,8 @@ START_TEST(addAndRemoveShallYieldEmptyList)
 	myAddPayloadVectorToFront(&list,plv,sizeof(plv)/sizeof(UA_Int32));
 	// when
 	UA_list_Element* e = UA_list_search(&list,comparer,(void*)&plv[0]);
-	UA_list_removeElement(e,UA_NULL);
+	UA_list_removeElement(e,visitor);
+	ck_assert_int_eq(visit_count,1);
 	visit_count = 0;
 	UA_list_iteratePayload(&list,visitor);
 	// then
@@ -165,6 +172,27 @@ START_TEST(addAndRemoveShallYieldEmptyList)
 }
 END_TEST
 
+START_TEST(addAndRemoveShallYieldEmptyList2)
+{
+	// given
+	UA_list_List list;
+	UA_list_init(&list);
+	UA_Int32 plv[] = {42};
+	myAddPayloadVectorToFront(&list,plv,sizeof(plv)/sizeof(UA_Int32));
+	// when
+	UA_list_search(&list,comparer,(void*)&plv[0]);
+	UA_list_removeLast(&list,visitor);  //additionally testing removeLast explicitly
+	ck_assert_int_eq(visit_count,1);
+	visit_count = 0;
+	UA_list_iterateElement(&list,elementVisitor); //additionally testing iterateElement
+	// then
+	ck_assert_int_eq(list.size,0);
+	ck_assert_int_eq(visit_count,0);
+	// finally
+	UA_list_destroy(&list, freer);
+}
+END_TEST
+
 START_TEST(addTwiceAndRemoveFirstShallYieldListWithOneElement)
 {
 	// given
@@ -214,6 +242,7 @@ Suite*list_testSuite(void)
 	tcase_add_test(tc_core, findElementShallFind42);
 	tcase_add_test(tc_core, searchElementShallFind24);
 	tcase_add_test(tc_core, addAndRemoveShallYieldEmptyList);
+	tcase_add_test(tc_core, addAndRemoveShallYieldEmptyList2);
 	tcase_add_test(tc_core, addTwiceAndRemoveFirstShallYieldListWithOneElement);
 	tcase_add_test(tc_core, addTwiceAndRemoveLastShallYieldListWithOneElement);
 	suite_add_tcase(s,tc_core);

+ 194 - 0
tests/check_stack.c

@@ -438,6 +438,189 @@ START_TEST(validCreateSessionShallCreateSession) {
 }
 END_TEST
 
+START_TEST(UA_OPCUATcpMessageHeader_copyShallWorkOnInputExample) {
+	// given
+	UA_OPCUATcpMessageHeader src;
+	UA_OPCUATcpMessageHeader_init(&src);
+	src.isFinal = 2;
+	src.messageSize = 43;
+	src.messageType = UA_MESSAGETYPE_MSG;
+	const UA_OPCUATcpMessageHeader srcConst = src;
+
+	UA_OPCUATcpMessageHeader dst;
+	UA_Int32 ret;
+
+	// when
+	ret = UA_OPCUATcpMessageHeader_copy(&srcConst, &dst);
+	// then
+	ck_assert_int_eq(ret, UA_SUCCESS);
+	ck_assert_int_eq(UA_MESSAGETYPE_MSG, dst.messageType);
+	ck_assert_int_eq(43, dst.messageSize);
+	ck_assert_int_eq(2, dst.isFinal);
+}
+END_TEST
+START_TEST(UA_AsymmetricAlgorithmSecurityHeader_copyShallWorkOnInputExample) {
+	// given
+	UA_AsymmetricAlgorithmSecurityHeader src;
+	UA_AsymmetricAlgorithmSecurityHeader_init(&src);
+	src.receiverCertificateThumbprint = (UA_String){10, (UA_Byte*)"thumbprint"};
+	src.securityPolicyUri = (UA_String){6, (UA_Byte*)"policy"};
+	src.senderCertificate = (UA_String){8, (UA_Byte*)"tEsT123!"};
+	src.requestId = 99;
+	const UA_AsymmetricAlgorithmSecurityHeader srcConst = src;
+
+	UA_AsymmetricAlgorithmSecurityHeader dst;
+	UA_Int32 ret;
+
+	// when
+	ret = UA_AsymmetricAlgorithmSecurityHeader_copy(&srcConst, &dst);
+	// then
+	ck_assert_int_eq(ret, UA_SUCCESS);
+	ck_assert_int_eq('m', dst.receiverCertificateThumbprint.data[3]);
+	ck_assert_int_eq(10, dst.receiverCertificateThumbprint.length);
+	ck_assert_int_eq('o', dst.securityPolicyUri.data[1]);
+	ck_assert_int_eq(6, dst.securityPolicyUri.length);
+	ck_assert_int_eq('t', dst.senderCertificate.data[0]);
+	ck_assert_int_eq(8, dst.senderCertificate.length);
+	ck_assert_int_eq(99, dst.requestId);
+}
+END_TEST
+START_TEST(UA_SecureConversationMessageHeader_copyShallWorkOnInputExample) {
+	// given
+	UA_SecureConversationMessageHeader src;
+	UA_SecureConversationMessageHeader_init(&src);
+	src.secureChannelId = 84;
+	UA_OPCUATcpMessageHeader srcHeader;
+	UA_OPCUATcpMessageHeader_init(&srcHeader);
+	srcHeader.isFinal = 4;
+	srcHeader.messageSize = 765;
+	srcHeader.messageType = UA_MESSAGETYPE_CLO;
+	src.messageHeader = srcHeader;
+
+	const UA_SecureConversationMessageHeader srcConst = src;
+
+	UA_SecureConversationMessageHeader dst;
+	UA_Int32 ret;
+
+	// when
+	ret = UA_SecureConversationMessageHeader_copy(&srcConst, &dst);
+	// then
+	ck_assert_int_eq(ret, UA_SUCCESS);
+	ck_assert_int_eq(84, dst.secureChannelId);
+	ck_assert_int_eq(4, dst.messageHeader.isFinal);
+	ck_assert_int_eq(765, dst.messageHeader.messageSize);
+	ck_assert_int_eq(UA_MESSAGETYPE_CLO, dst.messageHeader.messageType);
+}
+END_TEST
+START_TEST(UA_SequenceHeader_copyShallWorkOnInputExample) {
+	// given
+	UA_SequenceHeader src;
+	UA_SequenceHeader_init(&src);
+	src.requestId = 84;
+	src.sequenceNumber = 1345;
+
+	const UA_SequenceHeader srcConst = src;
+
+	UA_SequenceHeader dst;
+	UA_Int32 ret;
+
+	// when
+	ret = UA_SequenceHeader_copy(&srcConst, &dst);
+	// then
+	ck_assert_int_eq(ret, UA_SUCCESS);
+	ck_assert_int_eq(84, dst.requestId);
+	ck_assert_int_eq(1345, dst.sequenceNumber);
+}
+END_TEST
+START_TEST(UA_SecureConversationMessageFooter_copyShallWorkOnInputExample) {
+	// given
+	UA_SecureConversationMessageFooter src;
+	UA_SecureConversationMessageFooter_init(&src);
+	UA_Byte srcByte[3] = {24, 57, 87};
+	src.padding = srcByte;
+	src.paddingSize = 3;
+	src.signature = 5;
+
+	const UA_SecureConversationMessageFooter srcConst = src;
+
+	UA_SecureConversationMessageFooter dst;
+	UA_Int32 ret;
+
+	// when
+	ret = UA_SecureConversationMessageFooter_copy(&srcConst, &dst);
+	// then
+	ck_assert_int_eq(ret, UA_SUCCESS);
+	ck_assert_int_eq(5, dst.signature);
+	ck_assert_int_eq(3, dst.paddingSize);
+	ck_assert_int_eq(24, dst.padding[0]);
+	ck_assert_int_eq(57, dst.padding[1]);
+	ck_assert_int_eq(87, dst.padding[2]);
+}
+END_TEST
+START_TEST(UA_SecureConversationMessageFooter_calcSizeBinaryShallWorkOnInputExample) {
+	// given
+	UA_SecureConversationMessageFooter src;
+	UA_SecureConversationMessageFooter_init(&src);
+	UA_Byte srcByte[3] = {24, 57, 87};
+	src.padding = srcByte;
+	src.paddingSize = 3;
+	src.signature = 5;
+
+	const UA_SecureConversationMessageFooter srcConst = src;
+
+	UA_Int32 ret;
+
+	// when
+	ret = UA_SecureConversationMessageFooter_calcSizeBinary(&srcConst);
+	// then
+	ck_assert_int_eq(ret, 8);
+}
+END_TEST
+START_TEST(UA_SecureConversationMessageFooter_encodeBinaryShallWorkOnInputExample) {
+//	// given
+//	UA_SecureConversationMessageFooter src = {3, (UA_Byte*)"447", 5};;
+//
+//	UA_Int32 ret;
+//	UA_UInt32 offset = 0;
+//	UA_ByteString dst = (UA_ByteString){15, (UA_Byte*)"123456789abcdef"};
+//
+//	// when
+//	ret = UA_SecureConversationMessageFooter_encodeBinary(&src, &dst, &offset);
+//	// then
+//	ck_assert_int_eq(ret, UA_SUCCESS);
+//	ck_assert_int_eq(dst.length, 8);
+//	ck_assert_int_eq(dst.data[0], 0);
+//	ck_assert_int_eq(dst.data[1], 0);
+//	ck_assert_int_eq(dst.data[2], 0);
+//	ck_assert_int_eq(dst.data[3], 3);
+//	ck_assert_int_eq(dst.data[4], 24);
+//	ck_assert_int_eq(dst.data[5], 57);
+//	ck_assert_int_eq(dst.data[6], 87);
+//	ck_assert_int_eq(dst.data[7], 6);
+}
+END_TEST
+START_TEST(UA_SecureConversationMessageAbortBody_copyShallWorkOnInputExample) {
+	// given
+	UA_SecureConversationMessageAbortBody src;
+	UA_SecureConversationMessageAbortBody_init(&src);
+	src.error = 5478;
+	src.reason = (UA_String){6, (UA_Byte*)"reAson"};
+
+	const UA_SecureConversationMessageAbortBody srcConst = src;
+
+	UA_SecureConversationMessageAbortBody dst;
+	UA_Int32 ret;
+
+	// when
+	ret = UA_SecureConversationMessageAbortBody_copy(&srcConst, &dst);
+	// then
+	ck_assert_int_eq(ret, UA_SUCCESS);
+	ck_assert_int_eq(5478, dst.error);
+	ck_assert_int_eq('A', dst.reason.data[2]);
+	ck_assert_int_eq(6, dst.reason.length);
+}
+END_TEST
+
 Suite *testSuite() {
 	Suite *s = suite_create("Stack Test");
 	TCase *tc_core = tcase_create("Core");
@@ -447,6 +630,17 @@ Suite *testSuite() {
 	tcase_add_test(tc_core, validOpeningCloseSequence);
 	tcase_add_test(tc_core, validCreateSessionShallCreateSession);
 	suite_add_tcase(s, tc_core);
+
+	TCase *tc_transport = tcase_create("Transport");
+	tcase_add_test(tc_transport, UA_OPCUATcpMessageHeader_copyShallWorkOnInputExample);
+	tcase_add_test(tc_transport, UA_AsymmetricAlgorithmSecurityHeader_copyShallWorkOnInputExample);
+	tcase_add_test(tc_transport, UA_SecureConversationMessageHeader_copyShallWorkOnInputExample);
+	tcase_add_test(tc_transport, UA_SequenceHeader_copyShallWorkOnInputExample);
+	tcase_add_test(tc_transport, UA_SecureConversationMessageFooter_copyShallWorkOnInputExample);
+	tcase_add_test(tc_transport, UA_SecureConversationMessageFooter_calcSizeBinaryShallWorkOnInputExample);
+	tcase_add_test(tc_transport, UA_SecureConversationMessageFooter_encodeBinaryShallWorkOnInputExample);
+	tcase_add_test(tc_transport, UA_SecureConversationMessageAbortBody_copyShallWorkOnInputExample);
+	suite_add_tcase(s, tc_transport);
 	return s;
 }
 

+ 28 - 16
tools/generate_builtin.py

@@ -7,17 +7,21 @@ from collections import OrderedDict
 import re
 from lxml import etree
 import inspect
-
-if len(sys.argv) != 3:
-	print("Usage: python generate_builtin.py <path/to/Opc.Ua.Types.bsd> <outfile w/o extension>", file=sys.stdout)
-	exit(0)
-
+import argparse
+
+parser = argparse.ArgumentParser()
+parser.add_argument('types', help='path/to/Opc.Ua.Types.bsd')
+parser.add_argument('outfile', help='outfile w/o extension')
+parser.add_argument('--with-xml', action='store_true', help='generate xml encoding')
+parser.add_argument('--only-nano', action='store_true', help='generate only the types for the nano profile')
+args = parser.parse_args()
+        
 ns = {"opc": "http://opcfoundation.org/BinarySchema/"}
-tree = etree.parse(sys.argv[1])
+tree = etree.parse(args.types)
 types = tree.xpath("/opc:TypeDictionary/*[not(self::opc:Import)]", namespaces=ns)
 
-fh = open(sys.argv[2] + ".h",'w')
-fc = open(sys.argv[2] + ".c",'w')
+fh = open(args.outfile + ".h",'w')
+fc = open(args.outfile + ".c",'w')
 
 # dirty hack. we go up the call frames to access local variables of the calling
 # function. this allows to shorten code and get %()s replaces with less clutter.
@@ -42,6 +46,10 @@ fixed_size = set(["UA_Boolean", "UA_SByte", "UA_Byte", "UA_Int16", "UA_UInt16",
 def skipType(name):
     if name in existing_types:
         return True
+    if "Test" in name:
+        return True
+    if re.search("Attributes$", name) != None:
+        return True
     if re.search("NodeId$", name) != None:
         return True
     return False
@@ -79,10 +87,11 @@ def createEnumerated(element):
            "\n};")
     printh("UA_TYPE_PROTOTYPES (" + name + ")")
     printh("UA_TYPE_BINARY_ENCODING(" + name + ")")
-    printh("UA_TYPE_XML_ENCODING(" + name + ")\n")
     printc("UA_TYPE_AS(" + name + ", UA_Int32)")
     printc("UA_TYPE_BINARY_ENCODING_AS(" + name + ", UA_Int32)")
-    printc('''UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(%(name)s)
+    if args.with_xml:
+        printh("UA_TYPE_XML_ENCODING(" + name + ")\n")
+        printc('''UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(%(name)s)
 UA_TYPE_METHOD_ENCODEXML_NOTIMPL(%(name)s)
 UA_TYPE_METHOD_DECODEXML_NOTIMPL(%(name)s\n)''')
 
@@ -94,10 +103,11 @@ def createOpaque(element):
     printh("typedef UA_ByteString %(name)s;")
     printh("UA_TYPE_PROTOTYPES(%(name)s)")
     printh("UA_TYPE_BINARY_ENCODING(%(name)s)")
-    printh("UA_TYPE_XML_ENCODING(" + name + ")\n")
     printc("UA_TYPE_AS(%(name)s, UA_ByteString)")
     printc("UA_TYPE_BINARY_ENCODING_AS(%(name)s, UA_ByteString)")
-    printc('''UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(%(name)s)
+    if args.with_xml:
+        printh("UA_TYPE_XML_ENCODING(" + name + ")\n")
+        printc('''UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(%(name)s)
 UA_TYPE_METHOD_ENCODEXML_NOTIMPL(%(name)s)
 UA_TYPE_METHOD_DECODEXML_NOTIMPL(%(name)s)\n''')
 
@@ -140,7 +150,8 @@ def createStructured(element):
     # 3) function prototypes
     printh("UA_TYPE_PROTOTYPES(" + name + ")")
     printh("UA_TYPE_BINARY_ENCODING(" + name + ")")
-    printh("UA_TYPE_XML_ENCODING(" + name + ")\n")
+    if args.with_xml:
+        printh("UA_TYPE_XML_ENCODING(" + name + ")\n")
 
     # 4) CalcSizeBinary
     printc('''UA_Int32 %(name)s_calcSizeBinary(%(name)s const * ptr) {
@@ -188,9 +199,10 @@ def createStructured(element):
     printc("\treturn retval;\n}\n")
 
     # 7) Xml
-    printc('''UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(%(name)s)
-    UA_TYPE_METHOD_ENCODEXML_NOTIMPL(%(name)s)
-    UA_TYPE_METHOD_DECODEXML_NOTIMPL(%(name)s)''')
+    if args.with_xml:
+        printc('''UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(%(name)s)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(%(name)s)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(%(name)s)''')
     
     # 8) Delete
     printc('''UA_Int32 %(name)s_delete(%(name)s *p) {

+ 32 - 20
tools/generate_namespace.py

@@ -4,11 +4,14 @@ import sys
 import platform
 import getpass
 import time
+import re
+import argparse
 
-if len(sys.argv) != 3:
-    print("Usage: python generate_namespace.py <path/to/NodeIds.csv> <outfile w/o extension>",
-          file=sys.stdout)
-    exit(0)
+parser = argparse.ArgumentParser()
+parser.add_argument('nodeids', help='path/to/NodeIds.csv')
+parser.add_argument('outfile', help='outfile w/o extension')
+parser.add_argument('--with-xml', action='store_true', help='generate xml encoding')
+args = parser.parse_args()
 
 # types that are to be excluded
 exclude_kinds = set(["Object","ObjectType","Variable","Method","ReferenceType"])
@@ -52,14 +55,23 @@ fixed_size = ['UA_DeadbandType', 'UA_DataChangeTrigger', 'UA_Guid', 'UA_Applicat
               'UA_ExceptionDeviationFormat', 'UA_ComplianceLevel', 'UA_DateTime', 'UA_Int64',
               'UA_Double']
 
-f = open(sys.argv[1])
+def skipType(row):
+    if row[0] == "" or row[0] in exclude_types or row[2] in exclude_kinds:
+        return True
+    if "Test" in row[0]:
+        return True
+    if re.search("Attributes$", row[0]) != None:
+        return True
+    return False
+
+f = open(args.nodeids)
 input_str = f.read() + "\nInvalidType,0,DataType"
 input_str = input_str.replace('\r','')
 rows = map(lambda x:tuple(x.split(',')), input_str.split('\n'))
 f.close()
 
-fh = open(sys.argv[2] + ".h",'w')
-fc = open(sys.argv[2] + ".c",'w')
+fh = open(args.outfile + ".h",'w')
+fc = open(args.outfile + ".c",'w')
 def printh(string):
     print(string % inspect.currentframe().f_back.f_locals, end='\n', file=fh)
 
@@ -67,14 +79,14 @@ def printc(string):
     print(string % inspect.currentframe().f_back.f_locals, end='\n', file=fc)
 
 printh('''/**********************************************************
- * '''+sys.argv[2]+'''.hgen -- do not modify
+ * '''+args.outfile+'''.hgen -- do not modify
  **********************************************************
- * Generated from '''+sys.argv[1]+''' with script '''+sys.argv[0]+'''
+ * Generated from '''+args.nodeids+''' with script '''+sys.argv[0]+'''
  * on host '''+platform.uname()[1]+''' by user '''+getpass.getuser()+''' at '''+
        time.strftime("%Y-%m-%d %I:%M:%S")+'''
  **********************************************************/\n 
-#ifndef ''' + sys.argv[2].upper() + '''_H_
-#define ''' + sys.argv[2].upper() + '''_H_\n
+#ifndef ''' + args.outfile.upper() + '''_H_
+#define ''' + args.outfile.upper() + '''_H_\n
 #include "util/ua_util.h"
 #include "ua_types.h"  // definition of UA_VTable and basic UA_Types
 #include "ua_types_generated.h"\n
@@ -98,13 +110,13 @@ extern const UA_VTable UA_borrowed_;\n
 enum UA_VTableIndex_enum {''')
 
 printc('''/**********************************************************
- * '''+sys.argv[2]+'''.cgen -- do not modify
+ * '''+args.outfile+'''.cgen -- do not modify
  **********************************************************
- * Generated from '''+sys.argv[1]+''' with script '''+sys.argv[0]+'''
+ * Generated from '''+args.nodeids+''' with script '''+sys.argv[0]+'''
  * on host '''+platform.uname()[1]+''' by user '''+getpass.getuser() +
        ''' at '''+ time.strftime("%Y-%m-%d %I:%M:%S")+'''
  **********************************************************/\n
-#include "''' + sys.argv[2] + '''.h"\n
+#include "''' + args.outfile + '''.h"\n
 UA_Int32 UA_ns0ToVTableIndex(const UA_NodeId *id) {
 	UA_Int32 retval = 0; // InvalidType
         if(id->namespace != 0) return retval;
@@ -112,7 +124,7 @@ UA_Int32 UA_ns0ToVTableIndex(const UA_NodeId *id) {
 
 i = 0
 for row in rows:
-    if row[0] == "" or row[0] in exclude_types or row[2] in exclude_kinds:
+    if skipType(row):
         continue
     if row[0] == "BaseDataType":
     	name = "UA_Variant"
@@ -134,7 +146,7 @@ printc('''const UA_VTable UA_ = {
 
 i = 0
 for row in rows:
-    if row[0] == "" or row[0] in exclude_types or row[2] in exclude_kinds:
+    if skipType(row):
         continue
     if row[0] == "BaseDataType":
         name = "UA_Variant"
@@ -145,7 +157,7 @@ for row in rows:
 	i=i+1
     printh('#define '+name.upper()+'_NS0 '+row[1])
 
-    printc("\t{.typeId={UA_NODEIDTYPE_FOURBYTE,0,.identifier.numeric=" + row[1] + "}" + 
+    printc("\t{.typeId={.encodingByte = UA_NODEIDTYPE_TWOBYTE, .namespace = 0,.identifier.numeric=" + row[1] + "}" + 
           ",\n.name=(UA_Byte*)&\"%(name)s\"" +
           ",\n.new=(UA_Int32(*)(void **))%(name)s_new" +
           ",\n.init=(UA_Int32(*)(void *))%(name)s_init"+
@@ -160,9 +172,9 @@ for row in rows:
           ",\n.encodings={{.calcSize=(UA_calcSize)%(name)s_calcSizeBinary" +
           ",\n.encode=(UA_encode)%(name)s_encodeBinary" +
           ",\n.decode=(UA_decode)%(name)s_decodeBinary}" +
-          ",\n{.calcSize=(UA_calcSize)%(name)s_calcSizeXml" +
-          ",\n.encode=(UA_encode)%(name)s_encodeXml" +
-          ",\n.decode=(UA_decode)%(name)s_decodeXml}" +
+           (",\n{.calcSize=(UA_calcSize)%(name)s_calcSizeXml" +
+            ",\n.encode=(UA_encode)%(name)s_encodeXml" +
+            ",\n.decode=(UA_decode)%(name)s_decodeXml}" if (args.with_xml) else "") +
           "}},")
 
 printc('''}};''')