blob: e0ab94190f968b39bd1313f112d42f8399fcde90 [file] [log] [blame]
Lev Walkincb4cd5b2006-03-14 15:23:06 +00001#include "asn1fix_internal.h"
Lev Walkinaa7f5302006-03-14 15:53:59 +00002#include "asn1fix_cws.h"
Lev Walkin9d542d22006-03-14 16:31:37 +00003
Lev Walkind370e9f2006-03-16 10:03:35 +00004static 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);
8static 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);
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +08009static asn1p_wsyntx_chunk_t *asn1f_next_literal_chunk(asn1p_wsyntx_t *syntax, asn1p_wsyntx_chunk_t *chunk, uint8_t *buf);
10
11int
12asn1f_check_class_object(arg_t *arg) {
13 asn1p_expr_t *expr = arg->expr;
14 asn1p_expr_t *eclass;
15 asn1p_ioc_row_t *row;
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 eclass = asn1f_find_terminal_type(arg, expr);
25 if(!eclass
26 || eclass->meta_type != AMT_OBJECTCLASS
27 || eclass->expr_type != A1TC_CLASSDEF) {
28 return 0;
29 }
30
31 if(!eclass->with_syntax) {
32 DEBUG("Can't process classes without %s just yet",
33 "WITH SYNTAX");
34 return 0;
35 }
36
37 row = asn1p_ioc_row_new(eclass);
38 assert(row);
39
40 ret = _asn1f_parse_class_object_data(arg, eclass, row,
41 eclass->with_syntax,
42 expr->value->value.string.buf + 1,
43 expr->value->value.string.buf
44 + expr->value->value.string.size - 1,
45 0, 0);
46
47 asn1p_ioc_row_delete(row);
48
49 return ret;
50}
Lev Walkin9d542d22006-03-14 16:31:37 +000051
Lev Walkind370e9f2006-03-16 10:03:35 +000052int
53asn1f_parse_class_object(arg_t *arg) {
54 asn1p_expr_t *expr = arg->expr;
55 asn1p_expr_t *eclass;
56 asn1p_ioc_row_t *row;
57 void *new_rows_ptr;
58 int ret;
59
60 if(expr->meta_type != AMT_VALUE
61 || expr->expr_type != A1TC_REFERENCE
62 || !expr->value
63 || expr->value->type != ATV_UNPARSED)
Lev Walkin9d542d22006-03-14 16:31:37 +000064 return 0;
65
Lev Walkind370e9f2006-03-16 10:03:35 +000066 /*
67 * Find the governing class.
68 */
69 eclass = asn1f_find_terminal_type(arg, expr);
70 if(!eclass
71 || eclass->meta_type != AMT_OBJECTCLASS
72 || eclass->expr_type != A1TC_CLASSDEF) {
73 return 0;
74 }
75
76 DEBUG("Value %s of CLASS %s found at line %d",
77 expr->Identifier, eclass->Identifier, expr->_lineno);
78
79 if(!eclass->with_syntax) {
Lev Walkinfaf35a82006-03-16 13:37:03 +000080 DEBUG("Can't process classes without %s just yet",
81 "WITH SYNTAX");
Lev Walkind370e9f2006-03-16 10:03:35 +000082 return 0;
83 }
84
85 row = asn1p_ioc_row_new(eclass);
86 assert(row);
87
88 ret = _asn1f_parse_class_object_data(arg, eclass, row,
89 eclass->with_syntax,
90 expr->value->value.string.buf + 1,
91 expr->value->value.string.buf
92 + expr->value->value.string.size - 1,
93 0, 0);
94 if(ret) {
Lev Walkin67303be2014-10-12 19:22:35 -070095 LOG((int)(ret < 0),
Lev Walkind370e9f2006-03-16 10:03:35 +000096 "Cannot parse %s of CLASS %s found at line %d",
97 expr->Identifier, eclass->Identifier, expr->_lineno);
98 asn1p_ioc_row_delete(row);
99 return ret;
100 }
101
102 new_rows_ptr = realloc(eclass->object_class_matrix.row,
103 (eclass->object_class_matrix.rows + 1)
104 * sizeof(eclass->object_class_matrix.row[0]));
105 assert(new_rows_ptr);
106 eclass->object_class_matrix.row = new_rows_ptr;
107 eclass->object_class_matrix.row[eclass->object_class_matrix.rows] = row;
108 eclass->object_class_matrix.rows++;
109 /* Propagate max identifier length */
110 if(eclass->object_class_matrix.max_identifier_length
111 < row->max_identifier_length)
112 eclass->object_class_matrix.max_identifier_length
113 = row->max_identifier_length;
Lev Walkin9d542d22006-03-14 16:31:37 +0000114
115 return 0;
116}
Lev Walkind370e9f2006-03-16 10:03:35 +0000117
118#define SKIPSPACES for(; buf < bend && isspace(*buf); buf++)
119
120static int
121_asn1f_parse_class_object_data(arg_t *arg, asn1p_expr_t *eclass,
122 struct asn1p_ioc_row_s *row, asn1p_wsyntx_t *syntax,
123 uint8_t *buf, const uint8_t *bend,
124 int optional_mode, uint8_t **newpos) {
125 struct asn1p_wsyntx_chunk_s *chunk;
126 int ret;
127
128 TQ_FOR(chunk, (&syntax->chunks), next) {
129 switch(chunk->type) {
130 case WC_LITERAL: {
131 int token_len = strlen(chunk->content.token);
132 SKIPSPACES;
133 if(bend - buf < token_len
134 || memcmp(buf, chunk->content.token, token_len)) {
135 if(!optional_mode) {
136 FATAL("While parsing object class value %s at line %d: Expected: \"%s\", found: \"%s\"",
137 arg->expr->Identifier, arg->expr->_lineno, chunk->content.token, buf);
138 }
139 if(newpos) *newpos = buf;
140 return -1;
141 }
142 buf += token_len;
143 } break;
144 case WC_WHITESPACE: break; /* Ignore whitespace */
145 case WC_FIELD: {
146 struct asn1p_ioc_cell_s *cell;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800147 asn1p_wsyntx_chunk_t *next_literal;
148 uint8_t *buf_old = buf;
149 uint8_t *p = 0;
Lev Walkinfaf35a82006-03-16 13:37:03 +0000150
151 SKIPSPACES;
152
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800153 next_literal = asn1f_next_literal_chunk(syntax, chunk, buf);
154 if(!next_literal) {
155 p += (bend - p);
156 } else {
157 p = (uint8_t *)strstr((char *)buf, (char *)next_literal->content.token);
158 if(!p) {
159 if (!optional_mode)
160 FATAL("Next literal \"%s\" not found !", next_literal->content.token);
161
162 if(newpos) *newpos = buf_old;
163 return -1;
Lev Walkind370e9f2006-03-16 10:03:35 +0000164 }
165 }
Lev Walkind370e9f2006-03-16 10:03:35 +0000166 cell = asn1p_ioc_row_cell_fetch(row,
167 chunk->content.token);
168 if(cell == NULL) {
169 FATAL("Field reference %s found in WITH SYNAX {} clause does not match actual field in Object Class %s",
170 chunk->content.token,
171 eclass->Identifier, eclass->_lineno);
172 if(newpos) *newpos = buf;
173 return -1;
174 }
175 DEBUG("Reference %s satisfied by %s (%d)",
176 chunk->content.token,
177 buf, p - buf);
178 ret = _asn1f_assign_cell_value(arg, row, cell, buf, p);
Lev Walkindc4376d2006-03-16 11:04:55 +0000179 if(ret) return ret;
Lev Walkind370e9f2006-03-16 10:03:35 +0000180 buf = p;
Lev Walkindc4376d2006-03-16 11:04:55 +0000181 if(newpos) *newpos = buf;
Lev Walkind370e9f2006-03-16 10:03:35 +0000182 } break;
183 case WC_OPTIONALGROUP: {
184 uint8_t *np = 0;
185 SKIPSPACES;
186 ret = _asn1f_parse_class_object_data(arg, eclass, row,
187 chunk->content.syntax, buf, bend, 1, &np);
188 if(newpos) *newpos = np;
189 if(ret && np != buf)
190 return ret;
Lev Walkindc4376d2006-03-16 11:04:55 +0000191 buf = np;
Lev Walkind370e9f2006-03-16 10:03:35 +0000192 } break;
193 }
194 }
195
196
197 if(newpos) *newpos = buf;
198 return 0;
199}
200
201
202static int
203_asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_ioc_cell_s *cell,
204 uint8_t *buf, const uint8_t *bend) {
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800205 asn1p_expr_t *expr = (asn1p_expr_t *)NULL;
Lev Walkinc46b7cb2006-08-18 02:27:55 +0000206 int idLength;
Lev Walkind370e9f2006-03-16 10:03:35 +0000207 char *p;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800208 int new_ref = 1;
209 asn1p_t *asn;
210 asn1p_module_t *mod;
211 asn1p_expr_t *type_expr = (asn1p_expr_t *)NULL;
212 int i, ret = 0, psize;
213 char *pp;
Lev Walkind370e9f2006-03-16 10:03:35 +0000214
215 if((bend - buf) <= 0) {
216 FATAL("Assignment warning: empty string is being assigned into %s for %s at line %d",
217 cell->field->Identifier,
218 arg->expr->Identifier, arg->expr->_lineno);
219 return -1;
220 }
221
222 p = malloc(bend - buf + 1);
223 assert(p);
224 memcpy(p, buf, bend - buf);
225 p[bend - buf] = '\0';
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800226 /* remove trailing space */
227 for (i = bend - buf - 1; (i > 0) && isspace(p[i]); i--)
228 p[i] = '\0';
Lev Walkind370e9f2006-03-16 10:03:35 +0000229
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800230 /* This value 100 should be larger than following formatting string */
231 psize = bend - buf + 100;
232 pp = malloc(psize);
233 if(pp == NULL) {
234 free(p);
235 return -1;
236 }
Lev Walkind370e9f2006-03-16 10:03:35 +0000237
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800238 if(cell->field->expr_type == A1TC_CLASSFIELD_TFS) {
239 ret = snprintf(pp, psize,
240 "M DEFINITIONS ::=\nBEGIN\n"
241 "V ::= %s\n"
242 "END\n",
243 p
244 );
245 } else if(cell->field->expr_type == A1TC_CLASSFIELD_FTVFS) {
246 type_expr = TQ_FIRST(&(cell->field->members));
247 ret = snprintf(pp, psize,
248 "M DEFINITIONS ::=\nBEGIN\n"
249 "v %s ::= %s\n"
250 "END\n",
251 type_expr->reference ?
252 type_expr->reference->components[0].name :
253 _asn1p_expr_type2string(type_expr->expr_type),
254 p
255 );
Lev Walkind370e9f2006-03-16 10:03:35 +0000256 } else {
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800257 WARNING("asn1c only be able to parse TypeFieldSpec and FixedTypeValueFieldSpec. Failed when parsing %s at line %d\n", p, arg->expr->_lineno);
Lev Walkinaf8595a2017-06-27 08:22:30 -0700258 free(p);
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800259 free(pp);
260 return -1;
261 }
262 DEBUG("ASN.1 :\n\n%s\n", pp);
Bi-Ruei, Chiu3dcf05b2017-05-04 21:45:05 +0800263
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800264 assert(ret < psize);
265 psize = ret;
266
267 asn = asn1p_parse_buffer(pp, psize, A1P_NOFLAGS);
268 free(pp);
269 if(asn == NULL) {
270 FATAL("Cannot parse Setting token %s "
271 "at line %d",
272 p,
273 arg->expr->_lineno
274 );
275 free(p);
276 return -1;
277 } else {
278 mod = TQ_FIRST(&(asn->modules));
279 assert(mod);
280 expr = TQ_REMOVE(&(mod->members), next);
281 assert(expr);
282
283 free(expr->Identifier);
284 expr->module = arg->expr->module;
285 expr->_lineno = arg->expr->_lineno;
286 if (expr->reference) {
287 expr->reference->module = arg->expr->module;
288 expr->reference->_lineno = arg->expr->_lineno;
289 expr->Identifier = strdup(expr->reference->components[expr->reference->comp_count - 1].name);
290 } else {
291 expr->Identifier = p;
292 }
293 asn1p_delete(asn);
294 }
295
296 if(expr->reference &&
297 !asn1f_lookup_symbol(arg, arg->mod, expr->rhs_pspecs, expr->reference)) {
298
299 asn1p_ref_free(expr->reference);
300 new_ref = 0;
301 expr->reference = type_expr->reference;
302 if (asn1f_value_resolve(arg, expr, 0)) {
303 expr->reference = 0;
304 asn1p_expr_free(expr);
Lev Walkind370e9f2006-03-16 10:03:35 +0000305 FATAL("Cannot find %s referenced by %s at line %d",
306 p, arg->expr->Identifier,
307 arg->expr->_lineno);
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800308 free(p); /* freeing must happen *after* p was used in FATAL() */
Lev Walkind370e9f2006-03-16 10:03:35 +0000309 return -1;
310 }
311 }
312
313 DEBUG("Field %s assignment of %s got %s",
314 cell->field->Identifier, p, expr->Identifier);
315
316 cell->value = expr;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800317 cell->new_ref = new_ref;
Lev Walkind370e9f2006-03-16 10:03:35 +0000318
Lev Walkinc46b7cb2006-08-18 02:27:55 +0000319 idLength = strlen(expr->Identifier);
320 if(row->max_identifier_length < idLength)
321 row->max_identifier_length = idLength;
Lev Walkind370e9f2006-03-16 10:03:35 +0000322
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800323 if(expr->Identifier != p)
324 free(p);
325
Lev Walkind370e9f2006-03-16 10:03:35 +0000326 return 0;
327}
328
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800329static asn1p_wsyntx_chunk_t *
330asn1f_next_literal_chunk(asn1p_wsyntx_t *syntax, asn1p_wsyntx_chunk_t *chunk, uint8_t *buf)
331{
332 asn1p_wsyntx_chunk_t *next_chunk;
333
334 next_chunk = TQ_NEXT(chunk, next);
335 do {
336 if(next_chunk == (struct asn1p_wsyntx_chunk_s *)0) {
337 if(!syntax->parent)
338 break;
339 next_chunk = TQ_NEXT(syntax->parent, next);
340 } else if(next_chunk->type == WC_LITERAL) {
341 if(strstr((char *)buf, (char *)next_chunk->content.token))
342 break;
343 if(!syntax->parent)
344 break;
345 next_chunk = TQ_NEXT(syntax->parent, next);
346 } else if(next_chunk->type == WC_WHITESPACE) {
347 next_chunk = TQ_NEXT(next_chunk, next);
348 } else if(next_chunk->type == WC_OPTIONALGROUP) {
349 syntax = next_chunk->content.syntax;
350 next_chunk = TQ_FIRST(((&next_chunk->content.syntax->chunks)));
351 } else
352 break;
353 } while (next_chunk);
354
355 return next_chunk;
356}