blob: ed08513b37a32642415b0610b95feed84ed119c5 [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; \
Lev Walkin188ed2c2004-09-13 08:31:01 +00005 if(skip && !(flags & AFT_FULL_COLLECT)) { \
Lev Walkin906654e2004-09-10 15:49:15 +00006 if(newtag.tag_mode != TM_IMPLICIT) \
7 skip--; \
8 break; \
9 } else { \
10 if(newtag.tag_mode == TM_IMPLICIT) \
11 skip++; \
12 } \
Lev Walkin8945e0e2004-09-10 06:07:04 +000013 __p = realloc((*tags), \
14 sizeof(struct asn1p_type_tag_s) * (count + 1)); \
15 if(!__p) return -1; \
16 *tags = __p; \
17 (*tags)[count++] = newtag; \
18 if((flags & AFT_FETCH_OUTMOST)) return count; \
Lev Walkin8945e0e2004-09-10 06:07:04 +000019} while(0)
Lev Walkinf15320b2004-06-03 03:38:44 +000020
Lev Walkin8945e0e2004-09-10 06:07:04 +000021static int
22asn1f_fetch_tags_impl(arg_t *arg, struct asn1p_type_tag_s **tags, int count, int skip, enum asn1f_aft_flags_e flags) {
23 asn1p_expr_t *expr = arg->expr;
Lev Walkinf15320b2004-06-03 03:38:44 +000024
Lev Walkin8945e0e2004-09-10 06:07:04 +000025 /* If this type is tagged, add this tag first */
26 if(expr->tag.tag_class != TC_NOCLASS)
27 ADD_TAG(skip, expr->tag);
28
29 /* REMOVE ME */
Lev Walkinf15320b2004-06-03 03:38:44 +000030 if(expr->expr_type == A1TC_EXTENSIBLE) {
Lev Walkin8945e0e2004-09-10 06:07:04 +000031 struct asn1p_type_tag_s tt;
32 memset(&tt, 0, sizeof(tt));
33 tt.tag_class = -1;
34 ADD_TAG(skip, tt);
35 return count;
Lev Walkinf15320b2004-06-03 03:38:44 +000036 }
37
38 if(expr->meta_type == AMT_TYPE) {
Lev Walkin8945e0e2004-09-10 06:07:04 +000039 struct asn1p_type_tag_s tt;
40 memset(&tt, 0, sizeof(tt));
41 tt.tag_class = TC_UNIVERSAL;
42 tt.tag_value = expr_type2uclass_value[expr->expr_type];
43 if(tt.tag_value == 0) {
44 if(expr->expr_type == ASN_TYPE_ANY
45 && (flags & AFT_IMAGINARY_ANY))
46 tt.tag_value = -1;
47 else
48 return -1;
Lev Walkind541c252004-09-05 10:36:22 +000049 }
Lev Walkin8945e0e2004-09-10 06:07:04 +000050 ADD_TAG(skip, tt);
51 return count;
Lev Walkinf15320b2004-06-03 03:38:44 +000052 }
53
54 if(expr->meta_type == AMT_TYPEREF) {
Lev Walkin906654e2004-09-10 15:49:15 +000055 asn1p_expr_t *nexpr;
56 nexpr = asn1f_lookup_symbol(arg, expr->module, expr->reference);
57 if(nexpr == NULL) {
58 if(errno != EEXIST) /* -fknown-extern-type */
59 return -1;
60 if(!count)
61 return 0; /* OK */
62 if((*tags)[count-1].tag_mode == TM_IMPLICIT) {
63 WARNING("Tagging mode for %s "
64 "is IMPLICIT, assuming %s "
65 "has exactly one tag",
66 expr->Identifier,
67 asn1f_printable_reference(expr->reference)
68 );
69 return count;
70 }
71 FATAL("Tagging mode %s -> %s "
72 "dangerously incompatible",
73 expr->Identifier,
74 asn1f_printable_reference(expr->reference)
75 );
76 return -1;
77 } else {
78 arg->expr = nexpr;
79 }
Lev Walkinf15320b2004-06-03 03:38:44 +000080 if(expr->_mark & TM_RECURSION)
81 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +000082 expr->_mark |= TM_RECURSION;
Lev Walkin8945e0e2004-09-10 06:07:04 +000083 count = asn1f_fetch_tags_impl(arg, tags, count, skip, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +000084 expr->_mark &= ~TM_RECURSION;
Lev Walkin8945e0e2004-09-10 06:07:04 +000085 return count;
Lev Walkinf15320b2004-06-03 03:38:44 +000086 }
87
88 return -1;
89}
90
Lev Walkin8945e0e2004-09-10 06:07:04 +000091
92int
93asn1f_fetch_outmost_tag(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag, int _aft_imaginary_any) {
94 struct asn1p_type_tag_s *tags;
95 enum asn1f_aft_flags_e flags;
96 int count;
97
98 flags = AFT_FETCH_OUTMOST;
99 flags |= AFT_IMAGINARY_ANY * _aft_imaginary_any;
100
101 count = asn1f_fetch_tags(asn, mod, expr, &tags, flags);
102 if(count <= 0) return count;
103
104 *tag = tags[0];
105 free(tags);
106
107 return 0;
108}
109
110int
111asn1f_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) {
112 arg_t arg;
113 struct asn1p_type_tag_s *tags = 0;
114 int count;
115
116 memset(&arg, 0, sizeof(arg));
117 arg.asn = asn;
118 arg.mod = mod;
119 arg.expr = expr;
120
121 count = asn1f_fetch_tags_impl(&arg, &tags, 0, 0, flags);
122 if(count <= 0 && tags) {
123 free(tags);
124 tags = 0;
125 }
126 *tags_r = tags;
127 return count;
128}