Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 1 | #include "asn1fix_internal.h" |
| 2 | |
| 3 | static int _compare_value(asn1p_expr_t *expr1, asn1p_expr_t *expr2) { |
| 4 | if(expr2->value->type == ATV_INTEGER |
| 5 | && expr1->value->type == ATV_INTEGER) { |
| 6 | return expr2->value->value.v_integer |
| 7 | - expr1->value->value.v_integer; |
| 8 | } else { |
| 9 | return -1; |
| 10 | } |
| 11 | } |
| 12 | |
| 13 | /* |
| 14 | * Check the validity of an INTEGER type. |
| 15 | */ |
| 16 | int |
| 17 | asn1f_fix_integer(arg_t *arg) { |
| 18 | asn1p_expr_t *expr = arg->expr; |
| 19 | asn1p_expr_t *iv; |
| 20 | int rvalue = 0; |
| 21 | int ret; |
| 22 | |
| 23 | if(expr->expr_type != ASN_BASIC_INTEGER) |
| 24 | return 0; /* Just ignore it */ |
| 25 | |
Lev Walkin | 0385018 | 2005-03-10 10:02:50 +0000 | [diff] [blame] | 26 | DEBUG("(\"%s\", %x) for line %d", |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 27 | expr->Identifier, expr->expr_type, expr->_lineno); |
| 28 | |
| 29 | /* |
| 30 | * Scan the integer values in search for inconsistencies. |
| 31 | */ |
| 32 | TQ_FOR(iv, &(expr->members), next) { |
| 33 | |
| 34 | DEBUG("\tItem %s(%s)", iv->Identifier, |
| 35 | asn1f_printable_value(iv->value)); |
| 36 | |
| 37 | /* |
| 38 | * Found "...", check correctness. |
| 39 | */ |
| 40 | if(iv->expr_type == A1TC_EXTENSIBLE) { |
| 41 | arg->eh(1, |
| 42 | "INTEGER %s at line %d: " |
| 43 | "Extension marker is not allowed", |
| 44 | expr->Identifier, |
| 45 | iv->_lineno |
| 46 | ); |
| 47 | rvalue = -1; |
| 48 | continue; |
| 49 | } |
| 50 | |
| 51 | if(iv->Identifier == NULL |
| 52 | || iv->expr_type != A1TC_UNIVERVAL) { |
| 53 | arg->eh(1, |
| 54 | "INTEGER %s at line %d: " |
| 55 | "Unsupported enumeration element %s", |
| 56 | expr->Identifier, |
| 57 | iv->_lineno, |
| 58 | iv->Identifier?iv->Identifier:"<Anonymous>" |
| 59 | ); |
| 60 | rvalue = -1; |
| 61 | continue; |
| 62 | } |
| 63 | |
| 64 | if(iv->value == NULL) { |
| 65 | arg->eh(1, |
| 66 | "INTEGER %s at line %d: " |
| 67 | "Value for the identifier %s " |
| 68 | "must be set explicitly", |
| 69 | expr->Identifier, |
| 70 | iv->_lineno, |
| 71 | iv->Identifier |
| 72 | ); |
| 73 | rvalue = -1; |
| 74 | continue; |
| 75 | } else if(iv->value->type == ATV_REFERENCED) { |
| 76 | /* |
| 77 | * Resolve the value, once and for all. |
| 78 | */ |
Lev Walkin | 9288d1c | 2005-03-10 11:27:13 +0000 | [diff] [blame] | 79 | if(asn1f_value_resolve(arg, iv, 0)) { |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 80 | /* This function will emit messages */ |
| 81 | rvalue = -1; |
| 82 | continue; |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | if(iv->value->type != ATV_INTEGER) { |
| 87 | arg->eh(1, |
| 88 | "INTEGER %s at line %d: " |
| 89 | "Value for the identifier %s " |
| 90 | "is not compatible with INTEGER type", |
| 91 | expr->Identifier, |
| 92 | iv->_lineno); |
| 93 | rvalue = -1; |
| 94 | continue; |
| 95 | } |
| 96 | |
| 97 | /* |
| 98 | * Check that all identifiers are distinct. |
| 99 | */ |
| 100 | ret = asn1f_check_unique_expr_child(arg, iv, NULL); |
| 101 | RET2RVAL(ret, rvalue); |
| 102 | /* |
| 103 | * Check that all values are distinct. |
| 104 | */ |
| 105 | ret = asn1f_check_unique_expr_child(arg, iv, _compare_value); |
| 106 | RET2RVAL(ret, rvalue); |
| 107 | } |
| 108 | |
| 109 | |
| 110 | return rvalue; |
| 111 | } |
| 112 | |
| 113 | static int |
| 114 | _asn1f_make_sure_type_is(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_type_e type) { |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 115 | asn1p_expr_t *next_expr; |
Lev Walkin | d9bd775 | 2004-06-05 08:17:50 +0000 | [diff] [blame] | 116 | asn1p_expr_type_e expr_type; |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 117 | int ret; |
| 118 | |
| 119 | expr_type = expr->expr_type; |
| 120 | |
| 121 | /* |
| 122 | * Here we're trying to make sure that the type of the given |
| 123 | * expression is really what is expected. |
| 124 | * This is ensured in two ways. |
| 125 | * First, if the immediate type matches the provided one, |
| 126 | * this is a clear hit. |
| 127 | */ |
| 128 | if(expr_type == type) |
| 129 | return 0; |
| 130 | |
| 131 | /* |
| 132 | * Otherwise, it must be either a reference or a different type. |
| 133 | */ |
| 134 | if(expr_type != A1TC_REFERENCE) { |
| 135 | errno = EPERM; |
| 136 | return -1; |
| 137 | } |
| 138 | |
| 139 | assert(expr_type == A1TC_REFERENCE); |
| 140 | assert(expr->reference); |
| 141 | |
| 142 | /* |
| 143 | * Then, it is a reference. For a reference, try to resolve type |
| 144 | * and try again. |
| 145 | */ |
Lev Walkin | 6fec44d | 2004-08-22 03:10:23 +0000 | [diff] [blame] | 146 | next_expr = asn1f_lookup_symbol(arg, expr->module, expr->reference); |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 147 | if(next_expr == NULL) { |
| 148 | errno = ESRCH; |
| 149 | return -1; |
| 150 | } |
| 151 | |
| 152 | /* |
| 153 | * If symbol is here, recursively check that it conforms to the type. |
| 154 | */ |
Lev Walkin | 6fec44d | 2004-08-22 03:10:23 +0000 | [diff] [blame] | 155 | WITH_MODULE(next_expr->module, |
| 156 | ret = _asn1f_make_sure_type_is(arg, next_expr, type)); |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 157 | |
| 158 | return ret; |
| 159 | } |
| 160 | |
| 161 | |