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