Skip to content
Snippets Groups Projects
Commit 59004fad authored by Lev Walkin's avatar Lev Walkin
Browse files

new constraints generation method

parent 2e3055da
No related branches found
No related tags found
No related merge requests found
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
......@@ -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;
}
#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_stop - range_start) > 255)
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->el_count == 0)
}
if((range_stop - range_start) > 255)
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 "
......
#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_ */
......@@ -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.
*/
......
#include "asn1c_internal.h"
#include "asn1c_misc.h"
#include <asn1fix_export.h>
/*
......
#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;
}
......@@ -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 */
......
#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);
......
#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;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment