From ea6635bdae9667bcf6111a25d896c556c946c11a Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Sun, 6 Aug 2017 23:23:04 -0700 Subject: [PATCH] better parsing information object class sets --- libasn1compiler/asn1c_C.c | 80 ++++- libasn1fix/asn1fix.c | 12 +- libasn1fix/asn1fix_class.c | 2 +- libasn1fix/asn1fix_class.h | 2 +- libasn1fix/asn1fix_constraint.c | 2 +- libasn1fix/asn1fix_cws.c | 282 ++++++++++++++---- libasn1fix/asn1fix_export.c | 4 +- libasn1fix/asn1fix_export.h | 6 +- libasn1fix/asn1fix_misc.c | 9 +- libasn1fix/asn1fix_retrieve.c | 6 +- libasn1fix/asn1fix_retrieve.h | 4 +- libasn1parser/asn1p_class.c | 30 ++ libasn1parser/asn1p_class.h | 7 + libasn1parser/asn1p_constr.c | 39 +++ libasn1parser/asn1p_constr.h | 8 + libasn1parser/asn1p_expr.c | 76 +++++ libasn1parser/asn1p_expr.h | 3 + libasn1parser/asn1p_oid.c | 2 +- libasn1parser/asn1p_oid.h | 2 +- libasn1parser/asn1p_ref.c | 62 +++- libasn1parser/asn1p_ref.h | 14 + libasn1parser/asn1p_value.c | 78 +++++ libasn1parser/asn1p_value.h | 3 + tests/139-component-relation-OK.asn1 | 36 +++ ...ent-relation-OK.asn1.-EFprint-class-matrix | 31 ++ tests/140-component-relation-OK.asn1 | 35 +++ ...ent-relation-OK.asn1.-EFprint-class-matrix | 35 +++ 27 files changed, 779 insertions(+), 91 deletions(-) create mode 100755 tests/139-component-relation-OK.asn1 create mode 100644 tests/139-component-relation-OK.asn1.-EFprint-class-matrix create mode 100755 tests/140-component-relation-OK.asn1 create mode 100644 tests/140-component-relation-OK.asn1.-EFprint-class-matrix diff --git a/libasn1compiler/asn1c_C.c b/libasn1compiler/asn1c_C.c index 9a018356..7c4d466a 100644 --- a/libasn1compiler/asn1c_C.c +++ b/libasn1compiler/asn1c_C.c @@ -298,15 +298,91 @@ asn1c_lang_C_type_BIT_STRING(arg_t *arg) { return asn1c_lang_C_type_SIMPLE_TYPE(arg); } +/* + * Given the table constraint or component relation constraint + * ({ObjectSetName}{...}) returns "ObjectSetName" as a reference. + */ +static const asn1p_ref_t * +asn1c_get_information_object_set_reference_from_constraint( + const asn1p_constraint_t *ct) { + + if(!ct) return NULL; + assert(ct->type == ACT_CA_CRC); + assert(ct->el_count >= 1); + + assert(ct->elements[0]->type == ACT_EL_VALUE); + + asn1p_value_t *val = ct->elements[0]->value; + assert(val->type == ATV_REFERENCED); + + return val->value.reference; +} + +typedef struct asn1c_ioc_table_s { +} asn1c_ioc_table_t; + +static asn1c_ioc_table_t * +asn1c_construct_ioc_table_from_objset(arg_t *arg, const asn1p_ref_t *objset_ref, asn1p_expr_t *objset) { + asn1c_ioc_table_t *itable = NULL; + itable = calloc(1, sizeof(*itable)); + assert(itable); + + return itable; +}; + +static asn1c_ioc_table_t * +asn1c_construct_ioc_table(arg_t *arg) { + asn1p_expr_t *expr = arg->expr; + asn1p_expr_t *memb; + asn1p_expr_t *objset = 0; + const asn1p_ref_t *objset_ref = NULL; + + TQ_FOR(memb, &(expr->members), next) { + const asn1p_ref_t *tmpref = + asn1c_get_information_object_set_reference_from_constraint( + asn1p_get_component_relation_constraint(memb->constraints)); + if(tmpref) { + if(objset_ref && asn1p_ref_compare(objset_ref, tmpref) != 0) { + FATAL( + "Object set reference on line %d differs from object set " + "reference on line %d", + objset_ref->_lineno, tmpref->_lineno); + errno = EINVAL; + return NULL; + } + objset_ref = tmpref; + } + } + + if(!objset_ref) { + errno = 0; /* "Safe" error. */ + return NULL; + } + + objset = asn1f_lookup_symbol_ex(arg->asn, arg->expr, objset_ref); + if(!objset) { + FATAL("Cannot found %s", asn1p_ref_string(objset_ref)); + return NULL; + } + + return asn1c_construct_ioc_table_from_objset(arg, objset_ref, objset); +} + int asn1c_lang_C_type_SEQUENCE(arg_t *arg) { asn1p_expr_t *expr = arg->expr; asn1p_expr_t *v; int comp_mode = 0; /* {root,ext=1,root,root,...} */ int saved_target = arg->target->target; + asn1c_ioc_table_t *itable = NULL; DEPENDENCIES; + itable = asn1c_construct_ioc_table(arg); + if(!itable && errno != 0) { + return -1; + } + if(arg->embed) { /* Use _anonymous_type field to indicate it's called from @@ -450,11 +526,13 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) { ++elm; } OUT(" };\n"); - if(roms_count > 65536) + if(roms_count > 65536) { FATAL("Too many optional elements in %s " "at line %d!", arg->expr->Identifier, arg->expr->_lineno); + return -1; + } } else { roms_count = 0; aoms_count = 0; diff --git a/libasn1fix/asn1fix.c b/libasn1fix/asn1fix.c index 124576f2..2cdf5271 100644 --- a/libasn1fix/asn1fix.c +++ b/libasn1fix/asn1fix.c @@ -338,18 +338,18 @@ phase_1_1(arg_t *arg, int prm2) { ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_values); RET2RVAL(ret, rvalue); - /* - * Parse class objects and fill up the object class with data. - */ - ret = asn1f_parse_class_object(arg); - RET2RVAL(ret, rvalue); - /* * Resolve references in constraints. */ ret = asn1f_recurse_expr(arg, asn1f_resolve_constraints); RET2RVAL(ret, rvalue); + /* + * Parse class information object sets. + */ + ret = asn1f_parse_class_object(arg); + RET2RVAL(ret, rvalue); + /* * 6. INTEGER value processed at 2.5.4. */ diff --git a/libasn1fix/asn1fix_class.c b/libasn1fix/asn1fix_class.c index 32ad8963..02bcaaca 100644 --- a/libasn1fix/asn1fix_class.c +++ b/libasn1fix/asn1fix_class.c @@ -1,7 +1,7 @@ #include "asn1fix_internal.h" asn1p_expr_t * -asn1f_class_access(arg_t *arg, asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, asn1p_ref_t *ref) { +asn1f_class_access(arg_t *arg, asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, const asn1p_ref_t *ref) { asn1p_expr_t *ioclass; asn1p_expr_t *classfield; asn1p_expr_t *expr; diff --git a/libasn1fix/asn1fix_class.h b/libasn1fix/asn1fix_class.h index 2120bc8c..b0c143bd 100644 --- a/libasn1fix/asn1fix_class.h +++ b/libasn1fix/asn1fix_class.h @@ -4,6 +4,6 @@ /* * Fetch the element from the class-related stuff (thing) by its reference. */ -asn1p_expr_t *asn1f_class_access(arg_t *, asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, asn1p_ref_t *); +asn1p_expr_t *asn1f_class_access(arg_t *, asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, const asn1p_ref_t *); #endif /* ASN1FIX_CLASS_H */ diff --git a/libasn1fix/asn1fix_constraint.c b/libasn1fix/asn1fix_constraint.c index 97fa589b..ec13bd6b 100644 --- a/libasn1fix/asn1fix_constraint.c +++ b/libasn1fix/asn1fix_constraint.c @@ -356,7 +356,7 @@ constraint_object_resolve(arg_t *arg, asn1p_value_t *value) { asn1p_expr_t tmp_expr = *arg->expr; asn1p_expr_t *saved_expr = arg->expr; - tmp_expr.meta_type = AMT_VALUE; + tmp_expr.meta_type = AMT_VALUESET; tmp_expr.expr_type = A1TC_REFERENCE; tmp_expr.value = value; arg->expr = &tmp_expr; diff --git a/libasn1fix/asn1fix_cws.c b/libasn1fix/asn1fix_cws.c index e0ab9419..de2d2406 100644 --- a/libasn1fix/asn1fix_cws.c +++ b/libasn1fix/asn1fix_cws.c @@ -3,10 +3,10 @@ static int _asn1f_parse_class_object_data(arg_t *, asn1p_expr_t *eclass, struct asn1p_ioc_row_s *row, asn1p_wsyntx_t *syntax, - uint8_t *buf, const uint8_t *bend, - int optional_mode, uint8_t **newpos); -static int _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_ioc_cell_s *cell, uint8_t *buf, const uint8_t *bend); -static asn1p_wsyntx_chunk_t *asn1f_next_literal_chunk(asn1p_wsyntx_t *syntax, asn1p_wsyntx_chunk_t *chunk, uint8_t *buf); + const uint8_t *buf, const uint8_t *bend, + int optional_mode, const uint8_t **newpos); +static int _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_ioc_cell_s *cell, const uint8_t *buf, const uint8_t *bend); +static asn1p_wsyntx_chunk_t *asn1f_next_literal_chunk(asn1p_wsyntx_t *syntax, asn1p_wsyntx_chunk_t *chunk, const uint8_t *buf); int asn1f_check_class_object(arg_t *arg) { @@ -15,11 +15,12 @@ asn1f_check_class_object(arg_t *arg) { asn1p_ioc_row_t *row; int ret; - if(expr->meta_type != AMT_VALUE + if(expr->meta_type != AMT_VALUESET || expr->expr_type != A1TC_REFERENCE || !expr->value - || expr->value->type != ATV_UNPARSED) + || expr->value->type != ATV_UNPARSED) { return 0; + } eclass = asn1f_find_terminal_type(arg, expr); if(!eclass @@ -49,19 +50,193 @@ asn1f_check_class_object(arg_t *arg) { return ret; } +static int +_asn1f_is_ioc_row_duplicate(asn1p_ioc_row_t **rows, size_t count, asn1p_ioc_row_t *row) { + for(size_t i = 0; i < count; i++) { + switch(asn1p_ioc_row_match(rows[i], row)) { + default: + case -1: + return -1; + case 1: + continue; + case 0: + return 1; /* Duplicate! */ + } + } + return 0; +} + +struct parse_object_key { + arg_t *arg; + asn1p_expr_t *expr; /* InformationObjectSet */ + asn1p_expr_t *eclass; /* CLASS */ +}; + +static int +_asn1f_add_row(arg_t *arg, asn1p_expr_t *expr, asn1p_ioc_row_t *row) { + void *new_rows_ptr; + + switch(_asn1f_is_ioc_row_duplicate(expr->object_class_matrix.row, + expr->object_class_matrix.rows, row)) { + case -1: + DEBUG("Found Information Object Duplicate in %s", expr->Identifier, + expr->_lineno); + return -1; + case 0: + /* Not a duplicate */ + break; + case 1: + /* Proper duplicate detected; ignore */ + asn1p_ioc_row_delete(row); + return 0; + } + + new_rows_ptr = realloc(expr->object_class_matrix.row, + (expr->object_class_matrix.rows + 1) + * sizeof(expr->object_class_matrix.row[0])); + assert(new_rows_ptr); + expr->object_class_matrix.row = new_rows_ptr; + expr->object_class_matrix.row[expr->object_class_matrix.rows] = row; + expr->object_class_matrix.rows++; + /* Propagate max identifier length */ + if(expr->object_class_matrix.max_identifier_length + < row->max_identifier_length) + expr->object_class_matrix.max_identifier_length + = row->max_identifier_length; + + return 0; +} + +/* + * Given a single blob of unparsed Information Object specification, parse it + * into a given InformationObjectSet. + */ +static int +_asn1f_parse_object_cb(const uint8_t *buf, size_t size, void *keyp) { + struct parse_object_key *key = keyp; + arg_t *arg = key->arg; + asn1p_expr_t *expr = key->expr; + asn1p_expr_t *eclass = key->eclass; + asn1p_ioc_row_t *row; + int ret; + + row = asn1p_ioc_row_new(eclass); + assert(row); + + ret = _asn1f_parse_class_object_data(arg, eclass, row, eclass->with_syntax, + buf, buf + size, 0, 0); + if(ret) { + LOG((int)(ret < 0), + "Cannot parse %s of CLASS %s found at line %d", + expr->Identifier, eclass->Identifier, expr->_lineno); + asn1p_ioc_row_delete(row); + return ret; + } + + /* Add object to a CLASS. */ + if(_asn1f_add_row(arg, eclass, row) != 0) + return -1; + + /* + * Add a copy of the object to the Information Object Set. + */ + row = asn1p_ioc_row_new(eclass); + assert(row); + ret = _asn1f_parse_class_object_data(arg, eclass, row, eclass->with_syntax, + buf, buf + size, 0, 0); + assert(ret == 0); + + if(_asn1f_add_row(arg, expr, row) != 0) + return -1; + + return 0; +} + +static int +_asn1f_foreach_unparsed_union(const asn1p_constraint_t *ct_union, + int (*process)(const uint8_t *buf, size_t size, + void *key), + void *key) { + assert(ct_union->type == ACT_CA_UNI); + + for(size_t j = 0; j < ct_union->el_count; j++) { + const asn1p_constraint_t *ct2 = ct_union->elements[j]; + if(ct2->type == ACT_EL_VALUE && ct2->value->type == ATV_UNPARSED) { + if(process + && process(ct2->value->value.string.buf + 1, + ct2->value->value.string.size - 2, key) + != 0) { + return -1; + } + continue; + } + return -1; + } + + return 0; +} + +static int +_asn1f_foreach_unparsed(const asn1p_constraint_t *ct, + int (*process)(const uint8_t *buf, size_t size, + void *key), + void *key) { + if(!ct) return -1; + if(ct->type == ACT_CA_UNI) { + return _asn1f_foreach_unparsed_union(ct, process, key); + } + if(ct->type != ACT_CA_CSV) return -1; + + for(size_t i = 0; i < ct->el_count; i++) { + const asn1p_constraint_t *ct1 = ct->elements[i]; + switch(ct1->type) { + case ACT_EL_EXT: + break; + case ACT_CA_UNI: + if(_asn1f_foreach_unparsed_union(ct1, process, key) != 0) { + return -1; + } + break; + default: + return -1; + } + } + + return 0; +} + +static int +_asn1f_constraint_looks_like_object_set(const asn1p_constraint_t *ct) { + return 0 == _asn1f_foreach_unparsed(ct, NULL, NULL); +} + int asn1f_parse_class_object(arg_t *arg) { asn1p_expr_t *expr = arg->expr; asn1p_expr_t *eclass; - asn1p_ioc_row_t *row; - void *new_rows_ptr; - int ret; + enum { + FROM_VALUE, + FROM_CONSTRAINT, + } source = FROM_VALUE; - if(expr->meta_type != AMT_VALUE - || expr->expr_type != A1TC_REFERENCE - || !expr->value - || expr->value->type != ATV_UNPARSED) - return 0; + if(expr->meta_type == AMT_VALUE + && expr->expr_type == A1TC_REFERENCE + && expr->value && expr->value->type == ATV_UNPARSED) { + source = FROM_VALUE; + } else if(expr->meta_type != AMT_VALUESET + || expr->expr_type != A1TC_REFERENCE) { + return 0; + } else if(expr->value && expr->value->type == ATV_UNPARSED) { + source = FROM_VALUE; + } else if(!expr->value) { + if(_asn1f_constraint_looks_like_object_set(expr->constraints)) { + source = FROM_CONSTRAINT; + } else { + return 0; + } + } else { + return 0; + } /* * Find the governing class. @@ -82,35 +257,27 @@ asn1f_parse_class_object(arg_t *arg) { return 0; } - row = asn1p_ioc_row_new(eclass); - assert(row); + struct parse_object_key key = { + .arg = arg, + .expr = expr, + .eclass = eclass, + }; - ret = _asn1f_parse_class_object_data(arg, eclass, row, - eclass->with_syntax, - expr->value->value.string.buf + 1, - expr->value->value.string.buf - + expr->value->value.string.size - 1, - 0, 0); - if(ret) { - LOG((int)(ret < 0), - "Cannot parse %s of CLASS %s found at line %d", - expr->Identifier, eclass->Identifier, expr->_lineno); - asn1p_ioc_row_delete(row); - return ret; - } - - new_rows_ptr = realloc(eclass->object_class_matrix.row, - (eclass->object_class_matrix.rows + 1) - * sizeof(eclass->object_class_matrix.row[0])); - assert(new_rows_ptr); - eclass->object_class_matrix.row = new_rows_ptr; - eclass->object_class_matrix.row[eclass->object_class_matrix.rows] = row; - eclass->object_class_matrix.rows++; - /* Propagate max identifier length */ - if(eclass->object_class_matrix.max_identifier_length - < row->max_identifier_length) - eclass->object_class_matrix.max_identifier_length - = row->max_identifier_length; + switch(source) { + case FROM_VALUE: + if(_asn1f_parse_object_cb(expr->value->value.string.buf + 1, + expr->value->value.string.size - 2, &key) + != 0) { + return -1; + } + break; + case FROM_CONSTRAINT: + if(_asn1f_foreach_unparsed(expr->constraints, _asn1f_parse_object_cb, + &key) + != 0) { + return -1; + } + } return 0; } @@ -120,8 +287,8 @@ asn1f_parse_class_object(arg_t *arg) { static int _asn1f_parse_class_object_data(arg_t *arg, asn1p_expr_t *eclass, struct asn1p_ioc_row_s *row, asn1p_wsyntx_t *syntax, - uint8_t *buf, const uint8_t *bend, - int optional_mode, uint8_t **newpos) { + const uint8_t *buf, const uint8_t *bend, + int optional_mode, const uint8_t **newpos) { struct asn1p_wsyntx_chunk_s *chunk; int ret; @@ -145,8 +312,8 @@ _asn1f_parse_class_object_data(arg_t *arg, asn1p_expr_t *eclass, case WC_FIELD: { struct asn1p_ioc_cell_s *cell; asn1p_wsyntx_chunk_t *next_literal; - uint8_t *buf_old = buf; - uint8_t *p = 0; + const uint8_t *buf_old = buf; + const uint8_t *p = 0; SKIPSPACES; @@ -154,7 +321,7 @@ _asn1f_parse_class_object_data(arg_t *arg, asn1p_expr_t *eclass, if(!next_literal) { p += (bend - p); } else { - p = (uint8_t *)strstr((char *)buf, (char *)next_literal->content.token); + p = (uint8_t *)strstr((const char *)buf, (const char *)next_literal->content.token); if(!p) { if (!optional_mode) FATAL("Next literal \"%s\" not found !", next_literal->content.token); @@ -181,7 +348,7 @@ _asn1f_parse_class_object_data(arg_t *arg, asn1p_expr_t *eclass, if(newpos) *newpos = buf; } break; case WC_OPTIONALGROUP: { - uint8_t *np = 0; + const uint8_t *np = 0; SKIPSPACES; ret = _asn1f_parse_class_object_data(arg, eclass, row, chunk->content.syntax, buf, bend, 1, &np); @@ -200,9 +367,10 @@ _asn1f_parse_class_object_data(arg_t *arg, asn1p_expr_t *eclass, static int -_asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_ioc_cell_s *cell, - uint8_t *buf, const uint8_t *bend) { - asn1p_expr_t *expr = (asn1p_expr_t *)NULL; +_asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, + struct asn1p_ioc_cell_s *cell, const uint8_t *buf, + const uint8_t *bend) { + asn1p_expr_t *expr = (asn1p_expr_t *)NULL; int idLength; char *p; int new_ref = 1; @@ -259,7 +427,7 @@ _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_i free(pp); return -1; } - DEBUG("ASN.1 :\n\n%s\n", pp); + DEBUG("ASN.1:\n\n%s\n", pp); assert(ret < psize); psize = ret; @@ -281,11 +449,9 @@ _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_i assert(expr); free(expr->Identifier); - expr->module = arg->expr->module; - expr->_lineno = arg->expr->_lineno; + expr->parent_expr = NULL; + asn1p_expr_set_source(expr, arg->expr->module, arg->expr->_lineno); if (expr->reference) { - expr->reference->module = arg->expr->module; - expr->reference->_lineno = arg->expr->_lineno; expr->Identifier = strdup(expr->reference->components[expr->reference->comp_count - 1].name); } else { expr->Identifier = p; @@ -327,7 +493,7 @@ _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_i } static asn1p_wsyntx_chunk_t * -asn1f_next_literal_chunk(asn1p_wsyntx_t *syntax, asn1p_wsyntx_chunk_t *chunk, uint8_t *buf) +asn1f_next_literal_chunk(asn1p_wsyntx_t *syntax, asn1p_wsyntx_chunk_t *chunk, const uint8_t *buf) { asn1p_wsyntx_chunk_t *next_chunk; @@ -338,7 +504,7 @@ asn1f_next_literal_chunk(asn1p_wsyntx_t *syntax, asn1p_wsyntx_chunk_t *chunk, ui break; next_chunk = TQ_NEXT(syntax->parent, next); } else if(next_chunk->type == WC_LITERAL) { - if(strstr((char *)buf, (char *)next_chunk->content.token)) + if(strstr((const char *)buf, (char *)next_chunk->content.token)) break; if(!syntax->parent) break; diff --git a/libasn1fix/asn1fix_export.c b/libasn1fix/asn1fix_export.c index bb598bf4..b5709258 100644 --- a/libasn1fix/asn1fix_export.c +++ b/libasn1fix/asn1fix_export.c @@ -8,7 +8,7 @@ asn1p_expr_t * asn1f_lookup_symbol_ex( asn1p_t *asn, asn1p_expr_t *expr, - asn1p_ref_t *ref) { + const asn1p_ref_t *ref) { arg_t arg; memset(&arg, 0, sizeof(arg)); @@ -28,7 +28,7 @@ asn1f_class_access_ex(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, asn1p_expr_t *rhs_pspecs, - asn1p_ref_t *ref) { + const asn1p_ref_t *ref) { arg_t arg; memset(&arg, 0, sizeof(arg)); diff --git a/libasn1fix/asn1fix_export.h b/libasn1fix/asn1fix_export.h index 0411843b..f03807ee 100644 --- a/libasn1fix/asn1fix_export.h +++ b/libasn1fix/asn1fix_export.h @@ -10,7 +10,7 @@ /* * Create a human-readable representation of a reference and value. */ -char const *asn1f_printable_reference(asn1p_ref_t *ref); +char const *asn1f_printable_reference(const asn1p_ref_t *ref); char const *asn1f_printable_value(asn1p_value_t *value); /* @@ -19,13 +19,13 @@ char const *asn1f_printable_value(asn1p_value_t *value); asn1p_expr_t *asn1f_lookup_symbol_ex( asn1p_t *asn, asn1p_expr_t *expr, - asn1p_ref_t *ref); + const asn1p_ref_t *ref); /* * Exportable version of an asn1f_class_access(). */ asn1p_expr_t *asn1f_class_access_ex(asn1p_t *asn, asn1p_module_t *mod, - asn1p_expr_t *expr, asn1p_expr_t *rhs_rspecs, asn1p_ref_t *); + asn1p_expr_t *expr, asn1p_expr_t *rhs_rspecs, const asn1p_ref_t *); /* * Exportable version of asn1f_find_terminal_type(). diff --git a/libasn1fix/asn1fix_misc.c b/libasn1fix/asn1fix_misc.c index e5f4f797..23ae24fc 100644 --- a/libasn1fix/asn1fix_misc.c +++ b/libasn1fix/asn1fix_misc.c @@ -2,14 +2,9 @@ #include "asn1fix.h" char const * -asn1f_printable_reference(asn1p_ref_t *ref) { +asn1f_printable_reference(const asn1p_ref_t *ref) { if(ref) { - asn1p_value_t v; - - v.type = ATV_REFERENCED; - v.value.reference = ref; - - return asn1f_printable_value(&v); + return asn1p_ref_string(ref); } else { return ""; } diff --git a/libasn1fix/asn1fix_retrieve.c b/libasn1fix/asn1fix_retrieve.c index 1700914f..f086ed39 100644 --- a/libasn1fix/asn1fix_retrieve.c +++ b/libasn1fix/asn1fix_retrieve.c @@ -80,7 +80,7 @@ asn1f_lookup_in_imports(arg_t *arg, asn1p_module_t *mod, const char *name) { } asn1p_module_t * -asn1f_lookup_module(arg_t *arg, const char *module_name, asn1p_oid_t *oid) { +asn1f_lookup_module(arg_t *arg, const char *module_name, const asn1p_oid_t *oid) { asn1p_module_t *mod; assert(module_name); @@ -147,7 +147,7 @@ asn1f_lookup_module(arg_t *arg, const char *module_name, asn1p_oid_t *oid) { } static asn1p_expr_t * -asn1f_lookup_symbol_impl(arg_t *arg, asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, asn1p_ref_t *ref, int recursion_depth) { +asn1f_lookup_symbol_impl(arg_t *arg, asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, const asn1p_ref_t *ref, int recursion_depth) { asn1p_expr_t *ref_tc; /* Referenced tc */ asn1p_module_t *imports_from; char *modulename; @@ -369,7 +369,7 @@ asn1f_lookup_symbol_impl(arg_t *arg, asn1p_module_t *mod, asn1p_expr_t *rhs_pspe asn1p_expr_t * asn1f_lookup_symbol(arg_t *arg, - asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, asn1p_ref_t *ref) { + asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, const asn1p_ref_t *ref) { return asn1f_lookup_symbol_impl(arg, mod, rhs_pspecs, ref, 0); } diff --git a/libasn1fix/asn1fix_retrieve.h b/libasn1fix/asn1fix_retrieve.h index 2d529ef9..95b8330f 100644 --- a/libasn1fix/asn1fix_retrieve.h +++ b/libasn1fix/asn1fix_retrieve.h @@ -31,7 +31,7 @@ asn1p_module_t *asn1f_lookup_in_imports(arg_t *arg, asn1p_module_t *mod, const c */ asn1p_module_t *asn1f_lookup_module(arg_t *arg, const char *module_name, - asn1p_oid_t *module_oid); + const asn1p_oid_t *module_oid); /* * Return the reference to a destination of the given reference, @@ -40,7 +40,7 @@ asn1p_module_t *asn1f_lookup_module(arg_t *arg, asn1p_expr_t *asn1f_lookup_symbol(arg_t *arg, asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, - asn1p_ref_t *ref); + const asn1p_ref_t *ref); /* * Recursively find the original type for the given expression. diff --git a/libasn1parser/asn1p_class.c b/libasn1parser/asn1p_class.c index 4603d188..666e0a2b 100644 --- a/libasn1parser/asn1p_class.c +++ b/libasn1parser/asn1p_class.c @@ -62,6 +62,36 @@ asn1p_ioc_row_delete(asn1p_ioc_row_t *row) { } } +int +asn1p_ioc_row_match(const asn1p_ioc_row_t *a, const asn1p_ioc_row_t *b) { + assert(a && b); + + if(a->columns != b->columns) + return -1; /* Bad! */ + + for(size_t i = 0; i < a->columns; i++) { + assert(a->column[i].field); + assert(b->column[i].field); + if(strcmp(a->column[i].field->Identifier, + b->column[i].field->Identifier) + != 0) { + return -1; /* Bad! */ + } + if((a->column[i].value && !b->column[i].value) + || (!a->column[i].value && b->column[i].value)) { + return 1; /* Not match */ + } + if(a->column[i].value && b->column[i].value) { + if(asn1p_expr_compare(a->column[i].value, b->column[i].value) + != 0) { + return 1; /* Not match */ + } + } + } + + return 0; +} + struct asn1p_ioc_cell_s * asn1p_ioc_row_cell_fetch(asn1p_ioc_row_t *row, const char *fieldname) { int i; diff --git a/libasn1parser/asn1p_class.h b/libasn1parser/asn1p_class.h index 893dec3a..08fd374e 100644 --- a/libasn1parser/asn1p_class.h +++ b/libasn1parser/asn1p_class.h @@ -20,6 +20,13 @@ typedef struct asn1p_ioc_row_s { asn1p_ioc_row_t *asn1p_ioc_row_new(struct asn1p_expr_s *oclass); void asn1p_ioc_row_delete(asn1p_ioc_row_t *); + +/* + * Match is similar to a comparison, + * but -1 means error and 1 means not equal. 0 is OK + */ +int asn1p_ioc_row_match(const asn1p_ioc_row_t *, const asn1p_ioc_row_t *); + struct asn1p_ioc_cell_s *asn1p_ioc_row_cell_fetch(asn1p_ioc_row_t *, const char *fieldname); diff --git a/libasn1parser/asn1p_constr.c b/libasn1parser/asn1p_constr.c index d4716842..a9e939da 100644 --- a/libasn1parser/asn1p_constr.c +++ b/libasn1parser/asn1p_constr.c @@ -6,6 +6,28 @@ #include "asn1parser.h" +void +asn1p_constraint_set_source(asn1p_constraint_t *ct, + struct asn1p_module_s *module, int lineno) { + if(ct) { + ct->module = module; + ct->_lineno = lineno; + asn1p_value_set_source(ct->containedSubtype,module,lineno); + asn1p_value_set_source(ct->value,module,lineno); + asn1p_value_set_source(ct->range_start,module,lineno); + asn1p_value_set_source(ct->range_stop,module,lineno); + for(size_t i = 0; i < ct->el_count; i++) { + asn1p_constraint_set_source(ct->elements[i], module, lineno); + } + } +} + +int asn1p_constraint_compare(const asn1p_constraint_t *a, + const asn1p_constraint_t *b) { + assert(!"Constraint comparison is not implemented"); + return -1; +} + asn1p_constraint_t * asn1p_constraint_new(int _lineno, asn1p_module_t *mod) { asn1p_constraint_t *ct; @@ -189,3 +211,20 @@ asn1p_constraint_type2str(enum asn1p_constraint_type_e type) { } return "UNKNOWN"; } + +const asn1p_constraint_t * +asn1p_get_component_relation_constraint(asn1p_constraint_t *ct) { + if(ct) { + if(ct->type == ACT_CA_CRC) + return ct; + if(ct->type == ACT_CA_SET) { + for(size_t i = 0; i < ct->el_count; i++) { + const asn1p_constraint_t *tmp = + asn1p_get_component_relation_constraint(ct->elements[i]); + if(tmp) return tmp; + } + } + } + return NULL; +} + diff --git a/libasn1parser/asn1p_constr.h b/libasn1parser/asn1p_constr.h index 7edd63fa..2351628d 100644 --- a/libasn1parser/asn1p_constr.h +++ b/libasn1parser/asn1p_constr.h @@ -71,6 +71,14 @@ typedef struct asn1p_constraint_s { /* Human-readable constraint type description */ const char *asn1p_constraint_type2str(enum asn1p_constraint_type_e); +const asn1p_constraint_t *asn1p_get_component_relation_constraint( + asn1p_constraint_t *); + +int asn1p_constraint_compare(const asn1p_constraint_t *, + const asn1p_constraint_t *); +void asn1p_constraint_set_source(asn1p_constraint_t *, + struct asn1p_module_s *module, int lineno); + /* * Constructors and a recursive destructor. */ diff --git a/libasn1parser/asn1p_expr.c b/libasn1parser/asn1p_expr.c index 7a24d066..4383ea12 100644 --- a/libasn1parser/asn1p_expr.c +++ b/libasn1parser/asn1p_expr.c @@ -9,6 +9,82 @@ static asn1p_expr_t *asn1p_expr_clone_impl(asn1p_expr_t *expr, int skip_extensions, asn1p_expr_t *(*)(asn1p_expr_t *, void *), void *); static asn1p_value_t *value_resolver(asn1p_value_t *, void *arg); +void +asn1p_expr_set_source(asn1p_expr_t *expr, asn1p_module_t *module, int lineno) { + if(expr) { + expr->module = module; + expr->_lineno = lineno; + asn1p_ref_set_source(expr->reference, module, lineno); + asn1p_value_set_source(expr->value, module, lineno); + asn1p_constraint_set_source(expr->constraints, module, lineno); + asn1p_constraint_set_source(expr->combined_constraints, module, lineno); + asn1p_expr_set_source(expr->rhs_pspecs, module, lineno); + + asn1p_expr_t *memb; + + TQ_FOR(memb, &(expr->members), next) { + asn1p_expr_set_source(memb, module, lineno); + } + } +} + +int +asn1p_expr_compare(const asn1p_expr_t *a, const asn1p_expr_t *b) { + if(a->meta_type != b->meta_type || a->expr_type != b->expr_type) { + return -1; + } + + if((!a->Identifier && b->Identifier) || (a->Identifier && !b->Identifier)) { + return -1; + } else if(a->Identifier && strcmp(a->Identifier, b->Identifier)) { + return -1; + } + + if((!a->reference && b->reference) || (a->reference && !b->reference)) { + return -1; + } else if(a->reference + && asn1p_ref_compare(a->reference, b->reference) != 0) { + return -1; + } + + if((!a->value && b->value) || (a->value && !b->value)) { + return -1; + } else if(a->value && asn1p_value_compare(a->value, b->value)) { + return -1; + } + + if((a->tag.tag_class != b->tag.tag_class) + || (a->tag.tag_mode != b->tag.tag_mode) + || (a->tag.tag_value != b->tag.tag_value)) { + return -1; + } + + if((a->marker.flags != b->marker.flags) + || (a->marker.default_value && !b->marker.default_value) + || (!a->marker.default_value && b->marker.default_value) + || (a->marker.default_value + && asn1p_value_compare(a->marker.default_value, + b->marker.default_value))) { + return -1; + } + + if(a->unique != b->unique) { + return -1; + } + + const asn1p_expr_t *am = TQ_FIRST(&a->members); + const asn1p_expr_t *bm = TQ_FIRST(&b->members); + for(; am || bm; am = TQ_NEXT(am, next), bm = TQ_NEXT(bm, next)) { + if((am && !bm) || (!am && bm)) { + return -1; + } else if(asn1p_expr_compare(am, bm) != 0) { + return -1; + } + } + + return 0; +} + /* * Construct a new empty types collection. */ diff --git a/libasn1parser/asn1p_expr.h b/libasn1parser/asn1p_expr.h index 6f2503b1..524f5321 100644 --- a/libasn1parser/asn1p_expr.h +++ b/libasn1parser/asn1p_expr.h @@ -281,7 +281,10 @@ asn1p_expr_t *asn1p_expr_clone_with_resolver(asn1p_expr_t *, void *resolver_arg); void asn1p_expr_add(asn1p_expr_t *to, asn1p_expr_t *what); void asn1p_expr_add_many(asn1p_expr_t *to, asn1p_expr_t *from_what); +int asn1p_expr_compare(const asn1p_expr_t *, const asn1p_expr_t *); void asn1p_expr_free(asn1p_expr_t *expr); +void asn1p_expr_set_source(asn1p_expr_t *, asn1p_module_t *, int lineno); + #define TAG2STRING_BUFFER_SIZE 64 /* buf should be at least this big */ char *asn1p_tag2string(struct asn1p_type_tag_s *tag, char *opt_buf); diff --git a/libasn1parser/asn1p_oid.c b/libasn1parser/asn1p_oid.c index 14b96aa9..a71c8c4a 100644 --- a/libasn1parser/asn1p_oid.c +++ b/libasn1parser/asn1p_oid.c @@ -81,7 +81,7 @@ asn1p_oid_arc_free(asn1p_oid_arc_t *arc) { } int -asn1p_oid_compare(asn1p_oid_t *a, asn1p_oid_t *b) { +asn1p_oid_compare(const asn1p_oid_t *a, const asn1p_oid_t *b) { int i; for(i = 0; ; i++) { diff --git a/libasn1parser/asn1p_oid.h b/libasn1parser/asn1p_oid.h index 489a3c5a..1b7ba52b 100644 --- a/libasn1parser/asn1p_oid.h +++ b/libasn1parser/asn1p_oid.h @@ -61,7 +61,7 @@ void asn1p_oid_free(asn1p_oid_t *); * 0: The specified OIDs are equal. * -1 or 1 otherwise. */ -int asn1p_oid_compare(asn1p_oid_t *a, asn1p_oid_t *b); +int asn1p_oid_compare(const asn1p_oid_t *a, const asn1p_oid_t *b); #endif /* ASN1_PARSER_OID_H */ diff --git a/libasn1parser/asn1p_ref.c b/libasn1parser/asn1p_ref.c index 3ea9b586..64f51b4d 100644 --- a/libasn1parser/asn1p_ref.c +++ b/libasn1parser/asn1p_ref.c @@ -14,10 +14,8 @@ asn1p_ref_new(int _lineno, asn1p_module_t *mod) { asn1p_ref_t *ref; ref = calloc(1, sizeof *ref); - if(ref) { - ref->_lineno = _lineno; - ref->module = mod; - } + assert(ref); + asn1p_ref_set_source(ref, mod, _lineno); return ref; } @@ -39,6 +37,14 @@ asn1p_ref_free(asn1p_ref_t *ref) { } } +void +asn1p_ref_set_source(asn1p_ref_t *ref, asn1p_module_t *module, int lineno) { + if(ref) { + ref->module = module; + ref->_lineno = lineno; + } +} + static enum asn1p_ref_lex_type_e asn1p_ref_name2lextype(const char *name) { enum asn1p_ref_lex_type_e lex_type; @@ -136,3 +142,51 @@ asn1p_ref_clone(asn1p_ref_t *ref) { return newref; } + +int +asn1p_ref_compare(const asn1p_ref_t *a, const asn1p_ref_t *b) { + if(a->comp_count != b->comp_count) + return -1; + if(a->module != b->module) + return -1; + + for(size_t i = 0; i < a->comp_count; i++) { + if(a->components[i].lex_type != b->components[i].lex_type + || strcmp(a->components[i].name, b->components[i].name) != 0) { + return -1; + } + } + + return 0; +} + +const char * +asn1p_ref_string(const asn1p_ref_t *ref) { + static char static_buf[32]; + static char *buf = static_buf; + static size_t buf_size = sizeof(static_buf); + char *p = buf; + + for(size_t i = 0; i < ref->comp_count; i++) { + size_t space = buf_size - (p - buf); + int ret = + snprintf(p, space, "%s%s", i ? "." : "", ref->components[i].name); + if(ret < 0 || (size_t)ret >= space) { + i--; + char *tmp = malloc(buf_size * 2 + 1); + assert(tmp); + size_t p_offset = p - buf; + memcpy(tmp, buf, (p - buf)); + if(buf != static_buf) free(buf); + buf_size *= 2; + buf = tmp; + p = tmp + p_offset; + } else { + p += ret; + } + } + + *p = '\0'; + return buf; +} + diff --git a/libasn1parser/asn1p_ref.h b/libasn1parser/asn1p_ref.h index c4d8b5ce..776289b5 100644 --- a/libasn1parser/asn1p_ref.h +++ b/libasn1parser/asn1p_ref.h @@ -49,6 +49,20 @@ void asn1p_ref_free(asn1p_ref_t *); asn1p_ref_t *asn1p_ref_clone(asn1p_ref_t *ref); +void asn1p_ref_set_source(asn1p_ref_t *, asn1p_module_t *module, int lineno); + + +/* + * Lexicographically compare references. + */ +int asn1p_ref_compare(const asn1p_ref_t *, const asn1p_ref_t *); + +/* + * Return a pointer to a statically allocated buffer representing the + * complete reference. + */ +const char *asn1p_ref_string(const asn1p_ref_t *); + /* * Add a new reference component to the existing reference structure. * diff --git a/libasn1parser/asn1p_value.c b/libasn1parser/asn1p_value.c index fa3c1f49..9bd75639 100644 --- a/libasn1parser/asn1p_value.c +++ b/libasn1parser/asn1p_value.c @@ -4,7 +4,85 @@ #include #include "asn1parser.h" +#include "asn1p_expr.h" +void +asn1p_value_set_source(asn1p_value_t *value, asn1p_module_t *module, + int lineno) { + if(value) { + switch(value->type) { + case ATV_TYPE: + asn1p_expr_set_source(value->value.v_type, module, lineno); + break; + case ATV_REFERENCED: + asn1p_ref_set_source(value->value.reference, module, lineno); + break; + case ATV_VALUESET: + asn1p_constraint_set_source(value->value.constraint, module, + lineno); + break; + default: + break; + } + } +} + +int +asn1p_value_compare(const asn1p_value_t *a, const asn1p_value_t *b) { + if(a->type != b->type) { + return -1; + } + + switch(a->type) { + case ATV_NULL: + case ATV_NOVALUE: + case ATV_MAX: + case ATV_MIN: + case ATV_FALSE: + case ATV_TRUE: + break; + case ATV_TYPE: + return asn1p_expr_compare(a->value.v_type, b->value.v_type); + case ATV_REAL: + return (a->value.v_double == b->value.v_double) ? 0 : -1; + case ATV_INTEGER: + case ATV_TUPLE: + case ATV_QUADRUPLE: + return (a->value.v_integer == b->value.v_integer) ? 0 : -1; + case ATV_STRING: + case ATV_UNPARSED: + if(a->value.string.size != b->value.string.size + || memcmp(a->value.string.buf, b->value.string.buf, + a->value.string.size) + != 0) { + return -1; + } + return 0; + case ATV_BITVECTOR: + if(a->value.binary_vector.size_in_bits + != b->value.binary_vector.size_in_bits + || memcmp(a->value.binary_vector.bits, b->value.binary_vector.bits, + (a->value.binary_vector.size_in_bits+7) >> 3) + != 0) { + return -1; + } + case ATV_VALUESET: + return asn1p_constraint_compare(a->value.constraint, + b->value.constraint); + case ATV_REFERENCED: + return asn1p_ref_compare(a->value.reference, b->value.reference); + case ATV_CHOICE_IDENTIFIER: + if(strcmp(a->value.choice_identifier.identifier, + b->value.choice_identifier.identifier) + != 0) { + return -1; + } + return asn1p_value_compare(a->value.choice_identifier.value, + b->value.choice_identifier.value); + } + + return 0; +} asn1p_value_t * asn1p_value_fromref(asn1p_ref_t *ref, int do_copy) { diff --git a/libasn1parser/asn1p_value.h b/libasn1parser/asn1p_value.h index c260c27e..c1167f3e 100644 --- a/libasn1parser/asn1p_value.h +++ b/libasn1parser/asn1p_value.h @@ -5,6 +5,7 @@ #define ASN1_PARSER_VALUE_H struct asn1p_constraint_s; /* Forward declaration */ +struct asn1p_module_s; struct asn1p_expr_s; /* @@ -76,5 +77,7 @@ asn1p_value_t *asn1p_value_clone(asn1p_value_t *); asn1p_value_t *asn1p_value_clone_with_resolver(asn1p_value_t *, asn1p_value_t *(*resolver)(asn1p_value_t *, void *rarg), void *rarg); +int asn1p_value_compare(const asn1p_value_t *, const asn1p_value_t *); +void asn1p_value_set_source(asn1p_value_t *, struct asn1p_module_s *, int line); #endif /* ASN1_PARSER_VALUE_H */ diff --git a/tests/139-component-relation-OK.asn1 b/tests/139-component-relation-OK.asn1 new file mode 100755 index 00000000..e71a35e6 --- /dev/null +++ b/tests/139-component-relation-OK.asn1 @@ -0,0 +1,36 @@ + +-- OK: Everything is fine + +-- iso.org.dod.internet.private.enterprise (1.3.6.1.4.1) +-- .spelio.software.asn1c.test (9363.1.5.1) +-- .139 + +ModuleComponentRelationConstraint + { iso org(3) dod(6) internet (1) private(4) enterprise(1) + spelio(9363) software(1) asn1c(5) test(1) 139 } + DEFINITIONS ::= +BEGIN + + Frame ::= SEQUENCE { + ident FRAME-STRUCTURE.&id({FrameTypes}), + value FRAME-STRUCTURE.&Type({FrameTypes}{@.ident}), + ... + } + + FRAME-STRUCTURE ::= CLASS { + &id INTEGER UNIQUE, + &Type + } WITH SYNTAX {&Type IDENTIFIED BY &id} + + FrameTypes FRAME-STRUCTURE ::= { + { PrimitiveMessage IDENTIFIED BY basicMessage } | + { ComplexMessage IDENTIFIED BY 2 }, + ... + } + + PrimitiveMessage ::= SEQUENCE {} + ComplexMessage ::= SEQUENCE {} + + basicMessage INTEGER ::= 1 + +END diff --git a/tests/139-component-relation-OK.asn1.-EFprint-class-matrix b/tests/139-component-relation-OK.asn1.-EFprint-class-matrix new file mode 100644 index 00000000..aa611a6a --- /dev/null +++ b/tests/139-component-relation-OK.asn1.-EFprint-class-matrix @@ -0,0 +1,31 @@ +ModuleComponentRelationConstraint { iso org(3) dod(6) internet(1) private(4) + enterprise(1) spelio(9363) software(1) asn1c(5) test(1) 139 } +DEFINITIONS ::= +BEGIN + +Frame ::= SEQUENCE { + ident FRAME-STRUCTURE.&id ({FrameTypes}), + value FRAME-STRUCTURE.&Type ({FrameTypes}{@.ident}), + ... +} + +FRAME-STRUCTURE ::= CLASS { + &id INTEGER UNIQUE, + &Type ANY +} WITH SYNTAX {&Type IDENTIFIED BY &id} + +-- Class matrix has 2 entries: +-- [ &id][ &Type] +-- [1] basicMessage PrimitiveMessage +-- [2] 2 ComplexMessage + + +FrameTypes FRAME-STRUCTURE ::= {{ PrimitiveMessage IDENTIFIED BY basicMessage } | { ComplexMessage IDENTIFIED BY 2 },...} + +PrimitiveMessage ::= SEQUENCE { } + +ComplexMessage ::= SEQUENCE { } + +basicMessage INTEGER ::= 1 + +END diff --git a/tests/140-component-relation-OK.asn1 b/tests/140-component-relation-OK.asn1 new file mode 100755 index 00000000..acb72e5d --- /dev/null +++ b/tests/140-component-relation-OK.asn1 @@ -0,0 +1,35 @@ + +-- OK: Everything is fine + +-- iso.org.dod.internet.private.enterprise (1.3.6.1.4.1) +-- .spelio.software.asn1c.test (9363.1.5.1) +-- .140 + +ModuleComponentRelationConstraint + { iso org(3) dod(6) internet (1) private(4) enterprise(1) + spelio(9363) software(1) asn1c(5) test(1) 140 } + DEFINITIONS ::= +BEGIN + + Frame ::= SEQUENCE { + ident FRAME-STRUCTURE.&id({FrameTypes}), + value FRAME-STRUCTURE.&Type({FrameTypes}{@.ident}), + ... + } + + FRAME-STRUCTURE ::= CLASS { + &id INTEGER UNIQUE, + &Type + } WITH SYNTAX {&Type IDENTIFIED BY &id} + + FrameTypes FRAME-STRUCTURE ::= { primType | complexType, ... } + + primType FRAME-STRUCTURE ::= { PrimitiveMessage IDENTIFIED BY basicMessage } + complexType FRAME-STRUCTURE ::= { ComplexMessage IDENTIFIED BY 2 } + + PrimitiveMessage ::= SEQUENCE {} + ComplexMessage ::= SEQUENCE {} + + basicMessage INTEGER ::= 1 + +END diff --git a/tests/140-component-relation-OK.asn1.-EFprint-class-matrix b/tests/140-component-relation-OK.asn1.-EFprint-class-matrix new file mode 100644 index 00000000..4e9769a7 --- /dev/null +++ b/tests/140-component-relation-OK.asn1.-EFprint-class-matrix @@ -0,0 +1,35 @@ +ModuleComponentRelationConstraint { iso org(3) dod(6) internet(1) private(4) + enterprise(1) spelio(9363) software(1) asn1c(5) test(1) 140 } +DEFINITIONS ::= +BEGIN + +Frame ::= SEQUENCE { + ident FRAME-STRUCTURE.&id ({FrameTypes}), + value FRAME-STRUCTURE.&Type ({FrameTypes}{@.ident}), + ... +} + +FRAME-STRUCTURE ::= CLASS { + &id INTEGER UNIQUE, + &Type ANY +} WITH SYNTAX {&Type IDENTIFIED BY &id} + +-- Class matrix has 2 entries: +-- [ &id][ &Type] +-- [1] basicMessage PrimitiveMessage +-- [2] 2 ComplexMessage + + +FrameTypes FRAME-STRUCTURE ::= {{ PrimitiveMessage IDENTIFIED BY basicMessage } | { ComplexMessage IDENTIFIED BY 2 },...} + +primType FRAME-STRUCTURE ::= { PrimitiveMessage IDENTIFIED BY basicMessage } + +complexType FRAME-STRUCTURE ::= { ComplexMessage IDENTIFIED BY 2 } + +PrimitiveMessage ::= SEQUENCE { } + +ComplexMessage ::= SEQUENCE { } + +basicMessage INTEGER ::= 1 + +END