blob: ccb0dd3a67fce70b9b847ab35255a75398f369a7 [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
7/*
8 * Given the table constraint or component relation constraint
9 * ({ObjectSetName}{...}) returns "ObjectSetName" as a reference.
10 */
11static const asn1p_ref_t *
12asn1c_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
27static asn1c_ioc_table_and_objset_t
28asn1c_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
45asn1c_ioc_table_and_objset_t
46asn1c_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
85static int
86emit_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
183static int
184emit_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 */
209int
210emit_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