COMPONENTS OF support


git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@189 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/ChangeLog b/ChangeLog
index 6ddf842..6c7e05a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,10 +1,12 @@
 
-0.9:	2004-Aug-20
+0.9:	2004-Aug-21
 
 	* Reworked subtype constraints handling, aiming at PER-applicability.
 	* BOOLEAN and NULL are now implemented in terms of native int type.
 	* Compiler now links in only necessary skeleton files.
 	* -t option added to asn1c to ease manual BER/CER/DER decoding.
+	* Added support COMPONENTS OF construct.
+	* Numerous parser fixes and enhancements.
 
 0.8.19:	2004-Aug-18
 
diff --git a/libasn1compiler/asn1c_C.c b/libasn1compiler/asn1c_C.c
index f54d2d5..eaac644 100644
--- a/libasn1compiler/asn1c_C.c
+++ b/libasn1compiler/asn1c_C.c
@@ -40,11 +40,13 @@
 	OUT("ber_dec_ctx_t _ber_dec_ctx;\n"));
 
 #define	DEPENDENCIES	do {						\
-	TQ_FOR(v, &(expr->members), next) {				\
-		if((!(v->expr_type & ASN_CONSTR_MASK)			\
-		&& v->expr_type > ASN_CONSTR_MASK)			\
-		|| v->meta_type == AMT_TYPEREF) {			\
-			GEN_INCLUDE(asn1c_type_name(arg, v, TNF_INCLUDE));\
+	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));			\
 		}							\
 	}								\
 	if(expr->expr_type == ASN_CONSTR_SET_OF)			\
@@ -124,8 +126,7 @@
 	DEPENDENCIES;
 
 	if(arg->embed) {
-		OUT("struct %s {\n",
-			MKID(expr->Identifier));
+		OUT("struct %s {\n", MKID(expr->Identifier));
 	} else {
 		OUT("typedef struct %s {\n",
 			MKID(expr->Identifier));
@@ -141,9 +142,9 @@
 	}
 
 	PCTX_DEF;
-	OUT("} %s%s", expr->marker?"*":"",
-		MKID(expr->Identifier));
-	if(arg->embed) OUT(";\n"); else OUT("_t;\n");
+	OUT("} %s%s%s", expr->marker?"*":"",
+		expr->_anonymous_type ? "" : MKID(expr->Identifier),
+		arg->embed ? "" : "_t");
 
 	return asn1c_lang_C_type_SEQUENCE_def(arg);
 }
@@ -221,7 +222,7 @@
 	OUT("};\n");
 	OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
 	INDENTED(
-		OUT("\"%s\",\n", expr->Identifier);
+		OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
 		OUT("SEQUENCE_constraint,\n");
 		OUT("SEQUENCE_decode_ber,\n");
 		OUT("SEQUENCE_encode_der,\n");
@@ -252,34 +253,6 @@
 }
 
 int
-asn1c_lang_C_type_SEQUENCE_OF(arg_t *arg) {
-	asn1p_expr_t *expr = arg->expr;
-	asn1p_expr_t *v;
-
-	DEPENDENCIES;
-
-	if(arg->embed) {
-		OUT("struct %s {\n", MKID(expr->Identifier));
-	} else {
-		OUT("typedef struct %s {\n", MKID(expr->Identifier));
-	}
-
-	TQ_FOR(v, &(expr->members), next) {
-		INDENTED(OUT("A_SEQUENCE_OF(%s) list;\n",
-			asn1c_type_name(arg, v, TNF_RSAFE)));
-	}
-
-	PCTX_DEF;
-	OUT("} %s%s", expr->marker?"*":"", MKID(expr->Identifier));
-	if(arg->embed) OUT(";\n"); else OUT("_t;\n");
-
-	/*
-	 * SET OF/SEQUENCE OF definition, SEQUENCE OF mode.
-	 */
-	return asn1c_lang_C_type_SEx_OF_def(arg, 1);
-}
-
-int
 asn1c_lang_C_type_SET(arg_t *arg) {
 	asn1p_expr_t *expr = arg->expr;
 	asn1p_expr_t *v;
@@ -338,8 +311,9 @@
 	);
 
 	PCTX_DEF;
-	OUT("} %s%s", expr->marker?"*":"", MKID(expr->Identifier));
-	if(arg->embed) OUT(";\n"); else OUT("_t;\n");
+	OUT("} %s%s%s", expr->marker?"*":"",
+		expr->_anonymous_type ? "" : MKID(expr->Identifier),
+		arg->embed ? "" : "_t");
 
 	return asn1c_lang_C_type_SET_def(arg);
 }
@@ -445,7 +419,7 @@
 	OUT("};\n");
 	OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
 	INDENTED(
-		OUT("\"%s\",\n", expr->Identifier);
+		OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
 		OUT("SET_constraint,\n");
 		OUT("SET_decode_ber,\n");
 		OUT("SET_encode_der,\n");
@@ -476,32 +450,56 @@
 }
 
 int
-asn1c_lang_C_type_SET_OF(arg_t *arg) {
+asn1c_lang_C_type_SEx_OF(arg_t *arg) {
 	asn1p_expr_t *expr = arg->expr;
-	asn1p_expr_t *v;
+	asn1p_expr_t *memb;
 
 	DEPENDENCIES;
 
 	if(arg->embed) {
 		OUT("struct %s {\n", MKID(expr->Identifier));
 	} else {
-		OUT("typedef struct %s {\n",
-			MKID(expr->Identifier));
+		OUT("typedef struct %s {\n", MKID(expr->Identifier));
 	}
 
-	TQ_FOR(v, &(expr->members), next) {
-		INDENTED(OUT("A_SET_OF(%s) list;\n",
-			asn1c_type_name(arg, v, TNF_RSAFE)));
+	memb = TQ_FIRST(&expr->members);
+
+	INDENT(+1);
+	OUT("A_%s_OF(",
+		(arg->expr->expr_type == ASN_CONSTR_SET_OF)
+			? "SET" : "SEQUENCE");
+	if(memb->expr_type & ASN_CONSTR_MASK) {
+		arg_t tmp;
+		asn1p_expr_t tmp_memb;
+		arg->embed++;
+			tmp = *arg;
+			tmp.expr = &tmp_memb;
+			tmp_memb = *memb;
+			tmp_memb._anonymous_type = 1;
+			tmp_memb.Identifier = strdup(
+				asn1c_make_identifier(0,
+					expr->Identifier, "member", 0));
+			assert(tmp_memb.Identifier);
+			tmp.default_cb(&tmp);
+			free(tmp_memb.Identifier);
+		arg->embed--;
+		assert(arg->target->target == OT_TYPE_DECLS);
+	} else {
+		OUT("%s", asn1c_type_name(arg, memb, TNF_RSAFE));
 	}
+	OUT(") list;\n");
+	INDENT(-1);
 
 	PCTX_DEF;
-	OUT("} %s%s", expr->marker?"*":"", MKID(expr->Identifier));
-	if(arg->embed) OUT(";\n"); else OUT("_t;\n");
+	OUT("} %s%s%s", expr->marker?"*":"",
+		expr->_anonymous_type ? "" : MKID(expr->Identifier),
+		arg->embed ? "" : "_t");
 
 	/*
-	 * SET OF/SEQUENCE OF definition, SET OF mode.
+	 * SET OF/SEQUENCE OF definition
 	 */
-	return asn1c_lang_C_type_SEx_OF_def(arg, 0);
+	return asn1c_lang_C_type_SEx_OF_def(arg,
+		(arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF));
 }
 
 static int
@@ -551,7 +549,7 @@
 	OUT("};\n");
 	OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
 	INDENTED(
-		OUT("\"%s\",\n", expr->Identifier);
+		OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
 		if(seq_of) {
 			OUT("SEQUENCE_OF_constraint,\n");
 			OUT("SEQUENCE_OF_decode_ber,\n");
@@ -593,43 +591,42 @@
 asn1c_lang_C_type_CHOICE(arg_t *arg) {
 	asn1p_expr_t *expr = arg->expr;
 	asn1p_expr_t *v;
-	char *p;
+	char *id;
 
 	DEPENDENCIES;
 
 	REDIR(OT_DEPS);
 
-	p = MKID(expr->Identifier);
-	OUT("typedef enum %s_PR {\n", p);
+	id = MKID(expr->Identifier);
+	OUT("typedef enum %s_PR {\n", id);
 	INDENTED(
-		p = MKID(expr->Identifier);
 		OUT("%s_PR_NOTHING,\t"
-			"/* No components present */\n", p);
+			"/* No components present */\n", id);
 		TQ_FOR(v, &(expr->members), next) {
 			if(v->expr_type == A1TC_EXTENSIBLE) {
 				OUT("/* Extensions may appear below */\n");
 				continue;
 			}
-			p = MKID(expr->Identifier);
-			OUT("%s_PR_", p);
-			p = MKID(v->Identifier);
-			OUT("%s,\n", p, p);
+			id = MKID(expr->Identifier);
+			OUT("%s_PR_", id);
+			id = MKID(v->Identifier);
+			OUT("%s,\n", id, id);
 		}
 	);
-	p = MKID(expr->Identifier);
-	OUT("} %s_PR;\n", p);
+	id = MKID(expr->Identifier);
+	OUT("} %s_PR;\n", id);
 
 	REDIR(OT_TYPE_DECLS);
 
 	if(arg->embed) {
-		OUT("struct %s {\n", p);
+		OUT("struct %s {\n", id);
 	} else {
-		OUT("typedef struct %s {\n", p);
+		OUT("typedef struct %s {\n", id);
 	}
 
 	INDENTED(
-		OUT("%s_PR present;\n", p);
-		OUT("union {\n", p);
+		OUT("%s_PR present;\n", id);
+		OUT("union {\n", id);
 		TQ_FOR(v, &(expr->members), next) {
 			EMBED(v);
 		}
@@ -638,8 +635,9 @@
 	);
 
 	PCTX_DEF;
-	OUT("} %s%s", expr->marker?"*":"", MKID(expr->Identifier));
-	if(arg->embed) OUT(";\n"); else OUT("_t;\n");
+	OUT("} %s%s%s", expr->marker?"*":"",
+		expr->_anonymous_type ? "" : MKID(expr->Identifier),
+		arg->embed ? "" : "_t");
 
 	return asn1c_lang_C_type_CHOICE_def(arg);
 }
@@ -720,7 +718,7 @@
 	OUT("};\n");
 	OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
 	INDENTED(
-		OUT("\"%s\",\n", expr->Identifier);
+		OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
 		OUT("CHOICE_constraint,\n");
 		OUT("CHOICE_decode_ber,\n");
 		OUT("CHOICE_encode_der,\n");
@@ -756,17 +754,16 @@
 
 	ref = arg->expr->reference;
 	if(ref->components[ref->comp_count-1].name[0] == '&') {
-		asn1p_module_t *mod;
 		asn1p_expr_t *extract;
 		arg_t tmp;
 		int ret;
 
-		extract = asn1f_class_access_ex(arg->asn, arg->mod, arg->expr,
-			ref, &mod);
+		extract = asn1f_class_access_ex(arg->asn, arg->mod,
+			arg->expr, ref);
 		if(extract == NULL)
 			return -1;
 
-		extract = asn1p_expr_clone(extract);
+		extract = asn1p_expr_clone(extract, 0);
 		if(extract) {
 			if(extract->Identifier)
 				free(extract->Identifier);
@@ -781,7 +778,7 @@
 
 		tmp = *arg;
 		tmp.asn = arg->asn;
-		tmp.mod = mod;
+		tmp.mod = extract->module;
 		tmp.expr = extract;
 
 		ret = arg->default_cb(&tmp);
@@ -808,10 +805,9 @@
 		OUT("%s\t", asn1c_type_name(arg, arg->expr,
 			expr->marker?TNF_RSAFE:TNF_CTYPE));
 		OUT("%s", expr->marker?"*":" ");
-		OUT("%s;", MKID(expr->Identifier));
+		OUT("%s", MKID(expr->Identifier));
 		if(expr->marker) OUT("\t/* %s */",
 			(expr->marker==EM_OPTIONAL)?"OPTIONAL":"DEFAULT");
-		OUT("\n");
 
 		REDIR(OT_TYPE_DECLS);
 		return 0;
@@ -824,8 +820,7 @@
 
 	OUT("typedef %s\t", asn1c_type_name(arg, arg->expr, TNF_CTYPE));
 	OUT("%s", expr->marker?"*":" ");
-	OUT("%s_t;\n", MKID(expr->Identifier));
-	OUT("\n");
+	OUT("%s_t", MKID(expr->Identifier));
 
 	REDIR(OT_STAT_DEFS);
 
@@ -837,7 +832,7 @@
 	p = MKID(expr->Identifier);
 	OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
 	INDENTED(
-		OUT("\"%s\",\n", expr->Identifier);
+		OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
 		OUT("%s_constraint,\n", p);
 		OUT("%s_decode_ber,\n", p);
 		OUT("%s_encode_der,\n", p);
@@ -1167,9 +1162,10 @@
 	if(arg->expr->expr_type == A1TC_REFERENCE) {
 		arg_t tmp = *arg;
 		asn1p_expr_t *expr;
-		expr = asn1f_lookup_symbol_ex(tmp.asn, &tmp.mod, tmp.expr,
+		expr = asn1f_lookup_symbol_ex(tmp.asn, tmp.mod, tmp.expr,
 			arg->expr->reference);
 		if(expr) {
+			tmp.mod = expr->module;
 			tmp.expr = expr;
 			return _add_tag2el_member(&tmp, tag2el, count, el_no);
 		} else {
@@ -1273,8 +1269,7 @@
 	asn1p_expr_t *v;
 	int elements = 0;
 
-	topmost_parent = asn1f_find_terminal_type_ex(arg->asn,
-				arg->mod, expr, 0);
+	topmost_parent = asn1f_find_terminal_type_ex(arg->asn, arg->mod, expr);
 	if(!topmost_parent) return 0;
 
 	if(!(topmost_parent->expr_type & ASN_CONSTR_MASK))
@@ -1290,6 +1285,7 @@
 
 static int
 _emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
+	static int global_memb_unique;
 	int save_target;
 	arg_t tmp_arg;
 	char *p;
@@ -1331,14 +1327,22 @@
 		OUT("0,\n");
 	}
 	if(C99_MODE) OUT(".type = ");
-	OUT("(void *)&asn1_DEF_%s,\n",
-		asn1c_type_name(arg, expr, TNF_SAFE));
+	if((expr->expr_type & ASN_CONSTR_MASK)
+	&& (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF
+		|| arg->expr->expr_type == ASN_CONSTR_SET_OF)) {
+		OUT("(void *)&asn1_DEF_%s_member,\n",
+			MKID(arg->expr->Identifier));
+	} else {
+		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);
+		OUT("memb_%s_%d_constraint,\n", p,
+			++global_memb_unique);
 	} else {
 		OUT("0,\t/* Defer to actual type */\n");
 	}
@@ -1358,7 +1362,7 @@
 	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);
+	OUT("memb_%s_%d_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p, global_memb_unique);
 	INDENT(+1);
 	OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
 	tmp_arg = *arg;
diff --git a/libasn1compiler/asn1c_C.h b/libasn1compiler/asn1c_C.h
index 643d629..6349306 100644
--- a/libasn1compiler/asn1c_C.h
+++ b/libasn1compiler/asn1c_C.h
@@ -7,9 +7,8 @@
 int asn1c_lang_C_type_EXTENSIBLE(arg_t *);
 
 int asn1c_lang_C_type_SEQUENCE(arg_t *);
-int asn1c_lang_C_type_SEQUENCE_OF(arg_t *);
 int asn1c_lang_C_type_SET(arg_t *);
-int asn1c_lang_C_type_SET_OF(arg_t *);
+int asn1c_lang_C_type_SEx_OF(arg_t *);	/* SET OF or  SEQUENCE OF */
 int asn1c_lang_C_type_CHOICE(arg_t *);
 
 int asn1c_lang_C_type_INTEGER(arg_t *);
@@ -24,11 +23,11 @@
 	 * Constructed types
 	 */
 	{ AMT_TYPE, ASN_CONSTR_SEQUENCE,	asn1c_lang_C_type_SEQUENCE },
-	{ AMT_TYPE, ASN_CONSTR_SEQUENCE_OF,	asn1c_lang_C_type_SEQUENCE_OF },
-	{ AMT_TYPEREF, ASN_CONSTR_SEQUENCE_OF,	asn1c_lang_C_type_SEQUENCE_OF },
+	{ AMT_TYPE, ASN_CONSTR_SEQUENCE_OF,	asn1c_lang_C_type_SEx_OF, },
+	{ AMT_TYPEREF, ASN_CONSTR_SEQUENCE_OF,	asn1c_lang_C_type_SEx_OF },
 	{ AMT_TYPE, ASN_CONSTR_SET,		asn1c_lang_C_type_SET },
-	{ AMT_TYPE, ASN_CONSTR_SET_OF,		asn1c_lang_C_type_SET_OF },
-	{ AMT_TYPEREF, ASN_CONSTR_SET_OF,	asn1c_lang_C_type_SET_OF },
+	{ AMT_TYPE, ASN_CONSTR_SET_OF,		asn1c_lang_C_type_SEx_OF },
+	{ AMT_TYPEREF, ASN_CONSTR_SET_OF,	asn1c_lang_C_type_SEx_OF },
 	{ AMT_TYPE, ASN_CONSTR_CHOICE,		asn1c_lang_C_type_CHOICE },
 	/*
 	 * Basic types