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