blob: 9a5e2531669f423682bead1913f7ad1f3bbb0fab [file] [log] [blame]
Lev Walkinad0d6372017-08-08 02:02:42 -07001#include "asn1c_internal.h"
2#include "asn1c_ioc.h"
3#include "asn1c_out.h"
4#include "asn1c_misc.h"
5#include <asn1fix_export.h>
Lev Walkind8e07c52017-08-23 07:38:30 -07006#include <asn1print.h>
Lev Walkinad0d6372017-08-08 02:02:42 -07007
Lev Walkin8354f342017-08-10 02:43:53 -07008#define MKID(expr) asn1c_make_identifier(0, (expr), 0)
9
Lev Walkinad0d6372017-08-08 02:02:42 -070010/*
11 * Given the table constraint or component relation constraint
12 * ({ObjectSetName}{...}) returns "ObjectSetName" as a reference.
13 */
Lev Walkind8e07c52017-08-23 07:38:30 -070014const asn1p_ref_t *
15asn1c_get_information_object_set_reference_from_constraint(arg_t *arg,
Lev Walkinad0d6372017-08-08 02:02:42 -070016 const asn1p_constraint_t *ct) {
17
18 if(!ct) return NULL;
19 assert(ct->type == ACT_CA_CRC);
20 assert(ct->el_count >= 1);
21
Lev Walkind8e07c52017-08-23 07:38:30 -070022 DEBUG("Component Relation Constraint: %s", asn1p_constraint_string(ct));
23
Lev Walkinad0d6372017-08-08 02:02:42 -070024 assert(ct->elements[0]->type == ACT_EL_VALUE);
25
26 asn1p_value_t *val = ct->elements[0]->value;
Lev Walkind523ea42017-09-06 22:15:08 -070027 if(val->type == ATV_VALUESET && val->value.constraint->type == ACT_EL_TYPE) {
28 asn1p_value_t *csub = val->value.constraint->containedSubtype;
29 if(!csub) {
30 /* Ignore */
31 } else if(csub->type == ATV_REFERENCED) {
32 return csub->value.reference;
33 } else if(csub->type == ATV_TYPE) {
34 if(csub->value.v_type->expr_type == A1TC_REFERENCE) {
35 assert(csub->value.v_type->reference);
36 return csub->value.v_type->reference;
37 }
38 }
Lev Walkind8e07c52017-08-23 07:38:30 -070039 }
40 if(val->type != ATV_REFERENCED) {
41 FATAL("Set reference: %s", asn1f_printable_value(val));
42 assert(val->type == ATV_REFERENCED);
43 }
Lev Walkinad0d6372017-08-08 02:02:42 -070044
45 return val->value.reference;
46}
47
48static asn1c_ioc_table_and_objset_t
49asn1c_get_ioc_table_from_objset(arg_t *arg, const asn1p_ref_t *objset_ref, asn1p_expr_t *objset) {
50 asn1c_ioc_table_and_objset_t ioc_tao = { 0, 0, 1 };
51
52 (void)objset_ref;
53
54 if(objset->ioc_table) {
55 ioc_tao.ioct = objset->ioc_table;
56 ioc_tao.objset = objset;
57 ioc_tao.fatal_error = 0;
58 } else {
59 FATAL("Information Object Set %s contains no objects at line %d",
60 objset->Identifier, objset->_lineno);
61 }
62
63 return ioc_tao;
64}
65
66asn1c_ioc_table_and_objset_t
67asn1c_get_ioc_table(arg_t *arg) {
68 asn1p_expr_t *expr = arg->expr;
69 asn1p_expr_t *memb;
70 asn1p_expr_t *objset = 0;
71 const asn1p_ref_t *objset_ref = NULL;
72 asn1c_ioc_table_and_objset_t safe_ioc_tao = {0, 0, 0};
73 asn1c_ioc_table_and_objset_t failed_ioc_tao = { 0, 0, 1 };
74
75 TQ_FOR(memb, &(expr->members), next) {
Lev Walkind8e07c52017-08-23 07:38:30 -070076 const asn1p_constraint_t *cr_ct =
77 asn1p_get_component_relation_constraint(memb->constraints);
Lev Walkinad0d6372017-08-08 02:02:42 -070078 const asn1p_ref_t *tmpref =
Lev Walkind8e07c52017-08-23 07:38:30 -070079 asn1c_get_information_object_set_reference_from_constraint(arg,
80 cr_ct);
Lev Walkinad0d6372017-08-08 02:02:42 -070081 if(tmpref) {
82 if(objset_ref && asn1p_ref_compare(objset_ref, tmpref) != 0) {
83 FATAL(
84 "Object set reference on line %d differs from object set "
85 "reference on line %d",
86 objset_ref->_lineno, tmpref->_lineno);
87 return failed_ioc_tao;
88 }
89 objset_ref = tmpref;
90 }
Lev Walkind8e07c52017-08-23 07:38:30 -070091
Lev Walkinad0d6372017-08-08 02:02:42 -070092 }
93
94 if(!objset_ref) {
95 return safe_ioc_tao;
96 }
97
Lev Walkinc0e03b92017-08-22 01:48:23 -070098 objset = WITH_MODULE_NAMESPACE(
99 arg->expr->module, expr_ns,
100 asn1f_lookup_symbol_ex(arg->asn, expr_ns, arg->expr, objset_ref));
Lev Walkinad0d6372017-08-08 02:02:42 -0700101 if(!objset) {
102 FATAL("Cannot found %s", asn1p_ref_string(objset_ref));
103 return failed_ioc_tao;
104 }
105
106 return asn1c_get_ioc_table_from_objset(arg, objset_ref, objset);
107}
108
Lev Walkinad0d6372017-08-08 02:02:42 -0700109static int
110emit_ioc_value(arg_t *arg, struct asn1p_ioc_cell_s *cell) {
111
112 if(cell->value && cell->value->meta_type == AMT_VALUE) {
113 const char *prim_type = NULL;
114 int primitive_representation = 0;
115
Lev Walkin8354f342017-08-10 02:43:53 -0700116 asn1p_expr_t *cv_type =
Lev Walkinc0e03b92017-08-22 01:48:23 -0700117 asn1f_find_terminal_type_ex(arg->asn, arg->ns, cell->value);
Lev Walkin8354f342017-08-10 02:43:53 -0700118
119 switch(cv_type->expr_type) {
Lev Walkinad0d6372017-08-08 02:02:42 -0700120 case ASN_BASIC_INTEGER:
121 case ASN_BASIC_ENUMERATED:
Lev Walkin8354f342017-08-10 02:43:53 -0700122 switch(asn1c_type_fits_long(arg, cell->value /* sic */)) {
Lev Walkinad0d6372017-08-08 02:02:42 -0700123 case FL_NOTFIT:
124 GEN_INCLUDE_STD("INTEGER");
125 prim_type = "INTEGER_t";
126 break;
127 case FL_PRESUMED:
128 case FL_FITS_SIGNED:
129 primitive_representation = 1;
130 prim_type = "long";
131 break;
132 case FL_FITS_UNSIGN:
133 prim_type = "unsigned long";
134 primitive_representation = 1;
135 break;
136 }
137 break;
138 case ASN_BASIC_OBJECT_IDENTIFIER:
139 prim_type = "OBJECT_IDENTIFIER_t";
140 break;
141 case ASN_BASIC_RELATIVE_OID:
142 prim_type = "RELATIVE_OID_t";
143 break;
144 default: {
145 char *p = strdup(MKID(cell->value));
146 FATAL("Unsupported type %s for value %s",
147 asn1c_type_name(arg, cell->value, TNF_UNMODIFIED), p);
148 free(p);
149 return -1;
150 }
151 }
Lev Walkind357f3d2017-08-10 17:40:37 -0700152 OUT("static const %s asn_VAL_%d_%s = ", prim_type,
153 cell->value->_type_unique_index, MKID(cell->value));
Lev Walkinad0d6372017-08-08 02:02:42 -0700154
155 asn1p_expr_t *expr_value = cell->value;
156 while(expr_value->value->type == ATV_REFERENCED) {
Lev Walkinc0e03b92017-08-22 01:48:23 -0700157 expr_value = WITH_MODULE_NAMESPACE(
158 expr_value->module, expr_ns,
159 asn1f_lookup_symbol_ex(arg->asn, expr_ns, expr_value,
160 expr_value->value->value.reference));
Lev Walkinad0d6372017-08-08 02:02:42 -0700161 if(!expr_value) {
162 FATAL("Unrecognized value type for %s", MKID(cell->value));
163 return -1;
164 }
165 }
166
167 if(!primitive_representation) OUT("{ ");
168
169 switch(expr_value->value->type) {
170 case ATV_INTEGER:
171 if(primitive_representation) {
172 OUT("%s", asn1p_itoa(expr_value->value->value.v_integer));
173 break;
174 } else {
175 asn1c_integer_t v = expr_value->value->value.v_integer;
176 if(v >= 0) {
177 if(v <= 127) {
Lev Walkin840fb8e2017-11-19 23:39:59 -0800178 OUT("\"\\x%02x\", 1", (int)v);
Lev Walkinad0d6372017-08-08 02:02:42 -0700179 break;
180 } else if(v <= 32767) {
Lev Walkin840fb8e2017-11-19 23:39:59 -0800181 OUT("\"\\x%02x\\x%02x\", 2", (int)(v >> 8), (int)(v & 0xff));
Lev Walkinad0d6372017-08-08 02:02:42 -0700182 break;
183 }
184 }
185 FATAL("Unsupported value %s range for type %s",
186 asn1f_printable_value(expr_value->value),
187 MKID(cell->value));
188 return -1;
189 }
190 case ATV_UNPARSED:
191 OUT("\"not supported\", 0 };\n");
192 FATAL("Inappropriate value %s for type %s",
193 asn1f_printable_value(expr_value->value), MKID(cell->value));
194 return 0; /* TEMPORARY FIXME FIXME */
195 default:
196 FATAL("Inappropriate value %s for type %s",
197 asn1f_printable_value(expr_value->value), MKID(cell->value));
198 return -1;
199 }
200
201 if(primitive_representation) {
202 OUT(";\n");
203 } else {
204 OUT(" };");
205 OUT(" /* %s */\n", asn1f_printable_value(expr_value->value));
206 }
207 }
208
209 return 0;
210}
211
212static int
213emit_ioc_cell(arg_t *arg, struct asn1p_ioc_cell_s *cell) {
214 OUT("{ \"%s\", ", cell->field->Identifier);
215
Bi-Ruei, Chiu069c0762017-09-11 14:09:34 +0800216 if(!cell->value) {
217 /* Ignore */
218 } else if(cell->value->meta_type == AMT_VALUE) {
Lev Walkinad0d6372017-08-08 02:02:42 -0700219 GEN_INCLUDE(asn1c_type_name(arg, cell->value, TNF_INCLUDE));
220 OUT("aioc__value, ");
221 OUT("&asn_DEF_%s, ", asn1c_type_name(arg, cell->value, TNF_SAFE));
Lev Walkind357f3d2017-08-10 17:40:37 -0700222 OUT("&asn_VAL_%d_%s", cell->value->_type_unique_index,
223 MKID(cell->value));
Lev Walkinad0d6372017-08-08 02:02:42 -0700224
225 } else if(cell->value->meta_type == AMT_TYPEREF) {
226 GEN_INCLUDE(asn1c_type_name(arg, cell->value, TNF_INCLUDE));
227 OUT("aioc__type, &asn_DEF_%s", MKID(cell->value));
228 } else {
229 return -1;
230 }
231
232 OUT(" }");
233
234 return 0;
235}
236
237/*
238 * Refer to skeletons/asn_ioc.h
239 */
240int
241emit_ioc_table(arg_t *arg, asn1p_expr_t *context, asn1c_ioc_table_and_objset_t ioc_tao) {
242 size_t columns = 0;
243
244 (void)context;
245 GEN_INCLUDE_STD("asn_ioc");
246
Lev Walkin9de6cd82017-08-10 05:47:46 -0700247 REDIR(OT_IOC_TABLES);
Lev Walkinad0d6372017-08-08 02:02:42 -0700248
249 /* Emit values that are used in the Information Object Set table first */
250 for(size_t rn = 0; rn < ioc_tao.ioct->rows; rn++) {
251 asn1p_ioc_row_t *row = ioc_tao.ioct->row[rn];
252 for(size_t cn = 0; cn < row->columns; cn++) {
253 if(emit_ioc_value(arg, &row->column[cn])) {
254 return -1;
255 }
256 }
257 }
258
259 /* Emit the Information Object Set */
260 OUT("static const asn_ioc_cell_t asn_IOS_%s_%d_rows[] = {\n",
261 MKID(ioc_tao.objset), ioc_tao.objset->_type_unique_index);
262 INDENT(+1);
263
264 for(size_t rn = 0; rn < ioc_tao.ioct->rows; rn++) {
265 asn1p_ioc_row_t *row = ioc_tao.ioct->row[rn];
266 columns = columns ? columns : row->columns;
267 if(columns != row->columns) {
268 FATAL("Information Object Set %s row column mismatch on line %d",
269 ioc_tao.objset->Identifier, ioc_tao.objset->_lineno);
270 return -1;
271 }
272 for(size_t cn = 0; cn < row->columns; cn++) {
273 if(rn || cn) OUT(",\n");
274 emit_ioc_cell(arg, &row->column[cn]);
275 }
276 }
277 OUT("\n");
278
279 INDENT(-1);
280 OUT("};\n");
281
Lev Walkin6aae7c62017-08-10 17:58:48 -0700282 OUT("static const asn_ioc_set_t asn_IOS_%s_%d[] = {\n",
283 MKID(ioc_tao.objset), ioc_tao.objset->_type_unique_index);
Lev Walkinad0d6372017-08-08 02:02:42 -0700284 INDENT(+1);
285 OUT("%zu, %zu, asn_IOS_%s_%d_rows\n", ioc_tao.ioct->rows, columns,
286 MKID(ioc_tao.objset), ioc_tao.objset->_type_unique_index);
287 INDENT(-1);
288 OUT("};\n");
289
290 return 0;
291}
292