removed duplicate includes; moved CHOICE enumeration to higher level


git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@77 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/libasn1compiler/Makefile.in b/libasn1compiler/Makefile.in
index 032a829..74f9893 100644
--- a/libasn1compiler/Makefile.in
+++ b/libasn1compiler/Makefile.in
@@ -101,6 +101,8 @@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
 CONFIGURE_DEPENDS = @CONFIGURE_DEPENDS@
+CPLUSPLUS_FOUND_FALSE = @CPLUSPLUS_FOUND_FALSE@
+CPLUSPLUS_FOUND_TRUE = @CPLUSPLUS_FOUND_TRUE@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
 CXX = @CXX@
diff --git a/libasn1compiler/asn1c_C.c b/libasn1compiler/asn1c_C.c
index d561e02..34594df 100644
--- a/libasn1compiler/asn1c_C.c
+++ b/libasn1compiler/asn1c_C.c
@@ -45,31 +45,19 @@
 	OUT("/* Context for parsing across buffer boundaries */\n");	\
 	OUT("ber_dec_ctx_t _ber_dec_ctx;\n"));
 
-#define	DEPENDENCIES	do {			\
-	int saved_target = arg->target->target;	\
-	int saved_indent = arg->indent_level;	\
-	int comment_printed = 0;		\
-	REDIR(OT_DEPS);				\
-	arg->indent_level = 0;			\
-	TQ_FOR(v, &(expr->members), next) {	\
-		if((!(v->expr_type & ASN_CONSTR_MASK)	\
-		&& v->expr_type > ASN_CONSTR_MASK)	\
-		|| v->meta_type == AMT_TYPEREF) {	\
-			if(!comment_printed++)		\
-				OUT("/* Dependencies for %s */\n",	\
-				asn1c_type_name(arg, expr, TNF_UNMODIFIED));	\
-			OUT("#include <%s.h>\n",			\
-				asn1c_type_name(arg, v, TNF_INCLUDE));	\
-		}					\
-	}						\
-	if(expr->expr_type == ASN_CONSTR_SET_OF)	\
-		OUT("#include <asn_SET_OF.h>\n");	\
-	if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF)	\
-		OUT("#include <asn_SEQUENCE_OF.h>\n");	\
-	OUT("\n");				\
-	REDIR(saved_target);			\
-	INDENT(saved_indent);			\
-	} while(0)
+#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));\
+		}							\
+	}								\
+	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)
 
 #define	MKID(id)	asn1c_make_identifier(0, (id), 0)
 
@@ -187,10 +175,11 @@
 		return -1;
 	}
 
-	REDIR(OT_STAT_DEFS);
+	GEN_INCLUDE("constr_SEQUENCE");
+	if(!arg->embed)
+		GEN_DECLARE(expr);	/* asn1_DEF_xxx */
 
-	OUT("#include <constr_SEQUENCE.h>\n");
-	OUT("\n");
+	REDIR(OT_STAT_DEFS);
 
 	/*
 	 * Print out the table according to which the parsing is performed.
@@ -291,12 +280,6 @@
 	OUT("};\n");
 	OUT("\n");
 
-	p = MKID(expr->Identifier);
-	REDIR(OT_DEPS);
-	OUT("#include <constr_SEQUENCE.h>\n");
-	OUT("\n");
-	if(!arg->embed)
-	OUT("extern asn1_TYPE_descriptor_t asn1_DEF_%s;\n", p);
 	REDIR(OT_TYPE_DECLS);
 
 	return 0;
@@ -413,12 +396,12 @@
 		return -1;
 	}
 
+	GEN_INCLUDE("constr_SET");
+	if(!arg->embed)
+		GEN_DECLARE(expr);	/* asn1_DEF_xxx */
 
 	REDIR(OT_STAT_DEFS);
 
-	OUT("#include <constr_SET.h>\n");
-	OUT("\n");
-
 	/*
 	 * Print out the table according to which the parsing is performed.
 	 */
@@ -542,11 +525,6 @@
 	OUT("};\n");
 	OUT("\n");
 
-	REDIR(OT_DEPS);
-	OUT("#include <constr_SET.h>\n");
-	OUT("\n");
-	if(!arg->embed)
-	OUT("extern asn1_TYPE_descriptor_t asn1_DEF_%s;\n", p);
 	REDIR(OT_TYPE_DECLS);
 
 	return 0;
@@ -588,14 +566,16 @@
 	int tags_impl_skip = 0;
 	char *p;
 
-	REDIR(OT_DEPS);
-
+	/*
+	 * Print out the table according to which the parsing is performed.
+	 */
 	if(seq_of) {
-		OUT("#include <constr_SEQUENCE_OF.h>\n");
+		GEN_INCLUDE("constr_SEQUENCE_OF");
 	} else {
-		OUT("#include <constr_SET_OF.h>\n");
-		OUT("\n");
+		GEN_INCLUDE("constr_SET_OF");
 	}
+	if(!arg->embed)
+		GEN_DECLARE(expr);	/* asn1_DEF_xxx */
 
 	REDIR(OT_STAT_DEFS);
 
@@ -660,9 +640,6 @@
 	OUT("};\n");
 	OUT("\n");
 
-	REDIR(OT_DEPS);
-	if(!arg->embed)
-	OUT("extern asn1_TYPE_descriptor_t asn1_DEF_%s;\n", p);
 	REDIR(OT_TYPE_DECLS);
 
 	return 0;
@@ -676,7 +653,29 @@
 
 	DEPENDENCIES;
 
+	REDIR(OT_DEPS);
+
 	p = MKID(expr->Identifier);
+	OUT("typedef enum %s_PR {\n", p);
+	INDENTED(
+		p = MKID(expr->Identifier);
+		OUT("%s_PR_NOTHING,\t"
+			"/* No components present */\n", p);
+		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);
+		}
+	);
+	p = MKID(expr->Identifier);
+	OUT("} %s_PR_e;\n", p);
+
+	REDIR(OT_TYPE_DECLS);
 
 	if(arg->embed) {
 		OUT("struct %s {\n", p);
@@ -685,20 +684,7 @@
 	}
 
 	INDENTED(
-		OUT("enum {\n");
-		INDENTED(
-			OUT("%s_PR_NOTHING,\t"
-				"/* No components present */\n", p);
-			TQ_FOR(v, &(expr->members), next) {
-				if(v->expr_type == A1TC_EXTENSIBLE) continue;
-				p = MKID(expr->Identifier);
-				OUT("%s_PR_", p);
-				p = MKID(v->Identifier);
-				OUT("%s,\n", p, p);
-			}
-		);
-		OUT("} present;\n");
-
+		OUT("%s_PR_e present;\n", p);
 		OUT("union {\n", p);
 		TQ_FOR(v, &(expr->members), next) {
 			EMBED(v);
@@ -733,10 +719,11 @@
 		return -1;
 	}
 
-	REDIR(OT_STAT_DEFS);
+	GEN_INCLUDE("constr_CHOICE");
+	if(!arg->embed)
+		GEN_DECLARE(expr);	/* asn1_DEF_xxx */
 
-	OUT("#include <constr_CHOICE.h>\n");
-	OUT("\n");
+	REDIR(OT_STAT_DEFS);
 
 	/*
 	 * Print out the table according to which the parsing is performed.
@@ -844,9 +831,6 @@
 	OUT("};\n");
 	OUT("\n");
 
-	REDIR(OT_DEPS);
-	if(!arg->embed)
-	OUT("extern asn1_TYPE_descriptor_t asn1_DEF_%s;\n", p);
 	REDIR(OT_TYPE_DECLS);
 
 	return 0;
@@ -916,9 +900,8 @@
 		return 0;
 	}
 
-	REDIR(OT_DEPS);
 
-	OUT("#include <%s.h>\n", asn1c_type_name(arg, expr, TNF_INCLUDE));
+	GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
 
 	REDIR(OT_TYPE_DECLS);
 
@@ -1069,6 +1052,8 @@
 	OUT("asn_struct_print_f %s_print;\n", p);
 	OUT("asn_struct_free_f %s_free;\n", p);
 
+	REDIR(OT_TYPE_DECLS);
+
 	return 0;
 }
 
diff --git a/libasn1compiler/asn1c_internal.h b/libasn1compiler/asn1c_internal.h
index 31bf697..6192650 100644
--- a/libasn1compiler/asn1c_internal.h
+++ b/libasn1compiler/asn1c_internal.h
@@ -40,37 +40,6 @@
 #include "asn1c_out.h"		/* Handle output during compilation */
 #include "asn1c_save.h"		/* Save compiled output */
 
-#define	INDENT(val)		arg->indent_level += (val)
-#define	INDENTED(code)	do {			\
-		INDENT(+1);			\
-		do { code; } while(0);		\
-		INDENT(-1);			\
-	} while(0)
-#define	FLAT(code)	do {			\
-		int _il = arg->indent_level;	\
-		arg->indent_level = 0;		\
-		do { code; } while(0);		\
-		arg->indent_level = _il;	\
-	} while(0)
-#define	EMBED(ev)	do {			\
-		REDIR(OT_TYPE_DECLS);		\
-		arg->embed++;			\
-		INDENTED(arg_t _tmp = *arg;	\
-			_tmp.expr = ev;		\
-			_tmp.default_cb(&_tmp);	\
-		);				\
-		arg->embed--;			\
-	} while(0)
-#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;			\
-	asn1c_compiled_output(arg, fmt, ##args);\
-	arg->indent_level = _saved_indent;	\
-} while(0)
-
-#define	REDIR(foo)	do { arg->target->target = foo; } while(0)
-
 /*
  * Logging.
  */
diff --git a/libasn1compiler/asn1c_out.c b/libasn1compiler/asn1c_out.c
index a643241..2f7c573 100644
--- a/libasn1compiler/asn1c_out.c
+++ b/libasn1compiler/asn1c_out.c
@@ -35,6 +35,8 @@
 			if(ret == -1) return -1;
 		}
 	}
+	if(lf_found)
+		arg->indented = 0;
 
 	/*
 	 * Estimate necessary size.
@@ -66,10 +68,22 @@
 	m->len = ret;
 	va_end(ap);
 
-	TQ_ADD(&(arg->target->targets[arg->target->target]), m, next);
+	if(arg->target->target == OT_INCLUDES) {
+		out_chunk_t *v;
+		TQ_FOR(v, &(arg->target->targets[OT_INCLUDES]), next) {
+			if(m->len == v->len
+			&& !memcmp(m->buf, v->buf, m->len))
+				break;
+		}
+		if(v) {
+			/* Entry is already present. Skip it. */
+			free(m->buf);
+			free(m);
+			return 0;
+		}
+	}
 
-	if(lf_found)
-		arg->indented = 0;
+	TQ_ADD(&(arg->target->targets[arg->target->target]), m, next);
 
 	return 0;
 }
diff --git a/libasn1compiler/asn1c_out.h b/libasn1compiler/asn1c_out.h
index 2267d5d..e989f44 100644
--- a/libasn1compiler/asn1c_out.h
+++ b/libasn1compiler/asn1c_out.h
@@ -13,7 +13,8 @@
 
 typedef struct compiler_streams {
 	enum {
-		OT_DEPS,	/* Dependencies */
+		OT_INCLUDES,	/* #include files */
+		OT_DEPS,	/* Dependencies (other than #includes) */
 		OT_TYPE_DECLS,	/* Type declarations */
 		OT_FUNC_DECLS,	/* Function declarations */
 		OT_STAT_DEFS,	/* Static definitions */
@@ -24,8 +25,70 @@
 } compiler_streams_t;
 
 static char *_compiler_stream2str[] __attribute__ ((unused))
-	= { "DEPS", "TYPE-DECLS", "FUNC-DECLS", "STAT-DEFS", "CODE" };
+    = { "INCLUDES", "DEPS", "TYPE-DECLS", "FUNC-DECLS", "STAT-DEFS", "CODE" };
 
 int asn1c_compiled_output(arg_t *arg, const char *fmt, ...);
 
+
+/*****************************************************************
+ * Useful macros for invoking asn1c_compiled_output() and friends.
+ */
+
+/* Redirect output to a different stream. */
+#define	REDIR(foo)	do { arg->target->target = foo; } while(0)
+
+#define	INDENT(val)		arg->indent_level += (val)
+#define	INDENTED(code)	do {			\
+		INDENT(+1);			\
+		do { code; } while(0);		\
+		INDENT(-1);			\
+	} while(0)
+
+#define	FLAT(code)	do {			\
+		int _il = arg->indent_level;	\
+		arg->indent_level = 0;		\
+		do { code; } while(0);		\
+		arg->indent_level = _il;	\
+	} while(0)
+
+#define	EMBED(ev)	do {					\
+		int saved_target = arg->target->target;		\
+		REDIR(OT_TYPE_DECLS);				\
+		arg->embed++;					\
+		INDENTED(arg_t _tmp = *arg;			\
+			_tmp.expr = ev;				\
+			_tmp.default_cb(&_tmp);			\
+		);						\
+		arg->embed--;					\
+		assert(arg->target->target == OT_TYPE_DECLS);	\
+		REDIR(saved_target);				\
+	} while(0)
+
+/* 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;			\
+	OUT(fmt, ##args);			\
+	arg->indent_level = _saved_indent;	\
+} while(0)
+
+/* Generate #include line */
+#define	GEN_INCLUDE(filename)	do {				\
+	int saved_target = arg->target->target;			\
+	REDIR(OT_INCLUDES);					\
+	OUT_NOINDENT("#include <%s.h>\n", filename);		\
+	REDIR(saved_target);					\
+} while(0)
+
+/* Generate ASN.1 type declaration */
+#define	GEN_DECLARE(expr)	do {				\
+	int saved_target = arg->target->target;			\
+	REDIR(OT_DEPS);						\
+	OUT_NOINDENT("extern asn1_TYPE_descriptor_t "		\
+			"asn1_DEF_%s;\n",			\
+			MKID(expr->Identifier));		\
+	REDIR(saved_target);					\
+} while(0)
+
 #endif	/* _ASN1_COMPILED_OUTPUT_H_ */
diff --git a/libasn1compiler/asn1c_save.c b/libasn1compiler/asn1c_save.c
index 3d806bc..5a8d3b6 100644
--- a/libasn1compiler/asn1c_save.c
+++ b/libasn1compiler/asn1c_save.c
@@ -180,6 +180,9 @@
 
 	fprintf(fp_h, "#include <constr_TYPE.h>\n\n");
 
+	TQ_FOR(ot, &(cs->targets[OT_INCLUDES]), next)
+		fwrite(ot->buf, ot->len, 1, fp_h);
+	fprintf(fp_h, "\n");
 	TQ_FOR(ot, &(cs->targets[OT_DEPS]), next)
 		fwrite(ot->buf, ot->len, 1, fp_h);
 	fprintf(fp_h, "\n");
@@ -189,17 +192,17 @@
 	TQ_FOR(ot, &(cs->targets[OT_FUNC_DECLS]), next)
 		fwrite(ot->buf, ot->len, 1, fp_h);
 
-	fprintf(fp_c, "#include <%s.h>\n\n", expr->Identifier);
+	fprintf(fp_h, "\n#ifdef __cplusplus\n}\n#endif\n\n"
+			"#endif\t/* _%s_H_ */\n",
+		header_id);
+
+	fprintf(fp_c, "#include <%s.h>\n\n", expr->Identifier);	/* Myself */
 	TQ_FOR(ot, &(cs->targets[OT_STAT_DEFS]), next)
 		fwrite(ot->buf, ot->len, 1, fp_c);
 	TQ_FOR(ot, &(cs->targets[OT_CODE]), next)
 		fwrite(ot->buf, ot->len, 1, fp_c);
 
-	assert(OT_MAX == 5);
-
-	fprintf(fp_h, "\n#ifdef __cplusplus\n}\n#endif\n\n"
-			"#endif\t/* _%s_H_ */\n",
-		header_id);
+	assert(OT_MAX == 6);
 
 	fclose(fp_c);
 	fclose(fp_h);