blob: 20066e6d410bc502f8dfad2a7142540767f941fb [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
2
Lev Walkin8945e0e2004-09-10 06:07:04 +00003#define ADD_TAG(skip, newtag) do { \
4 void *__p; \
5 if(skip) { skip--; break; } \
6 __p = realloc((*tags), \
7 sizeof(struct asn1p_type_tag_s) * (count + 1)); \
8 if(!__p) return -1; \
9 *tags = __p; \
10 (*tags)[count++] = newtag; \
11 if((flags & AFT_FETCH_OUTMOST)) return count; \
12 if(newtag.tag_mode == TM_IMPLICIT) skip++; \
13} while(0)
Lev Walkinf15320b2004-06-03 03:38:44 +000014
Lev Walkin8945e0e2004-09-10 06:07:04 +000015static int
16asn1f_fetch_tags_impl(arg_t *arg, struct asn1p_type_tag_s **tags, int count, int skip, enum asn1f_aft_flags_e flags) {
17 asn1p_expr_t *expr = arg->expr;
Lev Walkinf15320b2004-06-03 03:38:44 +000018
Lev Walkin8945e0e2004-09-10 06:07:04 +000019 /* If this type is tagged, add this tag first */
20 if(expr->tag.tag_class != TC_NOCLASS)
21 ADD_TAG(skip, expr->tag);
22
23 /* REMOVE ME */
Lev Walkinf15320b2004-06-03 03:38:44 +000024 if(expr->expr_type == A1TC_EXTENSIBLE) {
Lev Walkin8945e0e2004-09-10 06:07:04 +000025 struct asn1p_type_tag_s tt;
26 memset(&tt, 0, sizeof(tt));
27 tt.tag_class = -1;
28 ADD_TAG(skip, tt);
29 return count;
Lev Walkinf15320b2004-06-03 03:38:44 +000030 }
31
32 if(expr->meta_type == AMT_TYPE) {
Lev Walkin8945e0e2004-09-10 06:07:04 +000033 struct asn1p_type_tag_s tt;
34 memset(&tt, 0, sizeof(tt));
35 tt.tag_class = TC_UNIVERSAL;
36 tt.tag_value = expr_type2uclass_value[expr->expr_type];
37 if(tt.tag_value == 0) {
38 if(expr->expr_type == ASN_TYPE_ANY
39 && (flags & AFT_IMAGINARY_ANY))
40 tt.tag_value = -1;
41 else
42 return -1;
Lev Walkind541c252004-09-05 10:36:22 +000043 }
Lev Walkin8945e0e2004-09-10 06:07:04 +000044 ADD_TAG(skip, tt);
45 return count;
Lev Walkinf15320b2004-06-03 03:38:44 +000046 }
47
48 if(expr->meta_type == AMT_TYPEREF) {
Lev Walkin8945e0e2004-09-10 06:07:04 +000049 expr = asn1f_lookup_symbol(arg, expr->module, expr->reference);
Lev Walkinf15320b2004-06-03 03:38:44 +000050 if(expr == NULL) return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +000051 if(expr->_mark & TM_RECURSION)
52 return -1;
Lev Walkin8945e0e2004-09-10 06:07:04 +000053 arg->expr = expr;
Lev Walkinf15320b2004-06-03 03:38:44 +000054 expr->_mark |= TM_RECURSION;
Lev Walkin8945e0e2004-09-10 06:07:04 +000055 count = asn1f_fetch_tags_impl(arg, tags, count, skip, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +000056 expr->_mark &= ~TM_RECURSION;
Lev Walkin8945e0e2004-09-10 06:07:04 +000057 return count;
Lev Walkinf15320b2004-06-03 03:38:44 +000058 }
59
60 return -1;
61}
62
Lev Walkin8945e0e2004-09-10 06:07:04 +000063
64int
65asn1f_fetch_outmost_tag(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag, int _aft_imaginary_any) {
66 struct asn1p_type_tag_s *tags;
67 enum asn1f_aft_flags_e flags;
68 int count;
69
70 flags = AFT_FETCH_OUTMOST;
71 flags |= AFT_IMAGINARY_ANY * _aft_imaginary_any;
72
73 count = asn1f_fetch_tags(asn, mod, expr, &tags, flags);
74 if(count <= 0) return count;
75
76 *tag = tags[0];
77 free(tags);
78
79 return 0;
80}
81
82int
83asn1f_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) {
84 arg_t arg;
85 struct asn1p_type_tag_s *tags = 0;
86 int count;
87
88 memset(&arg, 0, sizeof(arg));
89 arg.asn = asn;
90 arg.mod = mod;
91 arg.expr = expr;
92
93 count = asn1f_fetch_tags_impl(&arg, &tags, 0, 0, flags);
94 if(count <= 0 && tags) {
95 free(tags);
96 tags = 0;
97 }
98 *tags_r = tags;
99 return count;
100}