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