-pdu=* changes
diff --git a/libasn1compiler/asn1c_save.c b/libasn1compiler/asn1c_save.c
index 06fc97d..4236e95 100644
--- a/libasn1compiler/asn1c_save.c
+++ b/libasn1compiler/asn1c_save.c
@@ -11,8 +11,12 @@
static int asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *, int, char **);
static int asn1c_copy_over(arg_t *arg, char *path);
static int identical_files(const char *fname1, const char *fname2);
+static int need_to_generate_pdu_collection(arg_t *arg);
static int generate_pdu_collection_file(arg_t *arg);
static int generate_preamble(arg_t *, FILE *, int optc, char **argv);
+static int include_type_to_pdu_collection(arg_t *arg);
+static void pdu_collection_print_unused_types(arg_t *arg);
+static const char *generate_pdu_C_definition(void);
int
asn1c_save_compiled_output(arg_t *arg, const char *datadir,
@@ -121,7 +125,7 @@
}
}
- if(arg->flags & A1C_PDU_AUTO) {
+ if(need_to_generate_pdu_collection(arg)) {
fprintf(mkf, "ASN_CONVERTER_SOURCES+=pdu_collection.c\n");
if(generate_pdu_collection_file(arg))
return -1;
@@ -135,7 +139,7 @@
"# This file may be used as an input for make(3)\n"
"# Remove the lines below to convert it into a pure .am file\n"
"TARGET = progname\n"
- "CFLAGS +=%s -I.\n"
+ "CFLAGS +=%s%s -I.\n"
"OBJS=${ASN_MODULE_SOURCES:.c=.o}"
" ${ASN_CONVERTER_SOURCES:.c=.o}\n"
"\nall: $(TARGET)\n"
@@ -150,7 +154,10 @@
"\n\trm -f $(OBJS)\n"
"\nregen: regenerate-from-asn1-source\n"
"\nregenerate-from-asn1-source:\n\t"
- , (arg->flags & A1C_PDU_AUTO) ? " -DASN_PDU_COLLECTION" : ""
+ , (arg->flags & A1C_PDU_TYPE)
+ ? generate_pdu_C_definition() : ""
+ , need_to_generate_pdu_collection(arg)
+ ? " -DASN_PDU_COLLECTION" : ""
);
for(i = 0; i < argc; i++)
@@ -483,9 +490,7 @@
TQ_FOR(mod, &(arg->asn->modules), mod_next) {
TQ_FOR(arg->expr, &(mod->members), next) {
- if(arg->expr->_type_referenced
- || !asn1_lang_map[arg->expr->meta_type]
- [arg->expr->expr_type].type_cb)
+ if(!include_type_to_pdu_collection(arg))
continue;
fprintf(fp, "extern struct asn_TYPE_descriptor_s "
"asn_DEF_%s;\n",
@@ -498,9 +503,7 @@
TQ_FOR(mod, &(arg->asn->modules), mod_next) {
int mod_printed = 0;
TQ_FOR(arg->expr, &(mod->members), next) {
- if(arg->expr->_type_referenced
- || !asn1_lang_map[arg->expr->meta_type]
- [arg->expr->expr_type].type_cb)
+ if(!include_type_to_pdu_collection(arg))
continue;
if(!mod_printed++)
fprintf(fp, "\t/* From module %s in %s */\n",
@@ -513,9 +516,92 @@
fprintf(fp, "\t0\n};\n\n");
+ pdu_collection_print_unused_types(arg);
+
fclose(fp);
fprintf(stderr, "Generated pdu_collection.c\n");
return 0;
}
+static struct PDUType {
+ char *typename;
+ int used;
+} *pduType;
+static int pduTypes;
+
+static const char *
+generate_pdu_C_definition(void) {
+ const char *src;
+ char *def;
+ char *dst;
+ if(pduTypes == 0) return "";
+ def = malloc(strlen(pduType[0].typename) + 20);
+ strcpy(def, " -DPDU=");
+ for(src = pduType[0].typename, dst = def + 7; *src; src++, dst++)
+ if((*dst = *src) == '-')
+ *dst = '_';
+ *dst = 0;
+ return def;
+}
+
+void
+asn1c__add_pdu_type(const char *ctypename) {
+ char *typename = strdup(ctypename);
+ assert(typename && *typename);
+
+ pduType = realloc(pduType, sizeof(pduType[0]) * (pduTypes + 1));
+ assert(pduType);
+ pduType[pduTypes].used = 0;
+ pduType[pduTypes].typename = typename;
+ pduTypes++;
+}
+
+static int
+asn1c__pdu_type_lookup(const char *typename) {
+ int i;
+ for(i = 0; i < pduTypes; i++) {
+ struct PDUType *pt = &pduType[i];
+ if(strcmp(pt->typename, typename) == 0) {
+ pt->used++;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int
+need_to_generate_pdu_collection(arg_t *arg) {
+ if(arg->flags & (A1C_PDU_ALL|A1C_PDU_AUTO))
+ return 1;
+ if(arg->flags & A1C_PDU_TYPE)
+ return (pduTypes > 1) ? 1 : 0;
+ return 0;
+}
+
+static void
+pdu_collection_print_unused_types(arg_t *arg) {
+ int i;
+ for(i = 0; i < pduTypes; i++) {
+ struct PDUType *pt = &pduType[i];
+ if(!pt->used) {
+ WARNING("Missing type specified in -pdu=%s",
+ pt->typename);
+ }
+ }
+}
+
+static int
+include_type_to_pdu_collection(arg_t *arg) {
+ if(!asn1_lang_map[arg->expr->meta_type]
+ [arg->expr->expr_type].type_cb)
+ return 0;
+
+ if((arg->flags & A1C_PDU_ALL)
+ || ((arg->flags & A1C_PDU_AUTO) && !arg->expr->_type_referenced)
+ || asn1c__pdu_type_lookup(arg->expr->Identifier)) {
+ return 1;
+ }
+
+ return 0;
+}