Add asn1c_helpers.c file to get type/enum/choice names for printing

Change-Id: I478d09776e58c86b84e82251f46f8d778b79a04c
diff --git a/src/Makefile.am b/src/Makefile.am
index fa86556..ab77375 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -10,9 +10,10 @@
 libosmo_rspro_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(RSPRO_LIBVERSION)
 libosmo_rspro_la_LIBADD = $(OSMOCORE_LIBS) $(OSMOGSM_LIBS) $(OSMOABIS_LIBS) \
 			  rspro/libosmo-asn1-rspro.la
-libosmo_rspro_la_SOURCES = rspro_util.c
+libosmo_rspro_la_SOURCES = rspro_util.c asn1c_helpers.c
 
 noinst_HEADERS = debug.h bankd.h client.h internal.h rspro_util.h slotmap.h rspro_client_fsm.h \
+		 asn1c_helpers.h \
 		 simtrace2/apdu_dispatch.h \
 		 simtrace2/libusb_util.h \
 		 simtrace2/simtrace2-discovery.h \
diff --git a/src/asn1c_helpers.c b/src/asn1c_helpers.c
new file mode 100644
index 0000000..ea3f5a6
--- /dev/null
+++ b/src/asn1c_helpers.c
@@ -0,0 +1,57 @@
+#include <assert.h>
+
+#include <asn_application.h>
+#include <constr_TYPE.h>
+#include <constr_CHOICE.h>
+#include <INTEGER.h>
+
+#include "asn1c_helpers.h"
+
+const char *asn_type_name(const asn_TYPE_descriptor_t *td)
+{
+	return td->name;
+}
+
+static int
+_fetch_present_idx(const void *struct_ptr, int pres_offset, int pres_size) {
+	const void *present_ptr;
+	int present;
+
+	present_ptr = ((const char *)struct_ptr) + pres_offset;
+
+	switch(pres_size) {
+	case sizeof(int):	present =   *(const int *)present_ptr; break;
+	case sizeof(short):	present = *(const short *)present_ptr; break;
+	case sizeof(char):	present =  *(const char *)present_ptr; break;
+	default:
+		/* ANSI C mandates enum to be equivalent to integer */
+		assert(pres_size != sizeof(int));
+		return 0;	/* If not aborted, pass back safe value */
+	}
+
+	return present;
+}
+
+const char *asn_choice_name(const asn_TYPE_descriptor_t *td, const void *sptr)
+{
+	const asn_CHOICE_specifics_t *cspec = td->specifics;
+	int present = _fetch_present_idx(sptr, cspec->pres_offset, cspec->pres_size);
+	const asn_TYPE_member_t *elm;
+
+	if (present < 0 || present >= td->elements_count)
+		return "<invalid>";
+
+	elm = &td->elements[present-1];
+	return elm->name;
+}
+
+const char *asn_enum_name(const asn_TYPE_descriptor_t *td, int data)
+{
+	const asn_INTEGER_specifics_t *ispec = td->specifics;
+
+	if (data < 0 || data >= ispec->map_count)
+		return "<invalid>";
+
+	return ispec->value2enum[data].enum_name;
+
+}
diff --git a/src/asn1c_helpers.h b/src/asn1c_helpers.h
new file mode 100644
index 0000000..8d4e676
--- /dev/null
+++ b/src/asn1c_helpers.h
@@ -0,0 +1,7 @@
+#pragma once
+
+struct asn_TYPE_descriptor_t;
+
+const char *asn_type_name(const asn_TYPE_descriptor_t *td);
+const char *asn_choice_name(const asn_TYPE_descriptor_t *td, const void *sptr);
+const char *asn_enum_name(const asn_TYPE_descriptor_t *td, int data);