new constraints generation method
diff --git a/libasn1compiler/Makefile.am b/libasn1compiler/Makefile.am
index bcfaf93..55c5298 100644
--- a/libasn1compiler/Makefile.am
+++ b/libasn1compiler/Makefile.am
@@ -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 @@
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
diff --git a/libasn1compiler/asn1c_C.c b/libasn1compiler/asn1c_C.c
index ac13873..f54d2d5 100644
--- a/libasn1compiler/asn1c_C.c
+++ b/libasn1compiler/asn1c_C.c
@@ -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 @@
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 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 @@
* 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 @@
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 @@
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 @@
}
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 @@
* 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 @@
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 @@
}
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 @@
* 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 @@
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 @@
}
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 @@
* 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 @@
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 @@
}
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 @@
if(expr->marker) OUT("\t/* %s */",
(expr->marker==EM_OPTIONAL)?"OPTIONAL":"DEFAULT");
OUT("\n");
+
+ REDIR(OT_TYPE_DECLS);
return 0;
}
@@ -951,17 +855,20 @@
}
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 @@
* 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 @@
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 @@
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 @@
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 @@
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;
+}
diff --git a/libasn1compiler/asn1c_constraint.c b/libasn1compiler/asn1c_constraint.c
index dd54224..cf5416b 100644
--- a/libasn1compiler/asn1c_constraint.c
+++ b/libasn1compiler/asn1c_constraint.c
@@ -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 @@
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 @@
}
}
+ /*
+ * 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 @@
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 @@
}
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 @@
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 @@
* 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 @@
}
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 @@
}
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 @@
} 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 @@
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 @@
(long long)r->right.value);
}
if(r != range) OUT(")");
+ generated_something = 1;
}
- return 0;
+ return generated_something;
}
static int
@@ -412,16 +495,18 @@
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 @@
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 @@
}
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 "
diff --git a/libasn1compiler/asn1c_constraint.h b/libasn1compiler/asn1c_constraint.h
index 481c0b3..7c2ffa8 100644
--- a/libasn1compiler/asn1c_constraint.h
+++ b/libasn1compiler/asn1c_constraint.h
@@ -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_ */
diff --git a/libasn1compiler/asn1c_internal.h b/libasn1compiler/asn1c_internal.h
index 061b936..e6b1852 100644
--- a/libasn1compiler/asn1c_internal.h
+++ b/libasn1compiler/asn1c_internal.h
@@ -33,16 +33,9 @@
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.
*/
diff --git a/libasn1compiler/asn1c_misc.c b/libasn1compiler/asn1c_misc.c
index ee43696..c30174b 100644
--- a/libasn1compiler/asn1c_misc.c
+++ b/libasn1compiler/asn1c_misc.c
@@ -1,4 +1,6 @@
#include "asn1c_internal.h"
+#include "asn1c_misc.h"
+
#include <asn1fix_export.h>
/*
diff --git a/libasn1compiler/asn1c_out.c b/libasn1compiler/asn1c_out.c
index 3954916..fb41871 100644
--- a/libasn1compiler/asn1c_out.c
+++ b/libasn1compiler/asn1c_out.c
@@ -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 @@
assert(arg->target->target != OT_ASSERT);
return -1;
default:
+ dst = &arg->target->destination[arg->target->target];
break;
}
@@ -37,16 +40,16 @@
/*
* 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 @@
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 @@
}
}
- TQ_ADD(&(arg->target->targets[arg->target->target]), m, next);
+ TQ_ADD(&dst->chunks, m, next);
return 0;
}
diff --git a/libasn1compiler/asn1c_out.h b/libasn1compiler/asn1c_out.h
index 51582d4..f604687 100644
--- a/libasn1compiler/asn1c_out.h
+++ b/libasn1compiler/asn1c_out.h
@@ -19,15 +19,21 @@
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 @@
/* 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 @@
/* 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 */
diff --git a/libasn1compiler/asn1c_save.c b/libasn1compiler/asn1c_save.c
index 3c63053..add70e1 100644
--- a/libasn1compiler/asn1c_save.c
+++ b/libasn1compiler/asn1c_save.c
@@ -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 @@
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 @@
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 @@
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);
diff --git a/libasn1compiler/asn1compiler.c b/libasn1compiler/asn1compiler.c
index 24e539a..dd51156 100644
--- a/libasn1compiler/asn1compiler.c
+++ b/libasn1compiler/asn1compiler.c
@@ -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 @@
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 @@
cs = expr->data;
for(i = 0; i < OT_MAX; i++) {
- TQ_INIT(&(cs->targets[i]));
+ TQ_INIT(&(cs->destination[i].chunks));
}
return 0;