3 #include "asn1fix_internal.h"
4 #include "asn1fix_cws.h"
6 static int _asn1f_parse_class_object_data(arg_t *, asn1p_expr_t *eclass,
7 struct asn1p_ioc_row_s *row, asn1p_wsyntx_t *syntax,
8 const uint8_t *buf, const uint8_t *bend,
9 int optional_mode, const uint8_t **newpos, int counter);
10 static int _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_cell_s *cell, const uint8_t *buf, const uint8_t *bend, int counter);
11 static asn1p_wsyntx_chunk_t *asn1f_next_literal_chunk(asn1p_wsyntx_t *syntax, asn1p_wsyntx_chunk_t *chunk, const uint8_t *buf);
14 asn1f_check_class_object(arg_t *arg) {
15 asn1p_expr_t *expr = arg->expr;
20 if(expr->meta_type != AMT_VALUESET
21 || expr->expr_type != A1TC_REFERENCE
23 || expr->value->type != ATV_UNPARSED) {
27 eclass = asn1f_find_terminal_type(arg, expr);
29 || eclass->meta_type != AMT_OBJECTCLASS
30 || eclass->expr_type != A1TC_CLASSDEF) {
34 if(!eclass->with_syntax) {
35 DEBUG("Can't process classes without %s just yet",
40 row = asn1p_ioc_row_new(eclass);
43 ret = _asn1f_parse_class_object_data(arg, eclass, row,
45 expr->value->value.string.buf + 1,
46 expr->value->value.string.buf
47 + expr->value->value.string.size - 1,
50 asn1p_ioc_row_delete(row);
56 _asn1f_is_ioc_row_duplicate(asn1p_ioc_table_t *it, asn1p_ioc_row_t *row) {
61 for(size_t i = 0; i < it->rows; i++) {
62 switch(asn1p_ioc_row_match(it->row[i], row)) {
69 return 1; /* Duplicate! */
75 struct parse_object_key {
77 asn1p_expr_t *expr; /* InformationObjectSet */
78 asn1p_expr_t *eclass; /* CLASS */
79 int sequence; /* Sequence counter */
83 * Add to the IoC table if the row is unique.
86 _asn1f_add_unique_row(arg_t *arg, asn1p_expr_t *expr, asn1p_ioc_row_t *row) {
87 assert(expr->ioc_table);
89 /* Look for duplicates */
90 switch(_asn1f_is_ioc_row_duplicate(expr->ioc_table, row)) {
92 DEBUG("Found Information Object Duplicate in %s", expr->Identifier,
99 /* Proper duplicate detected; ignore */
100 asn1p_ioc_row_delete(row);
104 asn1p_ioc_table_add(expr->ioc_table, row);
110 * Given a single blob of unparsed Information Object specification, parse it
111 * into a given InformationObjectSet.
114 _asn1f_parse_object_cb(const uint8_t *buf, size_t size, void *keyp) {
115 struct parse_object_key *key = keyp;
116 arg_t *arg = key->arg;
117 asn1p_expr_t *expr = key->expr;
118 asn1p_expr_t *eclass = key->eclass;
119 asn1p_ioc_row_t *row;
124 row = asn1p_ioc_row_new(eclass);
127 ret = _asn1f_parse_class_object_data(arg, eclass, row, eclass->with_syntax,
128 buf, buf + size, 0, 0, key->sequence);
130 LOG(ret, "Cannot parse %s of CLASS %s found at line %d",
131 expr->Identifier, eclass->Identifier, expr->_lineno);
132 asn1p_ioc_row_delete(row);
136 /* Add object to a CLASS. */
137 if(_asn1f_add_unique_row(arg, eclass, row) != 0)
141 * Add a copy of the object to the Information Object Set.
143 row = asn1p_ioc_row_new(eclass);
145 ret = _asn1f_parse_class_object_data(arg, eclass, row, eclass->with_syntax,
146 buf, buf + size, 0, 0, key->sequence);
149 if(_asn1f_add_unique_row(arg, expr, row) != 0)
156 _asn1f_foreach_unparsed_union(const asn1p_constraint_t *ct_union,
157 int (*process)(const uint8_t *buf, size_t size,
160 assert(ct_union->type == ACT_CA_UNI);
162 for(size_t j = 0; j < ct_union->el_count; j++) {
163 const asn1p_constraint_t *ct2 = ct_union->elements[j];
164 if(ct2->type == ACT_EL_VALUE && ct2->value->type == ATV_UNPARSED) {
166 && process(ct2->value->value.string.buf + 1,
167 ct2->value->value.string.size - 2, key)
180 _asn1f_foreach_unparsed(arg_t *arg, const asn1p_constraint_t *ct,
181 int (*process)(const uint8_t *buf, size_t size,
184 struct parse_object_key *key = keyp;
189 DEBUG("Constraint is of unknown type %d for CWS", ct->type);
191 case ACT_EL_EXT: /* ... */
193 key->expr->ioc_table->extensible = 1;
196 case ACT_CA_UNI: /* | */
197 return _asn1f_foreach_unparsed_union(ct, process, keyp);
198 case ACT_CA_CSV: /* , */
201 if(ct->value->type == ATV_UNPARSED) {
203 && process(ct->value->value.string.buf + 1,
204 ct->value->value.string.size - 2, key)
212 for(size_t i = 0; i < ct->el_count; i++) {
213 const asn1p_constraint_t *ct1 = ct->elements[i];
214 if(_asn1f_foreach_unparsed(arg, ct1, process, keyp) != 0) {
223 _asn1f_constraint_looks_like_object_set(arg_t *arg,
224 const asn1p_constraint_t *ct) {
225 return 0 == _asn1f_foreach_unparsed(arg, ct, NULL, NULL);
229 asn1f_parse_class_object(arg_t *arg) {
230 asn1p_expr_t *expr = arg->expr;
231 asn1p_expr_t *eclass;
235 } source = FROM_VALUE;
237 if(expr->meta_type == AMT_VALUE
238 && expr->expr_type == A1TC_REFERENCE
239 && expr->value && expr->value->type == ATV_UNPARSED) {
241 } else if(expr->meta_type != AMT_VALUESET
242 || expr->expr_type != A1TC_REFERENCE) {
244 } else if(expr->value && expr->value->type == ATV_UNPARSED) {
246 } else if(!expr->value) {
247 if(_asn1f_constraint_looks_like_object_set(arg, expr->constraints)) {
248 source = FROM_CONSTRAINT;
257 * Find the governing class.
259 eclass = asn1f_find_terminal_type(arg, expr);
261 || eclass->meta_type != AMT_OBJECTCLASS
262 || eclass->expr_type != A1TC_CLASSDEF) {
266 DEBUG("Value %s of CLASS %s found at line %d",
267 expr->Identifier, eclass->Identifier, expr->_lineno);
269 if(!eclass->with_syntax) {
270 DEBUG("Can't process classes without %s just yet",
275 struct parse_object_key key = {
279 .sequence = eclass->_type_unique_index
282 if(!expr->ioc_table) {
283 expr->ioc_table = asn1p_ioc_table_new();
286 if(!eclass->ioc_table) {
287 eclass->ioc_table = asn1p_ioc_table_new();
292 if(_asn1f_parse_object_cb(expr->value->value.string.buf + 1,
293 expr->value->value.string.size - 2, &key)
298 case FROM_CONSTRAINT:
299 if(_asn1f_foreach_unparsed(arg, expr->constraints,
300 _asn1f_parse_object_cb, &key)
306 eclass->_type_unique_index = key.sequence;
311 #define SKIPSPACES for(; buf < bend && isspace(*buf); buf++)
314 _asn1f_parse_class_object_data(arg_t *arg, asn1p_expr_t *eclass,
315 struct asn1p_ioc_row_s *row, asn1p_wsyntx_t *syntax,
316 const uint8_t *buf, const uint8_t *bend,
317 int optional_mode, const uint8_t **newpos, int counter) {
318 struct asn1p_wsyntx_chunk_s *chunk;
321 TQ_FOR(chunk, (&syntax->chunks), next) {
322 switch(chunk->type) {
324 int token_len = strlen(chunk->content.token);
326 if(bend - buf < token_len
327 || memcmp(buf, chunk->content.token, token_len)) {
329 FATAL("While parsing object class value %s at line %d: Expected: \"%s\", found: \"%s\"",
330 arg->expr->Identifier, arg->expr->_lineno, chunk->content.token, buf);
332 if(newpos) *newpos = buf;
337 case WC_WHITESPACE: break; /* Ignore whitespace */
339 struct asn1p_ioc_cell_s *cell;
340 asn1p_wsyntx_chunk_t *next_literal;
341 const uint8_t *buf_old = buf;
342 const uint8_t *p = 0;
346 next_literal = asn1f_next_literal_chunk(syntax, chunk, buf);
350 p = (uint8_t *)strstr((const char *)buf, (const char *)next_literal->content.token);
353 FATAL("Next literal \"%s\" not found !", next_literal->content.token);
355 if(newpos) *newpos = buf_old;
359 cell = asn1p_ioc_row_cell_fetch(row,
360 chunk->content.token);
362 FATAL("Field reference %s found in WITH SYNAX {} clause does not match actual field in Object Class %s",
363 chunk->content.token,
364 eclass->Identifier, eclass->_lineno);
365 if(newpos) *newpos = buf;
368 DEBUG("Reference %s satisfied by %s (%d)",
369 chunk->content.token,
371 ret = _asn1f_assign_cell_value(arg, cell, buf, p, counter);
374 if(newpos) *newpos = buf;
376 case WC_OPTIONALGROUP: {
377 const uint8_t *np = 0;
379 ret = _asn1f_parse_class_object_data(arg, eclass, row,
380 chunk->content.syntax, buf, bend, 1, &np, counter);
381 if(newpos) *newpos = np;
390 if(newpos) *newpos = buf;
396 _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_cell_s *cell,
397 const uint8_t *buf, const uint8_t *bend, int counter) {
398 asn1p_expr_t *expr = (asn1p_expr_t *)NULL;
399 char *mivr; /* Most Immediate Value Representation */
402 asn1p_expr_t *type_expr = (asn1p_expr_t *)NULL;
403 int i, ret = 0, psize;
406 if((bend - buf) <= 0) {
407 FATAL("Assignment warning: empty string is being assigned into %s for %s at line %d",
408 cell->field->Identifier,
409 arg->expr->Identifier, arg->expr->_lineno);
413 mivr = malloc(bend - buf + 1);
415 memcpy(mivr, buf, bend - buf);
416 mivr[bend - buf] = '\0';
417 /* remove trailing space */
418 for (i = bend - buf - 1; (i > 0) && isspace(mivr[i]); i--)
421 /* This value 100 should be larger than following formatting string */
422 psize = bend - buf + 100;
423 pp = calloc(1, psize);
429 if(cell->field->expr_type == A1TC_CLASSFIELD_TFS) {
430 ret = snprintf(pp, psize,
431 "M DEFINITIONS ::=\nBEGIN\n"
436 } else if(cell->field->expr_type == A1TC_CLASSFIELD_FTVFS) {
437 type_expr = TQ_FIRST(&(cell->field->members));
438 ret = snprintf(pp, psize,
439 "M DEFINITIONS ::=\nBEGIN\n"
442 type_expr->reference ?
443 type_expr->reference->components[0].name :
444 _asn1p_expr_type2string(type_expr->expr_type),
448 WARNING("asn1c only be able to parse TypeFieldSpec and FixedTypeValueFieldSpec. Failed when parsing %s at line %d\n", mivr, arg->expr->_lineno);
453 DEBUG("ASN.1:\n\n%s\n", pp);
458 asn = asn1p_parse_buffer(pp, psize,
459 arg->expr->module->source_file_name, arg->expr->_lineno, A1P_NOFLAGS);
462 FATAL("Cannot parse Setting token %s "
470 asn1p_module_t *mod = TQ_FIRST(&(asn->modules));
473 /* This member removal is safe with respect to members hash since the
474 * entire asn module will be deleted down below.
476 expr = TQ_REMOVE(&(mod->members), next);
479 expr->parent_expr = NULL;
480 asn1p_expr_set_source(expr, arg->expr->module, arg->expr->_lineno);
481 expr->_type_unique_index = counter;
482 DEBUG("Parsed identifier %s, mivr [%s], reference [%s] value [%s]",
483 expr->Identifier, mivr, asn1p_ref_string(expr->reference),
484 asn1f_printable_value(expr->value));
485 free(expr->Identifier);
487 expr->Identifier = strdup(asn1f_printable_value(expr->value));
488 } else if (expr->reference) {
489 expr->Identifier = strdup(expr->reference->components[expr->reference->comp_count - 1].name);
491 expr->Identifier = mivr;
496 if(expr->reference &&
497 !asn1f_lookup_symbol(arg, expr->rhs_pspecs, expr->reference)) {
499 asn1p_ref_free(expr->reference);
501 expr->reference = type_expr->reference;
502 if (asn1f_value_resolve(arg, expr, 0)) {
504 asn1p_expr_free(expr);
505 FATAL("Cannot find %s referenced by %s at line %d",
506 mivr, arg->expr->Identifier,
513 DEBUG("Field %s assignment of %s got %s",
514 cell->field->Identifier, mivr, expr->Identifier);
517 cell->new_ref = new_ref;
519 if(expr->Identifier != mivr) {
526 static asn1p_wsyntx_chunk_t *
527 asn1f_next_literal_chunk(asn1p_wsyntx_t *syntax, asn1p_wsyntx_chunk_t *chunk, const uint8_t *buf)
529 asn1p_wsyntx_chunk_t *next_chunk;
531 next_chunk = TQ_NEXT(chunk, next);
533 if(next_chunk == (struct asn1p_wsyntx_chunk_s *)0) {
536 next_chunk = TQ_NEXT(syntax->parent, next);
537 } else if(next_chunk->type == WC_LITERAL) {
538 if(strstr((const char *)buf, (char *)next_chunk->content.token))
542 next_chunk = TQ_NEXT(syntax->parent, next);
543 } else if(next_chunk->type == WC_WHITESPACE) {
544 next_chunk = TQ_NEXT(next_chunk, next);
545 } else if(next_chunk->type == WC_OPTIONALGROUP) {
546 syntax = next_chunk->content.syntax;
547 next_chunk = TQ_FIRST(((&next_chunk->content.syntax->chunks)));
550 } while (next_chunk);