asn1c/libasn1fix/asn1fix_enum.c

137 lines
2.8 KiB
C

#include "asn1fix_internal.h"
/*
* Check the validity of an enumeration.
*/
int
asn1f_fix_enum(arg_t *arg) {
asn1p_expr_t *expr = arg->expr;
asn1p_expr_t *ev;
asn1_integer_t max_value = -1;
int rvalue = 0;
asn1p_expr_t *ext_marker = NULL; /* "..." position */
int ret;
if(expr->expr_type != ASN_BASIC_ENUMERATED)
return 0; /* Just ignore it */
DEBUG("%s(%s)", __func__, expr->Identifier);
/*
* 1. Scan the enumeration values in search for inconsistencies.
*/
TQ_FOR(ev, &(expr->members), next) {
asn1_integer_t eval;
if(ev->value)
DEBUG("\tItem %s(%s)", ev->Identifier,
asn1f_printable_value(ev->value));
else
DEBUG("\tItem %s", ev->Identifier);
/*
* 1.1 Found an extension mark "...", check correctness.
*/
if(ev->expr_type == A1TC_EXTENSIBLE) {
if(ext_marker) {
arg->eh(1,
"Enumeration %s at line %d: "
"Second extension marker is not allowed",
expr->Identifier,
ev->_lineno);
rvalue = -1;
} else {
/*
* Remember the marker's position.
*/
ext_marker = ev;
}
continue;
} else if(ev->Identifier == NULL
|| ev->expr_type != A1TC_UNIVERVAL) {
FATAL(
"Enumeration %s at line %d: "
"Unsupported enumeration element %s",
expr->Identifier,
ev->_lineno,
ev->Identifier?ev->Identifier:"<anonymous>");
rvalue = -1;
continue;
}
/*
* 1.2 Compute the value of the enumeration element.
*/
if(ev->value) {
switch(ev->value->type) {
case ATV_INTEGER:
eval = ev->value->value.v_integer;
break;
case ATV_REFERENCED:
FATAL("HERE HERE HERE", 1);
rvalue = -1;
continue;
break;
default:
FATAL("ENUMERATED type %s at line %d "
"contain element %s(%s) at line %d",
expr->Identifier, expr->_lineno,
ev->Identifier,
asn1f_printable_value(ev->value),
ev->_lineno);
rvalue = -1;
continue;
}
} else {
eval = max_value + 1;
ev->value = asn1p_value_fromint(eval);
if(ev->value == NULL) {
rvalue = -1;
continue;
}
}
/*
* 1.3 Check the applicability of this value.
*/
if(eval <= max_value) {
if(ext_marker) {
/*
* Enumeration is allowed to be unordered
* before the first marker.
*/
FATAL(
"Enumeration %s at line %d: "
"Explicit value \"%s(%lld)\" "
"is not greater "
"than previous values (max %lld)",
expr->Identifier,
ev->_lineno,
ev->Identifier,
eval,
max_value);
rvalue = -1;
}
} else if(eval > max_value) {
max_value = eval;
}
/*
* 1.4 Check that all identifiers before the current one
* differs from it.
*/
ret = asn1f_check_unique_expr_child(arg, ev, NULL);
RET2RVAL(ret, rvalue);
}
/*
* 2. Reorder the first half (before optional "...") of the
* identifiers alphabetically.
*/
// TODO
return rvalue;
}