Update README.linux
[deliverable/titan.core.git] / compiler2 / CodeGenHelper.cc
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "CodeGenHelper.hh"
9 #include "Code.hh"
10 #include "error.h"
11 #include "main.hh"
12 #include <cstdio>
13 #include <cstring>
14
15 namespace Common {
16
17 CodeGenHelper* CodeGenHelper::instance = 0;
18
19 CodeGenHelper::generated_output_t::generated_output_t() :
20 is_module(false),
21 is_ttcn(true),
22 has_circular_import(false)
23 {
24 Code::init_output(&os);
25 }
26
27 CodeGenHelper::generated_output_t::~generated_output_t() {
28 Code::free_output(&os);
29 }
30
31 // from Type.cc
32 const char* const CodeGenHelper::typetypemap[] = {
33 "", /**< undefined */
34 "", /**< erroneous (e.g. nonexistent reference) */
35 "", /**< null (ASN.1) */
36 "", /**< boolean */
37 "", /**< integer */
38 "", /**< integer / ASN */
39 "", /**< real/float */
40 "", /**< enumerated / ASN */
41 "", /**< enumerated / TTCN */
42 "", /**< bitstring */
43 "", /**< bitstring */
44 "", /**< hexstring (TTCN-3) */
45 "", /**< octetstring */
46 "", /**< charstring (TTCN-3) */
47 "", /**< universal charstring (TTCN-3) */
48 "", /**< UTF8String (ASN.1) */
49 "", /**< NumericString (ASN.1) */
50 "", /**< PrintableString (ASN.1) */
51 "", /**< TeletexString (ASN.1) */
52 "", /**< VideotexString (ASN.1) */
53 "", /**< IA5String (ASN.1) */
54 "", /**< GraphicString (ASN.1) */
55 "", /**< VisibleString (ASN.1) */
56 "", /**< GeneralString (ASN.1) */
57 "", /**< UniversalString (ASN.1) */
58 "", /**< BMPString (ASN.1) */
59 "", /**< UnrestrictedCharacterString (ASN.1) */
60 "", /**< UTCTime (ASN.1) */
61 "", /**< GeneralizedTime (ASN.1) */
62 "", /** Object descriptor, a kind of string (ASN.1) */
63 "", /**< object identifier */
64 "", /**< relative OID (ASN.1) */
65 "_union", /**< choice /ASN, uses u.secho */
66 "_union", /**< union /TTCN, uses u.secho */
67 "_seqof", /**< sequence (record) of */
68 "_setof", /**< set of */
69 "_seq", /**< sequence /ASN, uses u.secho */
70 "_seq", /**< record /TTCN, uses u.secho */
71 "_set", /**< set /ASN, uses u.secho */
72 "_set", /**< set /TTCN, uses u.secho */
73 "", /**< ObjectClassFieldType (ASN.1) */
74 "", /**< open type (ASN.1) */
75 "", /**< ANY (deprecated ASN.1) */
76 "", /**< %EXTERNAL (ASN.1) */
77 "", /**< EMBEDDED PDV (ASN.1) */
78 "", /**< referenced */
79 "", /**< special referenced (by pointer, not by name) */
80 "", /**< selection type (ASN.1) */
81 "", /**< verdict type (TTCN-3) */
82 "", /**< port type (TTCN-3) */
83 "", /**< component type (TTCN-3) */
84 "", /**< address type (TTCN-3) */
85 "", /**< default type (TTCN-3) */
86 "", /**< array (TTCN-3), uses u.array */
87 "", /**< signature (TTCN-3) */
88 "", /**< function reference (TTCN-3) */
89 "", /**< altstep reference (TTCN-3) */
90 "", /**< testcase reference (TTCN-3) */
91 "", /**< anytype (TTCN-3) */
92 0
93 };
94
95 CodeGenHelper::CodeGenHelper() :
96 split_mode(SPLIT_NONE)
97 {
98 if (instance != 0)
99 FATAL_ERROR("Attempted to create a second code generator.");
100 instance = this;
101 }
102
103 CodeGenHelper& CodeGenHelper::GetInstance() {
104 if (instance == 0)
105 FATAL_ERROR("Trying to access to the already destroyed code generator.");
106 return *instance;
107 }
108
109 void CodeGenHelper::set_split_mode(split_type st) {
110 split_mode = st;
111 }
112
113 bool CodeGenHelper::set_split_mode(const char* type) {
114 if (strcmp(type, "none") == 0)
115 split_mode = SPLIT_NONE;
116 else if (strcmp(type, "type") == 0)
117 split_mode = SPLIT_BY_KIND;
118 else
119 return false;
120 return true;
121 }
122
123 CodeGenHelper::split_type CodeGenHelper::get_split_mode() const {
124 return split_mode;
125 }
126
127 void CodeGenHelper::add_module(const string& name, const string& dispname,
128 bool is_ttcn, bool has_circular_import) {
129 generated_output_t* go = new generated_output_t;
130 go->filename.clear();
131 go->modulename = name;
132 go->module_dispname = dispname;
133 go->is_module = true;
134 go->is_ttcn = is_ttcn;
135 go->has_circular_import = has_circular_import;
136 generated_code.add(dispname, go);
137 module_names_t* mod_names = new module_names_t;
138 mod_names->name = name;
139 mod_names->dispname = dispname;
140 modules.add(mod_names);
141 }
142
143 output_struct* CodeGenHelper::get_outputstruct(const string& name) {
144 return &generated_code[name]->os;
145 }
146
147 void CodeGenHelper::set_current_module(const string& name) {
148 current_module = name;
149 }
150
151 output_struct* CodeGenHelper::get_outputstruct(Ttcn::Definition* def) {
152 string key = get_key(*def);
153 const string& new_name = current_module + key;
154 if (!generated_code.has_key(new_name)) {
155 generated_output_t* go = new generated_output_t;
156 go->filename = key;
157 go->modulename = generated_code[current_module]->modulename;
158 go->module_dispname = generated_code[current_module]->module_dispname;
159 generated_code.add(new_name, go);
160 go->os.source.includes = mprintf("\n#include \"%s.hh\"\n"
161 , current_module.c_str());
162 }
163 return &generated_code[new_name]->os;
164 }
165
166 output_struct* CodeGenHelper::get_outputstruct(Type* type) {
167 string key = get_key(*type);
168 const string& new_name = current_module + key;
169 if (!generated_code.has_key(new_name)) {
170 generated_output_t* go = new generated_output_t;
171 go->filename = key;
172 go->modulename = generated_code[current_module]->modulename;
173 go->module_dispname = generated_code[current_module]->module_dispname;
174 generated_code.add(new_name, go);
175 go->os.source.includes = mprintf("\n#include \"%s.hh\"\n"
176 , current_module.c_str());
177 }
178 return &generated_code[new_name]->os;
179 }
180
181 output_struct* CodeGenHelper::get_current_outputstruct() {
182 return &generated_code[current_module]->os;
183 }
184
185 void CodeGenHelper::transfer_value(char* &dst, char* &src) {
186 dst = mputstr(dst, src);
187 Free(src);
188 src = 0;
189 }
190
191 void CodeGenHelper::finalize_generation(Type* type) {
192 string key = get_key(*type);
193 if (key.empty()) return;
194
195 output_struct& dst = *get_current_outputstruct();
196 output_struct& src = *get_outputstruct(current_module + key);
197 // key is not empty so these can never be the same
198
199 transfer_value(dst.header.includes, src.header.includes);
200 transfer_value(dst.header.class_decls, src.header.class_decls);
201 transfer_value(dst.header.typedefs, src.header.typedefs);
202 transfer_value(dst.header.class_defs, src.header.class_defs);
203 transfer_value(dst.header.function_prototypes, src.header.function_prototypes);
204 transfer_value(dst.header.global_vars, src.header.global_vars);
205 transfer_value(dst.header.testport_includes, src.header.testport_includes);
206
207 transfer_value(dst.source.global_vars, src.source.global_vars);
208
209 transfer_value(dst.functions.pre_init, src.functions.pre_init);
210 transfer_value(dst.functions.post_init, src.functions.post_init);
211
212 transfer_value(dst.functions.set_param, src.functions.set_param);
213 transfer_value(dst.functions.log_param, src.functions.log_param);
214 transfer_value(dst.functions.init_comp, src.functions.init_comp);
215 transfer_value(dst.functions.start, src.functions.start);
216 transfer_value(dst.functions.control, src.functions.control);
217 }
218
219 string CodeGenHelper::get_key(Ttcn::Definition& def) const {
220 string retval;
221 switch (split_mode) {
222 case SPLIT_NONE:
223 // returns the current module
224 break;
225 case SPLIT_BY_KIND:
226 break;
227 case SPLIT_BY_NAME:
228 retval += "_" + def.get_id().get_name();
229 break;
230 case SPLIT_BY_HEURISTICS:
231 break;
232 }
233 return retval;
234 }
235
236 string CodeGenHelper::get_key(Type& type) const {
237 string retval;
238 switch (split_mode) {
239 case SPLIT_NONE:
240 break;
241 case SPLIT_BY_KIND: {
242 Type::typetype_t tt = type.get_typetype();
243 switch(tt) {
244 case Type::T_CHOICE_A:
245 case Type::T_CHOICE_T:
246 case Type::T_SEQOF:
247 case Type::T_SETOF:
248 case Type::T_SEQ_A:
249 case Type::T_SEQ_T:
250 case Type::T_SET_A:
251 case Type::T_SET_T:
252 retval += typetypemap[(int)tt];
253 break;
254 default:
255 // put it into the module (no suffix)
256 break;
257 }
258 break; }
259 case SPLIT_BY_NAME:
260 break;
261 case SPLIT_BY_HEURISTICS:
262 break;
263 }
264 return retval;
265 }
266
267 void CodeGenHelper::write_output() {
268 size_t i, j;
269 if (split_mode == SPLIT_BY_KIND) {
270 // Create empty files to have a fix set of files to compile
271 string fname;
272 for (j = 0; j < modules.size(); j++) {
273 for (i = 0; typetypemap[i]; i++) {
274 fname = modules[j]->dispname + typetypemap[i];
275 if (!generated_code.has_key(fname)) {
276 generated_output_t* go = new generated_output_t;
277 go->filename = typetypemap[i];
278 go->modulename = modules[j]->name;
279 go->module_dispname = modules[j]->dispname;
280 go->os.source.includes = mcopystr(
281 "\n//This file intentionally empty."
282 "\n#include <version.h>\n");
283 generated_code.add(fname, go);
284 }
285 }
286 }
287 }
288 generated_output_t* go;
289 for (i = 0; i < generated_code.size(); i++) {
290 go = generated_code.get_nth_elem(i);
291 ::write_output(&go->os, go->modulename.c_str(), go->module_dispname.c_str(),
292 go->filename.c_str(), go->is_ttcn, go->has_circular_import, go->is_module);
293 }
294 }
295
296 CodeGenHelper::~CodeGenHelper() {
297 size_t i;
298 for (i = 0; i < generated_code.size(); i++)
299 delete generated_code.get_nth_elem(i);
300 generated_code.clear();
301 for (i = 0; i < modules.size(); i++)
302 delete modules[i];
303 modules.clear();
304 instance = 0;
305 }
306
307 }
This page took 0.037727 seconds and 5 git commands to generate.