📄 asn1c_c.c
字号:
/* * Don't look into this file. First, because it's a mess, and second, because * it's a brain of the compiler, and you don't wanna mess with brains do you? ;) */#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 { struct asn1p_type_tag_s el_tag; int el_no; int toff_first; int toff_last; asn1p_expr_t *from_expr;} tag2el_t;typedef enum fte { FTE_ALLTAGS, FTE_CANONICAL_XER,} fte_e;static int _fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags);static int _add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags);static int asn1c_lang_C_type_SEQUENCE_def(arg_t *arg);static int asn1c_lang_C_type_SET_def(arg_t *arg);static int asn1c_lang_C_type_CHOICE_def(arg_t *arg);static int asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of);static int _print_tag(arg_t *arg, struct asn1p_type_tag_s *tag_p);static int check_if_extensible(asn1p_expr_t *expr);static int expr_better_indirect(arg_t *arg, asn1p_expr_t *expr);static int expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr);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 emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier);static int emit_include_dependencies(arg_t *arg);static int out_name_chain(arg_t *arg, int check_reserved_keywords);enum tvm_compat { _TVM_SAME = 0, /* tags and all_tags are same */ _TVM_SUBSET = 1, /* tags are subset of all_tags */ _TVM_DIFFERENT = 2, /* tags and all_tags are different */};static enum tvm_compat emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tc, int *atc);enum etd_spec { ETD_NO_SPECIFICS, ETD_HAS_SPECIFICS};static int emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, enum tvm_compat tv_mode, int tags_count, int all_tags_count, int elements_count, enum etd_spec);#define C99_MODE (!(arg->flags & A1C_NO_C99))#define UNNAMED_UNIONS (arg->flags & A1C_UNNAMED_UNIONS)#define HIDE_INNER_DEFS (arg->embed && !(arg->flags & A1C_ALL_DEFS_GLOBAL))#define PCTX_DEF INDENTED( \ OUT("\n"); \ OUT("/* Context for parsing across buffer boundaries */\n"); \ OUT("asn_struct_ctx_t _asn_ctx;\n"));#define DEPENDENCIES do { \ emit_include_dependencies(arg); \ if(expr->expr_type == ASN_CONSTR_SET_OF) \ GEN_INCLUDE("asn_SET_OF"); \ if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF) \ GEN_INCLUDE("asn_SEQUENCE_OF"); \} while(0)/* MKID_safe() without checking for reserved keywords */#define MKID(id) asn1c_make_identifier(0, (id), 0)#define MKID_safe(id) asn1c_make_identifier(AMI_CHECK_RESERVED, (id), 0)intasn1c_lang_C_type_REAL(arg_t *arg) { return asn1c_lang_C_type_SIMPLE_TYPE(arg);}struct value2enum { asn1c_integer_t value; const char *name; int idx;};static int compar_enumMap_byName(const void *ap, const void *bp) { const struct value2enum *a = (const struct value2enum *)ap; const struct value2enum *b = (const struct value2enum *)bp; return strcmp(a->name, b->name);}static int compar_enumMap_byValue(const void *ap, const void *bp) { const struct value2enum *a = (const struct value2enum *)ap; const struct value2enum *b = (const struct value2enum *)bp; if(a->value < b->value) return -1; else if(a->value == b->value) return 0; return 1;}intasn1c_lang_C_type_common_INTEGER(arg_t *arg) { asn1p_expr_t *expr = arg->expr; asn1p_expr_t *v; int el_count = expr_elements_count(arg, expr); struct value2enum *v2e; int map_is_extensible = (expr->expr_type == ASN_BASIC_INTEGER); v2e = alloca((el_count + 1) * sizeof(*v2e)); /* * For all ENUMERATED types [and for those INTEGER types which * have identifiers -- prohibited by X.693:8.3.4], * print out an enumeration table and a mapping * between identifiers and associated values. */ if(expr->expr_type == ASN_BASIC_ENUMERATED || (0 && el_count /* -- prohibited by X.693:8.3.4 */)) { int eidx = 0; REDIR(OT_DEPS); OUT("typedef enum "); out_name_chain(arg, 1); OUT(" {\n"); TQ_FOR(v, &(expr->members), next) { switch(v->expr_type) { case A1TC_UNIVERVAL: OUT("\t"); out_name_chain(arg, 0); OUT("_%s", MKID(v->Identifier)); OUT("\t= %" PRIdASN "%s\n", v->value->value.v_integer, (eidx+1 < el_count) ? "," : ""); v2e[eidx].name = v->Identifier; v2e[eidx].value = v->value->value.v_integer; eidx++; break; case A1TC_EXTENSIBLE: OUT("\t/*\n"); OUT("\t * Enumeration is extensible\n"); OUT("\t */\n"); map_is_extensible = 1; break; default: return -1; } } OUT("} "); out_name_chain(arg, 0); OUT("_e;\n"); assert(eidx == el_count); /* * Generate a enumerationName<->value map for XER codec. */ REDIR(OT_STAT_DEFS); OUT("static asn_INTEGER_enum_map_t asn_MAP_%s_%d_value2enum[] = {\n", MKID(expr->Identifier), expr->_type_unique_index); qsort(v2e, el_count, sizeof(v2e[0]), compar_enumMap_byValue); for(eidx = 0; eidx < el_count; eidx++) { v2e[eidx].idx = eidx; OUT("\t{ %" PRIdASN ",\t%ld,\t\"%s\" }%s\n", v2e[eidx].value, (long)strlen(v2e[eidx].name), v2e[eidx].name, (eidx + 1 < el_count) ? "," : ""); } if(map_is_extensible) OUT("\t/* This list is extensible */\n"); OUT("};\n"); OUT("static unsigned int asn_MAP_%s_%d_enum2value[] = {\n", MKID(expr->Identifier), expr->_type_unique_index); qsort(v2e, el_count, sizeof(v2e[0]), compar_enumMap_byName); for(eidx = 0; eidx < el_count; eidx++) { OUT("\t%d%s\t/* %s(%" PRIdASN ") */\n", v2e[eidx].idx, (eidx + 1 < el_count) ? "," : "", v2e[eidx].name, v2e[eidx].value); } if(map_is_extensible) OUT("\t/* This list is extensible */\n"); OUT("};\n"); OUT("static asn_INTEGER_specifics_t asn_SPC_%s_%d_specs = {\n", MKID(expr->Identifier), expr->_type_unique_index); INDENT(+1); OUT("asn_MAP_%s_%d_value2enum,\t" "/* \"tag\" => N; sorted by tag */\n", MKID(expr->Identifier), expr->_type_unique_index); OUT("asn_MAP_%s_%d_enum2value,\t" "/* N => \"tag\"; sorted by N */\n", MKID(expr->Identifier), expr->_type_unique_index); OUT("%d,\t/* Number of elements in the maps */\n", el_count); OUT("%d,\t/* Enumeration is %sextensible */\n", map_is_extensible, map_is_extensible ? "": "not "); if(expr->expr_type == ASN_BASIC_ENUMERATED) OUT("1\t/* Strict enumeration */\n"); else OUT("0\n"); INDENT(-1); OUT("};\n"); } return asn1c_lang_C_type_SIMPLE_TYPE(arg);}intasn1c_lang_C_type_SEQUENCE(arg_t *arg) { asn1p_expr_t *expr = arg->expr; asn1p_expr_t *v; int comp_mode = 0; /* {root,ext=1,root,root,...} */ DEPENDENCIES; if(arg->embed) { OUT("struct "); out_name_chain(arg, 1); OUT(" {\n"); } else { OUT("typedef struct %s {\n", MKID_safe(expr->Identifier)); } TQ_FOR(v, &(expr->members), next) { if(v->expr_type == A1TC_EXTENSIBLE) { if(comp_mode < 3) comp_mode++; } if(comp_mode == 1 || expr_better_indirect(arg, v)) v->marker.flags |= EM_INDIRECT; EMBED(v); } PCTX_DEF; OUT("} %s%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"", expr->_anonymous_type ? "" : arg->embed ? MKID_safe(expr->Identifier) : MKID(expr->Identifier), arg->embed ? "" : "_t"); return asn1c_lang_C_type_SEQUENCE_def(arg);}static intasn1c_lang_C_type_SEQUENCE_def(arg_t *arg) { asn1p_expr_t *expr = arg->expr; asn1p_expr_t *v; int elements; /* Number of elements */ int ext_start = -1; int ext_stop = -1; tag2el_t *tag2el = NULL; int tag2el_count = 0; int tags_count; int all_tags_count; enum tvm_compat tv_mode; /* * Fetch every inner tag from the tag to elements map. */ if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) { if(tag2el) free(tag2el); return -1; } GEN_INCLUDE("constr_SEQUENCE"); if(!arg->embed) GEN_DECLARE(expr); /* asn_DEF_xxx */ REDIR(OT_STAT_DEFS); /* * Print out the table according to which the parsing is performed. */ if(expr_elements_count(arg, expr)) { int comp_mode = 0; /* {root,ext=1,root,root,...} */ OUT("static asn_TYPE_member_t asn_MBR_%s_%d[] = {\n", MKID(expr->Identifier), expr->_type_unique_index); elements = 0; INDENTED(TQ_FOR(v, &(expr->members), next) { if(v->expr_type == A1TC_EXTENSIBLE) { if((++comp_mode) == 1) ext_start = elements - 1; else ext_stop = elements - 1; continue; } elements++; emit_member_table(arg, v); }); OUT("};\n"); } else { elements = 0; } /* * Print out asn_DEF_<type>_[all_]tags[] vectors. */ tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count); /* * Tags to elements map. */ emit_tag2member_map(arg, tag2el, tag2el_count, 0); OUT("static asn_SEQUENCE_specifics_t asn_SPC_%s_%d_specs = {\n", MKID(expr->Identifier), expr->_type_unique_index); INDENTED( OUT("sizeof(struct "); out_name_chain(arg, 1); OUT("),\n"); OUT("offsetof(struct "); out_name_chain(arg, 1); OUT(", _asn_ctx),\n"); OUT("asn_MAP_%s_%d_tag2el,\n", MKID(expr->Identifier), expr->_type_unique_index); OUT("%d,\t/* Count of tags in the map */\n", tag2el_count); OUT("%d,\t/* Start extensions */\n", ext_start); OUT("%d\t/* Stop extensions */\n", (ext_stop<ext_start)?elements+1:ext_stop, ext_stop); ); OUT("};\n"); /* * Emit asn_DEF_xxx table. */ emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements, ETD_HAS_SPECIFICS); REDIR(OT_TYPE_DECLS); return 0;} /* _SEQUENCE_def() */intasn1c_lang_C_type_SET(arg_t *arg) { asn1p_expr_t *expr = arg->expr; asn1p_expr_t *v; long mcount; char *id; int comp_mode = 0; /* {root,ext=1,root,root,...} */ DEPENDENCIES; REDIR(OT_DEPS); OUT("\n"); OUT("/*\n"); OUT(" * Method of determining the components presence\n"); OUT(" */\n"); mcount = 0; OUT("typedef enum "); out_name_chain(arg, 0); OUT("_PR {\n"); TQ_FOR(v, &(expr->members), next) { if(v->expr_type == A1TC_EXTENSIBLE) continue; INDENTED( out_name_chain(arg, 0); OUT("_PR_"); id = MKID(v->Identifier); OUT("%s,\t/* Member %s is present */\n", id, id) ); mcount++; } OUT("} "); out_name_chain(arg, 0); OUT("_PR;\n"); REDIR(OT_TYPE_DECLS); if(arg->embed) { OUT("struct "); out_name_chain(arg, 1); OUT(" {\n"); } else { OUT("typedef struct %s {\n", MKID_safe(expr->Identifier)); } TQ_FOR(v, &(expr->members), next) { if(v->expr_type == A1TC_EXTENSIBLE) { if(comp_mode < 3) comp_mode++; } if(comp_mode == 1 || expr_better_indirect(arg, v)) v->marker.flags |= EM_INDIRECT; EMBED(v); } INDENTED( id = MKID(expr->Identifier); OUT("\n"); OUT("/* Presence bitmask: ASN_SET_ISPRESENT(p%s, %s_PR_x) */\n", id, id); OUT("unsigned int _presence_map\n"); OUT("\t[((%ld+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];\n", mcount); ); PCTX_DEF; OUT("} %s%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"", expr->_anonymous_type ? "" : MKID_safe(expr->Identifier), arg->embed ? "" : "_t"); return asn1c_lang_C_type_SET_def(arg);}static intasn1c_lang_C_type_SET_def(arg_t *arg) { asn1p_expr_t *expr = arg->expr; asn1p_expr_t *v; int elements; tag2el_t *tag2el = NULL; int tag2el_count = 0; tag2el_t *tag2el_cxer = NULL; int tag2el_cxer_count = 0; int tags_count; int all_tags_count; enum tvm_compat tv_mode; char *p; /* * Fetch every inner tag from the tag to elements map. */ if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) { if(tag2el) free(tag2el); return -1; } if(_fill_tag2el_map(arg, &tag2el_cxer, &tag2el_cxer_count, -1, FTE_CANONICAL_XER)) { if(tag2el) free(tag2el); if(tag2el_cxer) free(tag2el_cxer); return -1; } if(tag2el_cxer_count == tag2el_count && memcmp(tag2el, tag2el_cxer, tag2el_count) == 0) { free(tag2el_cxer); tag2el_cxer = 0; } GEN_INCLUDE("constr_SET"); if(!arg->embed) GEN_DECLARE(expr); /* asn_DEF_xxx */ REDIR(OT_STAT_DEFS); /* * Print out the table according to which the parsing is performed. */ if(expr_elements_count(arg, expr)) { int comp_mode = 0; /* {root,ext=1,root,root,...} */ OUT("static asn_TYPE_member_t asn_MBR_%s_%d[] = {\n", MKID(expr->Identifier), expr->_type_unique_index); elements = 0; INDENTED(TQ_FOR(v, &(expr->members), next) { if(v->expr_type == A1TC_EXTENSIBLE) { if(comp_mode < 3) comp_mode++; } else { if(comp_mode == 1 || expr_better_indirect(arg, v)) v->marker.flags |= EM_INDIRECT; elements++; emit_member_table(arg, v); } }); OUT("};\n"); } else { elements = 0; } /* * Print out asn_DEF_<type>_[all_]tags[] vectors. */ tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count); /* * Tags to elements map. */ emit_tag2member_map(arg, tag2el, tag2el_count, 0); if(tag2el_cxer)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -