aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLev Walkin <vlm@lionet.info>2004-09-10 06:07:04 +0000
committerLev Walkin <vlm@lionet.info>2004-09-10 06:07:04 +0000
commit8945e0ea30918e97d183b782de553f43266bb509 (patch)
treeb8314e5a1fedb1c20b654dd97cdb7381858aee5d
parent71a8aaf50fc3ae749dc11522d09c6598d803bdc7 (diff)
extended tags support
-rw-r--r--libasn1fix/asn1fix_constr.c8
-rw-r--r--libasn1fix/asn1fix_tags.c109
-rw-r--r--libasn1fix/asn1fix_tags.h25
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_ */