diff options
-rw-r--r-- | libasn1fix/asn1fix.h | 6 | ||||
-rw-r--r-- | libasn1fix/asn1fix_dereft.c | 14 | ||||
-rw-r--r-- | libasn1fix/asn1fix_internal.h | 4 | ||||
-rw-r--r-- | libasn1fix/asn1fix_misc.c | 58 | ||||
-rw-r--r-- | libasn1fix/asn1fix_misc.h | 5 | ||||
-rw-r--r-- | libasn1fix/asn1fix_retrieve.c | 16 |
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; } |