blob: 31a422787e33a2798c6c7445bea4db1a8d8fe59a [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);
9
10int
Lev Walkin866cff12005-03-05 00:50:53 +000011asn1_compile(asn1p_t *asn, const char *datadir, enum asn1c_flags flags,
12 int argc, char **argv) {
Lev Walkinf15320b2004-06-03 03:38:44 +000013 arg_t arg_s;
14 arg_t *arg = &arg_s;
15 int ret;
16
17 /*
18 * Initialize target language.
19 */
20 ret = asn1c_with_language(ASN1C_LANGUAGE_C);
21 assert(ret == 0);
22
23 memset(arg, 0, sizeof(*arg));
24 arg->default_cb = asn1c_compile_expr;
25 arg->logger_cb = default_logger_cb;
26 arg->flags = flags;
27 arg->asn = asn;
28
29 /*
30 * Compile each individual top level structure.
31 */
32 TQ_FOR(arg->mod, &(asn->modules), mod_next) {
33 TQ_FOR(arg->expr, &(arg->mod->members), next) {
34 compiler_streams_t *cs = NULL;
35
36 if(asn1c_attach_streams(arg->expr))
37 return -1;
38
39 cs = arg->expr->data;
40 cs->target = OT_TYPE_DECLS;
41 arg->target = cs;
42
43 ret = asn1c_compile_expr(arg);
44 if(ret) {
45 FATAL("Cannot compile %s (%x:%x) at line %d",
46 arg->expr->Identifier,
47 arg->expr->expr_type,
48 arg->expr->meta_type,
49 arg->expr->_lineno);
50 return ret;
51 }
52 }
53 }
54
55 DEBUG("Saving compiled data");
56
57 /*
58 * Save or print out the compiled result.
59 */
Lev Walkin866cff12005-03-05 00:50:53 +000060 if(asn1c_save_compiled_output(arg, datadir, argc, argv))
Lev Walkinf15320b2004-06-03 03:38:44 +000061 return -1;
62
63 return 0;
64}
65
66static int
67asn1c_compile_expr(arg_t *arg) {
68 asn1p_expr_t *expr = arg->expr;
69 int (*type_cb)(arg_t *);
70 int ret;
71
Lev Walkind9bd7752004-06-05 08:17:50 +000072 assert((int)expr->meta_type >= AMT_INVALID);
Lev Walkinf15320b2004-06-03 03:38:44 +000073 assert(expr->meta_type < AMT_EXPR_META_MAX);
Lev Walkind9bd7752004-06-05 08:17:50 +000074 assert((int)expr->expr_type >= A1TC_INVALID);
Lev Walkinf15320b2004-06-03 03:38:44 +000075 assert(expr->expr_type < ASN_EXPR_TYPE_MAX);
76
77 type_cb = asn1_lang_map[expr->meta_type][expr->expr_type].type_cb;
78 if(type_cb) {
79
Lev Walkinf15320b2004-06-03 03:38:44 +000080 DEBUG("Compiling %s at line %d",
81 expr->Identifier,
82 expr->_lineno);
83
84 ret = type_cb(arg);
Lev Walkin6fec44d2004-08-22 03:10:23 +000085
86 if(arg->target->destination[OT_TYPE_DECLS].indent_level == 0)
87 OUT(";\n");
Lev Walkinf15320b2004-06-03 03:38:44 +000088 } else {
89 ret = -1;
90 /*
91 * Even if the target language compiler does not know
92 * how to compile the given expression, we know that
93 * certain expressions need not to be compiled at all.
94 */
95 switch(expr->meta_type) {
96 case AMT_PARAMTYPE:
97 case AMT_OBJECT:
98 case AMT_OBJECTSET:
99 case AMT_VALUE:
100 case AMT_VALUESET:
101 ret = 0;
102 break;
103 default:
104 break;
105 }
106
107 switch(expr->expr_type) {
108 case A1TC_TYPEID:
109 ret = 0; /* TYPE-IDENTIFIER is a CLASS */
110 default:
111 break;
112 }
113 }
114
115 if(ret == -1) {
Lev Walkin6fec44d2004-08-22 03:10:23 +0000116 FATAL("Cannot compile \"%s\" (%x:%x) at line %d",
117 arg->expr->Identifier,
118 arg->expr->expr_type,
119 arg->expr->meta_type,
120 arg->expr->_lineno);
Lev Walkinf15320b2004-06-03 03:38:44 +0000121 OUT("#error Cannot compile \"%s\" (%x/%x) at line %d\n",
122 arg->expr->Identifier,
123 arg->expr->meta_type,
124 arg->expr->expr_type,
125 arg->expr->_lineno
126 );
127 }
128
129 return ret;
130}
131
132static int
133asn1c_attach_streams(asn1p_expr_t *expr) {
134 compiler_streams_t *cs;
135 int i;
136
137 if(expr->data)
138 return 0; /* Already attached? */
139
140 expr->data = calloc(1, sizeof(compiler_streams_t));
141 if(expr->data == NULL)
142 return -1;
143
144 cs = expr->data;
145 for(i = 0; i < OT_MAX; i++) {
Lev Walkin59004fa2004-08-20 13:37:01 +0000146 TQ_INIT(&(cs->destination[i].chunks));
Lev Walkinf15320b2004-06-03 03:38:44 +0000147 }
148
149 return 0;
150}
151
152static void
153default_logger_cb(int _severity, const char *fmt, ...) {
154 va_list ap;
155 char *pfx = "";
156
157 switch(_severity) {
158 case -1: pfx = "DEBUG: "; break;
159 case 0: pfx = "WARNING: "; break;
160 case 1: pfx = "FATAL: "; break;
161 }
162
163 fprintf(stderr, "%s", pfx);
164 va_start(ap, fmt);
165 vfprintf(stderr, fmt, ap);
166 va_end(ap);
167 fprintf(stderr, "\n");
168}
169