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