Commit 9de6cd89 authored by Lev Walkin's avatar Lev Walkin

using ioc constraints in run time

parent 9ec239e7
......@@ -33,7 +33,8 @@ enum onc_flags {
ONC_force_compound_name = 0x02,
};
static int out_name_chain(arg_t *arg, enum onc_flags);
static int asn1c_lang_C_type_SEQUENCE_def(arg_t *arg);
static int asn1c_lang_C_type_SEQUENCE_def(
arg_t *arg, asn1c_ioc_table_and_objset_t *);
static int asn1c_lang_C_type_SET_def(arg_t *arg);
static int asn1c_lang_C_type_CHOICE_def(arg_t *arg);
static int asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of);
......@@ -47,7 +48,8 @@ static int emit_single_member_OER_constraint_size(arg_t *arg, asn1cnst_range_t *
static int emit_single_member_PER_constraint(arg_t *arg, asn1cnst_range_t *range, int juscountvalues, const 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_member_table(arg_t *arg, asn1p_expr_t *expr,
asn1c_ioc_table_and_objset_t *);
static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier);
static int emit_include_dependencies(arg_t *arg);
static asn1p_expr_t *terminal_structable(arg_t *arg, asn1p_expr_t *expr);
......@@ -341,7 +343,7 @@ asn1c_lang_C_type_SEQUENCE(arg_t *arg) {
if(comp_mode == 1)
v->marker.flags |= EM_OMITABLE | EM_INDIRECT;
try_inline_default(arg, v, 1);
EMBED(v);
EMBED_WITH_IOCT(v, ioc_tao);
}
PCTX_DEF;
......@@ -364,11 +366,11 @@ asn1c_lang_C_type_SEQUENCE(arg_t *arg) {
arg->embed ? "" : "_t");
}
return asn1c_lang_C_type_SEQUENCE_def(arg);
return asn1c_lang_C_type_SEQUENCE_def(arg, ioc_tao.ioct ? &ioc_tao : 0);
}
static int
asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
asn1c_lang_C_type_SEQUENCE_def(arg_t *arg, asn1c_ioc_table_and_objset_t *opt_ioc) {
asn1p_expr_t *expr = arg->expr;
asn1p_expr_t *v;
int elements; /* Number of elements */
......@@ -420,7 +422,7 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
}
if(v->marker.flags & EM_OMITABLE)
comp_mode == 1 ? ++aoms_count : ++roms_count;
emit_member_table(arg, v);
emit_member_table(arg, v, opt_ioc);
elements++;
});
OUT("};\n");
......@@ -675,7 +677,7 @@ asn1c_lang_C_type_SET_def(arg_t *arg) {
if(v->expr_type == A1TC_EXTENSIBLE) {
if(comp_mode < 3) comp_mode++;
} else {
emit_member_table(arg, v);
emit_member_table(arg, v, NULL);
elements++;
}
});
......@@ -824,7 +826,7 @@ asn1c_lang_C_type_SEx_OF(arg_t *arg) {
expr, "Member", 0));
assert(tmp_memb.Identifier);
}
tmp.default_cb(&tmp);
tmp.default_cb(&tmp, NULL);
if(tmp_memb.Identifier != memb->Identifier)
if(0) free(tmp_memb.Identifier);
arg->embed--;
......@@ -901,7 +903,7 @@ asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
}
v->_anonymous_type = 1;
arg->embed++;
emit_member_table(arg, v);
emit_member_table(arg, v, NULL);
arg->embed--;
free(v->Identifier);
v->Identifier = (char *)NULL;
......@@ -1070,7 +1072,7 @@ asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
INDENTED(TQ_FOR(v, &(expr->members), next) {
if(v->expr_type == A1TC_EXTENSIBLE)
continue;
emit_member_table(arg, v);
emit_member_table(arg, v, NULL);
elements++;
});
OUT("};\n");
......@@ -1184,7 +1186,7 @@ asn1c_lang_C_type_REFERENCE(arg_t *arg) {
tmp.asn = arg->asn;
tmp.expr = extract;
ret = arg->default_cb(&tmp);
ret = arg->default_cb(&tmp, NULL);
asn1p_expr_free(extract);
......@@ -2586,7 +2588,210 @@ try_inline_default(arg_t *arg, asn1p_expr_t *expr, int out) {
}
static int
emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
emit_member_type_selector(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_objset_t *opt_ioc) {
int save_target = arg->target->target;
asn1p_expr_t *parent_expr = arg->expr;
const asn1p_constraint_t *crc =
asn1p_get_component_relation_constraint(expr->combined_constraints);
if(!crc || crc->el_count <= 1) {
/* Not an Open Type, it seems. */
OUT("0");
return 0;
}
if(crc->el_count <= 1 || crc->elements[0]->type != ACT_EL_VALUE
|| crc->elements[0]->value->type != ATV_REFERENCED
|| crc->elements[0]->value->value.reference->comp_count != 1) {
FATAL(
"Reference does not look like an object set");
return -1;
}
const char *objset_name =
crc->elements[0]->value->value.reference->components[0].name;
if(strcmp(objset_name, opt_ioc->objset->Identifier) != 0) {
FATAL("Object Set references do not match: %s != %s", objset_name,
opt_ioc->objset->Identifier);
return -1;
}
if(crc->el_count != 2 || crc->elements[1]->type != ACT_EL_VALUE
|| crc->elements[1]->value->type != ATV_REFERENCED
|| crc->elements[1]->value->value.reference->comp_count != 1) {
FATAL(
"Do not know how to handle complex IoS constraints (%d components "
"of constraint, %d components of reference %s) for %s at line "
"%d",
crc->el_count,
crc->el_count >= 2 && crc->elements[1]->type == ACT_EL_VALUE
&& crc->elements[1]->value->type == ATV_REFERENCED
? crc->elements[1]->value->value.reference->comp_count
: -1,
crc->el_count >= 2 && crc->elements[1]->type == ACT_EL_VALUE
&& crc->elements[1]->value->type == ATV_REFERENCED
? asn1p_ref_string(crc->elements[1]->value->value.reference)
: "?",
MKID(parent_expr), parent_expr->_lineno);
OUT("0");
return -1;
}
const asn1p_ref_t *cref = crc->elements[1]->value->value.reference;
const char *cname = cref->components[0].name;
if(cname[0] == '@' && cname[1] != '.') {
cname += 1;
} else if(cname[0] == '@' && cname[1] == '.' && cname[2] != '.') {
cname += 2;
} else {
FATAL("Complex IoS reference %s can not be processed",
asn1p_ref_string(cref));
OUT("0");
return -1;
}
assert(opt_ioc != NULL);
asn1p_expr_t *constraining_memb = NULL;
TQ_FOR(constraining_memb, &(parent_expr->members), next) {
if(strcmp(constraining_memb->Identifier, cname) == 0)
break;
}
if(!constraining_memb) {
FATAL("Can not find \"%s\" in %s at line %d", cname, MKID(parent_expr),
parent_expr->_lineno);
return -1;
}
if(constraining_memb->meta_type != AMT_TYPEREF
|| constraining_memb->expr_type != A1TC_REFERENCE
|| constraining_memb->reference->comp_count != 2
|| constraining_memb->reference->components[1].lex_type
!= RLT_Amplowercase) {
FATAL(
"Does not look like %s is a CLASS field reference (%s) on line "
"%d",
MKID(constraining_memb),
constraining_memb->reference
? asn1p_ref_string(constraining_memb->reference)
: "<no reference>",
constraining_memb->_lineno);
return -1;
}
const char *cfield = constraining_memb->reference->components[1].name;
ssize_t constraining_column = -1;
for(size_t cn = 0; cn < opt_ioc->ioct->rows ? opt_ioc->ioct->row[0]->columns : 0;
cn++) {
if(strcmp(cfield, opt_ioc->ioct->row[0]->column[cn].field->Identifier)
== 0) {
constraining_column = cn;
break;
}
}
if(constraining_column < 0) {
FATAL("Can not find referenced object class column %s\n", cfield);
return -1;
}
if(expr->meta_type != AMT_TYPEREF
|| expr->expr_type != A1TC_REFERENCE
|| expr->reference->comp_count != 2
|| expr->reference->components[1].lex_type
!= RLT_AmpUppercase) {
FATAL(
"Does not look like %s is a CLASS field reference (%s) denoting a type on line "
"%d",
MKID(expr),
expr->reference
? asn1p_ref_string(expr->reference)
: "<no reference>",
expr->_lineno);
return -1;
}
const char *for_field = expr->reference->components[1].name;
ssize_t for_column = -1;
for(size_t cn = 0; cn < opt_ioc->ioct->rows ? opt_ioc->ioct->row[0]->columns : 0;
cn++) {
if(strcmp(for_field,
opt_ioc->ioct->row[0]->column[cn].field->Identifier)
== 0) {
for_column = cn;
break;
}
}
if(for_column < 0) {
FATAL("Can not find referenced object class column %s\n", for_field);
return -1;
}
REDIR(OT_CODE);
OUT("static asn_TYPE_descriptor_t *\n");
OUT("select_%s_type(const asn_TYPE_descriptor_t *parent_type, const void *parent_sptr) {\n", MKID_safe(expr));
INDENT(+1);
OUT("asn_ioc_set_t *itable = asn_IOS_%s_%d;\n", MKID(opt_ioc->objset),
opt_ioc->objset->_type_unique_index);
OUT("size_t constraining_column = %zu; /* %s */\n", constraining_column, cfield);
OUT("size_t for_column = %zu; /* %s */\n", for_column, for_field);
OUT("size_t row;\n");
const char *tname = asn1c_type_name(arg, constraining_memb, TNF_SAFE);
if(constraining_memb->marker.flags & EM_INDIRECT) {
OUT("void *memb_ptr = *(const void **)");
OUT("((const char *)parent_sptr + offsetof(struct ");
out_name_chain(arg, ONC_avoid_keywords);
OUT(", %s));", MKID_safe(constraining_memb));
OUT("if(!memb_ptr) return NULL;\n");
OUT("\n");
}
switch(asn1c_type_fits_long(arg, constraining_memb)) {
case FL_NOTFIT:
OUT("const %s_t *constraining_value = (const %s_t *)", tname, tname);
break;
case FL_PRESUMED:
case FL_FITS_SIGNED:
OUT("const long *constraining_value = (const long *)");
break;
case FL_FITS_UNSIGN:
OUT("const unsigned long *constraining_value = (const unsigned long *)");
break;
}
if(constraining_memb->marker.flags & EM_INDIRECT) {
OUT("memb_ptr;\n");
} else {
OUT("((const char *)parent_sptr + offsetof(struct ");
out_name_chain(arg, ONC_avoid_keywords);
OUT(", %s));\n", MKID_safe(constraining_memb));
}
OUT("\n");
OUT("for(row=0; row < itable->rows_count; row++) {\n");
OUT(" asn_ioc_cell_s *constraining_cell = itable->rows[row * itable->columns_count + constraining_column];\n");
OUT(" asn_ioc_cell_s *type_cell = itable->rows[row * itable->columns_count + for_column];\n");
OUT(" if(constraining_cell->type_descriptor->struct_compare(constraining_cell->type_descriptor, constraining_value, constraining_cell->value_sptr) == 0) {\n");
OUT(" return type_cell->type_descriptor;\n");
OUT(" }\n");
OUT("}\n");
OUT("\n");
OUT("return NULL;\n");
INDENT(-1);
OUT("}\n");
OUT("\n");
REDIR(save_target);
OUT("select_%s_type", MKID_safe(expr));
return 0;
}
static int
emit_member_table(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_objset_t *opt_ioc) {
int save_target;
arg_t tmp_arg;
struct asn1p_type_tag_s outmost_tag_s;
......@@ -2675,6 +2880,16 @@ emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
OUT("%s", asn1c_type_name(arg, expr, TNF_SAFE));
}
OUT(",\n");
if(C99_MODE) OUT(".type_selector = ");
if(opt_ioc) {
emit_member_type_selector(arg, expr, opt_ioc);
} else {
OUT("0");
}
OUT(",\n");
if(C99_MODE) OUT(".memb_constraints = ");
if(expr->constraints) {
if(arg->flags & A1C_NO_CONSTRAINTS) {
......
......@@ -41,13 +41,15 @@
#include "asn1compiler.h"
struct asn1c_ioc_table_and_objset_s;
typedef struct arg_s {
enum asn1c_flags flags;
void (*logger_cb)(int _severity, const char *fmt, ...);
int (*default_cb)(struct arg_s *);
int (*default_cb)(struct arg_s *, const struct asn1c_ioc_table_and_objset_s *opt);
struct compiler_streams *target;
......
......@@ -223,7 +223,7 @@ emit_ioc_table(arg_t *arg, asn1p_expr_t *context, asn1c_ioc_table_and_objset_t i
(void)context;
GEN_INCLUDE_STD("asn_ioc");
REDIR(OT_STAT_DEFS);
REDIR(OT_IOC_TABLES);
/* Emit values that are used in the Information Object Set table first */
for(size_t rn = 0; rn < ioc_tao.ioct->rows; rn++) {
......
......@@ -21,6 +21,7 @@ typedef struct compiler_streams {
OT_TYPE_DECLS, /* Type declarations */
OT_FUNC_DECLS, /* Function declarations */
OT_POST_INCLUDE,/* #include after type definition */
OT_IOC_TABLES, /* Information Object Class tables */
OT_CTABLES, /* Constraint tables */
OT_CODE, /* Some code */
OT_CTDEFS, /* Constraint definitions */
......@@ -36,7 +37,7 @@ typedef struct compiler_streams {
} compiler_streams_t;
static char *_compiler_stream2str[] __attribute__ ((unused))
= { "IGNORE", "INCLUDES", "DEPS", "FWD-DECLS", "FWD-DEFS", "TYPE-DECLS", "FUNC-DECLS", "POST-INCLUDE", "CTABLES", "CODE", "CTDEFS", "STAT-DEFS" };
= { "IGNORE", "INCLUDES", "DEPS", "FWD-DECLS", "FWD-DEFS", "TYPE-DECLS", "FUNC-DECLS", "POST-INCLUDE", "IOC-TABLES", "CTABLES", "CODE", "CTDEFS", "STAT-DEFS" };
int asn1c_compiled_output(arg_t *arg, const char *fmt, ...);
......@@ -56,17 +57,26 @@ int asn1c_compiled_output(arg_t *arg, const char *fmt, ...);
INDENT(-1); \
} while(0)
#define EMBED(ev) do { \
#define EMBED(ev) \
do { \
arg->embed++; \
INDENTED(arg_t _tmp = *arg; _tmp.expr = ev; \
_tmp.default_cb(&_tmp, NULL);); \
arg->embed--; \
if(ev->expr_type != A1TC_EXTENSIBLE) OUT(";\n"); \
assert(arg->target->target == OT_TYPE_DECLS \
|| arg->target->target == OT_FWD_DEFS); \
} while(0)
#define EMBED_WITH_IOCT(ev, ioc) \
do { \
arg->embed++; \
INDENTED(arg_t _tmp = *arg; \
_tmp.expr = ev; \
_tmp.default_cb(&_tmp); \
); \
INDENTED(arg_t _tmp = *arg; _tmp.expr = ev; \
_tmp.default_cb(&_tmp, ((ioc).ioct ? &ioc : 0));); \
arg->embed--; \
if(ev->expr_type != A1TC_EXTENSIBLE) \
OUT(";\n"); \
assert(arg->target->target == OT_TYPE_DECLS || \
arg->target->target == OT_FWD_DEFS); \
if(ev->expr_type != A1TC_EXTENSIBLE) OUT(";\n"); \
assert(arg->target->target == OT_TYPE_DECLS \
|| arg->target->target == OT_FWD_DEFS); \
} while(0)
/* Output a piece of text into a default stream */
......
......@@ -303,6 +303,8 @@ asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *deps, int optc, char **argv) {
safe_fprintf(fp_c, "#include \"%s.h\"\n\n", filename);
if(arg->flags & A1C_NO_INCLUDE_DEPS)
SAVE_STREAM(fp_c, OT_POST_INCLUDE, "", 1);
TQ_FOR(ot, &(cs->destination[OT_IOC_TABLES].chunks), next)
safe_fwrite(ot->buf, ot->len, 1, fp_c);
TQ_FOR(ot, &(cs->destination[OT_CTABLES].chunks), next)
safe_fwrite(ot->buf, ot->len, 1, fp_c);
TQ_FOR(ot, &(cs->destination[OT_CODE].chunks), next)
......@@ -312,7 +314,7 @@ asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *deps, int optc, char **argv) {
TQ_FOR(ot, &(cs->destination[OT_STAT_DEFS].chunks), next)
safe_fwrite(ot->buf, ot->len, 1, fp_c);
assert(OT_MAX == 12); /* Protection from reckless changes */
assert(OT_MAX == 13); /* Protection from reckless changes */
fclose(fp_c);
fclose(fp_h);
......
......@@ -2,9 +2,10 @@
#include "asn1c_lang.h"
#include "asn1c_out.h"
#include "asn1c_save.h"
#include "asn1c_ioc.h"
static void default_logger_cb(int, const char *fmt, ...);
static int asn1c_compile_expr(arg_t *arg);
static int asn1c_compile_expr(arg_t *arg, const asn1c_ioc_table_and_objset_t *);
static int asn1c_attach_streams(asn1p_expr_t *expr);
static int asn1c_detach_streams(asn1p_expr_t *expr);
......@@ -42,7 +43,7 @@ asn1_compile(asn1p_t *asn, const char *datadir, enum asn1c_flags flags,
cs->target = OT_TYPE_DECLS;
arg->target = cs;
ret = asn1c_compile_expr(arg);
ret = asn1c_compile_expr(arg, NULL);
if(ret) {
FATAL("Cannot compile \"%s\" (%x:%x) at line %d",
arg->expr->Identifier,
......@@ -72,7 +73,7 @@ asn1_compile(asn1p_t *asn, const char *datadir, enum asn1c_flags flags,
}
static int
asn1c_compile_expr(arg_t *arg) {
asn1c_compile_expr(arg_t *arg, const asn1c_ioc_table_and_objset_t *opt_ioc) {
asn1p_expr_t *expr = arg->expr;
int (*type_cb)(arg_t *);
int ret;
......@@ -99,7 +100,7 @@ asn1c_compile_expr(arg_t *arg) {
for(i = 0; i<expr->specializations.pspecs_count; i++) {
arg->expr = expr->specializations
.pspec[i].my_clone;
ret = asn1c_compile_expr(arg);
ret = asn1c_compile_expr(arg, opt_ioc);
if(ret) break;
}
arg->expr = expr; /* Restore */
......
......@@ -1119,8 +1119,18 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
/* Fetch the member from the stream */
ASN_DEBUG("Decoding member %s in %s", elm->name, td->name);
if((elm->flags & ATF_OPEN_TYPE) && elm->type_selector) {
asn_TYPE_descriptor_t *et = elm->type_selector(td, st);
if(!et) {
FREEMEM(opres);
ASN__DECODE_FAILED;
}
rv = uper_open_type_get(opt_codec_ctx, et, NULL, memb_ptr2, pd);
} else {
rv = elm->type->uper_decoder(opt_codec_ctx, elm->type,
elm->per_constraints, memb_ptr2, pd);
}
if(rv.code != RC_OK) {
ASN_DEBUG("Failed decode %s in %s",
elm->name, td->name);
......
......@@ -91,7 +91,14 @@ typedef ber_tlv_tag_t (asn_outmost_tag_f)(
/* The instance of the above function type; used internally. */
asn_outmost_tag_f asn_TYPE_outmost_tag;
/*
* Fetch the desired type of the Open Type based on the
* Information Object Set driven constraints.
*/
typedef struct asn_TYPE_descriptor_s *(asn_type_selector_f)(
const struct asn_TYPE_descriptor_s *parent_type_descriptor,
const void *parent_structure_ptr);
/*
* The definitive description of the destination language's structure.
*/
......@@ -161,6 +168,7 @@ typedef struct asn_TYPE_member_s {
ber_tlv_tag_t tag; /* Outmost (most immediate) tag */
int tag_mode; /* IMPLICIT/no/EXPLICIT tag at current level */
asn_TYPE_descriptor_t *type; /* Member type descriptor */
asn_type_selector_f *type_selector; /* IoS selector */
asn_constr_check_f *memb_constraints; /* Constraints validator */
asn_oer_constraints_t *oer_constraints; /* OER compiled constraints */
asn_per_constraints_t *per_constraints; /* PER compiled constraints */
......
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