Commit 59004fad authored by Lev Walkin's avatar Lev Walkin

new constraints generation method

parent 2e3055da
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
This diff is collapsed.
#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)
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);
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,6 +330,7 @@ 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("}\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,8 +44,9 @@ 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 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); \
......@@ -47,10 +54,10 @@ int asn1c_compiled_output(arg_t *arg, const char *fmt, ...);
} while(0)
#define FLAT(code) do { \
int _il = arg->indent_level; \
arg->indent_level = 0; \
int _il = INDENT_LEVEL; \
INDENT_LEVEL = 0; \
do { code; } while(0); \
arg->indent_level = _il; \
INDENT_LEVEL = _il; \
} while(0)
#define EMBED(ev) do { \
......@@ -69,10 +76,10 @@ 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; \
int _saved_indent = INDENT_LEVEL; \
INDENT_LEVEL = 0; \
OUT(fmt, ##args); \
arg->indent_level = _saved_indent; \
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;
......
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