91847a6fb1c23dd07704f5daef5ee1ce8c092c29
[com/asn1c.git] / libasn1fix / asn1fix_class.c
1 #include "asn1fix_internal.h"
2
3 asn1p_expr_t *
4 asn1f_class_access(arg_t *arg, asn1p_expr_t *rhs_pspecs, const asn1p_ref_t *ref) {
5         asn1p_expr_t *ioclass;
6         asn1p_expr_t *classfield;
7         asn1p_expr_t *expr;
8         asn1p_ref_t tmpref;
9
10         assert(ref->comp_count > 1);
11
12     DEBUG("ClassAccess lookup (%s%s) for line %d",
13           asn1f_printable_reference(ref), rhs_pspecs ? ", parameterized" : "",
14           ref->_lineno);
15
16     /*
17          * Fetch the first part of the reference (OBJECT or ObjectSet).
18          * OBJECT.&<something>...
19          * ObjectSet.&<something>...
20          */
21         assert(isupper(ref->components[0].name[0]));
22
23         tmpref = *ref;
24         tmpref.comp_count = 1;
25         ioclass = asn1f_lookup_symbol(arg, rhs_pspecs, &tmpref);
26         if(ioclass == NULL) {
27         DEBUG("ClassAccess lookup (%s) failed",
28               asn1f_printable_reference(&tmpref));
29         errno = ESRCH;
30                 return NULL;
31         }
32         if(ioclass->expr_type == A1TC_REFERENCE) {
33         ioclass = WITH_MODULE(
34             ioclass->module,
35             asn1f_lookup_symbol(arg, ioclass->rhs_pspecs, ioclass->reference));
36         if(ioclass == NULL) {
37                         errno = ESRCH;
38                         return NULL;
39                 }
40         }
41         if(ioclass->expr_type != A1TC_CLASSDEF) {
42                 if(!(ioclass->_mark & TM_BROKEN)) {
43                         ioclass->_mark |= TM_BROKEN;
44                         FATAL("Class field %s lookup at line %d in something that is not a class: %s at line %d",
45                                 asn1f_printable_reference(ref), ref->_lineno,
46                                 ioclass->Identifier,
47                                 ioclass->_lineno);
48                 }
49                 errno = EINVAL;
50                 return NULL;
51         }
52
53         classfield = asn1f_lookup_child(ioclass, ref->components[1].name);
54         if(classfield == NULL) {
55                 DEBUG("CLASS %s does not contain field %s",
56                         ioclass->Identifier, ref->components[1].name);
57                 errno = ESRCH;
58                 return NULL;
59         }
60
61         assert(classfield->meta_type == AMT_OBJECTFIELD);
62
63         DEBUG("CLASS %s -> %s (%d)", ioclass->Identifier,
64                 classfield->Identifier, classfield->expr_type);
65
66         switch(classfield->expr_type) {
67         case A1TC_CLASSFIELD_TFS:
68                 if(TQ_FIRST(&classfield->members)) {
69                         /* Already have something */
70                 } else {
71                         expr = asn1p_expr_new(classfield->_lineno, arg->mod);
72                         expr->expr_type = ASN_TYPE_ANY;
73                         expr->meta_type = AMT_TYPE;
74                         asn1p_expr_add(classfield, expr);
75                 }
76                 /* Fall through */
77         case A1TC_CLASSFIELD_FTVFS:
78                 expr = TQ_FIRST(&classfield->members);
79                 assert(expr);
80                 return expr;
81                 break;
82         default:
83                 FATAL("%s.%s: field type not yet supported. "
84                         "Consider donation to the asn1c author.",
85                         ioclass->Identifier, classfield->Identifier);
86                 return NULL;
87         }
88
89         return NULL;
90 }
91