3f45141d064e8cd8cfe8b9fb0ceaba396eed3413
[deliverable/titan.core.git] / compiler2 / AST.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 <set>
9 #include <string>
10 #include <sstream>
11
12 #include "../common/dbgnew.hh"
13 #include "AST.hh"
14 #include "asn1/AST_asn1.hh"
15 #include "Identifier.hh"
16 #include "Type.hh"
17 #include "TypeCompat.hh"
18 #include "Value.hh"
19 #include "ustring.hh"
20 #include "main.hh"
21 #include "asn1/Object0.hh"
22 #include "PredefFunc.hh"
23 #include "../common/version.h"
24 #include "CodeGenHelper.hh"
25 #include <limits.h>
26
27 reffer::reffer(const char*) {}
28
29 namespace Common {
30
31 // =================================
32 // ===== Modules
33 // =================================
34
35 Modules::Modules()
36 : Node(), mods_v(), mods_m()
37 {
38 set_fullname(string('@'));
39 }
40
41 Modules::~Modules()
42 {
43 for(size_t i = 0; i < mods_v.size(); i++) delete mods_v[i];
44 mods_v.clear();
45 mods_m.clear();
46 }
47
48 Modules *Modules::clone() const
49 {
50 FATAL_ERROR("Modules::clone()");
51 return 0;
52 }
53
54 void Modules::add_mod(Module *p_mod)
55 {
56 if (!p_mod) FATAL_ERROR("NULL parameter: Common::Modules::add_mod()");
57 p_mod->set_fullname("@"+p_mod->get_modid().get_dispname());
58 p_mod->set_scope_name(p_mod->get_modid().get_dispname());
59 mods_v.add(p_mod);
60 }
61
62 bool Modules::has_mod_withId(const Identifier& p_modid)
63 {
64 return mods_m.has_key(p_modid.get_name());
65 }
66
67 Module* Modules::get_mod_byId(const Identifier& p_modid)
68 {
69 const string& name = p_modid.get_name();
70 return mods_m.has_key(name)?mods_m[name]:0;
71 }
72
73 Assignment* Modules::get_ass_bySRef(Ref_simple *p_ref)
74 {
75 if(!p_ref)
76 FATAL_ERROR("NULL parameter: Common::Modules::get_ass_bySRef()");
77 const Identifier *modid=p_ref->get_modid();
78 if(modid) {
79 if(has_mod_withId(*modid))
80 return get_mod_byId(*modid)->get_ass_bySRef(p_ref);
81 else {
82 p_ref->error("There is no module with identifier `%s'",
83 modid->get_dispname().c_str());
84 return 0;
85 }
86 }
87 else {
88 p_ref->error("`%s' entity not found in global scope",
89 p_ref->get_dispname().c_str());
90 return 0;
91 }
92 }
93
94 void Modules::chk_uniq()
95 {
96 for(size_t i = 0; i < mods_v.size(); i++) {
97 Module *m = mods_v[i];
98 const Identifier& id = m->get_modid();
99 const string& name = id.get_name();
100 if (mods_m.has_key(name)) {
101 Module *m2 = mods_m[name];
102 m->error("A module with identifier `%s' already exists",
103 id.get_dispname().c_str());
104 m2->error("This is the first module with the same name");
105 if (m->get_moduletype() == m2->get_moduletype() &&
106 !strcmp(m->get_filename(), m2->get_filename())) {
107 // the same file was given twice -> drop the entire module
108 delete m;
109 mods_v.replace(i, 1);
110 i--;
111 }
112 } else mods_m.add(name, m);
113 }
114 }
115
116 void Modules::chk()
117 {
118 // first check the uniqueness of module names
119 chk_uniq();
120 // check the import chains
121 size_t nof_mods = mods_v.size();
122 for (size_t i = 0; i < nof_mods; i++) {
123 Module *m = mods_v[i];
124 ReferenceChain refch(m, "While checking import chains");
125 vector<Common::Module> modules;
126 m->chk_imp(refch, modules);
127 modules.clear();
128 //clear the reference chain, get a fresh start
129 refch.reset();
130 }
131 // check the modules
132 Module::module_set_t checked_modules;
133 if (nof_top_level_pdus > 0) {
134 chk_top_level_pdus();
135 // do not check ASN.1 modules, but assume they are already checked
136 for (size_t i = 0; i < nof_mods; i++) {
137 Module *module = mods_v[i];
138 if (module->get_moduletype() == Module::MOD_ASN)
139 checked_modules.add(module, 0);
140 }
141 for (size_t i = 0; i < nof_mods; i++) {
142 Module *module = mods_v[i];
143 if (module->get_moduletype() != Module::MOD_ASN)
144 module->chk_recursive(checked_modules);
145 }
146 } else {
147 // walk through all modules in bottom-up order
148 for (size_t i = 0; i < nof_mods; i++)
149 mods_v[i]->chk_recursive(checked_modules);
150 }
151 checked_modules.clear();
152 }
153
154 void Modules::chk_top_level_pdus()
155 {
156 Location loc("<command line>");
157 for(size_t i=0; i<nof_top_level_pdus; i++) {
158 string pduname(top_level_pdu[i]);
159 size_t dotpos=pduname.find('.');
160 if(dotpos>=pduname.size()) {
161 loc.error("While searching top-level pdu `%s': "
162 "Please use the `modulename.identifier' format",
163 pduname.c_str());
164 continue;
165 }
166 Module *module=0;
167 Identifier *pdu_id=0;
168 { // searching the module
169 const string& pduname_mod = pduname.substr(0, dotpos);
170 const string& pduname_id = pduname.substr(dotpos + 1);
171 { // ASN
172 Identifier modid(Identifier::ID_ASN, pduname_mod, true);
173 module = get_mod_byId(modid);
174 }
175 if (module && module->get_moduletype() == Module::MOD_ASN) {
176 pdu_id = new Identifier(Identifier::ID_ASN, pduname_id, true);
177 goto mod_ok;
178 }
179 { // TTCN
180 Identifier modid(Identifier::ID_TTCN, pduname_mod, true);
181 module = get_mod_byId(modid);
182 }
183 if (module && module->get_moduletype() == Module::MOD_TTCN) {
184 pdu_id = new Identifier(Identifier::ID_TTCN, pduname_id, true);
185 goto mod_ok;
186 }
187 { // C++
188 Identifier modid(Identifier::ID_NAME, pduname_mod, true);
189 module = get_mod_byId(modid);
190 }
191 if(module) {
192 pdu_id = new Identifier(Identifier::ID_NAME, pduname_id, true);
193 goto mod_ok;
194 }
195 // error - no such module
196 loc.error("While searching top-level pdu `%s': "
197 "No module with name `%s'",
198 pduname.c_str(), pduname_mod.c_str());
199 continue;
200 }
201 mod_ok:
202 Assignments *asss=module->get_asss();
203 if(asss->has_local_ass_withId(*pdu_id)) {
204 Assignment *ass=asss->get_local_ass_byId(*pdu_id);
205 ass->chk();
206 }
207 else {
208 loc.error("While searching top-level pdu `%s': "
209 "No assignment with identifier `%s'",
210 pduname.c_str(), pdu_id->get_dispname().c_str());
211 }
212 delete pdu_id;
213 } // for top-level pdus
214 }
215
216 void Modules::write_checksums()
217 {
218 fputs("Module name Language MD5 checksum Version\n"
219 "---------------------------------------------------------------------------\n", stderr);
220 size_t nof_mods = mods_v.size();
221 for (size_t i = 0; i < nof_mods; i++) {
222 mods_v[i]->write_checksum();
223 }
224 }
225
226 void Modules::generate_code(CodeGenHelper& cgh)
227 {
228 Common::Module::rename_default_namespace(); // if needed
229 /*
230 The White Rabbit put on his spectacles.
231 "Where shall I begin, please your Majesty ?" he asked.
232 "Begin at the beginning,", the King said, very gravely, "and go on
233 till you come to the end: then stop."
234 -- Lewis Carroll
235 */
236 for (size_t i = 0; i < mods_v.size(); i++) {
237 mods_v[i]->generate_code(cgh);
238 if (tcov_file_name && in_tcov_files(mods_v[i]->get_filename())) {
239 Free(effective_module_lines);
240 Free(effective_module_functions);
241 effective_module_lines = effective_module_functions = NULL;
242 }
243 }
244
245 cgh.write_output();
246 }
247
248
249 void Modules::dump(unsigned level) const
250 {
251 DEBUG(level, "Modules (%lu pcs.)", (unsigned long) mods_v.size());
252 for(size_t i = 0; i < mods_v.size(); i++) mods_v[i]->dump(level);
253 }
254
255 std::set<ModuleVersion> Modules::getVersionsWithProductNumber() const {
256 std::set<ModuleVersion> versions;
257 for (size_t i = 0; i < mods_v.size(); ++i) {
258 const ModuleVersion version = mods_v[i]->getVersion();
259 if (version.hasProductNumber()) {
260 versions.insert(version);
261 }
262 }
263 return versions;
264 }
265
266 void Modules::add_types_to_json_schema(JSON_Tokenizer& json)
267 {
268 for(size_t i = 0; i < mods_v.size(); ++i) {
269 mods_v[i]->add_types_to_json_schema(json);
270 }
271 }
272
273 void Modules::add_func_to_json_schema(map<Type*, JSON_Tokenizer>& json_refs)
274 {
275 for(size_t i = 0; i < mods_v.size(); ++i) {
276 mods_v[i]->add_func_to_json_schema(json_refs);
277 }
278 }
279
280
281 // =================================
282 // ===== Module
283 // =================================
284
285 ModuleVersion Module::getVersion() const {
286 return ModuleVersion(product_number, suffix, release, patch, build, extra);
287 }
288
289 void Module::generate_literals(output_struct *target)
290 {
291 char *src = NULL;
292 char *hdr = NULL;
293 generate_bs_literals(src, hdr); // implementations follow directly below
294 generate_bp_literals(src, hdr);
295 generate_hs_literals(src, hdr);
296 generate_hp_literals(src, hdr);
297 generate_os_literals(src, hdr);
298 generate_op_literals(src, hdr);
299 generate_cs_literals(src, hdr);
300 generate_us_literals(src, hdr);
301 generate_oid_literals(src, hdr);
302 generate_pp_literals(src, hdr);
303 generate_mp_literals(src, hdr);
304 target->source.string_literals =
305 mputstr(target->source.string_literals, src);
306 if (CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE) {
307 target->header.global_vars = mputstr(target->header.global_vars, hdr);
308 }
309 Free(src);
310 Free(hdr);
311 }
312
313 void Module::generate_bs_literals(char *&src, char *&hdr)
314 {
315 if (bs_literals.size() == 0) return;
316 // indicates whether we have found at least one non-empty bitstring
317 bool is_nonempty = false;
318 bool splitting =
319 CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE;
320 for (size_t i = 0; i < bs_literals.size(); i++) {
321 const string& str = bs_literals.get_nth_key(i);
322 size_t bits = str.size();
323 if (bits == 0) continue;
324 if (is_nonempty) src = mputstr(src, ",\n");
325 else {
326 src = mputstr(src, "static const unsigned char ");
327 is_nonempty = true;
328 }
329 src = mputprintf(src, "%s_bits[] = { ",
330 bs_literals.get_nth_elem(i)->c_str());
331 // Filling up the octets one-by-one
332 for (size_t j = 0; j < (bits + 7) / 8; j++) {
333 size_t offset = 8 * j;
334 unsigned char value = 0;
335 for (size_t k = 0; k < 8 && k < bits - offset; k++) {
336 if (str[offset + k] == '1') value |= (1 << k);
337 }
338 if (j > 0) src = mputstr(src, ", ");
339 src = mputprintf(src, "%d", value);
340 }
341 src = mputstr(src, " }");
342 }
343 if (is_nonempty) src = mputstr(src, ";\n");
344 for (size_t i = 0; i < bs_literals.size(); i++) {
345 if (i > 0) {
346 src = mputstr(src, ",\n");
347 if (splitting) hdr = mputstr(hdr, ",\n");
348 }
349 else {
350 src = mputprintf(src, "%s const BITSTRING ",
351 splitting ? "extern" : "static");
352 if (splitting) hdr = mputstr(hdr, "extern const BITSTRING ");
353 }
354 size_t bits = bs_literals.get_nth_key(i).size();
355 const char *object_name = bs_literals.get_nth_elem(i)->c_str();
356 if (bits > 0) src = mputprintf(src, "%s(%lu, %s_bits)",
357 object_name, (unsigned long) bits, object_name);
358 else src = mputprintf(src, "%s(0, NULL)", object_name);
359 if (splitting) hdr = mputstr(hdr, object_name);
360 }
361 src = mputstr(src, ";\n");
362 if (splitting) hdr = mputstr(hdr, ";\n");
363 }
364
365 void Module::generate_bp_literals(char *&src, char *& /*hdr*/)
366 {
367 if (bp_literals.size() == 0) return;
368 for (size_t i = 0; i < bp_literals.size(); i++) {
369 if (i > 0) src = mputstr(src, ",\n");
370 else src = mputstr(src, "static const unsigned char ");
371 src = mputprintf(src, "%s_elements[] = { ",
372 bp_literals.get_nth_elem(i)->c_str());
373 const string& str = bp_literals.get_nth_key(i);
374 for (size_t j = 0; j < str.size(); j++) {
375 if (j > 0) src = mputstr(src, ", ");
376 switch (str[j]) {
377 case '0':
378 src = mputc(src, '0');
379 break;
380 case '1':
381 src = mputc(src, '1');
382 break;
383 case '?':
384 src = mputc(src, '2');
385 break;
386 case '*':
387 src = mputc(src, '3');
388 break;
389 default:
390 FATAL_ERROR("Invalid character in bitstring pattern.");
391 }
392 }
393 src = mputstr(src, " }");
394 }
395 src = mputstr(src, ";\n");
396 for (size_t i = 0; i < bp_literals.size(); i++) {
397 if (i > 0) src = mputstr(src, ",\n");
398 else src = mputstr(src, "static const BITSTRING_template ");
399 const char *name = bp_literals.get_nth_elem(i)->c_str();
400 src = mputprintf(src, "%s(%lu, %s_elements)",
401 name, (unsigned long) bp_literals.get_nth_key(i).size(), name);
402 }
403 src = mputstr(src, ";\n");
404 }
405
406 void Module::generate_hs_literals(char *&src, char *&hdr)
407 {
408 if (hs_literals.size() == 0) return;
409 // indicates whether we have found at least one non-empty hexstring
410 bool is_nonempty = false;
411 bool splitting =
412 CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE;
413 for (size_t i = 0; i < hs_literals.size(); i++) {
414 const string& str = hs_literals.get_nth_key(i);
415 size_t nibbles = str.size();
416 if (nibbles == 0) continue;
417 size_t octets = (nibbles + 1) / 2;
418 const char *str_ptr = str.c_str();
419 if (is_nonempty) src = mputstr(src, ",\n");
420 else {
421 src = mputstr(src, "static const unsigned char ");
422 is_nonempty = true;
423 }
424 src = mputprintf(src, "%s_nibbles[] = { ",
425 hs_literals.get_nth_elem(i)->c_str());
426 for (size_t j = 0; j < octets; j++) {
427 // Hex digit with even index always goes to the least significant
428 // 4 bits of the octet.
429 unsigned char value = char_to_hexdigit(str_ptr[2 * j]);
430 if (2 * j + 1 < nibbles) {
431 // Hex digit with odd index always goes to the most significant
432 // 4 bits of the octet.
433 // This digit is not present (bits are set to zero) if the length
434 // of hexstring is odd.
435 value += 16 * char_to_hexdigit(str_ptr[2 * j + 1]);
436 }
437 if (j > 0) src = mputstr(src, ", ");
438 src = mputprintf(src, "%u", value);
439 }
440 src = mputstr(src, " }");
441 }
442 if (is_nonempty) src = mputstr(src, ";\n");
443 for (size_t i = 0; i < hs_literals.size(); i++) {
444 if (i > 0) {
445 src = mputstr(src, ",\n");
446 if (splitting) hdr = mputstr(hdr, ",\n");
447 }
448 else {
449 src = mputprintf(src, "%s const HEXSTRING ",
450 splitting ? "extern" : "static");
451 if (splitting) hdr = mputstr(hdr, "extern const HEXSTRING ");
452 }
453 size_t nibbles = hs_literals.get_nth_key(i).size();
454 const char *object_name = hs_literals.get_nth_elem(i)->c_str();
455 if (nibbles > 0) src = mputprintf(src, "%s(%lu, %s_nibbles)",
456 object_name, (unsigned long) nibbles, object_name);
457 else src = mputprintf(src, "%s(0, NULL)", object_name);
458 if (splitting) hdr = mputstr(hdr, object_name);
459 }
460 src = mputstr(src, ";\n");
461 if (splitting) hdr = mputstr(hdr, ";\n");
462 }
463
464 void Module::generate_hp_literals(char *&src, char *& /*hdr*/)
465 {
466 if (hp_literals.size() == 0) return;
467 for (size_t i = 0; i < hp_literals.size(); i++) {
468 if (i > 0) src = mputstr(src, ",\n");
469 else src = mputstr(src, "static const unsigned char ");
470 src = mputprintf(src, "%s_elements[] = { ",
471 hp_literals.get_nth_elem(i)->c_str());
472 const string& str = hp_literals.get_nth_key(i);
473 size_t size = str.size();
474 const char *str_ptr = str.c_str();
475 for (size_t j = 0; j < size; j++) {
476 if (j > 0) src = mputstr(src, ", ");
477 unsigned char num;
478 if (str_ptr[j] == '?') num = 16;
479 else if (str_ptr[j] == '*') num = 17;
480 else num = char_to_hexdigit(str_ptr[j]);
481 src = mputprintf(src, "%u", num);
482 }
483 src = mputstr(src, " }");
484 }
485 src = mputstr(src, ";\n");
486 for (size_t i = 0; i < hp_literals.size(); i++) {
487 if (i > 0) src = mputstr(src, ",\n");
488 else src = mputstr(src, "static const HEXSTRING_template ");
489 const char *name = hp_literals.get_nth_elem(i)->c_str();
490 src = mputprintf(src, "%s(%lu, %s_elements)",
491 name, (unsigned long) hp_literals.get_nth_key(i).size(), name);
492 }
493 src = mputstr(src, ";\n");
494 }
495
496 void Module::generate_os_literals(char *&src, char *&hdr)
497 {
498 if (os_literals.size() == 0) return;
499 // indicates whether we have found at least one non-empty octetstring
500 bool is_nonempty = false;
501 bool splitting =
502 CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE;
503 for (size_t i = 0; i < os_literals.size(); i++) {
504 const string& str = os_literals.get_nth_key(i);
505 size_t size = str.size();
506 if (size % 2) FATAL_ERROR("Invalid length for an octetstring.");
507 size_t octets = size / 2;
508 if (octets == 0) continue;
509 const char *str_ptr = str.c_str();
510 if (is_nonempty) src = mputstr(src, ",\n");
511 else {
512 src = mputstr(src, "static const unsigned char ");
513 is_nonempty = true;
514 }
515 src = mputprintf(src, "%s_octets[] = { ",
516 os_literals.get_nth_elem(i)->c_str());
517 for (size_t j = 0; j < octets; j++) {
518 if (j > 0) src = mputstr(src, ", ");
519 src = mputprintf(src, "%u", 16 * char_to_hexdigit(str_ptr[2 * j]) +
520 char_to_hexdigit(str_ptr[2 * j + 1]));
521 }
522 src = mputstr(src, " }");
523 }
524 if (is_nonempty) src = mputstr(src, ";\n");
525 for (size_t i = 0; i < os_literals.size(); i++) {
526 if (i > 0) {
527 src = mputstr(src, ",\n");
528 if (splitting) hdr = mputstr(hdr, ",\n");
529 }
530 else {
531 src = mputprintf(src, "%s const OCTETSTRING ",
532 splitting ? "extern" : "static");
533 if (splitting) hdr = mputstr(hdr, "extern const OCTETSTRING ");
534 }
535 size_t octets = os_literals.get_nth_key(i).size() / 2;
536 const char *object_name = os_literals.get_nth_elem(i)->c_str();
537 if (octets > 0) src = mputprintf(src, "%s(%lu, %s_octets)",
538 object_name, (unsigned long) octets, object_name);
539 else src = mputprintf(src, "%s(0, NULL)", object_name);
540 if (splitting) hdr = mputstr(hdr, object_name);
541 }
542 src = mputstr(src, ";\n");
543 if (splitting) hdr = mputstr(hdr, ";\n");
544 }
545
546 void Module::generate_op_literals(char *&src, char *& /*hdr*/)
547 {
548 if (op_literals.size() == 0) return;
549 vector<size_t> pattern_lens;
550 for(size_t i = 0; i < op_literals.size(); i++) {
551 if (i > 0) src = mputstr(src, ",\n");
552 else src = mputstr(src, "static const unsigned short ");
553 src = mputprintf(src, "%s_elements[] = { ",
554 op_literals.get_nth_elem(i)->c_str());
555 const string& str = op_literals.get_nth_key(i);
556 size_t size = str.size();
557 size_t pattern_len = 0;
558 const char *str_ptr = str.c_str();
559 for (size_t j = 0; j < size; j++) {
560 if (j > 0) src = mputstr(src, ", ");
561 unsigned short num;
562 if (str_ptr[j] == '?') num = 256;
563 else if (str_ptr[j] == '*') num = 257;
564 else {
565 // first digit
566 num = 16 * char_to_hexdigit(str_ptr[j]);
567 j++;
568 if (j >= size) FATAL_ERROR("Unexpected end of octetstring pattern.");
569 // second digit
570 num += char_to_hexdigit(str_ptr[j]);
571 }
572 src = mputprintf(src, "%u", num);
573 pattern_len++;
574 }
575 src = mputstr(src, " }");
576 pattern_lens.add(new size_t(pattern_len));
577 }
578 src = mputstr(src, ";\n");
579 for (size_t i = 0; i < op_literals.size(); i++) {
580 if (i > 0) src = mputstr(src, ",\n");
581 else src = mputstr(src, "static const OCTETSTRING_template ");
582 const char *name = op_literals.get_nth_elem(i)->c_str();
583 src = mputprintf(src, "%s(%lu, %s_elements)",
584 name, (unsigned long) *pattern_lens[i], name);
585 }
586 src = mputstr(src, ";\n");
587 for (size_t i = 0; i < pattern_lens.size(); i++) delete pattern_lens[i];
588 pattern_lens.clear();
589 }
590
591 void Module::generate_cs_literals(char *&src, char *&hdr)
592 {
593 if (cs_literals.size() == 0) return;
594 bool splitting =
595 CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE;
596 for (size_t i = 0; i < cs_literals.size(); i++) {
597 const string& str = cs_literals.get_nth_key(i);
598 size_t str_len = str.size();
599 const char *str_ptr = str.c_str();
600 const char *str_name = cs_literals.get_nth_elem(i)->c_str();
601
602 if (i > 0) {
603 src = mputstr(src, ",\n");
604 if (splitting) hdr = mputstr(hdr, ",\n");
605 }
606 else {
607 src = mputprintf(src, "%s const CHARSTRING ",
608 splitting ? "extern" : "static");
609 if (splitting) hdr = mputstr(hdr, "extern const CHARSTRING ");
610 }
611
612 switch (str_len) {
613 case 0:
614 src = mputprintf(src, "%s(0, NULL)", str_name);
615 break;
616 case 1:
617 src = mputprintf(src, "%s('", str_name);
618 src = Code::translate_character(src, *str_ptr, false);
619 src = mputstr(src, "')");
620 break;
621 default:
622 src = mputprintf(src, "%s(%lu, \"", str_name, (unsigned long) str_len);
623 // Note: Code::translate_string() is not suitable because the string
624 // may contain NUL characters at which translate_string() stops
625 // immediately
626 for (size_t j = 0; j < str_len; j++)
627 src = Code::translate_character(src, str_ptr[j], true);
628 src = mputstr(src, "\")");
629 break;
630 } // switch
631 if (splitting) hdr = mputstr(hdr, str_name);
632 }
633 src = mputstr(src, ";\n");
634 if (splitting) hdr = mputstr(hdr, ";\n");
635 }
636
637 void Module::generate_pp_literals(char *&src, char *&) // padding patterns
638 {
639 if (pp_literals.size() == 0) return;
640 for (size_t i = 0; i < pp_literals.size(); i++) {
641 const string& pattern = pp_literals.get_nth_key(i);
642 size_t pattern_len = pattern.size();
643 const char *pattern_ptr = pattern.c_str();
644 if (i > 0) src = mputstr(src, ",\n");
645 else src = mputstr(src, "static const unsigned char ");
646 src = mputprintf(src, "%s[] = { ", pp_literals.get_nth_elem(i)->c_str());
647 if (pattern_len % 8 != 0) FATAL_ERROR("Module::generate_pp_literals()");
648 size_t nof_octets = pattern_len / 8;
649 for (size_t j = 0; j < nof_octets; j++) {
650 if (j > 0) src = mputstr(src, ", ");
651 unsigned char octet = 0;
652 for (size_t k = 0; k < 8; k++) {
653 // take the octets in reverse order
654 // MSB is the first character of the string
655 octet <<= 1;
656 if (pattern_ptr[8 * (nof_octets - j - 1) + k] == '1') octet |= 0x01;
657 }
658 src = mputprintf(src, "0x%02x", octet);
659 }
660 src = mputstr(src, " }");
661 }
662 src = mputstr(src, ";\n");
663 }
664
665 void Module::generate_mp_literals(char *&src, char *&) // matching patt.
666 {
667 if (mp_literals.size() == 0) return;
668 for (size_t i = 0; i < mp_literals.size(); i++) {
669 const string& str = mp_literals.get_nth_key(i);
670 if (str.size() < 1) FATAL_ERROR("Module::generate_mp_literals()");
671 const char *str_ptr = str.c_str();
672
673 if (i > 0) src = mputstr(src, ",\n");
674 else src = mputstr(src, "static const Token_Match ");
675
676 src = mputprintf(src, "%s(\"", mp_literals.get_nth_elem(i)->c_str());
677 src = Code::translate_string(src, str_ptr + 1);
678 // The first character of the string is case-sensitiveness flag:
679 // 'I' for yes, 'N' for no,
680 // 'F' for fixed string matching which is always case sensitive.
681 src = mputprintf(src, "\", %s%s)", (str_ptr[0]!='N') ? "TRUE" : "FALSE",
682 (str_ptr[0] == 'F') ? ", TRUE" : "");
683 }
684 src = mputstr(src, ";\n");
685 }
686
687 void Module::generate_us_literals(char *&src, char *&hdr) // univ.cs
688 {
689 size_t n_literals = us_literals.size();
690 if (n_literals == 0) return;
691 bool array_needed = false;
692 bool splitting =
693 CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE;
694 for (size_t i = 0; i < n_literals; i++) {
695 const ustring& value = us_literals.get_nth_key(i);
696 size_t value_size = value.size();
697 if (value_size < 2) continue;
698 if (array_needed) src = mputstr(src, ",\n");
699 else {
700 src = mputstr(src, "static const universal_char ");
701 array_needed = true;
702 }
703 src = mputprintf(src, "%s_uchars[] = { ",
704 us_literals.get_nth_elem(i)->c_str());
705 const ustring::universal_char *uchars_ptr = value.u_str();
706 for (size_t j = 0; j < value_size; j++) {
707 if (j > 0) src = mputstr(src, ", ");
708 src = mputprintf(src, "{ %u, %u, %u, %u }", uchars_ptr[j].group,
709 uchars_ptr[j].plane, uchars_ptr[j].row, uchars_ptr[j].cell);
710 }
711 src = mputstr(src, " }");
712 }
713 if (array_needed) src = mputstr(src, ";\n");
714 for (size_t i = 0; i < n_literals; i++) {
715 if (i > 0) {
716 src = mputstr(src, ",\n");
717 if (splitting) hdr = mputstr(hdr, ",\n");
718 }
719 else {
720 src = mputprintf(src, "%s const UNIVERSAL_CHARSTRING ",
721 splitting ? "extern" : "static");
722 if (splitting) hdr = mputstr(hdr, "extern const UNIVERSAL_CHARSTRING ");
723 }
724 const char *value_name = us_literals.get_nth_elem(i)->c_str();
725 const ustring& value = us_literals.get_nth_key(i);
726 size_t value_size = value.size();
727 switch (value_size) {
728 case 0:
729 src = mputprintf(src, "%s(0, (const universal_char*)NULL)", value_name);
730 break;
731 case 1: {
732 const ustring::universal_char& uchar = value.u_str()[0];
733 src = mputprintf(src, "%s(%u, %u, %u, %u)", value_name,
734 uchar.group, uchar.plane, uchar.row, uchar.cell);
735 break; }
736 default:
737 src = mputprintf(src, "%s(%lu, %s_uchars)", value_name,
738 (unsigned long) value_size, value_name);
739 break;
740 }
741 if (splitting) hdr = mputstr(hdr, value_name);
742 }
743 src = mputstr(src, ";\n");
744 if (splitting) hdr = mputstr(hdr, ";\n");
745 }
746
747 void Module::generate_oid_literals(char *&src, char *& /*hdr*/)
748 {
749 if (oid_literals.size() == 0) return;
750 for (size_t i = 0; i < oid_literals.size(); i++) {
751 if (i > 0) src = mputstr(src, ",\n");
752 else src = mputstr(src, "static const OBJID::objid_element ");
753
754 src = mputprintf(src, "%s_comps[] = { %s }",
755 oid_literals.get_nth_elem(i)->oid_id.c_str(),
756 oid_literals.get_nth_key(i).c_str());
757 }
758 src = mputstr(src, ";\n");
759 for(size_t i = 0; i < oid_literals.size(); i++) {
760 const OID_literal *litstruct = oid_literals.get_nth_elem(i);
761
762 if (i > 0) src = mputstr(src, ",\n");
763 else src = mputstr(src, "static const OBJID ");
764
765 src = mputprintf(src, "%s(%lu, %s_comps)",
766 litstruct->oid_id.c_str(), (unsigned long) litstruct->nof_elems,
767 litstruct->oid_id.c_str());
768 }
769 src = mputstr(src, ";\n");
770 }
771
772 void Module::generate_functions(output_struct *output)
773 {
774 bool tcov_enabled = tcov_file_name && in_tcov_files(get_filename());
775 bool has_pre_init_before_tcov = output->functions.pre_init != NULL;
776 if (tcov_enabled) {
777 output->functions.pre_init = mputprintf(output->functions.pre_init,
778 "TTCN_Location_Statistics::init_file_lines(\"%s\", effective_module_lines, sizeof(effective_module_lines) / sizeof(int));\n" \
779 "TTCN_Location_Statistics::init_file_functions(\"%s\", effective_module_functions, sizeof(effective_module_functions) / sizeof(char *));\n",
780 get_tcov_file_name(get_filename()), get_tcov_file_name(get_filename()));
781 }
782 // pre_init function
783 bool has_pre_init = false;
784 if (output->functions.pre_init) {
785 output->source.static_function_prototypes =
786 mputstr(output->source.static_function_prototypes,
787 "static void pre_init_module();\n");
788 output->source.static_function_bodies = mputstr(output->source.static_function_bodies,
789 "static void pre_init_module()\n"
790 "{\n");
791 if (include_location_info) {
792 output->source.static_function_bodies =
793 mputstr(output->source.static_function_bodies,
794 (tcov_enabled && has_pre_init_before_tcov) ? "TTCN_Location_Statistics current_location(\""
795 : "TTCN_Location current_location(\"");
796 output->source.static_function_bodies =
797 Code::translate_string(output->source.static_function_bodies, (tcov_enabled && has_pre_init_before_tcov) ? get_tcov_file_name(get_filename()) : get_filename());
798 output->source.static_function_bodies =
799 mputprintf(output->source.static_function_bodies,
800 (tcov_enabled && has_pre_init_before_tcov) ? "\", 0, TTCN_Location_Statistics::LOCATION_UNKNOWN, \"%s\");\n"
801 : "\", 0, TTCN_Location::LOCATION_UNKNOWN, \"%s\");\n", get_modid().get_dispname().c_str());
802 if (tcov_enabled && has_pre_init_before_tcov) {
803 effective_module_lines =
804 mputprintf(effective_module_lines, "%s0",
805 (effective_module_lines ? ", " : ""));
806 effective_module_functions =
807 mputprintf(effective_module_functions, "%s\"%s\"",
808 (effective_module_functions ? ", " : ""), get_modid().get_dispname().c_str());
809 }
810 }
811 output->source.static_function_bodies =
812 mputstr(output->source.static_function_bodies, output->functions.pre_init);
813 output->source.static_function_bodies =
814 mputstr(output->source.static_function_bodies, "}\n\n");
815 Free(output->functions.pre_init);
816 output->functions.pre_init = NULL;
817 has_pre_init = true;
818 }
819 bool has_post_init_before_tcov = output->functions.post_init != NULL;
820 // post_init function
821 bool has_post_init = false;
822 if (output->functions.post_init) {
823 output->source.static_function_prototypes = mputstr(output->source.static_function_prototypes,
824 "static void post_init_module();\n");
825 output->source.static_function_bodies = mputstr(output->source.static_function_bodies,
826 "static void post_init_module()\n"
827 "{\n");
828 if (include_location_info) {
829 output->source.static_function_bodies =
830 mputstr(output->source.static_function_bodies,
831 (tcov_enabled && has_post_init_before_tcov) ? "TTCN_Location_Statistics current_location(\""
832 : "TTCN_Location current_location(\"");
833 output->source.static_function_bodies =
834 Code::translate_string(output->source.static_function_bodies, (tcov_enabled && has_post_init_before_tcov) ? get_tcov_file_name(get_filename()) : get_filename());
835 output->source.static_function_bodies =
836 mputprintf(output->source.static_function_bodies,
837 (tcov_enabled && has_post_init_before_tcov) ? "\", 0, TTCN_Location_Statistics::LOCATION_UNKNOWN, \"%s\");\n"
838 : "\", 0, TTCN_Location::LOCATION_UNKNOWN, \"%s\");\n", get_modid().get_dispname().c_str());
839 if (tcov_enabled && has_post_init_before_tcov) {
840 effective_module_lines =
841 mputprintf(effective_module_lines, "%s0",
842 (effective_module_lines ? ", " : ""));
843 effective_module_functions =
844 mputprintf(effective_module_functions, "%s\"%s\"",
845 (effective_module_functions ? ", " : ""), get_modid().get_dispname().c_str());
846 }
847 }
848 output->source.static_function_bodies =
849 mputstr(output->source.static_function_bodies, output->functions.post_init);
850 output->source.static_function_bodies =
851 mputstr(output->source.static_function_bodies, "}\n\n");
852 Free(output->functions.post_init);
853 output->functions.post_init = NULL;
854 has_post_init = true;
855 }
856 // set_param function
857 bool has_set_param;
858 if (output->functions.set_param) {
859 output->source.static_function_prototypes = mputstr(output->source.static_function_prototypes,
860 "static boolean set_module_param(Module_Param& param);\n");
861 output->source.static_function_bodies = mputstr(output->source.static_function_bodies,
862 "static boolean set_module_param(Module_Param& param)\n"
863 "{\n"
864 "const char* const par_name = param.get_id()->get_current_name();\n");
865 output->source.static_function_bodies =
866 mputstr(output->source.static_function_bodies, output->functions.set_param);
867 output->source.static_function_bodies =
868 mputstr(output->source.static_function_bodies, "return FALSE;\n"
869 "}\n\n");
870 Free(output->functions.set_param);
871 output->functions.set_param = NULL;
872 has_set_param = true;
873 } else has_set_param = false;
874 // log_param function
875 bool has_log_param;
876 if (output->functions.log_param) {
877 output->source.static_function_prototypes = mputstr(output->source.static_function_prototypes,
878 "static void log_module_param();\n");
879 output->source.static_function_bodies = mputstr(output->source.static_function_bodies,
880 "static void log_module_param()\n"
881 "{\n");
882 output->source.static_function_bodies =
883 mputstr(output->source.static_function_bodies, output->functions.log_param);
884 output->source.static_function_bodies = mputstr(output->source.static_function_bodies,
885 "}\n\n");
886 Free(output->functions.log_param);
887 output->functions.log_param = NULL;
888 has_log_param = true;
889 } else has_log_param = false;
890 // init_comp function
891 bool has_init_comp;
892 if (output->functions.init_comp) {
893 output->source.static_function_prototypes =
894 mputstr(output->source.static_function_prototypes,
895 "static boolean init_comp_type("
896 "const char *component_type, boolean init_base_comps);\n");
897 output->source.static_function_bodies =
898 mputstr(output->source.static_function_bodies,
899 "static boolean init_comp_type(const char *component_type, "
900 "boolean init_base_comps)\n"
901 "{\n(void)init_base_comps;\n");
902 output->source.static_function_bodies =
903 mputstr(output->source.static_function_bodies,
904 output->functions.init_comp);
905 output->source.static_function_bodies =
906 mputstr(output->source.static_function_bodies, "return FALSE;\n"
907 "}\n\n");
908 Free(output->functions.init_comp);
909 output->functions.init_comp = NULL;
910 has_init_comp = true;
911 } else has_init_comp = false;
912 // start function
913 bool has_start;
914 if (output->functions.start) {
915 output->source.static_function_prototypes = mputstr(output->source.static_function_prototypes,
916 "static boolean start_ptc_function(const char *function_name, "
917 "Text_Buf& function_arguments);\n");
918 output->source.static_function_bodies = mputstr(output->source.static_function_bodies,
919 "static boolean start_ptc_function(const char *function_name, "
920 "Text_Buf& function_arguments)\n"
921 "{\n");
922 output->source.static_function_bodies =
923 mputstr(output->source.static_function_bodies, output->functions.start);
924 output->source.static_function_bodies =
925 mputstr(output->source.static_function_bodies, "return FALSE;\n"
926 "}\n\n");
927 Free(output->functions.start);
928 output->functions.start = NULL;
929 has_start = true;
930 } else has_start = false;
931 // control part
932 bool has_control;
933 if (output->functions.control) {
934 output->source.static_function_prototypes = mputstr(output->source.static_function_prototypes,
935 "static void module_control_part();\n");
936 output->source.static_function_bodies = mputstr(output->source.static_function_bodies,
937 "static void module_control_part()\n"
938 "{\n");
939 output->source.static_function_bodies =
940 mputstr(output->source.static_function_bodies, output->functions.control);
941 output->source.static_function_bodies =
942 mputstr(output->source.static_function_bodies, "}\n\n");
943 Free(output->functions.control);
944 output->functions.control = NULL;
945 has_control = true;
946 } else has_control = false;
947 // module checksum
948 if (has_checksum) {
949 output->source.string_literals = mputstr(output->source.string_literals,
950 "static const unsigned char module_checksum[] = {");
951 for (size_t i = 0; i < sizeof(module_checksum); i++) {
952 if (i > 0) output->source.string_literals =
953 mputc(output->source.string_literals, ',');
954 output->source.string_literals =
955 mputprintf(output->source.string_literals, " 0x%02x",
956 module_checksum[i]);
957 }
958 output->source.string_literals = mputstr(output->source.string_literals,
959 " };\n");
960 }
961 const char *module_name = modid->get_name().c_str();
962
963 // XML namespaces. Written in the order they are stored:
964 // sorted ASCIIbetically by the prefix.
965 // Not all namespaces are used by every module. Unfortunately, the array
966 // (which has the same size in all modules) cannot be compacted, because
967 // the indexes have already been used when the XER descriptors were written.
968 // All we can do is store NULLs for the unused namespaces.
969 size_t num_xml_namespaces = namespaces.size();
970 if (moduletype == MOD_TTCN) { //TODO remove this when ASN.1 gets EXER
971 output->source.global_vars = mputprintf(output->source.global_vars,
972 #ifndef NDEBUG
973 "// written by %s in " __FILE__ " at %d\n"
974 #endif
975 "static const size_t num_namespaces = %lu;\n"
976 #ifndef NDEBUG
977 , __FUNCTION__, __LINE__
978 #endif
979 , (unsigned long)num_xml_namespaces
980 );
981 if (num_xml_namespaces != 0 || (control_ns && control_ns_prefix)) {
982 output->source.global_vars = mputstr(output->source.global_vars,
983 "static const namespace_t xml_namespaces[num_namespaces+1] = {\n");
984 for (size_t i=0; i < namespaces.size(); ++i) {
985 if (used_namespaces.has_key(i)) {
986 output->source.global_vars = mputprintf(output->source.global_vars,
987 " { \"%s\", \"%s\" },\n", // ns, then prefix
988 namespaces.get_nth_elem(i), namespaces.get_nth_key(i).c_str());
989 }
990 else {
991 output->source.global_vars = mputstr(output->source.global_vars,
992 " { NULL, NULL },\n"); // not used in this module
993 }
994 } // next namespace
995 output->source.global_vars = mputprintf(output->source.global_vars,
996 " { \"%s\", \"%s\" }\n};\n\n",
997 (control_ns ? control_ns : ""),
998 (control_ns_prefix ? control_ns_prefix : ""));
999 } // if there are namespaces
1000 } // if TTCN
1001
1002
1003 // module object
1004 output->header.global_vars = mputprintf(output->header.global_vars,
1005 "extern TTCN_Module %s;\n",
1006 "module_object");
1007
1008 output->source.global_vars = mputprintf(output->source.global_vars,
1009 "TTCN_Module %s(\"%s\", __DATE__, __TIME__, %s, %s",
1010 "module_object",
1011
1012 modid->get_dispname().c_str(),
1013 (has_checksum ? "module_checksum" : "NULL"),
1014 has_pre_init ? "pre_init_module" : "NULL");
1015
1016 if (moduletype == MOD_TTCN) {
1017 // TTCN-3 specific function pointers
1018 if (product_number == NULL) {
1019 output->source.global_vars = mputstr(output->source.global_vars, ", NULL");
1020 } else {
1021 output->source.global_vars = mputprintf(output->source.global_vars, ", \"%s\"", product_number);
1022 }
1023 string extra_str = extra ? ( string('"') + extra + string('"') ) : string("NULL");
1024 output->source.global_vars = mputprintf(output->source.global_vars,
1025 ", %uU, %uU, %uU, %uU, %s, %luLU, %s, %s, %s, %s, %s, %s, %s",
1026 suffix, release, patch, build, extra_str.c_str(),
1027 (unsigned long)num_xml_namespaces,
1028 ((num_xml_namespaces || (control_ns && control_ns_prefix)) ? "xml_namespaces" : "0"),
1029 has_post_init ? "post_init_module" : "NULL",
1030 has_set_param ? "set_module_param" : "NULL",
1031 has_log_param ? "log_module_param" : "NULL",
1032 has_init_comp ? "init_comp_type" : "NULL",
1033 has_start ? "start_ptc_function" : "NULL",
1034 has_control ? "module_control_part" : "NULL");
1035 } else {
1036 // self checks for ASN.1 modules
1037 if (has_post_init)
1038 FATAL_ERROR("Module::generate_functions(): post_init function in ASN.1 module");
1039 if (has_set_param)
1040 FATAL_ERROR("Module::generate_functions(): set_param function in ASN.1 module");
1041 if (has_log_param)
1042 FATAL_ERROR("Module::generate_functions(): log_param function in ASN.1 module");
1043 if (has_init_comp)
1044 FATAL_ERROR("Module::generate_functions(): init_comp function in ASN.1 module");
1045 if (has_start)
1046 FATAL_ERROR("Module::generate_functions(): startable function in ASN.1 module");
1047 if (has_control)
1048 FATAL_ERROR("Module::generate_functions(): control part in ASN.1 module");
1049 }
1050 output->source.global_vars = mputstr(output->source.global_vars, ");\n");
1051 // #include into the source file
1052 output->source.includes = mputprintf(output->source.includes,
1053 "#include \"%s.hh\"\n",
1054 duplicate_underscores ? module_name : modid->get_ttcnname().c_str());
1055
1056 output->source.global_vars = mputprintf(output->source.global_vars,
1057 "\nstatic const RuntimeVersionChecker ver_checker("
1058 " current_runtime_version.requires_major_version_%d,\n"
1059 " current_runtime_version.requires_minor_version_%d,\n"
1060 " current_runtime_version.requires_patch_level_%d,"
1061 " current_runtime_version.requires_runtime_%d);\n",
1062 TTCN3_MAJOR, TTCN3_MINOR, TTCN3_PATCHLEVEL, use_runtime_2 ? 2 : 1
1063 );
1064 if (tcov_enabled) {
1065 output->source.global_vars = mputprintf(output->source.global_vars,
1066 "\nstatic const int effective_module_lines[] = { %s };\n" \
1067 "static const char *effective_module_functions[] = { %s };\n",
1068 effective_module_lines ? static_cast<const char *>(effective_module_lines) : "",
1069 effective_module_functions ? static_cast<const char *>(effective_module_functions) : "");
1070 }
1071 }
1072
1073 void Module::generate_conversion_functions(output_struct *output)
1074 {
1075 for (size_t i = 0; i < type_conv_v.size(); i++)
1076 type_conv_v[i]
1077 ->gen_conv_func(&output->source.static_conversion_function_prototypes,
1078 &output->source.static_conversion_function_bodies,
1079 this);
1080 }
1081
1082 string Module::add_literal(map<string, string>& literals, const string& str,
1083 const char *prefix)
1084 {
1085 if (literals.has_key(str)) return *literals[str];
1086 else {
1087 string *literal = new string(prefix+Int2string(literals.size()));
1088 literals.add(str, literal);
1089 return *literal;
1090 }
1091 }
1092
1093 void Module::clear_literals(map<string, string>& literals)
1094 {
1095 for (size_t i = 0; i < literals.size(); i++)
1096 delete literals.get_nth_elem(i);
1097 literals.clear();
1098 }
1099
1100 map<string, const char> Module::namespaces;
1101 map<string, const char> Module::invented_prefixes;
1102 size_t Module::default_namespace_attempt = 0;
1103 size_t Module::replacement_for_empty_prefix = (size_t)-1;
1104
1105 Module::Module(moduletype_t p_mt, Identifier *p_modid)
1106 : Scope(), moduletype(p_mt), modid(p_modid),
1107 imp_checked(false), gen_code(false), has_checksum(false),
1108 visible_mods(), module_checksum(),
1109 bs_literals(), bp_literals(), hs_literals(), hp_literals(), os_literals(),
1110 op_literals(), cs_literals(), us_literals(), pp_literals(), mp_literals(),
1111 oid_literals(), tmp_id_count(0),
1112 control_ns(p_mt == MOD_ASN ? mcopystr("urn:oid:2.1.5.2.0.1") : NULL),
1113 control_ns_prefix(p_mt == MOD_ASN ? mcopystr("asn1") : NULL),
1114 // only ASN.1 modules have default control namespace (X.693 amd1, 16.9)
1115 used_namespaces(), type_conv_v(), product_number(NULL),
1116 suffix(0), release(UINT_MAX), patch(UINT_MAX), build(UINT_MAX), extra(NULL)
1117 {
1118 if(!p_modid)
1119 FATAL_ERROR("NULL parameter: Common::Module::Module()");
1120 memset(module_checksum, 0, sizeof(module_checksum));
1121 set_scopeMacro_name(modid->get_dispname());
1122 }
1123
1124 Module::~Module()
1125 {
1126 delete modid;
1127 visible_mods.clear();
1128 clear_literals(bs_literals);
1129 clear_literals(bp_literals);
1130 clear_literals(hs_literals);
1131 clear_literals(hp_literals);
1132 clear_literals(os_literals);
1133 clear_literals(op_literals);
1134 clear_literals(cs_literals);
1135 clear_literals(pp_literals);
1136 clear_literals(mp_literals);
1137 for (size_t i = 0; i < us_literals.size(); i++)
1138 delete us_literals.get_nth_elem(i);
1139 us_literals.clear();
1140 for (size_t i = 0; i < oid_literals.size(); i++)
1141 delete oid_literals.get_nth_elem(i);
1142 oid_literals.clear();
1143 for (size_t i = 0; i < type_conv_v.size(); i++)
1144 delete type_conv_v[i];
1145 type_conv_v.clear();
1146 Free(control_ns);
1147 Free(control_ns_prefix);
1148 used_namespaces.clear(); // all the values are NULL, no need to free
1149 // static members below; repeated clear()s are redundant but harmless
1150 namespaces.clear();
1151 invented_prefixes.clear();
1152 Free(product_number);
1153 Free(extra);
1154 }
1155
1156 Type *Module::get_address_type()
1157 {
1158 FATAL_ERROR("Common::Module::get_address_type()");
1159 return 0;
1160 }
1161
1162 string Module::add_ustring_literal(const ustring& ustr)
1163 {
1164 if (us_literals.has_key(ustr)) return *us_literals[ustr];
1165 else {
1166 string *literal = new string("us_" + Int2string(us_literals.size()));
1167 us_literals.add(ustr, literal);
1168 return *literal;
1169 }
1170 }
1171
1172 string Module::add_objid_literal(const string& oi_str, const size_t nof_elems)
1173 {
1174 if(oid_literals.has_key(oi_str)) return oid_literals[oi_str]->oid_id;
1175 else {
1176 OID_literal *oi_struct = new OID_literal;
1177 oi_struct->nof_elems = nof_elems;
1178 oi_struct->oid_id = "oi_" + Int2string(oid_literals.size());
1179 oid_literals.add(oi_str, oi_struct);
1180 return oi_struct->oid_id;
1181 }
1182 }
1183
1184 void Module::add_type_conv(TypeConv *p_conv)
1185 {
1186 if (p_conv == NULL) FATAL_ERROR("Module::add_type_conv()");
1187 Type *p_from_type = p_conv->get_from_type();
1188 Type *p_to_type = p_conv->get_to_type();
1189 if (!p_from_type->is_structured_type()
1190 || !p_to_type->is_structured_type())
1191 FATAL_ERROR("Module::add_type_conv()");
1192 if (p_from_type == p_to_type) {
1193 // Never add the same types.
1194 delete p_conv;
1195 return;
1196 }
1197 for (size_t i = 0; i < type_conv_v.size(); i++) {
1198 TypeConv *conv = type_conv_v[i];
1199 if (conv->get_from_type() == p_from_type
1200 && conv->get_to_type() == p_to_type
1201 && conv->is_temp() == p_conv->is_temp()) {
1202 // Same pair of types, both for values or templates. We're the
1203 // owners, deallocate.
1204 delete p_conv;
1205 return;
1206 }
1207 }
1208 type_conv_v.add(p_conv);
1209 }
1210
1211 bool Module::needs_type_conv(Type *p_from_type, Type *p_to_type) const
1212 {
1213 for (size_t i = 0; i < type_conv_v.size(); i++) {
1214 TypeConv *conv = type_conv_v[i];
1215 if (conv->get_from_type() == p_from_type
1216 && conv->get_to_type() == p_to_type)
1217 return true;
1218 }
1219 return false;
1220 }
1221
1222 void Module::chk_recursive(module_set_t& checked_modules)
1223 {
1224 if (checked_modules.has_key(this)) return;
1225 // this must be added to the set at the beginning
1226 // in order to deal with circular imports
1227 checked_modules.add(this, 0);
1228 // check the imported modules first
1229 size_t nof_visible_mods = visible_mods.size();
1230 for (size_t i = 0; i < nof_visible_mods; i++) {
1231 Module *m = visible_mods.get_nth_key(i);
1232 if (m != this) m->chk_recursive(checked_modules);
1233 }
1234 // then check the module itself
1235 chk(); // this is the only virtual call
1236 }
1237
1238 bool Module::is_visible(Module *m)
1239 {
1240 collect_visible_mods();
1241 return visible_mods.has_key(m);
1242 }
1243
1244 void Module::get_visible_mods(module_set_t& p_visible_mods)
1245 {
1246 if (visible_mods.has_key(this)) {
1247 size_t nof_visible_mods = visible_mods.size();
1248 for (size_t i = 0; i < nof_visible_mods; i++) {
1249 Module *m = visible_mods.get_nth_key(i);
1250 if (!p_visible_mods.has_key(m)) p_visible_mods.add(m, 0);
1251 }
1252 } else {
1253 get_imported_mods(p_visible_mods);
1254 }
1255 }
1256
1257 void Module::write_checksum()
1258 {
1259 fprintf(stderr, "%-18s ", modid->get_dispname().c_str());
1260 switch (moduletype) {
1261 case MOD_TTCN: fprintf(stderr, "%-15s ", "TTCN-3"); break;
1262 case MOD_ASN: fprintf(stderr, "%-15s ", "ASN.1"); break;
1263 case MOD_UNKNOWN: fprintf(stderr, "%-15s ", "OTHER"); break;
1264 }
1265
1266 if (!has_checksum) {
1267 fputc('\n', stderr);
1268 return;
1269 }
1270
1271 size_t nof_checksum = sizeof(module_checksum);
1272 for (size_t i = 0; i < nof_checksum; i++) {
1273 fprintf(stderr, "%02x", module_checksum[i]);
1274 }
1275
1276 if (release <= 999999 && patch < 30 && build < 100) {
1277 char *product_identifier =
1278 get_product_identifier(product_number, suffix, release, patch, build, extra);
1279 fprintf(stderr, " %s", product_identifier);
1280 Free(product_identifier);
1281 }
1282
1283 fputc('\n', stderr);
1284 }
1285
1286 char* Module::get_product_identifier(const char* product_number,
1287 const unsigned int suffix, unsigned int release, unsigned int patch,
1288 unsigned int build, const char* extra)
1289 {
1290 expstring_t ret_val = memptystr();
1291 if ( product_number == NULL
1292 && suffix == UINT_MAX
1293 && release == UINT_MAX
1294 && patch == UINT_MAX
1295 && build == UINT_MAX) {
1296 ret_val = mputstr(ret_val, "<RnXnn>");
1297 return ret_val;
1298 }
1299 if (product_number != NULL) {
1300 ret_val = mputstr(ret_val, product_number);
1301 if (suffix != 0) {
1302 ret_val = mputprintf(ret_val, "/%d", suffix);
1303 }
1304 ret_val = mputc(ret_val, ' ');
1305 }
1306
1307 char* build_str = buildstr(build);
1308 ret_val = mputprintf(ret_val, "R%u%c%s%s", release, eri(patch), build_str, extra ? extra : "");
1309 Free(build_str);
1310 return ret_val;
1311 }
1312
1313 void Module::collect_visible_mods()
1314 {
1315 if (!visible_mods.has_key(this)) {
1316 get_imported_mods(visible_mods);
1317 if (!visible_mods.has_key(this)) visible_mods.add(this, 0);
1318 }
1319 }
1320
1321 void Module::set_checksum(size_t checksum_len,
1322 const unsigned char* checksum_ptr)
1323 {
1324 if (checksum_len != sizeof(module_checksum))
1325 FATAL_ERROR("Module::set_checksum(): invalid length");
1326 memcpy(module_checksum, checksum_ptr, sizeof(module_checksum));
1327 has_checksum = true;
1328 }
1329
1330 void Module::set_controlns(char *ns, char *prefix)
1331 {
1332 Free(control_ns);
1333 control_ns = ns;
1334 Free(control_ns_prefix);
1335 control_ns_prefix = prefix;
1336 }
1337
1338 void Module::get_controlns(const char *&ns, const char *&prefix)
1339 {
1340 ns = control_ns;
1341 prefix = control_ns_prefix;
1342 }
1343
1344 const size_t max_invented_prefixes = 10000;
1345 void Module::add_namespace(const char *new_uri, char *&new_prefix)
1346 {
1347 const bool prefix_is_empty = new_prefix && !*new_prefix;
1348 const string key(new_prefix ? new_prefix : "");
1349 if (new_prefix && !namespaces.has_key(key)) {
1350 namespaces.add(key, new_uri);
1351 if (*new_prefix == 0) { // first add of default namespace
1352 ++default_namespace_attempt;
1353 }
1354 return; // newly added
1355 }
1356 else { // prefix already present (or we are required to invent one)
1357 if (new_prefix) {
1358 const char *uri_value = namespaces[key];
1359 if (!strcmp(uri_value, new_uri)) return; // same URI, same prefix: no-op
1360 }
1361
1362 // prefix already present but different URI,
1363 // or prefix is NULL (which means we must invent a prefix)
1364
1365 if (new_prefix && *new_prefix) {
1366 Free(new_prefix); // prefix is not empty, discard it and start fresh
1367 new_prefix = memptystr();
1368 }
1369
1370 const string uri_key(new_uri);
1371 if (invented_prefixes.has_key(uri_key)) {
1372 // we already made one up for this URI
1373 new_prefix = mputstr(new_prefix, invented_prefixes[uri_key]);
1374 return; // already there
1375 }
1376 else {
1377 // make one up on the spot
1378 size_t iidx = invented_prefixes.size(); // "invented index"
1379 new_prefix = mputprintf(new_prefix, "tq%04lu", (unsigned long)iidx++);
1380 string made_up_prefix(new_prefix);
1381 for (; iidx < max_invented_prefixes; ++iidx) {
1382 if (namespaces.has_key(made_up_prefix)) {
1383 // Some pervert wrote an XSD with a namespace prefix like tq0007!
1384 // Make up another one in the same memory spot.
1385 sprintf(new_prefix, "tq%04lu", (unsigned long)iidx);
1386 made_up_prefix = new_prefix;
1387 }
1388 else break;
1389 }
1390
1391 if (iidx >= max_invented_prefixes) {
1392 Location loc; // no particular location
1393 loc.error("Internal limit: too many assigned prefixes");
1394 return; // not added
1395 }
1396 invented_prefixes.add(uri_key, new_prefix);
1397 namespaces.add(made_up_prefix, new_uri);
1398
1399 // Search for the newly added prefix and remember it.
1400 replacement_for_empty_prefix = namespaces.find_key(made_up_prefix);
1401
1402 if (prefix_is_empty) {
1403 ++default_namespace_attempt;
1404 }
1405 return; // newly added
1406 }
1407 } // if (present)
1408 }
1409
1410 static const string empty_prefix;
1411 void Module::rename_default_namespace()
1412 {
1413 if (default_namespace_attempt < 2) return;
1414 // There was more than one default namespace. However, all but the first
1415 // are already renamed to tq%d.
1416 size_t di = namespaces.find_key(empty_prefix); // keys are prefixes
1417 if (di < namespaces.size()) { // found it
1418 const char *last_remaining_def_namespace = namespaces.get_nth_elem(di);
1419 // we can't change a key, we can only remove and re-add it
1420 namespaces.erase(empty_prefix);
1421
1422 expstring_t empty_prefix_string = NULL; // force a made-up prefix
1423 add_namespace(last_remaining_def_namespace, empty_prefix_string);
1424 Free(empty_prefix_string);
1425 }
1426 else FATAL_ERROR("Module::rename_default_namespace");
1427 }
1428
1429 size_t Module::get_ns_index(const char *prefix)
1430 {
1431 size_t idx = namespaces.find_key(string(prefix));
1432 if (idx >= namespaces.size()) { // not found
1433 // If the the caller asked for the empty prefix and it wasn't found
1434 // because it has been replaced, use the replacement.
1435 if (*prefix == '\0' && replacement_for_empty_prefix != (size_t)-1) {
1436 idx = replacement_for_empty_prefix;
1437 }
1438 else FATAL_ERROR("Module::get_ns_index()");
1439 }
1440
1441 // Remember that the index is used by this module
1442 if (!used_namespaces.has_key(idx)) {
1443 used_namespaces.add(idx, NULL);
1444 }
1445 return idx;
1446 }
1447
1448 string Module::get_temporary_id()
1449 {
1450 static const string tmp_prefix("tmp_");
1451 return tmp_prefix + Int2string(tmp_id_count++);
1452 }
1453
1454 void Module::generate_code(CodeGenHelper& cgh)
1455 {
1456 if (!gen_code) {
1457 nof_notupdated_files += 2;
1458 DEBUG(1, "Code not generated for module `%s'.",
1459 modid->get_dispname().c_str());
1460 return;
1461 }
1462 DEBUG(1, "Generating code for module `%s'.",
1463 modid->get_dispname().c_str());
1464
1465 // TODO: Always assume to have circular imports until
1466 // full program optimization is available,
1467 // this increases the size of the generated code,
1468 // but otherwise it is possible to create uncompilable code:
1469 // 1) let the project of module A and B refer to each other,
1470 // 2) A refers B, and compile A
1471 // 3) edit B to refer to A and compile it ...
1472 // As the code for A can not be rewritten the code will not compile
1473 cgh.add_module(modid->get_name(), modid->get_ttcnname(),
1474 moduletype == MOD_TTCN, true);
1475 cgh.set_current_module(modid->get_ttcnname());
1476
1477 // language specific parts (definitions, imports, etc.)
1478 //generate_code_internal(&target); <- needed to pass cgh
1479 generate_code_internal(cgh);
1480
1481 // string literals
1482 generate_literals(cgh.get_current_outputstruct());
1483 // module level entry points
1484 generate_functions(cgh.get_current_outputstruct());
1485 // type conversion functions for type compatibility
1486 generate_conversion_functions(cgh.get_current_outputstruct());
1487 }
1488
1489 void Module::dump(unsigned level) const
1490 {
1491 DEBUG(level, "Module: %s", get_modid().get_dispname().c_str());
1492 }
1493
1494 // =================================
1495 // ===== Assignments
1496 // =================================
1497
1498 Assignments *Assignments::get_scope_asss()
1499 {
1500 return this;
1501 }
1502
1503 Assignment *Assignments::get_ass_bySRef(Ref_simple *p_ref)
1504 {
1505 if (!p_ref || !parent_scope)
1506 FATAL_ERROR("NULL parameter: Common::Assignments::get_ass_bySRef()");
1507 if (!p_ref->get_modid()) {
1508 const Identifier *id = p_ref->get_id();
1509 if (id && has_local_ass_withId(*id)) return get_local_ass_byId(*id);
1510 }
1511 return parent_scope->get_ass_bySRef(p_ref);
1512 }
1513
1514 bool Assignments::has_ass_withId(const Identifier& p_id)
1515 {
1516 if (has_local_ass_withId(p_id)) return true;
1517 else if (parent_scope) return parent_scope->has_ass_withId(p_id);
1518 else return false;
1519 }
1520
1521 // =================================
1522 // ===== Assignment
1523 // =================================
1524
1525 Assignment::Assignment(asstype_t p_asstype, Identifier *p_id)
1526 : asstype(p_asstype), id(p_id), my_scope(0), checked(false),
1527 visibilitytype(PUBLIC)
1528 {
1529 if (!id) FATAL_ERROR("Assignment::Assignment(): NULL parameter");
1530 }
1531
1532 Assignment::Assignment(const Assignment& p)
1533 : Node(p), Location(p), asstype(p.asstype), id(p.id->clone()), my_scope(0),
1534 checked(false), visibilitytype(p.visibilitytype)
1535 {
1536
1537 }
1538
1539 Assignment::~Assignment()
1540 {
1541 delete id;
1542 }
1543
1544 Assignment::asstype_t Assignment::get_asstype() const
1545 {
1546 return asstype;
1547 }
1548
1549 const char *Assignment::get_assname() const
1550 {
1551 switch (get_asstype()) {
1552 case A_TYPE:
1553 return "type";
1554 case A_CONST:
1555 if (my_scope && my_scope->get_scope_mod()->get_moduletype() ==
1556 Module::MOD_ASN) return "value";
1557 else return "constant";
1558 case A_ERROR:
1559 return "erroneous assignment";
1560 case A_OC:
1561 return "information object class";
1562 case A_OBJECT:
1563 return "information object";
1564 case A_OS:
1565 return "information object set";
1566 case A_VS:
1567 return "value set";
1568 case A_EXT_CONST:
1569 return "external constant";
1570 case A_MODULEPAR:
1571 return "module parameter";
1572 case A_MODULEPAR_TEMP:
1573 return "template module parameter";
1574 case A_TEMPLATE:
1575 return "template";
1576 case A_VAR:
1577 return "variable";
1578 case A_VAR_TEMPLATE:
1579 return "template variable";
1580 case A_TIMER:
1581 return "timer";
1582 case A_PORT:
1583 return "port";
1584 case A_FUNCTION:
1585 case A_FUNCTION_RVAL:
1586 case A_FUNCTION_RTEMP:
1587 return "function";
1588 case A_EXT_FUNCTION:
1589 case A_EXT_FUNCTION_RVAL:
1590 case A_EXT_FUNCTION_RTEMP:
1591 return "external function";
1592 case A_ALTSTEP:
1593 return "altstep";
1594 case A_TESTCASE:
1595 return "testcase";
1596 case A_PAR_VAL:
1597 case A_PAR_VAL_IN:
1598 return "value parameter";
1599 case A_PAR_VAL_OUT:
1600 return "`out' value parameter";
1601 case A_PAR_VAL_INOUT:
1602 return "`inout' value parameter";
1603 case A_PAR_TEMPL_IN:
1604 return "template parameter";
1605 case A_PAR_TEMPL_OUT:
1606 return "`out' template parameter";
1607 case A_PAR_TEMPL_INOUT:
1608 return "`inout' template parameter";
1609 case A_PAR_TIMER:
1610 return "timer parameter";
1611 case A_PAR_PORT:
1612 return "port parameter";
1613 default:
1614 return "<unknown>";
1615 }
1616 }
1617
1618 string Assignment::get_description()
1619 {
1620 string ret_val(get_assname());
1621 ret_val += " `";
1622 switch (asstype) {
1623 case A_PAR_VAL:
1624 case A_PAR_VAL_IN:
1625 case A_PAR_VAL_OUT:
1626 case A_PAR_VAL_INOUT:
1627 case A_PAR_TEMPL_IN:
1628 case A_PAR_TEMPL_OUT:
1629 case A_PAR_TEMPL_INOUT:
1630 case A_PAR_TIMER:
1631 case A_PAR_PORT:
1632 // parameter is identified using its id
1633 ret_val += id->get_dispname();
1634 break;
1635 case A_CONST:
1636 case A_TEMPLATE:
1637 case A_VAR:
1638 case A_VAR_TEMPLATE:
1639 case A_TIMER:
1640 // these can be both local and global
1641 if (is_local()) ret_val += id->get_dispname();
1642 else ret_val += get_fullname();
1643 break;
1644 default:
1645 // the rest is always global
1646 ret_val += get_fullname();
1647 }
1648 ret_val += "'";
1649 return ret_val;
1650 }
1651
1652 void Assignment::set_my_scope(Scope *p_scope)
1653 {
1654 my_scope=p_scope;
1655 }
1656
1657 bool Assignment::is_local() const
1658 {
1659 return false;
1660 }
1661
1662 Setting *Assignment::get_Setting()
1663 {
1664 FATAL_ERROR("Common::Assignment::get_Setting()");
1665 return 0;
1666 }
1667
1668 Type *Assignment::get_Type()
1669 {
1670 FATAL_ERROR("Common::Assignment::get_Type()");
1671 return 0;
1672 }
1673
1674 Value *Assignment::get_Value()
1675 {
1676 FATAL_ERROR("Common::Assignment::get_Value()");
1677 return 0;
1678 }
1679
1680 Ttcn::Template *Assignment::get_Template()
1681 {
1682 FATAL_ERROR("Common::Assignment::get_Template()");
1683 return 0;
1684 }
1685
1686 bool Assignment::get_lazy_eval() const
1687 {
1688 FATAL_ERROR("Common::Assignment::get_lazy_eval()");
1689 return false;
1690 }
1691
1692 Ttcn::FormalParList *Assignment::get_FormalParList()
1693 {
1694 return 0;
1695 }
1696
1697 Ttcn::ArrayDimensions *Assignment::get_Dimensions()
1698 {
1699 return 0;
1700 }
1701
1702 Type *Assignment::get_RunsOnType()
1703 {
1704 return 0;
1705 }
1706
1707 void Assignment::chk_ttcn_id()
1708 {
1709 if(!my_scope) return;
1710 if(!get_id().get_has_valid(Identifier::ID_TTCN)
1711 && my_scope->get_parent_scope()==my_scope->get_scope_mod()
1712 // <internal> or <error> ...
1713 && my_scope->get_scope_mod()->get_modid().get_dispname()[0]!='<')
1714 warning("The identifier `%s' is not reachable from TTCN-3",
1715 get_id().get_dispname().c_str());
1716 }
1717
1718 // *this is the (var/const/modulepar/etc.) definition we want to access.
1719 // p_scope is the location from where we want to reach the definition.
1720 string Assignment::get_genname_from_scope(Scope *p_scope,
1721 const char *p_prefix)
1722 {
1723 if (!p_scope || !my_scope)
1724 FATAL_ERROR("Assignment::get_genname_from_scope()");
1725 string ret_val;
1726
1727 Module *my_mod = my_scope->get_scope_mod_gen();
1728 if ((my_mod != p_scope->get_scope_mod_gen()) &&
1729 !Asn::Assignments::is_spec_asss(my_mod)) {
1730 // when the definition is referred from another module
1731 // the reference shall be qualified with the namespace of my module
1732 ret_val = my_mod->get_modid().get_name();
1733 ret_val += "::";
1734 }
1735 if (p_prefix) ret_val += p_prefix;
1736 ret_val += get_genname();
1737 // add the cast to real type if its a lazy formal paramter
1738 switch (asstype) {
1739 case A_PAR_VAL:
1740 case A_PAR_VAL_IN:
1741 case A_PAR_TEMPL_IN:
1742 if (get_lazy_eval() && p_prefix==NULL) {
1743 Type* type = get_Type();
1744 string type_genname = (asstype==A_PAR_TEMPL_IN) ? type->get_genname_template(p_scope) : type->get_genname_value(p_scope);
1745 ret_val = string("((") + type_genname + string("&)") + ret_val + string(")");
1746 }
1747 break;
1748 default:
1749 // nothing to do
1750 break;
1751 }
1752 return ret_val;
1753 }
1754
1755 const char *Assignment::get_module_object_name()
1756 {
1757 if (!my_scope) FATAL_ERROR("Assignment::get_module_object_name()");
1758 return "module_object";
1759 }
1760
1761 void Assignment::use_as_lvalue(const Location&)
1762 {
1763 FATAL_ERROR("Common::Assignment::use_as_lvalue()");
1764 }
1765
1766 void Assignment::generate_code(output_struct *, bool)
1767 {
1768 }
1769
1770 void Assignment::generate_code(CodeGenHelper&)
1771 {
1772 }
1773
1774 void Assignment::dump(unsigned level) const
1775 {
1776 DEBUG(level, "Assignment: %s (%d)",
1777 id->get_dispname().c_str(), asstype);
1778 }
1779
1780 Ttcn::Group* Assignment::get_parent_group()
1781 {
1782 return NULL;
1783 }
1784
1785 } // namespace Common
This page took 0.126954 seconds and 4 git commands to generate.