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