diff --git a/compiler2/ttcn3/AST_ttcn3.cc b/compiler2/ttcn3/AST_ttcn3.cc index 8e727d3fd61281655d112e3f04f3e6369a1165cd..90ea38886824d044136337ebed39d1cd5662b4ba 100644 --- a/compiler2/ttcn3/AST_ttcn3.cc +++ b/compiler2/ttcn3/AST_ttcn3.cc @@ -6740,8 +6740,8 @@ namespace Ttcn { { delete encoding_options; delete eb_list; - if (NULL != json_printing) { - delete json_printing; + if (NULL != printing) { + delete printing; } } @@ -7131,7 +7131,7 @@ namespace Ttcn { break; } case ExtensionAttribute::PRINTING: { - json_printing = ea.get_printing(); + printing = ea.get_printing(); break; } case ExtensionAttribute::ANYTYPELIST: @@ -7157,9 +7157,9 @@ namespace Ttcn { chk_prototype(); chk_function_type(); - if (NULL != json_printing && (EXTFUNC_ENCODE != function_type || - Type::CT_JSON != encoding_type)) { - error("Attribute 'printing' is only allowed for JSON encoding functions."); + if (NULL != printing && (EXTFUNC_ENCODE != function_type || + (Type::CT_JSON != encoding_type && Type::CT_XER != encoding_type))) { + error("Attribute 'printing' is only allowed for JSON and XER encoding functions."); } } @@ -7194,14 +7194,27 @@ namespace Ttcn { input_type->get_genname_typedescriptor(my_scope).c_str(), Type::get_encoding_name(encoding_type)); if (encoding_type == Type::CT_JSON) { - if (json_printing != NULL) { - str = json_printing->generate_code(str); + if (printing != NULL) { + str = printing->generate_code(str); } else { str = mputstr(str, ", 0"); } + } else if (encoding_type == Type::CT_XER) { + bool compact_printing = + printing != NULL && printing->get_printing() == PrintingType::PT_COMPACT; + if (compact_printing || encoding_options) { + str = mputstr(str, ", "); + } + if (compact_printing) { + str = mputprintf(str, "XER_CANONICAL%s", + encoding_options ? "|" : ""); + } + if (encoding_options) str = mputprintf(str, "%s", + encoding_options->c_str()); + } else { + if (encoding_options) str = mputprintf(str, ", %s", + encoding_options->c_str()); } - if (encoding_options) str = mputprintf(str, ", %s", - encoding_options->c_str()); str = mputstr(str, ");\n"); const char *result_name; switch (prototype) { @@ -7599,10 +7612,10 @@ namespace Ttcn { } // insert printing type - if (json_printing != NULL) { + if (printing != NULL) { json->put_next_token(JSON_TOKEN_NAME, "printing"); json->put_next_token(JSON_TOKEN_STRING, - (json_printing->get_printing() == PrintingType::PT_PRETTY) ? + (printing->get_printing() == PrintingType::PT_PRETTY) ? "\"pretty\"" : "\"compact\""); } diff --git a/compiler2/ttcn3/AST_ttcn3.hh b/compiler2/ttcn3/AST_ttcn3.hh index aeb433e38e3d2f96bcb252eace664d4096db01ad..cfadc7a670cd48a2769c89ed92cf7377bb43f23e 100644 --- a/compiler2/ttcn3/AST_ttcn3.hh +++ b/compiler2/ttcn3/AST_ttcn3.hh @@ -1537,7 +1537,8 @@ namespace Ttcn { Type::MessageEncodingType_t encoding_type; string *encoding_options; Ttcn::ErrorBehaviorList *eb_list; - Ttcn::PrintingType *json_printing; + // pretty or compact printing for json or xml + Ttcn::PrintingType *printing; /// Copy constructor disabled Def_ExtFunction(const Def_ExtFunction& p); /// %Assignment disabled @@ -1559,7 +1560,7 @@ namespace Ttcn { : Def_Function_Base(true, p_id, p_fpl, p_return_type, returns_template, p_template_restriction), function_type(EXTFUNC_MANUAL), encoding_type(Type::CT_UNDEF), - encoding_options(0), eb_list(0), json_printing(0) { } + encoding_options(0), eb_list(0), printing(0) { } ~Def_ExtFunction(); virtual Def_ExtFunction *clone() const; virtual void set_fullname(const string& p_fullname); diff --git a/core/Basetype.cc b/core/Basetype.cc index 3d1386ae8ad27783b9955886b93f33d71fe960d5..8e2d53ff0ec48e9730877dc32aca75c2a480325d 100644 --- a/core/Basetype.cc +++ b/core/Basetype.cc @@ -217,6 +217,7 @@ void Base_Type::XER_encode_chk_coding(unsigned& p_coding, } switch (p_coding) { case XER_BASIC: + case XER_BASIC | XER_CANONICAL: case XER_CANONICAL: case XER_EXTENDED: case XER_EXTENDED | XER_CANONICAL: diff --git a/regression_test/XML/Makefile b/regression_test/XML/Makefile index f2506c080c5b34897e3d7b485cbf82ddba94807a..60583cf3b1a63a3a2979520dc3ba971d14b9daa9 100644 --- a/regression_test/XML/Makefile +++ b/regression_test/XML/Makefile @@ -30,7 +30,7 @@ endif XDIRS := $(wildcard $(SHADOWED)) xsdConverter \ HM60295 HN15589 HQ30408 HR49727 HU13380 $(RT2_ONLY) \ XmlWorkflow tpdValidTest AbstractBlock UseNilLong AttributeFormDefault \ -RecordOmit XSDBaseType LegacyUntaggedUnion +RecordOmit XSDBaseType LegacyUntaggedUnion Printing # List of fake targets: .PHONY: all dep clean run $(XDIRS) $(addsuffix /, $(XDIRS)) profile diff --git a/regression_test/XML/Printing/.gitignore b/regression_test/XML/Printing/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..700a8c171f7a105e4ab92e240230b8193df13ec0 --- /dev/null +++ b/regression_test/XML/Printing/.gitignore @@ -0,0 +1,8 @@ +*.old +*.log +compile +*.cc +*.hh +*.d +Printing +Printing.exe \ No newline at end of file diff --git a/regression_test/XML/Printing/Makefile b/regression_test/XML/Printing/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c49ae283adb0134dce76f5e9fae500ff7a9efecd --- /dev/null +++ b/regression_test/XML/Printing/Makefile @@ -0,0 +1,147 @@ +############################################################################## +# Copyright (c) 2000-2017 Ericsson Telecom AB +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Bence Janos Szabo – initial implementation +# +############################################################################## +TOPDIR = ../.. +include ../../Makefile.regression + +# WARNING! This Makefile can be used with GNU make only. +# Other versions of make may report syntax errors in it. + +# +# Do NOT touch this line... +# +.PHONY: all archive check clean dep objects + +.SUFFIXES: .d + +# +# Set these variables... +# + +# Flags for the C++ preprocessor (and makedepend as well): +#CPPFLAGS += + +# Flags for dependency generation +CXXDEPFLAGS = -MM + +# Flags for the C++ compiler: +CXXFLAGS += -Wall + +# Flags for the linker: +#LDFLAGS += + +# Flags for the TTCN-3 and ASN.1 compiler: +#COMPILER_FLAGS += + +# Execution mode: (either ttcn3 or ttcn3-parallel) +TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX) + +# +# You may change these variables. Add your files if necessary... +# + +# TTCN-3 modules of this project: +TTCN3_MODULES = Printing.ttcn + +# ASN.1 modules of this project: +ASN1_MODULES = + +# C++ source & header files generated from the TTCN-3 & ASN.1 modules of +# this project: +GENERATED_SOURCES = $(TTCN3_MODULES:.ttcn=.cc) $(ASN1_MODULES:.asn=.cc) +GENERATED_HEADERS = $(GENERATED_SOURCES:.cc=.hh) +ifdef SPLIT_TO_SLICES +POSTFIXES := $(foreach file, $(SPLIT_TO_SLICES), $(addsuffix $(file), _part_)) +POSTFIXES := $(foreach file, $(POSTFIXES), $(addprefix $(file), .cc)) +GENERATED_SOURCES2 := $(foreach file, $(GENERATED_SOURCES:.cc=), $(addprefix $(file), $(POSTFIXES))) +GENERATED_SOURCES += $(GENERATED_SOURCES2) +endif +# C/C++ Source & header files of Test Ports, external functions and +# other modules: +USER_SOURCES = +USER_HEADERS = $(USER_SOURCES:.cc=.hh) + +# Object files of this project that are needed for the executable test suite: +OBJECTS = $(GENERATED_OBJECTS) $(USER_OBJECTS) + +GENERATED_OBJECTS = $(GENERATED_SOURCES:.cc=.o) + +USER_OBJECTS = $(USER_SOURCES:.cc=.o) + +DEPFILES = $(USER_OBJECTS:.o=.d) $(GENERATED_OBJECTS:.o=.d) + +# Other files of the project (Makefile, configuration files, etc.) +# that will be added to the archived source files: +OTHER_FILES = Makefile + +# The name of the executable test suite: +TARGET = UseNilLong + +# +# Rules for building the executable... +# + +all: $(TARGET) ; + +objects: $(OBJECTS) compile; + +$(TARGET): $(OBJECTS) + if $(CXX) $(LDFLAGS) -o $@ $^ \ + -L$(TTCN3_DIR)/lib -l$(TTCN3_LIB) \ + -L$(OPENSSL_DIR)/lib -lcrypto \ + -L$(XMLDIR)/lib $($(PLATFORM)_LIBS); \ + then : ; else $(TTCN3_DIR)/bin/titanver $(OBJECTS); exit 1; fi + +.cc.o .c.o: + $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $< + +.cc.d .c.d: + @echo Creating dependency file for '$<'; set -e; \ + $(CXX) $(CXXDEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) $< \ + | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \ + [ -s $@ ] || rm -f $@ + +$(GENERATED_SOURCES) $(GENERATED_HEADERS): compile + @if [ ! -f $@ ]; then $(RM) compile; $(MAKE) compile; fi + +compile: $(TTCN3_MODULES) $(ASN1_MODULES) + $(TTCN3_COMPILER) $(COMPILER_FLAGS) $^ - $? + touch $@ + +clean distclean: + -$(RM) $(TARGET) $(OBJECTS) $(GENERATED_HEADERS) \ + $(GENERATED_SOURCES) compile $(DEPFILES) \ + tags *.log + +dep: $(GENERATED_SOURCES) $(USER_SOURCES) ; + +ifeq ($(findstring n,$(MAKEFLAGS)),) +ifeq ($(filter clean distclean check compile archive diag,$(MAKECMDGOALS)),) +-include $(DEPFILES) +endif +endif + +diag: + $(TTCN3_COMPILER) -v 2>&1 + $(TTCN3_DIR)/bin/mctr_cli -v 2>&1 + $(CXX) -v 2>&1 + @echo TTCN3_DIR=$(TTCN3_DIR) + @echo OPENSSL_DIR=$(OPENSSL_DIR) + @echo XMLDIR=$(XMLDIR) + @echo PLATFORM=$(PLATFORM) + +# +# Add your rules here if necessary... +# + +run: $(TARGET) + ./$^ + diff --git a/regression_test/XML/Printing/Printing.ttcn b/regression_test/XML/Printing/Printing.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..e931a4620c9e85d8cd336179f886c624bc9ae188 --- /dev/null +++ b/regression_test/XML/Printing/Printing.ttcn @@ -0,0 +1,202 @@ +/****************************************************************************** + * Copyright (c) 2000-2017 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Szabo, Bence Janos + * + ******************************************************************************/ +module Printing { + + + type component EmptyCT { + + } + + type union MyUnion { + integer i + } + + type record of MyRec MyRecOf; + + type record MyRec { + MyRecOf recof optional, + MyUnion un optional, + integer i optional + } + + + external function enc_compact0(in MyRec a) return octetstring + with { extension "prototype(convert) encode(XER) printing(compact)" } + + external function enc_compact1(in MyRec a) return octetstring + with { extension "prototype(convert) encode(XER:XER_EXTENDED) printing(compact)" } + + external function enc_compact2(in MyRec a) return octetstring + with { extension "prototype(convert) encode(XER:XER_BASIC) printing(compact)" } + + external function enc_compact3(in MyRec a) return octetstring + with { extension "prototype(convert) encode(XER:XER_EXTENDED|XER_CANONICAL) printing(compact)" } // !!! + + + external function enc_pretty0(in MyRec a) return octetstring + with { extension "prototype(convert) encode(XER)" } + + external function enc_pretty1(in MyRec a) return octetstring + with { extension "prototype(convert) encode(XER:XER_BASIC)" } + + external function enc_pretty2(in MyRec a) return octetstring + with { extension "prototype(convert) encode(XER:XER_EXTENDED)" } + + external function enc_pretty3(in MyRec a) return octetstring + with { extension "prototype(convert) encode(XER) printing(pretty)" } + + external function enc_pretty4(in MyRec a) return octetstring + with { extension "prototype(convert) encode(XER:XER_EXTENDED) printing(pretty)" } + + external function enc_pretty5(in MyRec a) return octetstring + with { extension "prototype(convert) encode(XER:XER_BASIC) printing(pretty)" } + + + external function dec_basic(in octetstring a) return MyRec + with { extension "prototype(convert) decode(XER:XER_BASIC)" } + + +const MyRec c_myrec := { recof := {{recof := omit, un := {i := 1}, i := 3}, {recof := omit, un := omit, i := 4}}, un := { i := 4}, i := 5}; +const universal charstring c_compact := +"<MyRec>"& + "<recof>"& + "<MyRec>"& + "<un>"& + "<i>1</i>"& + "</un>"& + "<i>3</i>"& + "</MyRec>"& + "<MyRec>"& + "<i>4</i>"& + "</MyRec>"& + "</recof>"& + "<un>"& + "<i>4</i>"& + "</un>"& + "<i>5</i>"& +"</MyRec>\n"; + +const universal charstring c_pretty := +"<MyRec>\n"& +"\t<recof>\n"& +"\t\t<MyRec>\n"& +"\t\t\t<un>\n"& +"\t\t\t\t<i>1</i>\n"& +"\t\t\t</un>\n"& +"\t\t\t<i>3</i>\n"& +"\t\t</MyRec>\n"& +"\t\t<MyRec>\n"& +"\t\t\t<i>4</i>\n"& +"\t\t</MyRec>\n"& +"\t</recof>\n"& +"\t<un>\n"& +"\t\t<i>4</i>\n"& +"\t</un>\n"& +"\t<i>5</i>\n"& +"</MyRec>\n\n" + + +testcase tc_compact() runs on EmptyCT { + var octetstring os; + var MyRec myrec; + + os := enc_compact0(c_myrec); + if (oct2unichar(os) != c_compact) { + setverdict(fail, match(oct2unichar(os), c_compact)); + } + myrec := dec_basic(os); + if (myrec != c_myrec) { + setverdict(fail, match(myrec, c_myrec)); + } + + os := enc_compact1(c_myrec); + if (oct2unichar(os) != c_compact) { + setverdict(fail, match(oct2unichar(os), c_compact)); + } + myrec := dec_basic(os); + if (myrec != c_myrec) { + setverdict(fail, match(myrec, c_myrec)); + } + + os := enc_compact2(c_myrec); + if (oct2unichar(os) != c_compact) { + setverdict(fail, match(oct2unichar(os), c_compact)); + } + myrec := dec_basic(os); + if (myrec != c_myrec) { + setverdict(fail, match(myrec, c_myrec)); + } + + os := enc_compact3(c_myrec); + if (oct2unichar(os) != c_compact) { + setverdict(fail, match(oct2unichar(os), c_compact)); + } + myrec := dec_basic(os); + if (myrec != c_myrec) { + setverdict(fail, match(myrec, c_myrec)); + } + + setverdict(pass); +} + +testcase tc_pretty() runs on EmptyCT { + var octetstring os; + var MyRec myrec; + + os := enc_pretty0(c_myrec); + if (oct2unichar(os) != c_pretty) { + setverdict(fail, match(oct2unichar(os), c_pretty)); + } + myrec := dec_basic(os); + if (myrec != c_myrec) { + setverdict(fail, match(myrec, c_myrec)); + } + + os := enc_pretty1(c_myrec); + if (oct2unichar(os) != c_pretty) { + setverdict(fail, match(oct2unichar(os), c_pretty)); + } + myrec := dec_basic(os); + if (myrec != c_myrec) { + setverdict(fail, match(myrec, c_myrec)); + } + + os := enc_pretty2(c_myrec); + if (oct2unichar(os) != c_pretty) { + setverdict(fail, match(oct2unichar(os), c_pretty)); + } + myrec := dec_basic(os); + if (myrec != c_myrec) { + setverdict(fail, match(myrec, c_myrec)); + } + + os := enc_pretty3(c_myrec); + if (oct2unichar(os) != c_pretty) { + setverdict(fail, match(oct2unichar(os), c_pretty)); + } + myrec := dec_basic(os); + if (myrec != c_myrec) { + setverdict(fail, match(myrec, c_myrec)); + } + + setverdict(pass); +} + +control { + execute(tc_compact()); + execute(tc_pretty()); +} + +} +with { + encode "XML"; +} diff --git a/usrguide/referenceguide.doc b/usrguide/referenceguide.doc index 2d0a4de28daee726c4c5ca3f1af1abb983fac98f..2b6744feeb90866970859a5a5e0132cf0aa5d5b8 100644 Binary files a/usrguide/referenceguide.doc and b/usrguide/referenceguide.doc differ