blob: 18b2c0088bc649b61b6001ab56fa204202d26449 [file] [log] [blame]
vlmfa67ddc2004-06-03 03:38:44 +00001#include "asn1c_internal.h"
vlmb2839012004-08-20 13:37:01 +00002#include "asn1c_lang.h"
3#include "asn1c_out.h"
4#include "asn1c_save.h"
vlmfa67ddc2004-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);
9
10int
vlm2c874fe2005-03-05 00:50:53 +000011asn1_compile(asn1p_t *asn, const char *datadir, enum asn1c_flags flags,
vlm52e84b02006-03-17 01:47:57 +000012 int argc, int optc, char **argv) {
vlmfa67ddc2004-06-03 03:38:44 +000013 arg_t arg_s;
14 arg_t *arg = &arg_s;
vlm6c4a8502005-08-18 13:38:19 +000015 asn1p_module_t *mod;
vlmfa67ddc2004-06-03 03:38:44 +000016 int ret;
17
18 /*
19 * Initialize target language.
20 */
21 ret = asn1c_with_language(ASN1C_LANGUAGE_C);
22 assert(ret == 0);
23
24 memset(arg, 0, sizeof(*arg));
25 arg->default_cb = asn1c_compile_expr;
26 arg->logger_cb = default_logger_cb;
27 arg->flags = flags;
28 arg->asn = asn;
29
30 /*
31 * Compile each individual top level structure.
32 */
vlm6c4a8502005-08-18 13:38:19 +000033 TQ_FOR(mod, &(asn->modules), mod_next) {
34 TQ_FOR(arg->expr, &(mod->members), next) {
vlmfa67ddc2004-06-03 03:38:44 +000035 compiler_streams_t *cs = NULL;
36
37 if(asn1c_attach_streams(arg->expr))
38 return -1;
39
40 cs = arg->expr->data;
41 cs->target = OT_TYPE_DECLS;
42 arg->target = cs;
43
44 ret = asn1c_compile_expr(arg);
45 if(ret) {
vlm0c6d3812006-03-21 03:40:38 +000046 FATAL("Cannot compile \"%s\" (%x:%x) at line %d",
vlmfa67ddc2004-06-03 03:38:44 +000047 arg->expr->Identifier,
48 arg->expr->expr_type,
49 arg->expr->meta_type,
50 arg->expr->_lineno);
51 return ret;
52 }
53 }
54 }
55
56 DEBUG("Saving compiled data");
57
58 /*
59 * Save or print out the compiled result.
60 */
vlm52e84b02006-03-17 01:47:57 +000061 if(asn1c_save_compiled_output(arg, datadir, argc, optc, argv))
vlmfa67ddc2004-06-03 03:38:44 +000062 return -1;
63
64 return 0;
65}
66
67static int
68asn1c_compile_expr(arg_t *arg) {
69 asn1p_expr_t *expr = arg->expr;
70 int (*type_cb)(arg_t *);
71 int ret;
72
vlmb42843a2004-06-05 08:17:50 +000073 assert((int)expr->meta_type >= AMT_INVALID);
vlmfa67ddc2004-06-03 03:38:44 +000074 assert(expr->meta_type < AMT_EXPR_META_MAX);
vlmb42843a2004-06-05 08:17:50 +000075 assert((int)expr->expr_type >= A1TC_INVALID);
vlmfa67ddc2004-06-03 03:38:44 +000076 assert(expr->expr_type < ASN_EXPR_TYPE_MAX);
77
78 type_cb = asn1_lang_map[expr->meta_type][expr->expr_type].type_cb;
79 if(type_cb) {
80
vlmfa67ddc2004-06-03 03:38:44 +000081 DEBUG("Compiling %s at line %d",
82 expr->Identifier,
83 expr->_lineno);
84
vlm0c6d3812006-03-21 03:40:38 +000085 if(expr->lhs_params && expr->spec_index == -1) {
86 int i;
87 ret = 0;
88 DEBUG("Parameterized type %s at line %d: %s (%d)",
89 expr->Identifier, expr->_lineno,
90 expr->specializations.pspecs_count
91 ? "compiling" : "unused, skipping");
92 for(i = 0; i<expr->specializations.pspecs_count; i++) {
93 arg->expr = expr->specializations
94 .pspec[i].my_clone;
95 ret = asn1c_compile_expr(arg);
96 if(ret) break;
97 }
98 arg->expr = expr; /* Restore */
99 } else {
100 ret = type_cb(arg);
101 if(arg->target->destination[OT_TYPE_DECLS]
102 .indent_level == 0)
103 OUT(";\n");
104 }
vlmfa67ddc2004-06-03 03:38:44 +0000105 } else {
106 ret = -1;
107 /*
108 * Even if the target language compiler does not know
109 * how to compile the given expression, we know that
110 * certain expressions need not to be compiled at all.
111 */
112 switch(expr->meta_type) {
vlmfa67ddc2004-06-03 03:38:44 +0000113 case AMT_OBJECT:
vlmdc7cf042006-03-09 08:49:26 +0000114 case AMT_OBJECTCLASS:
115 case AMT_OBJECTFIELD:
vlmfa67ddc2004-06-03 03:38:44 +0000116 case AMT_VALUE:
117 case AMT_VALUESET:
118 ret = 0;
119 break;
120 default:
121 break;
122 }
vlmfa67ddc2004-06-03 03:38:44 +0000123 }
124
125 if(ret == -1) {
vlm2e0c1942004-08-22 03:10:23 +0000126 FATAL("Cannot compile \"%s\" (%x:%x) at line %d",
127 arg->expr->Identifier,
128 arg->expr->expr_type,
129 arg->expr->meta_type,
130 arg->expr->_lineno);
vlmfa67ddc2004-06-03 03:38:44 +0000131 OUT("#error Cannot compile \"%s\" (%x/%x) at line %d\n",
132 arg->expr->Identifier,
133 arg->expr->meta_type,
134 arg->expr->expr_type,
135 arg->expr->_lineno
136 );
137 }
138
139 return ret;
140}
141
142static int
143asn1c_attach_streams(asn1p_expr_t *expr) {
144 compiler_streams_t *cs;
145 int i;
146
147 if(expr->data)
148 return 0; /* Already attached? */
149
150 expr->data = calloc(1, sizeof(compiler_streams_t));
151 if(expr->data == NULL)
152 return -1;
153
154 cs = expr->data;
155 for(i = 0; i < OT_MAX; i++) {
vlmb2839012004-08-20 13:37:01 +0000156 TQ_INIT(&(cs->destination[i].chunks));
vlmfa67ddc2004-06-03 03:38:44 +0000157 }
158
159 return 0;
160}
161
162static void
163default_logger_cb(int _severity, const char *fmt, ...) {
164 va_list ap;
165 char *pfx = "";
166
167 switch(_severity) {
168 case -1: pfx = "DEBUG: "; break;
169 case 0: pfx = "WARNING: "; break;
170 case 1: pfx = "FATAL: "; break;
171 }
172
173 fprintf(stderr, "%s", pfx);
174 va_start(ap, fmt);
175 vfprintf(stderr, fmt, ap);
176 va_end(ap);
177 fprintf(stderr, "\n");
178}
179