blob: 79dd25b7b7cb27c0635648d486dbd4688b784923 [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
Bi-Ruei, Chiu89cde742017-10-06 21:27:39 +0800123 ? "compiling" : "unused, skipping",
124 expr->specializations.pspecs_count);
Lev Walkina00d6b32006-03-21 03:40:38 +0000125 for(i = 0; i<expr->specializations.pspecs_count; i++) {
126 arg->expr = expr->specializations
127 .pspec[i].my_clone;
Lev Walkin9de6cd82017-08-10 05:47:46 -0700128 ret = asn1c_compile_expr(arg, opt_ioc);
Lev Walkina00d6b32006-03-21 03:40:38 +0000129 if(ret) break;
130 }
131 arg->expr = expr; /* Restore */
132 } else {
133 ret = type_cb(arg);
134 if(arg->target->destination[OT_TYPE_DECLS]
135 .indent_level == 0)
136 OUT(";\n");
137 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000138 } else {
139 ret = -1;
140 /*
141 * Even if the target language compiler does not know
142 * how to compile the given expression, we know that
143 * certain expressions need not to be compiled at all.
144 */
145 switch(expr->meta_type) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000146 case AMT_OBJECT:
Lev Walkin9c2285a2006-03-09 08:49:26 +0000147 case AMT_OBJECTCLASS:
148 case AMT_OBJECTFIELD:
Lev Walkinf15320b2004-06-03 03:38:44 +0000149 case AMT_VALUE:
150 case AMT_VALUESET:
151 ret = 0;
152 break;
153 default:
154 break;
155 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000156 }
157
158 if(ret == -1) {
Lev Walkin6fec44d2004-08-22 03:10:23 +0000159 FATAL("Cannot compile \"%s\" (%x:%x) at line %d",
160 arg->expr->Identifier,
161 arg->expr->expr_type,
162 arg->expr->meta_type,
163 arg->expr->_lineno);
Lev Walkinf15320b2004-06-03 03:38:44 +0000164 OUT("#error Cannot compile \"%s\" (%x/%x) at line %d\n",
165 arg->expr->Identifier,
166 arg->expr->meta_type,
167 arg->expr->expr_type,
168 arg->expr->_lineno
169 );
170 }
171
172 return ret;
173}
174
175static int
176asn1c_attach_streams(asn1p_expr_t *expr) {
177 compiler_streams_t *cs;
178 int i;
179
180 if(expr->data)
181 return 0; /* Already attached? */
182
183 expr->data = calloc(1, sizeof(compiler_streams_t));
184 if(expr->data == NULL)
185 return -1;
186
187 cs = expr->data;
188 for(i = 0; i < OT_MAX; i++) {
Lev Walkin59004fa2004-08-20 13:37:01 +0000189 TQ_INIT(&(cs->destination[i].chunks));
Lev Walkinf15320b2004-06-03 03:38:44 +0000190 }
191
192 return 0;
193}
194
Bi-Ruei, Chiu9b780832016-11-07 22:19:10 +0800195int
196asn1c_detach_streams(asn1p_expr_t *expr) {
197 compiler_streams_t *cs;
198 out_chunk_t *m;
199 int i;
200
201 if(!expr->data)
202 return 0; /* Already detached? */
203
204 cs = expr->data;
205 for(i = 0; i < OT_MAX; i++) {
206 while((m = TQ_REMOVE(&(cs->destination[i].chunks), next))) {
207 free(m->buf);
208 free(m);
209 }
210 }
211 free(expr->data);
212 expr->data = (void *)NULL;
213
214 return 0;
215}
216
Lev Walkinf15320b2004-06-03 03:38:44 +0000217static void
218default_logger_cb(int _severity, const char *fmt, ...) {
219 va_list ap;
220 char *pfx = "";
221
222 switch(_severity) {
223 case -1: pfx = "DEBUG: "; break;
224 case 0: pfx = "WARNING: "; break;
225 case 1: pfx = "FATAL: "; break;
226 }
227
228 fprintf(stderr, "%s", pfx);
229 va_start(ap, fmt);
230 vfprintf(stderr, fmt, ap);
231 va_end(ap);
232 fprintf(stderr, "\n");
233}
234