blob: 3542e0cdda6ee681fc1ba8bc9d90aa036b297af2 [file] [log] [blame]
vlmfa67ddc2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
2
3typedef enum field_category {
4 OFC_INVALID, /* Invalid object field category */
5 OFC_TYPE,
6 OFC_FIXED_TYPE_VALUE,
7 OFC_VARIABLE_TYPE_VALUE,
8 OFC_FIXED_TYPE_VALUE_SET,
9 OFC_VARIABLE_TYPE_VALUE_SET,
10 OFC_INFORMATION_OBJECT,
11 OFC_INFORMATION_OBJECT_SET,
12} field_category_e;
13
14typedef enum object_category {
15 OC_INVALID,
16 OC_OBJECT,
17 OC_OBJECTSET,
18} object_category_e;
19
20static field_category_e asn1f_class_field_category(asn1p_expr_t *ofield);
21static object_category_e asn1f_class_object_category(asn1p_expr_t *expr);
22static asn1p_expr_t *
23asn1f_class_dot_lookup(arg_t *arg, asn1p_expr_t *obj, asn1p_ref_t *ref);
24
25asn1p_expr_t *
vlm2e0c1942004-08-22 03:10:23 +000026asn1f_class_access(arg_t *arg, asn1p_module_t *mod, asn1p_ref_t *ref) {
vlmfa67ddc2004-06-03 03:38:44 +000027 asn1p_expr_t *obj; /* Information Object or Object Set */
28 object_category_e obj_cat; /* Object category */
29 //field_category_e field_cat; /* Field category */
30 asn1p_expr_t *result;
31 asn1p_ref_t tmpref;
32
vlmfa67ddc2004-06-03 03:38:44 +000033 assert(ref->comp_count > 1);
34
vlmfd245932005-03-10 10:02:50 +000035 DEBUG("(%s) for line %d", asn1f_printable_reference(ref), ref->_lineno);
vlmfa67ddc2004-06-03 03:38:44 +000036
37 /*
38 * Fetch the first part of the reference (OBJECT or ObjectSet).
39 * OBJECT.&<something>...
40 * ObjectSet.&<something>...
41 */
42 assert(isupper(ref->components[0].name[0]));
43
44 tmpref = *ref;
45 tmpref.comp_count = 1;
vlm2e0c1942004-08-22 03:10:23 +000046 obj = asn1f_lookup_symbol(arg, mod, &tmpref);
vlmfa67ddc2004-06-03 03:38:44 +000047 if(obj == NULL) {
48 errno = ESRCH;
49 return NULL;
50 }
51
52 /*
53 * Make sure the symbol lexical property (upper-case, lower-case)
54 * corresponds to the type of the expression returned by
55 * lookup_symbol().
56 */
57 obj_cat = asn1f_class_object_category(obj);
58 switch(obj_cat) {
59 case OC_OBJECT:
60 case OC_OBJECTSET:
61 if(ref->components[0].lex_type
62 == (obj_cat==OC_OBJECT)
63 ? RLT_CAPITALS
64 : RLT_Uppercase)
65 break;
66 /* Fall through */
67 case OC_INVALID:
68 WARNING("Symbol \"%s\" is not compatible "
69 "with referenced expression \"%s\" at line %d",
70 ref->components[0].name,
71 obj->Identifier, obj->_lineno);
72 errno = EPERM;
73 return NULL;
74 }
75
76 /*
77 * Find the specified field within the object.
78 */
79 result = asn1f_class_dot_lookup(arg, obj, ref);
80 if(result == NULL) {
81 return NULL;
82 }
83
84 //field_cat = asn1f_class_field_category(result);
85
86 DEBUG("FILLME: %s", result->Identifier);
87
88 return result;
89}
90
91static object_category_e
92asn1f_class_object_category(asn1p_expr_t *expr) {
93
94 switch(expr->meta_type) {
95 case AMT_OBJECT:
96 return OC_OBJECT;
97 case AMT_OBJECTSET:
98 return OC_OBJECTSET;
99 case AMT_VALUESET:
100 if(expr->expr_type == A1TC_REFERENCE
101 && expr->reference
102 && expr->reference->comp_count == 1
103 && expr->reference->components[0].lex_type == RLT_CAPITALS)
104 {
105 /* FIXME: use find_terminal_type instead! */
106 return OC_OBJECTSET;
107 }
108 break;
109 default:
110 break;
111 }
112
113 return OC_INVALID;
114}
115
116static field_category_e
117asn1f_class_field_category(asn1p_expr_t *ofield) {
vlm1cc17972005-01-22 16:02:45 +0000118
119 assert(ofield);
120
vlmfa67ddc2004-06-03 03:38:44 +0000121 if(ofield->Identifier[0] != '&') {
122 assert(ofield->Identifier[0] == '&');
123 return OFC_INVALID;
124 }
125
126 if(isupper(ofield->Identifier[1])) {
127 if(ofield->reference) {
128 enum asn1p_ref_lex_type_e lex_type
129 = ofield->reference->components[0].lex_type;
130
131 switch(lex_type) {
132 case RLT_CAPITALS:
133 return OFC_INFORMATION_OBJECT_SET;
134 case RLT_Uppercase:
135 return OFC_FIXED_TYPE_VALUE_SET;
136 case RLT_AmpUppercase:
137 return OFC_VARIABLE_TYPE_VALUE_SET;
138 default:
139 break;
140 }
141 } else {
142 if(ofield->expr_type == A1TC_CLASSFIELD)
143 return OFC_TYPE;
144
145 switch(ofield->meta_type) {
146 case AMT_TYPE:
147 case AMT_TYPEREF:
148 return OFC_FIXED_TYPE_VALUE_SET;
149 default:
150 break;
151 }
152
153 }
154 } else {
155 if(ofield->reference) {
156 enum asn1p_ref_lex_type_e lex_type
157 = ofield->reference->components[0].lex_type;
158
159 switch(lex_type) {
160 case RLT_CAPITALS:
161 return OFC_INFORMATION_OBJECT;
162 case RLT_Uppercase:
163 return OFC_FIXED_TYPE_VALUE;
164 case RLT_AmpUppercase:
165 return OFC_VARIABLE_TYPE_VALUE;
166 default:
167 break;
168 }
169 } else {
170 switch(ofield->meta_type) {
171 case AMT_TYPE:
172 case AMT_TYPEREF:
173 return OFC_FIXED_TYPE_VALUE;
174 default:
175 break;
176 }
177 }
178 }
179
180 return OFC_INVALID;
181}
182
183
184static asn1p_expr_t *
185asn1f_class_dot_lookup(arg_t *arg, asn1p_expr_t *obj, asn1p_ref_t *ref) {
186 asn1p_expr_t *ofield = NULL; /* Information Object's Field */
187 field_category_e field_cat; /* Field category */
188 int comp;
189
190 assert(ref->comp_count >= 2);
191
192 for(comp = 1 /* sic! */; comp < ref->comp_count; comp++) {
193 int is_last_component = (comp + 1 == ref->comp_count);
194 char *comp_name = ref->components[comp].name;
195
196 ofield = asn1f_lookup_child(obj, comp_name);
197 if(ofield == NULL) {
vlm7b9b5082005-01-22 16:04:32 +0000198 DEBUG("Cannot find field \"%s\" in \"%s\" at line %d",
vlmfa67ddc2004-06-03 03:38:44 +0000199 ref->components[1].name,
200 obj->Identifier,
201 obj->_lineno);
vlm1cc17972005-01-22 16:02:45 +0000202 errno = EPERM;
203 return NULL;
vlmfa67ddc2004-06-03 03:38:44 +0000204 }
205
206 /*
207 * Compute the category of the field of
208 * the information object class.
209 */
210 field_cat = asn1f_class_field_category(ofield);
211
212 switch(field_cat) {
213 case OFC_INVALID:
214 WARNING("Invalid field category of \"%s\" at line %d",
215 ofield->Identifier, ofield->_lineno);
216 errno = EPERM;
217 return NULL;
218 case OFC_TYPE:
219 case OFC_FIXED_TYPE_VALUE:
220 case OFC_VARIABLE_TYPE_VALUE:
221 case OFC_FIXED_TYPE_VALUE_SET:
222 case OFC_VARIABLE_TYPE_VALUE_SET:
223 if(!is_last_component) {
224 FATAL("Field name component \"%s\" at line %d "
225 "specifies non-dereferenceable thing",
226 comp_name, ref->_lineno);
227 errno = EPERM;
228 return NULL;
229 }
230 break;
231 case OFC_INFORMATION_OBJECT:
232 case OFC_INFORMATION_OBJECT_SET:
233 obj = ofield;
234 break;
235 }
236 }
237
238 assert(ofield);
239 return ofield;
240}