blob: 37dca3e2acc12eeb9a0659e6c03499570694800f [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 Walkinf15320b2004-06-03 03:38:44 +000037 compiler_streams_t *cs = NULL;
38
39 if(asn1c_attach_streams(arg->expr))
40 return -1;
41
42 cs = arg->expr->data;
43 cs->target = OT_TYPE_DECLS;
44 arg->target = cs;
45
Lev Walkin9de6cd82017-08-10 05:47:46 -070046 ret = asn1c_compile_expr(arg, NULL);
Lev Walkinf15320b2004-06-03 03:38:44 +000047 if(ret) {
Lev Walkina00d6b32006-03-21 03:40:38 +000048 FATAL("Cannot compile \"%s\" (%x:%x) at line %d",
Lev Walkinf15320b2004-06-03 03:38:44 +000049 arg->expr->Identifier,
50 arg->expr->expr_type,
51 arg->expr->meta_type,
52 arg->expr->_lineno);
53 return ret;
54 }
55 }
56 }
57
58 DEBUG("Saving compiled data");
59
60 /*
61 * Save or print out the compiled result.
62 */
Lev Walkin8253ea92006-03-17 01:47:57 +000063 if(asn1c_save_compiled_output(arg, datadir, argc, optc, argv))
Lev Walkinf15320b2004-06-03 03:38:44 +000064 return -1;
65
Bi-Ruei, Chiu9b780832016-11-07 22:19:10 +080066 TQ_FOR(mod, &(asn->modules), mod_next) {
67 TQ_FOR(arg->expr, &(mod->members), next) {
68 asn1c_detach_streams(arg->expr);
69 }
70 }
71
Lev Walkinf15320b2004-06-03 03:38:44 +000072 return 0;
73}
74
75static int
Lev Walkin9de6cd82017-08-10 05:47:46 -070076asn1c_compile_expr(arg_t *arg, const asn1c_ioc_table_and_objset_t *opt_ioc) {
Lev Walkinf15320b2004-06-03 03:38:44 +000077 asn1p_expr_t *expr = arg->expr;
78 int (*type_cb)(arg_t *);
79 int ret;
80
Lev Walkind9bd7752004-06-05 08:17:50 +000081 assert((int)expr->meta_type >= AMT_INVALID);
Lev Walkinf15320b2004-06-03 03:38:44 +000082 assert(expr->meta_type < AMT_EXPR_META_MAX);
Lev Walkind9bd7752004-06-05 08:17:50 +000083 assert((int)expr->expr_type >= A1TC_INVALID);
Lev Walkinf15320b2004-06-03 03:38:44 +000084 assert(expr->expr_type < ASN_EXPR_TYPE_MAX);
85
86 type_cb = asn1_lang_map[expr->meta_type][expr->expr_type].type_cb;
87 if(type_cb) {
88
Lev Walkinf15320b2004-06-03 03:38:44 +000089 DEBUG("Compiling %s at line %d",
90 expr->Identifier,
91 expr->_lineno);
92
Lev Walkina00d6b32006-03-21 03:40:38 +000093 if(expr->lhs_params && expr->spec_index == -1) {
94 int i;
95 ret = 0;
96 DEBUG("Parameterized type %s at line %d: %s (%d)",
97 expr->Identifier, expr->_lineno,
98 expr->specializations.pspecs_count
99 ? "compiling" : "unused, skipping");
100 for(i = 0; i<expr->specializations.pspecs_count; i++) {
101 arg->expr = expr->specializations
102 .pspec[i].my_clone;
Lev Walkin9de6cd82017-08-10 05:47:46 -0700103 ret = asn1c_compile_expr(arg, opt_ioc);
Lev Walkina00d6b32006-03-21 03:40:38 +0000104 if(ret) break;
105 }
106 arg->expr = expr; /* Restore */
107 } else {
108 ret = type_cb(arg);
109 if(arg->target->destination[OT_TYPE_DECLS]
110 .indent_level == 0)
111 OUT(";\n");
112 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000113 } else {
114 ret = -1;
115 /*
116 * Even if the target language compiler does not know
117 * how to compile the given expression, we know that
118 * certain expressions need not to be compiled at all.
119 */
120 switch(expr->meta_type) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000121 case AMT_OBJECT:
Lev Walkin9c2285a2006-03-09 08:49:26 +0000122 case AMT_OBJECTCLASS:
123 case AMT_OBJECTFIELD:
Lev Walkinf15320b2004-06-03 03:38:44 +0000124 case AMT_VALUE:
125 case AMT_VALUESET:
126 ret = 0;
127 break;
128 default:
129 break;
130 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000131 }
132
133 if(ret == -1) {
Lev Walkin6fec44d2004-08-22 03:10:23 +0000134 FATAL("Cannot compile \"%s\" (%x:%x) at line %d",
135 arg->expr->Identifier,
136 arg->expr->expr_type,
137 arg->expr->meta_type,
138 arg->expr->_lineno);
Lev Walkinf15320b2004-06-03 03:38:44 +0000139 OUT("#error Cannot compile \"%s\" (%x/%x) at line %d\n",
140 arg->expr->Identifier,
141 arg->expr->meta_type,
142 arg->expr->expr_type,
143 arg->expr->_lineno
144 );
145 }
146
147 return ret;
148}
149
150static int
151asn1c_attach_streams(asn1p_expr_t *expr) {
152 compiler_streams_t *cs;
153 int i;
154
155 if(expr->data)
156 return 0; /* Already attached? */
157
158 expr->data = calloc(1, sizeof(compiler_streams_t));
159 if(expr->data == NULL)
160 return -1;
161
162 cs = expr->data;
163 for(i = 0; i < OT_MAX; i++) {
Lev Walkin59004fa2004-08-20 13:37:01 +0000164 TQ_INIT(&(cs->destination[i].chunks));
Lev Walkinf15320b2004-06-03 03:38:44 +0000165 }
166
167 return 0;
168}
169
Bi-Ruei, Chiu9b780832016-11-07 22:19:10 +0800170int
171asn1c_detach_streams(asn1p_expr_t *expr) {
172 compiler_streams_t *cs;
173 out_chunk_t *m;
174 int i;
175
176 if(!expr->data)
177 return 0; /* Already detached? */
178
179 cs = expr->data;
180 for(i = 0; i < OT_MAX; i++) {
181 while((m = TQ_REMOVE(&(cs->destination[i].chunks), next))) {
182 free(m->buf);
183 free(m);
184 }
185 }
186 free(expr->data);
187 expr->data = (void *)NULL;
188
189 return 0;
190}
191
Lev Walkinf15320b2004-06-03 03:38:44 +0000192static void
193default_logger_cb(int _severity, const char *fmt, ...) {
194 va_list ap;
195 char *pfx = "";
196
197 switch(_severity) {
198 case -1: pfx = "DEBUG: "; break;
199 case 0: pfx = "WARNING: "; break;
200 case 1: pfx = "FATAL: "; break;
201 }
202
203 fprintf(stderr, "%s", pfx);
204 va_start(ap, fmt);
205 vfprintf(stderr, fmt, ap);
206 va_end(ap);
207 fprintf(stderr, "\n");
208}
209