blob: 056b9dda21966e92249e70ded0c27d4818aa0c08 [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 Walkin5efafc52017-09-05 03:43:00 -07006#include "asn1c_naming.h"
Lev Walkinf15320b2004-06-03 03:38:44 +00007
8static void default_logger_cb(int, const char *fmt, ...);
Lev Walkin9de6cd82017-08-10 05:47:46 -07009static int asn1c_compile_expr(arg_t *arg, const asn1c_ioc_table_and_objset_t *);
Lev Walkinf15320b2004-06-03 03:38:44 +000010static int asn1c_attach_streams(asn1p_expr_t *expr);
Bi-Ruei, Chiu9b780832016-11-07 22:19:10 +080011static int asn1c_detach_streams(asn1p_expr_t *expr);
Lev Walkinf15320b2004-06-03 03:38:44 +000012
13int
Lev Walkin866cff12005-03-05 00:50:53 +000014asn1_compile(asn1p_t *asn, const char *datadir, enum asn1c_flags flags,
Lev Walkin8253ea92006-03-17 01:47:57 +000015 int argc, int optc, char **argv) {
Lev Walkinf15320b2004-06-03 03:38:44 +000016 arg_t arg_s;
17 arg_t *arg = &arg_s;
Lev Walkinb85a8132005-08-18 13:38:19 +000018 asn1p_module_t *mod;
Lev Walkinf15320b2004-06-03 03:38:44 +000019 int ret;
20
Lev Walkin5efafc52017-09-05 03:43:00 -070021 c_name_clash_finder_init();
22
Lev Walkinf15320b2004-06-03 03:38:44 +000023 /*
24 * Initialize target language.
25 */
26 ret = asn1c_with_language(ASN1C_LANGUAGE_C);
27 assert(ret == 0);
28
29 memset(arg, 0, sizeof(*arg));
30 arg->default_cb = asn1c_compile_expr;
31 arg->logger_cb = default_logger_cb;
32 arg->flags = flags;
33 arg->asn = asn;
34
35 /*
36 * Compile each individual top level structure.
37 */
Lev Walkinb85a8132005-08-18 13:38:19 +000038 TQ_FOR(mod, &(asn->modules), mod_next) {
39 TQ_FOR(arg->expr, &(mod->members), next) {
Lev Walkinc0e03b92017-08-22 01:48:23 -070040 arg->ns = asn1_namespace_new_from_module(mod, 0);
41
Lev Walkinf15320b2004-06-03 03:38:44 +000042 compiler_streams_t *cs = NULL;
43
44 if(asn1c_attach_streams(arg->expr))
45 return -1;
46
47 cs = arg->expr->data;
48 cs->target = OT_TYPE_DECLS;
49 arg->target = cs;
50
Lev Walkin9de6cd82017-08-10 05:47:46 -070051 ret = asn1c_compile_expr(arg, NULL);
Lev Walkinf15320b2004-06-03 03:38:44 +000052 if(ret) {
Lev Walkina00d6b32006-03-21 03:40:38 +000053 FATAL("Cannot compile \"%s\" (%x:%x) at line %d",
Lev Walkinf15320b2004-06-03 03:38:44 +000054 arg->expr->Identifier,
55 arg->expr->expr_type,
56 arg->expr->meta_type,
57 arg->expr->_lineno);
58 return ret;
59 }
Lev Walkinc0e03b92017-08-22 01:48:23 -070060
61 asn1_namespace_free(arg->ns);
62 arg->ns = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +000063 }
64 }
65
Lev Walkin5efafc52017-09-05 03:43:00 -070066 if(c_name_clash(arg)) {
67 if(arg->flags & A1C_COMPOUND_NAMES) {
68 FATAL("Name clashes encountered even with -fcompound-names flag");
69 /* Proceed further for better debugging. */
70 } else {
71 FATAL("Use \"-fcompound-names\" flag to asn1c to resolve name clashes");
72 if(arg->flags & A1C_PRINT_COMPILED) {
73 /* Proceed further for better debugging. */
74 } else {
75 return -1;
76 }
77 }
78 }
79
Lev Walkinf15320b2004-06-03 03:38:44 +000080 DEBUG("Saving compiled data");
81
Lev Walkin47fc74c2017-09-26 18:02:27 -070082 c_name_clash_finder_destroy();
83
Lev Walkinf15320b2004-06-03 03:38:44 +000084 /*
85 * Save or print out the compiled result.
86 */
Lev Walkin8253ea92006-03-17 01:47:57 +000087 if(asn1c_save_compiled_output(arg, datadir, argc, optc, argv))
Lev Walkinf15320b2004-06-03 03:38:44 +000088 return -1;
89
Bi-Ruei, Chiu9b780832016-11-07 22:19:10 +080090 TQ_FOR(mod, &(asn->modules), mod_next) {
91 TQ_FOR(arg->expr, &(mod->members), next) {
92 asn1c_detach_streams(arg->expr);
93 }
94 }
95
Lev Walkinf15320b2004-06-03 03:38:44 +000096 return 0;
97}
98
99static int
Lev Walkin9de6cd82017-08-10 05:47:46 -0700100asn1c_compile_expr(arg_t *arg, const asn1c_ioc_table_and_objset_t *opt_ioc) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000101 asn1p_expr_t *expr = arg->expr;
102 int (*type_cb)(arg_t *);
103 int ret;
104
Lev Walkind9bd7752004-06-05 08:17:50 +0000105 assert((int)expr->meta_type >= AMT_INVALID);
Lev Walkinf15320b2004-06-03 03:38:44 +0000106 assert(expr->meta_type < AMT_EXPR_META_MAX);
Lev Walkind9bd7752004-06-05 08:17:50 +0000107 assert((int)expr->expr_type >= A1TC_INVALID);
Lev Walkinf15320b2004-06-03 03:38:44 +0000108 assert(expr->expr_type < ASN_EXPR_TYPE_MAX);
109
110 type_cb = asn1_lang_map[expr->meta_type][expr->expr_type].type_cb;
111 if(type_cb) {
112
Lev Walkinf15320b2004-06-03 03:38:44 +0000113 DEBUG("Compiling %s at line %d",
114 expr->Identifier,
115 expr->_lineno);
116
Lev Walkina00d6b32006-03-21 03:40:38 +0000117 if(expr->lhs_params && expr->spec_index == -1) {
118 int i;
119 ret = 0;
120 DEBUG("Parameterized type %s at line %d: %s (%d)",
121 expr->Identifier, expr->_lineno,
122 expr->specializations.pspecs_count
123 ? "compiling" : "unused, skipping");
124 for(i = 0; i<expr->specializations.pspecs_count; i++) {
125 arg->expr = expr->specializations
126 .pspec[i].my_clone;
Lev Walkin9de6cd82017-08-10 05:47:46 -0700127 ret = asn1c_compile_expr(arg, opt_ioc);
Lev Walkina00d6b32006-03-21 03:40:38 +0000128 if(ret) break;
129 }
130 arg->expr = expr; /* Restore */
131 } else {
132 ret = type_cb(arg);
133 if(arg->target->destination[OT_TYPE_DECLS]
134 .indent_level == 0)
135 OUT(";\n");
136 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000137 } else {
138 ret = -1;
139 /*
140 * Even if the target language compiler does not know
141 * how to compile the given expression, we know that
142 * certain expressions need not to be compiled at all.
143 */
144 switch(expr->meta_type) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000145 case AMT_OBJECT:
Lev Walkin9c2285a2006-03-09 08:49:26 +0000146 case AMT_OBJECTCLASS:
147 case AMT_OBJECTFIELD:
Lev Walkinf15320b2004-06-03 03:38:44 +0000148 case AMT_VALUE:
149 case AMT_VALUESET:
150 ret = 0;
151 break;
152 default:
153 break;
154 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000155 }
156
157 if(ret == -1) {
Lev Walkin6fec44d2004-08-22 03:10:23 +0000158 FATAL("Cannot compile \"%s\" (%x:%x) at line %d",
159 arg->expr->Identifier,
160 arg->expr->expr_type,
161 arg->expr->meta_type,
162 arg->expr->_lineno);
Lev Walkinf15320b2004-06-03 03:38:44 +0000163 OUT("#error Cannot compile \"%s\" (%x/%x) at line %d\n",
164 arg->expr->Identifier,
165 arg->expr->meta_type,
166 arg->expr->expr_type,
167 arg->expr->_lineno
168 );
169 }
170
171 return ret;
172}
173
174static int
175asn1c_attach_streams(asn1p_expr_t *expr) {
176 compiler_streams_t *cs;
177 int i;
178
179 if(expr->data)
180 return 0; /* Already attached? */
181
182 expr->data = calloc(1, sizeof(compiler_streams_t));
183 if(expr->data == NULL)
184 return -1;
185
186 cs = expr->data;
187 for(i = 0; i < OT_MAX; i++) {
Lev Walkin59004fa2004-08-20 13:37:01 +0000188 TQ_INIT(&(cs->destination[i].chunks));
Lev Walkinf15320b2004-06-03 03:38:44 +0000189 }
190
191 return 0;
192}
193
Bi-Ruei, Chiu9b780832016-11-07 22:19:10 +0800194int
195asn1c_detach_streams(asn1p_expr_t *expr) {
196 compiler_streams_t *cs;
197 out_chunk_t *m;
198 int i;
199
200 if(!expr->data)
201 return 0; /* Already detached? */
202
203 cs = expr->data;
204 for(i = 0; i < OT_MAX; i++) {
205 while((m = TQ_REMOVE(&(cs->destination[i].chunks), next))) {
206 free(m->buf);
207 free(m);
208 }
209 }
210 free(expr->data);
211 expr->data = (void *)NULL;
212
213 return 0;
214}
215
Lev Walkinf15320b2004-06-03 03:38:44 +0000216static void
217default_logger_cb(int _severity, const char *fmt, ...) {
218 va_list ap;
219 char *pfx = "";
220
221 switch(_severity) {
222 case -1: pfx = "DEBUG: "; break;
223 case 0: pfx = "WARNING: "; break;
224 case 1: pfx = "FATAL: "; break;
225 }
226
227 fprintf(stderr, "%s", pfx);
228 va_start(ap, fmt);
229 vfprintf(stderr, fmt, ap);
230 va_end(ap);
231 fprintf(stderr, "\n");
232}
233