new constraints generation method

This commit is contained in:
Lev Walkin 2004-08-20 13:37:01 +00:00
parent 2e3055da17
commit 59004fad9c
10 changed files with 322 additions and 212 deletions

View File

@ -1,7 +1,7 @@
AM_CPPFLAGS = \
-I${top_srcdir}/libasn1parser \
-I${top_srcdir}/libasn1fix
-I$(top_srcdir)/libasn1parser \
-I$(top_srcdir)/libasn1fix
noinst_LTLIBRARIES = libasn1compiler.la
@ -17,11 +17,3 @@ libasn1compiler_la_SOURCES = \
asn1c_compat.c asn1c_compat.h \
asn1c_fdeps.c asn1c_fdeps.h \
asn1c_internal.h
TESTS = $(check_PROGRAMS)
check_PROGRAMS = check_compiler
check_compiler_LDADD = $(noinst_LTLIBRARIES) \
$(top_builddir)/libasn1parser/libasn1parser.la \
$(top_builddir)/libasn1fix/libasn1fix.la

View File

@ -5,6 +5,8 @@
#include "asn1c_internal.h"
#include "asn1c_C.h"
#include "asn1c_constraint.h"
#include "asn1c_out.h"
#include "asn1c_misc.h"
#include <asn1fix_export.h> /* Stuff exported by libasn1fix */
typedef struct tag2el_s {
@ -17,6 +19,8 @@ typedef struct tag2el_s {
static int _fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no);
static int _add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no);
static int _expr_elements_count(arg_t *arg, asn1p_expr_t *expr);
static int _emit_member_table(arg_t *arg, asn1p_expr_t *expr);
static int asn1c_lang_C_type_SEQUENCE_def(arg_t *arg);
static int asn1c_lang_C_type_SET_def(arg_t *arg);
@ -27,7 +31,7 @@ static int check_if_extensible(asn1p_expr_t *expr);
static int emit_tags_vector(arg_t *arg, asn1p_expr_t *expr, int *tags_impl_skip, int choice_mode);
static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count);
#define C99_MODE (arg->flags & A1C_NO_C99)
#define C99_MODE (!(arg->flags & A1C_NO_C99))
#define UNNAMED_UNIONS (arg->flags & A1C_UNNAMED_UNIONS)
#define PCTX_DEF INDENTED( \
@ -176,7 +180,7 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
* Print out the table according to which the parsing is performed.
*/
p = MKID(expr->Identifier);
OUT("static asn1_SEQUENCE_element_t asn1_DEF_%s_elements[] = {\n", p);
OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
elements = 0;
INDENTED(TQ_FOR(v, &(expr->members), next) {
@ -187,43 +191,8 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
ext_stop = elements - 1;
continue;
}
OUT("{ ");
elements++;
OUT("offsetof(struct %s, ", MKID(expr->Identifier));
OUT("%s), ", MKID(v->Identifier));
if(v->marker) {
asn1p_expr_t *tv;
int opts = 0;
for(tv = v; tv && tv->marker;
tv = TQ_NEXT(tv, next), opts++) {
if(tv->expr_type == A1TC_EXTENSIBLE)
opts--;
}
OUT("%d,", opts);
} else {
OUT("0,");
}
OUT("\n");
INDENT(+1);
if(C99_MODE) OUT(".tag = ");
_print_tag(arg, v, NULL);
OUT(",\n");
if(C99_MODE) OUT(".tag_mode = ");
if(v->tag.tag_class) {
if(v->tag.tag_mode == TM_IMPLICIT)
OUT("-1,\t/* IMPLICIT tag at current level */\n");
else
OUT("+1,\t/* EXPLICIT tag at current level */\n");
} else {
OUT("0,\n");
}
if(C99_MODE) OUT(".type = ");
OUT("(void *)&asn1_DEF_%s,\n",
asn1c_type_name(arg, v, TNF_SAFE));
if(C99_MODE) OUT(".name = ");
OUT("\"%s\"\n", v->Identifier);
OUT("},\n");
INDENT(-1);
_emit_member_table(arg, v);
});
OUT("};\n");
@ -242,8 +211,6 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
INDENTED(
OUT("sizeof(struct %s),\n", p);
OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
OUT("asn1_DEF_%s_elements,\n", p);
OUT("%d,\t/* Elements count */\n", elements);
OUT("asn1_DEF_%s_tag2el,\n", p);
OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
OUT("%d,\t/* Start extensions */\n",
@ -272,6 +239,8 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
}
OUT("%d,\t/* Tags to skip */\n", tags_impl_skip);
OUT("%d,\t/* Whether CONSTRUCTED */\n", 1);
OUT("asn1_MBR_%s,\n", p);
OUT("%d,\t/* Elements count */\n", elements);
OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
);
OUT("};\n");
@ -405,48 +374,19 @@ asn1c_lang_C_type_SET_def(arg_t *arg) {
* Print out the table according to which the parsing is performed.
*/
p = MKID(expr->Identifier);
OUT("static asn1_SET_element_t asn1_DEF_%s_elements[] = {\n", p);
OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
elements = 0;
INDENTED(TQ_FOR(v, &(expr->members), next) {
if(v->expr_type != A1TC_EXTENSIBLE) {
if(comp_mode == 1)
v->marker = EM_OPTIONAL;
elements++;
} else {
if(comp_mode < 3) comp_mode++;
continue;
}
OUT("{ ");
p = MKID(expr->Identifier);
OUT("offsetof(struct %s, ", p);
p = MKID(v->Identifier);
OUT("%s), ", p);
if(v->marker) {
OUT("1, /* Optional element */\n");
} else {
OUT("0,\n");
}
INDENT(+1);
if(C99_MODE) OUT(".tag = ");
_print_tag(arg, v, NULL);
OUT(",\n");
if(C99_MODE) OUT(".tag_mode = ");
if(v->tag.tag_class) {
if(v->tag.tag_mode == TM_IMPLICIT)
OUT("-1,\t/* IMPLICIT tag at current level */\n");
else
OUT("+1,\t/* EXPLICIT tag at current level */\n");
} else {
OUT("0,\n");
}
if(C99_MODE) OUT(".type = ");
OUT("(void *)&asn1_DEF_%s,\n",
asn1c_type_name(arg, v, TNF_SAFE));
if(C99_MODE) OUT(".name = ");
OUT("\"%s\"\n", v->Identifier);
OUT("},\n");
INDENT(-1);
elements++;
_emit_member_table(arg, v);
});
OUT("};\n");
@ -496,8 +436,6 @@ asn1c_lang_C_type_SET_def(arg_t *arg) {
OUT("sizeof(struct %s),\n", p);
OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
OUT("offsetof(struct %s, _presence_map),\n", p);
OUT("asn1_DEF_%s_elements,\n", p);
OUT("%d,\t/* Elements count */\n", elements);
OUT("asn1_DEF_%s_tag2el,\n", p);
OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
OUT("%d,\t/* Whether extensible */\n",
@ -525,6 +463,8 @@ asn1c_lang_C_type_SET_def(arg_t *arg) {
}
OUT("%d,\t/* Tags to skip */\n", tags_impl_skip);
OUT("%d,\t/* Whether CONSTRUCTED */\n", 1);
OUT("asn1_MBR_%s,\n", p);
OUT("%d,\t/* Elements count */\n", elements);
OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
);
OUT("};\n");
@ -589,20 +529,11 @@ asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
* Print out the table according to which the parsing is performed.
*/
p = MKID(expr->Identifier);
OUT("static asn1_SET_OF_element_t asn1_DEF_%s_elements[] = {\n", p);
OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
INDENTED(OUT("{ ");
INDENTED(
v = TQ_FIRST(&(expr->members));
INDENT(+1);
if(C99_MODE) OUT(".tag = ");
_print_tag(arg, v, NULL);
OUT(",\n");
if(C99_MODE) OUT(".type = ");
OUT("(void *)&asn1_DEF_%s",
asn1c_type_name(arg, v, TNF_SAFE));
OUT(" ");
OUT("},\n");
INDENT(-1);
_emit_member_table(arg, v);
);
OUT("};\n");
@ -616,7 +547,6 @@ asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
INDENTED(
OUT("sizeof(struct %s),\n", p);
OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
OUT("asn1_DEF_%s_elements\n", p);
);
OUT("};\n");
OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
@ -647,6 +577,8 @@ asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
}
OUT("%d,\t/* Tags to skip */\n", tags_impl_skip);
OUT("%d,\t/* Whether CONSTRUCTED */\n", 1);
OUT("asn1_MBR_%s,\n", p);
OUT("1,\t/* Single element */\n");
OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
);
OUT("};\n");
@ -742,49 +674,19 @@ asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
* Print out the table according to which the parsing is performed.
*/
p = MKID(expr->Identifier);
OUT("static asn1_CHOICE_element_t asn1_DEF_%s_elements[] = {\n", p);
OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
elements = 0;
INDENTED(TQ_FOR(v, &(expr->members), next) {
if(v->expr_type != A1TC_EXTENSIBLE) {
if(comp_mode == 1)
v->marker = EM_OPTIONAL;
elements++;
} else {
if(comp_mode < 3) comp_mode++;
continue;
}
OUT("{ ");
p = MKID(expr->Identifier);
OUT("offsetof(struct %s, ", p);
p = MKID(v->Identifier);
if(!UNNAMED_UNIONS) OUT("choice.");
OUT("%s), ", p);
if(v->marker) {
OUT("1, /* Optional element */\n");
} else {
OUT("0,\n");
}
INDENT(+1);
if(C99_MODE) OUT(".tag = ");
_print_tag(arg, v, NULL);
OUT(",\n");
if(C99_MODE) OUT(".tag_mode = ");
if(v->tag.tag_class) {
if(v->tag.tag_mode == TM_IMPLICIT)
OUT("-1,\t/* IMPLICIT tag at current level */\n");
else
OUT("+1,\t/* EXPLICIT tag at current level */\n");
} else {
OUT("0,\n");
}
if(C99_MODE) OUT(".type = ");
OUT("(void *)&asn1_DEF_%s,\n",
asn1c_type_name(arg, v, TNF_SAFE));
if(C99_MODE) OUT(".name = ");
OUT("\"%s\"\n", v->Identifier);
OUT("},\n");
INDENT(-1);
elements++;
_emit_member_table(arg, v);
});
OUT("};\n");
@ -810,8 +712,6 @@ asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
OUT("offsetof(struct %s, present),\n", p);
OUT("sizeof(((struct %s *)0)->present),\n", p);
OUT("asn1_DEF_%s_elements,\n", p);
OUT("%d,\t/* Elements count */\n", elements);
OUT("asn1_DEF_%s_tag2el,\n", p);
OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
OUT("%d\t/* Whether extensible */\n",
@ -838,6 +738,8 @@ asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
}
OUT("%d,\t/* Tags to skip */\n", tags_impl_skip);
OUT("%d,\t/* Whether CONSTRUCTED */\n", 1);
OUT("asn1_MBR_%s,\n", p);
OUT("%d,\t/* Elements count */\n", elements);
OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
);
OUT("};\n");
@ -910,6 +812,8 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
if(expr->marker) OUT("\t/* %s */",
(expr->marker==EM_OPTIONAL)?"OPTIONAL":"DEFAULT");
OUT("\n");
REDIR(OT_TYPE_DECLS);
return 0;
}
@ -951,17 +855,20 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
}
OUT("%d,\t/* Tags to skip */\n", tags_impl_skip);
OUT("-0,\t/* Unknown yet */\n");
if(_expr_elements_count(arg, expr))
OUT("0, 0,\t/* Defined elsewhere */\n");
else
OUT("0, 0,\t/* No members */\n");
OUT("0\t/* No specifics */\n");
);
OUT("};\n");
OUT("\n");
REDIR(OT_CODE);
/*
* Constraint checking.
*/
/* Emit FROM() tables and others */
asn1c_emit_constraint_tables(arg, 0);
p = MKID(expr->Identifier);
OUT("int\n");
OUT("%s_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p);
@ -990,37 +897,41 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
* Emit suicidal functions.
*/
{
/*
* This function replaces certain fields from the definition
* of a type with the corresponding fields from the basic type
* (from which the current type is inherited).
*/
char *type_name = asn1c_type_name(arg, expr, TNF_SAFE);
OUT("/*\n");
OUT(" * This type is implemented using %s,\n", type_name);
OUT(" * This type is implemented using %s,\n",
asn1c_type_name(arg, expr, TNF_SAFE));
OUT(" * so adjust the DEF appropriately.\n");
OUT(" */\n");
OUT("static void\n");
OUT("inherit_TYPE_descriptor(asn1_TYPE_descriptor_t *td) {\n");
p = MKID(expr->Identifier);
OUT("%s_inherit_TYPE_descriptor(asn1_TYPE_descriptor_t *td) {\n", p);
INDENT(+1);
OUT("td->ber_decoder = asn1_DEF_%s.ber_decoder;\n", type_name);
OUT("td->der_encoder = asn1_DEF_%s.der_encoder;\n", type_name);
OUT("td->free_struct = asn1_DEF_%s.free_struct;\n", type_name);
OUT("td->print_struct = asn1_DEF_%s.print_struct;\n", type_name);
OUT("td->last_tag_form = asn1_DEF_%s.last_tag_form;\n", type_name);
OUT("td->specifics = asn1_DEF_%s.specifics;\n", type_name);
{
char *type_name = asn1c_type_name(arg, expr, TNF_SAFE);
OUT("td->ber_decoder = asn1_DEF_%s.ber_decoder;\n", type_name);
OUT("td->der_encoder = asn1_DEF_%s.der_encoder;\n", type_name);
OUT("td->free_struct = asn1_DEF_%s.free_struct;\n", type_name);
OUT("td->print_struct = asn1_DEF_%s.print_struct;\n", type_name);
OUT("td->last_tag_form = asn1_DEF_%s.last_tag_form;\n", type_name);
OUT("td->elements = asn1_DEF_%s.elements;\n", type_name);
OUT("td->elements_count = asn1_DEF_%s.elements_count;\n", type_name);
OUT("td->specifics = asn1_DEF_%s.specifics;\n", type_name);
}
INDENT(-1);
OUT("}\n");
OUT("\n");
}
p = MKID(expr->Identifier);
OUT("ber_dec_rval_t\n");
OUT("%s_decode_ber(asn1_TYPE_descriptor_t *td,\n", p);
INDENTED(
OUT("\tvoid **structure, void *bufptr, size_t size, int tag_mode) {\n");
OUT("inherit_TYPE_descriptor(td);\n");
OUT("%s_inherit_TYPE_descriptor(td);\n", p);
OUT("return td->ber_decoder(td, structure,\n");
OUT("\tbufptr, size, tag_mode);\n");
);
@ -1033,7 +944,7 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
INDENTED(
OUT("\tvoid *structure, int tag_mode, ber_tlv_tag_t tag,\n");
OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
OUT("inherit_TYPE_descriptor(td);\n");
OUT("%s_inherit_TYPE_descriptor(td);\n", p);
OUT("return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);\n");
);
OUT("}\n");
@ -1044,7 +955,7 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
OUT("%s_print(asn1_TYPE_descriptor_t *td, const void *struct_ptr,\n", p);
INDENTED(
OUT("\tint ilevel, asn_app_consume_bytes_f *cb, void *app_key) {\n");
OUT("inherit_TYPE_descriptor(td);\n");
OUT("%s_inherit_TYPE_descriptor(td);\n", p);
OUT("return td->print_struct(td, struct_ptr, ilevel, cb, app_key);\n");
);
OUT("}\n");
@ -1055,7 +966,7 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
OUT("%s_free(asn1_TYPE_descriptor_t *td,\n", p);
INDENTED(
OUT("\tvoid *struct_ptr, int contents_only) {\n");
OUT("inherit_TYPE_descriptor(td);\n");
OUT("%s_inherit_TYPE_descriptor(td);\n", p);
OUT("td->free_struct(td, struct_ptr, contents_only);\n");
);
OUT("}\n");
@ -1355,3 +1266,112 @@ emit_tags_vector(arg_t *arg, asn1p_expr_t *expr, int *tags_impl_skip, int choice
return tags_count;
}
static int
_expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
asn1p_expr_t *topmost_parent;
asn1p_expr_t *v;
int elements = 0;
topmost_parent = asn1f_find_terminal_type_ex(arg->asn,
arg->mod, expr, 0);
if(!topmost_parent) return 0;
if(!(topmost_parent->expr_type & ASN_CONSTR_MASK))
return 0;
TQ_FOR(v, &(topmost_parent->members), next) {
if(v->expr_type != A1TC_EXTENSIBLE)
elements++;
}
return elements;
}
static int
_emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
int save_target;
arg_t tmp_arg;
char *p;
OUT("{ ");
if(expr->marker) {
asn1p_expr_t *tv;
int opts = 0;
for(tv = expr; tv && tv->marker;
tv = TQ_NEXT(tv, next), opts++) {
if(tv->expr_type == A1TC_EXTENSIBLE)
opts--;
}
OUT("%d, ", opts);
} else {
OUT("0, ");
}
if(expr->Identifier) {
OUT("offsetof(struct %s, ", MKID(arg->expr->Identifier));
if(arg->expr->expr_type == ASN_CONSTR_CHOICE
&& (!UNNAMED_UNIONS)) OUT("choice.");
OUT("%s),\n", MKID(expr->Identifier));
} else {
assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
|| arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
OUT("0,\n");
}
INDENT(+1);
if(C99_MODE) OUT(".tag = ");
_print_tag(arg, expr , NULL);
OUT(",\n");
if(C99_MODE) OUT(".tag_mode = ");
if(expr->tag.tag_class) {
if(expr->tag.tag_mode == TM_IMPLICIT)
OUT("-1,\t/* IMPLICIT tag at current level */\n");
else
OUT("+1,\t/* EXPLICIT tag at current level */\n");
} else {
OUT("0,\n");
}
if(C99_MODE) OUT(".type = ");
OUT("(void *)&asn1_DEF_%s,\n",
asn1c_type_name(arg, expr, TNF_SAFE));
if(C99_MODE) OUT(".memb_constraints = ");
if(expr->constraints) {
p = MKID(expr->Identifier);
if(!expr->Identifier)
p = asn1c_type_name(arg, expr, TNF_SAFE);
OUT("memb_%s_constraint,\n", p);
} else {
OUT("0,\t/* Defer to actual type */\n");
}
if(C99_MODE) OUT(".name = ");
OUT("\"%s\"\n", expr->Identifier ? expr->Identifier : "");
OUT("},\n");
INDENT(-1);
if(!expr->constraints)
return 0;
save_target = arg->target->target;
REDIR(OT_CODE);
if(expr->Identifier)
p = MKID(expr->Identifier);
else
p = asn1c_type_name(arg, expr, TNF_SAFE);
OUT("static int\n");
OUT("memb_%s_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p);
INDENT(+1);
OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
tmp_arg = *arg;
tmp_arg.expr = expr;
if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
OUT("return td->check_constraints\n");
OUT("\t(td, sptr, app_errlog, app_key);\n");
}
INDENT(-1);
OUT("}\n");
OUT("\n");
REDIR(save_target);
return 0;
}

View File

@ -1,9 +1,12 @@
#include "asn1c_internal.h"
#include "asn1c_constraint.h"
#include "asn1c_misc.h"
#include "asn1c_out.h"
#include <asn1fix_crange.h> /* constraint groker from libasn1fix */
#include <asn1fix_export.h> /* other exportable stuff from libasn1fix */
static int asn1c_emit_constraint_tables(arg_t *arg, int got_size);
static int emit_alphabet_check_loop(arg_t *arg, asn1cnst_range_t *range);
static int emit_value_determination_code(arg_t *arg, asn1p_expr_type_e etype);
static int emit_size_determination_code(arg_t *arg, asn1p_expr_type_e etype);
@ -22,6 +25,7 @@ asn1c_emit_constraint_checking_code(arg_t *arg) {
asn1p_expr_type_e etype;
asn1p_constraint_t *ct;
int got_something = 0;
int produce_st = 0;
ct = expr->combined_constraints;
if(ct == NULL)
@ -57,6 +61,24 @@ asn1c_emit_constraint_checking_code(arg_t *arg) {
}
}
/*
* Do we really need an "*st = sptr" pointer?
*/
switch(etype) {
case ASN_BASIC_INTEGER:
case ASN_BASIC_ENUMERATED:
if(!(arg->flags & A1C_USE_NATIVE_INTEGERS))
produce_st = 1;
break;
case ASN_BASIC_OCTET_STRING:
produce_st = 1;
break;
default:
if(etype & ASN_STRING_MASK)
produce_st = 1;
break;
}
if(produce_st)
OUT("const %s_t *st = sptr;\n", MKID(arg->expr->Identifier));
if(r_size || r_value) {
@ -96,6 +118,13 @@ asn1c_emit_constraint_checking_code(arg_t *arg) {
if(r_size)
emit_size_determination_code(arg, etype);
INDENT(-1);
REDIR(OT_CTABLES);
/* Emit FROM() tables */
asn1c_emit_constraint_tables(arg, r_size?1:0);
REDIR(OT_CODE);
INDENT(+1);
/*
* Here is an if() {} else {} constaint checking code.
*/
@ -126,6 +155,12 @@ asn1c_emit_constraint_checking_code(arg_t *arg) {
}
if(!got_something) {
OUT("1 /* No applicable constraints whatsoever */");
OUT(") {\n");
INDENT(-1);
INDENTED(OUT("/* Nothing is here. See below */\n"));
OUT("}\n");
OUT("\n");
return 1;
}
INDENT(-1);
OUT(") {\n");
@ -144,16 +179,19 @@ asn1c_emit_constraint_checking_code(arg_t *arg) {
return 0;
}
int
asn1c_emit_constraint_tables(arg_t *arg, asn1p_constraint_t *ct) {
static int
asn1c_emit_constraint_tables(arg_t *arg, int got_size) {
asn1_integer_t range_start;
asn1_integer_t range_stop;
asn1p_expr_type_e etype;
asn1cnst_range_t *range;
asn1p_constraint_t *ct;
int utf8_full_alphabet_check = 0;
int max_table_size = 256;
int table[256];
int use_table;
if(!ct) ct = arg->expr->combined_constraints;
ct = arg->expr->combined_constraints;
if(!ct) return 0;
etype = _find_terminal_type(arg);
@ -180,10 +218,21 @@ asn1c_emit_constraint_tables(arg_t *arg, asn1p_constraint_t *ct) {
* Check if we need a test table to check the alphabet.
*/
use_table = 1;
if(range->el_count == 0) {
/*
* It's better to have a short if() check
* than waste 4k of table space
*/
use_table = 0;
}
if((range_stop - range_start) > 255)
use_table = 0;
if(range->el_count == 0)
use_table = 0;
if(etype == ASN_STRING_UTF8String) {
if(range_stop >= 0x80)
use_table = 0;
else
max_table_size = 128;
}
if(!ct->_compile_mark)
ct->_compile_mark = ++global_compile_mark;
@ -203,15 +252,15 @@ asn1c_emit_constraint_tables(arg_t *arg, asn1p_constraint_t *ct) {
}
for(v = r->left.value; v <= r->right.value; v++) {
assert((v - range_start) >= 0);
assert((v - range_start) < 256);
assert((v - range_start) < max_table_size);
table[v - range_start] = ++n;
}
}
OUT("static int permitted_alphabet_table_%d[256] = {\n",
ct->_compile_mark);
untl = (range_stop - range_start) + 1;
untl += (untl % 16)?16 - (untl % 16):0;
OUT("static int permitted_alphabet_table_%d[%d] = {\n",
ct->_compile_mark, max_table_size);
for(n = 0; n < untl; n++) {
OUT("%d,", table[n]?1:0);
if(!((n+1) % 16)) {
@ -238,11 +287,42 @@ asn1c_emit_constraint_tables(arg_t *arg, asn1p_constraint_t *ct) {
}
OUT("};\n");
OUT("\n");
} else if(etype == ASN_STRING_UTF8String) {
/*
* UTF8String type is a special case in many respects.
*/
assert(range_stop > 255); /* This one's unobvious */
if(got_size) {
/*
* Size has been already determined.
* The UTF8String length checker also checks
* for the syntax validity, so we don't have
* to repeat this process twice.
*/
ct->_compile_mark = 0; /* Don't generate code */
asn1constraint_range_free(range);
return 0;
} else {
utf8_full_alphabet_check = 1;
}
} else {
/*
* This permitted alphabet check will be
* expressed using conditional statements
* instead of table lookups. Table would be
* to large or otherwise inappropriate (too sparse?).
*/
}
OUT("static int check_permitted_alphabet_%d(const void *sptr) {\n",
ct->_compile_mark);
INDENT(+1);
INDENT(+1);
if(utf8_full_alphabet_check) {
OUT("if(UTF8String_length((UTF8String_t *)sptr, td->name, \n");
OUT("\tapp_errlog, app_key) == -1)\n");
OUT("\t\treturn 0; /* Alphabet (sic!) test failed. */\n");
OUT("\n");
} else {
if(use_table) {
OUT("int *table = permitted_alphabet_table_%d;\n",
ct->_compile_mark);
@ -250,8 +330,9 @@ asn1c_emit_constraint_tables(arg_t *arg, asn1p_constraint_t *ct) {
} else {
emit_alphabet_check_loop(arg, range);
}
OUT("return 1;\n");
INDENT(-1);
}
OUT("return 1;\n");
INDENT(-1);
OUT("}\n");
OUT("\n");
@ -338,6 +419,7 @@ static int
emit_range_comparison_code(arg_t *arg, asn1cnst_range_t *range, const char *varname, asn1_integer_t natural_start, asn1_integer_t natural_stop) {
int ignore_left;
int ignore_right;
int generated_something = 0;
int i;
for(i = -1; i < range->el_count; i++) {
@ -381,9 +463,10 @@ emit_range_comparison_code(arg_t *arg, asn1cnst_range_t *range, const char *varn
(long long)r->right.value);
}
if(r != range) OUT(")");
generated_something = 1;
}
return 0;
return generated_something;
}
static int
@ -412,16 +495,18 @@ emit_size_determination_code(arg_t *arg, asn1p_expr_type_e etype) {
case ASN_CONSTR_SEQUENCE_OF:
OUT("{ /* Determine the number of elements */\n");
INDENT(+1);
OUT("A_%s_OF(void) *list;\n",
OUT("const A_%s_OF(void) *list;\n",
etype==ASN_CONSTR_SET_OF?"SET":"SEQUENCE");
OUT("(void *)list = st;\n");
OUT("(const void *)list = sptr;\n");
OUT("size = list->count;\n");
INDENT(-1);
OUT("}\n");
break;
case ASN_BASIC_OCTET_STRING:
OUT("size = st->size;\n");
break;
default:
if((etype & ASN_STRING_MASK)
|| etype == ASN_BASIC_OCTET_STRING) {
if(etype & ASN_STRING_MASK) {
OUT("size = st->size;\n");
break;
} else {
@ -446,7 +531,7 @@ emit_value_determination_code(arg_t *arg, asn1p_expr_type_e etype) {
case ASN_BASIC_INTEGER:
case ASN_BASIC_ENUMERATED:
if(arg->flags & A1C_USE_NATIVE_INTEGERS) {
OUT("value = *(int *)st;\n");
OUT("value = *(int *)sptr;\n");
} else {
OUT("if(asn1_INTEGER2long(st, &value)) {\n");
INDENT(+1);
@ -458,7 +543,7 @@ emit_value_determination_code(arg_t *arg, asn1p_expr_type_e etype) {
}
break;
case ASN_BASIC_BOOLEAN:
OUT("value = (*(int *)st) ? 1 : 0;\n");
OUT("value = (*(int *)sptr) ? 1 : 0;\n");
break;
default:
WARNING("Value cannot be determined "

View File

@ -1,7 +1,6 @@
#ifndef _ASN1C_CONSTRAINT_H_
#define _ASN1C_CONSTRAINT_H_
int asn1c_emit_constraint_tables(arg_t *arg, asn1p_constraint_t *ct);
int asn1c_emit_constraint_checking_code(arg_t *arg);
#endif /* _ASN1C_CONSTRAINT_H_ */

View File

@ -33,16 +33,9 @@ typedef struct arg_s {
asn1p_module_t *mod;
asn1p_expr_t *expr;
int indent_level;
int indented;
int embed;
} arg_t;
#include "asn1c_lang.h" /* Target language initialization */
#include "asn1c_misc.h" /* Miscellaneous functions */
#include "asn1c_out.h" /* Handle output during compilation */
#include "asn1c_save.h" /* Save compiled output */
/*
* Logging.
*/

View File

@ -1,4 +1,6 @@
#include "asn1c_internal.h"
#include "asn1c_misc.h"
#include <asn1fix_export.h>
/*

View File

@ -1,4 +1,5 @@
#include "asn1c_internal.h"
#include "asn1c_out.h"
/*
* Add an elementary chunk of target language text
@ -6,6 +7,7 @@
*/
int
asn1c_compiled_output(arg_t *arg, const char *fmt, ...) {
struct compiler_stream_destination_s *dst;
const char *p;
int lf_found;
va_list ap;
@ -20,6 +22,7 @@ asn1c_compiled_output(arg_t *arg, const char *fmt, ...) {
assert(arg->target->target != OT_ASSERT);
return -1;
default:
dst = &arg->target->destination[arg->target->target];
break;
}
@ -37,16 +40,16 @@ asn1c_compiled_output(arg_t *arg, const char *fmt, ...) {
/*
* Print out the indentation.
*/
if(arg->indented == 0) {
int i = arg->indent_level;
arg->indented = 1;
if(dst->indented == 0) {
int i = dst->indent_level;
dst->indented = 1;
while(i--) {
ret = asn1c_compiled_output(arg, "\t");
if(ret == -1) return -1;
}
}
if(lf_found)
arg->indented = 0;
dst->indented = 0;
/*
* Estimate necessary size.
@ -80,7 +83,7 @@ asn1c_compiled_output(arg_t *arg, const char *fmt, ...) {
if(arg->target->target == OT_INCLUDES) {
out_chunk_t *v;
TQ_FOR(v, &(arg->target->targets[OT_INCLUDES]), next) {
TQ_FOR(v, &dst->chunks, next) {
if(m->len == v->len
&& !memcmp(m->buf, v->buf, m->len))
break;
@ -93,7 +96,7 @@ asn1c_compiled_output(arg_t *arg, const char *fmt, ...) {
}
}
TQ_ADD(&(arg->target->targets[arg->target->target]), m, next);
TQ_ADD(&dst->chunks, m, next);
return 0;
}

View File

@ -19,15 +19,21 @@ typedef struct compiler_streams {
OT_DEPS, /* Dependencies (other than #includes) */
OT_TYPE_DECLS, /* Type declarations */
OT_FUNC_DECLS, /* Function declarations */
OT_STAT_DEFS, /* Static definitions */
OT_CTABLES, /* Constraint tables */
OT_CODE, /* Some code */
OT_STAT_DEFS, /* Static definitions */
OT_MAX
} target;
TQ_HEAD(out_chunk_t) targets[OT_MAX];
struct compiler_stream_destination_s {
TQ_HEAD(out_chunk_t) chunks;
int indent_level;
int indented;
} destination[OT_MAX];
} compiler_streams_t;
static char *_compiler_stream2str[] __attribute__ ((unused))
= { "ASSERT", "INCLUDES", "DEPS", "TYPE-DECLS", "FUNC-DECLS", "STAT-DEFS", "CODE" };
= { "ASSERT", "INCLUDES", "DEPS", "TYPE-DECLS", "FUNC-DECLS", "CTABLES", "CODE", "STAT-DEFS" };
int asn1c_compiled_output(arg_t *arg, const char *fmt, ...);
@ -38,19 +44,20 @@ int asn1c_compiled_output(arg_t *arg, const char *fmt, ...);
/* Redirect output to a different stream. */
#define REDIR(foo) do { arg->target->target = foo; } while(0)
#define INDENT(val) arg->indent_level += (val)
#define INDENTED(code) do { \
INDENT(+1); \
do { code; } while(0); \
INDENT(-1); \
#define INDENT_LEVEL \
arg->target->destination[arg->target->target].indent_level
#define INDENT(val) INDENT_LEVEL += (val)
#define INDENTED(code) do { \
INDENT(+1); \
do { code; } while(0); \
INDENT(-1); \
} while(0)
#define FLAT(code) do { \
int _il = arg->indent_level; \
arg->indent_level = 0; \
do { code; } while(0); \
arg->indent_level = _il; \
#define FLAT(code) do { \
int _il = INDENT_LEVEL; \
INDENT_LEVEL = 0; \
do { code; } while(0); \
INDENT_LEVEL = _il; \
} while(0)
#define EMBED(ev) do { \
@ -68,11 +75,11 @@ int asn1c_compiled_output(arg_t *arg, const char *fmt, ...);
/* Output a piece of text into a default stream */
#define OUT(fmt, args...) asn1c_compiled_output(arg, fmt, ##args)
#define OUT_NOINDENT(fmt, args...) do { \
int _saved_indent = arg->indent_level; \
arg->indent_level = 0; \
OUT(fmt, ##args); \
arg->indent_level = _saved_indent; \
#define OUT_NOINDENT(fmt, args...) do { \
int _saved_indent = INDENT_LEVEL; \
INDENT_LEVEL = 0; \
OUT(fmt, ##args); \
INDENT_LEVEL = _saved_indent; \
} while(0)
/* Generate #include line */

View File

@ -1,6 +1,10 @@
#include "asn1c_internal.h"
#include "asn1c_compat.h"
#include "asn1c_fdeps.h"
#include "asn1c_lang.h"
#include "asn1c_misc.h"
#include "asn1c_save.h"
#include "asn1c_out.h"
static int asn1c_dump_streams(arg_t *arg, asn1c_fdeps_t *);
static int asn1c_print_streams(arg_t *arg);
@ -114,14 +118,14 @@ asn1c_print_streams(arg_t *arg) {
for(i = 1; i < OT_MAX; i++) {
out_chunk_t *ot;
if(TQ_FIRST(&cs->targets[i]) == NULL)
if(TQ_FIRST(&cs->destination[i].chunks) == NULL)
continue;
printf("\n/*** <<< %s [%s] >>> ***/\n\n",
_compiler_stream2str[i],
expr->Identifier);
TQ_FOR(ot, &(cs->targets[i]), next) {
TQ_FOR(ot, &(cs->destination[i].chunks), next) {
fwrite(ot->buf, ot->len, 1, stdout);
}
}
@ -178,18 +182,18 @@ asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *deps) {
fprintf(fp_h, "#include <constr_TYPE.h>\n\n");
TQ_FOR(ot, &(cs->targets[OT_INCLUDES]), next) {
TQ_FOR(ot, &(cs->destination[OT_INCLUDES].chunks), next) {
asn1c_activate_dependency(deps, 0, ot->buf);
fwrite(ot->buf, ot->len, 1, fp_h);
}
fprintf(fp_h, "\n");
TQ_FOR(ot, &(cs->targets[OT_DEPS]), next)
TQ_FOR(ot, &(cs->destination[OT_DEPS].chunks), next)
fwrite(ot->buf, ot->len, 1, fp_h);
fprintf(fp_h, "\n");
TQ_FOR(ot, &(cs->targets[OT_TYPE_DECLS]), next)
TQ_FOR(ot, &(cs->destination[OT_TYPE_DECLS].chunks), next)
fwrite(ot->buf, ot->len, 1, fp_h);
fprintf(fp_h, "\n");
TQ_FOR(ot, &(cs->targets[OT_FUNC_DECLS]), next)
TQ_FOR(ot, &(cs->destination[OT_FUNC_DECLS].chunks), next)
fwrite(ot->buf, ot->len, 1, fp_h);
fprintf(fp_h, "\n#ifdef __cplusplus\n}\n#endif\n\n"
@ -197,12 +201,14 @@ asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *deps) {
header_id);
fprintf(fp_c, "#include <%s.h>\n\n", expr->Identifier); /* Myself */
TQ_FOR(ot, &(cs->targets[OT_STAT_DEFS]), next)
TQ_FOR(ot, &(cs->destination[OT_CTABLES].chunks), next)
fwrite(ot->buf, ot->len, 1, fp_c);
TQ_FOR(ot, &(cs->targets[OT_CODE]), next)
TQ_FOR(ot, &(cs->destination[OT_CODE].chunks), next)
fwrite(ot->buf, ot->len, 1, fp_c);
TQ_FOR(ot, &(cs->destination[OT_STAT_DEFS].chunks), next)
fwrite(ot->buf, ot->len, 1, fp_c);
assert(OT_MAX == 7);
assert(OT_MAX == 8);
fclose(fp_c);
fclose(fp_h);

View File

@ -1,4 +1,7 @@
#include "asn1c_internal.h"
#include "asn1c_lang.h"
#include "asn1c_out.h"
#include "asn1c_save.h"
static void default_logger_cb(int, const char *fmt, ...);
static int asn1c_compile_expr(arg_t *arg);
@ -73,7 +76,7 @@ asn1c_compile_expr(arg_t *arg) {
type_cb = asn1_lang_map[expr->meta_type][expr->expr_type].type_cb;
if(type_cb) {
if(arg->indent_level == 0)
if(arg->target->destination[OT_TYPE_DECLS].indent_level == 0)
OUT("\n");
DEBUG("Compiling %s at line %d",
@ -134,7 +137,7 @@ asn1c_attach_streams(asn1p_expr_t *expr) {
cs = expr->data;
for(i = 0; i < OT_MAX; i++) {
TQ_INIT(&(cs->targets[i]));
TQ_INIT(&(cs->destination[i].chunks));
}
return 0;