blob: 107303db4f0c319606895fc51658ff696dce096c [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 Walkinf15320b2004-06-03 03:38:44 +000079 DEBUG("Compiling %s at line %d",
80 expr->Identifier,
81 expr->_lineno);
82
83 ret = type_cb(arg);
Lev Walkin6fec44d2004-08-22 03:10:23 +000084
85 if(arg->target->destination[OT_TYPE_DECLS].indent_level == 0)
86 OUT(";\n");
Lev Walkinf15320b2004-06-03 03:38:44 +000087 } else {
88 ret = -1;
89 /*
90 * Even if the target language compiler does not know
91 * how to compile the given expression, we know that
92 * certain expressions need not to be compiled at all.
93 */
94 switch(expr->meta_type) {
95 case AMT_PARAMTYPE:
96 case AMT_OBJECT:
97 case AMT_OBJECTSET:
98 case AMT_VALUE:
99 case AMT_VALUESET:
100 ret = 0;
101 break;
102 default:
103 break;
104 }
105
106 switch(expr->expr_type) {
107 case A1TC_TYPEID:
108 ret = 0; /* TYPE-IDENTIFIER is a CLASS */
109 default:
110 break;
111 }
112 }
113
114 if(ret == -1) {
Lev Walkin6fec44d2004-08-22 03:10:23 +0000115 FATAL("Cannot compile \"%s\" (%x:%x) at line %d",
116 arg->expr->Identifier,
117 arg->expr->expr_type,
118 arg->expr->meta_type,
119 arg->expr->_lineno);
Lev Walkinf15320b2004-06-03 03:38:44 +0000120 OUT("#error Cannot compile \"%s\" (%x/%x) at line %d\n",
121 arg->expr->Identifier,
122 arg->expr->meta_type,
123 arg->expr->expr_type,
124 arg->expr->_lineno
125 );
126 }
127
128 return ret;
129}
130
131static int
132asn1c_attach_streams(asn1p_expr_t *expr) {
133 compiler_streams_t *cs;
134 int i;
135
136 if(expr->data)
137 return 0; /* Already attached? */
138
139 expr->data = calloc(1, sizeof(compiler_streams_t));
140 if(expr->data == NULL)
141 return -1;
142
143 cs = expr->data;
144 for(i = 0; i < OT_MAX; i++) {
Lev Walkin59004fa2004-08-20 13:37:01 +0000145 TQ_INIT(&(cs->destination[i].chunks));
Lev Walkinf15320b2004-06-03 03:38:44 +0000146 }
147
148 return 0;
149}
150
151static void
152default_logger_cb(int _severity, const char *fmt, ...) {
153 va_list ap;
154 char *pfx = "";
155
156 switch(_severity) {
157 case -1: pfx = "DEBUG: "; break;
158 case 0: pfx = "WARNING: "; break;
159 case 1: pfx = "FATAL: "; break;
160 }
161
162 fprintf(stderr, "%s", pfx);
163 va_start(ap, fmt);
164 vfprintf(stderr, fmt, ap);
165 va_end(ap);
166 fprintf(stderr, "\n");
167}
168