#include "asn1c_internal.h" #include "asn1c_ioc.h" #include "asn1c_out.h" #include "asn1c_misc.h" #include #define MKID(expr) asn1c_make_identifier(0, (expr), 0) /* * Given the table constraint or component relation constraint * ({ObjectSetName}{...}) returns "ObjectSetName" as a reference. */ static const asn1p_ref_t * asn1c_get_information_object_set_reference_from_constraint( const asn1p_constraint_t *ct) { if(!ct) return NULL; assert(ct->type == ACT_CA_CRC); assert(ct->el_count >= 1); assert(ct->elements[0]->type == ACT_EL_VALUE); asn1p_value_t *val = ct->elements[0]->value; assert(val->type == ATV_REFERENCED); return val->value.reference; } static asn1c_ioc_table_and_objset_t asn1c_get_ioc_table_from_objset(arg_t *arg, const asn1p_ref_t *objset_ref, asn1p_expr_t *objset) { asn1c_ioc_table_and_objset_t ioc_tao = { 0, 0, 1 }; (void)objset_ref; if(objset->ioc_table) { ioc_tao.ioct = objset->ioc_table; ioc_tao.objset = objset; ioc_tao.fatal_error = 0; } else { FATAL("Information Object Set %s contains no objects at line %d", objset->Identifier, objset->_lineno); } return ioc_tao; } asn1c_ioc_table_and_objset_t asn1c_get_ioc_table(arg_t *arg) { asn1p_expr_t *expr = arg->expr; asn1p_expr_t *memb; asn1p_expr_t *objset = 0; const asn1p_ref_t *objset_ref = NULL; asn1c_ioc_table_and_objset_t safe_ioc_tao = {0, 0, 0}; asn1c_ioc_table_and_objset_t failed_ioc_tao = { 0, 0, 1 }; if(expr->lhs_params) { if(0) WARNING( "Can not process Information Object Set on a parameterized type %s", MKID(expr)); return safe_ioc_tao; } TQ_FOR(memb, &(expr->members), next) { const asn1p_ref_t *tmpref = asn1c_get_information_object_set_reference_from_constraint( asn1p_get_component_relation_constraint(memb->constraints)); if(tmpref) { if(objset_ref && asn1p_ref_compare(objset_ref, tmpref) != 0) { FATAL( "Object set reference on line %d differs from object set " "reference on line %d", objset_ref->_lineno, tmpref->_lineno); return failed_ioc_tao; } objset_ref = tmpref; } } if(!objset_ref) { return safe_ioc_tao; } objset = asn1f_lookup_symbol_ex(arg->asn, arg->expr, objset_ref); if(!objset) { FATAL("Cannot found %s", asn1p_ref_string(objset_ref)); return failed_ioc_tao; } return asn1c_get_ioc_table_from_objset(arg, objset_ref, objset); } static int emit_ioc_value(arg_t *arg, struct asn1p_ioc_cell_s *cell) { if(cell->value && cell->value->meta_type == AMT_VALUE) { const char *prim_type = NULL; int primitive_representation = 0; asn1p_expr_t *cv_type = asn1f_find_terminal_type_ex(arg->asn, cell->value); switch(cv_type->expr_type) { case ASN_BASIC_INTEGER: case ASN_BASIC_ENUMERATED: switch(asn1c_type_fits_long(arg, cell->value /* sic */)) { case FL_NOTFIT: GEN_INCLUDE_STD("INTEGER"); prim_type = "INTEGER_t"; break; case FL_PRESUMED: case FL_FITS_SIGNED: primitive_representation = 1; prim_type = "long"; break; case FL_FITS_UNSIGN: prim_type = "unsigned long"; primitive_representation = 1; break; } break; case ASN_BASIC_OBJECT_IDENTIFIER: prim_type = "OBJECT_IDENTIFIER_t"; break; case ASN_BASIC_RELATIVE_OID: prim_type = "RELATIVE_OID_t"; break; default: { char *p = strdup(MKID(cell->value)); FATAL("Unsupported type %s for value %s", asn1c_type_name(arg, cell->value, TNF_UNMODIFIED), p); free(p); return -1; } } OUT("static const %s asn_VAL_%d_%s = ", prim_type, cell->value->_type_unique_index, MKID(cell->value)); asn1p_expr_t *expr_value = cell->value; while(expr_value->value->type == ATV_REFERENCED) { expr_value = asn1f_lookup_symbol_ex( arg->asn, expr_value, expr_value->value->value.reference); if(!expr_value) { FATAL("Unrecognized value type for %s", MKID(cell->value)); return -1; } } if(!primitive_representation) OUT("{ "); switch(expr_value->value->type) { case ATV_INTEGER: if(primitive_representation) { OUT("%s", asn1p_itoa(expr_value->value->value.v_integer)); break; } else { asn1c_integer_t v = expr_value->value->value.v_integer; if(v >= 0) { if(v <= 127) { OUT("\"\\x%02x\", 1", v); break; } else if(v <= 32767) { OUT("\"\\x%02x\\x%02x\", 2", (v >> 8), (v & 0xff)); break; } } FATAL("Unsupported value %s range for type %s", asn1f_printable_value(expr_value->value), MKID(cell->value)); return -1; } case ATV_UNPARSED: OUT("\"not supported\", 0 };\n"); FATAL("Inappropriate value %s for type %s", asn1f_printable_value(expr_value->value), MKID(cell->value)); return 0; /* TEMPORARY FIXME FIXME */ default: FATAL("Inappropriate value %s for type %s", asn1f_printable_value(expr_value->value), MKID(cell->value)); return -1; } if(primitive_representation) { OUT(";\n"); } else { OUT(" };"); OUT(" /* %s */\n", asn1f_printable_value(expr_value->value)); } } return 0; } static int emit_ioc_cell(arg_t *arg, struct asn1p_ioc_cell_s *cell) { OUT("{ \"%s\", ", cell->field->Identifier); if(cell->value->meta_type == AMT_VALUE) { GEN_INCLUDE(asn1c_type_name(arg, cell->value, TNF_INCLUDE)); OUT("aioc__value, "); OUT("&asn_DEF_%s, ", asn1c_type_name(arg, cell->value, TNF_SAFE)); OUT("&asn_VAL_%d_%s", cell->value->_type_unique_index, MKID(cell->value)); } else if(cell->value->meta_type == AMT_TYPEREF) { GEN_INCLUDE(asn1c_type_name(arg, cell->value, TNF_INCLUDE)); OUT("aioc__type, &asn_DEF_%s", MKID(cell->value)); } else { return -1; } OUT(" }"); return 0; } /* * Refer to skeletons/asn_ioc.h */ int emit_ioc_table(arg_t *arg, asn1p_expr_t *context, asn1c_ioc_table_and_objset_t ioc_tao) { size_t columns = 0; (void)context; GEN_INCLUDE_STD("asn_ioc"); REDIR(OT_IOC_TABLES); /* Emit values that are used in the Information Object Set table first */ for(size_t rn = 0; rn < ioc_tao.ioct->rows; rn++) { asn1p_ioc_row_t *row = ioc_tao.ioct->row[rn]; for(size_t cn = 0; cn < row->columns; cn++) { if(emit_ioc_value(arg, &row->column[cn])) { return -1; } } } /* Emit the Information Object Set */ OUT("static const asn_ioc_cell_t asn_IOS_%s_%d_rows[] = {\n", MKID(ioc_tao.objset), ioc_tao.objset->_type_unique_index); INDENT(+1); for(size_t rn = 0; rn < ioc_tao.ioct->rows; rn++) { asn1p_ioc_row_t *row = ioc_tao.ioct->row[rn]; columns = columns ? columns : row->columns; if(columns != row->columns) { FATAL("Information Object Set %s row column mismatch on line %d", ioc_tao.objset->Identifier, ioc_tao.objset->_lineno); return -1; } for(size_t cn = 0; cn < row->columns; cn++) { if(rn || cn) OUT(",\n"); emit_ioc_cell(arg, &row->column[cn]); } } OUT("\n"); INDENT(-1); OUT("};\n"); OUT("static const asn_ioc_set_t asn_IOS_%s_%d[] = {\n", MKID(ioc_tao.objset), ioc_tao.objset->_type_unique_index); INDENT(+1); OUT("%zu, %zu, asn_IOS_%s_%d_rows\n", ioc_tao.ioct->rows, columns, MKID(ioc_tao.objset), ioc_tao.objset->_type_unique_index); INDENT(-1); OUT("};\n"); return 0; }