diff --git a/libasn1fix/asn1fix.h b/libasn1fix/asn1fix.h index 4847330a52f63e5e1641fbdd1c77a3d89a834f77..58ca537c515820684cd6df5543c3b0d43585cf86 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 f0ec9a6ce5102d043499b89eb8b602f6f87f21ab..1f9b5bf4f212d1e48098d0333a53161f13851f21 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 ff3b4e96daa4b4f19b241fa2632b23764cb47e41..ac543cbb57cba99e3bdf06177c4b0a38b63ab877 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 a9a5378b8cdb4ce302ac8756a3af3a7492f5a1b4..4ea94950a63a1f639cf5fa2e15fde89b34a4d859 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 e88e432299973e1ce5a4a9c3a467e83005ba186d..a586faa88e980d158e9ab61a8d6dd31779d35fcd 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 0dfcce40564a43430285885ea2766646611caaeb..f2f91d5c98a3a5b0267d367f84b9b83cead4a088 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; }