1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
12 #include "../common/dbgnew.hh"
14 #include "asn1/AST_asn1.hh"
15 #include "Identifier.hh"
17 #include "TypeCompat.hh"
21 #include "asn1/Object0.hh"
22 #include "PredefFunc.hh"
23 #include "../common/version.h"
24 #include "CodeGenHelper.hh"
26 #include "ttcn3/profiler.h"
28 reffer::reffer(const char*) {}
32 // =================================
34 // =================================
36 vector
<Modules::type_enc_t
> Modules::delayed_type_enc_v
;
39 : Node(), mods_v(), mods_m()
41 set_fullname(string('@'));
46 for(size_t i
= 0; i
< mods_v
.size(); i
++) delete mods_v
[i
];
51 Modules
*Modules::clone() const
53 FATAL_ERROR("Modules::clone()");
57 void Modules::add_mod(Module
*p_mod
)
59 if (!p_mod
) FATAL_ERROR("NULL parameter: Common::Modules::add_mod()");
60 p_mod
->set_fullname("@"+p_mod
->get_modid().get_dispname());
61 p_mod
->set_scope_name(p_mod
->get_modid().get_dispname());
65 bool Modules::has_mod_withId(const Identifier
& p_modid
)
67 return mods_m
.has_key(p_modid
.get_name());
70 Module
* Modules::get_mod_byId(const Identifier
& p_modid
)
72 const string
& name
= p_modid
.get_name();
73 return mods_m
.has_key(name
)?mods_m
[name
]:0;
76 Assignment
* Modules::get_ass_bySRef(Ref_simple
*p_ref
)
79 FATAL_ERROR("NULL parameter: Common::Modules::get_ass_bySRef()");
80 const Identifier
*modid
=p_ref
->get_modid();
82 if(has_mod_withId(*modid
))
83 return get_mod_byId(*modid
)->get_ass_bySRef(p_ref
);
85 p_ref
->error("There is no module with identifier `%s'",
86 modid
->get_dispname().c_str());
91 p_ref
->error("`%s' entity not found in global scope",
92 p_ref
->get_dispname().c_str());
97 void Modules::chk_uniq()
99 for(size_t i
= 0; i
< mods_v
.size(); i
++) {
100 Module
*m
= mods_v
[i
];
101 const Identifier
& id
= m
->get_modid();
102 const string
& name
= id
.get_name();
103 if (mods_m
.has_key(name
)) {
104 Module
*m2
= mods_m
[name
];
105 m
->error("A module with identifier `%s' already exists",
106 id
.get_dispname().c_str());
107 m2
->error("This is the first module with the same name");
108 if (m
->get_moduletype() == m2
->get_moduletype() &&
109 !strcmp(m
->get_filename(), m2
->get_filename())) {
110 // the same file was given twice -> drop the entire module
112 mods_v
.replace(i
, 1);
115 } else mods_m
.add(name
, m
);
121 // first check the uniqueness of module names
123 // check the import chains
124 size_t nof_mods
= mods_v
.size();
125 for (size_t i
= 0; i
< nof_mods
; i
++) {
126 Module
*m
= mods_v
[i
];
127 ReferenceChain
refch(m
, "While checking import chains");
128 vector
<Common::Module
> modules
;
129 m
->chk_imp(refch
, modules
);
131 //clear the reference chain, get a fresh start
135 Module::module_set_t checked_modules
;
136 if (nof_top_level_pdus
> 0) {
137 chk_top_level_pdus();
138 // do not check ASN.1 modules, but assume they are already checked
139 for (size_t i
= 0; i
< nof_mods
; i
++) {
140 Module
*module
= mods_v
[i
];
141 if (module
->get_moduletype() == Module::MOD_ASN
)
142 checked_modules
.add(module
, 0);
144 for (size_t i
= 0; i
< nof_mods
; i
++) {
145 Module
*module
= mods_v
[i
];
146 if (module
->get_moduletype() != Module::MOD_ASN
)
147 module
->chk_recursive(checked_modules
);
150 // walk through all modules in bottom-up order
151 for (size_t i
= 0; i
< nof_mods
; i
++)
152 mods_v
[i
]->chk_recursive(checked_modules
);
154 checked_modules
.clear();
155 // run delayed Type::chk_coding() calls
156 if (!delayed_type_enc_v
.empty()) {
157 for (size_t i
= 0; i
< delayed_type_enc_v
.size(); ++i
) {
158 delayed_type_enc_v
[i
]->t
->chk_coding(delayed_type_enc_v
[i
]->enc
, true);
159 delete delayed_type_enc_v
[i
];
161 delayed_type_enc_v
.clear();
165 void Modules::chk_top_level_pdus()
167 Location
loc("<command line>");
168 for(size_t i
=0; i
<nof_top_level_pdus
; i
++) {
169 string
pduname(top_level_pdu
[i
]);
170 size_t dotpos
=pduname
.find('.');
171 if(dotpos
>=pduname
.size()) {
172 loc
.error("While searching top-level pdu `%s': "
173 "Please use the `modulename.identifier' format",
178 Identifier
*pdu_id
=0;
179 { // searching the module
180 const string
& pduname_mod
= pduname
.substr(0, dotpos
);
181 const string
& pduname_id
= pduname
.substr(dotpos
+ 1);
183 Identifier
modid(Identifier::ID_ASN
, pduname_mod
, true);
184 module
= get_mod_byId(modid
);
186 if (module
&& module
->get_moduletype() == Module::MOD_ASN
) {
187 pdu_id
= new Identifier(Identifier::ID_ASN
, pduname_id
, true);
191 Identifier
modid(Identifier::ID_TTCN
, pduname_mod
, true);
192 module
= get_mod_byId(modid
);
194 if (module
&& module
->get_moduletype() == Module::MOD_TTCN
) {
195 pdu_id
= new Identifier(Identifier::ID_TTCN
, pduname_id
, true);
199 Identifier
modid(Identifier::ID_NAME
, pduname_mod
, true);
200 module
= get_mod_byId(modid
);
203 pdu_id
= new Identifier(Identifier::ID_NAME
, pduname_id
, true);
206 // error - no such module
207 loc
.error("While searching top-level pdu `%s': "
208 "No module with name `%s'",
209 pduname
.c_str(), pduname_mod
.c_str());
213 Assignments
*asss
=module
->get_asss();
214 if(asss
->has_local_ass_withId(*pdu_id
)) {
215 Assignment
*ass
=asss
->get_local_ass_byId(*pdu_id
);
219 loc
.error("While searching top-level pdu `%s': "
220 "No assignment with identifier `%s'",
221 pduname
.c_str(), pdu_id
->get_dispname().c_str());
224 } // for top-level pdus
227 void Modules::write_checksums()
229 fputs("Module name Language MD5 checksum Version\n"
230 "---------------------------------------------------------------------------\n", stderr
);
231 size_t nof_mods
= mods_v
.size();
232 for (size_t i
= 0; i
< nof_mods
; i
++) {
233 mods_v
[i
]->write_checksum();
237 void Modules::generate_code(CodeGenHelper
& cgh
)
239 Common::Module::rename_default_namespace(); // if needed
241 The White Rabbit put on his spectacles.
242 "Where shall I begin, please your Majesty ?" he asked.
243 "Begin at the beginning,", the King said, very gravely, "and go on
244 till you come to the end: then stop."
247 for (size_t i
= 0; i
< mods_v
.size(); i
++) {
248 mods_v
[i
]->generate_code(cgh
);
249 if (tcov_file_name
&& in_tcov_files(mods_v
[i
]->get_filename())) {
250 Free(effective_module_lines
);
251 Free(effective_module_functions
);
252 effective_module_lines
= effective_module_functions
= NULL
;
260 void Modules::dump(unsigned level
) const
262 DEBUG(level
, "Modules (%lu pcs.)", (unsigned long) mods_v
.size());
263 for(size_t i
= 0; i
< mods_v
.size(); i
++) mods_v
[i
]->dump(level
);
266 std::set
<ModuleVersion
> Modules::getVersionsWithProductNumber() const {
267 std::set
<ModuleVersion
> versions
;
268 for (size_t i
= 0; i
< mods_v
.size(); ++i
) {
269 const ModuleVersion version
= mods_v
[i
]->getVersion();
270 if (version
.hasProductNumber()) {
271 versions
.insert(version
);
277 void Modules::generate_json_schema(JSON_Tokenizer
& json
, map
<Type
*, JSON_Tokenizer
>& json_refs
)
279 for(size_t i
= 0; i
< mods_v
.size(); ++i
) {
280 mods_v
[i
]->generate_json_schema(json
, json_refs
);
284 void Modules::delay_type_encode_check(Type
* p_type
, bool p_encode
)
286 type_enc_t
* elem
= new type_enc_t
;
288 elem
->enc
= p_encode
;
289 delayed_type_enc_v
.add(elem
);
293 // =================================
295 // =================================
297 ModuleVersion
Module::getVersion() const {
298 return ModuleVersion(product_number
, suffix
, release
, patch
, build
, extra
);
301 void Module::generate_literals(output_struct
*target
)
305 generate_bs_literals(src
, hdr
); // implementations follow directly below
306 generate_bp_literals(src
, hdr
);
307 generate_hs_literals(src
, hdr
);
308 generate_hp_literals(src
, hdr
);
309 generate_os_literals(src
, hdr
);
310 generate_op_literals(src
, hdr
);
311 generate_cs_literals(src
, hdr
);
312 generate_us_literals(src
, hdr
);
313 generate_oid_literals(src
, hdr
);
314 generate_pp_literals(src
, hdr
);
315 generate_mp_literals(src
, hdr
);
316 target
->source
.string_literals
=
317 mputstr(target
->source
.string_literals
, src
);
318 if (CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE
) {
319 target
->header
.global_vars
= mputstr(target
->header
.global_vars
, hdr
);
325 void Module::generate_bs_literals(char *&src
, char *&hdr
)
327 if (bs_literals
.size() == 0) return;
328 // indicates whether we have found at least one non-empty bitstring
329 bool is_nonempty
= false;
331 CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE
;
332 for (size_t i
= 0; i
< bs_literals
.size(); i
++) {
333 const string
& str
= bs_literals
.get_nth_key(i
);
334 size_t bits
= str
.size();
335 if (bits
== 0) continue;
336 if (is_nonempty
) src
= mputstr(src
, ",\n");
338 src
= mputstr(src
, "static const unsigned char ");
341 src
= mputprintf(src
, "%s_bits[] = { ",
342 bs_literals
.get_nth_elem(i
)->c_str());
343 // Filling up the octets one-by-one
344 for (size_t j
= 0; j
< (bits
+ 7) / 8; j
++) {
345 size_t offset
= 8 * j
;
346 unsigned char value
= 0;
347 for (size_t k
= 0; k
< 8 && k
< bits
- offset
; k
++) {
348 if (str
[offset
+ k
] == '1') value
|= (1 << k
);
350 if (j
> 0) src
= mputstr(src
, ", ");
351 src
= mputprintf(src
, "%d", value
);
353 src
= mputstr(src
, " }");
355 if (is_nonempty
) src
= mputstr(src
, ";\n");
356 for (size_t i
= 0; i
< bs_literals
.size(); i
++) {
358 src
= mputstr(src
, ",\n");
359 if (splitting
) hdr
= mputstr(hdr
, ",\n");
362 src
= mputprintf(src
, "%s const BITSTRING ",
363 splitting
? "extern" : "static");
364 if (splitting
) hdr
= mputstr(hdr
, "extern const BITSTRING ");
366 size_t bits
= bs_literals
.get_nth_key(i
).size();
367 const char *object_name
= bs_literals
.get_nth_elem(i
)->c_str();
368 if (bits
> 0) src
= mputprintf(src
, "%s(%lu, %s_bits)",
369 object_name
, (unsigned long) bits
, object_name
);
370 else src
= mputprintf(src
, "%s(0, NULL)", object_name
);
371 if (splitting
) hdr
= mputstr(hdr
, object_name
);
373 src
= mputstr(src
, ";\n");
374 if (splitting
) hdr
= mputstr(hdr
, ";\n");
377 void Module::generate_bp_literals(char *&src
, char *& /*hdr*/)
379 if (bp_literals
.size() == 0) return;
380 for (size_t i
= 0; i
< bp_literals
.size(); i
++) {
381 if (i
> 0) src
= mputstr(src
, ",\n");
382 else src
= mputstr(src
, "static const unsigned char ");
383 src
= mputprintf(src
, "%s_elements[] = { ",
384 bp_literals
.get_nth_elem(i
)->c_str());
385 const string
& str
= bp_literals
.get_nth_key(i
);
386 for (size_t j
= 0; j
< str
.size(); j
++) {
387 if (j
> 0) src
= mputstr(src
, ", ");
390 src
= mputc(src
, '0');
393 src
= mputc(src
, '1');
396 src
= mputc(src
, '2');
399 src
= mputc(src
, '3');
402 FATAL_ERROR("Invalid character in bitstring pattern.");
405 src
= mputstr(src
, " }");
407 src
= mputstr(src
, ";\n");
408 for (size_t i
= 0; i
< bp_literals
.size(); i
++) {
409 if (i
> 0) src
= mputstr(src
, ",\n");
410 else src
= mputstr(src
, "static const BITSTRING_template ");
411 const char *name
= bp_literals
.get_nth_elem(i
)->c_str();
412 src
= mputprintf(src
, "%s(%lu, %s_elements)",
413 name
, (unsigned long) bp_literals
.get_nth_key(i
).size(), name
);
415 src
= mputstr(src
, ";\n");
418 void Module::generate_hs_literals(char *&src
, char *&hdr
)
420 if (hs_literals
.size() == 0) return;
421 // indicates whether we have found at least one non-empty hexstring
422 bool is_nonempty
= false;
424 CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE
;
425 for (size_t i
= 0; i
< hs_literals
.size(); i
++) {
426 const string
& str
= hs_literals
.get_nth_key(i
);
427 size_t nibbles
= str
.size();
428 if (nibbles
== 0) continue;
429 size_t octets
= (nibbles
+ 1) / 2;
430 const char *str_ptr
= str
.c_str();
431 if (is_nonempty
) src
= mputstr(src
, ",\n");
433 src
= mputstr(src
, "static const unsigned char ");
436 src
= mputprintf(src
, "%s_nibbles[] = { ",
437 hs_literals
.get_nth_elem(i
)->c_str());
438 for (size_t j
= 0; j
< octets
; j
++) {
439 // Hex digit with even index always goes to the least significant
440 // 4 bits of the octet.
441 unsigned char value
= char_to_hexdigit(str_ptr
[2 * j
]);
442 if (2 * j
+ 1 < nibbles
) {
443 // Hex digit with odd index always goes to the most significant
444 // 4 bits of the octet.
445 // This digit is not present (bits are set to zero) if the length
446 // of hexstring is odd.
447 value
+= 16 * char_to_hexdigit(str_ptr
[2 * j
+ 1]);
449 if (j
> 0) src
= mputstr(src
, ", ");
450 src
= mputprintf(src
, "%u", value
);
452 src
= mputstr(src
, " }");
454 if (is_nonempty
) src
= mputstr(src
, ";\n");
455 for (size_t i
= 0; i
< hs_literals
.size(); i
++) {
457 src
= mputstr(src
, ",\n");
458 if (splitting
) hdr
= mputstr(hdr
, ",\n");
461 src
= mputprintf(src
, "%s const HEXSTRING ",
462 splitting
? "extern" : "static");
463 if (splitting
) hdr
= mputstr(hdr
, "extern const HEXSTRING ");
465 size_t nibbles
= hs_literals
.get_nth_key(i
).size();
466 const char *object_name
= hs_literals
.get_nth_elem(i
)->c_str();
467 if (nibbles
> 0) src
= mputprintf(src
, "%s(%lu, %s_nibbles)",
468 object_name
, (unsigned long) nibbles
, object_name
);
469 else src
= mputprintf(src
, "%s(0, NULL)", object_name
);
470 if (splitting
) hdr
= mputstr(hdr
, object_name
);
472 src
= mputstr(src
, ";\n");
473 if (splitting
) hdr
= mputstr(hdr
, ";\n");
476 void Module::generate_hp_literals(char *&src
, char *& /*hdr*/)
478 if (hp_literals
.size() == 0) return;
479 for (size_t i
= 0; i
< hp_literals
.size(); i
++) {
480 if (i
> 0) src
= mputstr(src
, ",\n");
481 else src
= mputstr(src
, "static const unsigned char ");
482 src
= mputprintf(src
, "%s_elements[] = { ",
483 hp_literals
.get_nth_elem(i
)->c_str());
484 const string
& str
= hp_literals
.get_nth_key(i
);
485 size_t size
= str
.size();
486 const char *str_ptr
= str
.c_str();
487 for (size_t j
= 0; j
< size
; j
++) {
488 if (j
> 0) src
= mputstr(src
, ", ");
490 if (str_ptr
[j
] == '?') num
= 16;
491 else if (str_ptr
[j
] == '*') num
= 17;
492 else num
= char_to_hexdigit(str_ptr
[j
]);
493 src
= mputprintf(src
, "%u", num
);
495 src
= mputstr(src
, " }");
497 src
= mputstr(src
, ";\n");
498 for (size_t i
= 0; i
< hp_literals
.size(); i
++) {
499 if (i
> 0) src
= mputstr(src
, ",\n");
500 else src
= mputstr(src
, "static const HEXSTRING_template ");
501 const char *name
= hp_literals
.get_nth_elem(i
)->c_str();
502 src
= mputprintf(src
, "%s(%lu, %s_elements)",
503 name
, (unsigned long) hp_literals
.get_nth_key(i
).size(), name
);
505 src
= mputstr(src
, ";\n");
508 void Module::generate_os_literals(char *&src
, char *&hdr
)
510 if (os_literals
.size() == 0) return;
511 // indicates whether we have found at least one non-empty octetstring
512 bool is_nonempty
= false;
514 CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE
;
515 for (size_t i
= 0; i
< os_literals
.size(); i
++) {
516 const string
& str
= os_literals
.get_nth_key(i
);
517 size_t size
= str
.size();
518 if (size
% 2) FATAL_ERROR("Invalid length for an octetstring.");
519 size_t octets
= size
/ 2;
520 if (octets
== 0) continue;
521 const char *str_ptr
= str
.c_str();
522 if (is_nonempty
) src
= mputstr(src
, ",\n");
524 src
= mputstr(src
, "static const unsigned char ");
527 src
= mputprintf(src
, "%s_octets[] = { ",
528 os_literals
.get_nth_elem(i
)->c_str());
529 for (size_t j
= 0; j
< octets
; j
++) {
530 if (j
> 0) src
= mputstr(src
, ", ");
531 src
= mputprintf(src
, "%u", 16 * char_to_hexdigit(str_ptr
[2 * j
]) +
532 char_to_hexdigit(str_ptr
[2 * j
+ 1]));
534 src
= mputstr(src
, " }");
536 if (is_nonempty
) src
= mputstr(src
, ";\n");
537 for (size_t i
= 0; i
< os_literals
.size(); i
++) {
539 src
= mputstr(src
, ",\n");
540 if (splitting
) hdr
= mputstr(hdr
, ",\n");
543 src
= mputprintf(src
, "%s const OCTETSTRING ",
544 splitting
? "extern" : "static");
545 if (splitting
) hdr
= mputstr(hdr
, "extern const OCTETSTRING ");
547 size_t octets
= os_literals
.get_nth_key(i
).size() / 2;
548 const char *object_name
= os_literals
.get_nth_elem(i
)->c_str();
549 if (octets
> 0) src
= mputprintf(src
, "%s(%lu, %s_octets)",
550 object_name
, (unsigned long) octets
, object_name
);
551 else src
= mputprintf(src
, "%s(0, NULL)", object_name
);
552 if (splitting
) hdr
= mputstr(hdr
, object_name
);
554 src
= mputstr(src
, ";\n");
555 if (splitting
) hdr
= mputstr(hdr
, ";\n");
558 void Module::generate_op_literals(char *&src
, char *& /*hdr*/)
560 if (op_literals
.size() == 0) return;
561 vector
<size_t> pattern_lens
;
562 for(size_t i
= 0; i
< op_literals
.size(); i
++) {
563 if (i
> 0) src
= mputstr(src
, ",\n");
564 else src
= mputstr(src
, "static const unsigned short ");
565 src
= mputprintf(src
, "%s_elements[] = { ",
566 op_literals
.get_nth_elem(i
)->c_str());
567 const string
& str
= op_literals
.get_nth_key(i
);
568 size_t size
= str
.size();
569 size_t pattern_len
= 0;
570 const char *str_ptr
= str
.c_str();
571 for (size_t j
= 0; j
< size
; j
++) {
572 if (j
> 0) src
= mputstr(src
, ", ");
574 if (str_ptr
[j
] == '?') num
= 256;
575 else if (str_ptr
[j
] == '*') num
= 257;
578 num
= 16 * char_to_hexdigit(str_ptr
[j
]);
580 if (j
>= size
) FATAL_ERROR("Unexpected end of octetstring pattern.");
582 num
+= char_to_hexdigit(str_ptr
[j
]);
584 src
= mputprintf(src
, "%u", num
);
587 src
= mputstr(src
, " }");
588 pattern_lens
.add(new size_t(pattern_len
));
590 src
= mputstr(src
, ";\n");
591 for (size_t i
= 0; i
< op_literals
.size(); i
++) {
592 if (i
> 0) src
= mputstr(src
, ",\n");
593 else src
= mputstr(src
, "static const OCTETSTRING_template ");
594 const char *name
= op_literals
.get_nth_elem(i
)->c_str();
595 src
= mputprintf(src
, "%s(%lu, %s_elements)",
596 name
, (unsigned long) *pattern_lens
[i
], name
);
598 src
= mputstr(src
, ";\n");
599 for (size_t i
= 0; i
< pattern_lens
.size(); i
++) delete pattern_lens
[i
];
600 pattern_lens
.clear();
603 void Module::generate_cs_literals(char *&src
, char *&hdr
)
605 if (cs_literals
.size() == 0) return;
607 CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE
;
608 for (size_t i
= 0; i
< cs_literals
.size(); i
++) {
609 const string
& str
= cs_literals
.get_nth_key(i
);
610 size_t str_len
= str
.size();
611 const char *str_ptr
= str
.c_str();
612 const char *str_name
= cs_literals
.get_nth_elem(i
)->c_str();
615 src
= mputstr(src
, ",\n");
616 if (splitting
) hdr
= mputstr(hdr
, ",\n");
619 src
= mputprintf(src
, "%s const CHARSTRING ",
620 splitting
? "extern" : "static");
621 if (splitting
) hdr
= mputstr(hdr
, "extern const CHARSTRING ");
626 src
= mputprintf(src
, "%s(0, NULL)", str_name
);
629 src
= mputprintf(src
, "%s('", str_name
);
630 src
= Code::translate_character(src
, *str_ptr
, false);
631 src
= mputstr(src
, "')");
634 src
= mputprintf(src
, "%s(%lu, \"", str_name
, (unsigned long) str_len
);
635 // Note: Code::translate_string() is not suitable because the string
636 // may contain NUL characters at which translate_string() stops
638 for (size_t j
= 0; j
< str_len
; j
++)
639 src
= Code::translate_character(src
, str_ptr
[j
], true);
640 src
= mputstr(src
, "\")");
643 if (splitting
) hdr
= mputstr(hdr
, str_name
);
645 src
= mputstr(src
, ";\n");
646 if (splitting
) hdr
= mputstr(hdr
, ";\n");
649 void Module::generate_pp_literals(char *&src
, char *&) // padding patterns
651 if (pp_literals
.size() == 0) return;
652 for (size_t i
= 0; i
< pp_literals
.size(); i
++) {
653 const string
& pattern
= pp_literals
.get_nth_key(i
);
654 size_t pattern_len
= pattern
.size();
655 const char *pattern_ptr
= pattern
.c_str();
656 if (i
> 0) src
= mputstr(src
, ",\n");
657 else src
= mputstr(src
, "static const unsigned char ");
658 src
= mputprintf(src
, "%s[] = { ", pp_literals
.get_nth_elem(i
)->c_str());
659 if (pattern_len
% 8 != 0) FATAL_ERROR("Module::generate_pp_literals()");
660 size_t nof_octets
= pattern_len
/ 8;
661 for (size_t j
= 0; j
< nof_octets
; j
++) {
662 if (j
> 0) src
= mputstr(src
, ", ");
663 unsigned char octet
= 0;
664 for (size_t k
= 0; k
< 8; k
++) {
665 // take the octets in reverse order
666 // MSB is the first character of the string
668 if (pattern_ptr
[8 * (nof_octets
- j
- 1) + k
] == '1') octet
|= 0x01;
670 src
= mputprintf(src
, "0x%02x", octet
);
672 src
= mputstr(src
, " }");
674 src
= mputstr(src
, ";\n");
677 void Module::generate_mp_literals(char *&src
, char *&) // matching patt.
679 if (mp_literals
.size() == 0) return;
680 for (size_t i
= 0; i
< mp_literals
.size(); i
++) {
681 const string
& str
= mp_literals
.get_nth_key(i
);
682 if (str
.size() < 1) FATAL_ERROR("Module::generate_mp_literals()");
683 const char *str_ptr
= str
.c_str();
685 if (i
> 0) src
= mputstr(src
, ",\n");
686 else src
= mputstr(src
, "static const Token_Match ");
688 src
= mputprintf(src
, "%s(\"", mp_literals
.get_nth_elem(i
)->c_str());
689 src
= Code::translate_string(src
, str_ptr
+ 1);
690 // The first character of the string is case-sensitiveness flag:
691 // 'I' for yes, 'N' for no,
692 // 'F' for fixed string matching which is always case sensitive.
693 src
= mputprintf(src
, "\", %s%s)", (str_ptr
[0]!='N') ? "TRUE" : "FALSE",
694 (str_ptr
[0] == 'F') ? ", TRUE" : "");
696 src
= mputstr(src
, ";\n");
699 void Module::generate_us_literals(char *&src
, char *&hdr
) // univ.cs
701 size_t n_literals
= us_literals
.size();
702 if (n_literals
== 0) return;
703 bool array_needed
= false;
705 CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE
;
706 for (size_t i
= 0; i
< n_literals
; i
++) {
707 const ustring
& value
= us_literals
.get_nth_key(i
);
708 size_t value_size
= value
.size();
709 if (value_size
< 2) continue;
710 if (array_needed
) src
= mputstr(src
, ",\n");
712 src
= mputstr(src
, "static const universal_char ");
715 src
= mputprintf(src
, "%s_uchars[] = { ",
716 us_literals
.get_nth_elem(i
)->c_str());
717 const ustring::universal_char
*uchars_ptr
= value
.u_str();
718 for (size_t j
= 0; j
< value_size
; j
++) {
719 if (j
> 0) src
= mputstr(src
, ", ");
720 src
= mputprintf(src
, "{ %u, %u, %u, %u }", uchars_ptr
[j
].group
,
721 uchars_ptr
[j
].plane
, uchars_ptr
[j
].row
, uchars_ptr
[j
].cell
);
723 src
= mputstr(src
, " }");
725 if (array_needed
) src
= mputstr(src
, ";\n");
726 for (size_t i
= 0; i
< n_literals
; i
++) {
728 src
= mputstr(src
, ",\n");
729 if (splitting
) hdr
= mputstr(hdr
, ",\n");
732 src
= mputprintf(src
, "%s const UNIVERSAL_CHARSTRING ",
733 splitting
? "extern" : "static");
734 if (splitting
) hdr
= mputstr(hdr
, "extern const UNIVERSAL_CHARSTRING ");
736 const char *value_name
= us_literals
.get_nth_elem(i
)->c_str();
737 const ustring
& value
= us_literals
.get_nth_key(i
);
738 size_t value_size
= value
.size();
739 switch (value_size
) {
741 src
= mputprintf(src
, "%s(0, (const universal_char*)NULL)", value_name
);
744 const ustring::universal_char
& uchar
= value
.u_str()[0];
745 src
= mputprintf(src
, "%s(%u, %u, %u, %u)", value_name
,
746 uchar
.group
, uchar
.plane
, uchar
.row
, uchar
.cell
);
749 src
= mputprintf(src
, "%s(%lu, %s_uchars)", value_name
,
750 (unsigned long) value_size
, value_name
);
753 if (splitting
) hdr
= mputstr(hdr
, value_name
);
755 src
= mputstr(src
, ";\n");
756 if (splitting
) hdr
= mputstr(hdr
, ";\n");
759 void Module::generate_oid_literals(char *&src
, char *& /*hdr*/)
761 if (oid_literals
.size() == 0) return;
762 for (size_t i
= 0; i
< oid_literals
.size(); i
++) {
763 if (i
> 0) src
= mputstr(src
, ",\n");
764 else src
= mputstr(src
, "static const OBJID::objid_element ");
766 src
= mputprintf(src
, "%s_comps[] = { %s }",
767 oid_literals
.get_nth_elem(i
)->oid_id
.c_str(),
768 oid_literals
.get_nth_key(i
).c_str());
770 src
= mputstr(src
, ";\n");
771 for(size_t i
= 0; i
< oid_literals
.size(); i
++) {
772 const OID_literal
*litstruct
= oid_literals
.get_nth_elem(i
);
774 if (i
> 0) src
= mputstr(src
, ",\n");
775 else src
= mputstr(src
, "static const OBJID ");
777 src
= mputprintf(src
, "%s(%lu, %s_comps)",
778 litstruct
->oid_id
.c_str(), (unsigned long) litstruct
->nof_elems
,
779 litstruct
->oid_id
.c_str());
781 src
= mputstr(src
, ";\n");
784 void Module::generate_functions(output_struct
*output
)
786 bool tcov_enabled
= tcov_file_name
&& in_tcov_files(get_filename());
787 bool has_pre_init_before_tcov
= output
->functions
.pre_init
!= NULL
;
789 output
->functions
.pre_init
= mputprintf(output
->functions
.pre_init
,
790 "TTCN_Location_Statistics::init_file_lines(\"%s\", effective_module_lines, sizeof(effective_module_lines) / sizeof(int));\n" \
791 "TTCN_Location_Statistics::init_file_functions(\"%s\", effective_module_functions, sizeof(effective_module_functions) / sizeof(char *));\n",
792 get_tcov_file_name(get_filename()), get_tcov_file_name(get_filename()));
795 bool has_pre_init
= false;
796 bool profiled
= MOD_TTCN
== get_moduletype() && is_file_profiled(get_filename());
797 // always generate pre_init_module if the file is profiled
798 if (output
->functions
.pre_init
|| profiled
) {
799 output
->source
.static_function_prototypes
=
800 mputstr(output
->source
.static_function_prototypes
,
801 "static void pre_init_module();\n");
802 output
->source
.static_function_bodies
= mputstr(output
->source
.static_function_bodies
,
803 "static void pre_init_module()\n"
805 if (include_location_info
) {
806 output
->source
.static_function_bodies
=
807 mputstr(output
->source
.static_function_bodies
,
808 (tcov_enabled
&& has_pre_init_before_tcov
) ? "TTCN_Location_Statistics current_location(\""
809 : "TTCN_Location current_location(\"");
810 output
->source
.static_function_bodies
=
811 Code::translate_string(output
->source
.static_function_bodies
, (tcov_enabled
&& has_pre_init_before_tcov
) ? get_tcov_file_name(get_filename()) : get_filename());
812 output
->source
.static_function_bodies
=
813 mputprintf(output
->source
.static_function_bodies
,
814 (tcov_enabled
&& has_pre_init_before_tcov
) ? "\", 0, TTCN_Location_Statistics::LOCATION_UNKNOWN, \"%s\");\n"
815 : "\", 0, TTCN_Location::LOCATION_UNKNOWN, \"%s\");\n", get_modid().get_dispname().c_str());
816 if (tcov_enabled
&& has_pre_init_before_tcov
) {
817 effective_module_lines
=
818 mputprintf(effective_module_lines
, "%s0",
819 (effective_module_lines
? ", " : ""));
820 effective_module_functions
=
821 mputprintf(effective_module_functions
, "%s\"%s\"",
822 (effective_module_functions
? ", " : ""), get_modid().get_dispname().c_str());
825 output
->source
.static_function_bodies
= mputprintf(output
->source
.static_function_bodies
,
826 "%s::init_ttcn3_profiler();\n"
827 "TTCN3_Stack_Depth stack_depth;\n"
828 "ttcn3_prof.execute_line(\"%s\", 0);\n", get_modid().get_name().c_str(), get_filename());
831 output
->source
.static_function_bodies
=
832 mputstr(output
->source
.static_function_bodies
, output
->functions
.pre_init
);
833 output
->source
.static_function_bodies
=
834 mputstr(output
->source
.static_function_bodies
, "}\n\n");
835 Free(output
->functions
.pre_init
);
836 output
->functions
.pre_init
= NULL
;
839 bool has_post_init_before_tcov
= output
->functions
.post_init
!= NULL
;
840 // post_init function
841 bool has_post_init
= false;
842 if (output
->functions
.post_init
) {
843 output
->source
.static_function_prototypes
= mputstr(output
->source
.static_function_prototypes
,
844 "static void post_init_module();\n");
845 output
->source
.static_function_bodies
= mputstr(output
->source
.static_function_bodies
,
846 "static void post_init_module()\n"
848 if (include_location_info
) {
849 output
->source
.static_function_bodies
=
850 mputstr(output
->source
.static_function_bodies
,
851 (tcov_enabled
&& has_post_init_before_tcov
) ? "TTCN_Location_Statistics current_location(\""
852 : "TTCN_Location current_location(\"");
853 output
->source
.static_function_bodies
=
854 Code::translate_string(output
->source
.static_function_bodies
, (tcov_enabled
&& has_post_init_before_tcov
) ? get_tcov_file_name(get_filename()) : get_filename());
855 output
->source
.static_function_bodies
=
856 mputprintf(output
->source
.static_function_bodies
,
857 (tcov_enabled
&& has_post_init_before_tcov
) ? "\", 0, TTCN_Location_Statistics::LOCATION_UNKNOWN, \"%s\");\n"
858 : "\", 0, TTCN_Location::LOCATION_UNKNOWN, \"%s\");\n", get_modid().get_dispname().c_str());
859 if (tcov_enabled
&& has_post_init_before_tcov
) {
860 effective_module_lines
=
861 mputprintf(effective_module_lines
, "%s0",
862 (effective_module_lines
? ", " : ""));
863 effective_module_functions
=
864 mputprintf(effective_module_functions
, "%s\"%s\"",
865 (effective_module_functions
? ", " : ""), get_modid().get_dispname().c_str());
867 if (MOD_TTCN
== get_moduletype() && is_file_profiled(get_filename())) {
868 output
->source
.static_function_bodies
= mputprintf(output
->source
.static_function_bodies
,
869 "TTCN3_Stack_Depth stack_depth;\n"
870 "ttcn3_prof.execute_line(\"%s\", 0);\n", get_filename());
873 output
->source
.static_function_bodies
=
874 mputstr(output
->source
.static_function_bodies
, output
->functions
.post_init
);
875 output
->source
.static_function_bodies
=
876 mputstr(output
->source
.static_function_bodies
, "}\n\n");
877 Free(output
->functions
.post_init
);
878 output
->functions
.post_init
= NULL
;
879 has_post_init
= true;
881 // set_param function
883 if (output
->functions
.set_param
) {
884 output
->source
.static_function_prototypes
= mputstr(output
->source
.static_function_prototypes
,
885 "static boolean set_module_param(Module_Param& param);\n");
886 output
->source
.static_function_bodies
= mputstr(output
->source
.static_function_bodies
,
887 "static boolean set_module_param(Module_Param& param)\n"
889 "const char* const par_name = param.get_id()->get_current_name();\n");
890 output
->source
.static_function_bodies
=
891 mputstr(output
->source
.static_function_bodies
, output
->functions
.set_param
);
892 output
->source
.static_function_bodies
=
893 mputstr(output
->source
.static_function_bodies
, "return FALSE;\n"
895 Free(output
->functions
.set_param
);
896 output
->functions
.set_param
= NULL
;
897 has_set_param
= true;
898 } else has_set_param
= false;
899 // get_param function
901 if (output
->functions
.get_param
) {
902 output
->source
.static_function_prototypes
= mputstr(output
->source
.static_function_prototypes
,
903 "static Module_Param* get_module_param(Module_Param_Name& param_name);\n");
904 output
->source
.static_function_bodies
= mputstr(output
->source
.static_function_bodies
,
905 "static Module_Param* get_module_param(Module_Param_Name& param_name)\n"
907 "const char* const par_name = param_name.get_current_name();\n");
908 output
->source
.static_function_bodies
=
909 mputstr(output
->source
.static_function_bodies
, output
->functions
.get_param
);
910 output
->source
.static_function_bodies
=
911 mputstr(output
->source
.static_function_bodies
, "return NULL;\n"
913 Free(output
->functions
.get_param
);
914 output
->functions
.get_param
= NULL
;
915 has_get_param
= true;
916 } else has_get_param
= false;
917 // log_param function
919 if (output
->functions
.log_param
) {
920 output
->source
.static_function_prototypes
= mputstr(output
->source
.static_function_prototypes
,
921 "static void log_module_param();\n");
922 output
->source
.static_function_bodies
= mputstr(output
->source
.static_function_bodies
,
923 "static void log_module_param()\n"
925 output
->source
.static_function_bodies
=
926 mputstr(output
->source
.static_function_bodies
, output
->functions
.log_param
);
927 output
->source
.static_function_bodies
= mputstr(output
->source
.static_function_bodies
,
929 Free(output
->functions
.log_param
);
930 output
->functions
.log_param
= NULL
;
931 has_log_param
= true;
932 } else has_log_param
= false;
933 // init_comp function
935 if (output
->functions
.init_comp
) {
936 output
->source
.static_function_prototypes
=
937 mputstr(output
->source
.static_function_prototypes
,
938 "static boolean init_comp_type("
939 "const char *component_type, boolean init_base_comps);\n");
940 output
->source
.static_function_bodies
=
941 mputstr(output
->source
.static_function_bodies
,
942 "static boolean init_comp_type(const char *component_type, "
943 "boolean init_base_comps)\n"
944 "{\n(void)init_base_comps;\n");
945 output
->source
.static_function_bodies
=
946 mputstr(output
->source
.static_function_bodies
,
947 output
->functions
.init_comp
);
948 output
->source
.static_function_bodies
=
949 mputstr(output
->source
.static_function_bodies
, "return FALSE;\n"
951 Free(output
->functions
.init_comp
);
952 output
->functions
.init_comp
= NULL
;
953 has_init_comp
= true;
954 } else has_init_comp
= false;
957 if (output
->functions
.start
) {
958 output
->source
.static_function_prototypes
= mputstr(output
->source
.static_function_prototypes
,
959 "static boolean start_ptc_function(const char *function_name, "
960 "Text_Buf& function_arguments);\n");
961 output
->source
.static_function_bodies
= mputstr(output
->source
.static_function_bodies
,
962 "static boolean start_ptc_function(const char *function_name, "
963 "Text_Buf& function_arguments)\n"
965 output
->source
.static_function_bodies
=
966 mputstr(output
->source
.static_function_bodies
, output
->functions
.start
);
967 output
->source
.static_function_bodies
=
968 mputstr(output
->source
.static_function_bodies
, "return FALSE;\n"
970 Free(output
->functions
.start
);
971 output
->functions
.start
= NULL
;
973 } else has_start
= false;
976 if (output
->functions
.control
) {
977 output
->source
.static_function_prototypes
= mputstr(output
->source
.static_function_prototypes
,
978 "static void module_control_part();\n");
979 output
->source
.static_function_bodies
= mputstr(output
->source
.static_function_bodies
,
980 "static void module_control_part()\n"
982 output
->source
.static_function_bodies
=
983 mputstr(output
->source
.static_function_bodies
, output
->functions
.control
);
984 output
->source
.static_function_bodies
=
985 mputstr(output
->source
.static_function_bodies
, "}\n\n");
986 Free(output
->functions
.control
);
987 output
->functions
.control
= NULL
;
989 } else has_control
= false;
992 output
->source
.string_literals
= mputstr(output
->source
.string_literals
,
993 "static const unsigned char module_checksum[] = {");
994 for (size_t i
= 0; i
< sizeof(module_checksum
); i
++) {
995 if (i
> 0) output
->source
.string_literals
=
996 mputc(output
->source
.string_literals
, ',');
997 output
->source
.string_literals
=
998 mputprintf(output
->source
.string_literals
, " 0x%02x",
1001 output
->source
.string_literals
= mputstr(output
->source
.string_literals
,
1004 const char *module_name
= modid
->get_name().c_str();
1006 // XML namespaces. Written in the order they are stored:
1007 // sorted ASCIIbetically by the prefix.
1008 // Not all namespaces are used by every module. Unfortunately, the array
1009 // (which has the same size in all modules) cannot be compacted, because
1010 // the indexes have already been used when the XER descriptors were written.
1011 // All we can do is store NULLs for the unused namespaces.
1012 size_t num_xml_namespaces
= namespaces
.size();
1013 if (moduletype
== MOD_TTCN
) { //TODO remove this when ASN.1 gets EXER
1014 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
1016 "// written by %s in " __FILE__
" at %d\n"
1018 "static const size_t num_namespaces = %lu;\n"
1020 , __FUNCTION__
, __LINE__
1022 , (unsigned long)num_xml_namespaces
1024 if (num_xml_namespaces
!= 0 || (control_ns
&& control_ns_prefix
)) {
1025 output
->source
.global_vars
= mputstr(output
->source
.global_vars
,
1026 "static const namespace_t xml_namespaces[num_namespaces+1] = {\n");
1027 for (size_t i
=0; i
< namespaces
.size(); ++i
) {
1028 if (used_namespaces
.has_key(i
)) {
1029 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
1030 " { \"%s\", \"%s\" },\n", // ns, then prefix
1031 namespaces
.get_nth_elem(i
), namespaces
.get_nth_key(i
).c_str());
1034 output
->source
.global_vars
= mputstr(output
->source
.global_vars
,
1035 " { NULL, NULL },\n"); // not used in this module
1038 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
1039 " { \"%s\", \"%s\" }\n};\n\n",
1040 (control_ns
? control_ns
: ""),
1041 (control_ns_prefix
? control_ns_prefix
: ""));
1042 } // if there are namespaces
1047 output
->header
.global_vars
= mputprintf(output
->header
.global_vars
,
1048 "extern TTCN_Module %s;\n",
1051 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
1052 "TTCN_Module %s(\"%s\", __DATE__, __TIME__, %s, %s",
1055 modid
->get_dispname().c_str(),
1056 (has_checksum
? "module_checksum" : "NULL"),
1057 has_pre_init
? "pre_init_module" : "NULL");
1059 if (moduletype
== MOD_TTCN
) {
1060 // TTCN-3 specific function pointers
1061 if (product_number
== NULL
) {
1062 output
->source
.global_vars
= mputstr(output
->source
.global_vars
, ", NULL");
1064 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
, ", \"%s\"", product_number
);
1066 string extra_str
= extra
? ( string('"') + extra
+ string('"') ) : string("NULL");
1067 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
1068 ", %uU, %uU, %uU, %uU, %s, %luLU, %s, %s, %s, %s, %s, %s, %s, %s",
1069 suffix
, release
, patch
, build
, extra_str
.c_str(),
1070 (unsigned long)num_xml_namespaces
,
1071 ((num_xml_namespaces
|| (control_ns
&& control_ns_prefix
)) ? "xml_namespaces" : "0"),
1072 has_post_init
? "post_init_module" : "NULL",
1073 has_set_param
? "set_module_param" : "NULL",
1074 has_get_param
? "get_module_param" : "NULL",
1075 has_log_param
? "log_module_param" : "NULL",
1076 has_init_comp
? "init_comp_type" : "NULL",
1077 has_start
? "start_ptc_function" : "NULL",
1078 has_control
? "module_control_part" : "NULL");
1080 // self checks for ASN.1 modules
1082 FATAL_ERROR("Module::generate_functions(): post_init function in ASN.1 module");
1084 FATAL_ERROR("Module::generate_functions(): set_param function in ASN.1 module");
1086 FATAL_ERROR("Module::generate_functions(): get_param function in ASN.1 module");
1088 FATAL_ERROR("Module::generate_functions(): log_param function in ASN.1 module");
1090 FATAL_ERROR("Module::generate_functions(): init_comp function in ASN.1 module");
1092 FATAL_ERROR("Module::generate_functions(): startable function in ASN.1 module");
1094 FATAL_ERROR("Module::generate_functions(): control part in ASN.1 module");
1096 output
->source
.global_vars
= mputstr(output
->source
.global_vars
, ");\n");
1097 // #include into the source file
1098 output
->source
.includes
= mputprintf(output
->source
.includes
,
1099 "#include \"%s.hh\"\n",
1100 duplicate_underscores
? module_name
: modid
->get_ttcnname().c_str());
1102 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
1103 "\nstatic const RuntimeVersionChecker ver_checker("
1104 " current_runtime_version.requires_major_version_%d,\n"
1105 " current_runtime_version.requires_minor_version_%d,\n"
1106 " current_runtime_version.requires_patch_level_%d,"
1107 " current_runtime_version.requires_runtime_%d);\n",
1108 TTCN3_MAJOR
, TTCN3_MINOR
, TTCN3_PATCHLEVEL
, use_runtime_2
? 2 : 1
1111 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
1112 "\nstatic const int effective_module_lines[] = { %s };\n" \
1113 "static const char *effective_module_functions[] = { %s };\n",
1114 effective_module_lines
? static_cast<const char *>(effective_module_lines
) : "",
1115 effective_module_functions
? static_cast<const char *>(effective_module_functions
) : "");
1119 void Module::generate_conversion_functions(output_struct
*output
)
1121 for (size_t i
= 0; i
< type_conv_v
.size(); i
++)
1123 ->gen_conv_func(&output
->source
.static_conversion_function_prototypes
,
1124 &output
->source
.static_conversion_function_bodies
,
1128 string
Module::add_literal(map
<string
, string
>& literals
, const string
& str
,
1131 if (literals
.has_key(str
)) return *literals
[str
];
1133 string
*literal
= new string(prefix
+Int2string(literals
.size()));
1134 literals
.add(str
, literal
);
1139 void Module::clear_literals(map
<string
, string
>& literals
)
1141 for (size_t i
= 0; i
< literals
.size(); i
++)
1142 delete literals
.get_nth_elem(i
);
1146 map
<string
, const char> Module::namespaces
;
1147 map
<string
, const char> Module::invented_prefixes
;
1148 size_t Module::default_namespace_attempt
= 0;
1149 size_t Module::replacement_for_empty_prefix
= (size_t)-1;
1151 Module::Module(moduletype_t p_mt
, Identifier
*p_modid
)
1152 : Scope(), moduletype(p_mt
), modid(p_modid
),
1153 imp_checked(false), gen_code(false), has_checksum(false),
1154 visible_mods(), module_checksum(),
1155 bs_literals(), bp_literals(), hs_literals(), hp_literals(), os_literals(),
1156 op_literals(), cs_literals(), us_literals(), pp_literals(), mp_literals(),
1157 oid_literals(), tmp_id_count(0),
1158 control_ns(p_mt
== MOD_ASN
? mcopystr("urn:oid:2.1.5.2.0.1") : NULL
),
1159 control_ns_prefix(p_mt
== MOD_ASN
? mcopystr("asn1") : NULL
),
1160 // only ASN.1 modules have default control namespace (X.693 amd1, 16.9)
1161 used_namespaces(), type_conv_v(), product_number(NULL
),
1162 suffix(0), release(UINT_MAX
), patch(UINT_MAX
), build(UINT_MAX
), extra(NULL
)
1165 FATAL_ERROR("NULL parameter: Common::Module::Module()");
1166 memset(module_checksum
, 0, sizeof(module_checksum
));
1167 set_scopeMacro_name(modid
->get_dispname());
1173 visible_mods
.clear();
1174 clear_literals(bs_literals
);
1175 clear_literals(bp_literals
);
1176 clear_literals(hs_literals
);
1177 clear_literals(hp_literals
);
1178 clear_literals(os_literals
);
1179 clear_literals(op_literals
);
1180 clear_literals(cs_literals
);
1181 clear_literals(pp_literals
);
1182 clear_literals(mp_literals
);
1183 for (size_t i
= 0; i
< us_literals
.size(); i
++)
1184 delete us_literals
.get_nth_elem(i
);
1185 us_literals
.clear();
1186 for (size_t i
= 0; i
< oid_literals
.size(); i
++)
1187 delete oid_literals
.get_nth_elem(i
);
1188 oid_literals
.clear();
1189 for (size_t i
= 0; i
< type_conv_v
.size(); i
++)
1190 delete type_conv_v
[i
];
1191 type_conv_v
.clear();
1193 Free(control_ns_prefix
);
1194 used_namespaces
.clear(); // all the values are NULL, no need to free
1195 // static members below; repeated clear()s are redundant but harmless
1197 invented_prefixes
.clear();
1198 Free(product_number
);
1202 Type
*Module::get_address_type()
1204 FATAL_ERROR("Common::Module::get_address_type()");
1208 string
Module::add_ustring_literal(const ustring
& ustr
)
1210 if (us_literals
.has_key(ustr
)) return *us_literals
[ustr
];
1212 string
*literal
= new string("us_" + Int2string(us_literals
.size()));
1213 us_literals
.add(ustr
, literal
);
1218 string
Module::add_objid_literal(const string
& oi_str
, const size_t nof_elems
)
1220 if(oid_literals
.has_key(oi_str
)) return oid_literals
[oi_str
]->oid_id
;
1222 OID_literal
*oi_struct
= new OID_literal
;
1223 oi_struct
->nof_elems
= nof_elems
;
1224 oi_struct
->oid_id
= "oi_" + Int2string(oid_literals
.size());
1225 oid_literals
.add(oi_str
, oi_struct
);
1226 return oi_struct
->oid_id
;
1230 void Module::add_type_conv(TypeConv
*p_conv
)
1232 if (p_conv
== NULL
) FATAL_ERROR("Module::add_type_conv()");
1233 Type
*p_from_type
= p_conv
->get_from_type();
1234 Type
*p_to_type
= p_conv
->get_to_type();
1235 if (!p_from_type
->is_structured_type()
1236 || !p_to_type
->is_structured_type())
1237 FATAL_ERROR("Module::add_type_conv()");
1238 if (p_from_type
== p_to_type
) {
1239 // Never add the same types.
1243 for (size_t i
= 0; i
< type_conv_v
.size(); i
++) {
1244 TypeConv
*conv
= type_conv_v
[i
];
1245 if (conv
->get_from_type() == p_from_type
1246 && conv
->get_to_type() == p_to_type
1247 && conv
->is_temp() == p_conv
->is_temp()) {
1248 // Same pair of types, both for values or templates. We're the
1249 // owners, deallocate.
1254 type_conv_v
.add(p_conv
);
1257 bool Module::needs_type_conv(Type
*p_from_type
, Type
*p_to_type
) const
1259 for (size_t i
= 0; i
< type_conv_v
.size(); i
++) {
1260 TypeConv
*conv
= type_conv_v
[i
];
1261 if (conv
->get_from_type() == p_from_type
1262 && conv
->get_to_type() == p_to_type
)
1268 void Module::chk_recursive(module_set_t
& checked_modules
)
1270 if (checked_modules
.has_key(this)) return;
1271 // this must be added to the set at the beginning
1272 // in order to deal with circular imports
1273 checked_modules
.add(this, 0);
1274 // check the imported modules first
1275 size_t nof_visible_mods
= visible_mods
.size();
1276 for (size_t i
= 0; i
< nof_visible_mods
; i
++) {
1277 Module
*m
= visible_mods
.get_nth_key(i
);
1278 if (m
!= this) m
->chk_recursive(checked_modules
);
1280 // then check the module itself
1281 chk(); // this is the only virtual call
1284 bool Module::is_visible(Module
*m
)
1286 collect_visible_mods();
1287 return visible_mods
.has_key(m
);
1290 void Module::get_visible_mods(module_set_t
& p_visible_mods
)
1292 if (visible_mods
.has_key(this)) {
1293 size_t nof_visible_mods
= visible_mods
.size();
1294 for (size_t i
= 0; i
< nof_visible_mods
; i
++) {
1295 Module
*m
= visible_mods
.get_nth_key(i
);
1296 if (!p_visible_mods
.has_key(m
)) p_visible_mods
.add(m
, 0);
1299 get_imported_mods(p_visible_mods
);
1303 void Module::write_checksum()
1305 fprintf(stderr
, "%-18s ", modid
->get_dispname().c_str());
1306 switch (moduletype
) {
1307 case MOD_TTCN
: fprintf(stderr
, "%-15s ", "TTCN-3"); break;
1308 case MOD_ASN
: fprintf(stderr
, "%-15s ", "ASN.1"); break;
1309 case MOD_UNKNOWN
: fprintf(stderr
, "%-15s ", "OTHER"); break;
1312 if (!has_checksum
) {
1313 fputc('\n', stderr
);
1317 size_t nof_checksum
= sizeof(module_checksum
);
1318 for (size_t i
= 0; i
< nof_checksum
; i
++) {
1319 fprintf(stderr
, "%02x", module_checksum
[i
]);
1322 if (release
<= 999999 && patch
< 30 && build
< 100) {
1323 char *product_identifier
=
1324 get_product_identifier(product_number
, suffix
, release
, patch
, build
, extra
);
1325 fprintf(stderr
, " %s", product_identifier
);
1326 Free(product_identifier
);
1329 fputc('\n', stderr
);
1332 char* Module::get_product_identifier(const char* product_number
,
1333 const unsigned int suffix
, unsigned int release
, unsigned int patch
,
1334 unsigned int build
, const char* extra
)
1336 expstring_t ret_val
= memptystr();
1337 if ( product_number
== NULL
1338 && suffix
== UINT_MAX
1339 && release
== UINT_MAX
1340 && patch
== UINT_MAX
1341 && build
== UINT_MAX
) {
1342 ret_val
= mputstr(ret_val
, "<RnXnn>");
1345 if (product_number
!= NULL
) {
1346 ret_val
= mputstr(ret_val
, product_number
);
1348 ret_val
= mputprintf(ret_val
, "/%d", suffix
);
1350 ret_val
= mputc(ret_val
, ' ');
1353 char* build_str
= buildstr(build
);
1354 ret_val
= mputprintf(ret_val
, "R%u%c%s%s", release
, eri(patch
), build_str
, extra
? extra
: "");
1359 void Module::collect_visible_mods()
1361 if (!visible_mods
.has_key(this)) {
1362 get_imported_mods(visible_mods
);
1363 if (!visible_mods
.has_key(this)) visible_mods
.add(this, 0);
1367 void Module::set_checksum(size_t checksum_len
,
1368 const unsigned char* checksum_ptr
)
1370 if (checksum_len
!= sizeof(module_checksum
))
1371 FATAL_ERROR("Module::set_checksum(): invalid length");
1372 memcpy(module_checksum
, checksum_ptr
, sizeof(module_checksum
));
1373 has_checksum
= true;
1376 void Module::set_controlns(char *ns
, char *prefix
)
1380 Free(control_ns_prefix
);
1381 control_ns_prefix
= prefix
;
1384 void Module::get_controlns(const char *&ns
, const char *&prefix
)
1387 prefix
= control_ns_prefix
;
1390 const size_t max_invented_prefixes
= 10000;
1391 void Module::add_namespace(const char *new_uri
, char *&new_prefix
)
1393 const bool prefix_is_empty
= new_prefix
&& !*new_prefix
;
1394 const string
key(new_prefix
? new_prefix
: "");
1395 if (new_prefix
&& !namespaces
.has_key(key
)) {
1396 namespaces
.add(key
, new_uri
);
1397 if (*new_prefix
== 0) { // first add of default namespace
1398 ++default_namespace_attempt
;
1400 return; // newly added
1402 else { // prefix already present (or we are required to invent one)
1404 const char *uri_value
= namespaces
[key
];
1405 if (!strcmp(uri_value
, new_uri
)) return; // same URI, same prefix: no-op
1408 // prefix already present but different URI,
1409 // or prefix is NULL (which means we must invent a prefix)
1411 if (new_prefix
&& *new_prefix
) {
1412 Free(new_prefix
); // prefix is not empty, discard it and start fresh
1413 new_prefix
= memptystr();
1416 const string
uri_key(new_uri
);
1417 if (invented_prefixes
.has_key(uri_key
)) {
1418 // we already made one up for this URI
1419 new_prefix
= mputstr(new_prefix
, invented_prefixes
[uri_key
]);
1420 return; // already there
1423 // make one up on the spot
1424 size_t iidx
= invented_prefixes
.size(); // "invented index"
1425 new_prefix
= mputprintf(new_prefix
, "tq%04lu", (unsigned long)iidx
++);
1426 string
made_up_prefix(new_prefix
);
1427 for (; iidx
< max_invented_prefixes
; ++iidx
) {
1428 if (namespaces
.has_key(made_up_prefix
)) {
1429 // Some pervert wrote an XSD with a namespace prefix like tq0007!
1430 // Make up another one in the same memory spot.
1431 sprintf(new_prefix
, "tq%04lu", (unsigned long)iidx
);
1432 made_up_prefix
= new_prefix
;
1437 if (iidx
>= max_invented_prefixes
) {
1438 Location loc
; // no particular location
1439 loc
.error("Internal limit: too many assigned prefixes");
1440 return; // not added
1442 invented_prefixes
.add(uri_key
, new_prefix
);
1443 namespaces
.add(made_up_prefix
, new_uri
);
1445 // Search for the newly added prefix and remember it.
1446 replacement_for_empty_prefix
= namespaces
.find_key(made_up_prefix
);
1448 if (prefix_is_empty
) {
1449 ++default_namespace_attempt
;
1451 return; // newly added
1456 static const string empty_prefix
;
1457 void Module::rename_default_namespace()
1459 if (default_namespace_attempt
< 2) return;
1460 // There was more than one default namespace. However, all but the first
1461 // are already renamed to tq%d.
1462 size_t di
= namespaces
.find_key(empty_prefix
); // keys are prefixes
1463 if (di
< namespaces
.size()) { // found it
1464 const char *last_remaining_def_namespace
= namespaces
.get_nth_elem(di
);
1465 // we can't change a key, we can only remove and re-add it
1466 namespaces
.erase(empty_prefix
);
1468 expstring_t empty_prefix_string
= NULL
; // force a made-up prefix
1469 add_namespace(last_remaining_def_namespace
, empty_prefix_string
);
1470 Free(empty_prefix_string
);
1472 else FATAL_ERROR("Module::rename_default_namespace");
1475 size_t Module::get_ns_index(const char *prefix
)
1477 size_t idx
= namespaces
.find_key(string(prefix
));
1478 if (idx
>= namespaces
.size()) { // not found
1479 // If the the caller asked for the empty prefix and it wasn't found
1480 // because it has been replaced, use the replacement.
1481 if (*prefix
== '\0' && replacement_for_empty_prefix
!= (size_t)-1) {
1482 idx
= replacement_for_empty_prefix
;
1484 else FATAL_ERROR("Module::get_ns_index()");
1487 // Remember that the index is used by this module
1488 if (!used_namespaces
.has_key(idx
)) {
1489 used_namespaces
.add(idx
, NULL
);
1494 string
Module::get_temporary_id()
1496 static const string
tmp_prefix("tmp_");
1497 return tmp_prefix
+ Int2string(tmp_id_count
++);
1500 void Module::generate_code(CodeGenHelper
& cgh
)
1503 nof_notupdated_files
+= 2;
1504 DEBUG(1, "Code not generated for module `%s'.",
1505 modid
->get_dispname().c_str());
1508 DEBUG(1, "Generating code for module `%s'.",
1509 modid
->get_dispname().c_str());
1511 // TODO: Always assume to have circular imports until
1512 // full program optimization is available,
1513 // this increases the size of the generated code,
1514 // but otherwise it is possible to create uncompilable code:
1515 // 1) let the project of module A and B refer to each other,
1516 // 2) A refers B, and compile A
1517 // 3) edit B to refer to A and compile it ...
1518 // As the code for A can not be rewritten the code will not compile
1519 cgh
.add_module(modid
->get_name(), modid
->get_ttcnname(),
1520 moduletype
== MOD_TTCN
, true);
1521 cgh
.set_current_module(modid
->get_ttcnname());
1523 // language specific parts (definitions, imports, etc.)
1524 //generate_code_internal(&target); <- needed to pass cgh
1525 generate_code_internal(cgh
);
1527 output_struct
* output
= cgh
.get_current_outputstruct();
1530 generate_literals(output
);
1531 // module level entry points
1532 generate_functions(output
);
1533 // type conversion functions for type compatibility
1534 generate_conversion_functions(output
);
1536 /* generate the initializer function for the TTCN-3 profiler
1537 * (this is done at the end of the code generation, to make sure all code
1538 * lines have been added to the profiler database) */
1539 if (is_file_profiled(get_filename())) {
1540 output
->source
.global_vars
= mputstr(output
->source
.global_vars
,
1541 "\n/* Initializing TTCN-3 profiler */\n"
1542 "void init_ttcn3_profiler()\n"
1544 char* function_name
= 0;
1546 while(get_profiler_code_line(get_filename(), &function_name
, &line_no
)) {
1547 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
1548 " ttcn3_prof.create_line(ttcn3_prof.get_element(\"%s\"), %d);\n",
1549 get_filename(), line_no
);
1550 if (0 != function_name
) {
1551 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
1552 " ttcn3_prof.create_function(ttcn3_prof.get_element(\"%s\"), %d, \"%s\");\n",
1553 get_filename(), line_no
, function_name
);
1556 output
->source
.global_vars
= mputstr(output
->source
.global_vars
, "}\n\n");
1560 void Module::dump(unsigned level
) const
1562 DEBUG(level
, "Module: %s", get_modid().get_dispname().c_str());
1565 // =================================
1566 // ===== Assignments
1567 // =================================
1569 Assignments
*Assignments::get_scope_asss()
1574 Assignment
*Assignments::get_ass_bySRef(Ref_simple
*p_ref
)
1576 if (!p_ref
|| !parent_scope
)
1577 FATAL_ERROR("NULL parameter: Common::Assignments::get_ass_bySRef()");
1578 if (!p_ref
->get_modid()) {
1579 const Identifier
*id
= p_ref
->get_id();
1580 if (id
&& has_local_ass_withId(*id
)) return get_local_ass_byId(*id
);
1582 return parent_scope
->get_ass_bySRef(p_ref
);
1585 bool Assignments::has_ass_withId(const Identifier
& p_id
)
1587 if (has_local_ass_withId(p_id
)) return true;
1588 else if (parent_scope
) return parent_scope
->has_ass_withId(p_id
);
1592 // =================================
1594 // =================================
1596 Assignment::Assignment(asstype_t p_asstype
, Identifier
*p_id
)
1597 : asstype(p_asstype
), id(p_id
), my_scope(0), checked(false),
1598 visibilitytype(PUBLIC
)
1600 if (!id
) FATAL_ERROR("Assignment::Assignment(): NULL parameter");
1603 Assignment::Assignment(const Assignment
& p
)
1604 : Node(p
), Location(p
), asstype(p
.asstype
), id(p
.id
->clone()), my_scope(0),
1605 checked(false), visibilitytype(p
.visibilitytype
)
1610 Assignment::~Assignment()
1615 Assignment::asstype_t
Assignment::get_asstype() const
1620 const char *Assignment::get_assname() const
1622 switch (get_asstype()) {
1626 if (my_scope
&& my_scope
->get_scope_mod()->get_moduletype() ==
1627 Module::MOD_ASN
) return "value";
1628 else return "constant";
1630 return "erroneous assignment";
1632 return "information object class";
1634 return "information object";
1636 return "information object set";
1640 return "external constant";
1642 return "module parameter";
1643 case A_MODULEPAR_TEMP
:
1644 return "template module parameter";
1649 case A_VAR_TEMPLATE
:
1650 return "template variable";
1656 case A_FUNCTION_RVAL
:
1657 case A_FUNCTION_RTEMP
:
1659 case A_EXT_FUNCTION
:
1660 case A_EXT_FUNCTION_RVAL
:
1661 case A_EXT_FUNCTION_RTEMP
:
1662 return "external function";
1669 return "value parameter";
1671 return "`out' value parameter";
1672 case A_PAR_VAL_INOUT
:
1673 return "`inout' value parameter";
1674 case A_PAR_TEMPL_IN
:
1675 return "template parameter";
1676 case A_PAR_TEMPL_OUT
:
1677 return "`out' template parameter";
1678 case A_PAR_TEMPL_INOUT
:
1679 return "`inout' template parameter";
1681 return "timer parameter";
1683 return "port parameter";
1689 string
Assignment::get_description()
1691 string
ret_val(get_assname());
1697 case A_PAR_VAL_INOUT
:
1698 case A_PAR_TEMPL_IN
:
1699 case A_PAR_TEMPL_OUT
:
1700 case A_PAR_TEMPL_INOUT
:
1703 // parameter is identified using its id
1704 ret_val
+= id
->get_dispname();
1709 case A_VAR_TEMPLATE
:
1711 // these can be both local and global
1712 if (is_local()) ret_val
+= id
->get_dispname();
1713 else ret_val
+= get_fullname();
1716 // the rest is always global
1717 ret_val
+= get_fullname();
1723 void Assignment::set_my_scope(Scope
*p_scope
)
1728 bool Assignment::is_local() const
1733 Setting
*Assignment::get_Setting()
1735 FATAL_ERROR("Common::Assignment::get_Setting()");
1739 Type
*Assignment::get_Type()
1741 FATAL_ERROR("Common::Assignment::get_Type()");
1745 Value
*Assignment::get_Value()
1747 FATAL_ERROR("Common::Assignment::get_Value()");
1751 Ttcn::Template
*Assignment::get_Template()
1753 FATAL_ERROR("Common::Assignment::get_Template()");
1757 bool Assignment::get_lazy_eval() const
1759 FATAL_ERROR("Common::Assignment::get_lazy_eval()");
1763 Ttcn::FormalParList
*Assignment::get_FormalParList()
1768 Ttcn::ArrayDimensions
*Assignment::get_Dimensions()
1773 Type
*Assignment::get_RunsOnType()
1778 void Assignment::chk_ttcn_id()
1780 if(!my_scope
) return;
1781 if(!get_id().get_has_valid(Identifier::ID_TTCN
)
1782 && my_scope
->get_parent_scope()==my_scope
->get_scope_mod()
1783 // <internal> or <error> ...
1784 && my_scope
->get_scope_mod()->get_modid().get_dispname()[0]!='<')
1785 warning("The identifier `%s' is not reachable from TTCN-3",
1786 get_id().get_dispname().c_str());
1789 // *this is the (var/const/modulepar/etc.) definition we want to access.
1790 // p_scope is the location from where we want to reach the definition.
1791 string
Assignment::get_genname_from_scope(Scope
*p_scope
,
1792 const char *p_prefix
)
1794 if (!p_scope
|| !my_scope
)
1795 FATAL_ERROR("Assignment::get_genname_from_scope()");
1798 Module
*my_mod
= my_scope
->get_scope_mod_gen();
1799 if ((my_mod
!= p_scope
->get_scope_mod_gen()) &&
1800 !Asn::Assignments::is_spec_asss(my_mod
)) {
1801 // when the definition is referred from another module
1802 // the reference shall be qualified with the namespace of my module
1803 ret_val
= my_mod
->get_modid().get_name();
1806 if (p_prefix
) ret_val
+= p_prefix
;
1807 ret_val
+= get_genname();
1808 // add the cast to real type if its a lazy formal paramter
1812 case A_PAR_TEMPL_IN
:
1813 if (get_lazy_eval() && p_prefix
==NULL
) {
1814 Type
* type
= get_Type();
1815 string type_genname
= (asstype
==A_PAR_TEMPL_IN
) ? type
->get_genname_template(p_scope
) : type
->get_genname_value(p_scope
);
1816 ret_val
= string("((") + type_genname
+ string("&)") + ret_val
+ string(")");
1826 const char *Assignment::get_module_object_name()
1828 if (!my_scope
) FATAL_ERROR("Assignment::get_module_object_name()");
1829 return "module_object";
1832 void Assignment::use_as_lvalue(const Location
&)
1834 FATAL_ERROR("Common::Assignment::use_as_lvalue()");
1837 void Assignment::generate_code(output_struct
*, bool)
1841 void Assignment::generate_code(CodeGenHelper
&)
1845 void Assignment::dump(unsigned level
) const
1847 DEBUG(level
, "Assignment: %s (%d)",
1848 id
->get_dispname().c_str(), asstype
);
1851 Ttcn::Group
* Assignment::get_parent_group()
1856 } // namespace Common