blob: de09cfb48b032dddb041ea161d5fdc7a50df06d3 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include "asn1c_internal.h"
Lev Walkin59004fa2004-08-20 13:37:01 +00002#include "asn1c_lang.h"
3#include "asn1c_out.h"
4#include "asn1c_save.h"
Lev Walkin9de6cd82017-08-10 05:47:46 -07005#include "asn1c_ioc.h"
Lev Walkinf15320b2004-06-03 03:38:44 +00006
7static void default_logger_cb(int, const char *fmt, ...);
Lev Walkin9de6cd82017-08-10 05:47:46 -07008static int asn1c_compile_expr(arg_t *arg, const asn1c_ioc_table_and_objset_t *);
Lev Walkinf15320b2004-06-03 03:38:44 +00009static int asn1c_attach_streams(asn1p_expr_t *expr);
Bi-Ruei, Chiu9b780832016-11-07 22:19:10 +080010static int asn1c_detach_streams(asn1p_expr_t *expr);
Lev Walkinf15320b2004-06-03 03:38:44 +000011
12int
Lev Walkin866cff12005-03-05 00:50:53 +000013asn1_compile(asn1p_t *asn, const char *datadir, enum asn1c_flags flags,
Lev Walkin8253ea92006-03-17 01:47:57 +000014 int argc, int optc, char **argv) {
Lev Walkinf15320b2004-06-03 03:38:44 +000015 arg_t arg_s;
16 arg_t *arg = &arg_s;
Lev Walkinb85a8132005-08-18 13:38:19 +000017 asn1p_module_t *mod;
Lev Walkinf15320b2004-06-03 03:38:44 +000018 int ret;
19
20 /*
21 * Initialize target language.
22 */
23 ret = asn1c_with_language(ASN1C_LANGUAGE_C);
24 assert(ret == 0);
25
26 memset(arg, 0, sizeof(*arg));
27 arg->default_cb = asn1c_compile_expr;
28 arg->logger_cb = default_logger_cb;
29 arg->flags = flags;
30 arg->asn = asn;
31
32 /*
33 * Compile each individual top level structure.
34 */
Lev Walkinb85a8132005-08-18 13:38:19 +000035 TQ_FOR(mod, &(asn->modules), mod_next) {
36 TQ_FOR(arg->expr, &(mod->members), next) {
Lev Walkinc0e03b92017-08-22 01:48:23 -070037 arg->ns = asn1_namespace_new_from_module(mod, 0);
38
Lev Walkinf15320b2004-06-03 03:38:44 +000039 compiler_streams_t *cs = NULL;
40
41 if(asn1c_attach_streams(arg->expr))
42 return -1;
43
44 cs = arg->expr->data;
45 cs->target = OT_TYPE_DECLS;
46 arg->target = cs;
47
Lev Walkin9de6cd82017-08-10 05:47:46 -070048 ret = asn1c_compile_expr(arg, NULL);
Lev Walkinf15320b2004-06-03 03:38:44 +000049 if(ret) {
Lev Walkina00d6b32006-03-21 03:40:38 +000050 FATAL("Cannot compile \"%s\" (%x:%x) at line %d",
Lev Walkinf15320b2004-06-03 03:38:44 +000051 arg->expr->Identifier,
52 arg->expr->expr_type,
53 arg->expr->meta_type,
54 arg->expr->_lineno);
55 return ret;
56 }
Lev Walkinc0e03b92017-08-22 01:48:23 -070057
58 asn1_namespace_free(arg->ns);
59 arg->ns = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +000060 }
61 }
62
63 DEBUG("Saving compiled data");
64
65 /*
66 * Save or print out the compiled result.
67 */
Lev Walkin8253ea92006-03-17 01:47:57 +000068 if(asn1c_save_compiled_output(arg, datadir, argc, optc, argv))
Lev Walkinf15320b2004-06-03 03:38:44 +000069 return -1;
70
Bi-Ruei, Chiu9b780832016-11-07 22:19:10 +080071 TQ_FOR(mod, &(asn->modules), mod_next) {
72 TQ_FOR(arg->expr, &(mod->members), next) {
73 asn1c_detach_streams(arg->expr);
74 }
75 }
76
Lev Walkinf15320b2004-06-03 03:38:44 +000077 return 0;
78}
79
80static int
Lev Walkin9de6cd82017-08-10 05:47:46 -070081asn1c_compile_expr(arg_t *arg, const asn1c_ioc_table_and_objset_t *opt_ioc) {
Lev Walkinf15320b2004-06-03 03:38:44 +000082 asn1p_expr_t *expr = arg->expr;
83 int (*type_cb)(arg_t *);
84 int ret;
85
Lev Walkind9bd7752004-06-05 08:17:50 +000086 assert((int)expr->meta_type >= AMT_INVALID);
Lev Walkinf15320b2004-06-03 03:38:44 +000087 assert(expr->meta_type < AMT_EXPR_META_MAX);
Lev Walkind9bd7752004-06-05 08:17:50 +000088 assert((int)expr->expr_type >= A1TC_INVALID);
Lev Walkinf15320b2004-06-03 03:38:44 +000089 assert(expr->expr_type < ASN_EXPR_TYPE_MAX);
90
91 type_cb = asn1_lang_map[expr->meta_type][expr->expr_type].type_cb;
92 if(type_cb) {
93
Lev Walkinf15320b2004-06-03 03:38:44 +000094 DEBUG("Compiling %s at line %d",
95 expr->Identifier,
96 expr->_lineno);
97
Lev Walkina00d6b32006-03-21 03:40:38 +000098 if(expr->lhs_params && expr->spec_index == -1) {
99 int i;
100 ret = 0;
101 DEBUG("Parameterized type %s at line %d: %s (%d)",
102 expr->Identifier, expr->_lineno,
103 expr->specializations.pspecs_count
104 ? "compiling" : "unused, skipping");
105 for(i = 0; i<expr->specializations.pspecs_count; i++) {
106 arg->expr = expr->specializations
107 .pspec[i].my_clone;
Lev Walkin9de6cd82017-08-10 05:47:46 -0700108 ret = asn1c_compile_expr(arg, opt_ioc);
Lev Walkina00d6b32006-03-21 03:40:38 +0000109 if(ret) break;
110 }
111 arg->expr = expr; /* Restore */
112 } else {
113 ret = type_cb(arg);
114 if(arg->target->destination[OT_TYPE_DECLS]
115 .indent_level == 0)
116 OUT(";\n");
117 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000118 } else {
119 ret = -1;
120 /*
121 * Even if the target language compiler does not know
122 * how to compile the given expression, we know that
123 * certain expressions need not to be compiled at all.
124 */
125 switch(expr->meta_type) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000126 case AMT_OBJECT:
Lev Walkin9c2285a2006-03-09 08:49:26 +0000127 case AMT_OBJECTCLASS:
128 case AMT_OBJECTFIELD:
Lev Walkinf15320b2004-06-03 03:38:44 +0000129 case AMT_VALUE:
130 case AMT_VALUESET:
131 ret = 0;
132 break;
133 default:
134 break;
135 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000136 }
137
138 if(ret == -1) {
Lev Walkin6fec44d2004-08-22 03:10:23 +0000139 FATAL("Cannot compile \"%s\" (%x:%x) at line %d",
140 arg->expr->Identifier,
141 arg->expr->expr_type,
142 arg->expr->meta_type,
143 arg->expr->_lineno);
Lev Walkinf15320b2004-06-03 03:38:44 +0000144 OUT("#error Cannot compile \"%s\" (%x/%x) at line %d\n",
145 arg->expr->Identifier,
146 arg->expr->meta_type,
147 arg->expr->expr_type,
148 arg->expr->_lineno
149 );
150 }
151
152 return ret;
153}
154
155static int
156asn1c_attach_streams(asn1p_expr_t *expr) {
157 compiler_streams_t *cs;
158 int i;
159
160 if(expr->data)
161 return 0; /* Already attached? */
162
163 expr->data = calloc(1, sizeof(compiler_streams_t));
164 if(expr->data == NULL)
165 return -1;
166
167 cs = expr->data;
168 for(i = 0; i < OT_MAX; i++) {
Lev Walkin59004fa2004-08-20 13:37:01 +0000169 TQ_INIT(&(cs->destination[i].chunks));
Lev Walkinf15320b2004-06-03 03:38:44 +0000170 }
171
172 return 0;
173}
174
Bi-Ruei, Chiu9b780832016-11-07 22:19:10 +0800175int
176asn1c_detach_streams(asn1p_expr_t *expr) {
177 compiler_streams_t *cs;
178 out_chunk_t *m;
179 int i;
180
181 if(!expr->data)
182 return 0; /* Already detached? */
183
184 cs = expr->data;
185 for(i = 0; i < OT_MAX; i++) {
186 while((m = TQ_REMOVE(&(cs->destination[i].chunks), next))) {
187 free(m->buf);
188 free(m);
189 }
190 }
191 free(expr->data);
192 expr->data = (void *)NULL;
193
194 return 0;
195}
196
Lev Walkinf15320b2004-06-03 03:38:44 +0000197static void
198default_logger_cb(int _severity, const char *fmt, ...) {
199 va_list ap;
200 char *pfx = "";
201
202 switch(_severity) {
203 case -1: pfx = "DEBUG: "; break;
204 case 0: pfx = "WARNING: "; break;
205 case 1: pfx = "FATAL: "; break;
206 }
207
208 fprintf(stderr, "%s", pfx);
209 va_start(ap, fmt);
210 vfprintf(stderr, fmt, ap);
211 va_end(ap);
212 fprintf(stderr, "\n");
213}
214