From fd171ef359bc5842686d2ae01dbbc01c8d0eb6f9 Mon Sep 17 00:00:00 2001
From: Lev Walkin <vlm@lionet.info>
Date: Sun, 6 Jun 2004 07:20:17 +0000
Subject: [PATCH] tag2member map required for SEQUENCE

---
 libasn1compiler/asn1c_C.c | 195 +++++++++++++++++---------------------
 1 file changed, 87 insertions(+), 108 deletions(-)

diff --git a/libasn1compiler/asn1c_C.c b/libasn1compiler/asn1c_C.c
index 9fb4f23c..54bd847e 100644
--- a/libasn1compiler/asn1c_C.c
+++ b/libasn1compiler/asn1c_C.c
@@ -6,11 +6,21 @@
 #include "asn1c_C.h"
 #include <asn1fix_export.h>	/* exportable stuff from libasn1fix */
 
+typedef struct tag2el_s {
+	struct asn1p_type_tag_s el_tag;
+	int el_no;
+	asn1p_expr_t *from_expr;
+} tag2el_t;
+
+static int _fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no);
+static int _add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no);
+
 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, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag_p);
+static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count);
 static int emit_constraint_checking_code(arg_t *arg);
 static int emit_single_constraint_check(arg_t *arg, asn1p_constraint_t *ct, int mode);
 static int emit_alphabet_tables(arg_t *arg, asn1p_constraint_t *ct, int *table);
@@ -23,15 +33,6 @@ static long compute_min_size(arg_t *arg);
 static long compute_max_size(arg_t *arg);
 static long compute_xxx_size(arg_t *arg, int _max);
 
-typedef struct tag2el_s {
-	struct asn1p_type_tag_s el_tag;
-	int el_no;
-	asn1p_expr_t *from_expr;
-} tag2el_t;
-
-static int _fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no);
-static int _add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no);
-
 #define	C99_MODE	(arg->flags & A1C_NO_C99)
 #define	UNNAMED_UNIONS	(arg->flags & A1C_UNNAMED_UNIONS)
 
@@ -170,8 +171,18 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
 	int comp_mode = 0;	/* {root,ext=1,root,root,...} */
 	int ext_start = -1;
 	int ext_stop = -1;
+	tag2el_t *tag2el = NULL;
+	int tag2el_count = 0;
 	char *p;
 
+	/*
+	 * Fetch every inner tag from the tag to elements map.
+	 */
+	if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
+		if(tag2el) free(tag2el);
+		return -1;
+	}
+
 	REDIR(OT_STAT_DEFS);
 
 	OUT("#include <constr_SEQUENCE.h>\n");
@@ -255,12 +266,19 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
 	);
 	OUT("};\n");
 
+	/*
+	 * Tags to elements map.
+	 */
+	emit_tag2member_map(arg, tag2el, tag2el_count);
+
 	OUT("static asn1_SEQUENCE_specifics_t asn1_DEF_%s_specs = {\n", p);
 	INDENTED(
 		OUT("sizeof(struct %s),\n", p);
 		OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
 		OUT("asn1_DEF_%s_elements,\n", p);
 		OUT("%d,\t/* Elements count */\n", elements);
+		OUT("asn1_DEF_%s_tag2el,\n", p);
+		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",
@@ -388,61 +406,6 @@ asn1c_lang_C_type_SET(arg_t *arg) {
 	return asn1c_lang_C_type_SET_def(arg);
 }
 
-/*
- * Compare tags according to their canonical order.
- * Canonical order: [UNIVERSAL] [APPLICATION] [] [PRIVATE]
- * As you see, the class is encoded using the two lowest bits.
- */
-static arg_t *_ctc_arg;
-static int _canonical_tags_cmp(const void *ap, const void *bp)
-	__attribute__ ((unused));
-static int
-_canonical_tags_cmp(const void *ap, const void *bp) {
-	asn1p_expr_t *a, *b;
-	struct asn1p_type_tag_s ta, tb;
-
-	(const asn1p_expr_t *)a = *(const asn1p_expr_t * const *)ap;
-	(const asn1p_expr_t *)b = *(const asn1p_expr_t * const *)bp;
-
-	if(asn1f_fetch_tag(_ctc_arg->asn, _ctc_arg->mod, a, &ta)
-	|| asn1f_fetch_tag(_ctc_arg->asn, _ctc_arg->mod, b, &tb))
-		return 0;
-
-	if(ta.tag_class == tb.tag_class) {
-		if(ta.tag_value == tb.tag_value)
-			return 0;
-		else if(ta.tag_value < tb.tag_value)
-			return -1;
-		else
-			return 1;
-	} else if(ta.tag_class < tb.tag_class) {
-		return -1;
-	} else {
-		return 1;
-	}
-}
-
-static int
-_tag2el_cmp(const void *ap, const void *bp) {
-	const tag2el_t *a = ap;
-	const tag2el_t *b = bp;
-	const struct asn1p_type_tag_s *ta = &a->el_tag;
-	const struct asn1p_type_tag_s *tb = &b->el_tag;
-
-	if(ta->tag_class == tb->tag_class) {
-		if(ta->tag_value == tb->tag_value)
-			return 0;
-		else if(ta->tag_value < tb->tag_value)
-			return -1;
-		else
-			return 1;
-	} else if(ta->tag_class < tb->tag_class) {
-		return -1;
-	} else {
-		return 1;
-	}
-}
-
 static int
 asn1c_lang_C_type_SET_def(arg_t *arg) {
 	asn1p_expr_t *expr = arg->expr;
@@ -461,12 +424,6 @@ asn1c_lang_C_type_SET_def(arg_t *arg) {
 	if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
 		if(tag2el) free(tag2el);
 		return -1;
-	} else {
-		/*
-		 * Sort the map according to canonical order of their tags.
-		 */
-		_ctc_arg = arg;
-		qsort(tag2el, tag2el_count, sizeof(*tag2el), _tag2el_cmp);
 	}
 
 
@@ -550,22 +507,7 @@ asn1c_lang_C_type_SET_def(arg_t *arg) {
 	/*
 	 * Tags to elements map.
 	 */
-	p = MKID(expr->Identifier);
-	OUT("static asn1_SET_tag2member_t asn1_DEF_%s_tag2el[] = {\n", p);
-	if(tag2el_count) {
-		int i;
-		for(i = 0; i < tag2el_count; i++) {
-			OUT("    { ");
-			_print_tag(arg, expr, &tag2el[i].el_tag);
-			OUT(", ");
-			OUT("%d ", tag2el[i].el_no);
-			OUT("}, /* %s at %d */\n",
-				tag2el[i].from_expr->Identifier,
-				tag2el[i].from_expr->_lineno
-			);
-		}
-	}
-	OUT("};\n");
+	emit_tag2member_map(arg, tag2el, tag2el_count);
 
 	/*
 	 * Emit a map of mandatory elements.
@@ -836,12 +778,6 @@ asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
 	if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
 		if(tag2el) free(tag2el);
 		return -1;
-	} else {
-		/*
-		 * Sort the map according to canonical order of their tags.
-		 */
-		_ctc_arg = arg;
-		qsort(tag2el, tag2el_count, sizeof(*tag2el), _tag2el_cmp);
 	}
 
 	REDIR(OT_STAT_DEFS);
@@ -920,22 +856,7 @@ asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
 	/*
 	 * Tags to elements map.
 	 */
-	p = MKID(expr->Identifier);
-	OUT("static asn1_CHOICE_tag2member_t asn1_DEF_%s_tag2el[] = {\n", p);
-	if(tag2el_count) {
-		int i;
-		for(i = 0; i < tag2el_count; i++) {
-			OUT("    { ");
-			_print_tag(arg, expr, &tag2el[i].el_tag);
-			OUT(", ");
-			OUT("%d ", tag2el[i].el_no);
-			OUT("}, /* %s at %d */\n",
-				tag2el[i].from_expr->Identifier,
-				tag2el[i].from_expr->_lineno
-			);
-		}
-	}
-	OUT("};\n");
+	emit_tag2member_map(arg, tag2el, tag2el_count);
 
 	OUT("static asn1_CHOICE_specifics_t asn1_DEF_%s_specs = {\n", p);
 	INDENTED(
@@ -1252,6 +1173,35 @@ _print_tag(arg_t *arg, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag_p) {
 	return 0;
 }
 
+
+static int
+_tag2el_cmp(const void *ap, const void *bp) {
+	const tag2el_t *a = ap;
+	const tag2el_t *b = bp;
+	const struct asn1p_type_tag_s *ta = &a->el_tag;
+	const struct asn1p_type_tag_s *tb = &b->el_tag;
+
+	if(ta->tag_class == tb->tag_class) {
+		if(ta->tag_value == tb->tag_value) {
+			/*
+			 * Sort by their respective positions.
+			 */
+			if(a->el_no < b->el_no)
+				return -1;
+			else if(a->el_no > b->el_no)
+				return 1;
+			return 0;
+		} else if(ta->tag_value < tb->tag_value)
+			return -1;
+		else
+			return 1;
+	} else if(ta->tag_class < tb->tag_class) {
+		return -1;
+	} else {
+		return 1;
+	}
+}
+
 /*
  * For constructed types, number of external tags may be greater than
  * number of elements in the type because of CHOICE type.
@@ -1285,6 +1235,11 @@ _fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no) {
 		element++;
 	}
 
+	/*
+	 * Sort the map according to canonical order of their tags.
+	 */
+	qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
+
 	return 0;
 }
 
@@ -1348,6 +1303,30 @@ _add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no) {
 	return -1;
 }
 
+static int
+emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count) {
+	asn1p_expr_t *expr = arg->expr;
+
+	OUT("static asn1_TYPE_tag2member_t asn1_DEF_%s_tag2el[] = {\n",
+		MKID(expr->Identifier));
+	if(tag2el_count) {
+		int i;
+		for(i = 0; i < tag2el_count; i++) {
+			OUT("    { ");
+			_print_tag(arg, expr, &tag2el[i].el_tag);
+			OUT(", ");
+			OUT("%d ", tag2el[i].el_no);
+			OUT("}, /* %s at %d */\n",
+				tag2el[i].from_expr->Identifier,
+				tag2el[i].from_expr->_lineno
+			);
+		}
+	}
+	OUT("};\n");
+
+	return 0;;
+}
+
 static int
 emit_constraint_checking_code(arg_t *arg) {
 	asn1p_expr_t *expr = arg->expr;
-- 
GitLab