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