better parsing information object class sets

This commit is contained in:
Lev Walkin 2017-08-06 23:23:04 -07:00
parent e700b208bc
commit ea6635bdae
27 changed files with 779 additions and 91 deletions

View File

@ -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;

View File

@ -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.
*/

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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));

View File

@ -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().

View File

@ -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 "<no ref>";
}

View File

@ -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);
}

View File

@ -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.

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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.
*/

View File

@ -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.
*/

View File

@ -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);

View File

@ -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++) {

View File

@ -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 */

View File

@ -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;
}

View File

@ -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.
*

View File

@ -4,7 +4,85 @@
#include <assert.h>
#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) {

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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