aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libasn1fix/asn1fix.h6
-rw-r--r--libasn1fix/asn1fix_dereft.c14
-rw-r--r--libasn1fix/asn1fix_internal.h4
-rw-r--r--libasn1fix/asn1fix_misc.c58
-rw-r--r--libasn1fix/asn1fix_misc.h5
-rw-r--r--libasn1fix/asn1fix_retrieve.c16
6 files changed, 95 insertions, 8 deletions
diff --git a/libasn1fix/asn1fix.h b/libasn1fix/asn1fix.h
index 4847330a..58ca537c 100644
--- a/libasn1fix/asn1fix.h
+++ b/libasn1fix/asn1fix.h
@@ -27,4 +27,10 @@ int asn1f_process(asn1p_t *_asn,
enum asn1f_flags,
void (*error_log_callback)(int _severity, const char *fmt, ...));
+
+/*
+ * Explicitly mark type as known.
+ */
+int asn1f_make_known_external_type(const char *);
+
#endif /* ASN1FIX_H */
diff --git a/libasn1fix/asn1fix_dereft.c b/libasn1fix/asn1fix_dereft.c
index f0ec9a6c..1f9b5bf4 100644
--- a/libasn1fix/asn1fix_dereft.c
+++ b/libasn1fix/asn1fix_dereft.c
@@ -28,9 +28,19 @@ asn1f_fix_dereference_types(arg_t *arg) {
*/
type_expr = asn1f_find_terminal_type(arg, expr, 0);
if(type_expr == NULL) {
+ const char *type_name;
+
+ if(errno == EEXIST) {
+ /* Ignore missing type
+ * if known to be defined externally:
+ * -fknown-extern-type=<name>
+ */
+ return 0;
+ }
+
+ type_name = asn1f_printable_reference(expr->reference);
FATAL("Unknown type \"%s\" referenced by \"%s\" at line %d",
- asn1f_printable_reference(expr->reference),
- expr->Identifier, expr->_lineno);
+ type_name, expr->Identifier, expr->_lineno);
return -1;
}
diff --git a/libasn1fix/asn1fix_internal.h b/libasn1fix/asn1fix_internal.h
index ff3b4e96..ac543cbb 100644
--- a/libasn1fix/asn1fix_internal.h
+++ b/libasn1fix/asn1fix_internal.h
@@ -1,6 +1,10 @@
#ifndef _ASN1FIX_INTERNAL_H_
#define _ASN1FIX_INTERNAL_H_
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
/*
* System headers required in various modules.
*/
diff --git a/libasn1fix/asn1fix_misc.c b/libasn1fix/asn1fix_misc.c
index a9a5378b..4ea94950 100644
--- a/libasn1fix/asn1fix_misc.c
+++ b/libasn1fix/asn1fix_misc.c
@@ -1,5 +1,5 @@
#include "asn1fix_internal.h"
-
+#include "asn1fix.h"
char const *
asn1f_printable_reference(asn1p_ref_t *ref) {
@@ -274,3 +274,59 @@ asn1f_count_children(asn1p_expr_t *expr) {
return count;
}
+
+static char **known_types;
+static int known_types_count;
+static int known_types_size;
+
+static int _known_types_cmp(const void *ap, const void *bp) {
+ const char *a = *(const char * const *)ap;
+ const char *b = *(const char * const *)bp;
+ return strcmp(a, b);
+}
+
+int
+asn1f_make_known_external_type(const char *type_name) {
+ char *tname;
+
+ /* Check for duplicates */
+ if(asn1f_check_known_external_type(type_name) == 0) {
+ errno = EEXIST;
+ return -1;
+ }
+
+ /* Ensure enough space */
+ if(known_types_count <= known_types_size) {
+ int n = known_types_size ? known_types_size << 1 : 4;
+ void *p;
+ p = realloc(known_types, n * sizeof(known_types[0]));
+ if(!p) return -1;
+ known_types = p;
+ known_types_size = n;
+ }
+
+ tname = strdup(type_name);
+ if(!tname) return -1;
+
+ known_types[known_types_count++] = tname;
+
+#ifdef HAVE_MERGESORT
+ mergesort
+#else
+ qsort
+#endif
+ (known_types, known_types_count, sizeof(known_types[0]),
+ _known_types_cmp);
+
+ return 0;
+}
+
+int
+asn1f_check_known_external_type(const char *type_name) {
+ void *p = bsearch(&type_name, known_types, known_types_count,
+ sizeof(known_types[0]), _known_types_cmp);
+ if(p) return 0;
+ errno = ESRCH;
+ return -1;
+}
+
diff --git a/libasn1fix/asn1fix_misc.h b/libasn1fix/asn1fix_misc.h
index e88e4322..a586faa8 100644
--- a/libasn1fix/asn1fix_misc.h
+++ b/libasn1fix/asn1fix_misc.h
@@ -44,4 +44,9 @@ int asn1f_check_unique_expr_child(arg_t *arg, asn1p_expr_t *child,
*/
int asn1f_count_children(asn1p_expr_t *parent);
+/*
+ * Check if type is explicitly known.
+ */
+int asn1f_check_known_external_type(const char *);
+
#endif /* _ASN1FIX_MISC_H_ */
diff --git a/libasn1fix/asn1fix_retrieve.c b/libasn1fix/asn1fix_retrieve.c
index 0dfcce40..f2f91d5c 100644
--- a/libasn1fix/asn1fix_retrieve.c
+++ b/libasn1fix/asn1fix_retrieve.c
@@ -228,12 +228,17 @@ asn1f_lookup_symbol(arg_t *arg, asn1p_ref_t *ref, asn1p_module_t **module_r) {
}
if(ref_tc == NULL) {
DEBUG("Module \"%s\" does not contain \"%s\" "
- "mentioned at line %d",
+ "mentioned at line %d: %s",
src_mod->Identifier,
identifier,
- ref->_lineno
+ ref->_lineno,
+ strerror(errno)
);
- errno = ESRCH;
+ if(asn1f_check_known_external_type(identifier) == 0) {
+ errno = EEXIST; /* Exists somewhere */
+ } else {
+ errno = ESRCH;
+ }
return NULL;
}
@@ -312,8 +317,9 @@ asn1f_find_terminal_thing(arg_t *arg, asn1p_expr_t *expr,
*/
tc = asn1f_lookup_symbol(arg, ref, &mod);
if(tc == NULL) {
- DEBUG("\tSymbol \"%s\" not found",
- asn1f_printable_reference(ref));
+ DEBUG("\tSymbol \"%s\" not found: %s",
+ asn1f_printable_reference(ref),
+ strerror(errno));
return NULL;
}