Simplify the logic of accessing codec function for specific TYPE
diff --git a/libasn1compiler/asn1c_C.c b/libasn1compiler/asn1c_C.c
index 35e42db..1c1fb95 100644
--- a/libasn1compiler/asn1c_C.c
+++ b/libasn1compiler/asn1c_C.c
@@ -206,7 +206,8 @@
 			OUT("\t/* This list is extensible */\n");
 		OUT("};\n");
 
-		OUT("static asn_INTEGER_specifics_t asn_SPC_%s_specs_%d = {\n",
+		if(!(expr->_type_referenced)) OUT("static ");
+		OUT("const asn_INTEGER_specifics_t asn_SPC_%s_specs_%d = {\n",
 			MKID(expr), expr->_type_unique_index);
 		INDENT(+1);
 		OUT("asn_MAP_%s_value2enum_%d,\t"
@@ -238,7 +239,8 @@
 	if(expr->expr_type == ASN_BASIC_INTEGER
 	&& asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN) {
 		REDIR(OT_STAT_DEFS);
-		OUT("static asn_INTEGER_specifics_t asn_SPC_%s_specs_%d = {\n",
+		if(!(expr->_type_referenced)) OUT("static ");
+		OUT("const asn_INTEGER_specifics_t asn_SPC_%s_specs_%d = {\n",
 			MKID(expr), expr->_type_unique_index);
 		INDENT(+1);
 		OUT("0,\t");
@@ -379,7 +381,7 @@
 
 	GEN_INCLUDE_STD("constr_SEQUENCE");
 	if(!arg->embed)
-		GEN_DECLARE(expr);	/* asn_DEF_xxx */
+		GEN_DECLARE("SEQUENCE", expr);	/* asn_DEF_xxx */
 
 	REDIR(OT_STAT_DEFS);
 
@@ -389,7 +391,8 @@
 	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",
+		if(!(expr->_type_referenced)) OUT("static ");
+		OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
 			MKID(expr), expr->_type_unique_index);
 
 		elements = 0;
@@ -471,7 +474,8 @@
 	 */
 	emit_tag2member_map(arg, tag2el, tag2el_count, 0);
 
-	OUT("static asn_SEQUENCE_specifics_t asn_SPC_%s_specs_%d = {\n",
+	if(!(expr->_type_referenced)) OUT("static ");
+	OUT("asn_SEQUENCE_specifics_t asn_SPC_%s_specs_%d = {\n",
 		MKID(expr), expr->_type_unique_index);
 	INDENT(+1);
 	OUT("sizeof(struct ");
@@ -638,7 +642,7 @@
 
 	GEN_INCLUDE_STD("constr_SET");
 	if(!arg->embed)
-		GEN_DECLARE(expr);	/* asn_DEF_xxx */
+		GEN_DECLARE("SET", expr);	/* asn_DEF_xxx */
 
 	REDIR(OT_STAT_DEFS);
 
@@ -648,7 +652,8 @@
 	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",
+		if(!(expr->_type_referenced)) OUT("static ");
+		OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
 			MKID(expr), expr->_type_unique_index);
 
 		elements = 0;
@@ -708,7 +713,8 @@
 	OUT("\n");
 	OUT("};\n");
 
-	OUT("static asn_SET_specifics_t asn_SPC_%s_specs_%d = {\n",
+	if(!(expr->_type_referenced)) OUT("static \n");
+	OUT("asn_SET_specifics_t asn_SPC_%s_specs_%d = {\n",
 		MKID(expr), expr->_type_unique_index);
 	INDENTED(
 		OUT("sizeof(struct ");
@@ -863,14 +869,15 @@
 		GEN_INCLUDE_STD("constr_SET_OF");
 	}
 	if(!arg->embed)
-		GEN_DECLARE(expr);	/* asn_DEF_xxx */
+		GEN_DECLARE("SET_OF", expr);	/* asn_DEF_xxx */
 
 	REDIR(OT_STAT_DEFS);
 
 	/*
 	 * Print out the table according to which parsing is performed.
 	 */
-	OUT("static asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
+	if(!(expr->_type_referenced)) OUT("static ");
+	OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
 		MKID(expr), expr->_type_unique_index);
 	INDENT(+1);
 		v = TQ_FIRST(&(expr->members));
@@ -892,7 +899,8 @@
 	 */
 	tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
 
-	OUT("static asn_SET_OF_specifics_t asn_SPC_%s_specs_%d = {\n",
+	if(!(expr->_type_referenced)) OUT("static ");
+	OUT("asn_SET_OF_specifics_t asn_SPC_%s_specs_%d = {\n",
 		MKID(expr), expr->_type_unique_index);
 	INDENTED(
 		OUT("sizeof(struct ");
@@ -1031,7 +1039,7 @@
 
 	GEN_INCLUDE_STD("constr_CHOICE");
 	if(!arg->embed)
-		GEN_DECLARE(expr);	/* asn_DEF_xxx */
+		GEN_DECLARE("CHOICE", expr);	/* asn_DEF_xxx */
 
 	REDIR(OT_STAT_DEFS);
 
@@ -1040,7 +1048,8 @@
 	 */
 	if(expr_elements_count(arg, expr)) {
 
-		OUT("static asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
+		if(!(expr->_type_referenced)) OUT("static ");
+		OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
 			MKID(expr), expr->_type_unique_index);
 
 		elements = 0;
@@ -1088,7 +1097,8 @@
 	 */
 	emit_tag2member_map(arg, tag2el, tag2el_count, 0);
 
-	OUT("static asn_CHOICE_specifics_t asn_SPC_%s_specs_%d = {\n",
+	if(!(expr->_type_referenced)) OUT("static ");
+	OUT("asn_CHOICE_specifics_t asn_SPC_%s_specs_%d = {\n",
 		MKID(expr), expr->_type_unique_index);
 	INDENTED(
 		OUT("sizeof(struct ");
@@ -1275,7 +1285,7 @@
 	/*
 	 * Constraint checking.
 	 */
-	if(!(arg->flags & A1C_NO_CONSTRAINTS)) {
+	if(!(arg->flags & A1C_NO_CONSTRAINTS) && expr->combined_constraints) {
 		p = MKID(expr);
 		if(HIDE_INNER_DEFS) OUT("static ");
 		OUT("int\n");
@@ -1327,6 +1337,8 @@
 		asn1c_type_name(arg, expr, TNF_SAFE));
 	OUT(" * so here we adjust the DEF accordingly.\n");
 	OUT(" */\n");
+
+#if 0 /* remove unnecessary functions */
 	OUT("static void\n");
 	OUT("%s_%d_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {\n",
 		MKID(expr), expr->_type_unique_index);
@@ -1535,7 +1547,7 @@
 	OUT("}\n");
 	OUT("\n");
   }
-
+#endif
 	REDIR(OT_FUNC_DECLS);
 
 	p = MKID(expr);
@@ -1545,6 +1557,20 @@
 			p, expr->_type_unique_index);
 	} else {
 		OUT("extern asn_TYPE_descriptor_t asn_DEF_%s;\n", p);
+		if (etd_spec == ETD_HAS_SPECIFICS) {
+			if((expr->expr_type == ASN_BASIC_ENUMERATED) ||
+				(expr->expr_type == ASN_BASIC_INTEGER)) {
+				if(expr->_type_referenced) {
+					OUT("extern asn_INTEGER_specifics_t "
+						"asn_SPC_%s_specs_%d;\n", p, expr->_type_unique_index);
+				}
+			} else {
+				asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
+
+				OUT("extern asn_%s_specifics_t ", asn1c_type_name(arg, terminal, TNF_SAFE));
+				OUT("asn_SPC_%s_specs_%d;\n", MKID(expr), expr->_type_unique_index);
+			}
+		}
 		OUT("asn_struct_free_f %s_free;\n", p);
 		OUT("asn_struct_print_f %s_print;\n", p);
 		OUT("asn_constr_check_f %s_constraint;\n", p);
@@ -2246,9 +2272,18 @@
 		return 0;
 	}
 
+	if(expr->_type_referenced) {
+		REDIR(OT_FUNC_DECLS);
+
+		OUT("extern asn_per_constraints_t "
+			"asn_PER_%s_%s_constr_%d;\n",
+			pfx, MKID(expr), expr->_type_unique_index);
+	}
+
 	REDIR(OT_CTDEFS);
 
-	OUT("static asn_per_constraints_t "
+	if(!(expr->_type_referenced)) OUT("static ");
+	OUT("asn_per_constraints_t "
 		"asn_PER_%s_%s_constr_%d GCC_NOTUSED = {\n",
 		pfx, MKID(expr), expr->_type_unique_index);
 
@@ -2723,6 +2758,7 @@
 	asn1p_expr_t *terminal;
 	int using_type_name = 0;
 	char *p = MKID(expr);
+	char *p2 = (char *)0;
 
 	terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
 
@@ -2754,8 +2790,15 @@
 			using_type_name = 1;
 			p = asn1c_type_name(arg, arg->expr, TNF_SAFE);
 		} else {
+			if (expr->expr_type == A1TC_REFERENCE) {
+				p2 = strdup(asn1c_type_name(arg, terminal, TNF_SAFE));
+			} else {
+				p2 = strdup(asn1c_type_name(arg, expr, TNF_SAFE));
+			}
 			p = MKID(expr);
 		}
+		if (!p2)
+			p2 = strdup(p);
 
 #define FUNCREF(foo)	do {				\
 	OUT("%s", p);					\
@@ -2764,29 +2807,38 @@
 	OUT("_" #foo ",\n");				\
 } while(0)
 
-		FUNCREF(free);
-		FUNCREF(print);
-		FUNCREF(constraint);
-		FUNCREF(decode_ber);
-		FUNCREF(encode_der);
-		FUNCREF(decode_xer);
-		FUNCREF(encode_xer);
+#define FUNCREF2(foo)		\
+do {				\
+	OUT("%s", p2);		\
+	OUT("_" #foo ",\n");	\
+} while(0)
+
+		FUNCREF2(free);
+		FUNCREF2(print);
+		if (!expr->combined_constraints)
+			FUNCREF2(constraint);
+		else
+			FUNCREF(constraint);
+		FUNCREF2(decode_ber);
+		FUNCREF2(encode_der);
+		FUNCREF2(decode_xer);
+		FUNCREF2(encode_xer);
 
 		if(arg->flags & A1C_GEN_OER) {
-			FUNCREF(decode_oer);
-			FUNCREF(encode_oer);
+			FUNCREF2(decode_oer);
+			FUNCREF2(encode_oer);
 		} else {
 			OUT("0, 0,\t/* No OER support, "
 				"use \"-gen-OER\" to enable */\n");
 		}
-
 		if(arg->flags & A1C_GEN_PER) {
-			FUNCREF(decode_uper);
-			FUNCREF(encode_uper);
+			FUNCREF2(decode_uper);
+			FUNCREF2(encode_uper);
 		} else {
 			OUT("0, 0,\t/* No PER support, "
 				"use \"-gen-PER\" to enable */\n");
 		}
+		if (p2) free(p2);
 
 		if(!terminal || terminal->expr_type == ASN_CONSTR_CHOICE) {
 		//if(expr->expr_type == ASN_CONSTR_CHOICE) {
@@ -2857,16 +2909,35 @@
 			OUT("0,\t/* No PER visible constraints */\n");
 		}
 
-		if(elements_count) {
-			OUT("asn_MBR_%s_%d,\n", p, expr->_type_unique_index);
-			if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
-			|| expr->expr_type == ASN_CONSTR_SET_OF) {
-				OUT("%d,\t/* Single element */\n",
-					elements_count);
-				assert(elements_count == 1);
+		if(elements_count ||
+			((expr->expr_type == A1TC_REFERENCE) &&
+				(terminal->expr_type & ASN_CONSTR_MASK) &&
+				expr_elements_count(arg, terminal))) {
+
+			if (expr->expr_type == A1TC_REFERENCE) {
+				OUT("asn_MBR_%s_%d,\n", MKID(terminal), terminal->_type_unique_index);
+
+				if(terminal->expr_type == ASN_CONSTR_SEQUENCE_OF
+				|| terminal->expr_type == ASN_CONSTR_SET_OF) {
+					OUT("%d,\t/* Single element */\n",
+						expr_elements_count(arg, terminal));
+					assert(expr_elements_count(arg, terminal) == 1);
+				} else {
+					OUT("%d,\t/* Elements count */\n",
+						expr_elements_count(arg, terminal));
+				}
 			} else {
-				OUT("%d,\t/* Elements count */\n",
-					elements_count);
+				OUT("asn_MBR_%s_%d,\n", p, expr->_type_unique_index);
+
+				if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
+				|| expr->expr_type == ASN_CONSTR_SET_OF) {
+					OUT("%d,\t/* Single element */\n",
+						elements_count);
+					assert(elements_count == 1);
+				} else {
+					OUT("%d,\t/* Elements count */\n",
+						elements_count);
+				}
 			}
 		} else {
 			if(expr_elements_count(arg, expr))
@@ -2877,7 +2948,28 @@
 
 		switch(spec) {
 		case ETD_NO_SPECIFICS:
-			OUT("0\t/* No specifics */\n");
+			if ((expr->expr_type == A1TC_REFERENCE) &&
+				((terminal->expr_type & ASN_CONSTR_MASK) ||
+				(terminal->expr_type == ASN_BASIC_ENUMERATED) ||
+				((terminal->expr_type == ASN_BASIC_INTEGER) &&
+				(asn1c_type_fits_long(arg, terminal) == FL_FITS_UNSIGN)))) {
+				OUT("&asn_SPC_%s_specs_%d\t/* Additional specs */\n", MKID(terminal), terminal->_type_unique_index);
+			} else if ((expr->expr_type == ASN_TYPE_ANY) ||
+					(expr->expr_type == ASN_BASIC_BIT_STRING) ||
+					(expr->expr_type == ASN_STRING_BMPString) ||
+					(expr->expr_type == ASN_BASIC_OCTET_STRING) ||
+					(expr->expr_type == ASN_STRING_UniversalString)) {
+				OUT("&asn_SPC_%s_specs\t/* Additional specs */\n", asn1c_type_name(arg, expr, TNF_SAFE));
+			} else if ((expr->expr_type == A1TC_REFERENCE) &&
+					((terminal->expr_type == ASN_TYPE_ANY) ||
+					(terminal->expr_type == ASN_BASIC_BIT_STRING) ||
+					(terminal->expr_type == ASN_STRING_BMPString) ||
+					(terminal->expr_type == ASN_BASIC_OCTET_STRING) ||
+					(terminal->expr_type == ASN_STRING_UniversalString))) {
+				OUT("&asn_SPC_%s_specs\t/* Additional specs */\n", asn1c_type_name(arg, terminal, TNF_SAFE));
+			} else {
+				OUT("0\t/* No specifics */\n");
+			}
 			break;
 		case ETD_HAS_SPECIFICS:
 			OUT("&asn_SPC_%s_specs_%d\t/* Additional specs */\n",