earlier detection of unknown -pdu=Type
diff --git a/libasn1compiler/asn1c_save.c b/libasn1compiler/asn1c_save.c
index 5fe1b37..f302ceb 100644
--- a/libasn1compiler/asn1c_save.c
+++ b/libasn1compiler/asn1c_save.c
@@ -32,18 +32,26 @@
 		? safe_fprintf(fp_h, "#include \"%s\"\n", s)		\
 		: safe_fprintf(fp_h, "#include <%s>\n", s))		\
 
+enum include_type_result {
+    TI_NOT_INCLUDED,
+    TI_INCLUDED_FROM_BULK,
+    TI_INCLUDED_FROM_CMDLINE
+};
+
 static int asn1c_dump_streams(arg_t *arg, asn1c_fdeps_t *, int, char **);
 static int asn1c_print_streams(arg_t *arg);
 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 abuf *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 enum include_type_result include_type_to_pdu_collection(arg_t *arg);
+static int pdu_collection_has_unused_types(arg_t *arg);
 static const char *generate_pdu_C_definition(void);
 static void asn1c__cleanup_pdu_type(void);
+static int asn1c__pdu_type_lookup(const char *typename);
 
 static int
 asn1c__save_library_makefile(arg_t *arg, const asn1c_fdeps_t *deps, const char *datadir, const char *makefile_name) {
@@ -211,12 +219,29 @@
     return 0;
 }
 
+static int
+can_generate_pdu_collection(arg_t *arg) {
+    abuf *buf = generate_pdu_collection(arg);
+    if(!buf) {
+        return -1;
+    }
+    abuf_free(buf);
+    return 0;
+}
+
 int
 asn1c_save_compiled_output(arg_t *arg, const char *datadir,
 		int argc, int optc, char **argv) {
     asn1c_fdeps_t *deps = 0;
     int ret = -1;
 
+    /*
+     * Early check that we can properly generate PDU collection.
+     */
+    if(can_generate_pdu_collection(arg) == -1) {
+        return -1;
+    }
+
     do {
         asn1p_module_t *mod;
 
@@ -570,63 +595,79 @@
 
 static int
 generate_pdu_collection_file(arg_t *arg) {
-	asn1p_module_t *mod;
-	FILE *fp;
+    abuf *buf = generate_pdu_collection(arg);
+    assert(buf);
 
-	fp = asn1c_open_file("pdu_collection", ".c", 0);
+    FILE *fp = asn1c_open_file("pdu_collection", ".c", 0);
 	if(fp == NULL) {
 		perror("pdu_collection.c");
 		return -1;
 	}
+    safe_fwrite(buf->buffer, buf->length, 1, fp);
+    fclose(fp);
 
-	safe_fprintf(fp,
-		"/*\n"
-		" * Generated by asn1c-" VERSION " (http://lionet.info/asn1c)\n"
-		" */\n\n");
-	safe_fprintf(fp, "struct asn_TYPE_descriptor_s;\t"
-			"/* Forward declaration */\n\n");
-
-	TQ_FOR(mod, &(arg->asn->modules), mod_next) {
-		TQ_FOR(arg->expr, &(mod->members), next) {
-			if(!include_type_to_pdu_collection(arg))
-				continue;
-			safe_fprintf(fp, "extern struct asn_TYPE_descriptor_s "
-				"asn_DEF_%s;\n",
-				asn1c_make_identifier(0, arg->expr, NULL));
-		}
-	}
-
-	safe_fprintf(fp, "\n\n");
-	safe_fprintf(fp, "struct asn_TYPE_descriptor_s *asn_pdu_collection[] = {\n");
-	TQ_FOR(mod, &(arg->asn->modules), mod_next) {
-		int mod_printed = 0;
-		TQ_FOR(arg->expr, &(mod->members), next) {
-			if(!include_type_to_pdu_collection(arg))
-				continue;
-			if(!mod_printed++)
-			safe_fprintf(fp, "\t/* From module %s in %s */\n",
-				arg->expr->module->ModuleName,
-				arg->expr->module->source_file_name);
-			safe_fprintf(fp, "\t&asn_DEF_%s,\t\n",
-				asn1c_make_identifier(0, arg->expr, NULL));
-		}
-	}
-
-	safe_fprintf(fp, "\t0\n};\n\n");
-
-	pdu_collection_print_unused_types(arg);
-
-	fclose(fp);
 	safe_fprintf(stderr, "Generated pdu_collection.c\n");
+    return 0;
+}
 
-	return 0;
+static abuf *
+generate_pdu_collection(arg_t *arg) {
+	asn1p_module_t *mod;
+    abuf *buf = abuf_new();
+
+    abuf_printf(buf, "/*\n * Generated by asn1c-" VERSION
+                     " (http://lionet.info/asn1c)\n */\n\n");
+
+    TQ_FOR(mod, &(arg->asn->modules), mod_next) {
+        TQ_FOR(arg->expr, &(mod->members), next) {
+            if(include_type_to_pdu_collection(arg) == TI_NOT_INCLUDED) continue;
+            abuf_printf(buf,
+                        "extern asn_TYPE_descriptor_t "
+                        "asn_DEF_%s;\n",
+                        asn1c_make_identifier(0, arg->expr, NULL));
+        }
+    }
+
+    abuf_printf(buf, "\n\n");
+	abuf_printf(buf, "struct asn_TYPE_descriptor_s *asn_pdu_collection[] = {\n");
+    TQ_FOR(mod, &(arg->asn->modules), mod_next) {
+        int mod_printed = 0;
+        TQ_FOR(arg->expr, &(mod->members), next) {
+            switch(include_type_to_pdu_collection(arg)) {
+            case TI_NOT_INCLUDED:
+                continue;
+            case TI_INCLUDED_FROM_BULK:
+                /* Increment */
+                asn1c__pdu_type_lookup(arg->expr->Identifier);
+                break;
+            case TI_INCLUDED_FROM_CMDLINE:
+                break;
+            }
+            if(!mod_printed++) {
+                abuf_printf(buf, "\t/* From module %s in %s */\n",
+                             arg->expr->module->ModuleName,
+                             arg->expr->module->source_file_name);
+            }
+            abuf_printf(buf, "\t&asn_DEF_%s,\t\n",
+                         asn1c_make_identifier(0, arg->expr, NULL));
+        }
+    }
+
+    abuf_printf(buf, "\t0\n};\n\n");
+
+    if(pdu_collection_has_unused_types(arg)) {
+        abuf_free(buf);
+        return NULL;
+    }
+
+	return buf;
 }
 
 static struct PDUType {
 	char *typename;
 	int used;
 } *pduType;
-static int pduTypes;
+static size_t pduTypes;
 
 static const char *
 generate_pdu_C_definition(void) {
@@ -661,8 +702,7 @@
 
 static void
 asn1c__cleanup_pdu_type() {
-    int i;
-    for(i = 0; i < pduTypes; i++) {
+    for(size_t i = 0; i < pduTypes; i++) {
         free(pduType[i].typename);
     }
     free(pduType);
@@ -672,15 +712,14 @@
 
 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;
+    for(size_t i = 0; i < pduTypes; i++) {
+        struct PDUType *pt = &pduType[i];
+        if(strcmp(pt->typename, typename) == 0) {
+            pt->used++;
+            return 1;
+        }
+    }
+    return 0;
 }
 
 static int
@@ -692,34 +731,36 @@
 	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
+pdu_collection_has_unused_types(arg_t *arg) {
+    int ret = 0;
+
+    for(size_t i = 0; i < pduTypes; i++) {
+        struct PDUType *pt = &pduType[i];
+        if(!pt->used) {
+            FATAL("Unknown ASN.1 type specified in -pdu=%s", pt->typename);
+            ret = -1;
+        }
+    }
+
+    return ret;
 }
 
-static int
+static enum include_type_result
 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(!asn1_lang_map[arg->expr->meta_type][arg->expr->expr_type].type_cb)
+        return 0;
 
     /* Parameterized types can't serve as PDU's without instantiation. */
     if(arg->expr->lhs_params) {
         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;
-	}
+    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;
+    return 0;
 }