Lev Walkin | ad0d637 | 2017-08-08 02:02:42 -0700 | [diff] [blame^] | 1 | #include "asn1c_internal.h" |
| 2 | #include "asn1c_ioc.h" |
| 3 | #include "asn1c_out.h" |
| 4 | #include "asn1c_misc.h" |
| 5 | #include <asn1fix_export.h> |
| 6 | |
| 7 | /* |
| 8 | * Given the table constraint or component relation constraint |
| 9 | * ({ObjectSetName}{...}) returns "ObjectSetName" as a reference. |
| 10 | */ |
| 11 | static const asn1p_ref_t * |
| 12 | asn1c_get_information_object_set_reference_from_constraint( |
| 13 | const asn1p_constraint_t *ct) { |
| 14 | |
| 15 | if(!ct) return NULL; |
| 16 | assert(ct->type == ACT_CA_CRC); |
| 17 | assert(ct->el_count >= 1); |
| 18 | |
| 19 | assert(ct->elements[0]->type == ACT_EL_VALUE); |
| 20 | |
| 21 | asn1p_value_t *val = ct->elements[0]->value; |
| 22 | assert(val->type == ATV_REFERENCED); |
| 23 | |
| 24 | return val->value.reference; |
| 25 | } |
| 26 | |
| 27 | static asn1c_ioc_table_and_objset_t |
| 28 | asn1c_get_ioc_table_from_objset(arg_t *arg, const asn1p_ref_t *objset_ref, asn1p_expr_t *objset) { |
| 29 | asn1c_ioc_table_and_objset_t ioc_tao = { 0, 0, 1 }; |
| 30 | |
| 31 | (void)objset_ref; |
| 32 | |
| 33 | if(objset->ioc_table) { |
| 34 | ioc_tao.ioct = objset->ioc_table; |
| 35 | ioc_tao.objset = objset; |
| 36 | ioc_tao.fatal_error = 0; |
| 37 | } else { |
| 38 | FATAL("Information Object Set %s contains no objects at line %d", |
| 39 | objset->Identifier, objset->_lineno); |
| 40 | } |
| 41 | |
| 42 | return ioc_tao; |
| 43 | } |
| 44 | |
| 45 | asn1c_ioc_table_and_objset_t |
| 46 | asn1c_get_ioc_table(arg_t *arg) { |
| 47 | asn1p_expr_t *expr = arg->expr; |
| 48 | asn1p_expr_t *memb; |
| 49 | asn1p_expr_t *objset = 0; |
| 50 | const asn1p_ref_t *objset_ref = NULL; |
| 51 | asn1c_ioc_table_and_objset_t safe_ioc_tao = {0, 0, 0}; |
| 52 | asn1c_ioc_table_and_objset_t failed_ioc_tao = { 0, 0, 1 }; |
| 53 | |
| 54 | TQ_FOR(memb, &(expr->members), next) { |
| 55 | const asn1p_ref_t *tmpref = |
| 56 | asn1c_get_information_object_set_reference_from_constraint( |
| 57 | asn1p_get_component_relation_constraint(memb->constraints)); |
| 58 | if(tmpref) { |
| 59 | if(objset_ref && asn1p_ref_compare(objset_ref, tmpref) != 0) { |
| 60 | FATAL( |
| 61 | "Object set reference on line %d differs from object set " |
| 62 | "reference on line %d", |
| 63 | objset_ref->_lineno, tmpref->_lineno); |
| 64 | return failed_ioc_tao; |
| 65 | } |
| 66 | objset_ref = tmpref; |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | if(!objset_ref) { |
| 71 | return safe_ioc_tao; |
| 72 | } |
| 73 | |
| 74 | objset = asn1f_lookup_symbol_ex(arg->asn, arg->expr, objset_ref); |
| 75 | if(!objset) { |
| 76 | FATAL("Cannot found %s", asn1p_ref_string(objset_ref)); |
| 77 | return failed_ioc_tao; |
| 78 | } |
| 79 | |
| 80 | return asn1c_get_ioc_table_from_objset(arg, objset_ref, objset); |
| 81 | } |
| 82 | |
| 83 | #define MKID(expr) asn1c_make_identifier(0, (expr), 0) |
| 84 | |
| 85 | static int |
| 86 | emit_ioc_value(arg_t *arg, struct asn1p_ioc_cell_s *cell) { |
| 87 | |
| 88 | if(cell->value && cell->value->meta_type == AMT_VALUE) { |
| 89 | const char *prim_type = NULL; |
| 90 | int primitive_representation = 0; |
| 91 | |
| 92 | switch(cell->value->expr_type) { |
| 93 | case ASN_BASIC_INTEGER: |
| 94 | case ASN_BASIC_ENUMERATED: |
| 95 | switch(asn1c_type_fits_long(arg, cell->value)) { |
| 96 | case FL_NOTFIT: |
| 97 | GEN_INCLUDE_STD("INTEGER"); |
| 98 | prim_type = "INTEGER_t"; |
| 99 | break; |
| 100 | case FL_PRESUMED: |
| 101 | case FL_FITS_SIGNED: |
| 102 | primitive_representation = 1; |
| 103 | prim_type = "long"; |
| 104 | break; |
| 105 | case FL_FITS_UNSIGN: |
| 106 | prim_type = "unsigned long"; |
| 107 | primitive_representation = 1; |
| 108 | break; |
| 109 | } |
| 110 | break; |
| 111 | case ASN_BASIC_OBJECT_IDENTIFIER: |
| 112 | prim_type = "OBJECT_IDENTIFIER_t"; |
| 113 | break; |
| 114 | case ASN_BASIC_RELATIVE_OID: |
| 115 | prim_type = "RELATIVE_OID_t"; |
| 116 | break; |
| 117 | default: { |
| 118 | char *p = strdup(MKID(cell->value)); |
| 119 | FATAL("Unsupported type %s for value %s", |
| 120 | asn1c_type_name(arg, cell->value, TNF_UNMODIFIED), p); |
| 121 | free(p); |
| 122 | return -1; |
| 123 | } |
| 124 | } |
| 125 | OUT("static const %s asn_VAL_%s_%d = ", prim_type, MKID(cell->value), |
| 126 | cell->value->_type_unique_index); |
| 127 | |
| 128 | asn1p_expr_t *expr_value = cell->value; |
| 129 | while(expr_value->value->type == ATV_REFERENCED) { |
| 130 | expr_value = asn1f_lookup_symbol_ex( |
| 131 | arg->asn, expr_value, expr_value->value->value.reference); |
| 132 | if(!expr_value) { |
| 133 | FATAL("Unrecognized value type for %s", MKID(cell->value)); |
| 134 | return -1; |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | if(!primitive_representation) OUT("{ "); |
| 139 | |
| 140 | switch(expr_value->value->type) { |
| 141 | case ATV_INTEGER: |
| 142 | if(primitive_representation) { |
| 143 | OUT("%s", asn1p_itoa(expr_value->value->value.v_integer)); |
| 144 | break; |
| 145 | } else { |
| 146 | asn1c_integer_t v = expr_value->value->value.v_integer; |
| 147 | if(v >= 0) { |
| 148 | if(v <= 127) { |
| 149 | OUT("\"\\x%02x\", 1", v); |
| 150 | break; |
| 151 | } else if(v <= 32767) { |
| 152 | OUT("\"\\x%02x\\x%02x\", 2", (v >> 8), (v & 0xff)); |
| 153 | break; |
| 154 | } |
| 155 | } |
| 156 | FATAL("Unsupported value %s range for type %s", |
| 157 | asn1f_printable_value(expr_value->value), |
| 158 | MKID(cell->value)); |
| 159 | return -1; |
| 160 | } |
| 161 | case ATV_UNPARSED: |
| 162 | OUT("\"not supported\", 0 };\n"); |
| 163 | FATAL("Inappropriate value %s for type %s", |
| 164 | asn1f_printable_value(expr_value->value), MKID(cell->value)); |
| 165 | return 0; /* TEMPORARY FIXME FIXME */ |
| 166 | default: |
| 167 | FATAL("Inappropriate value %s for type %s", |
| 168 | asn1f_printable_value(expr_value->value), MKID(cell->value)); |
| 169 | return -1; |
| 170 | } |
| 171 | |
| 172 | if(primitive_representation) { |
| 173 | OUT(";\n"); |
| 174 | } else { |
| 175 | OUT(" };"); |
| 176 | OUT(" /* %s */\n", asn1f_printable_value(expr_value->value)); |
| 177 | } |
| 178 | } |
| 179 | |
| 180 | return 0; |
| 181 | } |
| 182 | |
| 183 | static int |
| 184 | emit_ioc_cell(arg_t *arg, struct asn1p_ioc_cell_s *cell) { |
| 185 | OUT("{ \"%s\", ", cell->field->Identifier); |
| 186 | |
| 187 | if(cell->value->meta_type == AMT_VALUE) { |
| 188 | GEN_INCLUDE(asn1c_type_name(arg, cell->value, TNF_INCLUDE)); |
| 189 | OUT("aioc__value, "); |
| 190 | OUT("&asn_DEF_%s, ", asn1c_type_name(arg, cell->value, TNF_SAFE)); |
| 191 | OUT("&asn_VAL_%s_%d", MKID(cell->value), |
| 192 | cell->value->_type_unique_index); |
| 193 | |
| 194 | } else if(cell->value->meta_type == AMT_TYPEREF) { |
| 195 | GEN_INCLUDE(asn1c_type_name(arg, cell->value, TNF_INCLUDE)); |
| 196 | OUT("aioc__type, &asn_DEF_%s", MKID(cell->value)); |
| 197 | } else { |
| 198 | return -1; |
| 199 | } |
| 200 | |
| 201 | OUT(" }"); |
| 202 | |
| 203 | return 0; |
| 204 | } |
| 205 | |
| 206 | /* |
| 207 | * Refer to skeletons/asn_ioc.h |
| 208 | */ |
| 209 | int |
| 210 | emit_ioc_table(arg_t *arg, asn1p_expr_t *context, asn1c_ioc_table_and_objset_t ioc_tao) { |
| 211 | size_t columns = 0; |
| 212 | |
| 213 | (void)context; |
| 214 | GEN_INCLUDE_STD("asn_ioc"); |
| 215 | |
| 216 | REDIR(OT_STAT_DEFS); |
| 217 | |
| 218 | /* Emit values that are used in the Information Object Set table first */ |
| 219 | for(size_t rn = 0; rn < ioc_tao.ioct->rows; rn++) { |
| 220 | asn1p_ioc_row_t *row = ioc_tao.ioct->row[rn]; |
| 221 | for(size_t cn = 0; cn < row->columns; cn++) { |
| 222 | if(emit_ioc_value(arg, &row->column[cn])) { |
| 223 | return -1; |
| 224 | } |
| 225 | } |
| 226 | } |
| 227 | |
| 228 | /* Emit the Information Object Set */ |
| 229 | OUT("static const asn_ioc_cell_t asn_IOS_%s_%d_rows[] = {\n", |
| 230 | MKID(ioc_tao.objset), ioc_tao.objset->_type_unique_index); |
| 231 | INDENT(+1); |
| 232 | |
| 233 | for(size_t rn = 0; rn < ioc_tao.ioct->rows; rn++) { |
| 234 | asn1p_ioc_row_t *row = ioc_tao.ioct->row[rn]; |
| 235 | columns = columns ? columns : row->columns; |
| 236 | if(columns != row->columns) { |
| 237 | FATAL("Information Object Set %s row column mismatch on line %d", |
| 238 | ioc_tao.objset->Identifier, ioc_tao.objset->_lineno); |
| 239 | return -1; |
| 240 | } |
| 241 | for(size_t cn = 0; cn < row->columns; cn++) { |
| 242 | if(rn || cn) OUT(",\n"); |
| 243 | emit_ioc_cell(arg, &row->column[cn]); |
| 244 | } |
| 245 | } |
| 246 | OUT("\n"); |
| 247 | |
| 248 | INDENT(-1); |
| 249 | OUT("};\n"); |
| 250 | |
| 251 | OUT("static asn_ioc_set_t asn_IOS_%s_%d[] = {\n", MKID(ioc_tao.objset), |
| 252 | ioc_tao.objset->_type_unique_index); |
| 253 | INDENT(+1); |
| 254 | OUT("%zu, %zu, asn_IOS_%s_%d_rows\n", ioc_tao.ioct->rows, columns, |
| 255 | MKID(ioc_tao.objset), ioc_tao.objset->_type_unique_index); |
| 256 | INDENT(-1); |
| 257 | OUT("};\n"); |
| 258 | |
| 259 | return 0; |
| 260 | } |
| 261 | |