blob: abebabb7cecb5a100acf3cc6d0ec1693c3481e1f [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>
6
Lev Walkin8354f342017-08-10 02:43:53 -07007#define MKID(expr) asn1c_make_identifier(0, (expr), 0)
8
Lev Walkinad0d6372017-08-08 02:02:42 -07009/*
10 * Given the table constraint or component relation constraint
11 * ({ObjectSetName}{...}) returns "ObjectSetName" as a reference.
12 */
13static const asn1p_ref_t *
14asn1c_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
29static asn1c_ioc_table_and_objset_t
30asn1c_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
47asn1c_ioc_table_and_objset_t
48asn1c_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 Walkin8354f342017-08-10 02:43:53 -070056 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 Walkinad0d6372017-08-08 02:02:42 -070063 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 Walkinad0d6372017-08-08 02:02:42 -070092static int
93emit_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 Walkin8354f342017-08-10 02:43:53 -070099 asn1p_expr_t *cv_type =
100 asn1f_find_terminal_type_ex(arg->asn, cell->value);
101
102 switch(cv_type->expr_type) {
Lev Walkinad0d6372017-08-08 02:02:42 -0700103 case ASN_BASIC_INTEGER:
104 case ASN_BASIC_ENUMERATED:
Lev Walkin8354f342017-08-10 02:43:53 -0700105 switch(asn1c_type_fits_long(arg, cell->value /* sic */)) {
Lev Walkinad0d6372017-08-08 02:02:42 -0700106 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 }
Lev Walkind357f3d2017-08-10 17:40:37 -0700135 OUT("static const %s asn_VAL_%d_%s = ", prim_type,
136 cell->value->_type_unique_index, MKID(cell->value));
Lev Walkinad0d6372017-08-08 02:02:42 -0700137
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
193static int
194emit_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));
Lev Walkind357f3d2017-08-10 17:40:37 -0700201 OUT("&asn_VAL_%d_%s", cell->value->_type_unique_index,
202 MKID(cell->value));
Lev Walkinad0d6372017-08-08 02:02:42 -0700203
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 */
219int
220emit_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
Lev Walkin9de6cd82017-08-10 05:47:46 -0700226 REDIR(OT_IOC_TABLES);
Lev Walkinad0d6372017-08-08 02:02:42 -0700227
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