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