blob: ff662cc38f744bfacc2e7fc21139f676c8448a88 [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;
Lev Walkin1a01e192005-01-17 12:27:41 +000047 else if(expr->expr_type == ASN_CONSTR_CHOICE)
48 return count ? count : -1;
Lev Walkin8945e0e2004-09-10 06:07:04 +000049 else
50 return -1;
Lev Walkind541c252004-09-05 10:36:22 +000051 }
Lev Walkin8945e0e2004-09-10 06:07:04 +000052 ADD_TAG(skip, tt);
53 return count;
Lev Walkinf15320b2004-06-03 03:38:44 +000054 }
55
56 if(expr->meta_type == AMT_TYPEREF) {
Lev Walkin906654e2004-09-10 15:49:15 +000057 asn1p_expr_t *nexpr;
58 nexpr = asn1f_lookup_symbol(arg, expr->module, expr->reference);
59 if(nexpr == NULL) {
60 if(errno != EEXIST) /* -fknown-extern-type */
61 return -1;
62 if(!count)
63 return 0; /* OK */
64 if((*tags)[count-1].tag_mode == TM_IMPLICIT) {
65 WARNING("Tagging mode for %s "
66 "is IMPLICIT, assuming %s "
67 "has exactly one tag",
68 expr->Identifier,
69 asn1f_printable_reference(expr->reference)
70 );
71 return count;
72 }
73 FATAL("Tagging mode %s -> %s "
74 "dangerously incompatible",
75 expr->Identifier,
76 asn1f_printable_reference(expr->reference)
77 );
78 return -1;
79 } else {
80 arg->expr = nexpr;
81 }
Lev Walkinf15320b2004-06-03 03:38:44 +000082 if(expr->_mark & TM_RECURSION)
83 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +000084 expr->_mark |= TM_RECURSION;
Lev Walkin8945e0e2004-09-10 06:07:04 +000085 count = asn1f_fetch_tags_impl(arg, tags, count, skip, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +000086 expr->_mark &= ~TM_RECURSION;
Lev Walkin8945e0e2004-09-10 06:07:04 +000087 return count;
Lev Walkinf15320b2004-06-03 03:38:44 +000088 }
89
90 return -1;
91}
92
Lev Walkin8945e0e2004-09-10 06:07:04 +000093
94int
95asn1f_fetch_outmost_tag(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag, int _aft_imaginary_any) {
96 struct asn1p_type_tag_s *tags;
97 enum asn1f_aft_flags_e flags;
98 int count;
99
100 flags = AFT_FETCH_OUTMOST;
101 flags |= AFT_IMAGINARY_ANY * _aft_imaginary_any;
102
103 count = asn1f_fetch_tags(asn, mod, expr, &tags, flags);
104 if(count <= 0) return count;
105
106 *tag = tags[0];
107 free(tags);
108
109 return 0;
110}
111
112int
113asn1f_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) {
114 arg_t arg;
115 struct asn1p_type_tag_s *tags = 0;
116 int count;
117
118 memset(&arg, 0, sizeof(arg));
119 arg.asn = asn;
120 arg.mod = mod;
121 arg.expr = expr;
122
123 count = asn1f_fetch_tags_impl(&arg, &tags, 0, 0, flags);
124 if(count <= 0 && tags) {
125 free(tags);
126 tags = 0;
127 }
128 *tags_r = tags;
129 return count;
130}