blob: 8d963ef67e8906efb2c380562a9f4032bf52aeb1 [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
82 /*
83 * Save or print out the compiled result.
84 */
Lev Walkin8253ea92006-03-17 01:47:57 +000085 if(asn1c_save_compiled_output(arg, datadir, argc, optc, argv))
Lev Walkinf15320b2004-06-03 03:38:44 +000086 return -1;
87
Bi-Ruei, Chiu9b780832016-11-07 22:19:10 +080088 TQ_FOR(mod, &(asn->modules), mod_next) {
89 TQ_FOR(arg->expr, &(mod->members), next) {
90 asn1c_detach_streams(arg->expr);
91 }
92 }
93
Lev Walkinf15320b2004-06-03 03:38:44 +000094 return 0;
95}
96
97static int
Lev Walkin9de6cd82017-08-10 05:47:46 -070098asn1c_compile_expr(arg_t *arg, const asn1c_ioc_table_and_objset_t *opt_ioc) {
Lev Walkinf15320b2004-06-03 03:38:44 +000099 asn1p_expr_t *expr = arg->expr;
100 int (*type_cb)(arg_t *);
101 int ret;
102
Lev Walkind9bd7752004-06-05 08:17:50 +0000103 assert((int)expr->meta_type >= AMT_INVALID);
Lev Walkinf15320b2004-06-03 03:38:44 +0000104 assert(expr->meta_type < AMT_EXPR_META_MAX);
Lev Walkind9bd7752004-06-05 08:17:50 +0000105 assert((int)expr->expr_type >= A1TC_INVALID);
Lev Walkinf15320b2004-06-03 03:38:44 +0000106 assert(expr->expr_type < ASN_EXPR_TYPE_MAX);
107
108 type_cb = asn1_lang_map[expr->meta_type][expr->expr_type].type_cb;
109 if(type_cb) {
110
Lev Walkinf15320b2004-06-03 03:38:44 +0000111 DEBUG("Compiling %s at line %d",
112 expr->Identifier,
113 expr->_lineno);
114
Lev Walkina00d6b32006-03-21 03:40:38 +0000115 if(expr->lhs_params && expr->spec_index == -1) {
116 int i;
117 ret = 0;
118 DEBUG("Parameterized type %s at line %d: %s (%d)",
119 expr->Identifier, expr->_lineno,
120 expr->specializations.pspecs_count
121 ? "compiling" : "unused, skipping");
122 for(i = 0; i<expr->specializations.pspecs_count; i++) {
123 arg->expr = expr->specializations
124 .pspec[i].my_clone;
Lev Walkin9de6cd82017-08-10 05:47:46 -0700125 ret = asn1c_compile_expr(arg, opt_ioc);
Lev Walkina00d6b32006-03-21 03:40:38 +0000126 if(ret) break;
127 }
128 arg->expr = expr; /* Restore */
129 } else {
130 ret = type_cb(arg);
131 if(arg->target->destination[OT_TYPE_DECLS]
132 .indent_level == 0)
133 OUT(";\n");
134 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000135 } else {
136 ret = -1;
137 /*
138 * Even if the target language compiler does not know
139 * how to compile the given expression, we know that
140 * certain expressions need not to be compiled at all.
141 */
142 switch(expr->meta_type) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000143 case AMT_OBJECT:
Lev Walkin9c2285a2006-03-09 08:49:26 +0000144 case AMT_OBJECTCLASS:
145 case AMT_OBJECTFIELD:
Lev Walkinf15320b2004-06-03 03:38:44 +0000146 case AMT_VALUE:
147 case AMT_VALUESET:
148 ret = 0;
149 break;
150 default:
151 break;
152 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000153 }
154
155 if(ret == -1) {
Lev Walkin6fec44d2004-08-22 03:10:23 +0000156 FATAL("Cannot compile \"%s\" (%x:%x) at line %d",
157 arg->expr->Identifier,
158 arg->expr->expr_type,
159 arg->expr->meta_type,
160 arg->expr->_lineno);
Lev Walkinf15320b2004-06-03 03:38:44 +0000161 OUT("#error Cannot compile \"%s\" (%x/%x) at line %d\n",
162 arg->expr->Identifier,
163 arg->expr->meta_type,
164 arg->expr->expr_type,
165 arg->expr->_lineno
166 );
167 }
168
169 return ret;
170}
171
172static int
173asn1c_attach_streams(asn1p_expr_t *expr) {
174 compiler_streams_t *cs;
175 int i;
176
177 if(expr->data)
178 return 0; /* Already attached? */
179
180 expr->data = calloc(1, sizeof(compiler_streams_t));
181 if(expr->data == NULL)
182 return -1;
183
184 cs = expr->data;
185 for(i = 0; i < OT_MAX; i++) {
Lev Walkin59004fa2004-08-20 13:37:01 +0000186 TQ_INIT(&(cs->destination[i].chunks));
Lev Walkinf15320b2004-06-03 03:38:44 +0000187 }
188
189 return 0;
190}
191
Bi-Ruei, Chiu9b780832016-11-07 22:19:10 +0800192int
193asn1c_detach_streams(asn1p_expr_t *expr) {
194 compiler_streams_t *cs;
195 out_chunk_t *m;
196 int i;
197
198 if(!expr->data)
199 return 0; /* Already detached? */
200
201 cs = expr->data;
202 for(i = 0; i < OT_MAX; i++) {
203 while((m = TQ_REMOVE(&(cs->destination[i].chunks), next))) {
204 free(m->buf);
205 free(m);
206 }
207 }
208 free(expr->data);
209 expr->data = (void *)NULL;
210
211 return 0;
212}
213
Lev Walkinf15320b2004-06-03 03:38:44 +0000214static void
215default_logger_cb(int _severity, const char *fmt, ...) {
216 va_list ap;
217 char *pfx = "";
218
219 switch(_severity) {
220 case -1: pfx = "DEBUG: "; break;
221 case 0: pfx = "WARNING: "; break;
222 case 1: pfx = "FATAL: "; break;
223 }
224
225 fprintf(stderr, "%s", pfx);
226 va_start(ap, fmt);
227 vfprintf(stderr, fmt, ap);
228 va_end(ap);
229 fprintf(stderr, "\n");
230}
231