blob: 42d55e692d4df859c913ec5084fb3ff103cb1ad3 [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 Walkinf15320b2004-06-03 03:38:44 +00005
6static void default_logger_cb(int, const char *fmt, ...);
7static int asn1c_compile_expr(arg_t *arg);
8static int asn1c_attach_streams(asn1p_expr_t *expr);
Bi-Ruei, Chiu9b780832016-11-07 22:19:10 +08009static int asn1c_detach_streams(asn1p_expr_t *expr);
Lev Walkinf15320b2004-06-03 03:38:44 +000010
11int
Lev Walkin866cff12005-03-05 00:50:53 +000012asn1_compile(asn1p_t *asn, const char *datadir, enum asn1c_flags flags,
Lev Walkin8253ea92006-03-17 01:47:57 +000013 int argc, int optc, char **argv) {
Lev Walkinf15320b2004-06-03 03:38:44 +000014 arg_t arg_s;
15 arg_t *arg = &arg_s;
Lev Walkinb85a8132005-08-18 13:38:19 +000016 asn1p_module_t *mod;
Lev Walkinf15320b2004-06-03 03:38:44 +000017 int ret;
18
19 /*
20 * Initialize target language.
21 */
22 ret = asn1c_with_language(ASN1C_LANGUAGE_C);
23 assert(ret == 0);
24
25 memset(arg, 0, sizeof(*arg));
26 arg->default_cb = asn1c_compile_expr;
27 arg->logger_cb = default_logger_cb;
28 arg->flags = flags;
29 arg->asn = asn;
30
31 /*
32 * Compile each individual top level structure.
33 */
Lev Walkinb85a8132005-08-18 13:38:19 +000034 TQ_FOR(mod, &(asn->modules), mod_next) {
35 TQ_FOR(arg->expr, &(mod->members), next) {
Lev Walkinf15320b2004-06-03 03:38:44 +000036 compiler_streams_t *cs = NULL;
37
38 if(asn1c_attach_streams(arg->expr))
39 return -1;
40
41 cs = arg->expr->data;
42 cs->target = OT_TYPE_DECLS;
43 arg->target = cs;
44
45 ret = asn1c_compile_expr(arg);
46 if(ret) {
Lev Walkina00d6b32006-03-21 03:40:38 +000047 FATAL("Cannot compile \"%s\" (%x:%x) at line %d",
Lev Walkinf15320b2004-06-03 03:38:44 +000048 arg->expr->Identifier,
49 arg->expr->expr_type,
50 arg->expr->meta_type,
51 arg->expr->_lineno);
52 return ret;
53 }
54 }
55 }
56
57 DEBUG("Saving compiled data");
58
59 /*
60 * Save or print out the compiled result.
61 */
Lev Walkin8253ea92006-03-17 01:47:57 +000062 if(asn1c_save_compiled_output(arg, datadir, argc, optc, argv))
Lev Walkinf15320b2004-06-03 03:38:44 +000063 return -1;
64
Bi-Ruei, Chiu9b780832016-11-07 22:19:10 +080065 TQ_FOR(mod, &(asn->modules), mod_next) {
66 TQ_FOR(arg->expr, &(mod->members), next) {
67 asn1c_detach_streams(arg->expr);
68 }
69 }
70
Lev Walkinf15320b2004-06-03 03:38:44 +000071 return 0;
72}
73
74static int
75asn1c_compile_expr(arg_t *arg) {
76 asn1p_expr_t *expr = arg->expr;
77 int (*type_cb)(arg_t *);
78 int ret;
79
Lev Walkind9bd7752004-06-05 08:17:50 +000080 assert((int)expr->meta_type >= AMT_INVALID);
Lev Walkinf15320b2004-06-03 03:38:44 +000081 assert(expr->meta_type < AMT_EXPR_META_MAX);
Lev Walkind9bd7752004-06-05 08:17:50 +000082 assert((int)expr->expr_type >= A1TC_INVALID);
Lev Walkinf15320b2004-06-03 03:38:44 +000083 assert(expr->expr_type < ASN_EXPR_TYPE_MAX);
84
85 type_cb = asn1_lang_map[expr->meta_type][expr->expr_type].type_cb;
86 if(type_cb) {
87
Lev Walkinf15320b2004-06-03 03:38:44 +000088 DEBUG("Compiling %s at line %d",
89 expr->Identifier,
90 expr->_lineno);
91
Lev Walkina00d6b32006-03-21 03:40:38 +000092 if(expr->lhs_params && expr->spec_index == -1) {
93 int i;
94 ret = 0;
95 DEBUG("Parameterized type %s at line %d: %s (%d)",
96 expr->Identifier, expr->_lineno,
97 expr->specializations.pspecs_count
98 ? "compiling" : "unused, skipping");
99 for(i = 0; i<expr->specializations.pspecs_count; i++) {
100 arg->expr = expr->specializations
101 .pspec[i].my_clone;
102 ret = asn1c_compile_expr(arg);
103 if(ret) break;
104 }
105 arg->expr = expr; /* Restore */
106 } else {
107 ret = type_cb(arg);
108 if(arg->target->destination[OT_TYPE_DECLS]
109 .indent_level == 0)
110 OUT(";\n");
111 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000112 } else {
113 ret = -1;
114 /*
115 * Even if the target language compiler does not know
116 * how to compile the given expression, we know that
117 * certain expressions need not to be compiled at all.
118 */
119 switch(expr->meta_type) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000120 case AMT_OBJECT:
Lev Walkin9c2285a2006-03-09 08:49:26 +0000121 case AMT_OBJECTCLASS:
122 case AMT_OBJECTFIELD:
Lev Walkinf15320b2004-06-03 03:38:44 +0000123 case AMT_VALUE:
124 case AMT_VALUESET:
125 ret = 0;
126 break;
127 default:
128 break;
129 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000130 }
131
132 if(ret == -1) {
Lev Walkin6fec44d2004-08-22 03:10:23 +0000133 FATAL("Cannot compile \"%s\" (%x:%x) at line %d",
134 arg->expr->Identifier,
135 arg->expr->expr_type,
136 arg->expr->meta_type,
137 arg->expr->_lineno);
Lev Walkinf15320b2004-06-03 03:38:44 +0000138 OUT("#error Cannot compile \"%s\" (%x/%x) at line %d\n",
139 arg->expr->Identifier,
140 arg->expr->meta_type,
141 arg->expr->expr_type,
142 arg->expr->_lineno
143 );
144 }
145
146 return ret;
147}
148
149static int
150asn1c_attach_streams(asn1p_expr_t *expr) {
151 compiler_streams_t *cs;
152 int i;
153
154 if(expr->data)
155 return 0; /* Already attached? */
156
157 expr->data = calloc(1, sizeof(compiler_streams_t));
158 if(expr->data == NULL)
159 return -1;
160
161 cs = expr->data;
162 for(i = 0; i < OT_MAX; i++) {
Lev Walkin59004fa2004-08-20 13:37:01 +0000163 TQ_INIT(&(cs->destination[i].chunks));
Lev Walkinf15320b2004-06-03 03:38:44 +0000164 }
165
166 return 0;
167}
168
Bi-Ruei, Chiu9b780832016-11-07 22:19:10 +0800169int
170asn1c_detach_streams(asn1p_expr_t *expr) {
171 compiler_streams_t *cs;
172 out_chunk_t *m;
173 int i;
174
175 if(!expr->data)
176 return 0; /* Already detached? */
177
178 cs = expr->data;
179 for(i = 0; i < OT_MAX; i++) {
180 while((m = TQ_REMOVE(&(cs->destination[i].chunks), next))) {
181 free(m->buf);
182 free(m);
183 }
184 }
185 free(expr->data);
186 expr->data = (void *)NULL;
187
188 return 0;
189}
190
Lev Walkinf15320b2004-06-03 03:38:44 +0000191static void
192default_logger_cb(int _severity, const char *fmt, ...) {
193 va_list ap;
194 char *pfx = "";
195
196 switch(_severity) {
197 case -1: pfx = "DEBUG: "; break;
198 case 0: pfx = "WARNING: "; break;
199 case 1: pfx = "FATAL: "; break;
200 }
201
202 fprintf(stderr, "%s", pfx);
203 va_start(ap, fmt);
204 vfprintf(stderr, fmt, ap);
205 va_end(ap);
206 fprintf(stderr, "\n");
207}
208