support for a class of circular references
diff --git a/libasn1compiler/asn1c_C.c b/libasn1compiler/asn1c_C.c
index 41ad21e..b8a7428 100644
--- a/libasn1compiler/asn1c_C.c
+++ b/libasn1compiler/asn1c_C.c
@@ -35,6 +35,7 @@
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 {
@@ -59,16 +60,9 @@
OUT("/* Context for parsing across buffer boundaries */\n"); \
OUT("asn_struct_ctx_t _asn_ctx;\n"));
+
#define DEPENDENCIES do { \
- asn1p_expr_t *__m; \
- TQ_FOR(__m, &(expr->members), next) { \
- if((!(__m->expr_type & ASN_CONSTR_MASK) \
- && __m->expr_type > ASN_CONSTR_MASK) \
- || __m->meta_type == AMT_TYPEREF) { \
- GEN_INCLUDE(asn1c_type_name(arg, \
- __m, TNF_INCLUDE)); \
- } \
- } \
+ 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) \
@@ -81,7 +75,6 @@
int
asn1c_lang_C_type_REAL(arg_t *arg) {
- REDIR(OT_DEPS);
return asn1c_lang_C_type_SIMPLE_TYPE(arg);
}
@@ -245,7 +238,7 @@
}
PCTX_DEF;
- OUT("} %s%s%s", expr->marker.flags?"*":"",
+ OUT("} %s%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
expr->_anonymous_type ? "" : MKID(expr->Identifier),
arg->embed ? "" : "_t");
@@ -406,7 +399,7 @@
);
PCTX_DEF;
- OUT("} %s%s%s", expr->marker.flags?"*":"",
+ OUT("} %s%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
expr->_anonymous_type ? "" : MKID(expr->Identifier),
arg->embed ? "" : "_t");
@@ -567,7 +560,7 @@
int
asn1c_lang_C_type_SEx_OF(arg_t *arg) {
asn1p_expr_t *expr = arg->expr;
- asn1p_expr_t *memb;
+ asn1p_expr_t *memb = TQ_FIRST(&expr->members);
DEPENDENCIES;
@@ -579,8 +572,6 @@
OUT("typedef struct %s {\n", MKID(expr->Identifier));
}
- memb = TQ_FIRST(&expr->members);
-
INDENT(+1);
OUT("A_%s_OF(",
(arg->expr->expr_type == ASN_CONSTR_SET_OF)
@@ -611,13 +602,13 @@
arg->embed--;
assert(arg->target->target == OT_TYPE_DECLS);
} else {
- OUT("%s", asn1c_type_name(arg, memb, TNF_CTYPE | TNF_CHECK));
+ OUT("%s", asn1c_type_name(arg, memb, TNF_RSAFE));
}
OUT(") list;\n");
INDENT(-1);
PCTX_DEF;
- OUT("} %s%s%s", expr->marker.flags?"*":"",
+ OUT("} %s%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
expr->_anonymous_type ? "" : MKID(expr->Identifier),
arg->embed ? "" : "_t");
@@ -752,7 +743,7 @@
);
PCTX_DEF;
- OUT("} %s%s%s", expr->marker.flags?"*":"",
+ OUT("} %s%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
expr->_anonymous_type ? "" : MKID(expr->Identifier),
arg->embed ? "" : "_t");
@@ -918,24 +909,23 @@
* refer it using "struct X" convention,
* as it may recursively include the current structure.
*/
- if(expr->marker.flags) {
+ if(expr->marker.flags & (EM_INDIRECT | EM_UNRECURSE)) {
asn1p_expr_t *terminal;
terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
if(terminal
&& (terminal->expr_type & ASN_CONSTR_MASK)) {
- REDIR(OT_DEPS);
- tnfmt = TNF_RSAFE;
- OUT("\n");
+ tnfmt = TNF_RSAFE;
+ REDIR(OT_FWD_DECLS);
OUT("%s;\t/* Forward declaration */\n",
- asn1c_type_name(arg, arg->expr, tnfmt | TNF_CHECK));
+ asn1c_type_name(arg, arg->expr, tnfmt));
}
}
REDIR(OT_TYPE_DECLS);
- OUT("%s", asn1c_type_name(arg, arg->expr, tnfmt | TNF_CHECK));
+ OUT("%s", asn1c_type_name(arg, arg->expr, tnfmt));
if(!expr->_anonymous_type) {
- OUT("%s", expr->marker.flags?"\t*":"\t ");
+ OUT("%s", (expr->marker.flags&EM_INDIRECT)?"\t*":"\t ");
OUT("%s", MKID(expr->Identifier));
if((expr->marker.flags & EM_DEFAULT) == EM_DEFAULT)
OUT("\t/* DEFAULT %s */",
@@ -951,11 +941,10 @@
REDIR(OT_TYPE_DECLS);
OUT("typedef %s\t",
- asn1c_type_name(arg, arg->expr, TNF_CTYPE | TNF_CHECK));
+ asn1c_type_name(arg, arg->expr, TNF_CTYPE));
OUT("%s%s_t",
- expr->marker.flags?"*":" ",
- MKID(expr->Identifier));
- OUT_DEBUG("\t/* %s:%d */", __FILE__, __LINE__);
+ (expr->marker.flags & EM_INDIRECT)?"*":" ",
+ MKID_nc(expr->Identifier));
}
if((expr->expr_type == ASN_BASIC_ENUMERATED)
@@ -1557,6 +1546,47 @@
}
static int
+emit_include_dependencies(arg_t *arg) {
+ asn1p_expr_t *expr = arg->expr;
+ asn1p_expr_t *memb;
+
+ TQ_FOR(memb, &(expr->members), next) {
+
+ if((memb->meta_type == AMT_TYPEREF
+ && (memb->marker.flags & EM_INDIRECT))
+ || expr->expr_type == ASN_CONSTR_SET_OF
+ || expr->expr_type == ASN_CONSTR_SEQUENCE_OF
+ ) {
+ asn1p_expr_t *terminal;
+ terminal = asn1f_find_terminal_type_ex(arg->asn, memb);
+ if(terminal && !terminal->parent_expr
+ && (terminal->expr_type & ASN_CONSTR_MASK)) {
+ int saved_target = arg->target->target;
+ REDIR(OT_FWD_DECLS);
+ OUT("%s;\t/* Forward declaration */\n",
+ asn1c_type_name(arg, memb, TNF_RSAFE));
+ REDIR(saved_target);
+ memb->marker.flags |= EM_UNRECURSE;
+ }
+ }
+
+ if((!(memb->expr_type & ASN_CONSTR_MASK)
+ && memb->expr_type > ASN_CONSTR_MASK)
+ || memb->meta_type == AMT_TYPEREF) {
+ if(memb->marker.flags & EM_UNRECURSE) {
+ GEN_POSTINCLUDE(asn1c_type_name(arg,
+ memb, TNF_INCLUDE));
+ } else {
+ GEN_INCLUDE(asn1c_type_name(arg,
+ memb, TNF_INCLUDE));
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int
emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
int save_target;
arg_t tmp_arg;
@@ -1576,7 +1606,8 @@
if(outmost_tag && outmost_tag->tag_value == -1)
OUT("ATF_OPEN_TYPE | ");
- OUT("%s, ", expr->marker.flags?"ATF_POINTER":"ATF_NOFLAGS");
+ OUT("%s, ",
+ (expr->marker.flags & EM_INDIRECT)?"ATF_POINTER":"ATF_NOFLAGS");
if((expr->marker.flags & EM_OPTIONAL) == EM_OPTIONAL) {
asn1p_expr_t *tv;
int opts = 0;