diff options
author | Lev Walkin <vlm@lionet.info> | 2004-09-10 06:07:04 +0000 |
---|---|---|
committer | Lev Walkin <vlm@lionet.info> | 2004-09-10 06:07:04 +0000 |
commit | 8945e0ea30918e97d183b782de553f43266bb509 (patch) | |
tree | b8314e5a1fedb1c20b654dd97cdb7381858aee5d | |
parent | 71a8aaf50fc3ae749dc11522d09c6598d803bdc7 (diff) |
extended tags support
-rw-r--r-- | libasn1fix/asn1fix_constr.c | 8 | ||||
-rw-r--r-- | libasn1fix/asn1fix_tags.c | 109 | ||||
-rw-r--r-- | libasn1fix/asn1fix_tags.h | 25 |
3 files changed, 106 insertions, 36 deletions
diff --git a/libasn1fix/asn1fix_constr.c b/libasn1fix/asn1fix_constr.c index 4a3b99bc..7a45cd97 100644 --- a/libasn1fix/asn1fix_constr.c +++ b/libasn1fix/asn1fix_constr.c @@ -1,6 +1,6 @@ #include "asn1fix_internal.h" -#define AFT_IMAGINARY_ANY 1 /* _fetch_tag() flag */ +#define AFT_MAGIC_ANY 1 /* _fetch_tag() flag */ static int _asn1f_check_if_tag_must_be_explicit(arg_t *arg, asn1p_expr_t *v); static int _asn1f_compare_tags(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b); @@ -375,7 +375,7 @@ _asn1f_check_if_tag_must_be_explicit(arg_t *arg, asn1p_expr_t *v) { */ save_tag = v->tag; /* Save existing tag */ memset(&v->tag, 0, sizeof(v->tag)); /* Remove it temporarily */ - ret = asn1f_fetch_tag(arg->asn, arg->mod, v, &tag, 0); + ret = asn1f_fetch_outmost_tag(arg->asn, arg->mod, v, &tag, 0); v->tag = save_tag; /* Restore the tag back */ if(ret == 0) return 0; /* If found tag, it's okay */ @@ -403,8 +403,8 @@ _asn1f_compare_tags(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b) { int ra, rb; int ret; - ra = asn1f_fetch_tag(arg->asn, arg->mod, a, &ta, AFT_IMAGINARY_ANY); - rb = asn1f_fetch_tag(arg->asn, arg->mod, b, &tb, AFT_IMAGINARY_ANY); + ra = asn1f_fetch_outmost_tag(arg->asn, arg->mod, a, &ta, AFT_MAGIC_ANY); + rb = asn1f_fetch_outmost_tag(arg->asn, arg->mod, b, &tb, AFT_MAGIC_ANY); /* * If both tags are explicitly or implicitly given, use them. diff --git a/libasn1fix/asn1fix_tags.c b/libasn1fix/asn1fix_tags.c index 22ba422c..20066e6d 100644 --- a/libasn1fix/asn1fix_tags.c +++ b/libasn1fix/asn1fix_tags.c @@ -1,53 +1,100 @@ #include "asn1fix_internal.h" -int -asn1f_fetch_tag(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag, int flags) { - int ret; +#define ADD_TAG(skip, newtag) do { \ + void *__p; \ + if(skip) { skip--; break; } \ + __p = realloc((*tags), \ + sizeof(struct asn1p_type_tag_s) * (count + 1)); \ + if(!__p) return -1; \ + *tags = __p; \ + (*tags)[count++] = newtag; \ + if((flags & AFT_FETCH_OUTMOST)) return count; \ + if(newtag.tag_mode == TM_IMPLICIT) skip++; \ +} while(0) - if(expr->tag.tag_class != TC_NOCLASS) { - *tag = expr->tag; - return 0; - } +static int +asn1f_fetch_tags_impl(arg_t *arg, struct asn1p_type_tag_s **tags, int count, int skip, enum asn1f_aft_flags_e flags) { + asn1p_expr_t *expr = arg->expr; + + /* If this type is tagged, add this tag first */ + if(expr->tag.tag_class != TC_NOCLASS) + ADD_TAG(skip, expr->tag); + /* REMOVE ME */ if(expr->expr_type == A1TC_EXTENSIBLE) { - memset(tag, 0, sizeof(*tag)); - tag->tag_class = -1; - return 0; + struct asn1p_type_tag_s tt; + memset(&tt, 0, sizeof(tt)); + tt.tag_class = -1; + ADD_TAG(skip, tt); + return count; } if(expr->meta_type == AMT_TYPE) { - memset(tag, 0, sizeof(*tag)); - tag->tag_class = TC_UNIVERSAL; - tag->tag_value = expr_type2uclass_value[expr->expr_type]; - if(flags && expr->expr_type == ASN_TYPE_ANY) { - assert(tag->tag_value == 0); - tag->tag_value = -1; - return 0; + struct asn1p_type_tag_s tt; + memset(&tt, 0, sizeof(tt)); + tt.tag_class = TC_UNIVERSAL; + tt.tag_value = expr_type2uclass_value[expr->expr_type]; + if(tt.tag_value == 0) { + if(expr->expr_type == ASN_TYPE_ANY + && (flags & AFT_IMAGINARY_ANY)) + tt.tag_value = -1; + else + return -1; } - return (tag->tag_value == 0) ? -1 : 0; + ADD_TAG(skip, tt); + return count; } if(expr->meta_type == AMT_TYPEREF) { - arg_t arg; - - memset(&arg, 0, sizeof(arg)); - arg.asn = asn; - arg.mod = mod; - arg.expr = expr; - - expr = asn1f_lookup_symbol(&arg, expr->module, expr->reference); + expr = asn1f_lookup_symbol(arg, expr->module, expr->reference); if(expr == NULL) return -1; - if(expr->_mark & TM_RECURSION) return -1; - + arg->expr = expr; expr->_mark |= TM_RECURSION; - ret = asn1f_fetch_tag(asn, expr->module, expr, tag, - flags); + count = asn1f_fetch_tags_impl(arg, tags, count, skip, flags); expr->_mark &= ~TM_RECURSION; - return ret; + return count; } return -1; } + +int +asn1f_fetch_outmost_tag(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag, int _aft_imaginary_any) { + struct asn1p_type_tag_s *tags; + enum asn1f_aft_flags_e flags; + int count; + + flags = AFT_FETCH_OUTMOST; + flags |= AFT_IMAGINARY_ANY * _aft_imaginary_any; + + count = asn1f_fetch_tags(asn, mod, expr, &tags, flags); + if(count <= 0) return count; + + *tag = tags[0]; + free(tags); + + return 0; +} + +int +asn1f_fetch_tags(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s **tags_r, enum asn1f_aft_flags_e flags) { + arg_t arg; + struct asn1p_type_tag_s *tags = 0; + int count; + + memset(&arg, 0, sizeof(arg)); + arg.asn = asn; + arg.mod = mod; + arg.expr = expr; + + count = asn1f_fetch_tags_impl(&arg, &tags, 0, 0, flags); + if(count <= 0 && tags) { + free(tags); + tags = 0; + } + *tags_r = tags; + return count; +} diff --git a/libasn1fix/asn1fix_tags.h b/libasn1fix/asn1fix_tags.h index 429e56d7..8dd622b7 100644 --- a/libasn1fix/asn1fix_tags.h +++ b/libasn1fix/asn1fix_tags.h @@ -1,6 +1,29 @@ #ifndef _ASN1FIX_TAGS_H_ #define _ASN1FIX_TAGS_H_ -int asn1f_fetch_tag(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag, int special_ANY_handling); +enum asn1f_aft_flags_e { + AFT_IMAGINARY_ANY = 0x01, /* Treat ANY tag as [IMAGINARY ANY] */ + AFT_FETCH_OUTMOST = 0x02, /* Fetch only outmost tag */ +}; + + +/* + * Allocate and return an array of tags for the given type. + * Type1 ::= [2] EXPLICIT Type2 + * Type2 ::= [3] IMPLICIT Type3 + * Type3 ::= [4] EXPLICIT SEQUENCE { ... } + * Will return [2][3][UNIVERSAL 16] for the Type1. + */ +int asn1f_fetch_tags(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, + struct asn1p_type_tag_s **tags, enum asn1f_aft_flags_e flags); + +/* + * Fetch the outmost tag of the given type. + * Type1 ::= Type2 + * Type2 ::= [2] Type3 + * Type3 ::= SEQUENCE { ... } + * Will yield [2] for Type1. + */ +int asn1f_fetch_outmost_tag(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag, int _aft_imaginary_any); #endif /* _ASN1FIX_TAGS_H_ */ |