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