1 #include "asn1fix_internal.h"
2 #include "asn1fix_cws.h"
3 
4 static int _asn1f_parse_class_object_data(arg_t *, asn1p_expr_t *eclass,
5 		struct asn1p_ioc_row_s *row, asn1p_wsyntx_t *syntax,
6 		uint8_t *buf, const uint8_t *bend,
7 		int optional_mode, uint8_t **newpos);
8 static int _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_ioc_cell_s *cell, uint8_t *buf, const uint8_t *bend);
9 
10 int
asn1f_parse_class_object(arg_t * arg)11 asn1f_parse_class_object(arg_t *arg) {
12 	asn1p_expr_t *expr = arg->expr;
13 	asn1p_expr_t *eclass;
14 	asn1p_ioc_row_t *row;
15 	void *new_rows_ptr;
16 	int ret;
17 
18 	if(expr->meta_type != AMT_VALUE
19 	|| expr->expr_type != A1TC_REFERENCE
20 	|| !expr->value
21 	|| expr->value->type != ATV_UNPARSED)
22 		return 0;
23 
24 	/*
25 	 * Find the governing class.
26 	 */
27 	eclass = asn1f_find_terminal_type(arg, expr);
28 	if(!eclass
29 	|| eclass->meta_type != AMT_OBJECTCLASS
30 	|| eclass->expr_type != A1TC_CLASSDEF) {
31 		return 0;
32 	}
33 
34 	DEBUG("Value %s of CLASS %s found at line %d",
35 		expr->Identifier, eclass->Identifier, expr->_lineno);
36 
37 	if(!eclass->with_syntax) {
38 		DEBUG("Can't process classes without %s just yet",
39 			"WITH SYNTAX");
40 		return 0;
41 	}
42 
43 	row = asn1p_ioc_row_new(eclass);
44 	assert(row);
45 
46 	ret = _asn1f_parse_class_object_data(arg, eclass, row,
47 		eclass->with_syntax,
48 		expr->value->value.string.buf + 1,
49 		expr->value->value.string.buf
50 			+ expr->value->value.string.size - 1,
51 		0, 0);
52 	if(ret) {
53 		LOG((ret < 0),
54 			"Cannot parse %s of CLASS %s found at line %d",
55 			expr->Identifier, eclass->Identifier, expr->_lineno);
56 		asn1p_ioc_row_delete(row);
57 		return ret;
58 	}
59 
60 	new_rows_ptr = realloc(eclass->object_class_matrix.row,
61 			(eclass->object_class_matrix.rows + 1)
62 			* sizeof(eclass->object_class_matrix.row[0]));
63 	assert(new_rows_ptr);
64 	eclass->object_class_matrix.row = new_rows_ptr;
65 	eclass->object_class_matrix.row[eclass->object_class_matrix.rows] = row;
66 	eclass->object_class_matrix.rows++;
67 	/* Propagate max identifier length */
68 	if(eclass->object_class_matrix.max_identifier_length
69 			< row->max_identifier_length)
70 		eclass->object_class_matrix.max_identifier_length
71 			= row->max_identifier_length;
72 
73 	return 0;
74 }
75 
76 #define	SKIPSPACES	for(; buf < bend && isspace(*buf); buf++)
77 
78 static int
_asn1f_parse_class_object_data(arg_t * arg,asn1p_expr_t * eclass,struct asn1p_ioc_row_s * row,asn1p_wsyntx_t * syntax,uint8_t * buf,const uint8_t * bend,int optional_mode,uint8_t ** newpos)79 _asn1f_parse_class_object_data(arg_t *arg, asn1p_expr_t *eclass,
80 		struct asn1p_ioc_row_s *row, asn1p_wsyntx_t *syntax,
81 		uint8_t *buf, const uint8_t *bend,
82 		int optional_mode, uint8_t **newpos) {
83 	struct asn1p_wsyntx_chunk_s *chunk;
84 	int ret;
85 
86 	TQ_FOR(chunk, (&syntax->chunks), next) {
87 		switch(chunk->type) {
88 		case WC_LITERAL: {
89 			int token_len = strlen(chunk->content.token);
90 			SKIPSPACES;
91 			if(bend - buf < token_len
92 			|| memcmp(buf, chunk->content.token, token_len)) {
93 				if(!optional_mode) {
94 					FATAL("While parsing object class value %s at line %d: Expected: \"%s\", found: \"%s\"",
95 					arg->expr->Identifier, arg->expr->_lineno, chunk->content.token, buf);
96 				}
97 				if(newpos) *newpos = buf;
98 				return -1;
99 			}
100 			buf += token_len;
101 		    } break;
102 		case WC_WHITESPACE: break;	/* Ignore whitespace */
103 		case WC_FIELD: {
104 			struct asn1p_ioc_cell_s *cell;
105 			int lbraces = 0;
106 			uint8_t *p;
107 
108 			SKIPSPACES;
109 
110 			p = buf;
111 			if(p < bend && *p == '{')
112 				lbraces = 1, p++;
113 			for(; p < bend; p++) {
114 				if(lbraces) {
115 					/* Search the terminating brace */
116 					switch(*p) {
117 					case '}': lbraces--; break;
118 					case '{': lbraces++; break;
119 					}
120 				} else if(isspace(*p)) {
121 					break;
122 				}
123 			}
124 			if(lbraces) {
125 				FATAL("Field reference %s found in class value definition for %s at line %d can not be satisfied by broken value \"%s\"",
126 				chunk->content.token,
127 				arg->expr->Identifier, arg->expr->_lineno, buf);
128 				if(newpos) *newpos = buf;
129 				return -1;
130 			}
131 			cell = asn1p_ioc_row_cell_fetch(row,
132 					chunk->content.token);
133 			if(cell == NULL) {
134 				FATAL("Field reference %s found in WITH SYNAX {} clause does not match actual field in Object Class %s",
135 					chunk->content.token,
136 					eclass->Identifier, eclass->_lineno);
137 				if(newpos) *newpos = buf;
138 				return -1;
139 			}
140 			DEBUG("Reference %s satisfied by %s (%d)",
141 				chunk->content.token,
142 				buf, p - buf);
143 			ret = _asn1f_assign_cell_value(arg, row, cell, buf, p);
144 			if(ret) return ret;
145 			buf = p;
146 			if(newpos) *newpos = buf;
147 		    } break;
148 		case WC_OPTIONALGROUP: {
149 			uint8_t *np = 0;
150 			SKIPSPACES;
151 			ret = _asn1f_parse_class_object_data(arg, eclass, row,
152 				chunk->content.syntax, buf, bend, 1, &np);
153 			if(newpos) *newpos = np;
154 			if(ret && np != buf)
155 				return ret;
156 			buf = np;
157 		    } break;
158 		}
159 	}
160 
161 
162 	if(newpos) *newpos = buf;
163 	return 0;
164 }
165 
166 
167 static int
_asn1f_assign_cell_value(arg_t * arg,struct asn1p_ioc_row_s * row,struct asn1p_ioc_cell_s * cell,uint8_t * buf,const uint8_t * bend)168 _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_ioc_cell_s *cell,
169 		uint8_t *buf, const uint8_t *bend) {
170 	asn1p_expr_t *expr;
171 	asn1p_ref_t *ref;
172 	int idLength;
173 	char *p;
174 
175 	if((bend - buf) <= 0) {
176 		FATAL("Assignment warning: empty string is being assigned into %s for %s at line %d",
177 			cell->field->Identifier,
178 			arg->expr->Identifier, arg->expr->_lineno);
179 		return -1;
180 	}
181 
182 	p = malloc(bend - buf + 1);
183 	assert(p);
184 	memcpy(p, buf, bend - buf);
185 	p[bend - buf] = '\0';
186 
187 	if(!isalpha(*p)) {
188 
189 		if(isdigit(*p)) {
190 			asn1c_integer_t value;
191 			if(asn1p_atoi(p, &value)) {
192 				FATAL("Value %s at line %d is too large for this compiler! Contact the asn1c author.\n", p, arg->expr->_lineno);
193 				return -1;
194 			}
195 			expr = asn1p_expr_new(arg->expr->_lineno, arg->expr->module);
196 			expr->Identifier = p;
197 			expr->meta_type = AMT_VALUE;
198 			expr->expr_type = ASN_BASIC_INTEGER;
199 			expr->value = asn1p_value_fromint(value);
200 		} else {
201 			WARNING("asn1c is not yet able to parse arbitrary direct values; try converting %s at line %d to a reference.", p, arg->expr->_lineno);
202 			free(p);
203 			return 1;
204 		}
205 	} else {
206 		ref = asn1p_ref_new(arg->expr->_lineno);
207 		asn1p_ref_add_component(ref, p, RLT_UNKNOWN);
208 		assert(ref);
209 
210 		expr = asn1f_lookup_symbol(arg, arg->mod, arg->expr->rhs_pspecs, ref);
211 		if(!expr) {
212 			FATAL("Cannot find %s referenced by %s at line %d",
213 				p, arg->expr->Identifier,
214 				arg->expr->_lineno);
215 			return -1;
216 		}
217 	}
218 
219 	DEBUG("Field %s assignment of %s got %s",
220 		cell->field->Identifier, p, expr->Identifier);
221 
222 	cell->value = expr;
223 
224 	idLength = strlen(expr->Identifier);
225 	if(row->max_identifier_length < idLength)
226 		row->max_identifier_length = idLength;
227 
228 	return 0;
229 }
230 
231