diff options
Diffstat (limited to 'lib/asn1')
83 files changed, 2451 insertions, 1743 deletions
diff --git a/lib/asn1/Makefile b/lib/asn1/Makefile index 9c1b19605c..18e95a2471 100644 --- a/lib/asn1/Makefile +++ b/lib/asn1/Makefile @@ -26,6 +26,9 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk SUB_DIRECTORIES = src doc/src c_src +static_lib: SUB_DIRECTORIES = c_src + + include vsn.mk VSN = $(ASN1_VSN) @@ -60,7 +63,6 @@ info: version: @echo "$(VSN)" - # ---------------------------------------------------- # Application (source) release targets # ---------------------------------------------------- diff --git a/lib/asn1/c_src/Makefile b/lib/asn1/c_src/Makefile index 70238335c4..a7cd03f516 100644 --- a/lib/asn1/c_src/Makefile +++ b/lib/asn1/c_src/Makefile @@ -46,12 +46,11 @@ else TYPEMARKER = endif -EI_LIBDIR = $(ERL_TOP)/lib/erl_interface/obj$(TYPEMARKER)/$(TARGET) - # ---------------------------------------------------- # FLAGS # ---------------------------------------------------- CFLAGS = $(DED_INCLUDES) $(EI_INCLUDES) $(DED_CFLAGS) +STATIC_CFLAGS = $(DED_INCLUDES) $(EI_INCLUDES) $(DED_STATIC_CFLAGS) LDFLAGS += $(DED_LDFLAGS) # ---------------------------------------------------- @@ -59,28 +58,55 @@ LDFLAGS += $(DED_LDFLAGS) # ---------------------------------------------------- NIF_OBJ_FILES = $(OBJDIR)/asn1_erl_nif.o +NIF_STATIC_OBJ_FILES = $(OBJDIR)/asn1_erl_nif_static.o - +# Module and shared lib have to have same name of +# static nifs to work ifeq ($(TARGET),win32) -NIF_SHARED_OBJ_FILE = $(LIBDIR)/asn1_erl_nif.dll +NIF_SHARED_OBJ_FILE = $(LIBDIR)/asn1rt_nif.dll +NIF_LIB_FILE = $(LIBDIR)/asn1rt_nif.lib CLIB_FLAGS = LN=cp else -NIF_SHARED_OBJ_FILE = $(LIBDIR)/asn1_erl_nif.so +NIF_SHARED_OBJ_FILE = $(LIBDIR)/asn1rt_nif.so +NIF_LIB_FILE = $(LIBDIR)/asn1rt_nif.a CLIB_FLAGS = -lc LN= ln -s endif +ifeq ($(USING_VC),yes) +AR_OUT=-out: +AR_FLAGS= +else +AR_OUT= +ifeq ($(V),0) +AR_FLAGS=rc +else +AR_FLAGS=rcv +endif +endif + +ifndef RANLIB +RANLIB=true +endif + # ---------------------------------------------------- # Targets # ---------------------------------------------------- _create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR)) +ifneq ($(findstring ose,$(TARGET)),ose) opt: $(NIF_SHARED_OBJ_FILE) +else +# Do not build dynamic files on OSE +opt: +endif debug: opt +static_lib: $(NIF_LIB_FILE) + clean: rm -f core *~ rm -f $(LIBDIR)/* @@ -96,6 +122,13 @@ docs: $(OBJDIR)/%.o: %.c $(V_CC) -c $(CFLAGS) -O3 -o $@ $< +$(OBJDIR)/%_static.o: %.c + $(V_CC) -c $(STATIC_CFLAGS) -O3 -o $@ $< + +$(NIF_LIB_FILE): $(NIF_STATIC_OBJ_FILES) + $(V_AR) $(AR_FLAGS) $(AR_OUT)$@ $(NIF_STATIC_OBJ_FILES) + $(V_RANLIB) $@ + $(NIF_SHARED_OBJ_FILE): $(NIF_OBJ_FILES) $(V_LD) $(LDFLAGS) -o $(NIF_SHARED_OBJ_FILE) $(NIF_OBJ_FILES) $(CLIB_FLAGS) $(LIBS) @@ -106,7 +139,9 @@ include $(ERL_TOP)/make/otp_release_targets.mk release_spec: opt $(INSTALL_DIR) "$(RELSYSDIR)/priv/lib" +ifneq ($(findstring ose,$(TARGET)),ose) $(INSTALL_PROGRAM) $(NIF_SHARED_OBJ_FILE) "$(RELSYSDIR)/priv/lib" +endif $(INSTALL_DIR) "$(RELSYSDIR)/c_src" $(INSTALL_DATA) *.c "$(RELSYSDIR)/c_src" diff --git a/lib/asn1/c_src/asn1_erl_nif.c b/lib/asn1/c_src/asn1_erl_nif.c index b3dd312fed..8a0e4b1cf0 100644 --- a/lib/asn1/c_src/asn1_erl_nif.c +++ b/lib/asn1/c_src/asn1_erl_nif.c @@ -57,54 +57,54 @@ #define MASK(X,M) (X & M) /* PER COMPLETE */ -int per_complete(ErlNifBinary *, unsigned char *, int); +static int per_complete(ErlNifBinary *, unsigned char *, int); -int per_insert_octets(int, unsigned char **, unsigned char **, int *); +static int per_insert_octets(int, unsigned char **, unsigned char **, int *); -int per_insert_octets_except_unused(int, unsigned char **, unsigned char **, +static int per_insert_octets_except_unused(int, unsigned char **, unsigned char **, int *, int); -int per_insert_octets_as_bits_exact_len(int, int, unsigned char **, +static int per_insert_octets_as_bits_exact_len(int, int, unsigned char **, unsigned char **, int *); -int per_insert_octets_as_bits(int, unsigned char **, unsigned char **, int *); +static int per_insert_octets_as_bits(int, unsigned char **, unsigned char **, int *); -int per_pad_bits(int, unsigned char **, int *); +static int per_pad_bits(int, unsigned char **, int *); -int per_insert_least_sign_bits(int, unsigned char, unsigned char **, int *); +static int per_insert_least_sign_bits(int, unsigned char, unsigned char **, int *); -int per_insert_most_sign_bits(int, unsigned char, unsigned char **, int *); +static int per_insert_most_sign_bits(int, unsigned char, unsigned char **, int *); -int per_insert_bits_as_bits(int, int, unsigned char **, unsigned char **, int *); +static int per_insert_bits_as_bits(int, int, unsigned char **, unsigned char **, int *); -int per_insert_octets_unaligned(int, unsigned char **, unsigned char **, int); +static int per_insert_octets_unaligned(int, unsigned char **, unsigned char **, int); -int per_realloc_memory(ErlNifBinary *, int, unsigned char **); +static int per_realloc_memory(ErlNifBinary *, int, unsigned char **); /* BER DECODE */ -int ber_decode_begin(ErlNifEnv *, ERL_NIF_TERM *, unsigned char *, int, +static int ber_decode_begin(ErlNifEnv *, ERL_NIF_TERM *, unsigned char *, int, unsigned int *); -int ber_decode(ErlNifEnv *, ERL_NIF_TERM *, unsigned char *, int *, int); +static int ber_decode(ErlNifEnv *, ERL_NIF_TERM *, unsigned char *, int *, int); -int ber_decode_tag(ErlNifEnv *, ERL_NIF_TERM *, unsigned char *, int, int *); +static int ber_decode_tag(ErlNifEnv *, ERL_NIF_TERM *, unsigned char *, int, int *); -int ber_decode_value(ErlNifEnv*, ERL_NIF_TERM *, unsigned char *, int *, int, +static int ber_decode_value(ErlNifEnv*, ERL_NIF_TERM *, unsigned char *, int *, int, int); /* BER ENCODE */ typedef struct ber_encode_mem_chunk mem_chunk_t; -int ber_encode(ErlNifEnv *, ERL_NIF_TERM , mem_chunk_t **, unsigned int *); +static int ber_encode(ErlNifEnv *, ERL_NIF_TERM , mem_chunk_t **, unsigned int *); -void ber_free_chunks(mem_chunk_t *chunk); -mem_chunk_t *ber_new_chunk(unsigned int length); -int ber_check_memory(mem_chunk_t **curr, unsigned int needed); +static void ber_free_chunks(mem_chunk_t *chunk); +static mem_chunk_t *ber_new_chunk(unsigned int length); +static int ber_check_memory(mem_chunk_t **curr, unsigned int needed); -int ber_encode_tag(ErlNifEnv *, ERL_NIF_TERM , unsigned int , +static int ber_encode_tag(ErlNifEnv *, ERL_NIF_TERM , unsigned int , mem_chunk_t **, unsigned int *); -int ber_encode_length(size_t , mem_chunk_t **, unsigned int *); +static int ber_encode_length(size_t , mem_chunk_t **, unsigned int *); /* * @@ -113,7 +113,7 @@ int ber_encode_length(size_t , mem_chunk_t **, unsigned int *); * */ -int per_complete(ErlNifBinary *out_binary, unsigned char *in_buf, +static int per_complete(ErlNifBinary *out_binary, unsigned char *in_buf, int in_buf_len) { int counter = in_buf_len; /* counter keeps track of number of bytes left in the @@ -489,7 +489,7 @@ int per_complete(ErlNifBinary *out_binary, unsigned char *in_buf, } } -int per_realloc_memory(ErlNifBinary *binary, int amount, unsigned char **ptr) { +static int per_realloc_memory(ErlNifBinary *binary, int amount, unsigned char **ptr) { int i = *ptr - binary->data; @@ -502,7 +502,7 @@ int per_realloc_memory(ErlNifBinary *binary, int amount, unsigned char **ptr) { return ASN1_OK; } -int per_insert_most_sign_bits(int no_bits, unsigned char val, +static int per_insert_most_sign_bits(int no_bits, unsigned char val, unsigned char **output_ptr, int *unused) { unsigned char *ptr = *output_ptr; @@ -523,7 +523,7 @@ int per_insert_most_sign_bits(int no_bits, unsigned char val, return ASN1_OK; } -int per_insert_least_sign_bits(int no_bits, unsigned char val, +static int per_insert_least_sign_bits(int no_bits, unsigned char val, unsigned char **output_ptr, int *unused) { unsigned char *ptr = *output_ptr; int ret = 0; @@ -552,7 +552,7 @@ int per_insert_least_sign_bits(int no_bits, unsigned char val, /* per_pad_bits adds no_bits bits in the buffer that output_ptr points at. */ -int per_pad_bits(int no_bits, unsigned char **output_ptr, int *unused) { +static int per_pad_bits(int no_bits, unsigned char **output_ptr, int *unused) { unsigned char *ptr = *output_ptr; int ret = 0; @@ -575,7 +575,7 @@ int per_pad_bits(int no_bits, unsigned char **output_ptr, int *unused) { The unused parameter tells how many bits that are not set in the actual byte in the output buffer. If desired_no is more bits than the input buffer has in no_bytes bytes, then zero bits is padded.*/ -int per_insert_bits_as_bits(int desired_no, int no_bytes, +static int per_insert_bits_as_bits(int desired_no, int no_bytes, unsigned char **input_ptr, unsigned char **output_ptr, int *unused) { unsigned char *in_ptr = *input_ptr; unsigned char val; @@ -615,7 +615,7 @@ int per_insert_bits_as_bits(int desired_no, int no_bytes, } /* per_insert_octets_as_bits_exact_len */ -int per_insert_octets_as_bits_exact_len(int desired_len, int in_buff_len, +static int per_insert_octets_as_bits_exact_len(int desired_len, int in_buff_len, unsigned char **in_ptr, unsigned char **ptr, int *unused) { int ret = 0; int ret2 = 0; @@ -653,7 +653,7 @@ int per_insert_octets_as_bits_exact_len(int desired_len, int in_buff_len, otherwise the function returns ASN1_ERROR. The output buffer is concatenated without alignment. */ -int per_insert_octets_as_bits(int no_bytes, unsigned char **input_ptr, +static int per_insert_octets_as_bits(int no_bytes, unsigned char **input_ptr, unsigned char **output_ptr, int *unused) { unsigned char *in_ptr = *input_ptr; unsigned char *ptr = *output_ptr; @@ -693,7 +693,7 @@ int per_insert_octets_as_bits(int no_bytes, unsigned char **input_ptr, into the output buffer, *output_ptr. Before the first byte is inserted the input buffer is aligned. */ -int per_insert_octets(int no_bytes, unsigned char **input_ptr, +static int per_insert_octets(int no_bytes, unsigned char **input_ptr, unsigned char **output_ptr, int *unused) { unsigned char *in_ptr = *input_ptr; unsigned char *ptr = *output_ptr; @@ -718,7 +718,7 @@ int per_insert_octets(int no_bytes, unsigned char **input_ptr, /* per_insert_octets_unaligned inserts bytes from the input buffer, *input_ptr, into the output buffer, *output_ptr.No alignment is done. */ -int per_insert_octets_unaligned(int no_bytes, unsigned char **input_ptr, +static int per_insert_octets_unaligned(int no_bytes, unsigned char **input_ptr, unsigned char **output_ptr, int unused) { unsigned char *in_ptr = *input_ptr; unsigned char *ptr = *output_ptr; @@ -742,7 +742,7 @@ int per_insert_octets_unaligned(int no_bytes, unsigned char **input_ptr, return no_bytes; } -int per_insert_octets_except_unused(int no_bytes, unsigned char **input_ptr, +static int per_insert_octets_except_unused(int no_bytes, unsigned char **input_ptr, unsigned char **output_ptr, int *unused, int in_unused) { unsigned char *in_ptr = *input_ptr; unsigned char *ptr = *output_ptr; @@ -835,7 +835,7 @@ int per_insert_octets_except_unused(int no_bytes, unsigned char **input_ptr, * is the empty binary. * If some error occured during the decoding of the in_buf an error is returned. */ -int ber_decode_begin(ErlNifEnv* env, ERL_NIF_TERM *term, unsigned char *in_buf, +static int ber_decode_begin(ErlNifEnv* env, ERL_NIF_TERM *term, unsigned char *in_buf, int in_buf_len, unsigned int *err_pos) { int maybe_ret; int ib_index = 0; @@ -857,7 +857,7 @@ int ber_decode_begin(ErlNifEnv* env, ERL_NIF_TERM *term, unsigned char *in_buf, return ASN1_OK; } -int ber_decode(ErlNifEnv* env, ERL_NIF_TERM *term, unsigned char *in_buf, +static int ber_decode(ErlNifEnv* env, ERL_NIF_TERM *term, unsigned char *in_buf, int *ib_index, int in_buf_len) { int maybe_ret; int form; @@ -889,7 +889,7 @@ int ber_decode(ErlNifEnv* env, ERL_NIF_TERM *term, unsigned char *in_buf, * decode_tag decodes the BER encoded tag in in_buf and creates an * nif term tag */ -int ber_decode_tag(ErlNifEnv* env, ERL_NIF_TERM *tag, unsigned char *in_buf, +static int ber_decode_tag(ErlNifEnv* env, ERL_NIF_TERM *tag, unsigned char *in_buf, int in_buf_len, int *ib_index) { int tag_no, tmp_tag, form; @@ -936,7 +936,7 @@ int ber_decode_tag(ErlNifEnv* env, ERL_NIF_TERM *tag, unsigned char *in_buf, * in_buf and puts the value part in the decode_buf as an Erlang * nif term into value */ -int ber_decode_value(ErlNifEnv* env, ERL_NIF_TERM *value, unsigned char *in_buf, +static int ber_decode_value(ErlNifEnv* env, ERL_NIF_TERM *value, unsigned char *in_buf, int *ib_index, int form, int in_buf_len) { int maybe_ret; unsigned int len = 0; @@ -1012,7 +1012,7 @@ struct ber_encode_mem_chunk { char *curr; }; -int ber_encode(ErlNifEnv *env, ERL_NIF_TERM term, mem_chunk_t **curr, unsigned int *count) { +static int ber_encode(ErlNifEnv *env, ERL_NIF_TERM term, mem_chunk_t **curr, unsigned int *count) { const ERL_NIF_TERM *tv; unsigned int form; @@ -1087,7 +1087,7 @@ int ber_encode(ErlNifEnv *env, ERL_NIF_TERM term, mem_chunk_t **curr, unsigned i return ASN1_OK; } -int ber_encode_tag(ErlNifEnv *env, ERL_NIF_TERM tag, unsigned int form, +static int ber_encode_tag(ErlNifEnv *env, ERL_NIF_TERM tag, unsigned int form, mem_chunk_t **curr, unsigned int *count) { unsigned int class_tag_no, head_tag; if (!enif_get_uint(env, tag, &class_tag_no)) @@ -1122,7 +1122,7 @@ int ber_encode_tag(ErlNifEnv *env, ERL_NIF_TERM tag, unsigned int form, } } -int ber_encode_length(size_t size, mem_chunk_t **curr, unsigned int *count) { +static int ber_encode_length(size_t size, mem_chunk_t **curr, unsigned int *count) { if (size < 128) { if (ber_check_memory(curr, 1u)) return ASN1_ERROR; @@ -1150,7 +1150,7 @@ int ber_encode_length(size_t size, mem_chunk_t **curr, unsigned int *count) { return ASN1_OK; } -mem_chunk_t *ber_new_chunk(unsigned int length) { +static mem_chunk_t *ber_new_chunk(unsigned int length) { mem_chunk_t *new = enif_alloc(sizeof(mem_chunk_t)); if (new == NULL) return NULL; @@ -1165,7 +1165,7 @@ mem_chunk_t *ber_new_chunk(unsigned int length) { return new; } -void ber_free_chunks(mem_chunk_t *chunk) { +static void ber_free_chunks(mem_chunk_t *chunk) { mem_chunk_t *curr, *next = chunk; while (next != NULL) { curr = next; @@ -1175,7 +1175,7 @@ void ber_free_chunks(mem_chunk_t *chunk) { } } -int ber_check_memory(mem_chunk_t **curr, unsigned int needed) { +static int ber_check_memory(mem_chunk_t **curr, unsigned int needed) { mem_chunk_t *new; if ((*curr)->curr-needed >= (*curr)->top) return ASN1_OK; @@ -1320,6 +1320,7 @@ static void unload(ErlNifEnv* env, void* priv_data) { } + static ErlNifFunc nif_funcs[] = { { "encode_per_complete", 1, encode_per_complete }, { "decode_ber_tlv_raw", 1, decode_ber_tlv_raw }, diff --git a/lib/asn1/doc/src/asn1_spec.xmlsrc b/lib/asn1/doc/src/asn1_spec.xmlsrc index 07cba17816..9001aca65c 100644 --- a/lib/asn1/doc/src/asn1_spec.xmlsrc +++ b/lib/asn1/doc/src/asn1_spec.xmlsrc @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> <header> <copyright> - <year>2003</year><year>2011</year> + <year>2003</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/asn1/doc/src/asn1_ug.xml b/lib/asn1/doc/src/asn1_ug.xml index 362ca9330f..ee54fdffd7 100644 --- a/lib/asn1/doc/src/asn1_ug.xml +++ b/lib/asn1/doc/src/asn1_ug.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> @@ -205,16 +205,13 @@ ok is saved in the <c>People.asn1db</c> file, the generated Erlang code is compiled using the Erlang compiler and loaded into the Erlang runtime system. Now there is a user interface - of encode/2 and decode/2 in the module People, which is invoked by: + for <c>encode/2</c> and <c>decode/2</c> in the module People, + which is invoked by: <br></br> <c><![CDATA['People':encode(<Type name>,<Value>),]]></c> <br></br> or <br></br> -<c><![CDATA['People':decode(<Type name>,<Value>),]]></c> <br></br> - - Alternatively one can use the <c><![CDATA[asn1rt:encode(<Module name> ,<Type name>,<Value>)]]></c> and <c><![CDATA[asn1rt:decode(< Module name>,<Type name>,<Value>)]]></c> calls. - However, they are not as efficient as the previous methods since they - result in an additional <c>apply/3</c> call.</p> +<c><![CDATA['People':decode(<Type name>,<Value>),]]></c></p> <p>Assume there is a network application which receives instances of the ASN.1 defined type Person, modifies and sends them back again:</p> @@ -241,16 +238,14 @@ receive encoding-rules. <br></br> The encoder and the decoder can also be run from - the shell. The following dialogue with the shell illustrates - how the functions - <c>asn1rt:encode/3</c> and <c>asn1rt:decode/3</c> are used.</p> + the shell.</p> <pre> 2> <input>Rockstar = {'Person',"Some Name",roving,50}.</input> {'Person',"Some Name",roving,50} -3> <input>{ok,Bin} = asn1rt:encode('People','Person',Rockstar).</input> +3> <input>{ok,Bin} = 'People':encode('Person',Rockstar).</input> {ok,<<243,17,19,9,83,111,109,101,32,78,97,109,101,2,1,2, 2,1,50>>} -4> <input>{ok,Person} = asn1rt:decode('People','Person',Bin).</input> +4> <input>{ok,Person} = 'People':decode('Person',Bin).</input> {ok,{'Person',"Some Name",roving,50}} 5> </pre> </section> @@ -279,11 +274,8 @@ The encoder and the decoder can also be run from (including the compiler).</p> </item> <item> - <p>The module <c>asn1rt</c> which provides the run-time functions. - However, it is preferable to use the generated <c>encode/2</c> and - <c>decode/2</c> functions in each module, ie. - Module:encode(Type,Value), in favor of the <c>asn1rt</c> - interface.</p> + <p>The module <c>asn1rt_nif</c> which provides the run-time functions + for the ASN.1 decoder for the BER back-end.</p> </item> </list> <p>The reason for the division of the interface into compile-time @@ -384,25 +376,9 @@ asn1ct:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre> <section> <title>Run-time Functions</title> - <p>A brief description of the major functions is given here. For a - complete description of each function see - <seealso marker="asn1rt"> the Asn1 Reference Manual</seealso>, the <c>asn1rt</c> module.</p> - <p>The generic run-time encode and decode functions can be invoked as below:</p> - <pre> -asn1rt:encode('H323-MESSAGES','SomeChoiceType',{call,"octetstring"}). -asn1rt:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre> - <p>Or, preferable like:</p> - <pre> -'H323-MESSAGES':encode('SomeChoiceType',{call,"octetstring"}). -'H323-MESSAGES':decode('SomeChoiceType',Bytes). </pre> - <p>The asn1 nif is enabled in two occasions: encoding of - asn1 values when the asn1 spec is compiled with <c>per</c> and - or decode of encoded asn1 values when the asn1 spec is - compiled with <c>ber</c>. In - those cases the nif will be loaded automatically at the first call - to <c>encode</c>/<c>decode</c>. If one doesn't want the performance - overhead of the nif being loaded at the first call it is possible - to load the nif separately by loading the <c>asn1rt_nif</c> module.</p> + <p>When an ASN.1 specification is compiled with the <c>ber</c> + option, the module <c>asn1rt_nif</c> module and the NIF library in + <c>asn1/priv_dir</c> will be needed at run-time.</p> <p>By invoking the function <c>info/0</c> in a generated module, one gets information about which compiler options were used.</p> </section> @@ -414,8 +390,8 @@ asn1rt:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre> a line number indicating where in the source file the error was detected. If no errors are found, an Erlang ASN.1 module will be created as default.</p> - <p>The run-time encoders and decoders (in the <c>asn1rt</c> module) do - execute within a catch and returns <c>{ok, Data}</c> or + <p>The run-time encoders and decoders execute within a catch and + returns <c>{ok, Data}</c> or <c>{error, {asn1, Description}}</c> where <c>Description</c> is an Erlang term describing the error. </p> @@ -653,7 +629,7 @@ Day1 = saturday, Bits1 ::= BIT STRING Bits2 ::= BIT STRING {foo(0),bar(1),gnu(2),gnome(3),punk(14)} </pre> - <p>There are five different notations available for representation of + <p>There are two notations available for representation of BIT STRING values in Erlang and as input to the encode functions.</p> <list type="ordered"> <item>A bitstring. By default, a BIT STRING with no @@ -661,43 +637,10 @@ Bits2 ::= BIT STRING {foo(0),bar(1),gnu(2),gnome(3),punk(14)} <item>A list of atoms corresponding to atoms in the <c>NamedBitList</c> in the BIT STRING definition. A BIT STRING with symbolic names will always be decoded to this format.</item> - <item>A list of binary digits (0 or 1). This format is always - accepted as input to the encode functions. A BIT STRING will - be decoded to this format if <em>legacy_bit_string</em> option - has been given. <em>This format may be withdrawn in a future - release.</em> - </item> - <item>As <c>{Unused,Binary}</c> where <c>Unused</c> denotes how - many trailing zero-bits 0 to 7 that are unused in the least - significant byte in <c>Binary</c>. This format is always - accepted as input to the encode functions. A BIT STRING will - be decoded to this format if <em>compact_bit_string</em> has - been given. <em>This format may be withdrawn in a future - release.</em> - </item> - <item>A hexadecimal number (or an integer). This format should be - avoided, since it is easy to misinterpret a <c>BIT STRING</c> - value in this format. <em>This format may be withdrawn in a future - release.</em> - </item> </list> - <note> - <p>It is recommended to either use the bitstring format (for - BIT STRINGs with no symbolic names) or a list of symbolic - names (for BIT STRINGs with symbolic names). The other formats - should be avoided since they may be withdrawn in a future - release. - </p> - </note> + <p>Example:</p> <pre> Bits1Val1 = <<0:1,1:1,0:1,1:1,1:1>>, -Bits1Val2 = 16#1A, -Bits1Val3 = {3,<<0:1,1:1,0:1,1:1,1:1,0:3>>}, -Bits1Val4 = [0,1,0,1,1] - </pre> - <p>Note that <c>Bits1Val1</c>, <c>Bits1Val2</c>, <c>Bits1Val3</c>, - and <c>Bits1Val1</c> denote the same value.</p> - <pre> Bits2Val1 = [gnu,punk], Bits2Val2 = <<2#1110:4>>, Bits2Val3 = [bar,gnu,gnome], @@ -708,37 +651,60 @@ Bits2Val3 = [bar,gnu,gnome], 2 and 14 are set to 1 and the rest set to 0. The symbolic values appear as a list of values. If a named value appears, which is not specified in the type definition, a run-time error will occur.</p> - <p>The compact notation equivalent to the empty BIT STRING is - <c><![CDATA[{0,<<>>}]]></c>, which in the other notations is - <c><![CDATA[<<>>]]></c>, <c>[]</c>, or - <c>0</c>.</p> <p>BIT STRINGS may also be sub-typed with, for example, a SIZE specification:</p> <pre> Bits3 ::= BIT STRING (SIZE(0..31)) </pre> <p>This means that no bit higher than 31 can ever be set.</p> + + <section> + <title>Deprecated representations for BIT STRING</title> + <p>In addition to the representations described above, the + following deprecated representations are available if the + specification has been compiled with the + <c>legacy_erlang_types</c> option:</p> + <list type="ordered"> + <item>A list of binary digits (0 or 1). This format is + accepted as input to the encode functions, and a BIT STRING + will be decoded to this format if the + <em>legacy_bit_string</em> option has been given. + </item> + <item>As <c>{Unused,Binary}</c> where <c>Unused</c> denotes + how many trailing zero-bits 0 to 7 that are unused in the + least significant byte in <c>Binary</c>. This format is + accepted as input to the encode functions, and a <c>BIT + STRING</c> will be decoded to this format if + <em>compact_bit_string</em> has been given. + </item> + <item>A hexadecimal number (or an integer). This format + should be avoided, since it is easy to misinterpret a BIT + STRING value in this format. + </item> + </list> + </section> </section> <section> <marker id="OCTET STRING"></marker> <title>OCTET STRING</title> - <p>The OCTET STRING is the simplest of all ASN.1 types The OCTET STRING - only moves or transfers e.g. binary files or other unstructured - information complying to two rules. - Firstly, the bytes consist of octets and secondly, encoding is - not required.</p> + <p>The OCTET STRING is the simplest of all ASN.1 types. The + OCTET STRING only moves or transfers e.g. binary files or other + unstructured information complying to two rules. Firstly, the + bytes consist of octets and secondly, encoding is not + required.</p> <p>It is possible to have the following ASN.1 type definitions:</p> <pre> O1 ::= OCTET STRING O2 ::= OCTET STRING (SIZE(28)) </pre> <p>With the following example assignments in Erlang:</p> <pre> -O1Val = [17,13,19,20,0,0,255,254], -O2Val = "must be exactly 28 chars....", </pre> - <p>Observe that <c>O1Val</c> is assigned a series of numbers between 0 - and 255 i.e. octets. - <c>O2Val</c> is assigned using the string notation. - </p> +O1Val = <<17,13,19,20,0,0,255,254>>, +O2Val = <<"must be exactly 28 chars....">>,</pre> + <p>By default, an OCTET STRING is always represented as + an Erlang binary. If the specification has been compiled with + the <c>legacy_erlang_types</c> option, the encode functions + will accept both lists and binaries, and the decode functions + will decode an OCTET STRING to a list.</p> </section> <section> diff --git a/lib/asn1/doc/src/asn1ct.xml b/lib/asn1/doc/src/asn1ct.xml index fcd77e9dc6..4d5a1a402a 100644 --- a/lib/asn1/doc/src/asn1ct.xml +++ b/lib/asn1/doc/src/asn1ct.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> @@ -42,6 +42,17 @@ can be used in during development of applications which handles ASN.1 data (encoded as BER or PER).</p> <note> + <p>By default in OTP 17, the representation of the BIT STRING + and OCTET STRING types as Erlang terms have changed. BIT + STRING values are now Erlang bitstrings and OCTET STRING values + are binaries. For details see <seealso + marker="asn1_ug#BIT STRING">BIT STRING</seealso> and <seealso + marker="asn1_ug#OCTET STRING">OCTET STRING</seealso> in User's + Guide.</p> + <p>To revert to the old representation of the types, use the + <c>legacy_erlang_types</c> option.</p> + </note> + <note> <p>In R16, the options have been simplified. The back-end is chosen using one of the options <c>ber</c>, <c>per</c>, or <c>uper</c>. The options <c>optimize</c>, <c>nif</c>, and <c>driver</c> options @@ -50,7 +61,7 @@ and <c>uper_bin</c> options will still work, but will print a warning. </p> <p>Another change in R16 is that the generated <c>encode/2</c> - function (and <c>asn1rt:encode/3</c>) always returns a binary. + function always returns a binary. The <c>encode/2</c> function for the BER back-end used to return an iolist.</p> </note> @@ -64,7 +75,7 @@ <v>Asn1module = atom() | string()</v> <v>Options = [Option| OldOption]</v> <v>Option = ber | per | uper | der | compact_bit_string | - legacy_bit_string | + legacy_bit_string | legacy_erlang_types | noobj | {n2n, EnumTypeName} |{outdir, Dir} | {i, IncludeDir} | asn1config | undec_rest | no_ok_wrapper | {macro_name_prefix, Prefix} | {record_name_prefix, Prefix} | verbose | warnings_as_errors</v> @@ -163,6 +174,7 @@ File3.asn </pre> BIT STRING type section in the Users Guide </seealso>. </p> + <p>This option implies the <c>legacy_erlang_types</c> option.</p> </item> <tag><c>legacy_bit_string</c></tag> <item> @@ -175,8 +187,19 @@ File3.asn </pre> <seealso marker="asn1_ug#BIT STRING"> BIT STRING type section in the Users Guide </seealso>. + <p>This option implies the <c>legacy_erlang_types</c> option.</p> </p> </item> + <tag><c>legacy_erlang_types</c></tag> + <item> + <p>Use the same Erlang types to represent BIT STRING and + OCTET STRING as in R16. For details see <seealso + marker="asn1_ug#BIT STRING">BIT STRING</seealso> and + <seealso marker="asn1_ug#OCTET STRING">OCTET + STRING</seealso> in User's Guide.</p> + <p><em>This option is not recommended for + new code.</em></p> + </item> <tag><c>{n2n, EnumTypeName}</c></tag> <item> <p> @@ -303,6 +326,8 @@ File3.asn </pre> not always checked. Returns <c>{ok, Bytes}</c> if successful or <c>{error, Reason}</c> if an error occurred. </p> + <p>This function is deprecated. + Use <c>Module:encode(Type, Value)</c> instead.</p> </desc> </func> <func> @@ -316,6 +341,8 @@ File3.asn </pre> <desc> <p>Decodes <c>Type</c> from <c>Module</c> from the binary <c>Bytes</c>. Returns <c>{ok, Value}</c> if successful.</p> + <p>This function is deprecated. + Use <c>Module:decode(Type, Bytes)</c> instead.</p> </desc> </func> <func> diff --git a/lib/asn1/doc/src/asn1rt.xml b/lib/asn1/doc/src/asn1rt.xml index 2b1b108ab1..3cf56b01ca 100644 --- a/lib/asn1/doc/src/asn1rt.xml +++ b/lib/asn1/doc/src/asn1rt.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> @@ -34,9 +34,12 @@ <module>asn1rt</module> <modulesummary>ASN.1 runtime support functions</modulesummary> <description> - <p>This module is the interface module for the ASN.1 runtime support functions. - To encode and decode ASN.1 types in runtime the functions in this module - should be used.</p> + <warning> + <p> + All functions in this module are deprecated and will be + removed in a future release. + </p> + </warning> </description> <funcs> @@ -52,6 +55,7 @@ <desc> <p>Decodes <c>Type</c> from <c>Module</c> from the binary <c>Bytes</c>. Returns <c>{ok,Value}</c> if successful.</p> + <p>Use <c>Module:decode(Type, Bytes)</c> instead of this function.</p> </desc> </func> @@ -65,16 +69,13 @@ <v>Reason = term()</v> </type> <desc> - <p>Encodes <c>Value</c> of <c>Type</c> defined in the ASN.1 module - <c>Module</c>. Returns a possibly nested list of bytes and or binaries - if successful. To get as fast execution as possible the - encode function only performs rudimentary tests that the input - <c>Value</c> - is a correct instance of <c>Type</c>. The length of strings is for example - not always checked. </p> - <note> - <p>Starting in R16, <c>Bytes</c> is always a binary.</p> - </note> + <p>Encodes <c>Value</c> of <c>Type</c> defined in the ASN.1 + module <c>Module</c>. Returns a binary if successful. To get + as fast execution as possible the encode function only + performs rudimentary tests that the input <c>Value</c> is a + correct instance of <c>Type</c>. The length of strings is, for + example, not always checked. </p> + <p>Use <c>Module:encode(Type, Value)</c> instead of this function.</p> </desc> </func> @@ -90,6 +91,7 @@ <p><c>info/1</c> returns the version of the asn1 compiler that was used to compile the module. It also returns the compiler options that was used.</p> + <p>Use <c>Module:info()</c> instead of this function.</p> </desc> </func> @@ -106,6 +108,7 @@ to a list of integers, where each integer represents one character as its unicode value. The function fails if the binary is not a properly encoded UTF8 string.</p> + <p>Use <seealso marker="stdlib:unicode#characters_to_list-1">unicode:characters_to_list/1</seealso> instead of this function.</p> </desc> </func> @@ -121,6 +124,7 @@ <p><c>utf8_list_to_binary/1</c> Transforms a list of integers, where each integer represents one character as its unicode value, to a UTF8 encoded binary.</p> + <p>Use <seealso marker="stdlib:unicode#characters_to_binary-1">unicode:characters_to_binary/1</seealso> instead of this function.</p> </desc> </func> diff --git a/lib/asn1/doc/src/book.xml b/lib/asn1/doc/src/book.xml index 718e6e7b17..2399267cb0 100644 --- a/lib/asn1/doc/src/book.xml +++ b/lib/asn1/doc/src/book.xml @@ -1,11 +1,11 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE book SYSTEM "book.dtd"> <book xmlns:xi="http://www.w3.org/2001/XInclude"> <header titlestyle="normal"> <copyright> - <year>1997</year><year>2009</year> + <year>1997</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/asn1/doc/src/fascicules.xml b/lib/asn1/doc/src/fascicules.xml index 2488e7b57e..837b4f57f4 100644 --- a/lib/asn1/doc/src/fascicules.xml +++ b/lib/asn1/doc/src/fascicules.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE fascicules SYSTEM "fascicules.dtd"> <fascicules> diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml index a00fc3de36..ff7962edd9 100644 --- a/lib/asn1/doc/src/notes.xml +++ b/lib/asn1/doc/src/notes.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> diff --git a/lib/asn1/doc/src/part.xml b/lib/asn1/doc/src/part.xml index 19ee64b4a0..735ec2e616 100644 --- a/lib/asn1/doc/src/part.xml +++ b/lib/asn1/doc/src/part.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE part SYSTEM "part.dtd"> <part xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>1997</year><year>2009</year> + <year>1997</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/asn1/doc/src/ref_man.xml b/lib/asn1/doc/src/ref_man.xml index a0af1f5be3..0a0ed5416a 100644 --- a/lib/asn1/doc/src/ref_man.xml +++ b/lib/asn1/doc/src/ref_man.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE application SYSTEM "application.dtd"> <application xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>1997</year><year>2009</year> + <year>1997</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/asn1/src/asn1.app.src b/lib/asn1/src/asn1.app.src index f2ee8deb75..02cbba0f10 100644 --- a/lib/asn1/src/asn1.app.src +++ b/lib/asn1/src/asn1.app.src @@ -10,5 +10,6 @@ asn1db ]}, {env, []}, - {applications, [kernel, stdlib]} + {applications, [kernel, stdlib]}, + {runtime_dependencies, ["stdlib-2.0","kernel-3.0","erts-6.0"]} ]}. diff --git a/lib/asn1/src/asn1.appup.src b/lib/asn1/src/asn1.appup.src index 2d11eddfbf..e4b3508cc4 100644 --- a/lib/asn1/src/asn1.appup.src +++ b/lib/asn1/src/asn1.appup.src @@ -1,11 +1,21 @@ +%% -*- erlang -*- +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2014. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% {"%VSN%", -% This version does not change anything of the runtime modules -% Only changes in compile time modules and thus no need for upgrade on target -[ - ], - [ - ]}. - - - - + [{<<".*">>,[{restart_application, asn1}]}], + [{<<".*">>,[{restart_application, asn1}]}] +}. diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl index f2ccf5f212..8470e5a1b4 100644 --- a/lib/asn1/src/asn1ct.erl +++ b/lib/asn1/src/asn1ct.erl @@ -19,6 +19,10 @@ %% %% -module(asn1ct). +-deprecated([decode/3,encode/3]). +-compile([{nowarn_deprecated_function,{asn1rt,decode,3}}, + {nowarn_deprecated_function,{asn1rt,encode,2}}, + {nowarn_deprecated_function,{asn1rt,encode,3}}]). %% Compile Time functions for ASN.1 (e.g ASN.1 compiler). @@ -40,7 +44,7 @@ maybe_rename_function/3,current_sindex/0, set_current_sindex/1,maybe_saved_sindex/2, parse_and_save/2,verbose/3,warning/3,warning/4,error/3]). --export([get_bit_string_format/0]). +-export([get_bit_string_format/0,use_legacy_types/0]). -include("asn1_records.hrl"). -include_lib("stdlib/include/erl_compile.hrl"). @@ -333,8 +337,7 @@ print_structured_errors([_|_]=Errors) -> print_structured_errors(_) -> ok. compile1(File, #st{opts=Opts}=St0) -> - verbose("Erlang ASN.1 version ~p, compiling ~p~n", [?vsn,File], Opts), - verbose("Compiler Options: ~p~n", [Opts], Opts), + compiler_verbose(File, Opts), Passes = single_passes(), Base = filename:rootname(filename:basename(File)), OutFile = outfile(Base, "", Opts), @@ -349,8 +352,7 @@ compile1(File, #st{opts=Opts}=St0) -> %% compile_set/3 merges and compiles a number of asn1 modules %% specified in a .set.asn file to one .erl file. compile_set(SetBase, Files, #st{opts=Opts}=St0) -> - verbose("Erlang ASN.1 version ~p compiling ~p ~n", [?vsn,Files], Opts), - verbose("Compiler Options: ~p~n",[Opts], Opts), + compiler_verbose(Files, Opts), OutFile = outfile(SetBase, "", Opts), DbFile = outfile(SetBase, "asn1db", Opts), InputModules = [begin @@ -363,6 +365,11 @@ compile_set(SetBase, Files, #st{opts=Opts}=St0) -> Passes = set_passes(), run_passes(Passes, St). +compiler_verbose(What, Opts) -> + verbose("Erlang ASN.1 compiler ~s\n", [?vsn], Opts), + verbose("Compiling: ~p\n", [What], Opts), + verbose("Options: ~p\n", [Opts], Opts). + %% merge_modules/2 -> returns a module record where the typeorval lists are merged, %% the exports lists are merged, the imports lists are merged when the %% elements come from other modules than the merge set, the tagdefault @@ -559,6 +566,8 @@ get_pos_of_def(#pobjectdef{pos=Pos}) -> Pos; get_pos_of_def(#pobjectsetdef{pos=Pos}) -> Pos; +get_pos_of_def(#'Externaltypereference'{pos=Pos}) -> + Pos; get_pos_of_def(#'Externalvaluereference'{pos=Pos}) -> Pos; get_pos_of_def(_) -> @@ -838,6 +847,7 @@ delete_double_of_symbol1([],Acc) -> generate({M,GenTOrV}, OutFile, EncodingRule, Options) -> debug_on(Options), setup_bit_string_format(Options), + setup_legacy_erlang_types(Options), put(encoding_options,Options), asn1ct_table:new(check_functions), @@ -866,6 +876,31 @@ generate({M,GenTOrV}, OutFile, EncodingRule, Options) -> asn1ct_table:delete(check_functions), Result. +setup_legacy_erlang_types(Opts) -> + F = case lists:member(legacy_erlang_types, Opts) of + false -> + case get_bit_string_format() of + bitstring -> + false; + compact -> + legacy_forced_info(compact_bit_string), + true; + legacy -> + legacy_forced_info(legacy_bit_string), + true + end; + true -> + true + end, + put(use_legacy_erlang_types, F). + +legacy_forced_info(Opt) -> + io:format("Info: The option 'legacy_erlang_types' " + "is implied by the '~s' option.\n", [Opt]). + +use_legacy_types() -> + get(use_legacy_erlang_types). + setup_bit_string_format(Opts) -> Format = case {lists:member(compact_bit_string, Opts), lists:member(legacy_bit_string, Opts)} of @@ -1011,7 +1046,7 @@ get_file_list1(Stream,Dir,Includes,Acc) -> Ret = io:get_line(Stream,''), case Ret of eof -> - file:close(Stream), + ok = file:close(Stream), lists:reverse(Acc); FileName -> SuffixedNameList = @@ -1072,6 +1107,7 @@ remove_asn_flags(Options) -> X /= optimize, X /= compact_bit_string, X /= legacy_bit_string, + X /= legacy_erlang_types, X /= debug, X /= asn1config, X /= record_name_prefix]. @@ -1896,8 +1932,9 @@ read_config_file(ModuleName) -> Includes = [I || {i,I} <- Options], read_config_file1(ModuleName,Includes); {error,Reason} -> - file:format_error(Reason), - throw({error,{"error reading asn1 config file",Reason}}) + Error = "error reading asn1 config file: " ++ + file:format_error(Reason), + throw({error,Error}) end. read_config_file1(ModuleName,[]) -> case filename:extension(ModuleName) of @@ -1915,8 +1952,9 @@ read_config_file1(ModuleName,[H|T]) -> {error,enoent} -> read_config_file1(ModuleName,T); {error,Reason} -> - file:format_error(Reason), - throw({error,{"error reading asn1 config file",Reason}}) + Error = "error reading asn1 config file: " ++ + file:format_error(Reason), + throw({error,Error}) end. get_config_info(CfgList,InfoType) -> diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl index 0a13801e08..e788aa5c6c 100644 --- a/lib/asn1/src/asn1ct_check.erl +++ b/lib/asn1/src/asn1ct_check.erl @@ -270,46 +270,30 @@ check_exports(S,Module = #module{}) -> end end. -check_imports(S,Module = #module{ }) -> - case Module#module.imports of - {imports,[]} -> - []; - {imports,ImportList} when is_list(ImportList) -> - check_imports2(S,ImportList,[]); - _ -> - [] - end. -check_imports2(_S,[],Acc) -> +check_imports(S, #module{imports={imports,Imports}}) -> + check_imports_1(S, Imports, []). + +check_imports_1(_S, [], Acc) -> Acc; -check_imports2(S,[#'SymbolsFromModule'{symbols=Imports,module=ModuleRef}|SFMs],Acc) -> - NameOfDef = - fun(#'Externaltypereference'{type=N}) -> N; - (#'Externalvaluereference'{value=N}) -> N - end, - Module = NameOfDef(ModuleRef), - Refs = [{M,R}||{{M,_},R} <- [{catch get_referenced_type(S,Ref),Ref}||Ref <- Imports]], - {Illegal,Other} = lists:splitwith(fun({error,_}) -> true;(_) -> false end, - Refs), - ChainedRefs = [R||{M,R} <- Other, M =/= Module], - IllegalRefs = [R||{error,R} <- Illegal] ++ - [R||{M,R} <- ChainedRefs, - ok =/= chained_import(S,Module,M,NameOfDef(R))], - ReportError = - fun(Ref) -> - NewS=S#state{type=Ref,tname=NameOfDef(Ref)}, - error({import,"imported undefined entity",NewS}) - end, - check_imports2(S,SFMs,[ReportError(Err)||Err <- IllegalRefs]++Acc). +check_imports_1(S, [#'SymbolsFromModule'{symbols=Imports,module=ModuleRef}|SFMs], Acc0) -> + Module = name_of_def(ModuleRef), + Refs0 = [{catch get_referenced_type(S, Ref),Ref} || Ref <- Imports], + Refs = [{M,R} || {{M,_},R} <- Refs0], + {Illegal,Other} = lists:splitwith(fun({error,_}) -> true; + (_) -> false + end, Refs), + ChainedRefs = [R || {M,R} <- Other, M =/= Module], + IllegalRefs = [R || {error,R} <- Illegal] ++ + [R || {M,R} <- ChainedRefs, + ok =/= chained_import(S, Module, M, name_of_def(R))], + Acc = [return_asn1_error(S, Ref, {undefined_import,name_of_def(Ref),Module}) || + Ref <- IllegalRefs] ++ Acc0, + check_imports_1(S, SFMs, Acc). chained_import(S,ImpMod,DefMod,Name) -> %% Name is a referenced structure that is not defined in ImpMod, %% but must be present in the Imports list of ImpMod. The chain of %% imports of Name must end in DefMod. - NameOfDef = - fun(#'Externaltypereference'{type=N}) -> N; - (#'Externalvaluereference'{value=N}) -> N; - (Other) -> Other - end, GetImports = fun(_M_) -> case asn1_db:dbget(_M_,'MODULE') of @@ -321,9 +305,9 @@ chained_import(S,ImpMod,DefMod,Name) -> FindNameInImports = fun([],N,_) -> {no_mod,N}; ([#'SymbolsFromModule'{symbols=Imports,module=ModuleRef}|SFMs],N,F) -> - case [NameOfDef(X)||X <- Imports, NameOfDef(X) =:= N] of + case [name_of_def(X) || X <- Imports, name_of_def(X) =:= N] of [] -> F(SFMs,N,F); - [N] -> {NameOfDef(ModuleRef),N} + [N] -> {name_of_def(ModuleRef),N} end end, case GetImports(ImpMod) of @@ -1567,13 +1551,13 @@ check_defaultfields(S, Fields, ClassFields) -> [] -> ok; [_|_]=Invalid -> - throw(asn1_error(S, T, {invalid_fields,Invalid,Obj})) + asn1_error(S, T, {invalid_fields,Invalid,Obj}) end, case ordsets:subtract(Mandatory, Present) of [] -> check_defaultfields_1(S, Fields, ClassFields, []); [_|_]=Missing -> - throw(asn1_error(S, T, {missing_mandatory_fields,Missing,Obj})) + asn1_error(S, T, {missing_mandatory_fields,Missing,Obj}) end. check_defaultfields_1(_S, [], _ClassFields, Acc) -> @@ -2464,7 +2448,7 @@ normalize_value(S0, Type, {'DEFAULT',Value}, NameList) -> {'BIT STRING',CType,_} -> normalize_bitstring(S,Value,CType); {'OCTET STRING',CType,_} -> - normalize_octetstring(S,Value,CType); + normalize_octetstring(S0, Value, CType); {'NULL',_CType,_} -> %%normalize_null(Value); 'NULL'; @@ -2574,6 +2558,18 @@ normalize_bitstring(S, Value, Type)-> Bs end. +hstring_to_binary(L) -> + byte_align(hstring_to_bitstring(L)). + +bstring_to_binary(L) -> + byte_align(bstring_to_bitstring(L)). + +byte_align(Bs) -> + case bit_size(Bs) rem 8 of + 0 -> Bs; + N -> <<Bs/bitstring,0:(8-N)>> + end. + hstring_to_bitstring(L) -> << <<(hex_to_int(D)):4>> || D <- L >>. @@ -2592,59 +2588,19 @@ hex_to_int(D) when $A =< D, D =< $F -> D - ($A - 10). normalize_octetstring(S,Value,CType) -> case Value of {bstring,String} -> - bstring_to_octetlist(String); + bstring_to_binary(String); {hstring,String} -> - hstring_to_octetlist(String); + hstring_to_binary(String); Rec when is_record(Rec,'Externalvaluereference') -> get_normalized_value(S,Value,CType, fun normalize_octetstring/3,[]); {Name,String} when is_atom(Name) -> normalize_octetstring(S,String,CType); - List when is_list(List) -> - %% check if list elements are valid octet values - lists:map(fun([])-> ok; - (H)when H > 255-> - asn1ct:warning("not legal octet value ~p in OCTET STRING, ~p~n", - [H,List],S, - "not legal octet value ~p in OCTET STRING"); - (_)-> ok - end, List), - List; - Other -> - asn1ct:warning("unknown default value ~p~n",[Other],S, - "unknown default value"), - Value + _ -> + Item = S#state.value, + asn1_error(S, Item, illegal_octet_string_value) end. - -bstring_to_octetlist([]) -> - []; -bstring_to_octetlist([H|T]) when H == $0 ; H == $1 -> - bstring_to_octetlist(T,6,[(H - $0) bsl 7]). -bstring_to_octetlist([H|T],0,[Hacc|Tacc]) when H == $0; H == $1 -> - bstring_to_octetlist(T, 7, [0,Hacc + (H -$0)| Tacc]); -bstring_to_octetlist([H|T],BSL,[Hacc|Tacc]) when H == $0; H == $1 -> - bstring_to_octetlist(T, BSL-1, [Hacc + ((H - $0) bsl BSL)| Tacc]); -bstring_to_octetlist([],7,[0|Acc]) -> - lists:reverse(Acc); -bstring_to_octetlist([],_,Acc) -> - lists:reverse(Acc). - -hstring_to_octetlist([]) -> - []; -hstring_to_octetlist(L) -> - hstring_to_octetlist(L,4,[]). -hstring_to_octetlist([H|T],0,[Hacc|Tacc]) when H >= $A, H =< $F -> - hstring_to_octetlist(T,4,[Hacc + (H - $A + 10)|Tacc]); -hstring_to_octetlist([H|T],BSL,Acc) when H >= $A, H =< $F -> - hstring_to_octetlist(T,0,[(H - $A + 10) bsl BSL|Acc]); -hstring_to_octetlist([H|T],0,[Hacc|Tacc]) when H >= $0; H =< $9 -> - hstring_to_octetlist(T,4,[Hacc + (H - $0)|Tacc]); -hstring_to_octetlist([H|T],BSL,Acc) when H >= $0; H =< $9 -> - hstring_to_octetlist(T,0,[(H - $0) bsl BSL|Acc]); -hstring_to_octetlist([],_,Acc) -> - lists:reverse(Acc). - normalize_objectidentifier(S, Value) -> {ok,Val} = validate_objectidentifier(S, o_id, Value, []), Val. @@ -2659,18 +2615,21 @@ normalize_objectdescriptor(Value) -> normalize_real(Value) -> Value. -normalize_enumerated(S, Id, {Base,Ext}) -> +normalize_enumerated(S, Id0, NNL) -> + {Id,_} = lookup_enum_value(S, Id0, NNL), + Id. + +lookup_enum_value(S, Id, {Base,Ext}) -> %% Extensible ENUMERATED. - normalize_enumerated(S, Id, Base++Ext); -normalize_enumerated(S, #'Externalvaluereference'{value=Id}, - NamedNumberList) -> - normalize_enumerated(S, Id, NamedNumberList); -normalize_enumerated(S, Id, NamedNumberList) when is_atom(Id) -> - case lists:keymember(Id, 1, NamedNumberList) of - true -> - Id; + lookup_enum_value(S, Id, Base++Ext); +lookup_enum_value(S, #'Externalvaluereference'{value=Id}, NNL) -> + lookup_enum_value(S, Id, NNL); +lookup_enum_value(S, Id, NNL) when is_atom(Id) -> + case lists:keyfind(Id, 1, NNL) of + {_,_}=Ret -> + Ret; false -> - throw(asn1_error(S, S#state.value, {undefined,Id})) + asn1_error(S, S#state.value, {undefined,Id}) end. normalize_choice(S,{'CHOICE',{C,V}},CType,NameList) when is_atom(C) -> @@ -3105,12 +3064,11 @@ check_type(S=#state{recordtopname=TopName},Type,Ts) when is_record(Ts,type) -> Ct=maybe_illicit_implicit_tag(open_type,Tag), TempNewDef#newt{type='ASN1_OPEN_TYPE',tag=Ct}; 'INTEGER' -> - check_integer(S,[],Constr), TempNewDef#newt{tag= merge_tags(Tag,?TAG_PRIMITIVE(?N_INTEGER))}; {'INTEGER',NamedNumberList} -> - TempNewDef#newt{type={'INTEGER',check_integer(S,NamedNumberList,Constr)}, + TempNewDef#newt{type={'INTEGER',check_integer(S,NamedNumberList)}, tag= merge_tags(Tag,?TAG_PRIMITIVE(?N_INTEGER))}; 'REAL' -> @@ -3118,8 +3076,7 @@ check_type(S=#state{recordtopname=TopName},Type,Ts) when is_record(Ts,type) -> TempNewDef#newt{tag=merge_tags(Tag,?TAG_PRIMITIVE(?N_REAL))}; {'BIT STRING',NamedNumberList} -> - NewL = check_bitstring(S,NamedNumberList,Constr), -%% erlang:display({asn1ct_check,NamedNumberList,NewL}), + NewL = check_bitstring(S, NamedNumberList), TempNewDef#newt{type={'BIT STRING',NewL}, tag= merge_tags(Tag,?TAG_PRIMITIVE(?N_BIT_STRING))}; @@ -3803,8 +3760,9 @@ resolv_value(S,Val) -> resolv_value1(S,Id). resolv_value1(S, ERef = #'Externalvaluereference'{value=Name}) -> - case catch resolve_namednumber(S,S#state.type,Name) of - V when is_integer(V) -> V; + case catch resolve_namednumber(S, S#state.type, Name) of + V when is_integer(V) -> + V; _ -> case get_referenced_type(S,ERef) of {Err,_Reason} when Err == error; Err == 'EXIT' -> @@ -3857,21 +3815,20 @@ resolve_value_from_object(S,Object,FieldName) -> end. - resolve_namednumber(S,#typedef{typespec=Type},Name) -> case Type#type.def of {'ENUMERATED',NameList} -> - NamedNumberList=check_enumerated(S,NameList,Type#type.constraint), - N = normalize_enumerated(S,Name,NamedNumberList), - {value,{_,V}} = lists:keysearch(N,1,NamedNumberList), - V; + resolve_namednumber_1(S, Name, NameList, Type); {'INTEGER',NameList} -> - NamedNumberList = check_enumerated(S,NameList,Type#type.constraint), - {value,{_,V}} = lists:keysearch(Name,1,NamedNumberList), - V; + resolve_namednumber_1(S, Name, NameList, Type); _ -> not_enumerated end. + +resolve_namednumber_1(S, Name, NameList, Type) -> + NamedNumberList = check_enumerated(S, NameList, Type#type.constraint), + {_,N} = lookup_enum_value(S, Name, NamedNumberList), + N. check_constraints(S,[{'ContainedSubtype',Type} | Rest], Acc) -> {RefMod,CTDef} = get_referenced_type(S,Type#type.def), @@ -3952,9 +3909,9 @@ check_constraint(S,{simpletable,Type}) -> #'Externaltypereference'{} -> ERef = check_externaltypereference(S,C), {simpletable,ERef#'Externaltypereference'.type}; - #type{def=#'Externaltypereference'{type=T}} -> - check_externaltypereference(S,C#type.def), - {simpletable,T}; + #type{def=#'Externaltypereference'{}=ExtTypeRef} -> + ERef = check_externaltypereference(S, ExtTypeRef), + {simpletable,ERef#'Externaltypereference'.type}; {valueset,#type{def=ERef=#'Externaltypereference'{}}} -> % this is an object set {_,TDef} = get_referenced_type(S,ERef), case TDef#typedef.typespec of @@ -4936,73 +4893,46 @@ imported1(Name, end; imported1(_Name,[]) -> false. - -check_integer(_S,[],_C) -> +%% Check the named number list for an INTEGER or a BIT STRING. +check_named_number_list(_S, []) -> []; -check_integer(S,NamedNumberList,_C) -> - case [X || X <- NamedNumberList, tuple_size(X) =:= 2] of - NamedNumberList -> - %% An already checked integer with NamedNumberList - NamedNumberList; - _ -> - case check_unique(NamedNumberList,2) of - [] -> - check_int(S,NamedNumberList,[]); - L when is_list(L) -> - error({type,{duplicates,L},S}), - unchanged - end +check_named_number_list(_S, [{_,_}|_]=NNL) -> + %% The named number list has already been checked. + NNL; +check_named_number_list(S, NNL0) -> + %% Check that the names are unique. + T = S#state.type, + case check_unique(NNL0, 2) of + [] -> + NNL1 = [{Id,resolve_valueref(S, Val)} || {'NamedNumber',Id,Val} <- NNL0], + NNL = lists:keysort(2, NNL1), + case check_unique(NNL, 2) of + [] -> + NNL; + [Val|_] -> + asn1_error(S, T, {value_reused,Val}) + end; + [H|_] -> + asn1_error(S, T, {namelist_redefinition,H}) end. - -check_int(S,[{'NamedNumber',Id,Num}|T],Acc) when is_integer(Num) -> - check_int(S,T,[{Id,Num}|Acc]); -check_int(S,[{'NamedNumber',Id,{identifier,_,Name}}|T],Acc) -> - Val = dbget_ex(S,S#state.mname,Name), - check_int(S,[{'NamedNumber',Id,Val#valuedef.value}|T],Acc); -check_int(S,[{'NamedNumber',Id,{'Externalvaluereference',_,Mod,Name}}|T],Acc) -> - Val = dbget_ex(S,Mod,Name), - check_int(S,[{'NamedNumber',Id,Val#valuedef.value}|T],Acc); -check_int(_S,[],Acc) -> - lists:keysort(2,Acc). +resolve_valueref(S, #'Externalvaluereference'{module=Mod,value=Name}) -> + dbget_ex(S, Mod, Name); +resolve_valueref(_, Val) when is_integer(Val) -> + Val. -check_real(_S,_Constr) -> - ok. +check_integer(S, NNL) -> + check_named_number_list(S, NNL). -check_bitstring(_S,[],_Constr) -> - []; -check_bitstring(S,NamedNumberList,_Constr) -> - case check_unique(NamedNumberList,2) of - [] -> - check_bitstr(S,NamedNumberList,[]); - L when is_list(L) -> - error({type,{duplicates,L},S}), - unchanged - end. +check_bitstring(S, NNL0) -> + NNL = check_named_number_list(S, NNL0), + _ = [asn1_error(S, S#state.type, {invalid_bit_number,Bit}) || + {_,Bit} <- NNL, Bit < 0], + NNL. -check_bitstr(S,[{'NamedNumber',Id,Num}|T],Acc)when is_integer(Num) -> - check_bitstr(S,T,[{Id,Num}|Acc]); -check_bitstr(S,[{'NamedNumber',Id,Name}|T],Acc) when is_atom(Name) -> -%%check_bitstr(S,[{'NamedNumber',Id,{identifier,_,Name}}|T],Acc) -> -%% io:format("asn1ct_check:check_bitstr/3 hej hop ~w~n",[Name]), - Val = dbget_ex(S,S#state.mname,Name), -%% io:format("asn1ct_check:check_bitstr/3: ~w~n",[Val]), - check_bitstr(S,[{'NamedNumber',Id,Val#valuedef.value}|T],Acc); -check_bitstr(S,[],Acc) -> - case check_unique(Acc,2) of - [] -> - lists:keysort(2,Acc); - L when is_list(L) -> - error({type,{duplicate_values,L},S}), - unchanged - end; -%% When a BIT STRING already is checked, for instance a COMPONENTS OF S -%% where S is a sequence that has a component that is a checked BS, the -%% NamedNumber list is a list of {atom(),integer()} elements. -check_bitstr(S,[El={Id,Num}|Rest],Acc) when is_atom(Id),is_integer(Num) -> - check_bitstr(S,Rest,[El|Acc]). - +check_real(_S,_Constr) -> + ok. %% Check INSTANCE OF %% check that DefinedObjectClass is of TYPE-IDENTIFIER class @@ -5013,20 +4943,16 @@ check_instance_of(S,DefinedObjectClass,Constraint) -> check_type_identifier(S,DefinedObjectClass), iof_associated_type(S,Constraint). - -check_type_identifier(_S,'TYPE-IDENTIFIER') -> - ok; -check_type_identifier(S,Eref=#'Externaltypereference'{}) -> - case get_referenced_type(S,Eref) of - {_,#classdef{name='TYPE-IDENTIFIER'}} -> ok; - {_,#classdef{typespec=NextEref}} - when is_record(NextEref,'Externaltypereference') -> - check_type_identifier(S,NextEref); +check_type_identifier(S, Eref=#'Externaltypereference'{type=Class}) -> + case get_referenced_type(S, Eref) of + {_,#classdef{name='TYPE-IDENTIFIER'}} -> + ok; + {_,#classdef{typespec=#'Externaltypereference'{}=NextEref}} -> + check_type_identifier(S, NextEref); {_,TD=#typedef{typespec=#type{def=#'Externaltypereference'{}}}} -> - check_type_identifier(S,(TD#typedef.typespec)#type.def); - Err -> - error({type,{"object set in type INSTANCE OF " - "not of class TYPE-IDENTIFIER",Eref,Err},S}) + check_type_identifier(S, (TD#typedef.typespec)#type.def); + _ -> + asn1_error(S, S#state.type, {illegal_instance_of,Class}) end. iof_associated_type(S,[]) -> @@ -5156,9 +5082,6 @@ check_enumerated(S,NamedNumberList,_Constr) -> %% the latter is returned if the ENUMERATION contains EXTENSIONMARK check_enum(S,[{'NamedNumber',Id,Num}|T],Acc1,Acc2,Root) when is_integer(Num) -> check_enum(S,T,[{Id,Num}|Acc1],Acc2,Root); -check_enum(S,[{'NamedNumber',Id,{identifier,_,Name}}|T],Acc1,Acc2,Root) -> - Val = dbget_ex(S,S#state.mname,Name), - check_enum(S,[{'NamedNumber',Id,Val#valuedef.value}|T],Acc1,Acc2,Root); check_enum(S,['EXTENSIONMARK'|T],Acc1,Acc2,_Root) -> NewAcc2 = lists:keysort(2,Acc1), NewList = enum_number(lists:reverse(Acc2),NewAcc2,0,[],[]), @@ -6774,7 +6697,7 @@ storeindb(#state{mname=Module}=S, [H|T], Errors) -> storeindb(S, T, Errors); Prev -> PrevLine = asn1ct:get_pos_of_def(Prev), - {error,Error} = asn1_error(S, H, {already_defined,Name,PrevLine}), + Error = return_asn1_error(S, H, {already_defined,Name,PrevLine}), storeindb(S, T, [Error|Errors]) end; storeindb(_, [], []) -> @@ -6821,20 +6744,37 @@ findtypes_and_values([],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc) -> {lists:reverse(Tacc),lists:reverse(Vacc),lists:reverse(Pacc), lists:reverse(Cacc),lists:reverse(Oacc),lists:reverse(OSacc)}. -asn1_error(#state{mname=Where}, Item, Error) -> +return_asn1_error(#state{mname=Where}, Item, Error) -> Pos = asn1ct:get_pos_of_def(Item), - {error,{structured_error,{Where,Pos},?MODULE,Error}}. + {structured_error,{Where,Pos},?MODULE,Error}. + +asn1_error(S, Item, Error) -> + throw({error,return_asn1_error(S, Item, Error)}). format_error({already_defined,Name,PrevLine}) -> io_lib:format("the name ~p has already been defined at line ~p", [Name,PrevLine]); +format_error({illegal_instance_of,Class}) -> + io_lib:format("using INSTANCE OF on class '~s' is illegal, " + "because INSTANCE OF may only be used on the class TYPE-IDENTFIER", + [Class]); +format_error(illegal_octet_string_value) -> + "expecting a bstring or an hstring as value for an OCTET STRING"; format_error({invalid_fields,Fields,Obj}) -> io_lib:format("invalid ~s in ~p", [format_fields(Fields),Obj]); +format_error({invalid_bit_number,Bit}) -> + io_lib:format("the bit number '~p' is invalid", [Bit]); format_error({missing_mandatory_fields,Fields,Obj}) -> io_lib:format("missing mandatory ~s in ~p", [format_fields(Fields),Obj]); +format_error({namelist_redefinition,Name}) -> + io_lib:format("the name '~s' can not be redefined", [Name]); format_error({undefined,Name}) -> io_lib:format("'~s' is referenced, but is not defined", [Name]); +format_error({undefined_import,Ref,Module}) -> + io_lib:format("'~s' is not exported from ~s", [Ref,Module]); +format_error({value_reused,Val}) -> + io_lib:format("the value '~p' is used more than once", [Val]); format_error(Other) -> io_lib:format("~p", [Other]). @@ -6850,14 +6790,6 @@ error({export,Msg,#state{mname=Mname,type=Ref,tname=Typename}}) -> Pos = Ref#'Externaltypereference'.pos, io:format("asn1error:~p:~p:~p~n~p~n",[Pos,Mname,Typename,Msg]), {error,{export,Pos,Mname,Typename,Msg}}; -error({import,Msg,#state{mname=Mname,type=Ref,tname=Typename}}) -> - PosOfDef = - fun(#'Externaltypereference'{pos=P}) -> P; - (#'Externalvaluereference'{pos=P}) -> P - end, - Pos = PosOfDef(Ref), - io:format("asn1error:~p:~p:~p~n~p~n",[Pos,Mname,Typename,Msg]), - {error,{import,Pos,Mname,Typename,Msg}}; % error({type,{Msg1,Msg2},#state{mname=Mname,type=Type,tname=Typename}}) % when is_record(Type,typedef) -> % io:format("asn1error:~p:~p:~p ~p~n", @@ -7158,3 +7090,6 @@ check_fold(S, [H|T], Check) -> [Error|check_fold(S, T, Check)] end; check_fold(_, [], Check) when is_function(Check, 3) -> []. + +name_of_def(#'Externaltypereference'{type=N}) -> N; +name_of_def(#'Externalvaluereference'{value=N}) -> N. diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl index 4672f7edd3..ed3f6f886e 100644 --- a/lib/asn1/src/asn1ct_constructed_per.erl +++ b/lib/asn1/src/asn1ct_constructed_per.erl @@ -79,7 +79,7 @@ gen_encode_constructed_imm(Erule, Typename, #type{}=D) -> [] end, Aligned = is_aligned(Erule), - Value0 = asn1ct_gen:mk_var(asn1ct_name:curr(val)), + Value0 = make_var(val), Optionals = optionals(to_textual_order(CompList)), ImmOptionals = [asn1ct_imm:per_enc_optional(Value0, Opt, Aligned) || Opt <- Optionals], @@ -87,7 +87,7 @@ gen_encode_constructed_imm(Erule, Typename, #type{}=D) -> ExtImm = case Ext of {ext,ExtPos,NumExt} when NumExt > 0 -> gen_encode_extaddgroup(CompList), - Value = asn1ct_gen:mk_var(asn1ct_name:curr(val)), + Value = make_var(val), asn1ct_imm:per_enc_extensions(Value, ExtPos, NumExt, Aligned); _ -> @@ -106,19 +106,17 @@ gen_encode_constructed_imm(Erule, Typename, #type{}=D) -> c_index=N, usedclassfield=UniqueFieldName, uniqueclassfield=UniqueFieldName, - valueindex=ValueIndex + valueindex=ValueIndex0 } -> %% N is index of attribute that determines constraint {Module,ObjSetName} = ObjectSet, #typedef{typespec=#'ObjectSet'{gen=Gen}} = asn1_db:dbget(Module, ObjSetName), case Gen of true -> - ObjectEncode = - asn1ct_gen:un_hyphen_var(lists:concat(['Obj',AttrN])), - El = make_element(N+1, asn1ct_gen:mk_var(asn1ct_name:curr(val))), - ValueMatch = value_match(ValueIndex, El), - ObjSetImm0 = [{assign,{var,ObjectEncode},ValueMatch}], - {{AttrN,ObjectEncode},ObjSetImm0}; + ValueIndex = ValueIndex0 ++ [{N+1,top}], + Val = make_var(val), + {ObjSetImm0,Dst} = enc_dig_out_value(ValueIndex, Val), + {{AttrN,Dst},ObjSetImm0}; false -> {false,[]} end; @@ -128,7 +126,7 @@ gen_encode_constructed_imm(Erule, Typename, #type{}=D) -> %% when the simpletableattributes was at an outer %% level and the objfun has been passed through the %% function call - {{"got objfun through args","ObjFun"},[]}; + {{"got objfun through args",{var,"ObjFun"}},[]}; _ -> {false,[]} end @@ -136,7 +134,7 @@ gen_encode_constructed_imm(Erule, Typename, #type{}=D) -> ImmSetExt = case Ext of {ext,_Pos,NumExt2} when NumExt2 > 0 -> - asn1ct_imm:per_enc_extension_bit('Extensions', Aligned); + asn1ct_imm:per_enc_extension_bit({var,"Extensions"}, Aligned); {ext,_Pos,_} -> asn1ct_imm:per_enc_extension_bit([], Aligned); _ -> @@ -452,8 +450,13 @@ dec_objset_default(N, C, LeadingAttr, false) -> "{value,Bytes}," "{unique_name_and_value,",{asis,LeadingAttr},",Id}}}).",nl,nl]); dec_objset_default(N, _, _, true) -> - emit([{asis,N},"(Bytes, Id) ->",nl, - "Bytes.",nl,nl]). + emit([{asis,N},"(Bytes, Id) ->",nl| + case asn1ct:use_legacy_types() of + false -> + ["{asn1_OPENTYPE,Bytes}.",nl,nl]; + true -> + ["Bytes.",nl,nl] + end]). dec_objset_1(Erule, N, {Id,Obj}, RestFields, Typename) -> emit([{asis,N},"(Bytes, ",{asis,Id},") ->",nl]), @@ -540,7 +543,7 @@ gen_encode_choice_imm(Erule, TopType, #type{def={'CHOICE',CompList}}) -> Aligned = is_aligned(Erule), Cs = gen_enc_choice(Erule, TopType, CompList, Ext), [{assign,{expr,"{ChoiceTag,ChoiceVal}"},"Val"}| - asn1ct_imm:per_enc_choice('ChoiceTag', Cs, Aligned)]. + asn1ct_imm:per_enc_choice({var,"ChoiceTag"}, Cs, Aligned)]. gen_decode_choice(Erules,Typename,D) when is_record(D,type) -> asn1ct_name:start(), @@ -562,14 +565,14 @@ gen_encode_sof(Erule, Typename, SeqOrSetOf, D) -> gen_encode_sof_imm(Erule, Typename, SeqOrSetOf, #type{}=D) -> {_SeqOrSetOf,ComponentType} = D#type.def, Aligned = is_aligned(Erule), - Constructed_Suffix = - asn1ct_gen:constructed_suffix(SeqOrSetOf, - ComponentType#type.def), - Conttype = asn1ct_gen:get_inner(ComponentType#type.def), + CompType = ComponentType#type.def, + Constructed_Suffix = asn1ct_gen:constructed_suffix(SeqOrSetOf, CompType), + Conttype = asn1ct_gen:get_inner(CompType), Currmod = get(currmod), Imm0 = case asn1ct_gen:type(Conttype) of {primitive,bif} -> - asn1ct_gen_per:gen_encode_prim_imm('Comp', ComponentType, Aligned); + asn1ct_gen_per:gen_encode_prim_imm({var,"Comp"}, + ComponentType, Aligned); {constructed,bif} -> TypeName = [Constructed_Suffix|Typename], Enc = enc_func(asn1ct_gen:list2name(TypeName)), @@ -577,17 +580,19 @@ gen_encode_sof_imm(Erule, Typename, SeqOrSetOf, #type{}=D) -> [{objfun,_}|_] -> [{var,"ObjFun"}]; _ -> [] end, - [{apply,Enc,[{var,"Comp"}|ObjArg]}]; + [{apply,{local,Enc,CompType}, + [{var,"Comp"}|ObjArg]}]; #'Externaltypereference'{module=Currmod,type=Ename} -> - [{apply,enc_func(Ename),[{var,"Comp"}]}]; + [{apply,{local,enc_func(Ename),CompType},[{var,"Comp"}]}]; #'Externaltypereference'{module=EMod,type=Ename} -> - [{apply,{EMod,enc_func(Ename)},[{var,"Comp"}]}]; + [{apply,{EMod,enc_func(Ename),CompType},[{var,"Comp"}]}]; 'ASN1_OPEN_TYPE' -> - asn1ct_gen_per:gen_encode_prim_imm('Comp', + asn1ct_gen_per:gen_encode_prim_imm({var,"Comp"}, #type{def='ASN1_OPEN_TYPE'}, Aligned) end, - asn1ct_imm:per_enc_sof('Val', D#type.constraint, 'Comp', Imm0, Aligned). + asn1ct_imm:per_enc_sof({var,"Val"}, D#type.constraint, 'Comp', + Imm0, Aligned). gen_decode_sof(Erules, Typename, SeqOrSetOf, #type{}=D) -> asn1ct_name:start(), @@ -871,8 +876,8 @@ gen_enc_components_call1(Erule,TopType, CanonicalNum -> CanonicalNum end, - Element0 = make_element(TermNo+1, asn1ct_gen:mk_var(asn1ct_name:curr(val))), - {Imm0,Element} = asn1ct_imm:enc_bind_var(Element0), + Val = make_var(val), + {Imm0,Element} = asn1ct_imm:enc_element(TermNo+1, Val), Imm1 = gen_enc_line_imm(Erule, TopType, Cname, Type, Element, DynamicEnc, Ext), Category = case {Prop,Ext} of {'OPTIONAL',_} -> @@ -906,26 +911,36 @@ def_values(#type{def=#'Externaltypereference'{module=Mod,type=Type}}, Def) -> #typedef{typespec=T} = asn1_db:dbget(Mod, Type), def_values(T, Def); def_values(#type{def={'BIT STRING',[]}}, Bs) when is_bitstring(Bs) -> - ListBs = [B || <<B:1>> <= Bs], - IntBs = lists:foldl(fun(B, A) -> - (A bsl 1) bor B - end, 0, lists:reverse(ListBs)), - Sz = bit_size(Bs), - Compact = case 8 - Sz rem 8 of - 8 -> - {0,Bs}; - Unused -> - {Unused,<<Bs:Sz/bits,0:Unused>>} - end, - [asn1_DEFAULT,Bs,Compact,ListBs,IntBs]; + case asn1ct:use_legacy_types() of + false -> + [asn1_DEFAULT,Bs]; + true -> + ListBs = [B || <<B:1>> <= Bs], + IntBs = lists:foldl(fun(B, A) -> + (A bsl 1) bor B + end, 0, lists:reverse(ListBs)), + Sz = bit_size(Bs), + Compact = case 8 - Sz rem 8 of + 8 -> + {0,Bs}; + Unused -> + {Unused,<<Bs:Sz/bits,0:Unused>>} + end, + [asn1_DEFAULT,Bs,Compact,ListBs,IntBs] + end; def_values(#type{def={'BIT STRING',[_|_]=Ns}}, List) when is_list(List) -> Bs = asn1ct_gen:named_bitstring_value(List, Ns), - ListBs = [B || <<B:1>> <= Bs], - IntBs = lists:foldl(fun(B, A) -> - (A bsl 1) bor B - end, 0, lists:reverse(ListBs)), - Args = [List,Bs,ListBs,IntBs], - {call,per_common,is_default_bitstring,Args}; + As = case asn1ct:use_legacy_types() of + false -> + [List,Bs]; + true -> + ListBs = [B || <<B:1>> <= Bs], + IntBs = lists:foldl(fun(B, A) -> + (A bsl 1) bor B + end, 0, lists:reverse(ListBs)), + [List,Bs,ListBs,IntBs] + end, + {call,per_common,is_default_bitstring,As}; def_values(#type{def={'INTEGER',Ns}}, Def) -> [asn1_DEFAULT,Def|case lists:keyfind(Def, 2, Ns) of false -> []; @@ -967,9 +982,9 @@ gen_enc_line_imm_1(Erule, TopType, Cname, Type, Element, DynamicEnc) -> CurrMod = get(currmod), case asn1ct_gen:type(Atype) of #'Externaltypereference'{module=CurrMod,type=EType} -> - [{apply,enc_func(EType),[{expr,Element}]}]; + [{apply,{local,enc_func(EType),Atype},[Element]}]; #'Externaltypereference'{module=Mod,type=EType} -> - [{apply,{Mod,enc_func(EType)},[{expr,Element}]}]; + [{apply,{Mod,enc_func(EType),Atype},[Element]}]; {primitive,bif} -> asn1ct_gen_per:gen_encode_prim_imm(Element, Type, Aligned); 'ASN1_OPEN_TYPE' -> @@ -988,9 +1003,9 @@ gen_enc_line_imm_1(Erule, TopType, Cname, Type, Element, DynamicEnc) -> Enc = enc_func(asn1ct_gen:list2name(NewTypename)), case {Type#type.tablecinf,DynamicEnc} of {[{objfun,_}|_R],{_,EncFun}} -> - [{apply,Enc,[{expr,Element},{var,EncFun}]}]; + [{apply,{local,Enc,Type},[Element,EncFun]}]; _ -> - [{apply,Enc,[{expr,Element}]}] + [{apply,{local,Enc,Type},[Element]}] end end end. @@ -1014,13 +1029,16 @@ enc_var_type_call(Erule, Name, RestFieldNames, {_,Key,Code} <- ObjSet1], ObjSet = lists:sort([P || {_,B}=P <- ObjSet2, B =/= none]), Key = erlang:md5(term_to_binary({encode,ObjSet,RestFieldNames,Extensible})), + Imm = enc_objset_imm(Erule, Name, ObjSet, RestFieldNames, Extensible), + Lambda = {lambda,[{var,"Val"},{var,"Id"}],Imm}, Gen = fun(_Fd, N) -> - enc_objset(Erule, Name, N, ObjSet, - RestFieldNames, Extensible) + Aligned = is_aligned(Erule), + emit([{asis,N},"(Val, Id) ->",nl]), + asn1ct_imm:enc_cg(Imm, Aligned), + emit([".",nl]) end, Prefix = lists:concat(["enc_os_",Name]), - F = asn1ct_func:call_gen(Prefix, Key, Gen), - [{apply,F,[{var,atom_to_list(Val)},{var,Fun}]}]. + [{call_gen,Prefix,Key,Gen,Lambda,[Val,Fun]}]. fix_object_code(Name, [{Name,B}|_], _ClassFields) -> B; @@ -1042,9 +1060,7 @@ fix_object_code(Name, [], ClassFields) -> end end. - -enc_objset(Erule, Component, Name, ObjSet, RestFieldNames, Extensible) -> - asn1ct_name:start(), +enc_objset_imm(Erule, Component, ObjSet, RestFieldNames, Extensible) -> Aligned = is_aligned(Erule), E = {error, fun() -> @@ -1053,22 +1069,28 @@ enc_objset(Erule, Component, Name, ObjSet, RestFieldNames, Extensible) -> "{value,Val}," "{unique_name_and_value,'_'}})",nl]) end}, - Imm = [{'cond', - [[{eq,{var,"Id"},Key}| - enc_obj(Erule, Obj, RestFieldNames, Aligned)] || - {Key,Obj} <- ObjSet] ++ - [['_',case Extensible of - false -> E; - true -> {put_bits,{var,"Val"},binary,[1]} - end]]}], - emit([{asis,Name},"(Val, Id) ->",nl]), - asn1ct_imm:enc_cg(Imm, Aligned), - emit([".",nl]). + [{'cond', + [[{eq,{var,"Id"},Key}| + enc_obj(Erule, Obj, RestFieldNames, Aligned)] || + {Key,Obj} <- ObjSet] ++ + [['_',case Extensible of + false -> + E; + true -> + case asn1ct:use_legacy_types() of + false -> + {call,per_common,open_type_to_binary, + [{var,"Val"}]}; + true -> + {call,per_common,legacy_open_type_to_binary, + [{var,"Val"}]} + end + end]]}]. enc_obj(Erule, Obj, RestFieldNames0, Aligned) -> case Obj of #typedef{name={primitive,bif},typespec=Def} -> - asn1ct_gen_per:gen_encode_prim_imm('Val', Def, Aligned); + asn1ct_gen_per:gen_encode_prim_imm({var,"Val"}, Def, Aligned); #typedef{name={constructed,bif},typespec=Def} -> InnerType = asn1ct_gen:get_inner(Def#type.def), case InnerType of @@ -1084,7 +1106,7 @@ enc_obj(Erule, Obj, RestFieldNames0, Aligned) -> gen_encode_sof_imm(Erule, name, InnerType, Def) end; #typedef{name=Type} -> - [{apply,enc_func(Type),[{var,"Val"}]}]; + [{apply,{local,enc_func(Type),Type},[{var,"Val"}]}]; #'Externalvaluereference'{module=Mod,value=Value} -> case asn1_db:dbget(Mod, Value) of #typedef{typespec=#'Object'{def=Def}} -> @@ -1097,9 +1119,9 @@ enc_obj(Erule, Obj, RestFieldNames0, Aligned) -> Func = enc_func(Type), case get(currmod) of Mod -> - [{apply,Func,[{var,"Val"}]}]; + [{apply,{local,Func,Obj},[{var,"Val"}]}]; _ -> - [{apply,{Mod,Func},[{var,"Val"}]}] + [{apply,{Mod,Func,Obj},[{var,"Val"}]}] end end. @@ -1540,12 +1562,12 @@ gen_enc_choices([H|T], Erule, TopType, Pos, Constr, Ext) -> no -> case Type#type.tablecinf of [{objfun,_}|_] -> - {"got objfun through args","ObjFun"}; + {"got objfun through args",{var,"ObjFun"}}; _ -> false end; _ -> - {no_attr,"ObjFun"} + {no_attr,{var,"ObjFun"}} end, DoExt = case Constr of ext -> Ext; @@ -1561,7 +1583,7 @@ gen_enc_choices([H|T], Erule, TopType, Pos, Constr, Ext) -> [{put_bits,0,1,[1]}| asn1ct_imm:per_enc_integer(Pos, Constr, Aligned)] end, - Body = gen_enc_line_imm(Erule, TopType, Cname, Type, 'ChoiceVal', + Body = gen_enc_line_imm(Erule, TopType, Cname, Type, {var,"ChoiceVal"}, EncObj, DoExt), Imm = Tag ++ Body, [{Cname,Imm}|gen_enc_choices(T, Erule, TopType, Pos+1, Constr, Ext)]; @@ -1778,3 +1800,13 @@ value_match1(Value,[],Acc,Depth) -> Acc ++ Value ++ lists:concat(lists:duplicate(Depth,")")); value_match1(Value,[{VI,_}|VIs],Acc,Depth) -> value_match1(Value,VIs,Acc++lists:concat(["element(",VI,","]),Depth+1). + +enc_dig_out_value([], Value) -> + {[],Value}; +enc_dig_out_value([{N,_}|T], Value) -> + {Imm0,Dst0} = enc_dig_out_value(T, Value), + {Imm,Dst} = asn1ct_imm:enc_element(N, Dst0), + {Imm0++Imm,Dst}. + +make_var(Base) -> + {var,atom_to_list(asn1ct_gen:mk_var(asn1ct_name:curr(Base)))}. diff --git a/lib/asn1/src/asn1ct_func.erl b/lib/asn1/src/asn1ct_func.erl index dbadedb683..33f998722a 100644 --- a/lib/asn1/src/asn1ct_func.erl +++ b/lib/asn1/src/asn1ct_func.erl @@ -48,7 +48,7 @@ need(MFA) -> call_gen(Prefix, Key, Gen, Args) when is_function(Gen, 2) -> F = req({gen_func,Prefix,Key,Gen}), - asn1ct_gen:emit([F,"(",call_args(Args, ""),")"]). + asn1ct_gen:emit([{asis,F},"(",call_args(Args, ""),")"]). call_gen(Prefix, Key, Gen) when is_function(Gen, 2) -> req({gen_func,Prefix,Key,Gen}). diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl index 30d337635b..44b050e59d 100644 --- a/lib/asn1/src/asn1ct_gen.erl +++ b/lib/asn1/src/asn1ct_gen.erl @@ -23,6 +23,7 @@ -export([demit/1, emit/1, + open_output_file/1,close_output_file/0, get_inner/1,type/1,def_to_tag/1,prim_bif/1, list2name/1, list2rname/1, @@ -70,8 +71,7 @@ pgen_module(OutFile,Erules,Module, HrlGenerated = pgen_hrl(Erules,Module,TypeOrVal,Options,Indent), asn1ct_name:start(), ErlFile = lists:concat([OutFile,".erl"]), - Fid = fopen(ErlFile), - put(gen_file_out,Fid), + _ = open_output_file(ErlFile), asn1ct_func:start_link(), gen_head(Erules,Module,HrlGenerated), pgen_exports(Erules,Module,TypeOrVal), @@ -85,9 +85,9 @@ pgen_module(OutFile,Erules,Module, "%%%",nl, "%%% Run-time functions.",nl, "%%%",nl]), - asn1ct_func:generate(Fid), - file:close(Fid), - _ = erase(gen_file_out), + Fd = get(gen_file_out), + asn1ct_func:generate(Fd), + close_output_file(), _ = erase(outfile), asn1ct:verbose("--~p--~n",[{generated,ErlFile}],Options). @@ -190,7 +190,7 @@ pgen_check_defaultval(Erules,Module) -> "********~n~n",[X]) end, lists:foreach(Fun,CheckObjects), - file:close(IoDevice); + ok = file:close(IoDevice); _ -> ok end, gen_check_defaultval(Erules,Module,CheckObjects). @@ -790,7 +790,8 @@ gen_decode_constructed(Erules,Typename,InnerType,D) when is_record(D,typedef) -> pgen_exports(Erules,_Module,{Types,Values,_,_,Objects,ObjectSets}) -> - emit(["-export([encoding_rule/0,bit_string_format/0]).",nl]), + emit(["-export([encoding_rule/0,bit_string_format/0," + " legacy_erlang_types/0]).",nl]), case Types of [] -> ok; _ -> @@ -1022,7 +1023,9 @@ gen_info_functions(Erules) -> emit(["encoding_rule() -> ", {asis,Erules},".",nl,nl, "bit_string_format() -> ", - {asis,asn1ct:get_bit_string_format()},".",nl,nl]). + {asis,asn1ct:get_bit_string_format()},".",nl,nl, + "legacy_erlang_types() -> ", + {asis,asn1ct:use_legacy_types()},".",nl,nl]). gen_decode_partial_incomplete(ber) -> case {asn1ct:read_config_data(partial_incomplete_decode), @@ -1121,9 +1124,23 @@ pgen_info() -> open_hrl(OutFile,Module) -> File = lists:concat([OutFile,".hrl"]), - Fid = fopen(File), - put(gen_file_out,Fid), - gen_hrlhead(Module). + _ = open_output_file(File), + gen_hrlhead(Module), + Protector = hrl_protector(OutFile), + emit(["-ifndef(",Protector,").\n", + "-define(",Protector,", true).\n" + "\n"]). + +hrl_protector(OutFile) -> + BaseName = filename:basename(OutFile), + P = "_" ++ string:to_upper(BaseName) ++ "_HRL_", + [if + $A =< C, C =< $Z -> C; + $a =< C, C =< $a -> C; + $0 =< C, C =< $9 -> C; + true -> $_ + end || C <- P]. + %% EMIT functions ************************ %% *************************************** @@ -1195,15 +1212,19 @@ call_args([A|As], Sep) -> [Sep,do_emit(A)|call_args(As, ", ")]; call_args([], _) -> []. -fopen(F) -> +open_output_file(F) -> case file:open(F, [write,raw,delayed_write]) of - {ok, Fd} -> + {ok,Fd} -> + put(gen_file_out, Fd), Fd; {error, Reason} -> io:format("** Can't open file ~p ~n", [F]), exit({error,Reason}) end. +close_output_file() -> + ok = file:close(erase(gen_file_out)). + pgen_hrl(Erules,Module,TypeOrVal,Options,_Indent) -> put(currmod,Module), {Types,Values,Ptypes,_,_,_} = TypeOrVal, @@ -1226,8 +1247,9 @@ pgen_hrl(Erules,Module,TypeOrVal,Options,_Indent) -> 0 -> 0; Y -> - Fid = get(gen_file_out), - file:close(Fid), + Protector = hrl_protector(get(outfile)), + emit(["-endif. %% ",Protector,"\n"]), + close_output_file(), asn1ct:verbose("--~p--~n", [{generated,lists:concat([get(outfile),".hrl"])}], Options), diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl index de81259fcb..bea0ec8968 100644 --- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl +++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl @@ -206,10 +206,32 @@ gen_encode_prim(_Erules, #type{}=D, DoTag, Value) -> {call,ber,encode_tags, [DoTag,{curr,realval},{curr,realsize}]},nl, "end"]); + {'BIT STRING',[]} -> + case asn1ct:use_legacy_types() of + false when BitStringConstraint =:= [] -> + call(encode_unnamed_bit_string, [Value,DoTag]); + false -> + call(encode_unnamed_bit_string, + [{asis,BitStringConstraint},Value,DoTag]); + true -> + call(encode_bit_string, + [{asis,BitStringConstraint},Value, + {asis,[]},DoTag]) + end; {'BIT STRING',NamedNumberList} -> - call(encode_bit_string, - [{asis,BitStringConstraint},Value, - {asis,NamedNumberList},DoTag]); + case asn1ct:use_legacy_types() of + false when BitStringConstraint =:= [] -> + call(encode_named_bit_string, + [Value,{asis,NamedNumberList},DoTag]); + false -> + call(encode_named_bit_string, + [{asis,BitStringConstraint},Value, + {asis,NamedNumberList},DoTag]); + true -> + call(encode_bit_string, + [{asis,BitStringConstraint},Value, + {asis,NamedNumberList},DoTag]) + end; 'NULL' -> call(encode_null, [Value,DoTag]); 'OBJECT IDENTIFIER' -> @@ -471,7 +493,6 @@ gen_dec_prim(_Erules, Att, BytesVar, DoTag, _TagIn, _Form, _OptOrMand) -> _ -> "" end, NewTypeName = case Typename of - 'OCTET STRING' -> restricted_string; 'NumericString' -> restricted_string; 'TeletexString' -> restricted_string; 'T61String' -> restricted_string; @@ -529,6 +550,19 @@ gen_dec_prim(_Erules, Att, BytesVar, DoTag, _TagIn, _Form, _OptOrMand) -> 'RELATIVE-OID' -> emit(["decode_relative_oid(",BytesVar,","]), need(decode_relative_oid, 2); + 'OCTET STRING' -> + F = case asn1ct:use_legacy_types() of + false -> decode_octet_string; + true -> decode_restricted_string + end, + emit([{asis,F},"(",BytesVar,","]), + case Constraint of + [] -> + need(F, 2); + _ -> + emit([{asis,Constraint},","]), + need(F, 3) + end; restricted_string -> emit(["decode_restricted_string",AsBin,"(",BytesVar,","]), case Constraint of @@ -1090,13 +1124,11 @@ gen_objset_enc(Erules, ObjSetName, UniqueName, %% See X.681 Annex E for the following case gen_objset_enc(_,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName, _ClFields,_NthObj,Acc) -> - emit(["'getenc_",ObjSetName,"'(_) ->",nl]), - emit({indent(3),"fun(_, Val, _RestPrimFieldName) ->",nl}), - emit({indent(6),"Len = case Val of",nl,indent(9), - "Bin when is_binary(Bin) -> byte_size(Bin);",nl,indent(9), - "_ -> length(Val)",nl,indent(6),"end,"}), - emit({indent(6),"{Val,Len}",nl}), - emit({indent(3),"end.",nl,nl}), + emit(["'getenc_",ObjSetName,"'(_) ->",nl, + indent(2),"fun(_, Val, _RestPrimFieldName) ->",nl]), + emit_enc_open_type(4), + emit([nl, + indent(2),"end.",nl,nl]), Acc; gen_objset_enc(_, ObjSetName, UniqueName, [], _, _, _, Acc) -> emit_default_getenc(ObjSetName, UniqueName), @@ -1158,13 +1190,8 @@ gen_inlined_enc_funs1(Fields, [{typefield,Name,_}|Rest], ObjSetName, %% were no type in the table and we therefore generate %% code that returns the input for application %% treatment. - emit([indent(9),{asis,Name}," ->",nl, - indent(12),"Len = case Val of",nl, - indent(15),"Bin when is_binary(Bin) -> " - "byte_size(Bin);",nl, - indent(15),"_ -> length(Val)",nl, - indent(12),"end,",nl, - indent(12),"{Val,Len}"]), + emit([indent(9),{asis,Name}," ->",nl]), + emit_enc_open_type(11), {Acc0,0} end, gen_inlined_enc_funs1(Fields, Rest, ObjSetName, Sep, NthObj+NAdd, Acc); @@ -1175,6 +1202,25 @@ gen_inlined_enc_funs1(_, [], _, _, NthObj, Acc) -> indent(3),"end"]), {Acc,NthObj}. +emit_enc_open_type(I) -> + Indent = indent(I), + S = [Indent, "case Val of",nl, + Indent,indent(2),"{asn1_OPENTYPE,Bin} when is_binary(Bin) ->",nl, + Indent,indent(4),"{Bin,byte_size(Bin)}"| + case asn1ct:use_legacy_types() of + false -> + [nl, + Indent,"end"]; + true -> + [";",nl, + Indent,indent(2),"Bin when is_binary(Bin) ->",nl, + Indent,indent(4),"{Bin,byte_size(Bin)};",nl, + Indent,indent(2),"_ ->",nl, + Indent,indent(4),"{Val,length(Val)}",nl, + Indent, "end"] + end], + emit(S). + emit_inner_of_fun(TDef=#typedef{name={ExtMod,Name},typespec=Type}, InternalDefFunName) -> OTag = Type#type.tag, @@ -1258,14 +1304,9 @@ gen_objset_dec(_,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName, _ClFields,_NthObj) -> emit(["'getdec_",ObjSetName,"'(_) ->",nl]), emit([indent(2),"fun(_,Bytes, _RestPrimFieldName) ->",nl]), - - emit([indent(4),"case Bytes of",nl, - indent(6),"Bin when is_binary(Bin) -> ",nl, - indent(8),"Bin;",nl, - indent(6),"_ ->",nl, - indent(8),{call,ber,ber_encode,["Bytes"]},nl, - indent(4),"end",nl]), - emit([indent(2),"end.",nl,nl]), + emit_dec_open_type(4), + emit([nl, + indent(2),"end.",nl,nl]), ok; gen_objset_dec(_, ObjSetName, UniqueName, [], _, _, _) -> emit_default_getdec(ObjSetName, UniqueName), @@ -1312,12 +1353,8 @@ gen_inlined_dec_funs1(Fields, [{typefield,Name,Prop}|Rest], end, 0; false -> - emit([indent(9),{asis,Name}," ->",nl, - indent(12),"Len = case Bytes of",nl, - indent(15),"B when is_binary(B) -> byte_size(B);",nl, - indent(15),"_ -> length(Bytes)",nl, - indent(12),"end,",nl, - indent(12),"{Bytes,[],Len}"]), + emit([indent(9),{asis,Name}," ->",nl]), + emit_dec_open_type(11), 0 end, gen_inlined_dec_funs1(Fields, Rest, ObjSetName, Sep, NthObj+N); @@ -1328,6 +1365,27 @@ gen_inlined_dec_funs1(_, [], _, _, NthObj) -> indent(3),"end"]), NthObj. +emit_dec_open_type(I) -> + Indent = indent(I), + S = case asn1ct:use_legacy_types() of + false -> + [Indent, "case Bytes of",nl, + Indent,indent(2),"Bin when is_binary(Bin) -> ",nl, + Indent,indent(4),"{asn1_OPENTYPE,Bin};",nl, + Indent,indent(2),"_ ->",nl, + Indent,indent(4),"{asn1_OPENTYPE,", + {call,ber,ber_encode,["Bytes"]},"}",nl, + Indent, "end"]; + true -> + [Indent, "case Bytes of",nl, + Indent,indent(2),"Bin when is_binary(Bin) -> ",nl, + Indent,indent(4),"Bin;",nl, + Indent,indent(2),"_ ->",nl, + Indent,indent(4),{call,ber,ber_encode,["Bytes"]},nl, + Indent, "end"] + end, + emit(S). + emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type},Prop, InternalDefFunName) -> OTag = Type#type.tag, diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl index 8b999ddbf0..519ce9f054 100644 --- a/lib/asn1/src/asn1ct_gen_per.erl +++ b/lib/asn1/src/asn1ct_gen_per.erl @@ -99,7 +99,7 @@ gen_encode_user(Erules,D) when is_record(D,typedef) -> gen_encode_prim(Erules, D) -> - Value = asn1ct_gen:mk_var(asn1ct_name:curr(val)), + Value = {var,atom_to_list(asn1ct_gen:mk_var(asn1ct_name:curr(val)))}, gen_encode_prim(Erules, D, Value). gen_encode_prim(Erules, #type{}=D, Value) -> @@ -132,7 +132,14 @@ gen_encode_prim_imm(Val, #type{def=Type0,constraint=Constraint}, Aligned) -> ToBinary = {real_common,encode_real}, asn1ct_imm:per_enc_restricted_string(Val, ToBinary, Aligned); {'BIT STRING',NNL} -> - asn1ct_imm:per_enc_bit_string(Val, NNL, Constraint, Aligned); + case asn1ct:use_legacy_types() of + false -> + asn1ct_imm:per_enc_bit_string(Val, NNL, + Constraint, Aligned); + true -> + asn1ct_imm:per_enc_legacy_bit_string(Val, NNL, + Constraint, Aligned) + end; 'NULL' -> asn1ct_imm:per_enc_null(Val, Aligned); 'OBJECT IDENTIFIER' -> @@ -144,15 +151,21 @@ gen_encode_prim_imm(Val, #type{def=Type0,constraint=Constraint}, Aligned) -> 'BOOLEAN' -> asn1ct_imm:per_enc_boolean(Val, Aligned); 'OCTET STRING' -> - asn1ct_imm:per_enc_octet_string(Val, Constraint, Aligned); + case asn1ct:use_legacy_types() of + false -> + asn1ct_imm:per_enc_octet_string(Val, Constraint, Aligned); + true -> + asn1ct_imm:per_enc_legacy_octet_string(Val, Constraint, + Aligned) + end; 'ASN1_OPEN_TYPE' -> case Constraint of [#'Externaltypereference'{type=Tname}] -> EncFunc = enc_func(Tname), - Imm = [{apply,EncFunc,[{expr,Val}]}], + Imm = [{apply,{local,EncFunc,[]},[Val]}], asn1ct_imm:per_enc_open_type(Imm, Aligned); [] -> - Imm = [{call,erlang,iolist_to_binary,[{expr,Val}]}], + Imm = [{call,erlang,iolist_to_binary,[Val]}], asn1ct_imm:per_enc_open_type(Imm, Aligned) end end. @@ -325,7 +338,10 @@ gen_dec_imm_1('GeneralizedTime', Constraint, Aligned) -> gen_dec_imm_1('OCTET STRING', Constraint, Aligned) -> SzConstr = asn1ct_imm:effective_constraint(bitstring, Constraint), Imm = asn1ct_imm:per_dec_octet_string(SzConstr, Aligned), - {convert,binary_to_list,Imm}; + case asn1ct:use_legacy_types() of + false -> {convert,{binary,copy},Imm}; + true -> {convert,binary_to_list,Imm} + end; gen_dec_imm_1('TeletexString', _Constraint, Aligned) -> gen_dec_restricted_string(Aligned); gen_dec_imm_1('T61String', _Constraint, Aligned) -> diff --git a/lib/asn1/src/asn1ct_imm.erl b/lib/asn1/src/asn1ct_imm.erl index 047156fc10..fde39c674e 100644 --- a/lib/asn1/src/asn1ct_imm.erl +++ b/lib/asn1/src/asn1ct_imm.erl @@ -26,17 +26,19 @@ per_dec_octet_string/2,per_dec_open_type/1,per_dec_real/1, per_dec_restricted_string/1]). -export([per_dec_constrained/3,per_dec_normally_small_number/1]). --export([per_enc_bit_string/4,per_enc_boolean/2, +-export([per_enc_bit_string/4,per_enc_legacy_bit_string/4, + per_enc_boolean/2, per_enc_choice/3,per_enc_enumerated/3, per_enc_integer/3,per_enc_integer/4, per_enc_null/2, per_enc_k_m_string/4,per_enc_octet_string/3, + per_enc_legacy_octet_string/3, per_enc_open_type/2, per_enc_restricted_string/3, per_enc_small_number/2]). -export([per_enc_extension_bit/2,per_enc_extensions/4,per_enc_optional/3]). -export([per_enc_sof/5]). --export([enc_absent/3,enc_append/1,enc_bind_var/1]). +-export([enc_absent/3,enc_append/1,enc_element/2]). -export([enc_cg/2]). -export([optimize_alignment/1,optimize_alignment/2, dec_slim_cg/2,dec_code_gen/2]). @@ -157,7 +159,35 @@ per_dec_restricted_string(Aligned) -> %%% Encoding. %%% -per_enc_bit_string(Val0, [], Constraint0, Aligned) -> +per_enc_bit_string(Val, [], Constraint0, Aligned) -> + {B,[[],Bits]} = mk_vars([], [bits]), + Constraint = effective_constraint(bitstring, Constraint0), + B ++ [{call,erlang,bit_size,[Val],Bits}| + per_enc_length(Val, 1, Bits, Constraint, Aligned, 'BIT STRING')]; +per_enc_bit_string(Val0, NNL0, Constraint0, Aligned) -> + {B,[Val,Bs,Bits,Positions]} = mk_vars(Val0, [bs,bits,positions]), + NNL = lists:keysort(2, NNL0), + Constraint = effective_constraint(bitstring, Constraint0), + ExtraArgs = case constr_min_size(Constraint) of + no -> []; + Lb -> [Lb] + end, + ToBs = case ExtraArgs of + [] -> + {call,per_common,bs_drop_trailing_zeroes,[Val]}; + [Lower] -> + {call,per_common,adjust_trailing_zeroes,[Val,Lower]} + end, + B ++ [{'try', + [bit_string_name2pos_fun(NNL, Val)], + {Positions, + [{call,per_common,bitstring_from_positions, + [Positions|ExtraArgs]}]}, + [ToBs],Bs}, + {call,erlang,bit_size,[Bs],Bits}| + per_enc_length(Bs, 1, Bits, Constraint, Aligned, 'BIT STRING')]. + +per_enc_legacy_bit_string(Val0, [], Constraint0, Aligned) -> {B,[Val,Bs,Bits]} = mk_vars(Val0, [bs,bits]), Constraint = effective_constraint(bitstring, Constraint0), ExtraArgs = case constr_min_size(Constraint) of @@ -167,7 +197,7 @@ per_enc_bit_string(Val0, [], Constraint0, Aligned) -> B ++ [{call,per_common,to_bitstring,[Val|ExtraArgs],Bs}, {call,erlang,bit_size,[Bs],Bits}| per_enc_length(Bs, 1, Bits, Constraint, Aligned, 'BIT STRING')]; -per_enc_bit_string(Val0, NNL0, Constraint0, Aligned) -> +per_enc_legacy_bit_string(Val0, NNL0, Constraint0, Aligned) -> {B,[Val,Bs,Bits,Positions]} = mk_vars(Val0, [bs,bits,positions]), NNL = lists:keysort(2, NNL0), Constraint = effective_constraint(bitstring, Constraint0), @@ -256,35 +286,33 @@ per_enc_k_m_string(Val0, StringType, Constraint, Aligned) -> B ++ [{call,erlang,length,[Val],Len},Enc] end ++ per_enc_length(Bin, Unit, Len, SzConstraint, Aligned, k_m_string). -per_enc_open_type([], Aligned) -> - [{put_bits,1,8,unit(1, Aligned)},{put_bits,0,8,[1]}]; -per_enc_open_type([{'cond', - [['_', - {put_bits,0,0,_}, - {call,per_common,encode_unconstrained_number,_}=Call]]}], - Aligned) -> - %% We KNOW that encode_unconstrained_number/1 will return an IO list; - %% therefore the call to complete/1 can be replaced with a cheaper - %% call to iolist_to_binary/1. - {Dst,Imm} = per_enc_open_type_output([Call], []), - ToBin = {erlang,iolist_to_binary}, - Imm ++ per_enc_open_type(Dst, ToBin, Aligned); -per_enc_open_type([{call,erlang,iolist_to_binary,Args}], Aligned) -> - {_,[_,Bin,Len]} = mk_vars('dummy', [bin,len]), - [{call,erlang,iolist_to_binary,Args,Bin}, - {call,erlang,byte_size,[Bin],Len}|per_enc_length(Bin, 8, Len, Aligned)]; per_enc_open_type(Imm0, Aligned) -> - try - {Prefix,Imm1} = split_off_nonbuilding(Imm0), - Prefix ++ enc_open_type(Imm1, Aligned) - catch - throw:impossible -> - {Dst,Imm} = per_enc_open_type_output(Imm0, []), - ToBin = {enc_mod(Aligned),complete}, - Imm ++ per_enc_open_type(Dst, ToBin, Aligned) - end. + Imm = case Aligned of + true -> + %% Temporarily make the implicit 'align' done by + %% complete/1 explicit to facilitate later + %% optimizations: the absence of 'align' can be used + %% as an indication that complete/1 can be replaced + %% with a cheaper operation such as + %% iolist_to_binary/1. The redundant 'align' will be + %% optimized away later. + Imm0 ++ [{put_bits,0,0,[1,align]}]; + false -> + Imm0 + end, + {[],[[],Val,Len,Bin]} = mk_vars([], [output,len,bin]), + [{list,Imm,Val}, + {call,enc_mod(Aligned),complete,[Val],Bin}, + {call,erlang,byte_size,[Bin],Len}| + per_enc_length(Bin, 8, Len, Aligned)]. + +per_enc_octet_string(Bin, Constraint0, Aligned) -> + {B,[[],Len]} = mk_vars([], [len]), + Constraint = effective_constraint(bitstring, Constraint0), + B ++ [{call,erlang,byte_size,[Bin],Len}| + per_enc_length(Bin, 8, Len, Constraint, Aligned, 'OCTET STRING')]. -per_enc_octet_string(Val0, Constraint0, Aligned) -> +per_enc_legacy_octet_string(Val0, Constraint0, Aligned) -> {B,[Val,Bin,Len]} = mk_vars(Val0, [bin,len]), Constraint = effective_constraint(bitstring, Constraint0), B ++ [{call,erlang,iolist_to_binary,[Val],Bin}, @@ -316,28 +344,27 @@ per_enc_extensions(Val0, Pos0, NumBits, Aligned) when NumBits > 0 -> _ -> [{put_bits,Bitmap,NumBits,[1]}] end, B++[{call,per_common,extension_bitmap,[Val,Pos,Pos+NumBits],Bitmap}, - {'cond',[[{eq,Bitmap,0}], - ['_'|Length ++ PutBits]],{var,"Extensions"}}]. + {list,[{'cond',[[{eq,Bitmap,0}], + ['_'|Length ++ PutBits]]}], + {var,"Extensions"}}]. per_enc_optional(Val0, {Pos,DefVals}, _Aligned) when is_integer(Pos), is_list(DefVals) -> - Val1 = lists:concat(["element(",Pos,", ",Val0,")"]), - {B,[Val]} = mk_vars(Val1, []), + {B,Val} = enc_element(Pos, Val0), Zero = {put_bits,0,1,[1]}, One = {put_bits,1,1,[1]}, B++[{'cond', [[{eq,Val,DefVal},Zero] || DefVal <- DefVals] ++ [['_',One]]}]; per_enc_optional(Val0, {Pos,{call,M,F,A}}, _Aligned) when is_integer(Pos) -> - Val1 = lists:concat(["element(",Pos,", ",Val0,")"]), - {B,[Val,Tmp]} = mk_vars(Val1, [tmp]), + {B,Val} = enc_element(Pos, Val0), + {[],[[],Tmp]} = mk_vars([], [tmp]), Zero = {put_bits,0,1,[1]}, One = {put_bits,1,1,[1]}, B++[{call,M,F,[Val|A],Tmp}, {'cond', [[{eq,Tmp,true},Zero],['_',One]]}]; per_enc_optional(Val0, Pos, _Aligned) when is_integer(Pos) -> - Val1 = lists:concat(["element(",Pos,", ",Val0,")"]), - {B,[Val]} = mk_vars(Val1, []), + {B,Val} = enc_element(Pos, Val0), Zero = {put_bits,0,1,[1]}, One = {put_bits,1,1,[1]}, B++[{'cond',[[{eq,Val,asn1_NOVALUE},Zero], @@ -391,20 +418,22 @@ enc_append([H|T]) -> [{block,H}|enc_append(T)]; enc_append([]) -> []. -enc_bind_var(Val) -> - {B,[{var,Var}]} = mk_vars(Val, []), - {B,list_to_atom(Var)}. +enc_element(N, Val0) -> + {[],[Val,Dst]} = mk_vars(Val0, [element]), + {[{call,erlang,element,[N,Val],Dst}],Dst}. enc_cg(Imm0, false) -> Imm1 = enc_cse(Imm0), - Imm = enc_pre_cg(Imm1), + Imm2 = enc_pre_cg(Imm1), + Imm = enc_opt(Imm2), enc_cg(Imm); enc_cg(Imm0, true) -> Imm1 = enc_cse(Imm0), Imm2 = enc_hoist_align(Imm1), Imm3 = enc_opt_al(Imm2), Imm4 = per_fixup(Imm3), - Imm = enc_pre_cg(Imm4), + Imm5 = enc_pre_cg(Imm4), + Imm = enc_opt(Imm5), enc_cg(Imm). %%% @@ -881,6 +910,9 @@ dcg_list_outside([{call,Fun,{V,Buf},{Dst,DstBuf}}|T]) -> emit(["{",Dst,",",DstBuf,"} = "]), Fun(V, Buf), iter_dcg_list_outside(T); +dcg_list_outside([{convert,{M,F},V,Dst}|T]) -> + emit([Dst," = ",{asis,M},":",{asis,F},"(",V,")"]), + iter_dcg_list_outside(T); dcg_list_outside([{convert,Op,V,Dst}|T]) -> emit([Dst," = ",Op,"(",V,")"]), iter_dcg_list_outside(T); @@ -972,11 +1004,11 @@ mk_dest(S) -> S. split_off_nonbuilding(Imm) -> lists:splitwith(fun is_nonbuilding/1, Imm). -is_nonbuilding({apply,_,_,_}) -> true; is_nonbuilding({assign,_,_}) -> true; is_nonbuilding({call,_,_,_,_}) -> true; -is_nonbuilding({'cond',_,_}) -> true; is_nonbuilding({lc,_,_,_,_}) -> true; +is_nonbuilding({set,_,_}) -> true; +is_nonbuilding({list,_,_}) -> true; is_nonbuilding({sub,_,_,_}) -> true; is_nonbuilding({'try',_,_,_,_}) -> true; is_nonbuilding(_) -> false. @@ -986,17 +1018,13 @@ mk_vars(Input0, Temps) -> Curr = asn1ct_name:curr(enc), [H|T] = atom_to_list(Curr), Base = [H - ($a - $A)|T ++ "@"], - if - is_atom(Input0) -> - Input = {var,atom_to_list(Input0)}, - {[],[Input|mk_vars_1(Base, Temps)]}; - is_integer(Input0) -> + case Input0 of + {var,Name} when is_list(Name) -> {[],[Input0|mk_vars_1(Base, Temps)]}; - Input0 =:= [] -> + [] -> {[],[Input0|mk_vars_1(Base, Temps)]}; - true -> - Input = mk_var(Base, input), - {[{assign,Input,Input0}],[Input|mk_vars_1(Base, Temps)]} + _ when is_integer(Input0) -> + {[],[Input0|mk_vars_1(Base, Temps)]} end. mk_vars_1(Base, Vars) -> @@ -1143,8 +1171,15 @@ per_enc_length(Bin, Unit, Len, {Lb,Ub}, Aligned, Type) U = unit(Unit, Aligned, Type, Lb*Unit, Ub*Unit), PutBits = [{put_bits,Bin,binary,U}], build_length_cond(Prefix, [[Check|PutLen++PutBits]]); -per_enc_length(Bin, Unit, Len, Sv, Aligned, Type) when is_integer(Sv) -> - NumBits = Sv*Unit, +per_enc_length(Bin, Unit0, Len, Sv, Aligned, Type) when is_integer(Sv) -> + NumBits = Sv*Unit0, + Unit = case NumBits rem 8 of + 0 -> + %% Help out the alignment optimizer. + 8; + _ -> + Unit0 + end, U = unit(Unit, Aligned, Type, NumBits, NumBits), Pb = {put_bits,Bin,binary,U}, [{'cond',[[{eq,Len,Sv},Pb]]}]. @@ -1358,58 +1393,6 @@ opt_choice_2([_|_], _) -> throw(impossible); opt_choice_2([], _) -> []. - -%%% -%%% Helper functions for code generation of open types. -%%% - -per_enc_open_type(Val0, {ToBinMod,ToBinFunc}, Aligned) -> - {B,[Val,Len,Bin]} = mk_vars(Val0, [len,bin]), - B ++ [{call,ToBinMod,ToBinFunc,[Val],Bin}, - {call,erlang,byte_size,[Bin],Len}| - per_enc_length(Bin, 8, Len, Aligned)]. - -enc_open_type([{'cond',Cs}], Aligned) -> - [{'cond',[[C|enc_open_type_1(Act, Aligned)] || [C|Act] <- Cs]}]; -enc_open_type(_, _) -> - throw(impossible). - -enc_open_type_1([{error,_}]=Imm, _) -> - Imm; -enc_open_type_1(Imm, Aligned) -> - NumBits = num_bits(Imm, 0), - Pad = case 8 - (NumBits rem 8) of - 8 -> []; - Pad0 -> [{put_bits,0,Pad0,[1]}] - end, - NumBytes = (NumBits+7) div 8, - enc_length(NumBytes, no, Aligned) ++ Imm ++ Pad. - -num_bits([{put_bits,_,N,[U|_]}|T], Sum) when is_integer(N) -> - num_bits(T, Sum+N*U); -num_bits([_|_], _) -> - throw(impossible); -num_bits([], Sum) -> Sum. - -per_enc_open_type_output([{apply,F,A}], Acc) -> - Dst = output_var(), - {Dst,lists:reverse(Acc, [{apply,F,A,{var,atom_to_list(Dst)}}])}; -per_enc_open_type_output([{call,M,F,A}], Acc) -> - Dst = output_var(), - {Dst,lists:reverse(Acc, [{call,M,F,A,{var,atom_to_list(Dst)}}])}; -per_enc_open_type_output([{'cond',Cs}], Acc) -> - Dst = output_var(), - {Dst,lists:reverse(Acc, [{'cond',Cs,{var,atom_to_list(Dst)}}])}; -per_enc_open_type_output([H|T], Acc) -> - per_enc_open_type_output(T, [H|Acc]). - -output_var() -> - asn1ct_name:new(enc), - Curr = asn1ct_name:curr(enc), - [H|T] = atom_to_list(Curr), - list_to_atom([H - ($a - $A)|T ++ "@output"]). - - %%% %%% Optimize list comprehensions (SEQUENCE OF/SET OF). %%% @@ -1587,16 +1570,16 @@ collect_put_bits(Imm) -> %%% the same element twice. %%% -enc_cse([{assign,{var,V},E}=H|T]) -> - [H|enc_cse_1(T, E, V)]; +enc_cse([{call,erlang,element,Args,V}=H|T]) -> + [H|enc_cse_1(T, Args, V)]; enc_cse(Imm) -> Imm. -enc_cse_1([{assign,Dst,E}|T], E, V) -> - [{assign,Dst,V}|enc_cse_1(T, E, V)]; -enc_cse_1([{block,Bl}|T], E, V) -> - [{block,enc_cse_1(Bl, E, V)}|enc_cse_1(T, E, V)]; -enc_cse_1([H|T], E, V) -> - [H|enc_cse_1(T, E, V)]; +enc_cse_1([{call,erlang,element,Args,Dst}|T], Args, V) -> + [{set,V,Dst}|enc_cse_1(T, Args, V)]; +enc_cse_1([{block,Bl}|T], Args, V) -> + [{block,enc_cse_1(Bl, Args, V)}|enc_cse_1(T, Args, V)]; +enc_cse_1([H|T], Args, V) -> + [H|enc_cse_1(T, Args, V)]; enc_cse_1([], _, _) -> []. @@ -1637,7 +1620,7 @@ enc_pre_cg_2({block,Bl0}, StL, StB) -> enc_pre_cg_1(Bl0, StL, StB); enc_pre_cg_2({call,_,_,_}=Imm, _, _) -> Imm; -enc_pre_cg_2({call_gen,_,_,_,_}=Imm, _, _) -> +enc_pre_cg_2({call_gen,_,_,_,_,_}=Imm, _, _) -> Imm; enc_pre_cg_2({'cond',Cs0}, StL, _StB) -> Cs = [{C,enc_pre_cg_1(Act, StL, outside_seq)} || [C|Act] <- Cs0], @@ -1662,18 +1645,22 @@ enc_pre_cg_2({var,_}=Imm, _, _) -> Imm. enc_make_cons({binary,H}, {binary,T}) -> {binary,H++T}; enc_make_cons({binary,H0}, {cons,{binary,H1},T}) -> - {cons,{binary,H0++H1},T}; + enc_make_cons({binary,H0++H1}, T); +enc_make_cons({binary,H}, {cons,{integer,Int},T}) -> + enc_make_cons({binary,H++[{put_bits,Int,8,[1]}]}, T); enc_make_cons({integer,Int}, {binary,T}) -> {binary,[{put_bits,Int,8,[1]}|T]}; +enc_make_cons({integer,Int}, {cons,{binary,H},T}) -> + enc_make_cons({binary,[{put_bits,Int,8,[1]}|H]}, T); enc_make_cons(H, T) -> {cons,H,T}. -enc_pre_cg_nonbuilding({'cond',Cs0,Dst}, StL) -> - Cs = [{C,enc_pre_cg_1(Act, StL, outside_seq)} || [C|Act] <- Cs0], - {'cond',Cs,Dst}; enc_pre_cg_nonbuilding({lc,B0,Var,List,Dst}, StL) -> B = enc_pre_cg_1(B0, StL, outside_seq), {lc,B,Var,List,Dst}; +enc_pre_cg_nonbuilding({list,List0,Dst}, _StL) -> + List = enc_pre_cg_1(List0, outside_list, outside_seq), + {list,List,Dst}; enc_pre_cg_nonbuilding({'try',Try0,{P,Succ0},Else0,Dst}, StL) -> Try = enc_pre_cg_1(Try0, StL, outside_seq), Succ = enc_pre_cg_1(Succ0, StL, outside_seq), @@ -1681,6 +1668,562 @@ enc_pre_cg_nonbuilding({'try',Try0,{P,Succ0},Else0,Dst}, StL) -> {'try',Try,{P,Succ},Else,Dst}; enc_pre_cg_nonbuilding(Imm, _) -> Imm. +%%% +%%% Optimize calls to complete/1 and surrounding code. There are +%%% several opportunities for optimizations. +%%% +%%% It may be possible to replace the call to complete/1 with +%%% something cheaper (most important for the PER back-end which has +%%% an expensive complete/1 implementation). If we can be sure that +%%% complete/1 will be called with an iolist (no 'align' atoms or +%%% bitstrings in the list), we can call iolist_to_binary/1 +%%% instead. If the list may include bitstrings, we can can call +%%% list_to_bitstring/1 (note that list_to_bitstring/1 does not accept +%%% a binary or bitstring, so we MUST be sure that we only pass it a +%%% list). If complete/1 is called with a binary, we can omit the +%%% call altogether. +%%% +%%% A call to byte_size/1 that follows complete/1 can be eliminated +%%% if the size of the binary produced by complete/1 can be determined +%%% and is constant. +%%% +%%% The code that encodes the length descriptor (a 'cond' instruction) +%%% for a binary produced by complete/1 can be simplified if the lower +%%% and upper bounds for the size of the binary are known. +%%% + +-record(ost, + {sym, + t + }). + +enc_opt(Imm0) -> + {Imm,_} = enc_opt(Imm0, #ost{sym=gb_trees:empty()}), + Imm. + +enc_opt(align, St) -> + {align,St#ost{t=t_align({0,7})}}; +enc_opt({apply,What,As}, St) -> + {{apply,What,subst_list(As, St)},St#ost{t=t_any()}}; +enc_opt({assign,_,_}=Imm, St) -> + {Imm,St}; +enc_opt({binary,PutBits0}, St) -> + PutBits = [{put_bits,subst(V, St),Sz,F} || + {put_bits,V,Sz,F} <- PutBits0], + NumBits = lists:foldl(fun({put_bits,_,Bits,_}, Sum) -> + Sum+Bits + end, 0, PutBits), + {{binary,PutBits},St#ost{t=t_bitstring(NumBits)}}; +enc_opt({block,Bl0}, St0) -> + {Bl,St} = enc_opt(Bl0, St0), + {{block,Bl},St}; +enc_opt({call,binary,encode_unsigned,[Int],Bin}=Imm, St0) -> + Type = get_type(Int, St0), + St = case t_range(Type) of + any -> + set_type(Bin, t_binary(), St0); + {Lb0,Ub0} -> + Lb = bit_size(binary:encode_unsigned(Lb0)), + Ub = bit_size(binary:encode_unsigned(Ub0)), + set_type(Bin, t_binary({Lb,Ub}), St0) + end, + {Imm,St}; +enc_opt({call,erlang,bit_size,[Bin],Dst}=Imm0, St0) -> + Type = get_type(Bin, St0), + case t_range(Type) of + any -> + St1 = set_type(Bin, t_bitstring(), St0), + St = propagate(Dst, + fun(T, S) -> + bit_size_propagate(Bin, T, S) + end, St1), + {Imm0,St}; + {Lb,Ub}=Range -> + St = set_type(Dst, t_integer(Range), St0), + Imm = case Lb of + Ub -> none; + _ -> Imm0 + end, + {Imm,St} + end; +enc_opt({call,erlang,byte_size,[Bin],Dst}=Imm0, St0) -> + Type = get_type(Bin, St0), + case t_range(Type) of + any -> + St1 = set_type(Bin, t_binary(), St0), + St = propagate(Dst, + fun(T, S) -> + byte_size_propagate(Bin, T, S) + end, St1), + {Imm0,St}; + {Lb0,Ub0} -> + Lb = (Lb0+7) div 8, + Ub = (Ub0+7) div 8, + St = set_type(Dst, t_integer({Lb,Ub}), St0), + Imm = case Lb of + Ub -> none; + _ -> Imm0 + end, + {Imm,St} + end; +enc_opt({call,erlang,iolist_to_binary,_}=Imm, St) -> + {Imm,St#ost{t=t_binary()}}; +enc_opt({call,erlang,length,[List],Dst}=Imm0, St0) -> + St1 = propagate(Dst, + fun(T, S) -> + length_propagate(List, T, S) + end, St0), + {Imm0,St1}; +enc_opt({call,per,complete,[Data],Dst}, St0) -> + Type = get_type(Data, St0), + St = set_type(Dst, t_binary(t_range(Type)), St0), + case t_type(Type) of + binary -> + {{set,Data,Dst},St}; + bitlist -> + %% We KNOW that list_to_bitstring/1 will construct + %% a binary (the number of bits is divisible by 8) + %% because per_enc_open_type/2 added an 'align' atom + %% at the end. If that 'align' atom had not been + %% optimized away, the type would have been 'align' + %% instead of 'bitlist'. + {{call,erlang,list_to_bitstring,[Data],Dst},St}; + iolist -> + {{call,erlang,iolist_to_binary,[Data],Dst},St}; + nil -> + Imm = {list,{binary,[{put_bits,0,8,[1]}]},Dst}, + enc_opt(Imm, St0); + _ -> + {{call,per,complete,[Data],Dst},St} + end; +enc_opt({call,uper,complete,[Data],Dst}, St0) -> + Type = get_type(Data, St0), + St = set_type(Dst, t_binary(t_range(Type)), St0), + case t_type(Type) of + binary -> + {{set,Data,Dst},St0}; + iolist -> + {{call,erlang,iolist_to_binary,[Data],Dst},St}; + nil -> + Imm = {list,{binary,[{put_bits,0,8,[1]}]},Dst}, + enc_opt(Imm, St0); + _ -> + %% 'bitlist' or 'any'. + {{call,uper,complete,[Data],Dst},St} + end; +enc_opt({call,per_common,encode_chars,[List,NumBits|_],Dst}=Imm, St0) -> + %% Note: Never used when NumBits =:= 8 (list_to_binary/1 will + %% be used instead). + St1 = set_type(Dst, t_bitstring(), St0), + St = propagate(List, + fun(T, S) -> + char_propagate(Dst, T, NumBits, S) + end, St1), + {Imm,St}; +enc_opt({call,per_common,encode_chars_16bit,[List],Dst}=Imm, St0) -> + St1 = set_type(Dst, t_binary(), St0), + St = propagate(List, + fun(T, S) -> + char_propagate(Dst, T, 16, S) + end, St1), + {Imm,St}; +enc_opt({call,per_common,encode_big_chars,[List],Dst}=Imm, St0) -> + St1 = set_type(Dst, t_binary(), St0), + St = propagate(List, + fun(T, S) -> + char_propagate(Dst, T, 32, S) + end, St1), + {Imm,St}; +enc_opt({call,per_common,encode_fragmented,[_,Unit]}=Imm, St) -> + T = case Unit rem 8 of + 0 -> t_iolist(); + _ -> t_bitlist() + end, + {Imm,St#ost{t=T}}; +enc_opt({call,per_common,encode_unconstrained_number,_}=Imm, St) -> + {Imm,St#ost{t=t_iolist()}}; +enc_opt({call,per_common,bitstring_from_positions,_}=Imm, St) -> + {Imm,St#ost{t=t_bitstring()}}; +enc_opt({call,per_common,to_named_bitstring,_}=Imm, St) -> + {Imm,St#ost{t=t_bitstring()}}; +enc_opt({call,_,_,_}=Imm, St) -> + {Imm,St#ost{t=t_any()}}; +enc_opt({call,_,_,_,_}=Imm, St) -> + {Imm,St#ost{t=undefined}}; +enc_opt({call_gen,N,K,F,L,As}, St) -> + {{call_gen,N,K,F,L,subst(As, St)},St#ost{t=t_any()}}; +enc_opt({'cond',Cs0}, St0) -> + case enc_opt_cs(Cs0, St0) of + [{'_',Imm,Type}] -> + {Imm,St0#ost{t=Type}}; + [{Cond,Imm,Type0}|Cs1] -> + {Cs,Type} = enc_opt_cond_1(Cs1, Type0, [{Cond,Imm}]), + {{'cond',Cs},St0#ost{t=Type}} + end; +enc_opt({cons,H0,T0}, St0) -> + {H,#ost{t=TypeH}=St1} = enc_opt(H0, St0), + {T,#ost{t=TypeT}=St} = enc_opt(T0, St1), + {{cons,H,T},St#ost{t=t_cons(TypeH, TypeT)}}; +enc_opt({error,_}=Imm, St) -> + {Imm,St#ost{t=t_any()}}; +enc_opt({integer,V}, St) -> + {{integer,subst(V, St)},St#ost{t=t_integer()}}; +enc_opt({lc,E0,B,C}, St) -> + {E,_} = enc_opt(E0, St), + {{lc,E,B,C},St#ost{t=t_any()}}; +enc_opt({lc,E0,B,C,Dst}, St) -> + {E,_} = enc_opt(E0, St), + {{lc,E,B,C,Dst},St#ost{t=undefined}}; +enc_opt({list,Imm0,Dst}, St0) -> + {Imm,#ost{t=Type}=St1} = enc_opt(Imm0, St0), + St = set_type(Dst, Type, St1), + {{list,Imm,Dst},St#ost{t=undefined}}; +enc_opt(nil, St) -> + {nil,St#ost{t=t_nil()}}; +enc_opt({seq,H0,T0}, St0) -> + {H,St1} = enc_opt(H0, St0), + {T,St} = enc_opt(T0, St1), + case {H,T} of + {none,_} -> + {T,St}; + {{list,Imm,Data}, + {seq,{call,per,complete,[Data],_},_}} -> + %% Get rid of any explicit 'align' added by per_enc_open_type/2. + {{seq,{list,remove_trailing_align(Imm),Data},T},St}; + {_,_} -> + {{seq,H,T},St} + end; +enc_opt({set,_,_}=Imm, St) -> + {Imm,St#ost{t=undefined}}; +enc_opt({sub,Src0,Int,Dst}, St0) -> + Src = subst(Src0, St0), + Type = get_type(Src, St0), + St = case t_range(Type) of + any -> + propagate(Dst, + fun(T, S) -> + set_type(Src, t_add(T, Int), S) + end, + St0); + {Lb,Ub} -> + set_type(Dst, t_integer({Lb-Int,Ub-Int}), St0) + end, + {{sub,Src,Int,Dst},St#ost{t=undefined}}; +enc_opt({'try',Try0,{P,Succ0},Else0,Dst}, St0) -> + {Try,_} = enc_opt(Try0, St0), + {Succ,_} = enc_opt(Succ0, St0), + {Else,_} = enc_opt(Else0, St0), + {{'try',Try,{P,Succ},Else,Dst},St0#ost{t=undefined}}; +enc_opt({var,_}=Imm, St) -> + Type = get_type(Imm, St), + {subst(Imm, St),St#ost{t=Type}}. + +remove_trailing_align({block,Bl}) -> + {block,remove_trailing_align(Bl)}; +remove_trailing_align({cons,H,{cons,align,nil}}) -> + H; +remove_trailing_align({seq,H,T}) -> + {seq,H,remove_trailing_align(T)}; +remove_trailing_align(Imm) -> Imm. + +bit_size_propagate(Bin, Type, St) -> + case t_range(Type) of + any -> + St; + {Lb,Ub} -> + set_type(Bin, t_bitstring({Lb,Ub}), St) + end. + +byte_size_propagate(Bin, Type, St) -> + case t_range(Type) of + any -> + St; + {Lb,Ub} -> + set_type(Bin, t_binary({Lb*8,Ub*8}), St) + end. + +char_propagate(Dst, T, NumBits, St) -> + case t_range(T) of + any -> + St; + {Sz,Sz} when Sz*NumBits rem 8 =:= 0 -> + Bits = Sz*NumBits, + set_type(Dst, t_binary({Bits,Bits}), St); + {Lb,Ub} -> + Range = {Lb*NumBits,Ub*NumBits}, + case NumBits rem 8 of + 0 -> + set_type(Dst, t_binary(Range), St); + _ -> + set_type(Dst, t_bitstring(Range), St) + end + end. + +length_propagate(List, Type, St) -> + set_type(List, t_list(t_range(Type)), St). + +enc_opt_cond_1([{Cond,{error,_}=Imm,_}|T], St, Acc) -> + enc_opt_cond_1(T, St, [{Cond,Imm}|Acc]); +enc_opt_cond_1([{Cond,Imm,Curr0}|T], Curr1, Acc) -> + Curr = t_join(Curr0, Curr1), + enc_opt_cond_1(T, Curr, [{Cond,Imm}|Acc]); +enc_opt_cond_1([], St, Acc) -> + {lists:reverse(Acc),St}. + +enc_opt_cs([{Cond,Imm0}|T], St0) -> + case eo_eval_cond(Cond, St0) of + false -> + enc_opt_cs(T, St0); + true -> + {Imm,#ost{t=Type}} = enc_opt(Imm0, St0), + [{'_',Imm,Type}]; + maybe -> + St = update_type_info(Cond, St0), + {Imm,#ost{t=Type}} = enc_opt(Imm0, St), + [{Cond,Imm,Type}|enc_opt_cs(T, St0)] + end; +enc_opt_cs([], _) -> []. + +eo_eval_cond('_', _) -> + true; +eo_eval_cond({Op,{var,_}=Var,Val}, St) -> + Type = get_type(Var, St), + case t_range(Type) of + any -> maybe; + {_,_}=Range -> eval_cond_range(Op, Range, Val) + end; +eo_eval_cond({_Op,{expr,_},_Val}, _St) -> maybe. + +eval_cond_range(lt, {Lb,Ub}, Val) -> + if + Ub < Val -> true; + Val =< Lb -> false; + true -> maybe + end; +eval_cond_range(_Op, _Range, _Val) -> maybe. + +update_type_info({ult,{var,_}=Var,Val}, St) -> + Int = t_integer({0,Val-1}), + Type = t_meet(get_type(Var, St), Int), + set_type(Var, Type, St); +update_type_info({lt,{var,_}=Var,Val}, St) -> + Int = t_integer({0,Val-1}), + Type = t_meet(get_type(Var, St), Int), + set_type(Var, Type, St); +update_type_info({eq,{var,_}=Var,Val}, St) when is_integer(Val) -> + Int = t_integer(Val), + Type = t_meet(get_type(Var, St), Int), + set_type(Var, Type, St); +update_type_info({eq,_,_}, St) -> + St; +update_type_info({ge,_,_}, St) -> St. + +subst_list(As, St) -> + [subst(A, St) || A <- As]. + +subst({var,_}=Var, St) -> + Type = get_type(Var, St), + case t_type(Type) of + integer -> + case t_range(Type) of + any -> Var; + {Val,Val} -> Val; + {_,_} -> Var + end; + _ -> + Var + end; +subst(V, _St) -> V. + +set_type({var,Var}, {_,_}=Type, #ost{sym=Sym0}=St0) -> + Sym1 = gb_trees:enter(Var, Type, Sym0), + case gb_trees:lookup({propagate,Var}, Sym1) of + none -> + St0#ost{sym=Sym1}; + {value,Propagate} -> + Sym = gb_trees:delete({propagate,Var}, Sym1), + St = St0#ost{sym=Sym}, + Propagate(Type, St) + end. + +get_type({var,V}, #ost{sym=Sym}) -> + case gb_trees:lookup(V, Sym) of + none -> t_any(); + {value,T} -> T + end. + +propagate({var,Var}, Propagate, #ost{sym=Sym0}=St) when is_function(Propagate, 2) -> + Sym = gb_trees:enter({propagate,Var}, Propagate, Sym0), + St#ost{sym=Sym}. + +%%% +%%% A simple type system. +%%% +%%% Each type descriptions is a tuple {Type,Range}. +%%% Type is one of the following atoms: +%%% +%%% Type name Description +%%% --------- ----------- +%%% any Anything. +%%% +%%% align Basically iodata, but the list may contain bitstrings +%%% and the the atom 'align'. Can be passed to complete/1 +%%% to construct a binary. Only used for aligned PER (per). +%%% +%%% bitstring An Erlang bitstring. +%%% +%%% bitlist A list that may be passed to list_to_bitstring/1 to +%%% construct a bitstring. +%%% NOTE: When analysing aligned PER (per), the number +%%% of bits in the bitlist is always divisible by 8 (if +%%% not, the type will be 'align' instead). +%%% +%%% binary An Erlang binary (the number of bits is divisible by 8). +%%% +%%% iolist An Erlang iolist. +%%% +%%% nil [] +%%% +%%% integer An integer. +%%% +%%% +%%% Range is one of: +%%% +%%% any +%%% {LowerBound,UpperBound} +%%% +%%% + +t_align(Range) -> + {align,t__range(Range)}. + +t_any() -> + {any,any}. + +t_binary() -> + {binary,any}. + +t_binary(Range) -> + {binary,t__range(Range)}. + +t_bitlist() -> + {bitlist,any}. + +t_bitstring() -> + {bitstring,any}. + +t_bitstring(Range0) -> + case t__range(Range0) of + {Bits,Bits}=Range when Bits rem 8 =:= 0 -> + {binary,Range}; + Range -> + {bitstring,Range} + end. + +t_add({integer,{Lb,Ub}}, N) -> + {integer,{Lb+N,Ub+N}}. + +t_cons({_,_}=T1, {_,_}=T2) -> + T = case {t__cons_type(T1),t__cons_type(T2)} of + {_,any} -> any; + {any,_} -> any; + {align,_} -> align; + {_,align} -> align; + {binary,binary} -> iolist; + {binary,bitstring} -> bitlist; + {bitstring,binary} -> bitlist; + {bitstring,bitstring} -> bitlist + end, + {T,t__cons_ranges(t__cons_range(T1), t__cons_range(T2))}. + +t_integer() -> + {integer,any}. + +t_integer(Range) -> + {integer,t__range(Range)}. + +t_iolist() -> + {iolist,any}. + +t_list(Range) -> + {list,t__range(Range)}. + +t_nil() -> + {nil,{0,0}}. + +t_meet({T1,Range1}, {T2,Range2}) -> + {t_meet_types(T1, T2),t_meet_ranges(Range1, Range2)}. + +t_meet_types(integer, integer) -> integer; +t_meet_types(any, integer) -> integer. + +t_meet_ranges(any, Range) -> + Range; +t_meet_ranges({Lb1,Ub1}, {Lb2,Ub2}) -> + if + Lb1 =< Ub2, Lb2 =< Ub1 -> + {max(Lb1, Lb2),Ub1}; + Lb2 =< Ub1, Lb1 =< Ub2 -> + {max(Lb1, Lb2),Ub2} + end. + +t_join({T1,Range1}, {T2,Range2}) -> + T = t_join_types(lists:sort([T1,T2])), + Range = t_join_ranges(Range1, Range2), + {T,Range}. + +t_join_ranges({Lb1,Ub1}, {Lb2,Ub2}) -> + {min(Lb1, Lb2),max(Ub1, Ub2)}; +t_join_ranges(any, _) -> any; +t_join_ranges(_, any) -> any. + +t_join_types([T,T]) -> T; +t_join_types([align,any]) -> any; +t_join_types([align,_]) -> align; +t_join_types([any,_]) -> any; +t_join_types([bitlist,bitstring]) -> any; +t_join_types([bitlist,integer]) -> any; +t_join_types([bitlist,iolist]) -> bitlist; +t_join_types([bitlist,nil]) -> bitlist; +t_join_types([binary,bitlist]) -> bitlist; +t_join_types([binary,bitstring]) -> bitstring; +t_join_types([binary,integer]) -> binary; +t_join_types([binary,iolist]) -> iolist; +t_join_types([binary,nil]) -> iolist; +t_join_types([bitstring,integer]) -> any; +t_join_types([bitstring,iolist]) -> any; +t_join_types([bitstring,nil]) -> any; +t_join_types([integer,_]) -> any; +t_join_types([iolist,nil]) -> iolist. + +t_type({T,_}) -> T. + +t_range({_,Range}) -> Range. + +t__cons_type({align,_}) -> align; +t__cons_type({any,_}) -> any; +t__cons_type({binary,_}) -> binary; +t__cons_type({bitstring,_}) -> bitstring; +t__cons_type({bitlist,_}) -> bitstring; +t__cons_type({integer,_}) -> binary; +t__cons_type({iolist,_}) -> binary; +t__cons_type({nil,_}) -> binary. + +t__cons_range({integer,_}) -> {8,8}; +t__cons_range({_,Range}) -> Range. + +t__cons_ranges({Lb1,Ub1}, {Lb2,Ub2}) -> + {Lb1+Lb2,Ub1+Ub2}; +t__cons_ranges(any, _) -> any; +t__cons_ranges(_, any) -> any. + +t__range({Lb,Ub}=Range) when is_integer(Lb), is_integer(Ub) -> + Range; +t__range(any) -> + any; +t__range(Val) when is_integer(Val) -> + {Val,Val}. + %%% %%% Code generation for encoding. @@ -1702,19 +2245,10 @@ enc_cg(align) -> enc_cg({apply,F0,As0}) -> As = enc_call_args(As0, ""), case F0 of - {M,F} -> - emit([{asis,M},":",{asis,F},"(",As,")"]); - F when is_atom(F) -> - emit([{asis,F},"(",As,")"]) - end; -enc_cg({apply,F0,As0,Dst}) -> - As = enc_call_args(As0, ""), - emit([mk_val(Dst)," = "]), - case F0 of - {M,F} -> - emit([{asis,M},":",{asis,F},"(",As,")"]); - F when is_atom(F) -> - emit([{asis,F},"(",As,")"]) + {local,F,_} when is_atom(F) -> + emit([{asis,F},"(",As,")"]); + {M,F,_} -> + emit([{asis,M},":",{asis,F},"(",As,")"]) end; enc_cg({assign,Dst0,Expr}) -> Dst = mk_val(Dst0), @@ -1728,15 +2262,11 @@ enc_cg({call,M,F,As0,Dst}) -> As = [mk_val(A) || A <- As0], emit([mk_val(Dst)," = "]), asn1ct_func:call(M, F, As); -enc_cg({call_gen,Prefix,Key,Gen,As0}) -> +enc_cg({call_gen,Prefix,Key,Gen,_,As0}) -> As = [mk_val(A) || A <- As0], asn1ct_func:call_gen(Prefix, Key, Gen, As); enc_cg({'cond',Cs}) -> enc_cg_cond(Cs); -enc_cg({'cond',Cs,Dst0}) -> - Dst = mk_val(Dst0), - emit([Dst," = "]), - enc_cg_cond(Cs); enc_cg({error,Error}) when is_function(Error, 0) -> Error(); enc_cg({error,Var0}) -> @@ -1752,12 +2282,17 @@ enc_cg({lc,Body,Var,List,Dst}) -> emit([mk_val(Dst)," = ["]), enc_cg(Body), emit([" || ",mk_val(Var)," <- ",mk_val(List),"]"]); +enc_cg({list,List,Dst}) -> + emit([mk_val(Dst)," = "]), + enc_cg(List); enc_cg(nil) -> emit("[]"); enc_cg({sub,Src0,Int,Dst0}) -> Src = mk_val(Src0), Dst = mk_val(Dst0), emit([Dst," = ",Src," - ",Int]); +enc_cg({set,{var,Src},{var,Dst}}) -> + emit([Dst," = ",Src]); enc_cg({'try',Try,{P,Succ},Else,Dst}) -> emit([mk_val(Dst)," = try "]), enc_cg(Try), @@ -1792,8 +2327,6 @@ enc_call_args([A|As], Sep) -> [Sep,mk_val(A)|enc_call_args(As, ", ")]; enc_call_args([], _) -> []. -enc_cg_cond([{'_',Action}]) -> - enc_cg(Action); enc_cg_cond(Cs) -> emit("if "), enc_cg_cond(Cs, ""), @@ -1849,7 +2382,7 @@ mk_val(Other) -> {asis,Other}. bit_string_name2pos_fun(NNL, Src) -> {call_gen,"bit_string_name2pos_",NNL, - fun(Fd, Name) -> gen_name2pos(Fd, Name, NNL) end,[Src]}. + fun(Fd, Name) -> gen_name2pos(Fd, Name, NNL) end,[],[Src]}. gen_name2pos(Fd, Name, Names) -> Cs0 = gen_name2pos_cs(Names, Name), @@ -1978,19 +2511,12 @@ enc_opt_al(Imm0) -> {Imm,_} = enc_opt_al_1(Imm0, unknown), Imm. -enc_opt_al_1([{'cond',Cs0,Dst},{call,per,complete,[Dst],Bin}|T0], Al0) -> - {Cs1,{M,F}} = enc_opt_al_prepare_cond(Cs0), - {Cs,_} = enc_opt_al_cond(Cs1, 0), - {T,Al} = enc_opt_al_1([{call,M,F,[Dst],Bin}|T0], Al0), - {[{'cond',Cs,Dst}|T],Al}; enc_opt_al_1([H0|T0], Al0) -> {H,Al1} = enc_opt_al(H0, Al0), {T,Al} = enc_opt_al_1(T0, Al1), {H++T,Al}; enc_opt_al_1([], Al) -> {[],Al}. -enc_opt_al({apply,_,_,_}=Imm, Al) -> - {[Imm],Al}; enc_opt_al({assign,_,_}=Imm, Al) -> {[Imm],Al}; enc_opt_al({block,Bl0}, Al0) -> @@ -2012,6 +2538,10 @@ enc_opt_al({'cond',Cs0}, Al0) -> {[{'cond',Cs}],Al}; enc_opt_al({error,_}=Imm, Al) -> {[Imm],Al}; +enc_opt_al({list,Imm0,Dst}, Al) -> + Imm1 = enc_opt_hoist_align(Imm0), + {Imm,_} = enc_opt_al_1(Imm1, 0), + {[{list,Imm,Dst}],Al}; enc_opt_al({put_bits,V,N,[U,align]}, Al0) when Al0 rem 8 =:= 0 -> Al = if is_integer(N) -> N*U; @@ -2038,8 +2568,12 @@ enc_opt_al({put_bits,_,N,[U]}=PutBits, Al) when is_integer(N), is_integer(Al) -> {[PutBits],Al+N*U}; enc_opt_al({put_bits,_,binary,[U]}=PutBits, Al) when U rem 8 =:= 0 -> {[PutBits],Al}; +enc_opt_al({set,_,_}=Imm, Al) -> + {[Imm],Al}; enc_opt_al({sub,_,_,_}=Imm, Al) -> {[Imm],Al}; +enc_opt_al({'try',_,_,_,_}=Imm, Al) -> + {[Imm],Al}; enc_opt_al(Imm, _) -> {[Imm],unknown}. @@ -2063,29 +2597,25 @@ enc_opt_al_cond_1([], _, CAcc, AAcc) -> end, {lists:reverse(CAcc),Al}. -enc_opt_al_prepare_cond(Cs0) -> - try enc_opt_al_prepare_cond_1(Cs0) of - Cs -> - {Cs,{erlang,iolist_to_binary}} +enc_opt_hoist_align([{'cond',Cs0},{put_bits,0,0,[1,align]}]=Imm) -> + try + Cs = [insert_align_last(C) || C <- Cs0], + [{'cond',Cs}] catch throw:impossible -> - {Cs0,{per,complete}} - end. - -enc_opt_al_prepare_cond_1(Cs) -> - [[C|enc_opt_al_prepare_cond_2(Act)] || [C|Act] <- Cs]. - -enc_opt_al_prepare_cond_2([{put_bits,_,binary,[U|_]}|_]) when U rem 8 =/= 0 -> - throw(impossible); -enc_opt_al_prepare_cond_2([{put_bits,_,_,_}=H|T]) -> - [H|enc_opt_al_prepare_cond_2(T)]; -enc_opt_al_prepare_cond_2([{call,per_common,encode_fragmented,_}=H|T]) -> - [H|enc_opt_al_prepare_cond_2(T)]; -enc_opt_al_prepare_cond_2([_|_]) -> - throw(impossible); -enc_opt_al_prepare_cond_2([]) -> - [{put_bits,0,0,[1,align]}]. + Imm + end; +enc_opt_hoist_align(Imm) -> Imm. +insert_align_last([_,{error,_}]=C) -> + C; +insert_align_last([H|T]) -> + case lists:last(T) of + {put_bits,_,_,_} -> + [H|T ++ [{put_bits,0,0,[1,align]}]]; + _ -> + throw(impossible) + end. %%% %%% For the aligned PER format, fix up the intermediate format @@ -2095,8 +2625,6 @@ enc_opt_al_prepare_cond_2([]) -> per_fixup([{apply,_,_}=H|T]) -> [H|per_fixup(T)]; -per_fixup([{apply,_,_,_}=H|T]) -> - [H|per_fixup(T)]; per_fixup([{block,Block}|T]) -> [{block,per_fixup(Block)}|per_fixup(T)]; per_fixup([{'assign',_,_}=H|T]) -> @@ -2104,14 +2632,11 @@ per_fixup([{'assign',_,_}=H|T]) -> per_fixup([{'cond',Cs0}|T]) -> Cs = [[C|per_fixup(Act)] || [C|Act] <- Cs0], [{'cond',Cs}|per_fixup(T)]; -per_fixup([{'cond',Cs0,Dst}|T]) -> - Cs = [[C|per_fixup(Act)] || [C|Act] <- Cs0], - [{'cond',Cs,Dst}|per_fixup(T)]; per_fixup([{call,_,_,_}=H|T]) -> [H|per_fixup(T)]; per_fixup([{call,_,_,_,_}=H|T]) -> [H|per_fixup(T)]; -per_fixup([{call_gen,_,_,_,_}=H|T]) -> +per_fixup([{call_gen,_,_,_,_,_}=H|T]) -> [H|per_fixup(T)]; per_fixup([{error,_}=H|T]) -> [H|per_fixup(T)]; @@ -2119,6 +2644,10 @@ per_fixup([{lc,B,V,L}|T]) -> [{lc,per_fixup(B),V,L}|per_fixup(T)]; per_fixup([{lc,B,V,L,Dst}|T]) -> [{lc,per_fixup(B),V,L,Dst}|per_fixup(T)]; +per_fixup([{list,Imm,Dst}|T]) -> + [{list,per_fixup(Imm),Dst}|per_fixup(T)]; +per_fixup([{set,_,_}=H|T]) -> + [H|per_fixup(T)]; per_fixup([{sub,_,_,_}=H|T]) -> [H|per_fixup(T)]; per_fixup([{'try',Try0,{P,Succ0},Else0,Dst}|T]) -> diff --git a/lib/asn1/src/asn1ct_table.erl b/lib/asn1/src/asn1ct_table.erl index a5eb6d0413..2eca80eda3 100644 --- a/lib/asn1/src/asn1ct_table.erl +++ b/lib/asn1/src/asn1ct_table.erl @@ -22,34 +22,25 @@ %% Table abstraction module for ASN.1 compiler -export([new/1]). --export([new/2]). -export([new_reuse/1]). --export([new_reuse/2]). -export([exists/1]). -export([size/1]). -export([insert/2]). -export([lookup/2]). -export([match/2]). -export([to_list/1]). --export([delete/1]). % TODO: Remove (since we run in a separate process) +-export([delete/1]). -%% Always creates a new table -new(Table) -> new(Table, []). -new(Table, Options) -> - TableId = case get(Table) of - undefined -> - ets:new(Table, Options); - _ -> - delete(Table), - ets:new(Table, Options) - end, +%% Always create a new table. +new(Table) -> + undefined = get(Table), %Assertion. + TableId = ets:new(Table, []), put(Table, TableId). -%% Only create it if it doesn't exist yet -new_reuse(Table) -> new_reuse(Table, []). -new_reuse(Table, Options) -> - not exists(Table) andalso new(Table, Options). +%% Only create it if it doesn't exist yet. +new_reuse(Table) -> + not exists(Table) andalso new(Table). exists(Table) -> get(Table) =/= undefined. @@ -63,14 +54,17 @@ match(Table, MatchSpec) -> ets:match(get(Table), MatchSpec). to_list(Table) -> ets:tab2list(get(Table)). +%% Deleting tables is no longer strictly necessary since each compilation +%% runs in separate process, but it will reduce memory consumption +%% especially when many compilations are run in parallel. + delete(Tables) when is_list(Tables) -> [delete(T) || T <- Tables], true; delete(Table) when is_atom(Table) -> - case get(Table) of + case erase(Table) of undefined -> true; TableId -> - ets:delete(TableId), - erase(Table) + ets:delete(TableId) end. diff --git a/lib/asn1/src/asn1ct_tok.erl b/lib/asn1/src/asn1ct_tok.erl index 85199c65ec..33f4379173 100644 --- a/lib/asn1/src/asn1ct_tok.erl +++ b/lib/asn1/src/asn1ct_tok.erl @@ -36,7 +36,7 @@ process(Stream,Lno,R) -> process(io:get_line(Stream, ''), Stream,Lno+1,R). process(eof, Stream,Lno,R) -> - file:close(Stream), + ok = file:close(Stream), lists:flatten(lists:reverse([{'$end',Lno}|R])); diff --git a/lib/asn1/src/asn1ct_value.erl b/lib/asn1/src/asn1ct_value.erl index 862b3c4ea5..221cd991a7 100644 --- a/lib/asn1/src/asn1ct_value.erl +++ b/lib/asn1/src/asn1ct_value.erl @@ -18,6 +18,7 @@ %% %% -module(asn1ct_value). +-compile([{nowarn_deprecated_function,{asn1rt,utf8_list_to_binary,1}}]). %% Generate Erlang values for ASN.1 types. %% The value is randomized within it's constraints @@ -260,7 +261,11 @@ from_type_prim(M, D) -> 'BOOLEAN' -> true; 'OCTET STRING' -> - adjust_list(size_random(C),c_string(C,"OCTET STRING")); + S0 = adjust_list(size_random(C), c_string(C, "OCTET STRING")), + case M:legacy_erlang_types() of + false -> list_to_binary(S0); + true -> S0 + end; 'NumericString' -> adjust_list(size_random(C),c_string(C,"0123456789")); 'TeletexString' -> @@ -348,7 +353,7 @@ random_unnamed_bit_string(M, C) -> random(Upper) -> {A1,A2,A3} = erlang:now(), - random:seed(A1,A2,A3), + _ = random:seed(A1, A2, A3), random:uniform(Upper). size_random(C) -> diff --git a/lib/asn1/src/asn1rt.erl b/lib/asn1/src/asn1rt.erl index d18f81346a..ad8b879c38 100644 --- a/lib/asn1/src/asn1rt.erl +++ b/lib/asn1/src/asn1rt.erl @@ -18,14 +18,13 @@ %% %% -module(asn1rt). +-deprecated(module). %% Runtime functions for ASN.1 (i.e encode, decode) -export([encode/2,encode/3,decode/3,load_driver/0,unload_driver/0,info/1]). -export([utf8_binary_to_list/1,utf8_list_to_binary/1]). - --deprecated([load_driver/0,unload_driver/0]). encode(Module,{Type,Term}) -> encode(Module,Type,Term). diff --git a/lib/asn1/src/asn1rt_nif.erl b/lib/asn1/src/asn1rt_nif.erl index c1879e3dcf..1a44f1a27c 100644 --- a/lib/asn1/src/asn1rt_nif.erl +++ b/lib/asn1/src/asn1rt_nif.erl @@ -30,7 +30,7 @@ -define(ASN1_NIF_VSN,1). load_nif() -> - LibBaseName = "asn1_erl_nif", + LibBaseName = "asn1rt_nif", PrivDir = code:priv_dir(asn1), LibName = case erlang:system_info(build_type) of opt -> diff --git a/lib/asn1/src/asn1rtt_ber.erl b/lib/asn1/src/asn1rtt_ber.erl index 583ff790b7..4bd814769f 100644 --- a/lib/asn1/src/asn1rtt_ber.erl +++ b/lib/asn1/src/asn1rtt_ber.erl @@ -29,6 +29,8 @@ decode_integer/2,decode_integer/3, decode_named_integer/3,decode_named_integer/4, encode_enumerated/2,decode_enumerated/3, + encode_unnamed_bit_string/2,encode_unnamed_bit_string/3, + encode_named_bit_string/3,encode_named_bit_string/4, encode_bit_string/4, decode_named_bit_string/3, decode_compact_bit_string/3, @@ -38,6 +40,7 @@ encode_relative_oid/2,decode_relative_oid/2, encode_object_identifier/2,decode_object_identifier/2, encode_restricted_string/2, + decode_octet_string/2,decode_octet_string/3, decode_restricted_string/2,decode_restricted_string/3, encode_universal_string/2,decode_universal_string/3, encode_UTF8_string/2,decode_UTF8_string/2, @@ -780,6 +783,55 @@ decode_enumerated1(Val, NamedNumberList) -> {asn1_enum,Val} end. +%%============================================================================ +%% Bitstring value, ITU_T X.690 Chapter 8.6 +%% +%% encode bitstring value +%%============================================================================ + +encode_unnamed_bit_string(Bits, TagIn) -> + Unused = (8 - (bit_size(Bits) band 7)) band 7, + Bin = <<Unused,Bits/bitstring,0:Unused>>, + encode_tags(TagIn, Bin, byte_size(Bin)). + +encode_unnamed_bit_string(C, Bits, TagIn) -> + NumBits = bit_size(Bits), + Unused = (8 - (NumBits band 7)) band 7, + Bin = <<Unused,Bits/bitstring,0:Unused>>, + case C of + {_Min,Max} -> + if + NumBits > Max -> + exit({error,{asn1, + {bitstring_length, + {{was,NumBits},{maximum,Max}}}}}); + true -> + ok + end; + Size -> + if NumBits =< Size -> + ok; + true -> + exit({error,{asn1, + {bitstring_length, + {{was,NumBits},{should_be,Size}}}}}) + end + end, + encode_tags(TagIn, Bin, byte_size(Bin)). + +encode_named_bit_string([H|_]=Bits, NamedBitList, TagIn) when is_atom(H) -> + encode_bit_string_named([], Bits, NamedBitList, TagIn); +encode_named_bit_string([{bit,_}|_]=Bits, NamedBitList, TagIn) -> + encode_bit_string_named([], Bits, NamedBitList, TagIn); +encode_named_bit_string(Bits, _NamedBitList, TagIn) when is_bitstring(Bits) -> + encode_unnamed_bit_string(Bits, TagIn). + +encode_named_bit_string(C, [H|_]=Bits, NamedBitList, TagIn) when is_atom(H) -> + encode_bit_string_named(C, Bits, NamedBitList, TagIn); +encode_named_bit_string(C, [{bit,_}|_]=Bits, NamedBitList, TagIn) -> + encode_bit_string_named(C, Bits, NamedBitList, TagIn); +encode_named_bit_string(C, Bits, _NamedBitList, TagIn) when is_bitstring(Bits) -> + encode_unnamed_bit_string(C, Bits, TagIn). %%============================================================================ %% Bitstring value, ITU_T X.690 Chapter 8.6 @@ -1251,6 +1303,19 @@ encode_restricted_string(OctetList, TagIn) when is_list(OctetList) -> encode_tags(TagIn, OctetList, length(OctetList)). %%============================================================================ +%% decode OCTET STRING to binary +%%============================================================================ + +decode_octet_string(Tlv, TagsIn) -> + Bin = match_and_collect(Tlv, TagsIn), + binary:copy(Bin). + +decode_octet_string(Tlv, Range, TagsIn) -> + Bin0 = match_and_collect(Tlv, TagsIn), + Bin = binary:copy(Bin0), + check_restricted_string(Bin, byte_size(Bin), Range). + +%%============================================================================ %% decode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings %%============================================================================ diff --git a/lib/asn1/src/asn1rtt_ext.erl b/lib/asn1/src/asn1rtt_ext.erl index 46adb2007d..f3eee1cdd5 100644 --- a/lib/asn1/src/asn1rtt_ext.erl +++ b/lib/asn1/src/asn1rtt_ext.erl @@ -38,7 +38,7 @@ transform_to_EXTERNAL1990([{'context-negotiation',Context_negot}|Rest], Acc) -> transform_to_EXTERNAL1990([asn1_NOVALUE|Rest], Acc) -> transform_to_EXTERNAL1990(Rest, [asn1_NOVALUE|Acc]); transform_to_EXTERNAL1990([Data_val_desc,Data_value], Acc) - when is_list(Data_value)-> + when is_list(Data_value); is_binary(Data_value) -> list_to_tuple(lists:reverse([{'octet-aligned',Data_value}, Data_val_desc|Acc])); transform_to_EXTERNAL1990([Data_val_desc,Data_value], Acc) diff --git a/lib/asn1/src/asn1rtt_per_common.erl b/lib/asn1/src/asn1rtt_per_common.erl index 3309e6a4ca..71fec411a0 100644 --- a/lib/asn1/src/asn1rtt_per_common.erl +++ b/lib/asn1/src/asn1rtt_per_common.erl @@ -37,8 +37,10 @@ bitstring_from_positions/1,bitstring_from_positions/2, to_bitstring/1,to_bitstring/2, to_named_bitstring/1,to_named_bitstring/2, - is_default_bitstring/5, - extension_bitmap/3]). + bs_drop_trailing_zeroes/1,adjust_trailing_zeroes/2, + is_default_bitstring/3,is_default_bitstring/5, + extension_bitmap/3, + open_type_to_binary/1,legacy_open_type_to_binary/1]). -define('16K',16384). @@ -272,6 +274,25 @@ to_named_bitstring(Val, Lb) -> %% for correctness, not speed. adjust_trailing_zeroes(to_bitstring(Val), Lb). +is_default_bitstring(asn1_DEFAULT, _, _) -> + true; +is_default_bitstring(Named, Named, _) -> + true; +is_default_bitstring(Bs, _, Bs) -> + true; +is_default_bitstring(Val, _, Def) when is_bitstring(Val) -> + Sz = bit_size(Def), + case Val of + <<Def:Sz/bitstring,T/bitstring>> -> + NumZeroes = bit_size(T), + case T of + <<0:NumZeroes>> -> true; + _ -> false + end; + _ -> + false + end. + is_default_bitstring(asn1_DEFAULT, _, _, _, _) -> true; is_default_bitstring({Unused,Bin}, V0, V1, V2, V3) when is_integer(Unused) -> @@ -306,6 +327,16 @@ is_default_bitstring(_, _, _, _, _) -> false. extension_bitmap(Val, Pos, Limit) -> extension_bitmap(Val, Pos, Limit, 0). +open_type_to_binary({asn1_OPENTYPE,Bin}) when is_binary(Bin) -> + Bin. + +legacy_open_type_to_binary({asn1_OPENTYPE,Bin}) when is_binary(Bin) -> + Bin; +legacy_open_type_to_binary(Bin) when is_binary(Bin) -> + Bin; +legacy_open_type_to_binary(List) when is_list(List) -> + List. + %%% %%% Internal functions. %%% @@ -438,6 +469,8 @@ adjust_trailing_zeroes(Bs0, Lb) -> bs_drop_trailing_zeroes(Bs) -> bs_drop_trailing_zeroes(Bs, bit_size(Bs)). +bs_drop_trailing_zeroes(Bs, 0) -> + Bs; bs_drop_trailing_zeroes(Bs0, Sz0) when Sz0 < 8 -> <<Byte:Sz0>> = Bs0, Sz = Sz0 - ntz(Byte), diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl index 83bd66a631..782217ed2d 100644 --- a/lib/asn1/test/asn1_SUITE.erl +++ b/lib/asn1/test/asn1_SUITE.erl @@ -328,6 +328,10 @@ testCompactBitString(Config, Rule, Opts) -> testPrimStrings(Config) -> test(Config, fun testPrimStrings/3, [ber,{ber,[der]},per,uper]). testPrimStrings(Config, Rule, Opts) -> + LegacyOpts = [legacy_erlang_types|Opts], + asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config, + [Rule|LegacyOpts]), + testPrimStrings_cases(Rule, LegacyOpts), asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config, [Rule|Opts]), testPrimStrings_cases(Rule, Opts), asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config, @@ -432,7 +436,8 @@ testDef(Config, Rule, Opts) -> testDEFAULT(Config) -> test(Config, fun testDEFAULT/3, [ber,{ber,[der]},per,uper]). testDEFAULT(Config, Rule, Opts) -> - asn1_test_lib:compile_all(["Def","Default"], Config, [Rule|Opts]), + asn1_test_lib:compile_all(["Def","Default"], Config, + [legacy_erlang_types,Rule|Opts]), testDef:main(Rule), testSeqSetDefaultVal:main(Rule, Opts). @@ -766,7 +771,10 @@ testParameterizedInfObj(Config) -> testParameterizedInfObj(Config, Rule, Opts) -> Files = ["Param","Param2"], asn1_test_lib:compile_all(Files, Config, [Rule|Opts]), - testParameterizedInfObj:main(Config, Rule). + testParameterizedInfObj:main(Config, Rule), + asn1_test_lib:compile("Param", Config, + [legacy_erlang_types,Rule|Opts]), + testParameterizedInfObj:param(Rule). testFragmented(Config) -> test(Config, fun testFragmented/3). @@ -784,7 +792,8 @@ testMergeCompile(Config, Rule, Opts) -> testobj(Config) -> test(Config, fun testobj/3). testobj(Config, Rule, Opts) -> - asn1_test_lib:compile("RANAP", Config, [Rule|Opts]), + asn1_test_lib:compile("RANAP", Config, [legacy_erlang_types, + Rule|Opts]), asn1_test_lib:compile_erlang("testobj", Config, []), ok = testobj:run(), ok = testParameterizedInfObj:ranap(Rule). @@ -804,14 +813,15 @@ testExport(Config) -> testImport(Config) -> test(Config, fun testImport/3). testImport(Config, Rule, Opts) -> - {error, _} = asn1ct:compile(filename:join(?config(data_dir, Config), - "ImportsFrom"), - [Rule, {outdir, ?config(priv_dir, Config)} - |Opts]). + Files = ["ImportsFrom","ImportsFrom2","ImportsFrom3"], + asn1_test_lib:compile_all(Files, Config, [Rule|Opts]), + 42 = 'ImportsFrom':i(), + ok. testMegaco(Config) -> test(Config, fun testMegaco/3). testMegaco(Config, Rule, Opts) -> - {ok, Module1, Module2} = testMegaco:compile(Config, Rule, Opts), + {ok, Module1, Module2} = testMegaco:compile(Config, Rule, + [legacy_erlang_types|Opts]), ok = testMegaco:main(Module1, Config), ok = testMegaco:main(Module2, Config). @@ -850,7 +860,7 @@ duplicate_tags(Config) -> rtUI(Config) -> test(Config, fun rtUI/3). rtUI(Config, Rule, Opts) -> asn1_test_lib:compile("Prim", Config, [Rule|Opts]), - {ok, _} = asn1rt:info('Prim'), + _ = 'Prim':info(), Rule = 'Prim':encoding_rule(), io:format("Default BIT STRING format: ~p\n", ['Prim':bit_string_format()]). @@ -892,7 +902,8 @@ specialized_decodes(Config, Rule, Opts) -> "PartialDecMyHTTP.asn", "MEDIA-GATEWAY-CONTROL.asn", "P-Record"], - Config, [Rule, asn1config|Opts]), + Config, + [Rule,legacy_erlang_types,asn1config|Opts]), test_partial_incomplete_decode:test(Config), test_selective_decode:test(). @@ -1022,7 +1033,8 @@ test_x691(Config, Rule, Opts) -> test_x691:cases(Rule), %% OTP-7708. - asn1_test_lib:compile("EUTRA-extract-55", Config, [Rule|Opts]), + asn1_test_lib:compile("EUTRA-extract-55", Config, + [legacy_erlang_types,Rule|Opts]), %% OTP-7763. Val = {'Seq',15,lists:duplicate(8, 0),[0],lists:duplicate(28, 0),15,true}, @@ -1128,21 +1140,21 @@ END ok = asn1ct:compile(File, [{outdir, PrivDir}]). -timer_compile(Config, Rule, Opts) -> +timer_compile(Config, Rule) -> asn1_test_lib:compile_all(["H235-SECURITY-MESSAGES", "H323-MESSAGES"], - Config, [Rule|Opts]). + Config, [no_ok_wrapper,Rule]). testTimer_ber(Config) -> - timer_compile(Config,ber,[]), - testTimer:go(Config,ber). + timer_compile(Config, ber), + testTimer:go(). testTimer_per(Config) -> - timer_compile(Config,per,[]), - testTimer:go(Config,per). + timer_compile(Config, per), + testTimer:go(). testTimer_uper(Config) -> - timer_compile(Config,uper,[]), - {comment,_} = testTimer:go(Config,uper). + timer_compile(Config, uper), + testTimer:go(). %% Test of multiple-line comment, OTP-8043 testComment(suite) -> []; @@ -1200,8 +1212,8 @@ ticket_7407_code(FinalPadding) -> eutra1(msg) -> {'BCCH-BCH-Message', - {'MasterInformationBlock',[0,1,0,1],[1,0,1,0], - {'PHICH-Configuration',short,ffs},[1,0,1,0,0,0,0,0]}}. + {'MasterInformationBlock',<<2#0101:4>>,<<2#1010:4>>, + {'PHICH-Configuration',short,ffs},<<2#10100000>>}}. eutra1(result, true) -> <<90,80,0>>; diff --git a/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1 b/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1 index 8dc5f3d7e1..74fa97e7aa 100644 --- a/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1 +++ b/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1 @@ -18,6 +18,8 @@ Ext1 ::= ENUMERATED { magenta(9) } +SubExt1 ::= Ext1 ( blue | orange | black ) + Noext ::= ENUMERATED { blue(0), red(1), diff --git a/lib/asn1/test/asn1_SUITE_data/INSTANCEOF.asn1 b/lib/asn1/test/asn1_SUITE_data/INSTANCEOF.asn1 index 8c4f3a8f7e..b4ea943040 100644 --- a/lib/asn1/test/asn1_SUITE_data/INSTANCEOF.asn1 +++ b/lib/asn1/test/asn1_SUITE_data/INSTANCEOF.asn1 @@ -16,7 +16,9 @@ Names ::= SEQUENCE { thirdName [2] INSTANCE OF OTHER-NAME ({TI}) } -OTHER-NAME ::= TYPE-IDENTIFIER +OTHER-NAME ::= YET-ANOTHER-NAME + +YET-ANOTHER-NAME ::= TYPE-IDENTIFIER TI OTHER-NAME ::= {{INTEGER IDENTIFIED BY {2 4}} | {Seq IDENTIFIED BY {2 3 4}} | diff --git a/lib/asn1/test/asn1_SUITE_data/ImportsFrom.asn1 b/lib/asn1/test/asn1_SUITE_data/ImportsFrom.asn1 index 896a35d627..32b8f75dde 100644 --- a/lib/asn1/test/asn1_SUITE_data/ImportsFrom.asn1 +++ b/lib/asn1/test/asn1_SUITE_data/ImportsFrom.asn1 @@ -1,16 +1,8 @@ -ImportsFrom DEFINITIONS ::= - +ImportsFrom DEFINITIONS AUTOMATIC TAGS ::= BEGIN -IMPORTS -Type1, Type2, Type3 -FROM RemoteFile1 objid -val1, val2, val3 -FROM RemoteFile2; - -objid OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) remote-operations(4) notation(0)} - -LocalType ::= INTEGER +IMPORTS Int FROM ImportsFrom2; +i Int ::= 42 END diff --git a/lib/asn1/test/asn1_SUITE_data/ImportsFrom2.asn1 b/lib/asn1/test/asn1_SUITE_data/ImportsFrom2.asn1 new file mode 100644 index 0000000000..b0c29d24ae --- /dev/null +++ b/lib/asn1/test/asn1_SUITE_data/ImportsFrom2.asn1 @@ -0,0 +1,7 @@ +ImportsFrom2 DEFINITIONS AUTOMATIC TAGS ::= +BEGIN +IMPORTS Int FROM ImportsFrom3; + +LocalDef ::= OCTET STRING + +END diff --git a/lib/asn1/test/asn1_SUITE_data/ImportsFrom3.asn1 b/lib/asn1/test/asn1_SUITE_data/ImportsFrom3.asn1 new file mode 100644 index 0000000000..ca27b20697 --- /dev/null +++ b/lib/asn1/test/asn1_SUITE_data/ImportsFrom3.asn1 @@ -0,0 +1,4 @@ +ImportsFrom3 DEFINITIONS AUTOMATIC TAGS ::= +BEGIN + Int ::= INTEGER (0..63) +END diff --git a/lib/asn1/test/asn1_SUITE_data/SeqPrim.asn1 b/lib/asn1/test/asn1_SUITE_data/SeqPrim.asn1 index 20c4126c0b..7068674647 100644 --- a/lib/asn1/test/asn1_SUITE_data/SeqPrim.asn1 +++ b/lib/asn1/test/asn1_SUITE_data/SeqPrim.asn1 @@ -16,4 +16,11 @@ Seq ::= SEQUENCE Empty ::= SEQUENCE {} +Big ::= SEQUENCE { + ..., + os1 [1] OCTET STRING (SIZE (120..130)) OPTIONAL, + os2 [2] OCTET STRING (SIZE (128..256)) OPTIONAL, + os3 [3] OCTET STRING (SIZE (17000..30000)) OPTIONAL +} + END diff --git a/lib/asn1/test/asn1_SUITE_data/TCAPPackage_msg.erl b/lib/asn1/test/asn1_SUITE_data/TCAPPackage_msg.erl index 06eba8b6eb..0bf4425263 100644 --- a/lib/asn1/test/asn1_SUITE_data/TCAPPackage_msg.erl +++ b/lib/asn1/test/asn1_SUITE_data/TCAPPackage_msg.erl @@ -47,7 +47,7 @@ val('TransactionPDU') -> dialoguePortion=val('DialoguePortion'), componentPortion=val('ComponentSequence')}; val('TransactionID') -> - "OCTET STRING"; + <<"OCTET STRING">>; val('DialoguePortion') -> #'DialoguePortion'{version=val('ProtocolVersion'), applicationContext={integerApplicationId,12}, @@ -57,23 +57,23 @@ val('DialoguePortion') -> val('Confidentiality') -> #'Confidentiality'{confidentialityId={integerConfidentialityId,14}}; val('ProtocolVersion') -> - "K"; + <<"K">>; val('UserInformation') -> [val('EXTERNAL'),val('EXTERNAL')]; val('EXTERNAL') -> #'EXTERNAL'{'direct-reference'={0,1,2}, - encoding={'single-ASN1-type',[1,2,3,4]}}; + encoding={'single-ASN1-type',<<1,2,3,4>>}}; val('ComponentSequence') -> [val('ComponentPDU',1),val('ComponentPDU',2),val('ComponentPDU',3)]; val('Invoke') -> - #'Invoke'{componentIDs="AB", + #'Invoke'{componentIDs = <<"AB">>, opcode={local,-2}, parameter=running}; val('ReturnResult') -> - #'ReturnResult'{componentID="C", + #'ReturnResult'{componentID = <<"C">>, parameter=[1,2,3,4]}; val('ReturnError') -> - #'ReturnError'{componentID="D", + #'ReturnError'{componentID = <<"D">>, errorCode={local,21}, parameter=true}; val('Abort') -> @@ -87,8 +87,8 @@ val(Type) -> check_result('PackageType',unidirectional,Res) -> {unidirectional, {'UniTransactionPDU', - "OCTET STRING", - {'DialoguePortion',"K", + <<"OCTET STRING">>, + {'DialoguePortion',<<"K">>, {integerApplicationId,12}, [_,%{'EXTERNAL',{syntax,{0,1,2}},asn1_NOVALUE,OTVal}, _],%{'EXTERNAL',{syntax,{0,1,2}},asn1_NOVALUE,OTVal}], @@ -96,14 +96,14 @@ check_result('PackageType',unidirectional,Res) -> {'Confidentiality', {integerConfidentialityId,14}}}, [{invokeLast, - {_,"AB",{local,-2},running}}, - {returnResultLast,{_,"C",_}}, - {returnError,{_,"D",{local,21},true}}]}} = Res, + {_,<<"AB">>,{local,-2},running}}, + {returnResultLast,{_,<<"C">>,_}}, + {returnError,{_,<<"D">>,{local,21},true}}]}} = Res, ok; %% check_OT_val(OTVal); check_result('PackageType',abort,Res)-> - {abort,{'Abort',"OCTET STRING", - {'DialoguePortion',"K", + {abort,{'Abort',<<"OCTET STRING">>, + {'DialoguePortion',<<"K">>, {integerApplicationId,12}, [_,%{'EXTERNAL',{syntax,{0,1,2}},asn1_NOVALUE,OTVal}, _],%{'EXTERNAL',{syntax,{0,1,2}},asn1_NOVALUE,OTVal}], @@ -114,9 +114,9 @@ check_result('PackageType',abort,Res)-> ok; %% check_OT_val(OTVal); check_result('PackageType',response,Res) -> - {response,{'TransactionPDU',"OCTET STRING", + {response,{'TransactionPDU',<<"OCTET STRING">>, {'DialoguePortion', - "K", + <<"K">>, {integerApplicationId,12}, [_,%{'EXTERNAL',{syntax,{0,1,2}},asn1_NOVALUE,OTVal}, _],%{'EXTERNAL',{syntax,{0,1,2}},asn1_NOVALUE,OTVal}], @@ -124,11 +124,11 @@ check_result('PackageType',response,Res) -> {'Confidentiality', {integerConfidentialityId,14}}}, [{invokeLast, - {_,"AB",{local,-2},running}}, + {_,<<"AB">>,{local,-2},running}}, {returnResultLast, - {_,"C",_}}, + {_,<<"C">>,_}}, {returnError, - {_,"D",{local,21},true}}]}} = Res, + {_,<<"D">>,{local,21},true}}]}} = Res, ok. %% check_OT_val(OTVal). diff --git a/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl b/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl index 8e21e6ca84..a1e563f6be 100644 --- a/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl +++ b/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl @@ -67,8 +67,8 @@ run3(Erule) -> asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE, asn1_NOVALUE,asn1_NOVALUE}, asn1_NOVALUE, - [[80,66,0,5,10,0,5,0,24,11,7,84,54,33,0,1,1,0,0,0,1,39,5,66,127,0,0,1], - []], + [<<80,66,0,5,10,0,5,0,24,11,7,84,54,33,0,1,1,0,0,0,1,39,5,66,127,0,0,1>>, + <<>>], {'RRC-RadioResourceConfigDedicated', [{'RRC-SRB-ToAddMod',1, {explicitValue, diff --git a/lib/asn1/test/asn1_appup_test.erl b/lib/asn1/test/asn1_appup_test.erl index a2c1423eda..7391959645 100644 --- a/lib/asn1/test/asn1_appup_test.erl +++ b/lib/asn1/test/asn1_appup_test.erl @@ -21,8 +21,8 @@ %% Purpose: Verify the application specifics of the asn1 application %%---------------------------------------------------------------------- -module(asn1_appup_test). --compile({no_auto_import,[error/1]}). -compile(export_all). +-include_lib("common_test/include/ct.hrl"). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -44,16 +44,9 @@ end_per_group(_GroupName, Config) -> init_per_suite(suite) -> []; init_per_suite(doc) -> []; init_per_suite(Config) when is_list(Config) -> - AppFile = file_name(asn1, ".app"), - AppupFile = file_name(asn1, ".appup"), - [{app_file, AppFile}, {appup_file, AppupFile}|Config]. + Config. -file_name(App, Ext) -> - LibDir = code:lib_dir(App), - filename:join([LibDir, "ebin", atom_to_list(App) ++ Ext]). - - end_per_suite(suite) -> []; end_per_suite(doc) -> []; end_per_suite(Config) when is_list(Config) -> @@ -62,349 +55,7 @@ end_per_suite(Config) when is_list(Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -appup(suite) -> - []; -appup(doc) -> - "perform a simple check of the appup file"; +appup() -> + [{doc, "perform a simple check of the asn1 appup file"}]. appup(Config) when is_list(Config) -> - AppupFile = key1search(appup_file, Config), - AppFile = key1search(app_file, Config), - Modules = modules(AppFile), - check_appup(AppupFile, Modules). - -modules(File) -> - case file:consult(File) of - {ok, [{application,asn1,Info}]} -> - case lists:keysearch(modules,1,Info) of - {value, {modules, Modules}} -> - Modules; - false -> - fail({bad_appinfo, Info}) - end; - Error -> - fail({bad_appfile, Error}) - end. - - -check_appup(AppupFile, Modules) -> - case file:consult(AppupFile) of - {ok, [{V, UpFrom, DownTo}]} -> - io:format("V= ~p, UpFrom= ~p, DownTo= ~p, Modules= ~p~n", - [V, UpFrom, DownTo, Modules]), - check_appup(V, UpFrom, DownTo, Modules); - Else -> - fail({bad_appupfile, Else}) - end. - - -check_appup(V, UpFrom, DownTo, Modules) -> - check_version(V), - check_depends(up, UpFrom, Modules), - check_depends(down, DownTo, Modules), - ok. - - -check_depends(_, [], _) -> - ok; -check_depends(UpDown, [Dep|Deps], Modules) -> - check_depend(UpDown, Dep, Modules), - check_depends(UpDown, Deps, Modules). - - -check_depend(up,I={add_application,_App},Modules) -> - d("check_instructions(~w) -> entry with" - "~n Instruction: ~p" - "~n Modules: ~p", [up,I , Modules]), - ok; -check_depend(down,I={remove_application,_App},Modules) -> - d("check_instructions(~w) -> entry with" - "~n Instruction: ~p" - "~n Modules: ~p", [down,I , Modules]), - ok; -check_depend(UpDown, {V, Instructions}, Modules) -> - d("check_instructions(~w) -> entry with" - "~n V: ~p" - "~n Modules: ~p", [UpDown, V, Modules]), - check_version(V), - case check_instructions(UpDown, - Instructions, Instructions, [], [], Modules) of - {_Good, []} -> - ok; - {_, Bad} -> - fail({bad_instructions, Bad, UpDown}) - end. - - -check_instructions(_, [], _, Good, Bad, _) -> - {lists:reverse(Good), lists:reverse(Bad)}; -check_instructions(UpDown, [Instr|Instrs], AllInstr, Good, Bad, Modules) -> - d("check_instructions(~w) -> entry with" - "~n Instr: ~p", [UpDown,Instr]), - case (catch check_instruction(UpDown, Instr, AllInstr, Modules)) of - ok -> - check_instructions(UpDown, Instrs, AllInstr, - [Instr|Good], Bad, Modules); - {error, Reason} -> - d("check_instructions(~w) -> bad instruction: " - "~n Reason: ~p", [UpDown,Reason]), - check_instructions(UpDown, Instrs, AllInstr, Good, - [{Instr, Reason}|Bad], Modules) - end. - -%% A new module is added -check_instruction(up, {add_module, Module}, _, Modules) - when is_atom(Module) -> - d("check_instruction -> entry when up-add_module instruction with" - "~n Module: ~p", [Module]), - check_module(Module, Modules); - -%% An old module is re-added -check_instruction(down, {add_module, Module}, _, Modules) - when is_atom(Module) -> - d("check_instruction -> entry when down-add_module instruction with" - "~n Module: ~p", [Module]), - case (catch check_module(Module, Modules)) of - {error, {unknown_module, Module, Modules}} -> - ok; - ok -> - error({existing_readded_module, Module}) - end; - -%% Removing a module on upgrade: -%% - the module has been removed from the app-file. -%% - check that no module depends on this (removed) module -check_instruction(up, {remove, {Module, Pre, Post}}, _, Modules) - when is_atom(Module), is_atom(Pre), is_atom(Post) -> - d("check_instruction -> entry when up-remove instruction with" - "~n Module: ~p" - "~n Pre: ~p" - "~n Post: ~p", [Module, Pre, Post]), - case (catch check_module(Module, Modules)) of - {error, {unknown_module, Module, Modules}} -> - check_purge(Pre), - check_purge(Post); - ok -> - error({existing_removed_module, Module}) - end; - -%% Removing a module on downgrade: the module exist -%% in the app-file. -check_instruction(down, {remove, {Module, Pre, Post}}, AllInstr, Modules) - when is_atom(Module), is_atom(Pre), is_atom(Post) -> - d("check_instruction -> entry when down-remove instruction with" - "~n Module: ~p" - "~n Pre: ~p" - "~n Post: ~p", [Module, Pre, Post]), - case (catch check_module(Module, Modules)) of - ok -> - check_purge(Pre), - check_purge(Post), - check_no_remove_depends(Module, AllInstr); - {error, {unknown_module, Module, Modules}} -> - error({nonexisting_removed_module, Module}) - end; - -check_instruction(_, {load_module, Module, Pre, Post, Depend}, - AllInstr, Modules) - when is_atom(Module), is_atom(Pre), is_atom(Post), is_list(Depend) -> - d("check_instruction -> entry when load_module instruction with" - "~n Module: ~p" - "~n Pre: ~p" - "~n Post: ~p" - "~n Depend: ~p", [Module, Pre, Post, Depend]), - check_module(Module, Modules), - check_module_depend(Module, Depend, Modules), - check_module_depend(Module, Depend, updated_modules(AllInstr, [])), - check_purge(Pre), - check_purge(Post); - -check_instruction(_, {update, Module, Change, Pre, Post, Depend}, - AllInstr, Modules) - when is_atom(Module), is_atom(Pre), is_atom(Post), is_list(Depend) -> - d("check_instruction -> entry when update instruction with" - "~n Module: ~p" - "~n Change: ~p" - "~n Pre: ~p" - "~n Post: ~p" - "~n Depend: ~p", [Module, Change, Pre, Post, Depend]), - check_module(Module, Modules), - check_module_depend(Module, Depend, Modules), - check_module_depend(Module, Depend, updated_modules(AllInstr, [])), - check_change(Change), - check_purge(Pre), - check_purge(Post); - -check_instruction(_, {apply, {Module, Function, Args}}, - _AllInstr, Modules) - when is_atom(Module), is_atom(Function), is_list(Args) -> - d("check_instruction -> entry when apply instruction with" - "~n Module: ~p" - "~n Function: ~p" - "~n Args: ~p", [Module, Function, Args]), - check_module(Module, Modules), - check_apply(Module,Function,Args); - -check_instruction(_, Instr, _AllInstr, _Modules) -> - d("check_instruction -> entry when unknown instruction with" - "~n Instr: ~p", [Instr]), - error({error, {unknown_instruction, Instr}}). - - -%% If Module X depends on Module Y, then module Y must have an update -%% instruction of some sort (otherwise the depend is faulty). -updated_modules([], Modules) -> - d("update_modules -> entry when done with" - "~n Modules: ~p", [Modules]), - Modules; -updated_modules([Instr|Instrs], Modules) -> - d("update_modules -> entry with" - "~n Instr: ~p" - "~n Modules: ~p", [Instr,Modules]), - Module = instruction_module(Instr), - d("update_modules -> Module: ~p", [Module]), - updated_modules(Instrs, [Module|Modules]). - -instruction_module({add_module, Module}) -> - Module; -instruction_module({remove, {Module, _, _}}) -> - Module; -instruction_module({load_module, Module, _, _, _}) -> - Module; -instruction_module({update, Module, _, _, _, _}) -> - Module; -instruction_module({apply, {Module, _, _}}) -> - Module; -instruction_module(Instr) -> - d("instruction_module -> entry when unknown instruction with" - "~n Instr: ~p", [Instr]), - error({error, {unknown_instruction, Instr}}). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -check_version(V) when is_list(V) -> - ok; -check_version(V) -> - error({bad_version, V}). - - -check_module(M, Modules) when is_atom(M) -> - case lists:member(M,Modules) of - true -> - ok; - false -> - error({unknown_module, M, Modules}) - end; -check_module(M, _) -> - error({bad_module, M}). - -check_apply(Module,Function,Args) -> - case (catch Module:module_info()) of - Info when is_list(Info) -> - check_exported(Function,Args,Info); - {'EXIT',{undef,_}} -> - error({not_existing_module,Module}) - end. - -check_exported(Function,Args,Info) -> - case lists:keysearch(exports,1,Info) of - {value,{exports,FunList}} -> - case lists:keysearch(Function,1,FunList) of - {value,{_,Arity}} when Arity==length(Args) -> - ok; - _ -> - error({not_exported_function,Function,length(Args)}) - end; - _ -> - error({bad_export,Info}) - end. - -check_module_depend(M, [], _) when is_atom(M) -> - d("check_module_depend -> entry with" - "~n M: ~p", [M]), - ok; -check_module_depend(M, Deps, Modules) when is_atom(M), is_list(Deps) -> - d("check_module_depend -> entry with" - "~n M: ~p" - "~n Deps: ~p" - "~n Modules: ~p", [M, Deps, Modules]), - case [Dep || Dep <- Deps, lists:member(Dep, Modules) == false] of - [] -> - ok; - Unknown -> - error({unknown_depend_modules, Unknown}) - end; -check_module_depend(_M, D, _Modules) -> - d("check_module_depend -> entry when bad depend with" - "~n D: ~p", [D]), - error({bad_depend, D}). - - -check_no_remove_depends(_Module, []) -> - ok; -check_no_remove_depends(Module, [Instr|Instrs]) -> - check_no_remove_depend(Module, Instr), - check_no_remove_depends(Module, Instrs). - -check_no_remove_depend(Module, {load_module, Mod, _Pre, _Post, Depend}) -> - case lists:member(Module, Depend) of - true -> - error({removed_module_in_depend, load_module, Mod, Module}); - false -> - ok - end; -check_no_remove_depend(Module, {update, Mod, _Change, _Pre, _Post, Depend}) -> - case lists:member(Module, Depend) of - true -> - error({removed_module_in_depend, update, Mod, Module}); - false -> - ok - end; -check_no_remove_depend(_, _) -> - ok. - - -check_change(soft) -> - ok; -check_change({advanced, _Something}) -> - ok; -check_change(Change) -> - error({bad_change, Change}). - - -check_purge(soft_purge) -> - ok; -check_purge(brutal_purge) -> - ok; -check_purge(Purge) -> - error({bad_purge, Purge}). - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -error(Reason) -> - throw({error, Reason}). - -fail(Reason) -> - exit({suite_failed, Reason}). - -key1search(Key, L) -> - case lists:keysearch(Key, 1, L) of - undefined -> - fail({not_found, Key, L}); - {value, {Key, Value}} -> - Value - end. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -d(F, A) -> - d(false, F, A). - -d(true, F, A) -> - io:format(F ++ "~n", A); -d(_, _, _) -> - ok. - - + ok = ?t:appup_test(asn1). diff --git a/lib/asn1/test/error_SUITE.erl b/lib/asn1/test/error_SUITE.erl index 6451f81c01..8a0414708d 100644 --- a/lib/asn1/test/error_SUITE.erl +++ b/lib/asn1/test/error_SUITE.erl @@ -19,7 +19,8 @@ -module(error_SUITE). -export([suite/0,all/0,groups/0, - already_defined/1,enumerated/1,objects/1]). + already_defined/1,bitstrings/1,enumerated/1, + imports/1,instance_of/1,integers/1,objects/1,values/1]). -include_lib("test_server/include/test_server.hrl"). @@ -29,9 +30,15 @@ all() -> [{group,p}]. groups() -> - [{p,parallel(),[already_defined, - enumerated, - objects]}]. + [{p,parallel(), + [already_defined, + bitstrings, + enumerated, + imports, + instance_of, + integers, + objects, + values]}]. parallel() -> case erlang:system_info(schedulers) > 1 of @@ -68,6 +75,23 @@ already_defined(Config) -> } = run(P, Config), ok. +bitstrings(Config) -> + M = 'Bitstrings', + P = {M, + <<"Bitstrings DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n" + " Bs1 ::= BIT STRING {a(1), a(1)}\n" + " Bs2 ::= BIT STRING {a(1), b(2), a(3)}\n" + " Bs3 ::= BIT STRING {x(1), y(1)}\n" + " Bs4 ::= BIT STRING {x(-1), y(0)}\n" + "END\n">>}, + {error, + [{structured_error,{M,2},asn1ct_check,{namelist_redefinition,a}}, + {structured_error,{M,3},asn1ct_check,{namelist_redefinition,a}}, + {structured_error,{M,4},asn1ct_check,{value_reused,1}}, + {structured_error,{M,5},asn1ct_check,{invalid_bit_number,-1}} + ]} = run(P, Config), + ok. + enumerated(Config) -> M = 'Enumerated', P = {M, @@ -96,6 +120,63 @@ enumerated(Config) -> } = run(P, Config), ok. +imports(Config) -> + Ext = 'ExternalModule', + ExtP = {Ext, + <<"ExternalModule DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n" + "END\n">>}, + ok = run(ExtP, Config), + + M = 'Imports', + P = {M, + <<"Imports DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n" + "IMPORTS NotDefined FROM ExternalModule\n" + "X FROM UndefinedModule objid\n" + "Y, Z FROM UndefinedModule2;\n" + "objid OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) remote-operations(4)\n" + " notation(0)}\n" + "END\n">>}, + {error,[{structured_error,{M,2},asn1ct_check, + {undefined_import,'NotDefined','ExternalModule'}}, + {structured_error,{M,3},asn1ct_check,{undefined_import,'X','UndefinedModule'}}, + {structured_error,{M,4},asn1ct_check,{undefined_import,'Y','UndefinedModule2'}}, + {structured_error,{M,4},asn1ct_check,{undefined_import,'Z','UndefinedModule2'}} + ]} = run(P, Config), + ok. + +instance_of(Config) -> + M = 'InstanceOf', + P = {M, + <<"InstanceOf DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n" + "XX ::= INSTANCE OF CL ({TI})\n" + "CL ::= CLASS {\n" + "&id INTEGER,\n" + "&Type\n" + "}\n" + "o1 CL ::= {&id 1, &Type OCTET STRING}\n" + "TI CL ::= { o1 }\n" + "END\n">>}, + {error, + [{structured_error,{M,2},asn1ct_check,{illegal_instance_of,'CL'}} + ]} = run(P, Config), + ok. + +integers(Config) -> + M = 'Integers', + P = {M, + <<"Integers DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n" + " Int1 ::= INTEGER {a(1), a(1)}\n" + " Int2 ::= INTEGER {a(1), b(2), a(3)}\n" + " Int3 ::= INTEGER {x(1), y(1)}\n" + "END\n">>}, + {error, + [{structured_error,{M,2},asn1ct_check,{namelist_redefinition,a}}, + {structured_error,{M,3},asn1ct_check,{namelist_redefinition,a}}, + {structured_error,{M,4},asn1ct_check,{value_reused,1}} + ]} = run(P, Config), + ok. + + objects(Config) -> M = 'Objects', P = {M, @@ -138,6 +219,25 @@ objects(Config) -> } = run(P, Config), ok. +values(Config) -> + M = 'Values', + P = {M, + <<"Values DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n" + " os1 OCTET STRING ::= \"abc\"\n" + " os2 OCTET STRING ::= 42\n" + " os3 OCTET STRING ::= { 1, 3 }\n" + "END\n">>}, + {error, + [ + {structured_error,{M,2},asn1ct_check, + illegal_octet_string_value}, + {structured_error,{M,3},asn1ct_check, + illegal_octet_string_value}, + {structured_error,{M,4},asn1ct_check, + illegal_octet_string_value} + ] + } = run(P, Config), + ok. run({Mod,Spec}, Config) -> diff --git a/lib/asn1/test/h323test.erl b/lib/asn1/test/h323test.erl index 3baaa994ea..7577928493 100644 --- a/lib/asn1/test/h323test.erl +++ b/lib/asn1/test/h323test.erl @@ -42,7 +42,7 @@ alerting_val() -> {'TerminalInfo',asn1_NOVALUE}, false,false}, asn1_NOVALUE, - {'CallIdentifier',[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}, + {'CallIdentifier',<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>}, asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}}, asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}, asn1_NOVALUE}. @@ -57,18 +57,18 @@ connect_val() -> {'Connect-UUIE', {0,0,8,2250,0,2}, {ipAddress, - {'TransportAddress_ipAddress',[136,225,41,58],1187}}, + {'TransportAddress_ipAddress',<<136,225,41,58>>,1187}}, {'EndpointType',asn1_NOVALUE, {'VendorIdentifier', {'H221NonStandard',181,0,21324}, - [77,105,99,114,111,115,111,102,116,174,32,78,101,116, - 77,101,100,116,105,110,103,174,0], - [51,46,48,0]}, + <<77,105,99,114,111,115,111,102,116,174,32,78,101,116, + 77,101,100,116,105,110,103,174,0>>, + <<51,46,48,0>>}, asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE, {'TerminalInfo',asn1_NOVALUE}, false,false}, - [22,137,237,197,191,35,211,17,140,45,0,192,79,75,28,208], - {'CallIdentifier',[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}, + <<22,137,237,197,191,35,211,17,140,45,0,192,79,75,28,208>>, + {'CallIdentifier',<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>}, asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}}, asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}, asn1_NOVALUE}. diff --git a/lib/asn1/test/testChoExtension.erl b/lib/asn1/test/testChoExtension.erl index e54cbe825b..09e19ceebb 100644 --- a/lib/asn1/test/testChoExtension.erl +++ b/lib/asn1/test/testChoExtension.erl @@ -31,13 +31,13 @@ extension(_Rules) -> %% A trick to encode with another compatible CHOICE type to test reception %% extension alternative - roundtrip('ChoExt1x', {str,"abc"}), + roundtrip('ChoExt1x', {str,<<"abc">>}), roundtrip('ChoExt2', {bool,true}), roundtrip('ChoExt2', {int,33}), roundtrip('ChoExt3', {bool,true}), roundtrip('ChoExt3', {int,33}), - roundtrip('ChoExt4', {str,"abc"}), + roundtrip('ChoExt4', {str,<<"abc">>}), roundtrip('ChoEmptyRoot', {bool,false}), roundtrip('ChoEmptyRoot', {bool,true}), diff --git a/lib/asn1/test/testChoExternal.erl b/lib/asn1/test/testChoExternal.erl index 12abdbb2bc..0914d54f33 100644 --- a/lib/asn1/test/testChoExternal.erl +++ b/lib/asn1/test/testChoExternal.erl @@ -31,16 +31,16 @@ external(_Rules) -> roundtrip('ChoXBool', {xboolImp,true}), roundtrip('ChoXBool', {xboolExp,true}), - roundtrip('NT', {os,"kalle"}), - roundtrip('Exp', {os,"kalle"}), - roundtrip('NTNT', {os,"kalle"}), - roundtrip('NTExp', {os,"kalle"}), - roundtrip('ExpNT', {os,"kalle"}), - roundtrip('ExpExp', {os,"kalle"}), - roundtrip('XNTNT', {os,"kalle"}), - roundtrip('XNTExp', {os,"kalle"}), - roundtrip('XExpNT', {os,"kalle"}), - roundtrip('XExpExp', {os,"kalle"}), + roundtrip('NT', {os,<<"kalle">>}), + roundtrip('Exp', {os,<<"kalle">>}), + roundtrip('NTNT', {os,<<"kalle">>}), + roundtrip('NTExp', {os,<<"kalle">>}), + roundtrip('ExpNT', {os,<<"kalle">>}), + roundtrip('ExpExp', {os,<<"kalle">>}), + roundtrip('XNTNT', {os,<<"kalle">>}), + roundtrip('XNTExp', {os,<<"kalle">>}), + roundtrip('XExpNT', {os,<<"kalle">>}), + roundtrip('XExpExp', {os,<<"kalle">>}), ok. diff --git a/lib/asn1/test/testChoOptional.erl b/lib/asn1/test/testChoOptional.erl index f5e77cb721..71a7346e3f 100644 --- a/lib/asn1/test/testChoOptional.erl +++ b/lib/asn1/test/testChoOptional.erl @@ -27,16 +27,20 @@ run() -> roundtrip('Seq1', #'Seq1'{bool=true,int=asn1_NOVALUE,cho=asn1_NOVALUE}), roundtrip('Seq1', #'Seq1'{bool=true,int=233,cho=asn1_NOVALUE}), - roundtrip('Seq1', #'Seq1'{bool=true,int=asn1_NOVALUE,cho={vsCho,"Vs Str"}}), - roundtrip('Seq1', #'Seq1'{bool=true,int=asn1_NOVALUE,cho={ocStrCho,"Oct Str"}}), + roundtrip('Seq1', #'Seq1'{bool=true,int=asn1_NOVALUE, + cho={vsCho,"Vs Str"}}), + roundtrip('Seq1', #'Seq1'{bool=true,int=asn1_NOVALUE, + cho={ocStrCho,<<"Oct Str">>}}), roundtrip('Seq2', #'Seq2'{int=asn1_NOVALUE,cho=asn1_NOVALUE,bool=true}), roundtrip('Seq2', #'Seq2'{int=233,cho=asn1_NOVALUE,bool=true}), roundtrip('Seq2', #'Seq2'{int=asn1_NOVALUE,cho={vsCho,"Vs Str"},bool=true}), - roundtrip('Seq2', #'Seq2'{int=asn1_NOVALUE,cho={ocStrCho,"Oct Str"},bool=true}), + roundtrip('Seq2', #'Seq2'{int=asn1_NOVALUE,cho={ocStrCho,<<"Oct Str">>}, + bool=true}), roundtrip('Seq3', #'Seq3'{cho=asn1_NOVALUE,int=asn1_NOVALUE,bool=true}), roundtrip('Seq3', #'Seq3'{cho=asn1_NOVALUE,int=233,bool=true}), roundtrip('Seq3', #'Seq3'{cho={vsCho,"Vs Str"},int=asn1_NOVALUE,bool=true}), - roundtrip('Seq3', #'Seq3'{cho={ocStrCho,"Oct Str"},int=asn1_NOVALUE,bool=true}), + roundtrip('Seq3', #'Seq3'{cho={ocStrCho,<<"Oct Str">>}, + int=asn1_NOVALUE,bool=true}), ok. roundtrip(Type, Value) -> diff --git a/lib/asn1/test/testChoRecursive.erl b/lib/asn1/test/testChoRecursive.erl index 593b845949..ccd60c2897 100644 --- a/lib/asn1/test/testChoRecursive.erl +++ b/lib/asn1/test/testChoRecursive.erl @@ -31,13 +31,13 @@ recursive(_Rules) -> roundtrip('ChoRec', {something, #'ChoRec_something'{a = 77, - b = "some octets here", + b = <<"some octets here">>, c = {nothing,'NULL'}}}), roundtrip('ChoRec', {nothing,'NULL'}), roundtrip('ChoRec2', {something, #'ChoRec2_something'{a = 77, - b = "some octets here", + b = <<"some octets here">>, c = {nothing,'NULL'}}}), roundtrip('ChoRec2', {nothing,'NULL'}), ok. diff --git a/lib/asn1/test/testChoTypeRefCho.erl b/lib/asn1/test/testChoTypeRefCho.erl index cd2672add0..636c301403 100644 --- a/lib/asn1/test/testChoTypeRefCho.erl +++ b/lib/asn1/test/testChoTypeRefCho.erl @@ -30,7 +30,7 @@ choice(_Rules) -> roundtrip('ChoTRcho', {'choChoE-E',{choInt,88}}), roundtrip('ChoChoInline', {bool1,true}), roundtrip('ChoChoInline', {choCho,{bool,true}}), - roundtrip('ChoChoInline', {choCho,{octStr,"kk"}}), + roundtrip('ChoChoInline', {choCho,{octStr,<<"kk">>}}), roundtrip('ChoChoInline', {choCho,{int,55}}), ok. diff --git a/lib/asn1/test/testChoTypeRefPrim.erl b/lib/asn1/test/testChoTypeRefPrim.erl index 8a2bc7bd8e..747baeddd8 100644 --- a/lib/asn1/test/testChoTypeRefPrim.erl +++ b/lib/asn1/test/testChoTypeRefPrim.erl @@ -25,18 +25,18 @@ prim(_Rules) -> roundtrip('ChoTR', {bool,true}), - roundtrip('ChoTR', {octStr,[11,12,13,14,15,16,17]}), + roundtrip('ChoTR', {octStr,<<11,12,13,14,15,16,17>>}), roundtrip('ChoTR', {int,233}), - roundtrip('ChoTR', {octStr,"Stringing in the rain"}), - roundtrip('ChoTR2', {octStr,"A string"}), - roundtrip('ChoTR2', {octStrI,"A string"}), - roundtrip('ChoTR2', {octStrE,"A string"}), - roundtrip('ChoTR2', {'octStr-I',"A string"}), - roundtrip('ChoTR2', {'octStrI-I',"A string"}), - roundtrip('ChoTR2', {'octStrE-I',"A string"}), - roundtrip('ChoTR2', {'octStr-E',"A string"}), - roundtrip('ChoTR2', {'octStrI-E',"A string"}), - roundtrip('ChoTR2', {'octStrE-E',"A string"}), + roundtrip('ChoTR', {octStr,<<"Stringing in the rain">>}), + roundtrip('ChoTR2', {octStr,<<"A string">>}), + roundtrip('ChoTR2', {octStrI,<<"A string">>}), + roundtrip('ChoTR2', {octStrE,<<"A string">>}), + roundtrip('ChoTR2', {'octStr-I',<<"A string">>}), + roundtrip('ChoTR2', {'octStrI-I',<<"A string">>}), + roundtrip('ChoTR2', {'octStrE-I',<<"A string">>}), + roundtrip('ChoTR2', {'octStr-E',<<"A string">>}), + roundtrip('ChoTR2', {'octStrI-E',<<"A string">>}), + roundtrip('ChoTR2', {'octStrE-E',<<"A string">>}), ok. roundtrip(Type, Value) -> diff --git a/lib/asn1/test/testChoTypeRefSeq.erl b/lib/asn1/test/testChoTypeRefSeq.erl index 86c22619aa..91d0b45e89 100644 --- a/lib/asn1/test/testChoTypeRefSeq.erl +++ b/lib/asn1/test/testChoTypeRefSeq.erl @@ -28,15 +28,24 @@ -record('ChoSeqExp', {seqInt, seqOs}). seq(_Rules) -> - roundtrip('ChoTRseq', {choSeq,#'ChoSeq'{seqInt=88,seqOs="A string"}}), - roundtrip('ChoTRseq', {choSeqI,#'ChoSeq'{seqInt=88,seqOs="A string"}}), - roundtrip('ChoTRseq', {choSeqE,#'ChoSeq'{seqInt=88,seqOs="A string"}}), - roundtrip('ChoTRseq', {'choSeq-I',#'ChoSeqImp'{seqInt=88,seqOs="A string"}}), - roundtrip('ChoTRseq', {'choSeqI-I',#'ChoSeqImp'{seqInt=88,seqOs="A string"}}), - roundtrip('ChoTRseq', {'choSeqE-I',#'ChoSeqImp'{seqInt=88,seqOs="A string"}}), - roundtrip('ChoTRseq', {'choSeq-E',#'ChoSeqExp'{seqInt=88,seqOs="A string"}}), - roundtrip('ChoTRseq', {'choSeqI-E',#'ChoSeqExp'{seqInt=88,seqOs="A string"}}), - roundtrip('ChoTRseq', {'choSeqE-E',#'ChoSeqExp'{seqInt=88,seqOs="A string"}}), + roundtrip('ChoTRseq', {choSeq,#'ChoSeq'{seqInt=88, + seqOs = <<"A string">>}}), + roundtrip('ChoTRseq', {choSeqI,#'ChoSeq'{seqInt=88, + seqOs = <<"A string">>}}), + roundtrip('ChoTRseq', {choSeqE,#'ChoSeq'{seqInt=88, + seqOs = <<"A string">>}}), + roundtrip('ChoTRseq', {'choSeq-I',#'ChoSeqImp'{seqInt=88, + seqOs = <<"A string">>}}), + roundtrip('ChoTRseq', {'choSeqI-I',#'ChoSeqImp'{seqInt=88, + seqOs = <<"A string">>}}), + roundtrip('ChoTRseq', {'choSeqE-I',#'ChoSeqImp'{seqInt=88, + seqOs = <<"A string">>}}), + roundtrip('ChoTRseq', {'choSeq-E',#'ChoSeqExp'{seqInt=88, + seqOs = <<"A string">>}}), + roundtrip('ChoTRseq', {'choSeqI-E',#'ChoSeqExp'{seqInt=88, + seqOs = <<"A string">>}}), + roundtrip('ChoTRseq', {'choSeqE-E',#'ChoSeqExp'{seqInt=88, + seqOs = <<"A string">>}}), ok. roundtrip(Type, Value) -> diff --git a/lib/asn1/test/testChoTypeRefSet.erl b/lib/asn1/test/testChoTypeRefSet.erl index fd3d75cbcb..bd9068b53e 100644 --- a/lib/asn1/test/testChoTypeRefSet.erl +++ b/lib/asn1/test/testChoTypeRefSet.erl @@ -28,15 +28,24 @@ -record('ChoSetExp', {setInt, setOs}). set(_Rules) -> - roundtrip('ChoTRset', {choSet,#'ChoSet'{setInt=88,setOs="A string"}}), - roundtrip('ChoTRset', {choSetI,#'ChoSet'{setInt=88,setOs="A string"}}), - roundtrip('ChoTRset', {choSetE,#'ChoSet'{setInt=88,setOs="A string"}}), - roundtrip('ChoTRset', {'choSet-I',#'ChoSetImp'{setInt=88,setOs="A string"}}), - roundtrip('ChoTRset', {'choSetI-I',#'ChoSetImp'{setInt=88,setOs="A string"}}), - roundtrip('ChoTRset', {'choSetE-I',#'ChoSetImp'{setInt=88,setOs="A string"}}), - roundtrip('ChoTRset', {'choSet-E',#'ChoSetExp'{setInt=88,setOs="A string"}}), - roundtrip('ChoTRset', {'choSetI-E',#'ChoSetExp'{setInt=88,setOs="A string"}}), - roundtrip('ChoTRset', {'choSetE-E',#'ChoSetExp'{setInt=88,setOs="A string"}}), + roundtrip('ChoTRset', {choSet,#'ChoSet'{setInt=88, + setOs = <<"A string">>}}), + roundtrip('ChoTRset', {choSetI,#'ChoSet'{setInt=88, + setOs = <<"A string">>}}), + roundtrip('ChoTRset', {choSetE,#'ChoSet'{setInt=88, + setOs = <<"A string">>}}), + roundtrip('ChoTRset', {'choSet-I',#'ChoSetImp'{setInt=88, + setOs = <<"A string">>}}), + roundtrip('ChoTRset', {'choSetI-I',#'ChoSetImp'{setInt=88, + setOs = <<"A string">>}}), + roundtrip('ChoTRset', {'choSetE-I',#'ChoSetImp'{setInt=88, + setOs = <<"A string">>}}), + roundtrip('ChoTRset', {'choSet-E',#'ChoSetExp'{setInt=88, + setOs = <<"A string">>}}), + roundtrip('ChoTRset', {'choSetI-E',#'ChoSetExp'{setInt=88, + setOs = <<"A string">>}}), + roundtrip('ChoTRset', {'choSetE-E',#'ChoSetExp'{setInt=88, + setOs = <<"A string">>}}), ok. roundtrip(Type, Value) -> diff --git a/lib/asn1/test/testConstraints.erl b/lib/asn1/test/testConstraints.erl index 54ba748519..3ccf883bd6 100644 --- a/lib/asn1/test/testConstraints.erl +++ b/lib/asn1/test/testConstraints.erl @@ -208,14 +208,14 @@ int_constraints(Rules) -> %% More SIZE Constraints %%========================================================== - roundtrip('FixedSize', "0123456789"), - roundtrip('FixedSize2', "0123456789"), - roundtrip('FixedSize2', "0123456789abcdefghij"), + roundtrip('FixedSize', <<"0123456789">>), + roundtrip('FixedSize2', <<"0123456789">>), + roundtrip('FixedSize2', <<"0123456789abcdefghij">>), range_error(Rules, 'FixedSize', "short"), range_error(Rules, 'FixedSize2', "short"), - [roundtrip('VariableSize', lists:seq($A, $A+L-1)) || + [roundtrip('VariableSize', list_to_binary(lists:seq($A, $A+L-1))) || L <- lists:seq(1, 10)], roundtrip_enc('ShorterExt', "a", shorter_ext(Rules, "a")), diff --git a/lib/asn1/test/testEnumExt.erl b/lib/asn1/test/testEnumExt.erl index c66adaf949..878518be11 100644 --- a/lib/asn1/test/testEnumExt.erl +++ b/lib/asn1/test/testEnumExt.erl @@ -59,6 +59,10 @@ main(ber) -> common(ber). common(Erule) -> + roundtrip('SubExt1', blue), + roundtrip('SubExt1', orange), + roundtrip('SubExt1', black), + roundtrip('Seq', {'Seq',blue,42}), roundtrip('Seq', {'Seq',red,42}), roundtrip('Seq', {'Seq',green,42}), diff --git a/lib/asn1/test/testFragmented.erl b/lib/asn1/test/testFragmented.erl index 8d5fa07a5b..35b21f90a9 100644 --- a/lib/asn1/test/testFragmented.erl +++ b/lib/asn1/test/testFragmented.erl @@ -22,10 +22,10 @@ -export([main/1]). main(_Erule) -> - roundtrip('PDU', {'PDU',1,false,["abc","def"]}), + roundtrip('PDU', {'PDU',1,false,[<<"abc">>,<<"def">>]}), B256 = lists:seq(0, 255), K1 = lists:duplicate(4, B256), - K8 = binary_to_list(iolist_to_binary(lists:duplicate(8, K1))), + K8 = iolist_to_binary(lists:duplicate(8, K1)), roundtrip('PDU', {'PDU',1,false,[K8,K8]}), roundtrip('PDU', {'PDU',1,false,[K8,K8,K8,K8]}), roundtrip('PDU', {'PDU',1,false,[K8,K8,K8,K8,K8,K8]}), diff --git a/lib/asn1/test/testInfObj.erl b/lib/asn1/test/testInfObj.erl index cd335e1023..311595cfda 100644 --- a/lib/asn1/test/testInfObj.erl +++ b/lib/asn1/test/testInfObj.erl @@ -49,7 +49,7 @@ main(_Erule) -> roundtrip('RANAPextract1', 'InitiatingMessage2', Val3), roundtrip('InfObj', 'MyPdu', {'MyPdu',42,12,false,"string"}), - roundtrip('InfObj', 'MyPdu', {'MyPdu',{'Seq',1023,"hello"}, + roundtrip('InfObj', 'MyPdu', {'MyPdu',{'Seq',1023,<<"hello">>}, 42,true,"longer string"}), roundtrip('InfObj', 'MyPdu', {'MyPdu',"75712346",43,true,"string"}), @@ -110,11 +110,11 @@ main(_Erule) -> enc_dec('InfObj', 'DefaultInSeq', {'DefaultInSeq',3,asn1_DEFAULT}), roundtrip('InfObj', 'Multiple-Optionals', - {'Multiple-Optionals',1,42,true,"abc"}), + {'Multiple-Optionals',1,42,true,<<"abc">>}), roundtrip('InfObj', 'Multiple-Optionals', - {'Multiple-Optionals',1,asn1_NOVALUE,true,"abc"}), + {'Multiple-Optionals',1,asn1_NOVALUE,true,<<"abc">>}), roundtrip('InfObj', 'Multiple-Optionals', - {'Multiple-Optionals',1,42,asn1_NOVALUE,"abc"}), + {'Multiple-Optionals',1,42,asn1_NOVALUE,<<"abc">>}), roundtrip('InfObj', 'Multiple-Optionals', {'Multiple-Optionals',1,42,true,asn1_NOVALUE}), roundtrip('InfObj', 'Multiple-Optionals', diff --git a/lib/asn1/test/testMergeCompile.erl b/lib/asn1/test/testMergeCompile.erl index 7cda71c441..b21897cfc2 100644 --- a/lib/asn1/test/testMergeCompile.erl +++ b/lib/asn1/test/testMergeCompile.erl @@ -30,12 +30,12 @@ main(Erule) -> %% test of module MS.set.asn that tests OTP-4492: different tagdefault in %% modules and types with same name in modules - MSVal = {'Type4M2',8,true,three,"OCTET STRING"}, + MSVal = {'Type4M2',8,true,three,<<"OCTET STRING">>}, asn1_test_lib:roundtrip('MS', 'Type4M2', MSVal), %% test of RANAP.set.asn1 PIEVal2 = [{'ProtocolIE-Field',4,ignore,{radioNetwork,'rab-pre-empted'}}], - EncVal = + EncVal0 = case Erule of per -> <<1,100>>; @@ -44,6 +44,7 @@ main(Erule) -> ber -> <<2,1,1>> end, + EncVal = {asn1_OPENTYPE,EncVal0}, PEVal2 = [{'ProtocolExtensionField',1,ignore,EncVal}, {'ProtocolExtensionField',2,reject,EncVal}], Val2 = @@ -142,7 +143,40 @@ test('InsertSubscriberDataArg') -> ok. test(mvrasn6,'InsertSubscriberDataArg') -> - Val = {'InsertSubscriberDataArg',"IMSI","Address","C",serviceGranted,["abc","cde"],["tele","serv","ice"],asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,{'NAEA-PreferredCI',"NCC",asn1_NOVALUE},{'GPRSSubscriptionData','NULL',[{'PDP-Context',49,"PT","PDP-Address","QoS",'NULL',"APN",asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}],asn1_NOVALUE},'NULL',onlyMSC,{'LSAInformation','NULL',accessOutsideLSAsAllowed,[{'LSAData',"LSA","L",'NULL',asn1_NOVALUE},{'LSAData',"LSA","L",'NULL',asn1_NOVALUE}],asn1_NOVALUE},'NULL',{'LCSInformation',["Addr","ess","string"],[{'LCS-PrivacyClass',"S","ExtSS",notifyLocationAllowed,[{'ExternalClient',{'LCSClientExternalID',"Addr",asn1_NOVALUE},asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}],[broadcastService,anonymousLocation,targetMSsubscribedService],asn1_NOVALUE}],asn1_NOVALUE},100,"age",{'MC-SS-Info',"S","ExtSS",5,4,asn1_NOVALUE},"C",{'SGSN-CAMEL-SubscriptionInfo',{'GPRS-CSI',[{'GPRS-CamelTDPData',attach,13,"Addr",continueTransaction,asn1_NOVALUE}],11,asn1_NOVALUE,'NULL','NULL'},{'SMS-CSI',[{'SMS-CAMEL-TDP-DataList','sms-CollectedInfo',13,"Addr",continueTransaction,asn1_NOVALUE}],11,asn1_NOVALUE,'NULL','NULL'},asn1_NOVALUE},"ON"}, - {ok,Bytes} = 'Mvrasn6':encode('InsertSubscriberDataArg', Val), - {ok,_} = 'Mvrasn6':decode('InsertSubscriberDataArg', Bytes), + Val = {'InsertSubscriberDataArg',<<"IMSI">>,<<"Address">>,<<"C">>, + serviceGranted,[<<"abc">>,<<"cde">>], + [<<"tele">>,<<"serv">>,<<"ice">>], + asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE, + asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE, + {'NAEA-PreferredCI',<<"NCC">>,asn1_NOVALUE}, + {'GPRSSubscriptionData','NULL', + [{'PDP-Context',49,<<"PT">>,<<"PDP-Address">>,<<"QoS">>, + 'NULL',<<"APN">>,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}], + asn1_NOVALUE},'NULL',onlyMSC, + {'LSAInformation','NULL',accessOutsideLSAsAllowed, + [{'LSAData',<<"LSA">>,<<"L">>,'NULL',asn1_NOVALUE}, + {'LSAData',<<"LSA">>,<<"L">>,'NULL',asn1_NOVALUE}], + asn1_NOVALUE},'NULL', + {'LCSInformation',[<<"Addr">>,<<"ess">>,<<"string">>], + [{'LCS-PrivacyClass',<<"S">>,<<"ExtSS">>,notifyLocationAllowed, + [{'ExternalClient', + {'LCSClientExternalID',<<"Addr">>,asn1_NOVALUE}, + asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}], + [broadcastService,anonymousLocation,targetMSsubscribedService], + asn1_NOVALUE}],asn1_NOVALUE}, + 100,<<"age">>, + {'MC-SS-Info',<<"S">>,<<"ExtSS">>,5,4,asn1_NOVALUE}, + <<"C">>, + {'SGSN-CAMEL-SubscriptionInfo', + {'GPRS-CSI', + [{'GPRS-CamelTDPData',attach,13,<<"Addr">>, + continueTransaction,asn1_NOVALUE}], + 11,asn1_NOVALUE,'NULL','NULL'}, + {'SMS-CSI', + [{'SMS-CAMEL-TDP-Data','sms-CollectedInfo', + 13,<<"Addr">>,continueTransaction,asn1_NOVALUE}], + 11,asn1_NOVALUE,'NULL','NULL'}, + asn1_NOVALUE}, + <<"ON">>}, + asn1_test_lib:roundtrip('Mvrasn6', 'InsertSubscriberDataArg', Val), ok. diff --git a/lib/asn1/test/testParameterizedInfObj.erl b/lib/asn1/test/testParameterizedInfObj.erl index f3b4f9b170..2fe900792d 100644 --- a/lib/asn1/test/testParameterizedInfObj.erl +++ b/lib/asn1/test/testParameterizedInfObj.erl @@ -20,7 +20,7 @@ -module(testParameterizedInfObj). --export([main/2,ranap/1]). +-export([main/2,param/1,ranap/1]). -include_lib("test_server/include/test_server.hrl"). @@ -36,31 +36,29 @@ main(Config, Erule) -> param2(Config, Erule). param(Erule) -> - PERVal = #'AllocationOrRetentionPriority' - {priorityLevel = true, - iE_Extensions = - [#'ProtocolExtensionField'{id=14, - criticality=reject, - extensionValue= <<0>>}, - #'ProtocolExtensionField'{id=2, - criticality=ignore, - extensionValue= <<1>>}]}, - BERVal = #'AllocationOrRetentionPriority' - {priorityLevel = true, - iE_Extensions = - [#'ProtocolExtensionField'{id=14, - criticality=reject, - extensionValue= <<2,1,0>>}, - #'ProtocolExtensionField'{id=2, - criticality=ignore, - extensionValue= <<2,1,1>>}]}, - case Erule of - ber -> - roundtrip('AllocationOrRetentionPriority', BERVal); - per -> - roundtrip('AllocationOrRetentionPriority', PERVal); - uper -> - roundtrip('AllocationOrRetentionPriority', PERVal) + Exts0 = case Erule of + ber -> + %% As implemented, the open type must contain + %% valid BER-encoded data. + [{14,<<2,1,0>>},{2,<<2,1,0>>}]; + _ -> + %% The PER decoder will not look inside the open type. + [{14,<<0>>},{2,<<"anything goes">>}] + end, + case 'Param':legacy_erlang_types() of + false -> + Exts = [#'ProtocolExtensionField'{id=Id, + criticality=reject, + extensionValue={asn1_OPENTYPE, + Eval}} || + {Id,Eval} <- Exts0], + aor_roundtrip(Exts); + true -> + Exts = [#'ProtocolExtensionField'{id=Id, + criticality=reject, + extensionValue=Eval} || + {Id,Eval} <- Exts0], + aor_roundtrip(Exts) end, %% test code for OTP-4242, ValueFromObject @@ -72,8 +70,13 @@ param(Erule) -> {error,_Reason2} = 'Param':decode('OS2',[4,4,1,2,3,4]), {ok,_Val4} = 'Param':decode('OS1',[4,2,1,2]); _ -> %per/uper - roundtrip('OS1', [1,2]), - {error,_Reason3} = 'Param':encode('OS1', [1,2,3,4]) + case 'Param':legacy_erlang_types() of + false -> + roundtrip('OS1', <<1,2>>), + {error,_Reason3} = 'Param':encode('OS1', <<1,2,3,4>>); + true -> + ok + end end, roundtrip('Scl', {'Scl',42,{a,9738654}}), @@ -82,6 +85,11 @@ param(Erule) -> ok. +aor_roundtrip(Exts) -> + Val = #'AllocationOrRetentionPriority'{priorityLevel = true, + iE_Extensions = Exts}, + roundtrip('AllocationOrRetentionPriority', Val). + roundtrip(T, V) -> asn1_test_lib:roundtrip('Param', T, V). @@ -102,11 +110,11 @@ ranap(_Erule) -> param2(Config, Erule) -> roundtrip2('HandoverRequired', {'HandoverRequired', - [{'ProtocolIE-Field',1,"ABC"}, + [{'ProtocolIE-Field',1,<<"ABC">>}, {'ProtocolIE-Field',2,577799}]}), Enc = roundtrip2('HandoverRequired', {'HandoverRequired', - [{'ProtocolIE-Field',1,"ABC"}, + [{'ProtocolIE-Field',1,<<"ABC">>}, {'ProtocolIE-Field',2,-42}, {'ProtocolIE-Field',100,533}, {'ProtocolIE-Field',101,true}]}), @@ -127,17 +135,19 @@ param2(Config, Erule) -> [{i,DataDir},{outdir,CaseDir},Erule]), %% Decompile extended data. - {ok,{'HandoverRequired',[{'ProtocolIE-Field',1,"ABC"}, + {ok,{'HandoverRequired',[{'ProtocolIE-Field',1,<<"ABC">>}, {'ProtocolIE-Field',2,-42}, - {'ProtocolIE-Field',100,Open100}, - {'ProtocolIE-Field',101,Open101}]}} = + {'ProtocolIE-Field',100, + {asn1_OPENTYPE,Open100}}, + {'ProtocolIE-Field',101, + {asn1_OPENTYPE,Open101}}]}} = 'Param2':decode('HandoverRequired', Enc), true = is_binary(Open100), true = is_binary(Open101), %% Test single root. roundtrip2('SingleRoot', - {'SingleRoot',[{'ProtocolIE-Field',1,"ABC"}, + {'SingleRoot',[{'ProtocolIE-Field',1,<<"ABC">>}, {'ProtocolIE-Field',2,9999}]}), ok. diff --git a/lib/asn1/test/testPrimExternal.erl b/lib/asn1/test/testPrimExternal.erl index 07a1de931f..a03760976d 100644 --- a/lib/asn1/test/testPrimExternal.erl +++ b/lib/asn1/test/testPrimExternal.erl @@ -45,6 +45,6 @@ external(_Rules) -> 'XExpNT', 'XExpImp', 'XExpExp'], - _ = [asn1_test_lib:roundtrip('PrimExternal', T, "kalle") || + _ = [asn1_test_lib:roundtrip('PrimExternal', T, <<"kalle">>) || T <- Types], ok. diff --git a/lib/asn1/test/testPrimStrings.erl b/lib/asn1/test/testPrimStrings.erl index 2fe0780701..155d6f6ff5 100644 --- a/lib/asn1/test/testPrimStrings.erl +++ b/lib/asn1/test/testPrimStrings.erl @@ -18,6 +18,8 @@ %% %% -module(testPrimStrings). +-compile([{nowarn_deprecated_function,{asn1rt,utf8_list_to_binary,1}}, + {nowarn_deprecated_function,{asn1rt,utf8_binary_to_list,1}}]). -export([bit_string/2]). -export([octet_string/1]). @@ -34,14 +36,11 @@ fragmented(Rules) -> Lens = fragmented_lengths(), - fragmented_octet_string(Rules, Lens), - case Rules of - per -> - %% NYI. - ok; - _ -> - fragmented_strings(Lens) - end. + case 'PrimStrings':legacy_erlang_types() of + false -> fragmented_octet_string(Rules, Lens); + true -> ok + end, + fragmented_strings(Lens). fragmented_strings(Lens) -> Types = ['Ns','Ps','Ps11','Vis','IA5'], @@ -74,33 +73,37 @@ bit_string(Rules, Opts) -> %% Bs1 ::= BIT STRING %%========================================================== - bs_roundtrip('Bs1', 0, <<>>), - bs_roundtrip('Bs1', 4, <<1:3>>), - bs_roundtrip('Bs1', 15, <<15:4>>), - bs_roundtrip('Bs1', 255, <<255:8>>), - - bs_roundtrip('Bs1', 256, [0,0,0,0,0,0,0,0,1]), - bs_roundtrip('Bs1', 257, [1,0,0,0,0,0,0,0,1]), - bs_roundtrip('Bs1', 444, [0,0,1,1,1,1,0,1,1]), - - {ok,Enc1} = 'PrimStrings':encode('Bs1', 12345678901234567890), - {ok,_} = 'PrimStrings':decode('Bs1', Enc1), + bs_roundtrip('Bs1', <<>>), + bs_roundtrip('Bs1', <<1:3>>), + bs_roundtrip('Bs1', <<15:4>>), + bs_roundtrip('Bs1', <<2#010010:6>>), + bs_roundtrip('Bs1', <<2#11111111:8>>), + bs_roundtrip('Bs1', <<2#100000000:9>>), + bs_roundtrip('Bs1', <<2#100000001:9>>), + bs_roundtrip('Bs1', <<2#001111011:9>>), + bs_roundtrip('Bs1', <<2#0100101111100010011:19>>), - bs_roundtrip('Bs1', [1,1,1,1,1,1,1,1]), - bs_roundtrip('Bs1', [0,1,0,0,1,0]), - bs_roundtrip('Bs1', [1,0,0,0,0,0,0,0,0]), - bs_roundtrip('Bs1', [0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,1]), + case 'PrimStrings':legacy_erlang_types() of + false -> + ok; + true -> + {ok,Enc1} = 'PrimStrings':encode('Bs1', 12345678901234567890), + {ok,_} = 'PrimStrings':decode('Bs1', Enc1) + end, case {Rules,Opts} of - {ber,[]} -> + {ber,[legacy_erlang_types]} -> bs_decode('Bs1', <<35,8,3,2,0,73,3,2,4,32>>, [0,1,0,0,1,0,0,1,0,0,1,0]), bs_decode('Bs1', <<35,9,3,2,0,234,3,3,7,156,0>>, [1,1,1,0,1,0,1,0,1,0,0,1,1,1,0,0,0]), bs_decode('Bs1', <<35,128,3,2,0,234,3,3,7,156,0,0,0>>, [1,1,1,0,1,0,1,0,1,0,0,1,1,1,0,0,0]); - _ -> + {ber,[]} -> + %% XXX + ok; + {_,_} -> %% DER, PER, UPER consistent_def_enc('BsDef1', [2#111101, @@ -120,30 +123,39 @@ bit_string(Rules, Opts) -> %%========================================================== roundtrip('Bs2', [mo,tu,fr]), - roundtrip('Bs2', [0,1,1,0,0,1,0], [mo,tu,fr]), + bs_roundtrip('Bs2', <<2#0110010:7>>, [mo,tu,fr]), + bs_roundtrip('Bs2', <<2#0110011:7>>, [mo,tu,fr,sa]), %%========================================================== %% Bs3 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) } (SIZE (1..7)) %%========================================================== roundtrip('Bs3', [mo,tu,fr]), - bs_roundtrip('Bs3', [0,1,1,0,0,1,0], [mo,tu,fr]), + bs_roundtrip('Bs3', <<2#0110010:7>>, [mo,tu,fr]), + bs_roundtrip('Bs3', <<2#0110010:7>>, [mo,tu,fr]), + bs_roundtrip('Bs2', <<2#0110011:7>>, [mo,tu,fr,sa]), + bs_roundtrip('Bs3', <<2#011001:6>>, [mo,tu,fr]), + bs_roundtrip('Bs3', <<2#11:2>>, [su,mo]), %%========================================================== %% Bs7 ::= BIT STRING (SIZE (24)) %%========================================================== - bs_roundtrip('Bs7', 53245, - [1,0,1,1,1,1,1,1,1,1,1,1,0,0,1,1,0,0,0,0,0,0,0,0]), - bs_roundtrip('Bs7', [1,0,1,0], - [1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + bs_roundtrip('Bs7', <<23563:24>>), + case 'PrimStrings':legacy_erlang_types() of + false -> +%% {error,_} = 'PrimStrings':encode('Bs7', <<2#1010:4>>); + ok; + true -> + ok + end, %%========================================================== %% BsPri ::= [PRIVATE 61] BIT STRING %%========================================================== - bs_roundtrip('BsPri', 45, [1,0,1,1,0,1]), - bs_roundtrip('BsPri', 211, [1,1,0,0,1,0,1,1]), + bs_roundtrip('BsPri', <<2#101101:6>>), + bs_roundtrip('BsPri', <<2#11001011:8>>), case Rules of ber -> @@ -164,8 +176,8 @@ bit_string(Rules, Opts) -> %% BsExpPri ::= [PRIVATE 61] EXPLICIT BIT STRING %%========================================================== - bs_roundtrip('BsExpPri', 45, [1,0,1,1,0,1]), - bs_roundtrip('BsExpPri', 211, [1,1,0,0,1,0,1,1]), + bs_roundtrip('BsExpPri', <<2#101101:6>>), + bs_roundtrip('BsExpPri', <<2#11001011:8>>), case Rules of ber -> @@ -186,14 +198,14 @@ bit_string(Rules, Opts) -> %% veteran(2), collegeGraduate(3)}, test case for OTP-5710 %%========================================================== - {ok,Bytes54} = 'BitStr':encode('PersonalStatus', []), + {ok,Bytes54} = 'BitStr':encode('PersonalStatus', <<>>), {ok,[]} = 'BitStr':decode('PersonalStatus', Bytes54), %%========================================================== %% BS5932 ::= BIT STRING (SIZE (5..MAX)) %% test case for OTP-5932 %%========================================================== - bs_roundtrip('BSMAX', [1,0,1,0,1]), + bs_roundtrip('BSMAX', <<2#10101:5>>), case Rules of ber -> {error,_} = 'PrimStrings':encode('BSMAX', [1,0,1]); @@ -207,28 +219,35 @@ bit_string(Rules, Opts) -> %% BS1024 ::= BIT STRING (SIZE (1024)) %% test case for OTP-7602 %%========================================================== - BSmaker = - fun(_F,S,S,_,Acc) -> - Acc; - (F,Ix,S,{A,B},Acc) -> - F(F,Ix+1,S,{B,A},[A|Acc]) - end, - - BSList255 = BSmaker(BSmaker,0,255,{1,0},[]), - bs_roundtrip('BS255', BSList255), - BSList256 = BSmaker(BSmaker,0,256,{1,0},[]), - bs_roundtrip('BS256', BSList256), - BSList1024 = BSmaker(BSmaker,0,1024,{1,0},[]), - bs_roundtrip('BS1024', BSList1024), - bs_roundtrip('TransportLayerAddress', [0,1,1,0]), + bs_roundtrip('BS255', random_bits(255)), + bs_roundtrip('BS256', random_bits(256)), + bs_roundtrip('BS1024', random_bits(1024)), + + bs_roundtrip('TransportLayerAddress', <<2#0110:4>>), case Rules of ber -> ok; _ -> per_bs_strings() end. -consistent_def_enc(Type, Vs) -> +random_bits(N) -> + Seed = integer_to_list(erlang:phash2(erlang:now())), + random_bits(<<>>, N, Seed). + +random_bits(Bin, N, Seed) -> + RandomBits = erlang:md5(Seed), + Bits = bit_size(RandomBits), + if + Bits < N -> + random_bits(<<Bin/bitstring,RandomBits/bitstring>>, + N-Bits, RandomBits); + true -> + <<LastBits:N/bitstring,_/bitstring>> = RandomBits, + <<Bin/bitstring,LastBits/bitstring>> + end. + +consistent_def_enc(Type, Vs0) -> M = 'PrimStrings', {ok,Enc} = M:encode(Type, {Type,asn1_DEFAULT}), {ok,Val} = M:decode(Type, Enc), @@ -241,6 +260,13 @@ consistent_def_enc(Type, Vs) -> {legacy,{_,Bs}} when is_list(Bs) -> ok end, + %% If this is not the legacy format, only bitstrings are + %% allowed. + Vs = case M:legacy_erlang_types() of + false -> [V || V <- Vs0, is_bitstring(V)]; + true -> Vs0 + end, + %% All values should be recognized and encoded as the %% the default value (i.e. not encoded at all). _ = [{ok,Enc} = M:encode(Type, {Type,V}) || V <- Vs], @@ -252,18 +278,9 @@ consistent_def_enc(Type, Vs) -> %% a SIZE constraint). per_bs_strings() -> - bs_roundtrip('Bs3', [0,0,1,0,0,0,0], [tu]), bs_roundtrip('Bs3', <<2#0010000:7>>, [tu]), - bs_roundtrip('Bs3', {1,<<2#00100000:8>>}, [tu]), - - bs_roundtrip('Bs4', [0,1,1,0,0,1,0], [mo,tu,fr]), bs_roundtrip('Bs4', <<2#0110010:7>>, [mo,tu,fr]), - bs_roundtrip('Bs4', {1,<<2#01100100:8>>}, [mo,tu,fr]), - - bs_roundtrip('Bs4', [0,1,1,0,0,0,0], [mo,tu]), bs_roundtrip('Bs4', <<2#011:3,0:32>>, [mo,tu]), - bs_roundtrip('Bs4', {5,<<2#011:3,0:32,0:5>>}, [mo,tu]), - [per_trailing_zeroes(B) || B <- lists:seq(0, 255)], ok. @@ -279,10 +296,6 @@ per_trailing_zeroes(Byte) -> {bit,LastBitPos} -> LastBitPos+1 end, - %% List of zeroes and ones. - named_roundtrip(L, Pos, ExpectedSz), - named_roundtrip(L++[0,0,0,0,0], Pos, ExpectedSz), - %% Bitstrings. Bs = << <<B:1>> || B <- L >>, Sz = bit_size(Bs), @@ -290,14 +303,22 @@ per_trailing_zeroes(Byte) -> Bin = <<Bs:Sz/bits,0:16,0:7>>, named_roundtrip(Bin, Pos, ExpectedSz), - %% Compact bitstring. - named_roundtrip({7,Bin}, Pos, ExpectedSz), + case 'PrimStrings':legacy_erlang_types() of + false -> + ok; + true -> + %% List of zeroes and ones. + named_roundtrip(L, Pos, ExpectedSz), + named_roundtrip(L++[0,0,0,0,0], Pos, ExpectedSz), - %% Integer bitstring (obsolete). - IntBs = intlist_to_integer(L, 0, 0), - named_roundtrip(IntBs, Pos, ExpectedSz), + %% Compact bitstring. + named_roundtrip({7,Bin}, Pos, ExpectedSz), - ok. + %% Integer bitstring (obsolete). + IntBs = intlist_to_integer(L, 0, 0), + named_roundtrip(IntBs, Pos, ExpectedSz), + ok + end. make_bit_list(0) -> []; make_bit_list(B) -> [B band 1|make_bit_list(B bsr 1)]. @@ -331,61 +352,62 @@ octet_string(Rules) -> %% Os ::= OCTET STRING %%========================================================== + Legacy = 'PrimStrings':legacy_erlang_types(), case Rules of - ber -> - {ok,"Jones"} = + ber when not Legacy -> + {ok,<<"Jones">>} = 'PrimStrings':decode('Os', <<4,5,16#4A,16#6F,16#6E,16#65,16#73>>), - {ok,"Jones"} = + {ok,<<"Jones">>} = 'PrimStrings':decode('Os', <<36,9,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73>>), - {ok,"Jones"} = + {ok,<<"Jones">>} = 'PrimStrings':decode('Os', <<36,128,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73,0,0>>), ok; _ -> ok end, - roundtrip('Os', [47,23,99,255,1]), - roundtrip('OsCon', [47,23,99,255,1]), - roundtrip('OsPri', [47,23,99,255,1]), - roundtrip('OsApp', [47,23,99,255,1]), + os_roundtrip('Os', <<47,23,99,255,1>>), + os_roundtrip('OsCon', <<47,23,99,255,1>>), + os_roundtrip('OsPri', <<47,23,99,255,1>>), + os_roundtrip('OsApp', <<47,23,99,255,1>>), - roundtrip('OsExpCon', [47,23,99,255,1]), - roundtrip('OsExpPri', [47,23,99,255,1]), - roundtrip('OsExpApp', [47,23,99,255,1]), + os_roundtrip('OsExpCon', <<47,23,99,255,1>>), + os_roundtrip('OsExpPri', <<47,23,99,255,1>>), + os_roundtrip('OsExpApp', <<47,23,99,255,1>>), - roundtrip('Os', []), - roundtrip('OsApp', []), - roundtrip('OsExpApp',[]), + os_roundtrip('Os', <<>>), + os_roundtrip('OsApp', <<>>), + os_roundtrip('OsExpApp', <<>>), - OsR = "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", + OsR = <<"12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890">>, - roundtrip('Os', OsR), - roundtrip('OsCon', OsR), - roundtrip('OsExpApp', OsR), + os_roundtrip('Os', OsR), + os_roundtrip('OsCon', OsR), + os_roundtrip('OsExpApp', OsR), case Rules of - ber -> - {ok,"Jones"} = 'PrimStrings':decode('OsExpApp', <<127,62,7,4,5,16#4A,16#6F,16#6E,16#65,16#73>>), - {ok,"Jones"} = 'PrimStrings':decode('OsExpApp', <<127,62,11,36,9,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73>>), - {ok,"Jones"} = 'PrimStrings':decode('OsExpApp', <<127,62,13,36,128,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73,0,0>>), - {ok,"Jones"} = 'PrimStrings':decode('OsExpApp', <<127,62,128,36,128,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73,0,0,0,0>>), - {ok,"JonesJones"} = 'PrimStrings':decode('OsExpApp', <<127,62,128,36,128,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73,0,0,36,128,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73,0,0,0,0>>), + ber when not Legacy -> + {ok,<<"Jones">>} = 'PrimStrings':decode('OsExpApp', <<127,62,7,4,5,16#4A,16#6F,16#6E,16#65,16#73>>), + {ok,<<"Jones">>} = 'PrimStrings':decode('OsExpApp', <<127,62,11,36,9,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73>>), + {ok,<<"Jones">>} = 'PrimStrings':decode('OsExpApp', <<127,62,13,36,128,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73,0,0>>), + {ok,<<"Jones">>} = 'PrimStrings':decode('OsExpApp', <<127,62,128,36,128,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73,0,0,0,0>>), + {ok,<<"JonesJones">>} = 'PrimStrings':decode('OsExpApp', <<127,62,128,36,128,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73,0,0,36,128,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73,0,0,0,0>>), ok; - - _-> + _ -> ok end, S255 = lists:seq(1, 255), - Strings = {type,true,"","1","12","345",true, - S255,[$a|S255],[$a,$b|S255],397}, - p_roundtrip('OsFixedStrings', Strings), - p_roundtrip('OsFixedStringsExt', Strings), - p_roundtrip('OsVarStringsExt', Strings), + Strings = {type,true,<<"">>,<<"1">>,<<"12">>,<<"345">>,true, + list_to_binary(S255),list_to_binary([$a|S255]), + list_to_binary([$a,$b|S255]),397}, + p_os_roundtrip('OsFixedStrings', Strings), + p_os_roundtrip('OsFixedStringsExt', Strings), + p_os_roundtrip('OsVarStringsExt', Strings), ShortenedStrings = shorten_by_two(Strings), - p_roundtrip('OsFixedStringsExt', ShortenedStrings), - p_roundtrip('OsVarStringsExt', ShortenedStrings), + p_os_roundtrip('OsFixedStringsExt', ShortenedStrings), + p_os_roundtrip('OsVarStringsExt', ShortenedStrings), ok. fragmented_octet_string(Erules, Lens) -> @@ -414,13 +436,14 @@ fragmented_octet_string(Erules, Types, L) -> ok. enc_frag(Erules, Type, Value) -> - {ok,Encoded} = 'PrimStrings':encode(Type, Value), + M = 'PrimStrings', + {ok,Encoded} = M:encode(Type, Value), case Erules of ber -> Encoded; _ -> %% Validate encoding with our own encoder. - Encoded = enc_frag_1(<<>>, list_to_binary(Value)) + Encoded = enc_frag_1(<<>>, Value) end. enc_frag_1(Res, Bin0) -> @@ -439,12 +462,12 @@ enc_frag_1(Res, Bin0) -> end. make_value(L) -> - make_value(L, 0, []). + make_value(L, 0, <<>>). make_value(0, _, Acc) -> Acc; make_value(N, Byte, Acc) when Byte =< 255 -> - make_value(N-1, Byte+7, [Byte|Acc]); + make_value(N-1, Byte+7, <<Acc/binary,Byte:8>>); make_value(N, Byte, Acc) -> make_value(N, Byte band 16#FF, Acc). @@ -742,10 +765,32 @@ utf8_string(_Rules) -> shorten_by_two(Tuple) -> L = [case E of [_,_|T] -> T; + <<_:16,T/binary>> -> T; _ -> E end || E <- tuple_to_list(Tuple)], list_to_tuple(L). +p_os_roundtrip(Type, Value0) -> + Value = setelement(1, Value0, Type), + p_os_roundtrip_1(Type, Value). + +p_os_roundtrip_1(Type, Value) -> + M = 'PrimStrings', + case M:legacy_erlang_types() of + false -> + asn1_test_lib:roundtrip(M, Type, Value); + true -> + {ok,Encoded} = M:encode(Type, Value), + Es0 = tuple_to_list(Value), + Es1 = [if + is_binary(E) -> binary_to_list(E); + true -> E + end || E <- Es0], + ListValue = list_to_tuple(Es1), + {ok,Encoded} = M:encode(Type, ListValue), + {ok,ListValue} = M:decode(Type, Encoded) + end. + p_roundtrip(Type, Value0) -> Value = setelement(1, Value0, Type), roundtrip(Type, Value). @@ -759,15 +804,57 @@ roundtrip(Type, Value, Expected) -> bs_roundtrip(Type, Value) -> bs_roundtrip(Type, Value, Value). -bs_roundtrip(Type, Value, Expected) -> +os_roundtrip(Type, Bin) when is_binary(Bin) -> M = 'PrimStrings', - {ok,Encoded} = M:encode(Type, Value), - {ok,Encoded} = M:encode(Type, Expected), - case M:decode(Type, Encoded) of - {ok,Expected} -> - ok; - {ok,Other} -> - Expected = convert(Other, Expected) + case M:legacy_erlang_types() of + false -> + asn1_test_lib:roundtrip(M, Type, Bin); + true -> + {ok,Encoded} = M:encode(Type, Bin), + List = binary_to_list(Bin), + {ok,Encoded} = M:encode(Type, List), + {ok,List} = M:decode(Type, Encoded) + end. + +bs_roundtrip(Type, Value, Expected) when is_bitstring(Value) -> + M = 'PrimStrings', + case M:legacy_erlang_types() of + false -> + asn1_test_lib:roundtrip(M, Type, Value, Expected); + true -> + {ok,Encoded} = M:encode(Type, Value), + BitList = [B || <<B:1>> <= Value], + {ok,Encoded} = M:encode(Type, BitList), + case BitList of + [] -> + {ok,Encoded} = M:encode(Type, 0); + [_|_] -> + case lists:last(BitList) of + 1 -> + Int = lists:foldr(fun(B, A) -> + (A bsl 1) bor B + end, 0, BitList), + {ok,Encoded} = M:encode(Type, Int); + 0 -> + %% This BIT STRING cannot be represented + %% as an integer. + ok + end + end, + Compact = case bit_size(Value) of + Bits when Bits rem 8 =:= 0 -> + {0,Value}; + Bits -> + Unused = 8 - Bits rem 8, + {Unused,<<Value:Bits/bitstring,0:Unused>>} + end, + {ok,Encoded} = M:encode(Type, Compact), + case M:decode(Type, Encoded) of + {ok,Expected} -> + ok; + {ok,Other} -> + Expected = convert(Other, Expected) + end end. bs_decode(Type, Encoded, Expected) -> diff --git a/lib/asn1/test/testSeqExtension.erl b/lib/asn1/test/testSeqExtension.erl index 8473459c36..c16e9fcd4c 100644 --- a/lib/asn1/test/testSeqExtension.erl +++ b/lib/asn1/test/testSeqExtension.erl @@ -44,7 +44,7 @@ main(Erule, DataDir, Opts) -> roundtrip('SeqExt4', #'SeqExt4'{bool=true,int=12345}), roundtrip('SeqExt4', #'SeqExt4'{bool=false,int=123456}), - roundtrip('SeqExt5', #'SeqExt5'{name="Arne",shoesize=47}), + roundtrip('SeqExt5', #'SeqExt5'{name = <<"Arne">>,shoesize=47}), %% Encode a value with this version of the specification. BigInt = 128638468966, @@ -52,7 +52,7 @@ main(Erule, DataDir, Opts) -> s2=#'SeqExt2'{bool=true,int=2345}, s3=#'SeqExt3'{bool=false,int=17}, s4=#'SeqExt4'{bool=true,int=38739739}, - s5=#'SeqExt5'{name="Arne",shoesize=47}, + s5=#'SeqExt5'{name = <<"Arne">>,shoesize=47}, s6=#'SeqExt6'{i1=531,i2=601,i3=999, i4=777,i5=11953, i6=13553,i7=77777}, diff --git a/lib/asn1/test/testSeqExternal.erl b/lib/asn1/test/testSeqExternal.erl index a8e0902244..0b1d305054 100644 --- a/lib/asn1/test/testSeqExternal.erl +++ b/lib/asn1/test/testSeqExternal.erl @@ -29,15 +29,15 @@ -record('SeqXSet3',{bool, int, set}). main(_Rules) -> - roundtrip('XNTNT', #'XSeqNT'{os="kalle",bool=true}), - roundtrip('XImpNT', #'XSeqNT'{os="kalle",bool=true}), - roundtrip('XExpNT', #'XSeqNT'{os="kalle",bool=true}), - roundtrip('XNTImp', #'XSeqImp'{os="kalle",bool=true}), - roundtrip('XImpImp', #'XSeqImp'{os="kalle",bool=true}), - roundtrip('XExpImp', #'XSeqImp'{os="kalle",bool=true}), - roundtrip('XNTExp', #'XSeqExp'{os="kalle",bool=true}), - roundtrip('XImpExp', #'XSeqExp'{os="kalle",bool=true}), - roundtrip('XExpExp', #'XSeqExp'{os="kalle",bool=true}), + roundtrip('XNTNT', #'XSeqNT'{os = <<"kalle">>,bool=true}), + roundtrip('XImpNT', #'XSeqNT'{os = <<"kalle">>,bool=true}), + roundtrip('XExpNT', #'XSeqNT'{os = <<"kalle">>,bool=true}), + roundtrip('XNTImp', #'XSeqImp'{os = <<"kalle">>,bool=true}), + roundtrip('XImpImp', #'XSeqImp'{os = <<"kalle">>,bool=true}), + roundtrip('XExpImp', #'XSeqImp'{os = <<"kalle">>,bool=true}), + roundtrip('XNTExp', #'XSeqExp'{os = <<"kalle">>,bool=true}), + roundtrip('XImpExp', #'XSeqExp'{os = <<"kalle">>,bool=true}), + roundtrip('XExpExp', #'XSeqExp'{os = <<"kalle">>,bool=true}), roundtrip('SeqXSet1', #'SeqXSet1'{set=#'XSet1'{bool1=true,int1=77, set1=#'XSetIn'{boolIn=false,intIn=88}}, diff --git a/lib/asn1/test/testSeqOf.erl b/lib/asn1/test/testSeqOf.erl index 7f8f4079b4..25059d6052 100644 --- a/lib/asn1/test/testSeqOf.erl +++ b/lib/asn1/test/testSeqOf.erl @@ -85,10 +85,10 @@ main(_Rules) -> seq43=SeqIn3}), roundtrip('Seq5', {'Seq5',true,[],77}), - roundtrip('Seq5', {'Seq5',true,[""],77}), - roundtrip('Seq5', {'Seq5',true,["a"],77}), - roundtrip('Seq5', {'Seq5',true,["ab"],77}), - roundtrip('Seq5', {'Seq5',true,["abc"],77}), + roundtrip('Seq5', {'Seq5',true,[<<"">>],77}), + roundtrip('Seq5', {'Seq5',true,[<<"a">>],77}), + roundtrip('Seq5', {'Seq5',true,[<<"ab">>],77}), + roundtrip('Seq5', {'Seq5',true,[<<"abc">>],77}), roundtrip('Seq6', {'Seq6',[],[],101}), roundtrip('Seq6', {'Seq6',[],[7],101}), @@ -100,15 +100,15 @@ main(_Rules) -> roundtrip('Seq8', {'Seq8',[],37}), roundtrip('Seq9', {'Seq9',true,[],97}), - roundtrip('Seq9', {'Seq9',true,[""],97}), - roundtrip('Seq9', {'Seq9',true,["x"],97}), - roundtrip('Seq9', {'Seq9',true,["xy"],97}), - roundtrip('Seq9', {'Seq9',true,["xyz"],97}), - - roundtrip('Seq10', {'Seq10',true,[""],97}), - roundtrip('Seq10', {'Seq10',true,["a"],97}), - roundtrip('Seq10', {'Seq10',true,["a","b"],97}), - roundtrip('Seq10', {'Seq10',true,["a","b","c"],97}), + roundtrip('Seq9', {'Seq9',true,[<<"">>],97}), + roundtrip('Seq9', {'Seq9',true,[<<"x">>],97}), + roundtrip('Seq9', {'Seq9',true,[<<"xy">>],97}), + roundtrip('Seq9', {'Seq9',true,[<<"xyz">>],97}), + + roundtrip('Seq10', {'Seq10',true,[<<"">>],97}), + roundtrip('Seq10', {'Seq10',true,[<<"a">>],97}), + roundtrip('Seq10', {'Seq10',true,[<<"a">>,<<"b">>],97}), + roundtrip('Seq10', {'Seq10',true,[<<"a">>,<<"b">>,<<"c">>],97}), roundtrip('SeqEmp', #'SeqEmp'{seq1=[#'Empty'{}]}), diff --git a/lib/asn1/test/testSeqOfExternal.erl b/lib/asn1/test/testSeqOfExternal.erl index 2e60f441c1..38b9f0ce7c 100644 --- a/lib/asn1/test/testSeqOfExternal.erl +++ b/lib/asn1/test/testSeqOfExternal.erl @@ -29,50 +29,59 @@ main(_Rules) -> roundtrip('NTNT', - [#'NT'{os="kalle",bool=true},#'NT'{os="kalle",bool=true}]), + [#'NT'{os = <<"kalle">>,bool=true}, + #'NT'{os = <<"kalle">>,bool=true}]), roundtrip('ImpNT', - [#'NT'{os="kalle",bool=true},#'NT'{os="kalle",bool=true}]), + [#'NT'{os = <<"kalle">>,bool=true}, + #'NT'{os = <<"kalle">>,bool=true}]), roundtrip('ExpNT', - [#'NT'{os="kalle",bool=true},#'NT'{os="kalle",bool=true}]), + [#'NT'{os = <<"kalle">>,bool=true}, + #'NT'{os = <<"kalle">>,bool=true}]), roundtrip('NTImp', - [#'Imp'{os="kalle",bool=true},#'Imp'{os="kalle",bool=true}]), + [#'Imp'{os = <<"kalle">>,bool=true}, + #'Imp'{os = <<"kalle">>,bool=true}]), roundtrip('ImpImp', - [#'Imp'{os="kalle",bool=true},#'Imp'{os="kalle",bool=true}]), + [#'Imp'{os = <<"kalle">>,bool=true}, + #'Imp'{os = <<"kalle">>,bool=true}]), roundtrip('ExpImp', - [#'Imp'{os="kalle",bool=true},#'Imp'{os="kalle",bool=true}]), + [#'Imp'{os = <<"kalle">>,bool=true}, + #'Imp'{os = <<"kalle">>,bool=true}]), roundtrip('NTExp', - [#'Exp'{os="kalle",bool=true},#'Exp'{os="kalle",bool=true}]), + [#'Exp'{os = <<"kalle">>,bool=true}, + #'Exp'{os = <<"kalle">>,bool=true}]), roundtrip('ImpExp', - [#'Exp'{os="kalle",bool=true},#'Exp'{os="kalle",bool=true}]), + [#'Exp'{os = <<"kalle">>,bool=true}, + #'Exp'{os = <<"kalle">>,bool=true}]), roundtrip('ExpExp', - [#'Exp'{os="kalle",bool=true},#'Exp'{os="kalle",bool=true}]), + [#'Exp'{os = <<"kalle">>,bool=true}, + #'Exp'{os = <<"kalle">>,bool=true}]), roundtrip('XNTNT', - [#'XSeqNT'{os="kalle",bool=true}, - #'XSeqNT'{os="kalle",bool=true}]), + [#'XSeqNT'{os = <<"kalle">>,bool=true}, + #'XSeqNT'{os = <<"kalle">>,bool=true}]), roundtrip('XImpNT', - [#'XSeqNT'{os="kalle",bool=true}, - #'XSeqNT'{os="kalle",bool=true}]), + [#'XSeqNT'{os = <<"kalle">>,bool=true}, + #'XSeqNT'{os = <<"kalle">>,bool=true}]), roundtrip('XExpNT', - [#'XSeqNT'{os="kalle",bool=true}, - #'XSeqNT'{os="kalle",bool=true}]), + [#'XSeqNT'{os = <<"kalle">>,bool=true}, + #'XSeqNT'{os = <<"kalle">>,bool=true}]), roundtrip('XNTImp', - [#'XSeqImp'{os="kalle",bool=true}, - #'XSeqImp'{os="kalle",bool=true}]), + [#'XSeqImp'{os = <<"kalle">>,bool=true}, + #'XSeqImp'{os = <<"kalle">>,bool=true}]), roundtrip('XImpImp', - [#'XSeqImp'{os="kalle",bool=true}, - #'XSeqImp'{os="kalle",bool=true}]), + [#'XSeqImp'{os = <<"kalle">>,bool=true}, + #'XSeqImp'{os = <<"kalle">>,bool=true}]), roundtrip('XExpImp', - [#'XSeqImp'{os="kalle",bool=true}, - #'XSeqImp'{os="kalle",bool=true}]), + [#'XSeqImp'{os = <<"kalle">>,bool=true}, + #'XSeqImp'{os = <<"kalle">>,bool=true}]), roundtrip('XNTExp', - [#'XSeqExp'{os="kalle",bool=true}, - #'XSeqExp'{os="kalle",bool=true}]), + [#'XSeqExp'{os = <<"kalle">>,bool=true}, + #'XSeqExp'{os = <<"kalle">>,bool=true}]), roundtrip('XImpExp', - [#'XSeqExp'{os="kalle",bool=true}, - #'XSeqExp'{os="kalle",bool=true}]), + [#'XSeqExp'{os = <<"kalle">>,bool=true}, + #'XSeqExp'{os = <<"kalle">>,bool=true}]), roundtrip('XExpExp', - [#'XSeqExp'{os="kalle",bool=true}, - #'XSeqExp'{os="kalle",bool=true}]), + [#'XSeqExp'{os = <<"kalle">>,bool=true}, + #'XSeqExp'{os = <<"kalle">>,bool=true}]), ok. roundtrip(T, V) -> diff --git a/lib/asn1/test/testSeqOfTag.erl b/lib/asn1/test/testSeqOfTag.erl index 38c1dcb90f..f66e29e91d 100644 --- a/lib/asn1/test/testSeqOfTag.erl +++ b/lib/asn1/test/testSeqOfTag.erl @@ -44,47 +44,47 @@ -record('Exp',{os, bool}). main(_Rules) -> - roundtrip('SeqTagNt', #'SeqTagNt'{nt=[#'NT'{os="kalle",bool=true}, - #'NT'{os="kalle",bool=true}]}), - roundtrip('SeqTagNtI', #'SeqTagNtI'{imp=[#'Imp'{os="kalle",bool=true}, - #'Imp'{os="kalle",bool=true}]}), - roundtrip('SeqTagNtE', #'SeqTagNtE'{exp=[#'Exp'{os="kalle",bool=true}, - #'Exp'{os="kalle",bool=true}]}), - roundtrip('SeqTagI', #'SeqTagI'{nt=[#'NT'{os="kalle",bool=true}, - #'NT'{os="kalle",bool=true}]}), - roundtrip('SeqTagII', #'SeqTagII'{imp=[#'Imp'{os="kalle",bool=true}, - #'Imp'{os="kalle",bool=true}]}), - roundtrip('SeqTagIE', #'SeqTagIE'{exp=[#'Exp'{os="kalle",bool=true}, - #'Exp'{os="kalle",bool=true}]}), - roundtrip('SeqTagE', #'SeqTagE'{nt=[#'NT'{os="kalle",bool=true}, - #'NT'{os="kalle",bool=true}]}), - roundtrip('SeqTagEI', #'SeqTagEI'{imp=[#'Imp'{os="kalle",bool=true}, - #'Imp'{os="kalle",bool=true}]}), - roundtrip('SeqTagEE', #'SeqTagEE'{exp=[#'Exp'{os="kalle",bool=true}, - #'Exp'{os="kalle",bool=true}]}), + roundtrip('SeqTagNt', #'SeqTagNt'{nt=[#'NT'{os = <<"kalle">>,bool=true}, + #'NT'{os = <<"kalle">>,bool=true}]}), + roundtrip('SeqTagNtI', #'SeqTagNtI'{imp=[#'Imp'{os = <<"kalle">>,bool=true}, + #'Imp'{os = <<"kalle">>,bool=true}]}), + roundtrip('SeqTagNtE', #'SeqTagNtE'{exp=[#'Exp'{os = <<"kalle">>,bool=true}, + #'Exp'{os = <<"kalle">>,bool=true}]}), + roundtrip('SeqTagI', #'SeqTagI'{nt=[#'NT'{os = <<"kalle">>,bool=true}, + #'NT'{os = <<"kalle">>,bool=true}]}), + roundtrip('SeqTagII', #'SeqTagII'{imp=[#'Imp'{os = <<"kalle">>,bool=true}, + #'Imp'{os = <<"kalle">>,bool=true}]}), + roundtrip('SeqTagIE', #'SeqTagIE'{exp=[#'Exp'{os = <<"kalle">>,bool=true}, + #'Exp'{os = <<"kalle">>,bool=true}]}), + roundtrip('SeqTagE', #'SeqTagE'{nt=[#'NT'{os = <<"kalle">>,bool=true}, + #'NT'{os = <<"kalle">>,bool=true}]}), + roundtrip('SeqTagEI', #'SeqTagEI'{imp=[#'Imp'{os = <<"kalle">>,bool=true}, + #'Imp'{os = <<"kalle">>,bool=true}]}), + roundtrip('SeqTagEE', #'SeqTagEE'{exp=[#'Exp'{os = <<"kalle">>,bool=true}, + #'Exp'{os = <<"kalle">>,bool=true}]}), roundtrip('SeqTagXNt', - #'SeqTagXNt'{xnt=[#'XSeqNT'{os="kalle",bool=true}, - #'XSeqNT'{os="kalle",bool=true}]}), + #'SeqTagXNt'{xnt=[#'XSeqNT'{os = <<"kalle">>,bool=true}, + #'XSeqNT'{os = <<"kalle">>,bool=true}]}), roundtrip('SeqTagXI', - #'SeqTagXI'{ximp=[#'XSeqImp'{os="kalle",bool=true}, - #'XSeqImp'{os="kalle",bool=true}]}), + #'SeqTagXI'{ximp=[#'XSeqImp'{os = <<"kalle">>,bool=true}, + #'XSeqImp'{os = <<"kalle">>,bool=true}]}), roundtrip('SeqTagXE', - #'SeqTagXE'{xexp=[#'XSeqExp'{os="kalle",bool=true}, - #'XSeqExp'{os="kalle",bool=true}]}), + #'SeqTagXE'{xexp=[#'XSeqExp'{os = <<"kalle">>,bool=true}, + #'XSeqExp'{os = <<"kalle">>,bool=true}]}), roundtrip('SeqTagImpX', - #'SeqTagImpX'{xnt=[#'XSeqNT'{os="kalle",bool=true}, - #'XSeqNT'{os="kalle",bool=true}], - ximp=[#'XSeqImp'{os="kalle",bool=true}, - #'XSeqImp'{os="kalle",bool=true}], - xexp=[#'XSeqExp'{os="kalle",bool=true}, - #'XSeqExp'{os="kalle",bool=true}]}), + #'SeqTagImpX'{xnt=[#'XSeqNT'{os = <<"kalle">>,bool=true}, + #'XSeqNT'{os = <<"kalle">>,bool=true}], + ximp=[#'XSeqImp'{os = <<"kalle">>,bool=true}, + #'XSeqImp'{os = <<"kalle">>,bool=true}], + xexp=[#'XSeqExp'{os = <<"kalle">>,bool=true}, + #'XSeqExp'{os = <<"kalle">>,bool=true}]}), roundtrip('SeqTagExpX', - #'SeqTagExpX'{xnt=[#'XSeqNT'{os="kalle",bool=true}, - #'XSeqNT'{os="kalle",bool=true}], - ximp=[#'XSeqImp'{os="kalle",bool=true}, - #'XSeqImp'{os="kalle",bool=true}], - xexp=[#'XSeqExp'{os="kalle",bool=true}, - #'XSeqExp'{os="kalle",bool=true}]}), + #'SeqTagExpX'{xnt=[#'XSeqNT'{os = <<"kalle">>,bool=true}, + #'XSeqNT'{os = <<"kalle">>,bool=true}], + ximp=[#'XSeqImp'{os = <<"kalle">>,bool=true}, + #'XSeqImp'{os = <<"kalle">>,bool=true}], + xexp=[#'XSeqExp'{os = <<"kalle">>,bool=true}, + #'XSeqExp'{os = <<"kalle">>,bool=true}]}), ok. roundtrip(T, V) -> diff --git a/lib/asn1/test/testSeqPrim.erl b/lib/asn1/test/testSeqPrim.erl index eb21d50a37..7f3ef86ac5 100644 --- a/lib/asn1/test/testSeqPrim.erl +++ b/lib/asn1/test/testSeqPrim.erl @@ -25,6 +25,7 @@ -record('Seq',{bool, boolCon, boolPri, boolApp, boolExpCon, boolExpPri, boolExpApp}). -record('Empty',{}). +-record('Big', {os1,os2,os3}). main(_Rules) -> roundtrip('Seq', #'Seq'{bool=true,boolCon=true,boolPri=true,boolApp=true, @@ -35,6 +36,9 @@ main(_Rules) -> roundtrip('Seq', #'Seq'{bool=false,boolCon=true,boolPri=false,boolApp=true, boolExpCon=false,boolExpPri=true,boolExpApp=false}), roundtrip('Empty', #'Empty'{}), + roundtrip('Big', #'Big'{os1=list_to_binary(lists:duplicate(120, 16#A5)), + os2=list_to_binary(lists:duplicate(128, 16#A7)), + os3=list_to_binary(lists:duplicate(17777, 16#F5))}), ok. roundtrip(Type, Value) -> diff --git a/lib/asn1/test/testSeqSetDefaultVal.erl b/lib/asn1/test/testSeqSetDefaultVal.erl index 044099199f..79992a0a94 100644 --- a/lib/asn1/test/testSeqSetDefaultVal.erl +++ b/lib/asn1/test/testSeqSetDefaultVal.erl @@ -162,7 +162,7 @@ main(Rule, Opts) -> {#'SeqOS'{}, [{#'SeqOS'.a, [asn1_DEFAULT, - [172]]}]}, + <<172>>]}]}, {#'SeqOI'{}, [{#'SeqOI'.a, @@ -314,17 +314,10 @@ der() -> c=[second], d = <<>>}), roundtrip(<<48,0>>, 'SeqOS', - #'SeqOS'{a=[172],b=[16#A8,16#A0],c='NULL'}), - roundtrip(<<48,0>>, - 'SeqOS', - #'SeqOS'{a=172,b=43168,c='NULL'}, - #'SeqOS'{a=[172],b=[16#A8,16#A0],c='NULL'}), + #'SeqOS'{a = <<172>>,b = <<16#A8,16#A0>>,c='NULL'}), - roundtrip(<<49,0>>, 'SetOS', #'SetOS'{a=[172],b=[16#A8,16#A0],c='NULL'}), - roundtrip(<<49,0>>, - 'SetOS', - #'SetOS'{a=172,b=43168,c='NULL'}, - #'SetOS'{a=[172],b=[16#A8,16#A0],c='NULL'}), + roundtrip(<<49,0>>, 'SetOS', + #'SetOS'{a = <<172>>,b = <<16#A8,16#A0>>,c='NULL'}), roundtrip(<<48,0>>, 'SeqOI', diff --git a/lib/asn1/test/testSeqTag.erl b/lib/asn1/test/testSeqTag.erl index 2f127b3e97..6bacca6808 100644 --- a/lib/asn1/test/testSeqTag.erl +++ b/lib/asn1/test/testSeqTag.erl @@ -35,24 +35,24 @@ -record('Exp',{os, bool}). main(_Rules) -> - roundtrip('SeqTag', #'SeqTag'{nt=#'NT'{os="kalle",bool=true}, - imp=#'Imp'{os="kalle",bool=true}, - exp=#'Exp'{os="kalle",bool=true}}), - roundtrip('SeqTagImp', #'SeqTagImp'{nt=#'NT'{os="kalle",bool=true}, - imp=#'Imp'{os="kalle",bool=true}, - exp=#'Exp'{os="kalle",bool=true}}), - roundtrip('SeqTagExp', #'SeqTagExp'{nt=#'NT'{os="kalle",bool=true}, - imp=#'Imp'{os="kalle",bool=true}, - exp=#'Exp'{os="kalle",bool=true}}), - roundtrip('SeqTagX', #'SeqTagX'{xnt=#'XSeqNT'{os="kalle",bool=true}, - ximp=#'XSeqImp'{os="kalle",bool=true}, - xexp=#'XSeqExp'{os="kalle",bool=true}}), - roundtrip('SeqTagImpX', #'SeqTagImpX'{xnt=#'XSeqNT'{os="kalle",bool=true}, - ximp=#'XSeqImp'{os="kalle",bool=true}, - xexp=#'XSeqExp'{os="kalle",bool=true}}), - roundtrip('SeqTagExpX', #'SeqTagExpX'{xnt=#'XSeqNT'{os="kalle",bool=true}, - ximp=#'XSeqImp'{os="kalle",bool=true}, - xexp=#'XSeqExp'{os="kalle",bool=true}}), + roundtrip('SeqTag', #'SeqTag'{nt=#'NT'{os = <<"kalle">>,bool=true}, + imp=#'Imp'{os = <<"kalle">>,bool=true}, + exp=#'Exp'{os = <<"kalle">>,bool=true}}), + roundtrip('SeqTagImp', #'SeqTagImp'{nt=#'NT'{os = <<"kalle">>,bool=true}, + imp=#'Imp'{os = <<"kalle">>,bool=true}, + exp=#'Exp'{os = <<"kalle">>,bool=true}}), + roundtrip('SeqTagExp', #'SeqTagExp'{nt=#'NT'{os = <<"kalle">>,bool=true}, + imp=#'Imp'{os = <<"kalle">>,bool=true}, + exp=#'Exp'{os = <<"kalle">>,bool=true}}), + roundtrip('SeqTagX', #'SeqTagX'{xnt=#'XSeqNT'{os = <<"kalle">>,bool=true}, + ximp=#'XSeqImp'{os = <<"kalle">>,bool=true}, + xexp=#'XSeqExp'{os = <<"kalle">>,bool=true}}), + roundtrip('SeqTagImpX', #'SeqTagImpX'{xnt=#'XSeqNT'{os = <<"kalle">>,bool=true}, + ximp=#'XSeqImp'{os = <<"kalle">>,bool=true}, + xexp=#'XSeqExp'{os = <<"kalle">>,bool=true}}), + roundtrip('SeqTagExpX', #'SeqTagExpX'{xnt=#'XSeqNT'{os = <<"kalle">>,bool=true}, + ximp=#'XSeqImp'{os = <<"kalle">>,bool=true}, + xexp=#'XSeqExp'{os = <<"kalle">>,bool=true}}), ok. roundtrip(T, V) -> diff --git a/lib/asn1/test/testSeqTypeRefCho.erl b/lib/asn1/test/testSeqTypeRefCho.erl index b008bc46b8..1a921c6f38 100644 --- a/lib/asn1/test/testSeqTypeRefCho.erl +++ b/lib/asn1/test/testSeqTypeRefCho.erl @@ -28,10 +28,10 @@ main(_Rules) -> roundtrip('SeqTRcho', - #'SeqTRcho'{'seqCho' = {choOs,"A string 1"}, - 'seqChoE' = {choOs,"A string 3"}, - 'seqCho-E' = {choOs,"A string 7"}, - 'seqChoE-E' = {choOs,"A string 9"}}), + #'SeqTRcho'{'seqCho' = {choOs,<<"A string 1">>}, + 'seqChoE' = {choOs,<<"A string 3">>}, + 'seqCho-E' = {choOs,<<"A string 7">>}, + 'seqChoE-E' = {choOs,<<"A string 9">>}}), ok. roundtrip(T, V) -> diff --git a/lib/asn1/test/testSeqTypeRefPrim.erl b/lib/asn1/test/testSeqTypeRefPrim.erl index b63882ae99..d66d1ebcfe 100644 --- a/lib/asn1/test/testSeqTypeRefPrim.erl +++ b/lib/asn1/test/testSeqTypeRefPrim.erl @@ -26,15 +26,15 @@ main(_Rules) -> roundtrip('SeqTR', - #'SeqTR'{'octStr' = "A string 1", - 'octStrI' = "A string 2", - 'octStrE' = "A string 3", - 'octStr-I' = "A string 4", - 'octStrI-I' = "A string 5", - 'octStrE-I' = "A string 6", - 'octStr-E' = "A string 7", - 'octStrI-E' = "A string 8", - 'octStrE-E' = "A string 9"}), + #'SeqTR'{'octStr' = <<"A string 1">>, + 'octStrI' = <<"A string 2">>, + 'octStrE' = <<"A string 3">>, + 'octStr-I' = <<"A string 4">>, + 'octStrI-I' = <<"A string 5">>, + 'octStrE-I' = <<"A string 6">>, + 'octStr-E' = <<"A string 7">>, + 'octStrI-E' = <<"A string 8">>, + 'octStrE-E' = <<"A string 9">>}), ok. roundtrip(T, V) -> diff --git a/lib/asn1/test/testSeqTypeRefSeq.erl b/lib/asn1/test/testSeqTypeRefSeq.erl index fc2e0a67c9..3288511f0a 100644 --- a/lib/asn1/test/testSeqTypeRefSeq.erl +++ b/lib/asn1/test/testSeqTypeRefSeq.erl @@ -71,15 +71,15 @@ main(_Rules) -> seqS2=#'SeqSTag_seqS2'{b2=true,i2=22}, seqS3=#'SeqSTag_seqS3'{b3=true,i3=33}}), roundtrip('SeqTRseq', - #'SeqTRseq'{seqSeq=#'SeqSeq'{seqInt=2,seqOs="A1"}, - seqSeqI=#'SeqSeq'{seqInt=2,seqOs="A2"}, - seqSeqE=#'SeqSeq'{seqInt=2,seqOs="A3"}, - 'seqSeq-I'=#'SeqSeqImp'{seqInt=2,seqOs="A4"}, - 'seqSeqI-I'=#'SeqSeqImp'{seqInt=2,seqOs="A5"}, - 'seqSeqE-I'=#'SeqSeqImp'{seqInt=2,seqOs="A6"}, - 'seqSeq-E'=#'SeqSeqExp'{seqInt=2,seqOs="A7"}, - 'seqSeqI-E'=#'SeqSeqExp'{seqInt=2,seqOs="A8"}, - 'seqSeqE-E'=#'SeqSeqExp'{seqInt=2,seqOs="A9"}}), + #'SeqTRseq'{seqSeq=#'SeqSeq'{seqInt=2,seqOs = <<"A1">>}, + seqSeqI=#'SeqSeq'{seqInt=2,seqOs = <<"A2">>}, + seqSeqE=#'SeqSeq'{seqInt=2,seqOs = <<"A3">>}, + 'seqSeq-I'=#'SeqSeqImp'{seqInt=2,seqOs = <<"A4">>}, + 'seqSeqI-I'=#'SeqSeqImp'{seqInt=2,seqOs = <<"A5">>}, + 'seqSeqE-I'=#'SeqSeqImp'{seqInt=2,seqOs = <<"A6">>}, + 'seqSeq-E'=#'SeqSeqExp'{seqInt=2,seqOs = <<"A7">>}, + 'seqSeqI-E'=#'SeqSeqExp'{seqInt=2,seqOs = <<"A8">>}, + 'seqSeqE-E'=#'SeqSeqExp'{seqInt=2,seqOs = <<"A9">>}}), ok. roundtrip(T, V) -> diff --git a/lib/asn1/test/testSeqTypeRefSet.erl b/lib/asn1/test/testSeqTypeRefSet.erl index 911a4b7a47..d73423284b 100644 --- a/lib/asn1/test/testSeqTypeRefSet.erl +++ b/lib/asn1/test/testSeqTypeRefSet.erl @@ -32,15 +32,15 @@ main(_Rules) -> roundtrip('SeqTRset', - #'SeqTRset'{seqSet=#'SeqSet'{setInt=2,setOs="A1"}, - seqSetI=#'SeqSet'{setInt=2,setOs="A2"}, - seqSetE=#'SeqSet'{setInt=2,setOs="A3"}, - 'seqSet-I'=#'SeqSetImp'{setInt=2,setOs="A4"}, - 'seqSetI-I'=#'SeqSetImp'{setInt=2,setOs="A5"}, - 'seqSetE-I'=#'SeqSetImp'{setInt=2,setOs="A6"}, - 'seqSet-E'=#'SeqSetExp'{setInt=2,setOs="A7"}, - 'seqSetI-E'=#'SeqSetExp'{setInt=2,setOs="A8"}, - 'seqSetE-E'=#'SeqSetExp'{setInt=2,setOs="A9"}}), + #'SeqTRset'{seqSet=#'SeqSet'{setInt=2,setOs = <<"A1">>}, + seqSetI=#'SeqSet'{setInt=2,setOs = <<"A2">>}, + seqSetE=#'SeqSet'{setInt=2,setOs = <<"A3">>}, + 'seqSet-I'=#'SeqSetImp'{setInt=2,setOs = <<"A4">>}, + 'seqSetI-I'=#'SeqSetImp'{setInt=2,setOs = <<"A5">>}, + 'seqSetE-I'=#'SeqSetImp'{setInt=2,setOs = <<"A6">>}, + 'seqSet-E'=#'SeqSetExp'{setInt=2,setOs = <<"A7">>}, + 'seqSetI-E'=#'SeqSetExp'{setInt=2,setOs = <<"A8">>}, + 'seqSetE-E'=#'SeqSetExp'{setInt=2,setOs = <<"A9">>}}), ok. roundtrip(T, V) -> diff --git a/lib/asn1/test/testSetExternal.erl b/lib/asn1/test/testSetExternal.erl index e17d7053aa..626adc5822 100644 --- a/lib/asn1/test/testSetExternal.erl +++ b/lib/asn1/test/testSetExternal.erl @@ -28,15 +28,15 @@ -record('SetXSeq3',{bool, int, seq}). main(_Rules) -> - roundtrip('XNTNT', #'XSetNT'{os="kalle",bool=true}), - roundtrip('XImpNT', #'XSetNT'{os="kalle",bool=true}), - roundtrip('XExpNT', #'XSetNT'{os="kalle",bool=true}), - roundtrip('XNTImp', #'XSetImp'{os="kalle",bool=true}), - roundtrip('XImpImp', #'XSetImp'{os="kalle",bool=true}), - roundtrip('XExpImp', #'XSetImp'{os="kalle",bool=true}), - roundtrip('XNTExp', #'XSetExp'{os="kalle",bool=true}), - roundtrip('XImpExp', #'XSetExp'{os="kalle",bool=true}), - roundtrip('XExpExp', #'XSetExp'{os="kalle",bool=true}), + roundtrip('XNTNT', #'XSetNT'{os = <<"kalle">>,bool=true}), + roundtrip('XImpNT', #'XSetNT'{os = <<"kalle">>,bool=true}), + roundtrip('XExpNT', #'XSetNT'{os = <<"kalle">>,bool=true}), + roundtrip('XNTImp', #'XSetImp'{os = <<"kalle">>,bool=true}), + roundtrip('XImpImp', #'XSetImp'{os = <<"kalle">>,bool=true}), + roundtrip('XExpImp', #'XSetImp'{os = <<"kalle">>,bool=true}), + roundtrip('XNTExp', #'XSetExp'{os = <<"kalle">>,bool=true}), + roundtrip('XImpExp', #'XSetExp'{os = <<"kalle">>,bool=true}), + roundtrip('XExpExp', #'XSetExp'{os = <<"kalle">>,bool=true}), roundtrip('SetXSeq1', #'SetXSeq1'{seq=#'XSeq1'{bool1=true,int1=77, seq1=#'XSeqIn'{boolIn=false,intIn=88}}, bool=true,int=66}), diff --git a/lib/asn1/test/testSetOf.erl b/lib/asn1/test/testSetOf.erl index 54c42c1f21..0f82a14625 100644 --- a/lib/asn1/test/testSetOf.erl +++ b/lib/asn1/test/testSetOf.erl @@ -121,9 +121,9 @@ main(_Rules) -> #'SetIn'{boolIn=false,intIn=125}, #'SetIn'{boolIn=false,intIn=225}]}), - roundtrip('SetOs', ["First","Second","Third"]), - roundtrip('SetOsImp', ["First","Second","Third"]), - roundtrip('SetOsExp', ["First","Second","Third"]), + roundtrip('SetOs', [<<"First">>,<<"Second">>,<<"Third">>]), + roundtrip('SetOsImp', [<<"First">>,<<"Second">>,<<"Third">>]), + roundtrip('SetOsExp', [<<"First">>,<<"Second">>,<<"Third">>]), roundtrip('SetEmp', #'SetEmp'{set1=[#'Empty'{}]}), ok. diff --git a/lib/asn1/test/testSetOfExternal.erl b/lib/asn1/test/testSetOfExternal.erl index a380ba5ac1..cc5fe10710 100644 --- a/lib/asn1/test/testSetOfExternal.erl +++ b/lib/asn1/test/testSetOfExternal.erl @@ -28,24 +28,42 @@ -record('Exp',{os, bool}). main(_Rules) -> - roundtrip('NTNT', [#'NT'{os="kalle",bool=true},#'NT'{os="kalle",bool=true}]), - roundtrip('ImpNT', [#'NT'{os="kalle",bool=true},#'NT'{os="kalle",bool=true}]), - roundtrip('ExpNT', [#'NT'{os="kalle",bool=true},#'NT'{os="kalle",bool=true}]), - roundtrip('NTImp', [#'Imp'{os="kalle",bool=true},#'Imp'{os="kalle",bool=true}]), - roundtrip('ImpImp', [#'Imp'{os="kalle",bool=true},#'Imp'{os="kalle",bool=true}]), - roundtrip('ExpImp', [#'Imp'{os="kalle",bool=true},#'Imp'{os="kalle",bool=true}]), - roundtrip('NTExp', [#'Exp'{os="kalle",bool=true},#'Exp'{os="kalle",bool=true}]), - roundtrip('ImpExp', [#'Exp'{os="kalle",bool=true},#'Exp'{os="kalle",bool=true}]), - roundtrip('ExpExp', [#'Exp'{os="kalle",bool=true},#'Exp'{os="kalle",bool=true}]), - roundtrip('XNTNT', [#'XSetNT'{os="kalle",bool=true},#'XSetNT'{os="kalle",bool=true}]), - roundtrip('XImpNT', [#'XSetNT'{os="kalle",bool=true},#'XSetNT'{os="kalle",bool=true}]), - roundtrip('XExpNT', [#'XSetNT'{os="kalle",bool=true},#'XSetNT'{os="kalle",bool=true}]), - roundtrip('XNTImp', [#'XSetImp'{os="kalle",bool=true},#'XSetImp'{os="kalle",bool=true}]), - roundtrip('XImpImp', [#'XSetImp'{os="kalle",bool=true},#'XSetImp'{os="kalle",bool=true}]), - roundtrip('XExpImp', [#'XSetImp'{os="kalle",bool=true},#'XSetImp'{os="kalle",bool=true}]), - roundtrip('XNTExp', [#'XSetExp'{os="kalle",bool=true},#'XSetExp'{os="kalle",bool=true}]), - roundtrip('XImpExp', [#'XSetExp'{os="kalle",bool=true},#'XSetExp'{os="kalle",bool=true}]), - roundtrip('XExpExp', [#'XSetExp'{os="kalle",bool=true},#'XSetExp'{os="kalle",bool=true}]), + roundtrip('NTNT', [#'NT'{os = <<"kalle">>,bool=true}, + #'NT'{os = <<"kalle">>,bool=true}]), + roundtrip('ImpNT', [#'NT'{os = <<"kalle">>,bool=true}, + #'NT'{os = <<"kalle">>,bool=true}]), + roundtrip('ExpNT', [#'NT'{os = <<"kalle">>,bool=true}, + #'NT'{os = <<"kalle">>,bool=true}]), + roundtrip('NTImp', [#'Imp'{os = <<"kalle">>,bool=true}, + #'Imp'{os = <<"kalle">>,bool=true}]), + roundtrip('ImpImp', [#'Imp'{os = <<"kalle">>,bool=true}, + #'Imp'{os = <<"kalle">>,bool=true}]), + roundtrip('ExpImp', [#'Imp'{os = <<"kalle">>,bool=true}, + #'Imp'{os = <<"kalle">>,bool=true}]), + roundtrip('NTExp', [#'Exp'{os = <<"kalle">>,bool=true}, + #'Exp'{os = <<"kalle">>,bool=true}]), + roundtrip('ImpExp', [#'Exp'{os = <<"kalle">>,bool=true}, + #'Exp'{os = <<"kalle">>,bool=true}]), + roundtrip('ExpExp', [#'Exp'{os = <<"kalle">>,bool=true}, + #'Exp'{os = <<"kalle">>,bool=true}]), + roundtrip('XNTNT', [#'XSetNT'{os = <<"kalle">>,bool=true}, + #'XSetNT'{os = <<"kalle">>,bool=true}]), + roundtrip('XImpNT', [#'XSetNT'{os = <<"kalle">>,bool=true}, + #'XSetNT'{os = <<"kalle">>,bool=true}]), + roundtrip('XExpNT', [#'XSetNT'{os = <<"kalle">>,bool=true}, + #'XSetNT'{os = <<"kalle">>,bool=true}]), + roundtrip('XNTImp', [#'XSetImp'{os = <<"kalle">>,bool=true}, + #'XSetImp'{os = <<"kalle">>,bool=true}]), + roundtrip('XImpImp', [#'XSetImp'{os = <<"kalle">>,bool=true}, + #'XSetImp'{os = <<"kalle">>,bool=true}]), + roundtrip('XExpImp', [#'XSetImp'{os = <<"kalle">>,bool=true}, + #'XSetImp'{os = <<"kalle">>,bool=true}]), + roundtrip('XNTExp', [#'XSetExp'{os = <<"kalle">>,bool=true}, + #'XSetExp'{os = <<"kalle">>,bool=true}]), + roundtrip('XImpExp', [#'XSetExp'{os = <<"kalle">>,bool=true}, + #'XSetExp'{os = <<"kalle">>,bool=true}]), + roundtrip('XExpExp', [#'XSetExp'{os = <<"kalle">>,bool=true}, + #'XSetExp'{os = <<"kalle">>,bool=true}]), ok. roundtrip(T, V) -> diff --git a/lib/asn1/test/testSetOfTag.erl b/lib/asn1/test/testSetOfTag.erl index 81bc467abb..0d656f05a6 100644 --- a/lib/asn1/test/testSetOfTag.erl +++ b/lib/asn1/test/testSetOfTag.erl @@ -42,42 +42,42 @@ -record('Exp',{os, bool}). main(_Rules) -> - roundtrip('SetTagNt', #'SetTagNt'{nt=[#'NT'{os="kalle",bool=true}, - #'NT'{os="kalle",bool=true}]}), - roundtrip('SetTagNtI', #'SetTagNtI'{imp=[#'Imp'{os="kalle",bool=true}, - #'Imp'{os="kalle",bool=true}]}), - roundtrip('SetTagNtE', #'SetTagNtE'{exp=[#'Exp'{os="kalle",bool=true}, - #'Exp'{os="kalle",bool=true}]}), - roundtrip('SetTagI', #'SetTagI'{nt=[#'NT'{os="kalle",bool=true}, - #'NT'{os="kalle",bool=true}]}), - roundtrip('SetTagII', #'SetTagII'{imp=[#'Imp'{os="kalle",bool=true}, - #'Imp'{os="kalle",bool=true}]}), - roundtrip('SetTagIE', #'SetTagIE'{exp=[#'Exp'{os="kalle",bool=true}, - #'Exp'{os="kalle",bool=true}]}), - roundtrip('SetTagE', #'SetTagE'{nt=[#'NT'{os="kalle",bool=true}, - #'NT'{os="kalle",bool=true}]}), - roundtrip('SetTagEI', #'SetTagEI'{imp=[#'Imp'{os="kalle",bool=true}, - #'Imp'{os="kalle",bool=true}]}), - roundtrip('SetTagEE', #'SetTagEE'{exp=[#'Exp'{os="kalle",bool=true}, - #'Exp'{os="kalle",bool=true}]}), - roundtrip('SetTagXNt', #'SetTagXNt'{xnt=[#'XSetNT'{os="kalle",bool=true}, - #'XSetNT'{os="kalle",bool=true}]}), - roundtrip('SetTagXI', #'SetTagXI'{ximp=[#'XSetImp'{os="kalle",bool=true}, - #'XSetImp'{os="kalle",bool=true}]}), - roundtrip('SetTagXE', #'SetTagXE'{xexp=[#'XSetExp'{os="kalle",bool=true}, - #'XSetExp'{os="kalle",bool=true}]}), - roundtrip('SetTagImpX', #'SetTagImpX'{xnt=[#'XSetNT'{os="kalle",bool=true}, - #'XSetNT'{os="kalle",bool=true}], - ximp=[#'XSetImp'{os="kalle",bool=true}, - #'XSetImp'{os="kalle",bool=true}], - xexp=[#'XSetExp'{os="kalle",bool=true}, - #'XSetExp'{os="kalle",bool=true}]}), - roundtrip('SetTagExpX', #'SetTagExpX'{xnt=[#'XSetNT'{os="kalle",bool=true}, - #'XSetNT'{os="kalle",bool=true}], - ximp=[#'XSetImp'{os="kalle",bool=true}, - #'XSetImp'{os="kalle",bool=true}], - xexp=[#'XSetExp'{os="kalle",bool=true}, - #'XSetExp'{os="kalle",bool=true}]}), + roundtrip('SetTagNt', #'SetTagNt'{nt=[#'NT'{os = <<"kalle">>,bool=true}, + #'NT'{os = <<"kalle">>,bool=true}]}), + roundtrip('SetTagNtI', #'SetTagNtI'{imp=[#'Imp'{os = <<"kalle">>,bool=true}, + #'Imp'{os = <<"kalle">>,bool=true}]}), + roundtrip('SetTagNtE', #'SetTagNtE'{exp=[#'Exp'{os = <<"kalle">>,bool=true}, + #'Exp'{os = <<"kalle">>,bool=true}]}), + roundtrip('SetTagI', #'SetTagI'{nt=[#'NT'{os = <<"kalle">>,bool=true}, + #'NT'{os = <<"kalle">>,bool=true}]}), + roundtrip('SetTagII', #'SetTagII'{imp=[#'Imp'{os = <<"kalle">>,bool=true}, + #'Imp'{os = <<"kalle">>,bool=true}]}), + roundtrip('SetTagIE', #'SetTagIE'{exp=[#'Exp'{os = <<"kalle">>,bool=true}, + #'Exp'{os = <<"kalle">>,bool=true}]}), + roundtrip('SetTagE', #'SetTagE'{nt=[#'NT'{os = <<"kalle">>,bool=true}, + #'NT'{os = <<"kalle">>,bool=true}]}), + roundtrip('SetTagEI', #'SetTagEI'{imp=[#'Imp'{os = <<"kalle">>,bool=true}, + #'Imp'{os = <<"kalle">>,bool=true}]}), + roundtrip('SetTagEE', #'SetTagEE'{exp=[#'Exp'{os = <<"kalle">>,bool=true}, + #'Exp'{os = <<"kalle">>,bool=true}]}), + roundtrip('SetTagXNt', #'SetTagXNt'{xnt=[#'XSetNT'{os = <<"kalle">>,bool=true}, + #'XSetNT'{os = <<"kalle">>,bool=true}]}), + roundtrip('SetTagXI', #'SetTagXI'{ximp=[#'XSetImp'{os = <<"kalle">>,bool=true}, + #'XSetImp'{os = <<"kalle">>,bool=true}]}), + roundtrip('SetTagXE', #'SetTagXE'{xexp=[#'XSetExp'{os = <<"kalle">>,bool=true}, + #'XSetExp'{os = <<"kalle">>,bool=true}]}), + roundtrip('SetTagImpX', #'SetTagImpX'{xnt=[#'XSetNT'{os = <<"kalle">>,bool=true}, + #'XSetNT'{os = <<"kalle">>,bool=true}], + ximp=[#'XSetImp'{os = <<"kalle">>,bool=true}, + #'XSetImp'{os = <<"kalle">>,bool=true}], + xexp=[#'XSetExp'{os = <<"kalle">>,bool=true}, + #'XSetExp'{os = <<"kalle">>,bool=true}]}), + roundtrip('SetTagExpX', #'SetTagExpX'{xnt=[#'XSetNT'{os = <<"kalle">>,bool=true}, + #'XSetNT'{os = <<"kalle">>,bool=true}], + ximp=[#'XSetImp'{os = <<"kalle">>,bool=true}, + #'XSetImp'{os = <<"kalle">>,bool=true}], + xexp=[#'XSetExp'{os = <<"kalle">>,bool=true}, + #'XSetExp'{os = <<"kalle">>,bool=true}]}), ok. roundtrip(T, V) -> diff --git a/lib/asn1/test/testSetTag.erl b/lib/asn1/test/testSetTag.erl index 5863a149b9..fa1d84f50d 100644 --- a/lib/asn1/test/testSetTag.erl +++ b/lib/asn1/test/testSetTag.erl @@ -34,24 +34,24 @@ -record('Exp',{os, bool}). main(_Rules) -> - roundtrip('SetTag', #'SetTag'{nt=#'NT'{os="kalle",bool=true}, - imp=#'Imp'{os="kalle",bool=true}, - exp=#'Exp'{os="kalle",bool=true}}), - roundtrip('SetTagImp', #'SetTagImp'{nt=#'NT'{os="kalle",bool=true}, - imp=#'Imp'{os="kalle",bool=true}, - exp=#'Exp'{os="kalle",bool=true}}), - roundtrip('SetTagExp', #'SetTagExp'{nt=#'NT'{os="kalle",bool=true}, - imp=#'Imp'{os="kalle",bool=true}, - exp=#'Exp'{os="kalle",bool=true}}), - roundtrip('SetTagX', #'SetTagX'{xnt=#'XSetNT'{os="kalle",bool=true}, - ximp=#'XSetImp'{os="kalle",bool=true}, - xexp=#'XSetExp'{os="kalle",bool=true}}), - roundtrip('SetTagImpX', #'SetTagImpX'{xnt=#'XSetNT'{os="kalle",bool=true}, - ximp=#'XSetImp'{os="kalle",bool=true}, - xexp=#'XSetExp'{os="kalle",bool=true}}), - roundtrip('SetTagExpX', #'SetTagExpX'{xnt=#'XSetNT'{os="kalle",bool=true}, - ximp=#'XSetImp'{os="kalle",bool=true}, - xexp=#'XSetExp'{os="kalle",bool=true}}), + roundtrip('SetTag', #'SetTag'{nt=#'NT'{os = <<"kalle">>,bool=true}, + imp=#'Imp'{os = <<"kalle">>,bool=true}, + exp=#'Exp'{os = <<"kalle">>,bool=true}}), + roundtrip('SetTagImp', #'SetTagImp'{nt=#'NT'{os = <<"kalle">>,bool=true}, + imp=#'Imp'{os = <<"kalle">>,bool=true}, + exp=#'Exp'{os = <<"kalle">>,bool=true}}), + roundtrip('SetTagExp', #'SetTagExp'{nt=#'NT'{os = <<"kalle">>,bool=true}, + imp=#'Imp'{os = <<"kalle">>,bool=true}, + exp=#'Exp'{os = <<"kalle">>,bool=true}}), + roundtrip('SetTagX', #'SetTagX'{xnt=#'XSetNT'{os = <<"kalle">>,bool=true}, + ximp=#'XSetImp'{os = <<"kalle">>,bool=true}, + xexp=#'XSetExp'{os = <<"kalle">>,bool=true}}), + roundtrip('SetTagImpX', #'SetTagImpX'{xnt=#'XSetNT'{os = <<"kalle">>,bool=true}, + ximp=#'XSetImp'{os = <<"kalle">>,bool=true}, + xexp=#'XSetExp'{os = <<"kalle">>,bool=true}}), + roundtrip('SetTagExpX', #'SetTagExpX'{xnt=#'XSetNT'{os = <<"kalle">>,bool=true}, + ximp=#'XSetImp'{os = <<"kalle">>,bool=true}, + xexp=#'XSetExp'{os = <<"kalle">>,bool=true}}), ok. roundtrip(T, V) -> diff --git a/lib/asn1/test/testSetTypeRefCho.erl b/lib/asn1/test/testSetTypeRefCho.erl index 8d62f45bfa..97bbd557e0 100644 --- a/lib/asn1/test/testSetTypeRefCho.erl +++ b/lib/asn1/test/testSetTypeRefCho.erl @@ -29,10 +29,10 @@ main(_Rules) -> roundtrip('SetTRcho', - #'SetTRcho'{'setCho' = {choOs,"A string 1"}, - 'setChoE' = {choOs,"A string 3"}, - 'setCho-E' = {choOs,"A string 7"}, - 'setChoE-E' = {choOs,"A string 9"}}), + #'SetTRcho'{'setCho' = {choOs,<<"A string 1">>}, + 'setChoE' = {choOs,<<"A string 3">>}, + 'setCho-E' = {choOs,<<"A string 7">>}, + 'setChoE-E' = {choOs,<<"A string 9">>}}), ok. roundtrip(T, V) -> diff --git a/lib/asn1/test/testSetTypeRefPrim.erl b/lib/asn1/test/testSetTypeRefPrim.erl index cc2e157e68..d441fb789d 100644 --- a/lib/asn1/test/testSetTypeRefPrim.erl +++ b/lib/asn1/test/testSetTypeRefPrim.erl @@ -28,15 +28,15 @@ main(_Rules) -> roundtrip('SetTR', - #'SetTR'{'octStr' = "A string 1", - 'octStrI' = "A string 2", - 'octStrE' = "A string 3", - 'octStr-I' = "A string 4", - 'octStrI-I' = "A string 5", - 'octStrE-I' = "A string 6", - 'octStr-E' = "A string 7", - 'octStrI-E' = "A string 8", - 'octStrE-E' = "A string 9"}), + #'SetTR'{'octStr' = <<"A string 1">>, + 'octStrI' = <<"A string 2">>, + 'octStrE' = <<"A string 3">>, + 'octStr-I' = <<"A string 4">>, + 'octStrI-I' = <<"A string 5">>, + 'octStrE-I' = <<"A string 6">>, + 'octStr-E' = <<"A string 7">>, + 'octStrI-E' = <<"A string 8">>, + 'octStrE-E' = <<"A string 9">>}), ok. roundtrip(T, V) -> diff --git a/lib/asn1/test/testSetTypeRefSeq.erl b/lib/asn1/test/testSetTypeRefSeq.erl index 17af5c2922..a2b5f5745e 100644 --- a/lib/asn1/test/testSetTypeRefSeq.erl +++ b/lib/asn1/test/testSetTypeRefSeq.erl @@ -30,23 +30,23 @@ main(_Rules) -> roundtrip('SetTRseq', - #'SetTRseq'{'setSeq' = #'SetSeq'{seqOs = "A1", + #'SetTRseq'{'setSeq' = #'SetSeq'{seqOs = <<"A1">>, seqInt = 2}, - 'setSeqI' = #'SetSeq'{seqOs = "A2", + 'setSeqI' = #'SetSeq'{seqOs = <<"A2">>, seqInt = 2}, - 'setSeqE' = #'SetSeq'{seqOs = "A3", + 'setSeqE' = #'SetSeq'{seqOs = <<"A3">>, seqInt = 2}, - 'setSeq-I' = #'SetSeqImp'{seqOs = "A4", + 'setSeq-I' = #'SetSeqImp'{seqOs = <<"A4">>, seqInt = 2}, - 'setSeqI-I' = #'SetSeqImp'{seqOs = "A5", + 'setSeqI-I' = #'SetSeqImp'{seqOs = <<"A5">>, seqInt = 2}, - 'setSeqE-I' = #'SetSeqImp'{seqOs = "A6", + 'setSeqE-I' = #'SetSeqImp'{seqOs = <<"A6">>, seqInt = 2}, - 'setSeq-E' = #'SetSeqExp'{seqOs = "A7", + 'setSeq-E' = #'SetSeqExp'{seqOs = <<"A7">>, seqInt = 2}, - 'setSeqI-E' = #'SetSeqExp'{seqOs = "A8", + 'setSeqI-E' = #'SetSeqExp'{seqOs = <<"A8">>, seqInt = 2}, - 'setSeqE-E' = #'SetSeqExp'{seqOs = "A9", + 'setSeqE-E' = #'SetSeqExp'{seqOs = <<"A9">>, seqInt = 2}}), ok. diff --git a/lib/asn1/test/testSetTypeRefSet.erl b/lib/asn1/test/testSetTypeRefSet.erl index 8786e0fb4d..80a6be58c9 100644 --- a/lib/asn1/test/testSetTypeRefSet.erl +++ b/lib/asn1/test/testSetTypeRefSet.erl @@ -71,15 +71,15 @@ main(_Rules) -> setS2=#'SetSTag_setS2'{b2=true,i2=22}, setS3=#'SetSTag_setS3'{b3=true,i3=33}}), roundtrip('SetTRset', - #'SetTRset'{setSet=#'SetSet'{setInt=2,setOs="A1"}, - setSetI=#'SetSet'{setInt=2,setOs="A2"}, - setSetE=#'SetSet'{setInt=2,setOs="A3"}, - 'setSet-I'=#'SetSetImp'{setInt=2,setOs="A4"}, - 'setSetI-I'=#'SetSetImp'{setInt=2,setOs="A5"}, - 'setSetE-I'=#'SetSetImp'{setInt=2,setOs="A6"}, - 'setSet-E'=#'SetSetExp'{setInt=2,setOs="A7"}, - 'setSetI-E'=#'SetSetExp'{setInt=2,setOs="A8"}, - 'setSetE-E'=#'SetSetExp'{setInt=2,setOs="A9"}}), + #'SetTRset'{setSet=#'SetSet'{setInt=2,setOs = <<"A1">>}, + setSetI=#'SetSet'{setInt=2,setOs = <<"A2">>}, + setSetE=#'SetSet'{setInt=2,setOs = <<"A3">>}, + 'setSet-I'=#'SetSetImp'{setInt=2,setOs = <<"A4">>}, + 'setSetI-I'=#'SetSetImp'{setInt=2,setOs = <<"A5">>}, + 'setSetE-I'=#'SetSetImp'{setInt=2,setOs = <<"A6">>}, + 'setSet-E'=#'SetSetExp'{setInt=2,setOs = <<"A7">>}, + 'setSetI-E'=#'SetSetExp'{setInt=2,setOs = <<"A8">>}, + 'setSetE-E'=#'SetSetExp'{setInt=2,setOs = <<"A9">>}}), ok. diff --git a/lib/asn1/test/testTimer.erl b/lib/asn1/test/testTimer.erl index 0f02bab6e0..89bc2b463d 100644 --- a/lib/asn1/test/testTimer.erl +++ b/lib/asn1/test/testTimer.erl @@ -18,163 +18,141 @@ %% %% -module(testTimer). --export([go/2]). +-export([go/0]). -include_lib("test_server/include/test_server.hrl"). -define(times, 5000). val() -> - _Value = {'H323-UserInformation',{'H323-UU-PDU', - {callProceeding, - {'CallProceeding-UUIE', - {0,8,222}, - {'EndpointType', - {'NonStandardParameter', - {object,{0,9,237}}, - "O"}, - {'VendorIdentifier', - {'H221NonStandard',62,63,16282}, - "OC", - "OC"}, - {'GatekeeperInfo', - {'NonStandardParameter', - {object,{0,10,260}}, - "O"}}, - {'GatewayInfo', - [{h320, - {'H320Caps', - {'NonStandardParameter', - {object,{0,11,282}}, - "O"}, - [{'DataRate', - {'NonStandardParameter', - {object, - {0,11,295}}, - "O"}, - 1290470518, - 78}], - [{'SupportedPrefix', - {'NonStandardParameter', - {object, - {0,12,312}}, - "O"}, - {'h323-ID',"BM"}}]}}], - {'NonStandardParameter', - {object,{0,13,326}}, - "O"}}, - {'McuInfo', - {'NonStandardParameter', - {object,{1,13,340,340}}, - "OC"}}, - {'TerminalInfo', - {'NonStandardParameter', - {object,{1,14,353,354}}, - "OC"}}, - true, - true}, - {ipxAddress, - {'TransportAddress_ipxAddress', - "OCTET ", - "OCTE", - "OC"}}, - {'CallIdentifier',"OCTET STRINGOCTE"}, - {noSecurity,'NULL'}, - [{'ClearToken', - 1667517741, - "BM", - {'DHset',[1],[1],[1]}, - "OCTET STR", - -26430296, - {'TypedCertificate', - {1,16,405,406}, - "OC"}, - "BMP", - {'NonStandardParameter', - {1,16,414,415}, - "OC"}}, - {'ClearToken', - 1817656756, - "BMP", - {'DHset',[1],[1],[1]}, - "OCTET STRI", - -16356110, - {'TypedCertificate', - {1,17,442,443}, - "OC"}, - "BMP", - {'NonStandardParameter', - {1,18,452,452}, - "OC"}}], - [{cryptoGKPwdEncr, - {'CryptoH323Token_cryptoGKPwdEncr', - {1,18,467,467}, - {'Params',-7477016,"OCTET ST"}, - "OC"}}, - {cryptoGKPwdEncr, - {'CryptoH323Token_cryptoGKPwdEncr', - {1,19,486,486}, - {'Params',-2404513,"OCTET ST"}, - []}}], - []}}, - {'NonStandardParameter',{object,{0,3,84}},[]}, - [], - true, - [], - []}, - {'H323-UserInformation_user-data',24,"O"}}. + {'H323-UserInformation',{'H323-UU-PDU', + {callProceeding, + {'CallProceeding-UUIE', + {0,8,222}, + {'EndpointType', + {'NonStandardParameter', + {object,{0,9,237}}, + <<"O">>}, + {'VendorIdentifier', + {'H221NonStandard',62,63,16282}, + <<"OC">>, + <<"OC">>}, + {'GatekeeperInfo', + {'NonStandardParameter', + {object,{0,10,260}}, + <<"O">>}}, + {'GatewayInfo', + [{h320, + {'H320Caps', + {'NonStandardParameter', + {object,{0,11,282}}, + <<"O">>}, + [{'DataRate', + {'NonStandardParameter', + {object, + {0,11,295}}, + <<"O">>}, + 1290470518, + 78}], + [{'SupportedPrefix', + {'NonStandardParameter', + {object, + {0,12,312}}, + <<"O">>}, + {'h323-ID',"BM"}}]}}], + {'NonStandardParameter', + {object,{0,13,326}}, + <<"O">>}}, + {'McuInfo', + {'NonStandardParameter', + {object,{1,13,340,340}}, + <<"OC">>}}, + {'TerminalInfo', + {'NonStandardParameter', + {object,{1,14,353,354}}, + <<"OC">>}}, + true, + true}, + {ipxAddress, + {'TransportAddress_ipxAddress', + <<"OCTET ">>, + <<"OCTE">>, + <<"OC">>}}, + {'CallIdentifier',<<"OCTET STRINGOCTE">>}, + {noSecurity,'NULL'}, + [{'ClearToken', + 1667517741, + "BM", + {'DHset',<<1:1>>,<<1:1>>,<<1:1>>}, + <<"OCTET STR">>, + -26430296, + {'TypedCertificate', + {1,16,405,406}, + <<"OC">>}, + "BMP", + {'NonStandardParameter', + {1,16,414,415}, + <<"OC">>}}, + {'ClearToken', + 1817656756, + "BMP", + {'DHset',<<1:1>>,<<1:1>>,<<1:1>>}, + <<"OCTET STRI">>, + -16356110, + {'TypedCertificate', + {1,17,442,443}, + <<"OC">>}, + "BMP", + {'NonStandardParameter', + {1,18,452,452}, + <<"OC">>}}], + [{cryptoGKPwdEncr, + {'CryptoH323Token_cryptoGKPwdEncr', + {1,18,467,467}, + {'Params',-7477016,<<"OCTET ST">>}, + <<"OC">>}}, + {cryptoGKPwdEncr, + {'CryptoH323Token_cryptoGKPwdEncr', + {1,19,486,486}, + {'Params',-2404513,<<"OCTET ST">>}, + <<>>}}], + []}}, + {'NonStandardParameter',{object,{0,3,84}},<<>>}, + [], + true, + [], + []}, + {'H323-UserInformation_user-data',24,<<"O">>}}. -go(Config, _Enc) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - +go() -> Module = 'H323-MESSAGES', Type = 'H323-UserInformation', Value = val(), - {ok,Bytes} = asn1rt:encode(Module,Type,Value), + Bytes = Module:encode(Type, Value), + Value = Module:decode(Type, Bytes), - CompileOptions = compile_options(), - {ValWr,done} = timer:tc(fun() -> encode(?times, Module, Type, Value) end), - ?line io:format("ASN1 encode ~p: ~p micro~n", [CompileOptions, ValWr / ?times]), + io:format("ASN.1 encoding: ~p micro~n", [ValWr / ?times]), done = decode(2, Module, Type, Bytes), {ValRead,done} = timer:tc(fun() -> decode(?times, Module, Type, Bytes) end), - ?line io:format("ASN1 decode ~p: ~p micro~n", [CompileOptions, ValRead /?times]), - + io:format("ASN.1 decoding: ~p micro~n", [ValRead /?times]), - ?line Comment = "encode: "++integer_to_list(round(ValWr/?times))++ - " micro, decode: "++integer_to_list(round(ValRead /?times))++ - " micro. " ++ CompileOptions, + Comment = "encode: "++integer_to_list(round(ValWr/?times)) ++ + " micro, decode: "++integer_to_list(round(ValRead /?times)) ++ + " micro. [" ++ atom_to_list(Module:encoding_rule()) ++ "]", {comment,Comment}. encode(0, _Module,_Type,_Value) -> done; encode(N, Module,Type,Value) -> - ?line {ok,B} = asn1rt:encode(Module,Type,Value), - _B2 = if - is_list(B) -> list_to_binary(B); - true -> B - end, - encode(N-1, Module,Type,Value). + Module:encode(Type, Value), + encode(N-1, Module, Type, Value). decode(0, _Module, _Type, _Value) -> done; decode(N, Module, Type, Value) -> - {ok,_B} = asn1rt:decode(Module, Type, Value), + Module:decode(Type, Value), decode(N-1, Module, Type, Value). - -compile_options() -> - {ok,Info} = asn1rt:info('H323-MESSAGES'), - case lists:keyfind(options, 1, Info) of - {_,Opts0} -> - Opts1 = [X || X <- Opts0, - (X =:= ber orelse - X =:= per orelse - X =:= uper)], - lists:flatten(io_lib:format("~p", [Opts1])); - _ -> - "[]" - end. - diff --git a/lib/asn1/test/testTypeValueNotation.erl b/lib/asn1/test/testTypeValueNotation.erl index b46d7177f5..2b5f3f74c1 100644 --- a/lib/asn1/test/testTypeValueNotation.erl +++ b/lib/asn1/test/testTypeValueNotation.erl @@ -24,7 +24,7 @@ -record('Seq', {octstr, int, bool, enum, bitstr, null, oid, vstr}). main(_Rule, _Option) -> - Value = #'Seq'{octstr = [1, 2, 3, 4], + Value = #'Seq'{octstr = <<1,2,3,4>>, int = 12, bool = true, enum = a, diff --git a/lib/asn1/test/test_compile_options.erl b/lib/asn1/test/test_compile_options.erl index 179299c78d..7f358e863c 100644 --- a/lib/asn1/test/test_compile_options.erl +++ b/lib/asn1/test/test_compile_options.erl @@ -123,7 +123,7 @@ verbose(Config) when is_list(Config) -> ?line ok = asn1ct:compile(Asn1File, [{i,DataDir},{outdir,OutDir},noobj,verbose]), ?line test_server:capture_stop(), ?line [Line0|_] = test_server:capture_get(), - ?line true = lists:prefix("Erlang ASN.1 version", Line0), + ?line true = lists:prefix("Erlang ASN.1 compiler", Line0), %% Test non-verbose compile ?line test_server:capture_start(), diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk index 153c64ebdd..1f16f31f6b 100644 --- a/lib/asn1/vsn.mk +++ b/lib/asn1/vsn.mk @@ -1,2 +1,2 @@ #next version number to use is 2.0 -ASN1_VSN = 2.0.4 +ASN1_VSN = 3.0 |