blob: 37719d18da4ddacd1cc3a0eddc67d119c00b4f91 [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 Walkind8e07c52017-08-23 07:38:30 -070027 if(val->type == ATV_VALUESET && val->value.constraint->type == ACT_EL_TYPE && val->value.constraint->containedSubtype && val->value.constraint->containedSubtype->type == ATV_REFERENCED) {
28 return val->value.constraint->containedSubtype->value.reference;
29 }
30 if(val->type != ATV_REFERENCED) {
31 FATAL("Set reference: %s", asn1f_printable_value(val));
32 assert(val->type == ATV_REFERENCED);
33 }
Lev Walkinad0d6372017-08-08 02:02:42 -070034
35 return val->value.reference;
36}
37
38static asn1c_ioc_table_and_objset_t
39asn1c_get_ioc_table_from_objset(arg_t *arg, const asn1p_ref_t *objset_ref, asn1p_expr_t *objset) {
40 asn1c_ioc_table_and_objset_t ioc_tao = { 0, 0, 1 };
41
42 (void)objset_ref;
43
44 if(objset->ioc_table) {
45 ioc_tao.ioct = objset->ioc_table;
46 ioc_tao.objset = objset;
47 ioc_tao.fatal_error = 0;
48 } else {
49 FATAL("Information Object Set %s contains no objects at line %d",
50 objset->Identifier, objset->_lineno);
51 }
52
53 return ioc_tao;
54}
55
56asn1c_ioc_table_and_objset_t
57asn1c_get_ioc_table(arg_t *arg) {
58 asn1p_expr_t *expr = arg->expr;
59 asn1p_expr_t *memb;
60 asn1p_expr_t *objset = 0;
61 const asn1p_ref_t *objset_ref = NULL;
62 asn1c_ioc_table_and_objset_t safe_ioc_tao = {0, 0, 0};
63 asn1c_ioc_table_and_objset_t failed_ioc_tao = { 0, 0, 1 };
64
65 TQ_FOR(memb, &(expr->members), next) {
Lev Walkind8e07c52017-08-23 07:38:30 -070066 const asn1p_constraint_t *cr_ct =
67 asn1p_get_component_relation_constraint(memb->constraints);
Lev Walkinad0d6372017-08-08 02:02:42 -070068 const asn1p_ref_t *tmpref =
Lev Walkind8e07c52017-08-23 07:38:30 -070069 asn1c_get_information_object_set_reference_from_constraint(arg,
70 cr_ct);
Lev Walkinad0d6372017-08-08 02:02:42 -070071 if(tmpref) {
72 if(objset_ref && asn1p_ref_compare(objset_ref, tmpref) != 0) {
73 FATAL(
74 "Object set reference on line %d differs from object set "
75 "reference on line %d",
76 objset_ref->_lineno, tmpref->_lineno);
77 return failed_ioc_tao;
78 }
79 objset_ref = tmpref;
80 }
Lev Walkind8e07c52017-08-23 07:38:30 -070081
Lev Walkinad0d6372017-08-08 02:02:42 -070082 }
83
84 if(!objset_ref) {
85 return safe_ioc_tao;
86 }
87
Lev Walkinc0e03b92017-08-22 01:48:23 -070088 objset = WITH_MODULE_NAMESPACE(
89 arg->expr->module, expr_ns,
90 asn1f_lookup_symbol_ex(arg->asn, expr_ns, arg->expr, objset_ref));
Lev Walkinad0d6372017-08-08 02:02:42 -070091 if(!objset) {
92 FATAL("Cannot found %s", asn1p_ref_string(objset_ref));
93 return failed_ioc_tao;
94 }
95
96 return asn1c_get_ioc_table_from_objset(arg, objset_ref, objset);
97}
98
Lev Walkinad0d6372017-08-08 02:02:42 -070099static int
100emit_ioc_value(arg_t *arg, struct asn1p_ioc_cell_s *cell) {
101
102 if(cell->value && cell->value->meta_type == AMT_VALUE) {
103 const char *prim_type = NULL;
104 int primitive_representation = 0;
105
Lev Walkin8354f342017-08-10 02:43:53 -0700106 asn1p_expr_t *cv_type =
Lev Walkinc0e03b92017-08-22 01:48:23 -0700107 asn1f_find_terminal_type_ex(arg->asn, arg->ns, cell->value);
Lev Walkin8354f342017-08-10 02:43:53 -0700108
109 switch(cv_type->expr_type) {
Lev Walkinad0d6372017-08-08 02:02:42 -0700110 case ASN_BASIC_INTEGER:
111 case ASN_BASIC_ENUMERATED:
Lev Walkin8354f342017-08-10 02:43:53 -0700112 switch(asn1c_type_fits_long(arg, cell->value /* sic */)) {
Lev Walkinad0d6372017-08-08 02:02:42 -0700113 case FL_NOTFIT:
114 GEN_INCLUDE_STD("INTEGER");
115 prim_type = "INTEGER_t";
116 break;
117 case FL_PRESUMED:
118 case FL_FITS_SIGNED:
119 primitive_representation = 1;
120 prim_type = "long";
121 break;
122 case FL_FITS_UNSIGN:
123 prim_type = "unsigned long";
124 primitive_representation = 1;
125 break;
126 }
127 break;
128 case ASN_BASIC_OBJECT_IDENTIFIER:
129 prim_type = "OBJECT_IDENTIFIER_t";
130 break;
131 case ASN_BASIC_RELATIVE_OID:
132 prim_type = "RELATIVE_OID_t";
133 break;
134 default: {
135 char *p = strdup(MKID(cell->value));
136 FATAL("Unsupported type %s for value %s",
137 asn1c_type_name(arg, cell->value, TNF_UNMODIFIED), p);
138 free(p);
139 return -1;
140 }
141 }
Lev Walkind357f3d2017-08-10 17:40:37 -0700142 OUT("static const %s asn_VAL_%d_%s = ", prim_type,
143 cell->value->_type_unique_index, MKID(cell->value));
Lev Walkinad0d6372017-08-08 02:02:42 -0700144
145 asn1p_expr_t *expr_value = cell->value;
146 while(expr_value->value->type == ATV_REFERENCED) {
Lev Walkinc0e03b92017-08-22 01:48:23 -0700147 expr_value = WITH_MODULE_NAMESPACE(
148 expr_value->module, expr_ns,
149 asn1f_lookup_symbol_ex(arg->asn, expr_ns, expr_value,
150 expr_value->value->value.reference));
Lev Walkinad0d6372017-08-08 02:02:42 -0700151 if(!expr_value) {
152 FATAL("Unrecognized value type for %s", MKID(cell->value));
153 return -1;
154 }
155 }
156
157 if(!primitive_representation) OUT("{ ");
158
159 switch(expr_value->value->type) {
160 case ATV_INTEGER:
161 if(primitive_representation) {
162 OUT("%s", asn1p_itoa(expr_value->value->value.v_integer));
163 break;
164 } else {
165 asn1c_integer_t v = expr_value->value->value.v_integer;
166 if(v >= 0) {
167 if(v <= 127) {
168 OUT("\"\\x%02x\", 1", v);
169 break;
170 } else if(v <= 32767) {
171 OUT("\"\\x%02x\\x%02x\", 2", (v >> 8), (v & 0xff));
172 break;
173 }
174 }
175 FATAL("Unsupported value %s range for type %s",
176 asn1f_printable_value(expr_value->value),
177 MKID(cell->value));
178 return -1;
179 }
180 case ATV_UNPARSED:
181 OUT("\"not supported\", 0 };\n");
182 FATAL("Inappropriate value %s for type %s",
183 asn1f_printable_value(expr_value->value), MKID(cell->value));
184 return 0; /* TEMPORARY FIXME FIXME */
185 default:
186 FATAL("Inappropriate value %s for type %s",
187 asn1f_printable_value(expr_value->value), MKID(cell->value));
188 return -1;
189 }
190
191 if(primitive_representation) {
192 OUT(";\n");
193 } else {
194 OUT(" };");
195 OUT(" /* %s */\n", asn1f_printable_value(expr_value->value));
196 }
197 }
198
199 return 0;
200}
201
202static int
203emit_ioc_cell(arg_t *arg, struct asn1p_ioc_cell_s *cell) {
204 OUT("{ \"%s\", ", cell->field->Identifier);
205
206 if(cell->value->meta_type == AMT_VALUE) {
207 GEN_INCLUDE(asn1c_type_name(arg, cell->value, TNF_INCLUDE));
208 OUT("aioc__value, ");
209 OUT("&asn_DEF_%s, ", asn1c_type_name(arg, cell->value, TNF_SAFE));
Lev Walkind357f3d2017-08-10 17:40:37 -0700210 OUT("&asn_VAL_%d_%s", cell->value->_type_unique_index,
211 MKID(cell->value));
Lev Walkinad0d6372017-08-08 02:02:42 -0700212
213 } else if(cell->value->meta_type == AMT_TYPEREF) {
214 GEN_INCLUDE(asn1c_type_name(arg, cell->value, TNF_INCLUDE));
215 OUT("aioc__type, &asn_DEF_%s", MKID(cell->value));
216 } else {
217 return -1;
218 }
219
220 OUT(" }");
221
222 return 0;
223}
224
225/*
226 * Refer to skeletons/asn_ioc.h
227 */
228int
229emit_ioc_table(arg_t *arg, asn1p_expr_t *context, asn1c_ioc_table_and_objset_t ioc_tao) {
230 size_t columns = 0;
231
232 (void)context;
233 GEN_INCLUDE_STD("asn_ioc");
234
Lev Walkin9de6cd82017-08-10 05:47:46 -0700235 REDIR(OT_IOC_TABLES);
Lev Walkinad0d6372017-08-08 02:02:42 -0700236
237 /* Emit values that are used in the Information Object Set table first */
238 for(size_t rn = 0; rn < ioc_tao.ioct->rows; rn++) {
239 asn1p_ioc_row_t *row = ioc_tao.ioct->row[rn];
240 for(size_t cn = 0; cn < row->columns; cn++) {
241 if(emit_ioc_value(arg, &row->column[cn])) {
242 return -1;
243 }
244 }
245 }
246
247 /* Emit the Information Object Set */
248 OUT("static const asn_ioc_cell_t asn_IOS_%s_%d_rows[] = {\n",
249 MKID(ioc_tao.objset), ioc_tao.objset->_type_unique_index);
250 INDENT(+1);
251
252 for(size_t rn = 0; rn < ioc_tao.ioct->rows; rn++) {
253 asn1p_ioc_row_t *row = ioc_tao.ioct->row[rn];
254 columns = columns ? columns : row->columns;
255 if(columns != row->columns) {
256 FATAL("Information Object Set %s row column mismatch on line %d",
257 ioc_tao.objset->Identifier, ioc_tao.objset->_lineno);
258 return -1;
259 }
260 for(size_t cn = 0; cn < row->columns; cn++) {
261 if(rn || cn) OUT(",\n");
262 emit_ioc_cell(arg, &row->column[cn]);
263 }
264 }
265 OUT("\n");
266
267 INDENT(-1);
268 OUT("};\n");
269
Lev Walkin6aae7c62017-08-10 17:58:48 -0700270 OUT("static const asn_ioc_set_t asn_IOS_%s_%d[] = {\n",
271 MKID(ioc_tao.objset), ioc_tao.objset->_type_unique_index);
Lev Walkinad0d6372017-08-08 02:02:42 -0700272 INDENT(+1);
273 OUT("%zu, %zu, asn_IOS_%s_%d_rows\n", ioc_tao.ioct->rows, columns,
274 MKID(ioc_tao.objset), ioc_tao.objset->_type_unique_index);
275 INDENT(-1);
276 OUT("};\n");
277
278 return 0;
279}
280