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 ///////////////////////////////////////////////////////////////////////////////
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"
27 reffer::reffer(const char*) {}
31 // =================================
33 // =================================
36 : Node(), mods_v(), mods_m()
38 set_fullname(string('@'));
43 for(size_t i
= 0; i
< mods_v
.size(); i
++) delete mods_v
[i
];
48 Modules
*Modules::clone() const
50 FATAL_ERROR("Modules::clone()");
54 void Modules::add_mod(Module
*p_mod
)
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());
62 bool Modules::has_mod_withId(const Identifier
& p_modid
)
64 return mods_m
.has_key(p_modid
.get_name());
67 Module
* Modules::get_mod_byId(const Identifier
& p_modid
)
69 const string
& name
= p_modid
.get_name();
70 return mods_m
.has_key(name
)?mods_m
[name
]:0;
73 Assignment
* Modules::get_ass_bySRef(Ref_simple
*p_ref
)
76 FATAL_ERROR("NULL parameter: Common::Modules::get_ass_bySRef()");
77 const Identifier
*modid
=p_ref
->get_modid();
79 if(has_mod_withId(*modid
))
80 return get_mod_byId(*modid
)->get_ass_bySRef(p_ref
);
82 p_ref
->error("There is no module with identifier `%s'",
83 modid
->get_dispname().c_str());
88 p_ref
->error("`%s' entity not found in global scope",
89 p_ref
->get_dispname().c_str());
94 void Modules::chk_uniq()
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
109 mods_v
.replace(i
, 1);
112 } else mods_m
.add(name
, m
);
118 // first check the uniqueness of module names
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
);
128 //clear the reference chain, get a fresh start
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);
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
);
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
);
151 checked_modules
.clear();
154 void Modules::chk_top_level_pdus()
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",
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);
172 Identifier
modid(Identifier::ID_ASN
, pduname_mod
, true);
173 module
= get_mod_byId(modid
);
175 if (module
&& module
->get_moduletype() == Module::MOD_ASN
) {
176 pdu_id
= new Identifier(Identifier::ID_ASN
, pduname_id
, true);
180 Identifier
modid(Identifier::ID_TTCN
, pduname_mod
, true);
181 module
= get_mod_byId(modid
);
183 if (module
&& module
->get_moduletype() == Module::MOD_TTCN
) {
184 pdu_id
= new Identifier(Identifier::ID_TTCN
, pduname_id
, true);
188 Identifier
modid(Identifier::ID_NAME
, pduname_mod
, true);
189 module
= get_mod_byId(modid
);
192 pdu_id
= new Identifier(Identifier::ID_NAME
, pduname_id
, true);
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());
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
);
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());
213 } // for top-level pdus
216 void Modules::write_checksums()
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();
226 void Modules::generate_code(CodeGenHelper
& cgh
)
228 Common::Module::rename_default_namespace(); // if needed
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."
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
;
249 void Modules::dump(unsigned level
) const
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
);
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
);
266 void Modules::generate_json_schema(JSON_Tokenizer
& json
, map
<Type
*, JSON_Tokenizer
>& json_refs
)
268 for(size_t i
= 0; i
< mods_v
.size(); ++i
) {
269 mods_v
[i
]->generate_json_schema(json
, json_refs
);
274 // =================================
276 // =================================
278 ModuleVersion
Module::getVersion() const {
279 return ModuleVersion(product_number
, suffix
, release
, patch
, build
, extra
);
282 void Module::generate_literals(output_struct
*target
)
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
);
306 void Module::generate_bs_literals(char *&src
, char *&hdr
)
308 if (bs_literals
.size() == 0) return;
309 // indicates whether we have found at least one non-empty bitstring
310 bool is_nonempty
= false;
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");
319 src
= mputstr(src
, "static const unsigned char ");
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
);
331 if (j
> 0) src
= mputstr(src
, ", ");
332 src
= mputprintf(src
, "%d", value
);
334 src
= mputstr(src
, " }");
336 if (is_nonempty
) src
= mputstr(src
, ";\n");
337 for (size_t i
= 0; i
< bs_literals
.size(); i
++) {
339 src
= mputstr(src
, ",\n");
340 if (splitting
) hdr
= mputstr(hdr
, ",\n");
343 src
= mputprintf(src
, "%s const BITSTRING ",
344 splitting
? "extern" : "static");
345 if (splitting
) hdr
= mputstr(hdr
, "extern const BITSTRING ");
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
);
354 src
= mputstr(src
, ";\n");
355 if (splitting
) hdr
= mputstr(hdr
, ";\n");
358 void Module::generate_bp_literals(char *&src
, char *& /*hdr*/)
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
, ", ");
371 src
= mputc(src
, '0');
374 src
= mputc(src
, '1');
377 src
= mputc(src
, '2');
380 src
= mputc(src
, '3');
383 FATAL_ERROR("Invalid character in bitstring pattern.");
386 src
= mputstr(src
, " }");
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
);
396 src
= mputstr(src
, ";\n");
399 void Module::generate_hs_literals(char *&src
, char *&hdr
)
401 if (hs_literals
.size() == 0) return;
402 // indicates whether we have found at least one non-empty hexstring
403 bool is_nonempty
= false;
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");
414 src
= mputstr(src
, "static const unsigned char ");
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]);
430 if (j
> 0) src
= mputstr(src
, ", ");
431 src
= mputprintf(src
, "%u", value
);
433 src
= mputstr(src
, " }");
435 if (is_nonempty
) src
= mputstr(src
, ";\n");
436 for (size_t i
= 0; i
< hs_literals
.size(); i
++) {
438 src
= mputstr(src
, ",\n");
439 if (splitting
) hdr
= mputstr(hdr
, ",\n");
442 src
= mputprintf(src
, "%s const HEXSTRING ",
443 splitting
? "extern" : "static");
444 if (splitting
) hdr
= mputstr(hdr
, "extern const HEXSTRING ");
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
);
453 src
= mputstr(src
, ";\n");
454 if (splitting
) hdr
= mputstr(hdr
, ";\n");
457 void Module::generate_hp_literals(char *&src
, char *& /*hdr*/)
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
, ", ");
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
);
476 src
= mputstr(src
, " }");
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
);
486 src
= mputstr(src
, ";\n");
489 void Module::generate_os_literals(char *&src
, char *&hdr
)
491 if (os_literals
.size() == 0) return;
492 // indicates whether we have found at least one non-empty octetstring
493 bool is_nonempty
= false;
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");
505 src
= mputstr(src
, "static const unsigned char ");
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]));
515 src
= mputstr(src
, " }");
517 if (is_nonempty
) src
= mputstr(src
, ";\n");
518 for (size_t i
= 0; i
< os_literals
.size(); i
++) {
520 src
= mputstr(src
, ",\n");
521 if (splitting
) hdr
= mputstr(hdr
, ",\n");
524 src
= mputprintf(src
, "%s const OCTETSTRING ",
525 splitting
? "extern" : "static");
526 if (splitting
) hdr
= mputstr(hdr
, "extern const OCTETSTRING ");
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
);
535 src
= mputstr(src
, ";\n");
536 if (splitting
) hdr
= mputstr(hdr
, ";\n");
539 void Module::generate_op_literals(char *&src
, char *& /*hdr*/)
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
, ", ");
555 if (str_ptr
[j
] == '?') num
= 256;
556 else if (str_ptr
[j
] == '*') num
= 257;
559 num
= 16 * char_to_hexdigit(str_ptr
[j
]);
561 if (j
>= size
) FATAL_ERROR("Unexpected end of octetstring pattern.");
563 num
+= char_to_hexdigit(str_ptr
[j
]);
565 src
= mputprintf(src
, "%u", num
);
568 src
= mputstr(src
, " }");
569 pattern_lens
.add(new size_t(pattern_len
));
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
);
579 src
= mputstr(src
, ";\n");
580 for (size_t i
= 0; i
< pattern_lens
.size(); i
++) delete pattern_lens
[i
];
581 pattern_lens
.clear();
584 void Module::generate_cs_literals(char *&src
, char *&hdr
)
586 if (cs_literals
.size() == 0) return;
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();
596 src
= mputstr(src
, ",\n");
597 if (splitting
) hdr
= mputstr(hdr
, ",\n");
600 src
= mputprintf(src
, "%s const CHARSTRING ",
601 splitting
? "extern" : "static");
602 if (splitting
) hdr
= mputstr(hdr
, "extern const CHARSTRING ");
607 src
= mputprintf(src
, "%s(0, NULL)", str_name
);
610 src
= mputprintf(src
, "%s('", str_name
);
611 src
= Code::translate_character(src
, *str_ptr
, false);
612 src
= mputstr(src
, "')");
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
619 for (size_t j
= 0; j
< str_len
; j
++)
620 src
= Code::translate_character(src
, str_ptr
[j
], true);
621 src
= mputstr(src
, "\")");
624 if (splitting
) hdr
= mputstr(hdr
, str_name
);
626 src
= mputstr(src
, ";\n");
627 if (splitting
) hdr
= mputstr(hdr
, ";\n");
630 void Module::generate_pp_literals(char *&src
, char *&) // padding patterns
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
649 if (pattern_ptr
[8 * (nof_octets
- j
- 1) + k
] == '1') octet
|= 0x01;
651 src
= mputprintf(src
, "0x%02x", octet
);
653 src
= mputstr(src
, " }");
655 src
= mputstr(src
, ";\n");
658 void Module::generate_mp_literals(char *&src
, char *&) // matching patt.
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();
666 if (i
> 0) src
= mputstr(src
, ",\n");
667 else src
= mputstr(src
, "static const Token_Match ");
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" : "");
677 src
= mputstr(src
, ";\n");
680 void Module::generate_us_literals(char *&src
, char *&hdr
) // univ.cs
682 size_t n_literals
= us_literals
.size();
683 if (n_literals
== 0) return;
684 bool array_needed
= false;
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");
693 src
= mputstr(src
, "static const universal_char ");
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
);
704 src
= mputstr(src
, " }");
706 if (array_needed
) src
= mputstr(src
, ";\n");
707 for (size_t i
= 0; i
< n_literals
; i
++) {
709 src
= mputstr(src
, ",\n");
710 if (splitting
) hdr
= mputstr(hdr
, ",\n");
713 src
= mputprintf(src
, "%s const UNIVERSAL_CHARSTRING ",
714 splitting
? "extern" : "static");
715 if (splitting
) hdr
= mputstr(hdr
, "extern const UNIVERSAL_CHARSTRING ");
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
) {
722 src
= mputprintf(src
, "%s(0, (const universal_char*)NULL)", value_name
);
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
);
730 src
= mputprintf(src
, "%s(%lu, %s_uchars)", value_name
,
731 (unsigned long) value_size
, value_name
);
734 if (splitting
) hdr
= mputstr(hdr
, value_name
);
736 src
= mputstr(src
, ";\n");
737 if (splitting
) hdr
= mputstr(hdr
, ";\n");
740 void Module::generate_oid_literals(char *&src
, char *& /*hdr*/)
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 ");
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());
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
);
755 if (i
> 0) src
= mputstr(src
, ",\n");
756 else src
= mputstr(src
, "static const OBJID ");
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());
762 src
= mputstr(src
, ";\n");
765 void Module::generate_functions(output_struct
*output
)
767 bool tcov_enabled
= tcov_file_name
&& in_tcov_files(get_filename());
768 bool has_pre_init_before_tcov
= output
->functions
.pre_init
!= NULL
;
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()));
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"
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());
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());
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
;
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"
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());
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());
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;
861 // set_param function
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"
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"
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
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"
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
,
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
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"
913 Free(output
->functions
.init_comp
);
914 output
->functions
.init_comp
= NULL
;
915 has_init_comp
= true;
916 } else has_init_comp
= false;
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"
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"
932 Free(output
->functions
.start
);
933 output
->functions
.start
= NULL
;
935 } else has_start
= false;
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"
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
;
951 } else has_control
= false;
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",
963 output
->source
.string_literals
= mputstr(output
->source
.string_literals
,
966 const char *module_name
= modid
->get_name().c_str();
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
,
978 "// written by %s in " __FILE__
" at %d\n"
980 "static const size_t num_namespaces = %lu;\n"
982 , __FUNCTION__
, __LINE__
984 , (unsigned long)num_xml_namespaces
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());
996 output
->source
.global_vars
= mputstr(output
->source
.global_vars
,
997 " { NULL, NULL },\n"); // not used in this module
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
1009 output
->header
.global_vars
= mputprintf(output
->header
.global_vars
,
1010 "extern TTCN_Module %s;\n",
1013 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
1014 "TTCN_Module %s(\"%s\", __DATE__, __TIME__, %s, %s",
1017 modid
->get_dispname().c_str(),
1018 (has_checksum
? "module_checksum" : "NULL"),
1019 has_pre_init
? "pre_init_module" : "NULL");
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");
1026 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
, ", \"%s\"", product_number
);
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");
1041 // self checks for ASN.1 modules
1043 FATAL_ERROR("Module::generate_functions(): post_init function in ASN.1 module");
1045 FATAL_ERROR("Module::generate_functions(): set_param function in ASN.1 module");
1047 FATAL_ERROR("Module::generate_functions(): log_param function in ASN.1 module");
1049 FATAL_ERROR("Module::generate_functions(): init_comp function in ASN.1 module");
1051 FATAL_ERROR("Module::generate_functions(): startable function in ASN.1 module");
1053 FATAL_ERROR("Module::generate_functions(): control part in ASN.1 module");
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());
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
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
) : "");
1078 void Module::generate_conversion_functions(output_struct
*output
)
1080 for (size_t i
= 0; i
< type_conv_v
.size(); i
++)
1082 ->gen_conv_func(&output
->source
.static_conversion_function_prototypes
,
1083 &output
->source
.static_conversion_function_bodies
,
1087 string
Module::add_literal(map
<string
, string
>& literals
, const string
& str
,
1090 if (literals
.has_key(str
)) return *literals
[str
];
1092 string
*literal
= new string(prefix
+Int2string(literals
.size()));
1093 literals
.add(str
, literal
);
1098 void Module::clear_literals(map
<string
, string
>& literals
)
1100 for (size_t i
= 0; i
< literals
.size(); i
++)
1101 delete literals
.get_nth_elem(i
);
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;
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
)
1124 FATAL_ERROR("NULL parameter: Common::Module::Module()");
1125 memset(module_checksum
, 0, sizeof(module_checksum
));
1126 set_scopeMacro_name(modid
->get_dispname());
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();
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
1156 invented_prefixes
.clear();
1157 Free(product_number
);
1161 Type
*Module::get_address_type()
1163 FATAL_ERROR("Common::Module::get_address_type()");
1167 string
Module::add_ustring_literal(const ustring
& ustr
)
1169 if (us_literals
.has_key(ustr
)) return *us_literals
[ustr
];
1171 string
*literal
= new string("us_" + Int2string(us_literals
.size()));
1172 us_literals
.add(ustr
, literal
);
1177 string
Module::add_objid_literal(const string
& oi_str
, const size_t nof_elems
)
1179 if(oid_literals
.has_key(oi_str
)) return oid_literals
[oi_str
]->oid_id
;
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
;
1189 void Module::add_type_conv(TypeConv
*p_conv
)
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.
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.
1213 type_conv_v
.add(p_conv
);
1216 bool Module::needs_type_conv(Type
*p_from_type
, Type
*p_to_type
) const
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
)
1227 void Module::chk_recursive(module_set_t
& checked_modules
)
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
);
1239 // then check the module itself
1240 chk(); // this is the only virtual call
1243 bool Module::is_visible(Module
*m
)
1245 collect_visible_mods();
1246 return visible_mods
.has_key(m
);
1249 void Module::get_visible_mods(module_set_t
& p_visible_mods
)
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);
1258 get_imported_mods(p_visible_mods
);
1262 void Module::write_checksum()
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;
1271 if (!has_checksum
) {
1272 fputc('\n', stderr
);
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
]);
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
);
1288 fputc('\n', stderr
);
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
)
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>");
1304 if (product_number
!= NULL
) {
1305 ret_val
= mputstr(ret_val
, product_number
);
1307 ret_val
= mputprintf(ret_val
, "/%d", suffix
);
1309 ret_val
= mputc(ret_val
, ' ');
1312 char* build_str
= buildstr(build
);
1313 ret_val
= mputprintf(ret_val
, "R%u%c%s%s", release
, eri(patch
), build_str
, extra
? extra
: "");
1318 void Module::collect_visible_mods()
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);
1326 void Module::set_checksum(size_t checksum_len
,
1327 const unsigned char* checksum_ptr
)
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;
1335 void Module::set_controlns(char *ns
, char *prefix
)
1339 Free(control_ns_prefix
);
1340 control_ns_prefix
= prefix
;
1343 void Module::get_controlns(const char *&ns
, const char *&prefix
)
1346 prefix
= control_ns_prefix
;
1349 const size_t max_invented_prefixes
= 10000;
1350 void Module::add_namespace(const char *new_uri
, char *&new_prefix
)
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
;
1359 return; // newly added
1361 else { // prefix already present (or we are required to invent one)
1363 const char *uri_value
= namespaces
[key
];
1364 if (!strcmp(uri_value
, new_uri
)) return; // same URI, same prefix: no-op
1367 // prefix already present but different URI,
1368 // or prefix is NULL (which means we must invent a prefix)
1370 if (new_prefix
&& *new_prefix
) {
1371 Free(new_prefix
); // prefix is not empty, discard it and start fresh
1372 new_prefix
= memptystr();
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
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
;
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
1401 invented_prefixes
.add(uri_key
, new_prefix
);
1402 namespaces
.add(made_up_prefix
, new_uri
);
1404 // Search for the newly added prefix and remember it.
1405 replacement_for_empty_prefix
= namespaces
.find_key(made_up_prefix
);
1407 if (prefix_is_empty
) {
1408 ++default_namespace_attempt
;
1410 return; // newly added
1415 static const string empty_prefix
;
1416 void Module::rename_default_namespace()
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
);
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
);
1431 else FATAL_ERROR("Module::rename_default_namespace");
1434 size_t Module::get_ns_index(const char *prefix
)
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
;
1443 else FATAL_ERROR("Module::get_ns_index()");
1446 // Remember that the index is used by this module
1447 if (!used_namespaces
.has_key(idx
)) {
1448 used_namespaces
.add(idx
, NULL
);
1453 string
Module::get_temporary_id()
1455 static const string
tmp_prefix("tmp_");
1456 return tmp_prefix
+ Int2string(tmp_id_count
++);
1459 void Module::generate_code(CodeGenHelper
& cgh
)
1462 nof_notupdated_files
+= 2;
1463 DEBUG(1, "Code not generated for module `%s'.",
1464 modid
->get_dispname().c_str());
1467 DEBUG(1, "Generating code for module `%s'.",
1468 modid
->get_dispname().c_str());
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());
1482 // language specific parts (definitions, imports, etc.)
1483 //generate_code_internal(&target); <- needed to pass cgh
1484 generate_code_internal(cgh
);
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());
1494 void Module::dump(unsigned level
) const
1496 DEBUG(level
, "Module: %s", get_modid().get_dispname().c_str());
1499 // =================================
1500 // ===== Assignments
1501 // =================================
1503 Assignments
*Assignments::get_scope_asss()
1508 Assignment
*Assignments::get_ass_bySRef(Ref_simple
*p_ref
)
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
);
1516 return parent_scope
->get_ass_bySRef(p_ref
);
1519 bool Assignments::has_ass_withId(const Identifier
& p_id
)
1521 if (has_local_ass_withId(p_id
)) return true;
1522 else if (parent_scope
) return parent_scope
->has_ass_withId(p_id
);
1526 // =================================
1528 // =================================
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
)
1534 if (!id
) FATAL_ERROR("Assignment::Assignment(): NULL parameter");
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
)
1544 Assignment::~Assignment()
1549 Assignment::asstype_t
Assignment::get_asstype() const
1554 const char *Assignment::get_assname() const
1556 switch (get_asstype()) {
1560 if (my_scope
&& my_scope
->get_scope_mod()->get_moduletype() ==
1561 Module::MOD_ASN
) return "value";
1562 else return "constant";
1564 return "erroneous assignment";
1566 return "information object class";
1568 return "information object";
1570 return "information object set";
1574 return "external constant";
1576 return "module parameter";
1577 case A_MODULEPAR_TEMP
:
1578 return "template module parameter";
1583 case A_VAR_TEMPLATE
:
1584 return "template variable";
1590 case A_FUNCTION_RVAL
:
1591 case A_FUNCTION_RTEMP
:
1593 case A_EXT_FUNCTION
:
1594 case A_EXT_FUNCTION_RVAL
:
1595 case A_EXT_FUNCTION_RTEMP
:
1596 return "external function";
1603 return "value parameter";
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";
1615 return "timer parameter";
1617 return "port parameter";
1623 string
Assignment::get_description()
1625 string
ret_val(get_assname());
1631 case A_PAR_VAL_INOUT
:
1632 case A_PAR_TEMPL_IN
:
1633 case A_PAR_TEMPL_OUT
:
1634 case A_PAR_TEMPL_INOUT
:
1637 // parameter is identified using its id
1638 ret_val
+= id
->get_dispname();
1643 case A_VAR_TEMPLATE
:
1645 // these can be both local and global
1646 if (is_local()) ret_val
+= id
->get_dispname();
1647 else ret_val
+= get_fullname();
1650 // the rest is always global
1651 ret_val
+= get_fullname();
1657 void Assignment::set_my_scope(Scope
*p_scope
)
1662 bool Assignment::is_local() const
1667 Setting
*Assignment::get_Setting()
1669 FATAL_ERROR("Common::Assignment::get_Setting()");
1673 Type
*Assignment::get_Type()
1675 FATAL_ERROR("Common::Assignment::get_Type()");
1679 Value
*Assignment::get_Value()
1681 FATAL_ERROR("Common::Assignment::get_Value()");
1685 Ttcn::Template
*Assignment::get_Template()
1687 FATAL_ERROR("Common::Assignment::get_Template()");
1691 bool Assignment::get_lazy_eval() const
1693 FATAL_ERROR("Common::Assignment::get_lazy_eval()");
1697 Ttcn::FormalParList
*Assignment::get_FormalParList()
1702 Ttcn::ArrayDimensions
*Assignment::get_Dimensions()
1707 Type
*Assignment::get_RunsOnType()
1712 void Assignment::chk_ttcn_id()
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());
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
)
1728 if (!p_scope
|| !my_scope
)
1729 FATAL_ERROR("Assignment::get_genname_from_scope()");
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();
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
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(")");
1760 const char *Assignment::get_module_object_name()
1762 if (!my_scope
) FATAL_ERROR("Assignment::get_module_object_name()");
1763 return "module_object";
1766 void Assignment::use_as_lvalue(const Location
&)
1768 FATAL_ERROR("Common::Assignment::use_as_lvalue()");
1771 void Assignment::generate_code(output_struct
*, bool)
1775 void Assignment::generate_code(CodeGenHelper
&)
1779 void Assignment::dump(unsigned level
) const
1781 DEBUG(level
, "Assignment: %s (%d)",
1782 id
->get_dispname().c_str(), asstype
);
1785 Ttcn::Group
* Assignment::get_parent_group()
1790 } // namespace Common