Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 1 | #include "asn1fix_internal.h" |
| 2 | |
Lev Walkin | 8945e0e | 2004-09-10 06:07:04 +0000 | [diff] [blame^] | 3 | #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 Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 14 | |
Lev Walkin | 8945e0e | 2004-09-10 06:07:04 +0000 | [diff] [blame^] | 15 | static int |
| 16 | asn1f_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 Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 18 | |
Lev Walkin | 8945e0e | 2004-09-10 06:07:04 +0000 | [diff] [blame^] | 19 | /* 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 Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 24 | if(expr->expr_type == A1TC_EXTENSIBLE) { |
Lev Walkin | 8945e0e | 2004-09-10 06:07:04 +0000 | [diff] [blame^] | 25 | 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 Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 30 | } |
| 31 | |
| 32 | if(expr->meta_type == AMT_TYPE) { |
Lev Walkin | 8945e0e | 2004-09-10 06:07:04 +0000 | [diff] [blame^] | 33 | 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 Walkin | d541c25 | 2004-09-05 10:36:22 +0000 | [diff] [blame] | 43 | } |
Lev Walkin | 8945e0e | 2004-09-10 06:07:04 +0000 | [diff] [blame^] | 44 | ADD_TAG(skip, tt); |
| 45 | return count; |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 46 | } |
| 47 | |
| 48 | if(expr->meta_type == AMT_TYPEREF) { |
Lev Walkin | 8945e0e | 2004-09-10 06:07:04 +0000 | [diff] [blame^] | 49 | expr = asn1f_lookup_symbol(arg, expr->module, expr->reference); |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 50 | if(expr == NULL) return -1; |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 51 | if(expr->_mark & TM_RECURSION) |
| 52 | return -1; |
Lev Walkin | 8945e0e | 2004-09-10 06:07:04 +0000 | [diff] [blame^] | 53 | arg->expr = expr; |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 54 | expr->_mark |= TM_RECURSION; |
Lev Walkin | 8945e0e | 2004-09-10 06:07:04 +0000 | [diff] [blame^] | 55 | count = asn1f_fetch_tags_impl(arg, tags, count, skip, flags); |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 56 | expr->_mark &= ~TM_RECURSION; |
Lev Walkin | 8945e0e | 2004-09-10 06:07:04 +0000 | [diff] [blame^] | 57 | return count; |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 58 | } |
| 59 | |
| 60 | return -1; |
| 61 | } |
| 62 | |
Lev Walkin | 8945e0e | 2004-09-10 06:07:04 +0000 | [diff] [blame^] | 63 | |
| 64 | int |
| 65 | 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) { |
| 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 | |
| 82 | int |
| 83 | 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) { |
| 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 | } |