Commit 98eabc1c authored by Lev Walkin's avatar Lev Walkin

a pass over OER constraints

parent b2284470
......@@ -40,7 +40,9 @@ static int compute_extensions_start(asn1p_expr_t *expr);
static int expr_break_recursion(arg_t *arg, asn1p_expr_t *expr);
static int expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr);
static int expr_elements_count(arg_t *arg, asn1p_expr_t *expr);
static int emit_single_member_OER_constraint(arg_t *arg, asn1cnst_range_t *range, char *type);
static int emit_single_member_PER_constraint(arg_t *arg, asn1cnst_range_t *range, int juscountvalues, char *type);
static int emit_member_OER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx);
static int emit_member_PER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx);
static int emit_member_table(arg_t *arg, asn1p_expr_t *expr);
static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier);
......@@ -1952,6 +1954,62 @@ PER_FROM_alphabet_characters(asn1cnst_range_t *range) {
return numchars;
}
static int
emit_single_member_OER_constraint(arg_t *arg, asn1cnst_range_t *range, char *type) {
if(!range) {
/* oer_support.h: asn_oer_constraint_s */
OUT("{ 0, 0, 0 }");
return 0;
}
if(range->incompatible || range->not_OER_visible) {
OUT("{ 0, 0, 0 }");
} else {
if(range->left.type == ARE_VALUE) {
if(range->right.type == ARE_VALUE) {
OUT("{ AOC_HAS_LOWER_BOUND | AOC_HAS_UPPER_BOUND, %" PRIdMAX
", %" PRIdMAX " }",
range->left.value, range->right.value);
} else {
OUT("{ AOC_HAS_LOWER_BOUND, %" PRIdMAX ", %" PRIdMAX " }",
range->left.value, range->right.value);
}
} else {
if(range->right.type == ARE_VALUE) {
OUT("{ AOC_HAS_UPPER_BOUND, %" PRIdMAX ", %" PRIdMAX " }",
range->left.value, range->right.value);
} else {
OUT("{ 0, %" PRIdMAX ", %" PRIdMAX " }", range->left.value,
range->right.value);
}
}
}
/*
* Print some courtesy debug information.
*/
if(range->left.type == ARE_VALUE
|| range->right.type == ARE_VALUE) {
OUT("\t/* ");
if(type) OUT("(%s", type);
OUT("(");
if(range->left.type == ARE_VALUE)
OUT("%" PRIdASN, range->left.value);
else
OUT("MIN");
OUT("..");
if(range->right.type == ARE_VALUE)
OUT("%" PRIdASN, range->right.value);
else
OUT("MAX");
if(range->extensible) OUT(",...");
if(type) OUT(")");
OUT(") */");
}
return 0;
}
static int
emit_single_member_PER_constraint(arg_t *arg, asn1cnst_range_t *range, int alphabetsize, char *type) {
if(!range || range->incompatible || range->not_PER_visible) {
......@@ -2069,6 +2127,55 @@ emit_single_member_PER_constraint(arg_t *arg, asn1cnst_range_t *range, int alpha
return 0;
}
static int
emit_member_OER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx) {
int save_target = arg->target->target;
asn1cnst_range_t *range;
asn1p_expr_type_e etype;
etype = expr_get_type(arg, expr);
if((arg->flags & A1C_GEN_OER)
&& (expr->constraints || etype == ASN_BASIC_ENUMERATED
|| etype == ASN_CONSTR_CHOICE)) {
/* Fall through */
} else {
return 0;
}
REDIR(OT_CTDEFS);
OUT("static asn_oer_constraints_t "
"asn_OER_%s_%s_constr_%d GCC_NOTUSED = {\n",
pfx, MKID(expr), expr->_type_unique_index);
INDENT(+1);
range = asn1constraint_compute_OER_range(etype, expr->combined_constraints,
ACT_EL_RANGE, 0, 0, 0);
if(emit_single_member_OER_constraint(arg, range, 0)) {
return -1;
}
asn1constraint_range_free(range);
OUT(",\n");
range = asn1constraint_compute_OER_range(etype, expr->combined_constraints,
ACT_CT_SIZE, 0, 0, 0);
if(emit_single_member_OER_constraint(arg, range, "SIZE")) {
return -1;
}
asn1constraint_range_free(range);
INDENT(-1);
OUT("};\n");
REDIR(save_target);
return 0;
}
static int
emit_member_PER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx) {
int save_target = arg->target->target;
......@@ -2545,6 +2652,9 @@ emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
OUT("}\n");
OUT("\n");
if(emit_member_OER_constraints(arg, expr, "memb"))
return -1;
if(emit_member_PER_constraints(arg, expr, "memb"))
return -1;
......
......@@ -698,8 +698,18 @@ _range_canonicalize(asn1cnst_range_t *range) {
return 0;
}
asn1cnst_range_t *
asn1constraint_compute_OER_range(asn1p_expr_type_e expr_type, const asn1p_constraint_t *ct, enum asn1p_constraint_type_e type, const asn1cnst_range_t *minmax, int *exmet, enum cpr_flags cpr_flags) {
return asn1constraint_compute_constraint_range(expr_type, ct, type, minmax, exmet, cpr_flags);
}
asn1cnst_range_t *
asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constraint_t *ct, enum asn1p_constraint_type_e type, const asn1cnst_range_t *minmax, int *exmet, enum cpr_flags cpr_flags) {
return asn1constraint_compute_constraint_range(expr_type, ct, type, minmax, exmet, cpr_flags);
}
asn1cnst_range_t *
asn1constraint_compute_constraint_range(asn1p_expr_type_e expr_type, const asn1p_constraint_t *ct, enum asn1p_constraint_type_e type, const asn1cnst_range_t *minmax, int *exmet, enum cpr_flags cpr_flags) {
asn1cnst_range_t *range;
asn1cnst_range_t *tmp;
asn1p_value_t *vmin;
......@@ -730,6 +740,10 @@ asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constr
*exmet = 1;
break;
case ACT_CT_FROM:
if(cpr_flags & CPR_strict_OER_visibility) {
errno = EINVAL;
return 0;
}
if(!minmax) {
minmax = asn1constraint_default_alphabet(expr_type);
if(minmax) {
......@@ -759,15 +773,27 @@ asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constr
/*
* X.691, #9.3.6
* Constraints on restricter character string types
* Constraints on restricted character string types
* which are not known-multiplier are not PER-visible.
*/
if((expr_type & ASN_STRING_NKM_MASK))
range->not_PER_visible = 1;
if(!ct
|| (range->not_PER_visible && (cpr_flags & CPR_strict_PER_visibility)))
return range;
if(!ct
|| (range->not_PER_visible && (cpr_flags & CPR_strict_PER_visibility)))
return range;
/*
* X.696 (08/2015), #8.2.2
* SIZE constraints on restricted character string types
* which are not known-multiplier are not OER-visible.
*/
if(type == ACT_CT_SIZE && (expr_type & ASN_STRING_NKM_MASK))
range->not_OER_visible = 1;
if(!ct
|| (range->not_OER_visible && (cpr_flags & CPR_strict_OER_visibility)))
return range;
switch(ct->type) {
case ACT_EL_VALUE:
......@@ -798,7 +824,7 @@ asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constr
return range;
}
assert(ct->el_count == 1);
tmp = asn1constraint_compute_PER_range(expr_type,
tmp = asn1constraint_compute_constraint_range(expr_type,
ct->elements[0], type, minmax, exmet, cpr_flags);
if(tmp) {
_range_free(range);
......@@ -817,7 +843,7 @@ asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constr
/* AND constraints, one after another. */
for(i = 0; i < ct->el_count; i++) {
tmp = asn1constraint_compute_PER_range(expr_type,
tmp = asn1constraint_compute_constraint_range(expr_type,
ct->elements[i], type,
ct->type==ACT_CA_SET?range:minmax, exmet,
cpr_flags);
......@@ -841,6 +867,15 @@ asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constr
continue;
}
if(tmp->not_OER_visible
&& (cpr_flags & CPR_strict_OER_visibility)) {
/*
* Ignore not OER-visible
*/
_range_free(tmp);
continue;
}
if(tmp->not_PER_visible
&& (cpr_flags & CPR_strict_PER_visibility)) {
if(ct->type == ACT_CA_SET) {
......@@ -878,7 +913,7 @@ asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constr
*/
tmp = 0;
for(i = 0; i < ct->el_count; i++) {
tmp = asn1constraint_compute_PER_range(expr_type,
tmp = asn1constraint_compute_constraint_range(expr_type,
ct->elements[i], type, minmax, exmet,
cpr_flags);
if(!tmp) {
......@@ -911,7 +946,7 @@ asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constr
* Canonicalizator will do the union magic.
*/
for(; i < ct->el_count; i++) {
tmp = asn1constraint_compute_PER_range(expr_type,
tmp = asn1constraint_compute_constraint_range(expr_type,
ct->elements[i], type, minmax, exmet,
cpr_flags);
if(!tmp) {
......@@ -945,14 +980,20 @@ asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constr
_range_canonicalize(range);
if(range->extensible && type == ACT_CT_FROM) {
/*
* X.691, #9.3.10:
* Extensible permitted alphabet constraints
* are not PER-visible.
*/
range->not_PER_visible = 1;
}
if(type == ACT_CT_FROM) {
/*
* X.696 permitted alphabet constraints are not OER-visible.
*/
range->not_OER_visible = 1;
if(range->extensible) {
/*
* X.691, #9.3.10:
* Extensible permitted alphabet constraints
* are not PER-visible.
*/
range->not_PER_visible = 1;
}
}
if(range->not_PER_visible
&& (cpr_flags & CPR_strict_PER_visibility)) {
......@@ -978,7 +1019,7 @@ asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constr
*/
assert(ct->el_count >= 1);
_range_free(range);
range = asn1constraint_compute_PER_range(expr_type,
range = asn1constraint_compute_constraint_range(expr_type,
ct->elements[0], type, minmax, exmet, cpr_flags);
return range;
default:
......
......@@ -24,11 +24,12 @@ typedef struct asn1cnst_range_s {
int extensible; /* Extension marker (...) is in effect. */
int incompatible; /* Constraint incompatible with argument */
int not_OER_visible; /* Contains not OER-visible components */
int not_PER_visible; /* Contains not PER-visible components */
} asn1cnst_range_t;
/*
* Compute the constraint range with variable PER visibility restrictions.
* Compute the constraint range with variable visibility restrictions.
*
* (expr_type) must have the type of the top-level parent ASN.1 type.
* (required_type) must be one of ACT_EL_RANGE, ACT_CT_SIZE or ACT_CT_FROM.
......@@ -40,15 +41,30 @@ typedef struct asn1cnst_range_s {
*/
enum cpr_flags {
CPR_noflags = 0x00,
CPR_strict_PER_visibility = 0x01,
CPR_simulate_fbless_SIZE = 0x02,
CPR_strict_OER_visibility = 0x01,
CPR_strict_PER_visibility = 0x02,
CPR_simulate_fbless_SIZE = 0x04,
};
asn1cnst_range_t *asn1constraint_compute_OER_range(asn1p_expr_type_e expr_type,
const asn1p_constraint_t *ct,
enum asn1p_constraint_type_e required_type,
const asn1cnst_range_t *minmax,
int *expectation_met,
enum cpr_flags);
asn1cnst_range_t *asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type,
const asn1p_constraint_t *ct,
enum asn1p_constraint_type_e required_type,
const asn1cnst_range_t *minmax,
int *expectation_met,
enum cpr_flags);
/* Base implementation */
asn1cnst_range_t *asn1constraint_compute_constraint_range(asn1p_expr_type_e expr_type,
const asn1p_constraint_t *ct,
enum asn1p_constraint_type_e required_type,
const asn1cnst_range_t *minmax,
int *expectation_met,
enum cpr_flags);
void asn1constraint_range_free(asn1cnst_range_t *);
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment