📄 asn1c_constraint.c
字号:
#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, asn1cnst_range_t *r_value);static int emit_size_determination_code(arg_t *arg, asn1p_expr_type_e etype);static asn1p_expr_type_e _find_terminal_type(arg_t *arg);static int emit_range_comparison_code(arg_t *arg, asn1cnst_range_t *range, const char *varname, asn1c_integer_t natural_start, asn1c_integer_t natural_stop);intasn1c_emit_constraint_checking_code(arg_t *arg) { asn1cnst_range_t *r_size; asn1cnst_range_t *r_value; asn1p_expr_t *expr = arg->expr; asn1p_expr_type_e etype; asn1p_constraint_t *ct; int got_something = 0; int alphabet_table_compiled; int produce_st = 0; ct = expr->combined_constraints; if(ct == NULL) return 1; /* No additional constraints defined */ etype = _find_terminal_type(arg); r_value=asn1constraint_compute_PER_range(etype, ct, ACT_EL_RANGE,0,0,0); r_size = asn1constraint_compute_PER_range(etype, ct, ACT_CT_SIZE,0,0,0); if(r_value) { if(r_value->incompatible || r_value->empty_constraint || (r_value->left.type == ARE_MIN && r_value->right.type == ARE_MAX) || (etype == ASN_BASIC_BOOLEAN && r_value->left.value == 0 && r_value->right.value == 1) ) { asn1constraint_range_free(r_value); r_value = 0; } } if(r_size) { if(r_size->incompatible || r_size->empty_constraint || (r_size->left.value == 0 /* or .type == MIN */ && r_size->right.type == ARE_MAX) ) { asn1constraint_range_free(r_size); r_size = 0; } } /* * Do we really need an "*st = sptr" pointer? */ switch(etype) { case ASN_BASIC_INTEGER: case ASN_BASIC_ENUMERATED: case ASN_BASIC_REAL: if(!(arg->flags & A1C_USE_NATIVE_TYPES)) produce_st = 1; break; case ASN_BASIC_BIT_STRING: case ASN_BASIC_OCTET_STRING: produce_st = 1; break; default: if(etype & ASN_STRING_MASK) produce_st = 1; break; } if(produce_st) { char *tname = asn1c_type_name(arg, arg->expr, TNF_SAFE); OUT("const %s_t *st = (const %s_t *)sptr;\n", tname, tname); } if(r_size || r_value) { if(r_size) { OUT("size_t size;\n"); } if(r_value) switch(etype) { case ASN_BASIC_INTEGER: case ASN_BASIC_ENUMERATED: OUT("long value;\n"); break; case ASN_BASIC_REAL: OUT("double value;\n"); break; case ASN_BASIC_BOOLEAN: OUT("BOOLEAN_t value;\n"); break; default: break; } } OUT("\n"); /* * Protection against null input. */ OUT("if(!sptr) {\n"); INDENT(+1); OUT("_ASN_ERRLOG(app_errlog, app_key,\n"); OUT("\t\"%%s: value not given (%%s:%%d)\",\n"); OUT("\ttd->name, __FILE__, __LINE__);\n"); OUT("return -1;\n"); INDENT(-1); OUT("}\n"); OUT("\n"); if(r_value) emit_value_determination_code(arg, etype, r_value); if(r_size) emit_size_determination_code(arg, etype); INDENT(-1); REDIR(OT_CTABLES); /* Emit FROM() tables */ alphabet_table_compiled = (asn1c_emit_constraint_tables(arg, r_size?1:0) == 1); REDIR(OT_CODE); INDENT(+1); /* * Here is an if() {} else {} constaint checking code. */ OUT("\n"); OUT("if("); INDENT(+1); if(r_size) { if(got_something++) { OUT("\n"); OUT(" && "); } OUT("("); emit_range_comparison_code(arg, r_size, "size", 0, -1); OUT(")"); } if(r_value) { if(got_something++) { OUT("\n"); OUT(" && "); } OUT("("); if(etype == ASN_BASIC_BOOLEAN) emit_range_comparison_code(arg, r_value, "value", 0, 1); else emit_range_comparison_code(arg, r_value, "value", -1, -1); OUT(")"); } if(alphabet_table_compiled) { if(got_something++) { OUT("\n"); OUT(" && "); } OUT("!check_permitted_alphabet_%d(%s)", arg->expr->_type_unique_index, produce_st ? "st" : "sptr"); } 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"); INDENT(+1); OUT("/* Constraint check succeeded */\n"); OUT("return 0;\n"); INDENT(-1); OUT("} else {\n"); INDENT(+1); OUT("_ASN_ERRLOG(app_errlog, app_key,\n"); OUT("\t\"%%s: constraint failed (%%s:%%d)\",\n"); OUT("\ttd->name, __FILE__, __LINE__);\n"); OUT("return -1;\n"); INDENT(-1); OUT("}\n"); return 0;}static intasn1c_emit_constraint_tables(arg_t *arg, int got_size) { asn1c_integer_t range_start; asn1c_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; ct = arg->expr->combined_constraints; if(!ct) return 0; etype = _find_terminal_type(arg); range = asn1constraint_compute_PER_range(etype, ct, ACT_CT_FROM, 0,0,0); if(!range) return 0; if(range->incompatible || range->empty_constraint) { asn1constraint_range_free(range); return 0; } if(range->left.type == ARE_MIN && range->right.type == ARE_MAX) { /* * The permitted alphabet constraint checker code guarantees * that either both bounds (left/right) are present, or * they're absent simultaneously. Thus, this assertion * legitimately holds true. */ assert(range->el_count == 0); /* The full range is specified. Ignore it. */ return 0; } range_start = range->left.value; range_stop = range->right.value; assert(range->left.type == ARE_VALUE); assert(range->right.type == ARE_VALUE); assert(range_start <= range_stop); range_start = 0; /* Force old behavior */ /* * 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(etype == ASN_STRING_UTF8String) { if(range_stop >= 0x80) use_table = 0; else max_table_size = 128; } if(use_table) { int i, n = 0; int untl; memset(table, 0, sizeof(table)); for(i = -1; i < range->el_count; i++) { asn1cnst_range_t *r; asn1c_integer_t v; if(i == -1) { if(range->el_count) continue; r = range; } else { r = range->elements[i]; } for(v = r->left.value; v <= r->right.value; v++) { assert((v - range_start) >= 0); assert((v - range_start) < max_table_size); table[v - range_start] = ++n; } } untl = (range_stop - range_start) + 1; untl += (untl % 16)?16 - (untl % 16):0; OUT("static int permitted_alphabet_table_%d[%d] = {\n", arg->expr->_type_unique_index, max_table_size); for(n = 0; n < untl; n++) { OUT("%d,", table[n]?1:0); if(!((n+1) % 16)) { int c; if(!n) { OUT("\n"); continue; } OUT("\t/* "); for(c = n - 15; c <= n; c++) { if(table[c]) { int a = c + range_start; if(a > 0x20 && a < 0x80) OUT("%c", a); else OUT("."); } else { OUT(" "); } } OUT(" */"); OUT("\n"); } } OUT("};\n"); OUT("\n"); } else if(etype == ASN_STRING_UTF8String) { /* * UTF8String type is a special case in many respects. */ 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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -