aboutsummaryrefslogtreecommitdiffstats
path: root/libasn1fix/asn1fix_class.c
blob: 32ad896347ae9d8b02cd94e917da6d27896c6f72 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include "asn1fix_internal.h"

asn1p_expr_t *
asn1f_class_access(arg_t *arg, asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, asn1p_ref_t *ref) {
	asn1p_expr_t *ioclass;
	asn1p_expr_t *classfield;
	asn1p_expr_t *expr;
	asn1p_ref_t tmpref;

	assert(ref->comp_count > 1);

	DEBUG("ClassAccess lookup (%s) for line %d", asn1f_printable_reference(ref), ref->_lineno);

	/*
	 * Fetch the first part of the reference (OBJECT or ObjectSet).
	 * OBJECT.&<something>...
	 * ObjectSet.&<something>...
	 */
	assert(isupper(ref->components[0].name[0]));

	tmpref = *ref;
	tmpref.comp_count = 1;
	ioclass = asn1f_lookup_symbol(arg, mod, rhs_pspecs, &tmpref);
	if(ioclass == NULL) {
		errno = ESRCH;
		return NULL;
	}
	if(ioclass->expr_type == A1TC_REFERENCE) {
		ioclass = asn1f_lookup_symbol(arg,
				ioclass->module,
				ioclass->rhs_pspecs,
				ioclass->reference);
		if(ioclass == NULL) {
			errno = ESRCH;
			return NULL;
		}
	}
	if(ioclass->expr_type != A1TC_CLASSDEF) {
		if(!(ioclass->_mark & TM_BROKEN)) {
			ioclass->_mark |= TM_BROKEN;
			FATAL("Class field %s lookup at line %d in something that is not a class: %s at line %d",
				asn1f_printable_reference(ref), ref->_lineno,
				ioclass->Identifier,
				ioclass->_lineno);
		}
		errno = EINVAL;
		return NULL;
	}

	classfield = asn1f_lookup_child(ioclass, ref->components[1].name);
	if(classfield == NULL) {
		DEBUG("CLASS %s does not contain field %s",
			ioclass->Identifier, ref->components[1].name);
		errno = ESRCH;
		return NULL;
	}

	assert(classfield->meta_type == AMT_OBJECTFIELD);

	DEBUG("CLASS %s -> %s (%d)", ioclass->Identifier,
		classfield->Identifier, classfield->expr_type);

	switch(classfield->expr_type) {
	case A1TC_CLASSFIELD_TFS:
		if(TQ_FIRST(&classfield->members)) {
			/* Already have something */
		} else {
			expr = asn1p_expr_new(classfield->_lineno, mod);
			expr->expr_type = ASN_TYPE_ANY;
			expr->meta_type = AMT_TYPE;
			asn1p_expr_add(classfield, expr);
		}
		/* Fall through */
	case A1TC_CLASSFIELD_FTVFS:
		expr = TQ_FIRST(&classfield->members);
		assert(expr);
		return expr;
		break;
	default:
		FATAL("%s.%s: field type not yet supported. "
			"Consider donation to the asn1c author.",
			ioclass->Identifier, classfield->Identifier);
		return NULL;
	}

	return NULL;
}