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