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