1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
24 * Szabo, Janos Zoltan – initial implementation
26 * Zalanyi, Balazs Andor
29 ******************************************************************************/
34 #include "../common/dbgnew.hh"
36 #include "asn1/AST_asn1.hh"
37 #include "Identifier.hh"
39 #include "TypeCompat.hh"
43 #include "asn1/Object0.hh"
44 #include "PredefFunc.hh"
45 #include "../common/version.h"
46 #include "CodeGenHelper.hh"
48 #include "ttcn3/profiler.h"
50 reffer::reffer(const char*) {}
54 // =================================
56 // =================================
58 vector
<Modules::type_enc_t
> Modules::delayed_type_enc_v
;
61 : Node(), mods_v(), mods_m()
63 set_fullname(string('@'));
68 for(size_t i
= 0; i
< mods_v
.size(); i
++) delete mods_v
[i
];
73 Modules
*Modules::clone() const
75 FATAL_ERROR("Modules::clone()");
79 void Modules::add_mod(Module
*p_mod
)
81 if (!p_mod
) FATAL_ERROR("NULL parameter: Common::Modules::add_mod()");
82 p_mod
->set_fullname("@"+p_mod
->get_modid().get_dispname());
83 p_mod
->set_scope_name(p_mod
->get_modid().get_dispname());
87 bool Modules::has_mod_withId(const Identifier
& p_modid
)
89 return mods_m
.has_key(p_modid
.get_name());
92 Module
* Modules::get_mod_byId(const Identifier
& p_modid
)
94 const string
& name
= p_modid
.get_name();
95 return mods_m
.has_key(name
)?mods_m
[name
]:0;
98 Assignment
* Modules::get_ass_bySRef(Ref_simple
*p_ref
)
101 FATAL_ERROR("NULL parameter: Common::Modules::get_ass_bySRef()");
102 const Identifier
*modid
=p_ref
->get_modid();
104 if(has_mod_withId(*modid
))
105 return get_mod_byId(*modid
)->get_ass_bySRef(p_ref
);
107 p_ref
->error("There is no module with identifier `%s'",
108 modid
->get_dispname().c_str());
113 p_ref
->error("`%s' entity not found in global scope",
114 p_ref
->get_dispname().c_str());
119 void Modules::chk_uniq()
121 for(size_t i
= 0; i
< mods_v
.size(); i
++) {
122 Module
*m
= mods_v
[i
];
123 const Identifier
& id
= m
->get_modid();
124 const string
& name
= id
.get_name();
125 if (mods_m
.has_key(name
)) {
126 Module
*m2
= mods_m
[name
];
127 m
->error("A module with identifier `%s' already exists",
128 id
.get_dispname().c_str());
129 m2
->error("This is the first module with the same name");
130 if (m
->get_moduletype() == m2
->get_moduletype() &&
131 !strcmp(m
->get_filename(), m2
->get_filename())) {
132 // the same file was given twice -> drop the entire module
134 mods_v
.replace(i
, 1);
137 } else mods_m
.add(name
, m
);
143 // first check the uniqueness of module names
145 // check the import chains
146 size_t nof_mods
= mods_v
.size();
147 for (size_t i
= 0; i
< nof_mods
; i
++) {
148 Module
*m
= mods_v
[i
];
149 ReferenceChain
refch(m
, "While checking import chains");
150 vector
<Common::Module
> modules
;
151 m
->chk_imp(refch
, modules
);
153 //clear the reference chain, get a fresh start
157 Module::module_set_t checked_modules
;
158 if (nof_top_level_pdus
> 0) {
159 chk_top_level_pdus();
160 // do not check ASN.1 modules, but assume they are already checked
161 for (size_t i
= 0; i
< nof_mods
; i
++) {
162 Module
*module
= mods_v
[i
];
163 if (module
->get_moduletype() == Module::MOD_ASN
)
164 checked_modules
.add(module
, 0);
166 for (size_t i
= 0; i
< nof_mods
; i
++) {
167 Module
*module
= mods_v
[i
];
168 if (module
->get_moduletype() != Module::MOD_ASN
)
169 module
->chk_recursive(checked_modules
);
172 // walk through all modules in bottom-up order
173 for (size_t i
= 0; i
< nof_mods
; i
++)
174 mods_v
[i
]->chk_recursive(checked_modules
);
176 checked_modules
.clear();
177 // run delayed Type::chk_coding() calls
178 if (!delayed_type_enc_v
.empty()) {
179 for (size_t i
= 0; i
< delayed_type_enc_v
.size(); ++i
) {
180 delayed_type_enc_v
[i
]->t
->chk_coding(delayed_type_enc_v
[i
]->enc
, true);
181 delete delayed_type_enc_v
[i
];
183 delayed_type_enc_v
.clear();
187 void Modules::chk_top_level_pdus()
189 Location
loc("<command line>");
190 for(size_t i
=0; i
<nof_top_level_pdus
; i
++) {
191 string
pduname(top_level_pdu
[i
]);
192 size_t dotpos
=pduname
.find('.');
193 if(dotpos
>=pduname
.size()) {
194 loc
.error("While searching top-level pdu `%s': "
195 "Please use the `modulename.identifier' format",
200 Identifier
*pdu_id
=0;
201 { // searching the module
202 const string
& pduname_mod
= pduname
.substr(0, dotpos
);
203 const string
& pduname_id
= pduname
.substr(dotpos
+ 1);
205 Identifier
modid(Identifier::ID_ASN
, pduname_mod
, true);
206 module
= get_mod_byId(modid
);
208 if (module
&& module
->get_moduletype() == Module::MOD_ASN
) {
209 pdu_id
= new Identifier(Identifier::ID_ASN
, pduname_id
, true);
213 Identifier
modid(Identifier::ID_TTCN
, pduname_mod
, true);
214 module
= get_mod_byId(modid
);
216 if (module
&& module
->get_moduletype() == Module::MOD_TTCN
) {
217 pdu_id
= new Identifier(Identifier::ID_TTCN
, pduname_id
, true);
221 Identifier
modid(Identifier::ID_NAME
, pduname_mod
, true);
222 module
= get_mod_byId(modid
);
225 pdu_id
= new Identifier(Identifier::ID_NAME
, pduname_id
, true);
228 // error - no such module
229 loc
.error("While searching top-level pdu `%s': "
230 "No module with name `%s'",
231 pduname
.c_str(), pduname_mod
.c_str());
235 Assignments
*asss
=module
->get_asss();
236 if(asss
->has_local_ass_withId(*pdu_id
)) {
237 Assignment
*ass
=asss
->get_local_ass_byId(*pdu_id
);
241 loc
.error("While searching top-level pdu `%s': "
242 "No assignment with identifier `%s'",
243 pduname
.c_str(), pdu_id
->get_dispname().c_str());
246 } // for top-level pdus
249 void Modules::write_checksums()
251 fputs("Module name Language MD5 checksum Version\n"
252 "---------------------------------------------------------------------------\n", stderr
);
253 size_t nof_mods
= mods_v
.size();
254 for (size_t i
= 0; i
< nof_mods
; i
++) {
255 mods_v
[i
]->write_checksum();
259 void Modules::generate_code(CodeGenHelper
& cgh
)
261 Common::Module::rename_default_namespace(); // if needed
263 The White Rabbit put on his spectacles.
264 "Where shall I begin, please your Majesty ?" he asked.
265 "Begin at the beginning,", the King said, very gravely, "and go on
266 till you come to the end: then stop."
269 for (size_t i
= 0; i
< mods_v
.size(); i
++) {
270 mods_v
[i
]->generate_code(cgh
);
271 if (tcov_file_name
&& in_tcov_files(mods_v
[i
]->get_filename())) {
272 Free(effective_module_lines
);
273 Free(effective_module_functions
);
274 effective_module_lines
= effective_module_functions
= NULL
;
282 void Modules::dump(unsigned level
) const
284 DEBUG(level
, "Modules (%lu pcs.)", (unsigned long) mods_v
.size());
285 for(size_t i
= 0; i
< mods_v
.size(); i
++) mods_v
[i
]->dump(level
);
288 std::set
<ModuleVersion
> Modules::getVersionsWithProductNumber() const {
289 std::set
<ModuleVersion
> versions
;
290 for (size_t i
= 0; i
< mods_v
.size(); ++i
) {
291 const ModuleVersion version
= mods_v
[i
]->getVersion();
292 if (version
.hasProductNumber()) {
293 versions
.insert(version
);
299 void Modules::generate_json_schema(JSON_Tokenizer
& json
, map
<Type
*, JSON_Tokenizer
>& json_refs
)
301 for(size_t i
= 0; i
< mods_v
.size(); ++i
) {
302 mods_v
[i
]->generate_json_schema(json
, json_refs
);
306 void Modules::delay_type_encode_check(Type
* p_type
, bool p_encode
)
308 type_enc_t
* elem
= new type_enc_t
;
310 elem
->enc
= p_encode
;
311 delayed_type_enc_v
.add(elem
);
315 // =================================
317 // =================================
319 ModuleVersion
Module::getVersion() const {
320 return ModuleVersion(product_number
, suffix
, release
, patch
, build
, extra
);
323 void Module::generate_literals(output_struct
*target
)
327 generate_bs_literals(src
, hdr
); // implementations follow directly below
328 generate_bp_literals(src
, hdr
);
329 generate_hs_literals(src
, hdr
);
330 generate_hp_literals(src
, hdr
);
331 generate_os_literals(src
, hdr
);
332 generate_op_literals(src
, hdr
);
333 generate_cs_literals(src
, hdr
);
334 generate_us_literals(src
, hdr
);
335 generate_oid_literals(src
, hdr
);
336 generate_pp_literals(src
, hdr
);
337 generate_mp_literals(src
, hdr
);
338 target
->source
.string_literals
=
339 mputstr(target
->source
.string_literals
, src
);
340 if (CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE
) {
341 target
->header
.global_vars
= mputstr(target
->header
.global_vars
, hdr
);
347 void Module::generate_bs_literals(char *&src
, char *&hdr
)
349 if (bs_literals
.size() == 0) return;
350 // indicates whether we have found at least one non-empty bitstring
351 bool is_nonempty
= false;
353 CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE
;
354 for (size_t i
= 0; i
< bs_literals
.size(); i
++) {
355 const string
& str
= bs_literals
.get_nth_key(i
);
356 size_t bits
= str
.size();
357 if (bits
== 0) continue;
358 if (is_nonempty
) src
= mputstr(src
, ",\n");
360 src
= mputprintf(src
, "%sconst unsigned char ", split_to_slices
? "" : "static ");
363 src
= mputprintf(src
, "%s_bits[] = { ",
364 bs_literals
.get_nth_elem(i
)->c_str());
365 // Filling up the octets one-by-one
366 for (size_t j
= 0; j
< (bits
+ 7) / 8; j
++) {
367 size_t offset
= 8 * j
;
368 unsigned char value
= 0;
369 for (size_t k
= 0; k
< 8 && k
< bits
- offset
; k
++) {
370 if (str
[offset
+ k
] == '1') value
|= (1 << k
);
372 if (j
> 0) src
= mputstr(src
, ", ");
373 src
= mputprintf(src
, "%d", value
);
375 src
= mputstr(src
, " }");
377 if (is_nonempty
) src
= mputstr(src
, ";\n");
378 for (size_t i
= 0; i
< bs_literals
.size(); i
++) {
380 src
= mputstr(src
, ",\n");
381 if (splitting
) hdr
= mputstr(hdr
, ",\n");
384 src
= mputprintf(src
, "%s const BITSTRING ",
385 splitting
? "extern" : "static");
386 if (splitting
) hdr
= mputstr(hdr
, "extern const BITSTRING ");
388 size_t bits
= bs_literals
.get_nth_key(i
).size();
389 const char *object_name
= bs_literals
.get_nth_elem(i
)->c_str();
390 if (bits
> 0) src
= mputprintf(src
, "%s(%lu, %s_bits)",
391 object_name
, (unsigned long) bits
, object_name
);
392 else src
= mputprintf(src
, "%s(0, NULL)", object_name
);
393 if (splitting
) hdr
= mputstr(hdr
, object_name
);
395 src
= mputstr(src
, ";\n");
396 if (splitting
) hdr
= mputstr(hdr
, ";\n");
399 void Module::generate_bp_literals(char *&src
, char *& hdr
)
401 if (bp_literals
.size() == 0) return;
402 for (size_t i
= 0; i
< bp_literals
.size(); i
++) {
403 if (i
> 0) src
= mputstr(src
, ",\n");
405 src
= mputprintf(src
, "%sconst unsigned char ", split_to_slices
? "" : "static ");
407 src
= mputprintf(src
, "%s_elements[] = { ",
408 bp_literals
.get_nth_elem(i
)->c_str());
409 const string
& str
= bp_literals
.get_nth_key(i
);
410 for (size_t j
= 0; j
< str
.size(); j
++) {
411 if (j
> 0) src
= mputstr(src
, ", ");
414 src
= mputc(src
, '0');
417 src
= mputc(src
, '1');
420 src
= mputc(src
, '2');
423 src
= mputc(src
, '3');
426 FATAL_ERROR("Invalid character in bitstring pattern.");
429 src
= mputstr(src
, " }");
431 src
= mputstr(src
, ";\n");
432 for (size_t i
= 0; i
< bp_literals
.size(); i
++) {
434 src
= mputstr(src
, ",\n");
435 if (split_to_slices
) {
436 hdr
= mputstr(hdr
, ",\n");
440 src
= mputprintf(src
, "%sconst BITSTRING_template ", split_to_slices
? "" : "static ");
441 if (split_to_slices
) {
442 hdr
= mputprintf(hdr
, "extern const BITSTRING_template ");
445 const char *name
= bp_literals
.get_nth_elem(i
)->c_str();
446 src
= mputprintf(src
, "%s(%lu, %s_elements)",
447 name
, (unsigned long) bp_literals
.get_nth_key(i
).size(), name
);
448 if (split_to_slices
) {
449 hdr
= mputstr(hdr
, name
);
452 src
= mputstr(src
, ";\n");
453 if (split_to_slices
) {
454 hdr
= mputstr(hdr
, ";\n");
458 void Module::generate_hs_literals(char *&src
, char *&hdr
)
460 if (hs_literals
.size() == 0) return;
461 // indicates whether we have found at least one non-empty hexstring
462 bool is_nonempty
= false;
464 CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE
;
465 for (size_t i
= 0; i
< hs_literals
.size(); i
++) {
466 const string
& str
= hs_literals
.get_nth_key(i
);
467 size_t nibbles
= str
.size();
468 if (nibbles
== 0) continue;
469 size_t octets
= (nibbles
+ 1) / 2;
470 const char *str_ptr
= str
.c_str();
471 if (is_nonempty
) src
= mputstr(src
, ",\n");
473 src
= mputprintf(src
, "%sconst unsigned char ", split_to_slices
? "" : "static ");
476 src
= mputprintf(src
, "%s_nibbles[] = { ",
477 hs_literals
.get_nth_elem(i
)->c_str());
478 for (size_t j
= 0; j
< octets
; j
++) {
479 // Hex digit with even index always goes to the least significant
480 // 4 bits of the octet.
481 unsigned char value
= char_to_hexdigit(str_ptr
[2 * j
]);
482 if (2 * j
+ 1 < nibbles
) {
483 // Hex digit with odd index always goes to the most significant
484 // 4 bits of the octet.
485 // This digit is not present (bits are set to zero) if the length
486 // of hexstring is odd.
487 value
+= 16 * char_to_hexdigit(str_ptr
[2 * j
+ 1]);
489 if (j
> 0) src
= mputstr(src
, ", ");
490 src
= mputprintf(src
, "%u", value
);
492 src
= mputstr(src
, " }");
494 if (is_nonempty
) src
= mputstr(src
, ";\n");
495 for (size_t i
= 0; i
< hs_literals
.size(); i
++) {
497 src
= mputstr(src
, ",\n");
498 if (splitting
) hdr
= mputstr(hdr
, ",\n");
501 src
= mputprintf(src
, "%s const HEXSTRING ",
502 splitting
? "extern" : "static");
503 if (splitting
) hdr
= mputstr(hdr
, "extern const HEXSTRING ");
505 size_t nibbles
= hs_literals
.get_nth_key(i
).size();
506 const char *object_name
= hs_literals
.get_nth_elem(i
)->c_str();
507 if (nibbles
> 0) src
= mputprintf(src
, "%s(%lu, %s_nibbles)",
508 object_name
, (unsigned long) nibbles
, object_name
);
509 else src
= mputprintf(src
, "%s(0, NULL)", object_name
);
510 if (splitting
) hdr
= mputstr(hdr
, object_name
);
512 src
= mputstr(src
, ";\n");
513 if (splitting
) hdr
= mputstr(hdr
, ";\n");
516 void Module::generate_hp_literals(char *&src
, char *& hdr
)
518 if (hp_literals
.size() == 0) return;
519 for (size_t i
= 0; i
< hp_literals
.size(); i
++) {
521 src
= mputstr(src
, ",\n");
523 src
= mputprintf(src
, "%sconst unsigned char ", split_to_slices
? "" : "static ");
525 src
= mputprintf(src
, "%s_elements[] = { ",
526 hp_literals
.get_nth_elem(i
)->c_str());
527 const string
& str
= hp_literals
.get_nth_key(i
);
528 size_t size
= str
.size();
529 const char *str_ptr
= str
.c_str();
530 for (size_t j
= 0; j
< size
; j
++) {
531 if (j
> 0) src
= mputstr(src
, ", ");
533 if (str_ptr
[j
] == '?') num
= 16;
534 else if (str_ptr
[j
] == '*') num
= 17;
535 else num
= char_to_hexdigit(str_ptr
[j
]);
536 src
= mputprintf(src
, "%u", num
);
538 src
= mputstr(src
, " }");
540 src
= mputstr(src
, ";\n");
541 for (size_t i
= 0; i
< hp_literals
.size(); i
++) {
543 src
= mputstr(src
, ",\n");
544 if (split_to_slices
) {
545 hdr
= mputstr(hdr
, ",\n");
548 src
= mputprintf(src
, "%sconst HEXSTRING_template ", split_to_slices
? "" : "static ");
549 if (split_to_slices
) {
550 hdr
= mputprintf(hdr
, "extern const HEXSTRING_template ");
553 const char *name
= hp_literals
.get_nth_elem(i
)->c_str();
554 src
= mputprintf(src
, "%s(%lu, %s_elements)",
555 name
, (unsigned long) hp_literals
.get_nth_key(i
).size(), name
);
556 if (split_to_slices
) {
557 hdr
= mputstr(hdr
, name
);
560 src
= mputstr(src
, ";\n");
561 if (split_to_slices
) {
562 hdr
= mputstr(hdr
, ";\n");
566 void Module::generate_os_literals(char *&src
, char *&hdr
)
568 if (os_literals
.size() == 0) return;
569 // indicates whether we have found at least one non-empty octetstring
570 bool is_nonempty
= false;
572 CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE
;
573 for (size_t i
= 0; i
< os_literals
.size(); i
++) {
574 const string
& str
= os_literals
.get_nth_key(i
);
575 size_t size
= str
.size();
576 if (size
% 2) FATAL_ERROR("Invalid length for an octetstring.");
577 size_t octets
= size
/ 2;
578 if (octets
== 0) continue;
579 const char *str_ptr
= str
.c_str();
580 if (is_nonempty
) src
= mputstr(src
, ",\n");
582 src
= mputprintf(src
, "%sconst unsigned char ", split_to_slices
? "" : "static ");
585 src
= mputprintf(src
, "%s_octets[] = { ",
586 os_literals
.get_nth_elem(i
)->c_str());
587 for (size_t j
= 0; j
< octets
; j
++) {
588 if (j
> 0) src
= mputstr(src
, ", ");
589 src
= mputprintf(src
, "%u", 16 * char_to_hexdigit(str_ptr
[2 * j
]) +
590 char_to_hexdigit(str_ptr
[2 * j
+ 1]));
592 src
= mputstr(src
, " }");
594 if (is_nonempty
) src
= mputstr(src
, ";\n");
595 for (size_t i
= 0; i
< os_literals
.size(); i
++) {
597 src
= mputstr(src
, ",\n");
598 if (splitting
) hdr
= mputstr(hdr
, ",\n");
601 src
= mputprintf(src
, "%s const OCTETSTRING ",
602 splitting
? "extern" : "static");
603 if (splitting
) hdr
= mputstr(hdr
, "extern const OCTETSTRING ");
605 size_t octets
= os_literals
.get_nth_key(i
).size() / 2;
606 const char *object_name
= os_literals
.get_nth_elem(i
)->c_str();
607 if (octets
> 0) src
= mputprintf(src
, "%s(%lu, %s_octets)",
608 object_name
, (unsigned long) octets
, object_name
);
609 else src
= mputprintf(src
, "%s(0, NULL)", object_name
);
610 if (splitting
) hdr
= mputstr(hdr
, object_name
);
612 src
= mputstr(src
, ";\n");
613 if (splitting
) hdr
= mputstr(hdr
, ";\n");
616 void Module::generate_op_literals(char *&src
, char *& hdr
)
618 if (op_literals
.size() == 0) return;
619 vector
<size_t> pattern_lens
;
620 for(size_t i
= 0; i
< op_literals
.size(); i
++) {
622 src
= mputstr(src
, ",\n");
624 src
= mputprintf(src
, "%sconst unsigned short ", split_to_slices
? "" : "static ");
626 src
= mputprintf(src
, "%s_elements[] = { ",
627 op_literals
.get_nth_elem(i
)->c_str());
628 const string
& str
= op_literals
.get_nth_key(i
);
629 size_t size
= str
.size();
630 size_t pattern_len
= 0;
631 const char *str_ptr
= str
.c_str();
632 for (size_t j
= 0; j
< size
; j
++) {
633 if (j
> 0) src
= mputstr(src
, ", ");
635 if (str_ptr
[j
] == '?') num
= 256;
636 else if (str_ptr
[j
] == '*') num
= 257;
639 num
= 16 * char_to_hexdigit(str_ptr
[j
]);
641 if (j
>= size
) FATAL_ERROR("Unexpected end of octetstring pattern.");
643 num
+= char_to_hexdigit(str_ptr
[j
]);
645 src
= mputprintf(src
, "%u", num
);
648 src
= mputstr(src
, " }");
649 pattern_lens
.add(new size_t(pattern_len
));
651 src
= mputstr(src
, ";\n");
652 for (size_t i
= 0; i
< op_literals
.size(); i
++) {
654 src
= mputstr(src
, ",\n");
655 if (split_to_slices
) {
656 hdr
= mputstr(hdr
, ",\n");
660 src
= mputprintf(src
, "%sconst OCTETSTRING_template ", split_to_slices
? "" : "static ");
661 if (split_to_slices
) {
662 hdr
= mputprintf(hdr
, "extern const OCTETSTRING_template ");
665 const char *name
= op_literals
.get_nth_elem(i
)->c_str();
666 src
= mputprintf(src
, "%s(%lu, %s_elements)",
667 name
, (unsigned long) *pattern_lens
[i
], name
);
668 if (split_to_slices
) {
669 hdr
= mputstr(hdr
, name
);
672 src
= mputstr(src
, ";\n");
673 if (split_to_slices
) {
674 hdr
= mputstr(hdr
, ";\n");
676 for (size_t i
= 0; i
< pattern_lens
.size(); i
++) delete pattern_lens
[i
];
677 pattern_lens
.clear();
680 void Module::generate_cs_literals(char *&src
, char *&hdr
)
682 if (cs_literals
.size() == 0) return;
684 CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE
;
685 for (size_t i
= 0; i
< cs_literals
.size(); i
++) {
686 const string
& str
= cs_literals
.get_nth_key(i
);
687 size_t str_len
= str
.size();
688 const char *str_ptr
= str
.c_str();
689 const char *str_name
= cs_literals
.get_nth_elem(i
)->c_str();
692 src
= mputstr(src
, ",\n");
693 if (splitting
) hdr
= mputstr(hdr
, ",\n");
696 src
= mputprintf(src
, "%s const CHARSTRING ",
697 splitting
? "extern" : "static");
698 if (splitting
) hdr
= mputstr(hdr
, "extern const CHARSTRING ");
703 src
= mputprintf(src
, "%s(0, NULL)", str_name
);
706 src
= mputprintf(src
, "%s('", str_name
);
707 src
= Code::translate_character(src
, *str_ptr
, false);
708 src
= mputstr(src
, "')");
711 src
= mputprintf(src
, "%s(%lu, \"", str_name
, (unsigned long) str_len
);
712 // Note: Code::translate_string() is not suitable because the string
713 // may contain NUL characters at which translate_string() stops
715 for (size_t j
= 0; j
< str_len
; j
++)
716 src
= Code::translate_character(src
, str_ptr
[j
], true);
717 src
= mputstr(src
, "\")");
720 if (splitting
) hdr
= mputstr(hdr
, str_name
);
722 src
= mputstr(src
, ";\n");
723 if (splitting
) hdr
= mputstr(hdr
, ";\n");
726 void Module::generate_pp_literals(char *&src
, char *&) // padding patterns
728 if (pp_literals
.size() == 0) return;
729 for (size_t i
= 0; i
< pp_literals
.size(); i
++) {
730 const string
& pattern
= pp_literals
.get_nth_key(i
);
731 size_t pattern_len
= pattern
.size();
732 const char *pattern_ptr
= pattern
.c_str();
734 src
= mputstr(src
, ",\n");
737 src
= mputprintf(src
, "%sconst unsigned char ", split_to_slices
? "" : "static ");
739 src
= mputprintf(src
, "%s[] = { ", pp_literals
.get_nth_elem(i
)->c_str());
740 if (pattern_len
% 8 != 0) FATAL_ERROR("Module::generate_pp_literals()");
741 size_t nof_octets
= pattern_len
/ 8;
742 for (size_t j
= 0; j
< nof_octets
; j
++) {
743 if (j
> 0) src
= mputstr(src
, ", ");
744 unsigned char octet
= 0;
745 for (size_t k
= 0; k
< 8; k
++) {
746 // take the octets in reverse order
747 // MSB is the first character of the string
749 if (pattern_ptr
[8 * (nof_octets
- j
- 1) + k
] == '1') octet
|= 0x01;
751 src
= mputprintf(src
, "0x%02x", octet
);
753 src
= mputstr(src
, " }");
755 src
= mputstr(src
, ";\n");
758 void Module::generate_mp_literals(char *&src
, char *&) // matching patt.
760 if (mp_literals
.size() == 0) return;
761 for (size_t i
= 0; i
< mp_literals
.size(); i
++) {
762 const string
& str
= mp_literals
.get_nth_key(i
);
763 if (str
.size() < 1) FATAL_ERROR("Module::generate_mp_literals()");
764 const char *str_ptr
= str
.c_str();
766 if (i
> 0) src
= mputstr(src
, ",\n");
767 else src
= mputprintf(src
, "%sconst Token_Match ", split_to_slices
? "" : "static ");
769 src
= mputprintf(src
, "%s(\"", mp_literals
.get_nth_elem(i
)->c_str());
770 src
= Code::translate_string(src
, str_ptr
+ 1);
771 // The first character of the string is case-sensitiveness flag:
772 // 'I' for yes, 'N' for no,
773 // 'F' for fixed string matching which is always case sensitive.
774 src
= mputprintf(src
, "\", %s%s)", (str_ptr
[0]!='N') ? "TRUE" : "FALSE",
775 (str_ptr
[0] == 'F') ? ", TRUE" : "");
777 src
= mputstr(src
, ";\n");
780 void Module::generate_us_literals(char *&src
, char *&hdr
) // univ.cs
782 size_t n_literals
= us_literals
.size();
783 if (n_literals
== 0) return;
784 bool array_needed
= false;
786 CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE
;
787 for (size_t i
= 0; i
< n_literals
; i
++) {
788 const ustring
& value
= us_literals
.get_nth_key(i
);
789 size_t value_size
= value
.size();
790 if (value_size
< 2) continue;
791 if (array_needed
) src
= mputstr(src
, ",\n");
793 src
= mputprintf(src
, "%sconst universal_char ", split_to_slices
? "" : "static ");
796 src
= mputprintf(src
, "%s_uchars[] = { ",
797 us_literals
.get_nth_elem(i
)->c_str());
798 const ustring::universal_char
*uchars_ptr
= value
.u_str();
799 for (size_t j
= 0; j
< value_size
; j
++) {
800 if (j
> 0) src
= mputstr(src
, ", ");
801 src
= mputprintf(src
, "{ %u, %u, %u, %u }", uchars_ptr
[j
].group
,
802 uchars_ptr
[j
].plane
, uchars_ptr
[j
].row
, uchars_ptr
[j
].cell
);
804 src
= mputstr(src
, " }");
806 if (array_needed
) src
= mputstr(src
, ";\n");
807 for (size_t i
= 0; i
< n_literals
; i
++) {
809 src
= mputstr(src
, ",\n");
810 if (splitting
) hdr
= mputstr(hdr
, ",\n");
813 src
= mputprintf(src
, "%s const UNIVERSAL_CHARSTRING ",
814 splitting
? "extern" : "static");
815 if (splitting
) hdr
= mputstr(hdr
, "extern const UNIVERSAL_CHARSTRING ");
817 const char *value_name
= us_literals
.get_nth_elem(i
)->c_str();
818 const ustring
& value
= us_literals
.get_nth_key(i
);
819 size_t value_size
= value
.size();
820 switch (value_size
) {
822 src
= mputprintf(src
, "%s(0, (const universal_char*)NULL)", value_name
);
825 const ustring::universal_char
& uchar
= value
.u_str()[0];
826 src
= mputprintf(src
, "%s(%u, %u, %u, %u)", value_name
,
827 uchar
.group
, uchar
.plane
, uchar
.row
, uchar
.cell
);
830 src
= mputprintf(src
, "%s(%lu, %s_uchars)", value_name
,
831 (unsigned long) value_size
, value_name
);
834 if (splitting
) hdr
= mputstr(hdr
, value_name
);
836 src
= mputstr(src
, ";\n");
837 if (splitting
) hdr
= mputstr(hdr
, ";\n");
840 void Module::generate_oid_literals(char *&src
, char *& hdr
)
842 if (oid_literals
.size() == 0) return;
843 for (size_t i
= 0; i
< oid_literals
.size(); i
++) {
844 if (i
> 0) src
= mputstr(src
, ",\n");
845 else src
= mputprintf(src
, "%sconst OBJID::objid_element ", split_to_slices
? "" : "static ");
847 src
= mputprintf(src
, "%s_comps[] = { %s }",
848 oid_literals
.get_nth_elem(i
)->oid_id
.c_str(),
849 oid_literals
.get_nth_key(i
).c_str());
851 src
= mputstr(src
, ";\n");
852 for(size_t i
= 0; i
< oid_literals
.size(); i
++) {
853 const OID_literal
*litstruct
= oid_literals
.get_nth_elem(i
);
856 src
= mputstr(src
, ",\n");
857 if (split_to_slices
) {
858 hdr
= mputstr(hdr
, ",\n");
862 src
= mputprintf(src
, "%sconst OBJID ", split_to_slices
? "" : "static ");
863 if (split_to_slices
) {
864 hdr
= mputstr(hdr
, "extern const OBJID ");
868 src
= mputprintf(src
, "%s(%lu, %s_comps)",
869 litstruct
->oid_id
.c_str(), (unsigned long) litstruct
->nof_elems
,
870 litstruct
->oid_id
.c_str());
871 if (split_to_slices
) {
872 hdr
= mputstr(hdr
, litstruct
->oid_id
.c_str());
875 src
= mputstr(src
, ";\n");
876 if (split_to_slices
) {
877 hdr
= mputstr(hdr
, ";\n");
881 void Module::generate_functions(output_struct
*output
)
883 bool tcov_enabled
= tcov_file_name
&& in_tcov_files(get_filename());
884 bool has_pre_init_before_tcov
= output
->functions
.pre_init
!= NULL
;
886 output
->functions
.pre_init
= mputprintf(output
->functions
.pre_init
,
887 "TTCN_Location_Statistics::init_file_lines(\"%s\", effective_module_lines, sizeof(effective_module_lines) / sizeof(int));\n" \
888 "TTCN_Location_Statistics::init_file_functions(\"%s\", effective_module_functions, sizeof(effective_module_functions) / sizeof(char *));\n",
889 get_tcov_file_name(get_filename()), get_tcov_file_name(get_filename()));
892 bool has_pre_init
= false;
893 bool profiled
= MOD_TTCN
== get_moduletype() && is_file_profiled(get_filename());
894 bool debugged
= debugger_active
&& MOD_TTCN
== get_moduletype();
895 // always generate pre_init_module if the file is profiled
896 if (output
->functions
.pre_init
|| profiled
|| debugged
) {
897 output
->source
.static_function_prototypes
=
898 mputprintf(output
->source
.static_function_prototypes
,
899 "%svoid pre_init_module();\n", split_to_slices
? "extern " : "static ");
900 output
->source
.static_function_bodies
= mputprintf(output
->source
.static_function_bodies
,
901 "%svoid pre_init_module()\n"
902 "{\n", split_to_slices
? "" : "static ");
903 if (include_location_info
) {
904 output
->source
.static_function_bodies
=
905 mputstr(output
->source
.static_function_bodies
,
906 (tcov_enabled
&& has_pre_init_before_tcov
) ? "TTCN_Location_Statistics current_location(\""
907 : "TTCN_Location current_location(\"");
908 output
->source
.static_function_bodies
=
909 Code::translate_string(output
->source
.static_function_bodies
, (tcov_enabled
&& has_pre_init_before_tcov
) ? get_tcov_file_name(get_filename()) : get_filename());
910 output
->source
.static_function_bodies
=
911 mputprintf(output
->source
.static_function_bodies
,
912 (tcov_enabled
&& has_pre_init_before_tcov
) ? "\", 0, TTCN_Location_Statistics::LOCATION_UNKNOWN, \"%s\");\n"
913 : "\", 0, TTCN_Location::LOCATION_UNKNOWN, \"%s\");\n", get_modid().get_dispname().c_str());
914 if (tcov_enabled
&& has_pre_init_before_tcov
) {
915 effective_module_lines
=
916 mputprintf(effective_module_lines
, "%s0",
917 (effective_module_lines
? ", " : ""));
918 effective_module_functions
=
919 mputprintf(effective_module_functions
, "%s\"%s\"",
920 (effective_module_functions
? ", " : ""), get_modid().get_dispname().c_str());
923 output
->source
.static_function_bodies
= mputprintf(output
->source
.static_function_bodies
,
924 "%s::init_ttcn3_profiler();\n"
925 "TTCN3_Stack_Depth stack_depth;\n"
926 "ttcn3_prof.execute_line(\"%s\", 0);\n", get_modid().get_name().c_str(), get_filename());
929 output
->source
.static_function_bodies
= mputprintf(output
->source
.static_function_bodies
,
930 "%s::init_ttcn3_debugger();\n", get_modid().get_name().c_str());
933 output
->source
.static_function_bodies
=
934 mputstr(output
->source
.static_function_bodies
, output
->functions
.pre_init
);
935 output
->source
.static_function_bodies
=
936 mputstr(output
->source
.static_function_bodies
, "}\n\n");
937 Free(output
->functions
.pre_init
);
938 output
->functions
.pre_init
= NULL
;
941 bool has_post_init_before_tcov
= output
->functions
.post_init
!= NULL
;
942 // post_init function
943 bool has_post_init
= false;
944 if (output
->functions
.post_init
) {
945 output
->source
.static_function_prototypes
= mputprintf(output
->source
.static_function_prototypes
,
946 "%svoid post_init_module();\n", split_to_slices
? "extern " : "static ");
947 output
->source
.static_function_bodies
= mputprintf(output
->source
.static_function_bodies
,
948 "%svoid post_init_module()\n"
949 "{\n", split_to_slices
? "" : "static ");
950 if (include_location_info
) {
951 output
->source
.static_function_bodies
=
952 mputstr(output
->source
.static_function_bodies
,
953 (tcov_enabled
&& has_post_init_before_tcov
) ? "TTCN_Location_Statistics current_location(\""
954 : "TTCN_Location current_location(\"");
955 output
->source
.static_function_bodies
=
956 Code::translate_string(output
->source
.static_function_bodies
, (tcov_enabled
&& has_post_init_before_tcov
) ? get_tcov_file_name(get_filename()) : get_filename());
957 output
->source
.static_function_bodies
=
958 mputprintf(output
->source
.static_function_bodies
,
959 (tcov_enabled
&& has_post_init_before_tcov
) ? "\", 0, TTCN_Location_Statistics::LOCATION_UNKNOWN, \"%s\");\n"
960 : "\", 0, TTCN_Location::LOCATION_UNKNOWN, \"%s\");\n", get_modid().get_dispname().c_str());
961 if (tcov_enabled
&& has_post_init_before_tcov
) {
962 effective_module_lines
=
963 mputprintf(effective_module_lines
, "%s0",
964 (effective_module_lines
? ", " : ""));
965 effective_module_functions
=
966 mputprintf(effective_module_functions
, "%s\"%s\"",
967 (effective_module_functions
? ", " : ""), get_modid().get_dispname().c_str());
969 if (MOD_TTCN
== get_moduletype() && is_file_profiled(get_filename())) {
970 output
->source
.static_function_bodies
= mputprintf(output
->source
.static_function_bodies
,
971 "TTCN3_Stack_Depth stack_depth;\n"
972 "ttcn3_prof.execute_line(\"%s\", 0);\n", get_filename());
975 output
->source
.static_function_bodies
=
976 mputstr(output
->source
.static_function_bodies
, output
->functions
.post_init
);
977 output
->source
.static_function_bodies
=
978 mputstr(output
->source
.static_function_bodies
, "}\n\n");
979 Free(output
->functions
.post_init
);
980 output
->functions
.post_init
= NULL
;
981 has_post_init
= true;
983 // set_param function
985 if (output
->functions
.set_param
) {
986 output
->source
.static_function_prototypes
= mputprintf(output
->source
.static_function_prototypes
,
987 "%sboolean set_module_param(Module_Param& param);\n", split_to_slices
? "extern " : "static ");
988 output
->source
.static_function_bodies
= mputprintf(output
->source
.static_function_bodies
,
989 "%sboolean set_module_param(Module_Param& param)\n"
991 "const char* const par_name = param.get_id()->get_current_name();\n", split_to_slices
? "" : "static ");
992 output
->source
.static_function_bodies
=
993 mputstr(output
->source
.static_function_bodies
, output
->functions
.set_param
);
994 output
->source
.static_function_bodies
=
995 mputstr(output
->source
.static_function_bodies
, "return FALSE;\n"
997 Free(output
->functions
.set_param
);
998 output
->functions
.set_param
= NULL
;
999 has_set_param
= true;
1000 } else has_set_param
= false;
1001 // get_param function
1003 if (output
->functions
.get_param
) {
1004 output
->source
.static_function_prototypes
= mputprintf(output
->source
.static_function_prototypes
,
1005 "%sModule_Param* get_module_param(Module_Param_Name& param_name);\n", split_to_slices
? "extern " : "static ");
1006 output
->source
.static_function_bodies
= mputprintf(output
->source
.static_function_bodies
,
1007 "%sModule_Param* get_module_param(Module_Param_Name& param_name)\n"
1009 "const char* const par_name = param_name.get_current_name();\n", split_to_slices
? "" : "static ");
1010 output
->source
.static_function_bodies
=
1011 mputstr(output
->source
.static_function_bodies
, output
->functions
.get_param
);
1012 output
->source
.static_function_bodies
=
1013 mputstr(output
->source
.static_function_bodies
, "return NULL;\n"
1015 Free(output
->functions
.get_param
);
1016 output
->functions
.get_param
= NULL
;
1017 has_get_param
= true;
1018 } else has_get_param
= false;
1019 // log_param function
1021 if (output
->functions
.log_param
) {
1022 output
->source
.static_function_prototypes
= mputprintf(output
->source
.static_function_prototypes
,
1023 "%svoid log_module_param();\n", split_to_slices
? "extern " : "static ");
1024 output
->source
.static_function_bodies
= mputprintf(output
->source
.static_function_bodies
,
1025 "%svoid log_module_param()\n"
1026 "{\n", split_to_slices
? "" : "static ");
1027 output
->source
.static_function_bodies
=
1028 mputstr(output
->source
.static_function_bodies
, output
->functions
.log_param
);
1029 output
->source
.static_function_bodies
= mputstr(output
->source
.static_function_bodies
,
1031 Free(output
->functions
.log_param
);
1032 output
->functions
.log_param
= NULL
;
1033 has_log_param
= true;
1034 } else has_log_param
= false;
1035 // init_comp function
1037 if (output
->functions
.init_comp
) {
1038 output
->source
.static_function_prototypes
=
1039 mputprintf(output
->source
.static_function_prototypes
,
1040 "%sboolean init_comp_type("
1041 "const char *component_type, boolean init_base_comps);\n", split_to_slices
? "extern " : "static ");
1042 output
->source
.static_function_bodies
=
1043 mputprintf(output
->source
.static_function_bodies
,
1044 "%sboolean init_comp_type(const char *component_type, "
1045 "boolean init_base_comps)\n"
1046 "{\n(void)init_base_comps;\n", split_to_slices
? "" : "static ");
1047 output
->source
.static_function_bodies
=
1048 mputstr(output
->source
.static_function_bodies
,
1049 output
->functions
.init_comp
);
1050 output
->source
.static_function_bodies
=
1051 mputstr(output
->source
.static_function_bodies
, "return FALSE;\n"
1053 Free(output
->functions
.init_comp
);
1054 output
->functions
.init_comp
= NULL
;
1055 has_init_comp
= true;
1056 } else has_init_comp
= false;
1059 if (output
->functions
.start
) {
1060 output
->source
.static_function_prototypes
= mputprintf(output
->source
.static_function_prototypes
,
1061 "%sboolean start_ptc_function(const char *function_name, "
1062 "Text_Buf& function_arguments);\n", split_to_slices
? "extern " : "static ");
1063 output
->source
.static_function_bodies
= mputprintf(output
->source
.static_function_bodies
,
1064 "%sboolean start_ptc_function(const char *function_name, "
1065 "Text_Buf& function_arguments)\n"
1066 "{\n", split_to_slices
? "" : "static ");
1067 output
->source
.static_function_bodies
=
1068 mputstr(output
->source
.static_function_bodies
, output
->functions
.start
);
1069 output
->source
.static_function_bodies
=
1070 mputstr(output
->source
.static_function_bodies
, "return FALSE;\n"
1072 Free(output
->functions
.start
);
1073 output
->functions
.start
= NULL
;
1075 } else has_start
= false;
1078 if (output
->functions
.control
) {
1079 output
->source
.static_function_prototypes
= mputprintf(output
->source
.static_function_prototypes
,
1080 "%svoid module_control_part();\n", split_to_slices
? "extern " : "static ");
1081 output
->source
.static_function_bodies
= mputprintf(output
->source
.static_function_bodies
,
1082 "%svoid module_control_part()\n"
1083 "{\n", split_to_slices
? "" : "static ");
1084 output
->source
.static_function_bodies
=
1085 mputstr(output
->source
.static_function_bodies
, output
->functions
.control
);
1086 output
->source
.static_function_bodies
=
1087 mputstr(output
->source
.static_function_bodies
, "}\n\n");
1088 Free(output
->functions
.control
);
1089 output
->functions
.control
= NULL
;
1091 } else has_control
= false;
1094 if (split_to_slices
) {
1095 output
->header
.global_vars
= mputprintf(output
->header
.global_vars
, "extern const unsigned char module_checksum[];\n");
1097 output
->source
.string_literals
= mputprintf(output
->source
.string_literals
,
1098 "%sconst unsigned char module_checksum[] = {", split_to_slices
? "" : "static ");
1099 for (size_t i
= 0; i
< sizeof(module_checksum
); i
++) {
1100 if (i
> 0) output
->source
.string_literals
=
1101 mputc(output
->source
.string_literals
, ',');
1102 output
->source
.string_literals
=
1103 mputprintf(output
->source
.string_literals
, " 0x%02x",
1104 module_checksum
[i
]);
1106 output
->source
.string_literals
= mputstr(output
->source
.string_literals
,
1109 const char *module_name
= modid
->get_name().c_str();
1111 // XML namespaces. Written in the order they are stored:
1112 // sorted ASCIIbetically by the prefix.
1113 // Not all namespaces are used by every module. Unfortunately, the array
1114 // (which has the same size in all modules) cannot be compacted, because
1115 // the indexes have already been used when the XER descriptors were written.
1116 // All we can do is store NULLs for the unused namespaces.
1117 size_t num_xml_namespaces
= namespaces
.size();
1118 if (moduletype
== MOD_TTCN
) { //TODO remove this when ASN.1 gets EXER
1120 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
1121 "// written by %s in " __FILE__
" at %d\n"
1122 , __FUNCTION__
, __LINE__
1126 if (num_xml_namespaces
!= 0 || (control_ns
&& control_ns_prefix
)) {
1127 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
1128 "%sconst size_t num_namespaces = %lu;\n"
1129 "%sconst namespace_t xml_namespaces[num_namespaces+1] = {\n"
1130 , split_to_slices
? "" : "static ", (unsigned long)num_xml_namespaces
1131 , split_to_slices
? "" : "static "
1133 if (split_to_slices
) {
1134 output
->header
.global_vars
= mputprintf(output
->header
.global_vars
,
1135 "extern const size_t num_namespaces;\n");
1136 output
->header
.global_vars
= mputprintf(output
->header
.global_vars
,
1137 "extern const namespace_t xml_namespaces[];\n");
1139 for (size_t i
=0; i
< namespaces
.size(); ++i
) {
1140 if (used_namespaces
.has_key(i
)) {
1141 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
1142 " { \"%s\", \"%s\" },\n", // ns, then prefix
1143 namespaces
.get_nth_elem(i
), namespaces
.get_nth_key(i
).c_str());
1146 output
->source
.global_vars
= mputstr(output
->source
.global_vars
,
1147 " { NULL, NULL },\n"); // not used in this module
1150 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
1151 " { \"%s\", \"%s\" }\n};\n\n",
1152 (control_ns
? control_ns
: ""),
1153 (control_ns_prefix
? control_ns_prefix
: ""));
1154 } // if there are namespaces
1159 output
->header
.global_vars
= mputprintf(output
->header
.global_vars
,
1160 "extern TTCN_Module %s;\n",
1163 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
1164 "TTCN_Module %s(\"%s\", __DATE__, __TIME__, %s, %s",
1167 modid
->get_dispname().c_str(),
1168 (has_checksum
? "module_checksum" : "NULL"),
1169 has_pre_init
? "pre_init_module" : "NULL");
1171 if (moduletype
== MOD_TTCN
) {
1172 // TTCN-3 specific function pointers
1173 if (product_number
== NULL
) {
1174 output
->source
.global_vars
= mputstr(output
->source
.global_vars
, ", NULL");
1176 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
, ", \"%s\"", product_number
);
1178 string extra_str
= extra
? ( string('"') + extra
+ string('"') ) : string("NULL");
1179 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
1180 ", %uU, %uU, %uU, %uU, %s, %luLU, %s, %s, %s, %s, %s, %s, %s, %s",
1181 suffix
, release
, patch
, build
, extra_str
.c_str(),
1182 (unsigned long)num_xml_namespaces
,
1183 ((num_xml_namespaces
|| (control_ns
&& control_ns_prefix
)) ? "xml_namespaces" : "0"),
1184 has_post_init
? "post_init_module" : "NULL",
1185 has_set_param
? "set_module_param" : "NULL",
1186 has_get_param
? "get_module_param" : "NULL",
1187 has_log_param
? "log_module_param" : "NULL",
1188 has_init_comp
? "init_comp_type" : "NULL",
1189 has_start
? "start_ptc_function" : "NULL",
1190 has_control
? "module_control_part" : "NULL");
1192 // self checks for ASN.1 modules
1194 FATAL_ERROR("Module::generate_functions(): post_init function in ASN.1 module");
1196 FATAL_ERROR("Module::generate_functions(): set_param function in ASN.1 module");
1198 FATAL_ERROR("Module::generate_functions(): get_param function in ASN.1 module");
1200 FATAL_ERROR("Module::generate_functions(): log_param function in ASN.1 module");
1202 FATAL_ERROR("Module::generate_functions(): init_comp function in ASN.1 module");
1204 FATAL_ERROR("Module::generate_functions(): startable function in ASN.1 module");
1206 FATAL_ERROR("Module::generate_functions(): control part in ASN.1 module");
1208 output
->source
.global_vars
= mputstr(output
->source
.global_vars
, ");\n");
1209 // #include into the source file
1210 output
->source
.includes
= mputprintf(output
->source
.includes
,
1211 "#include \"%s.hh\"\n",
1212 duplicate_underscores
? module_name
: modid
->get_ttcnname().c_str());
1214 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
1215 "\n%sconst RuntimeVersionChecker ver_checker("
1216 " current_runtime_version.requires_major_version_%d,\n"
1217 " current_runtime_version.requires_minor_version_%d,\n"
1218 " current_runtime_version.requires_patch_level_%d,"
1219 " current_runtime_version.requires_runtime_%d);\n",
1220 split_to_slices
? "" : "static ",
1221 TTCN3_MAJOR
, TTCN3_MINOR
, TTCN3_PATCHLEVEL
, use_runtime_2
? 2 : 1
1223 if (split_to_slices
) {
1224 output
->header
.global_vars
= mputprintf(output
->header
.global_vars
,
1225 "extern const RuntimeVersionChecker ver_checker;\n");
1228 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
1229 "\n%sconst int effective_module_lines[] = { %s };\n" \
1230 "%sconst char *effective_module_functions[] = { %s };\n",
1231 split_to_slices
? "" : "static ",
1232 effective_module_lines
? static_cast<const char *>(effective_module_lines
) : "",
1233 split_to_slices
? "" : "static ",
1234 effective_module_functions
? static_cast<const char *>(effective_module_functions
) : "");
1235 if (split_to_slices
) {
1236 output
->header
.global_vars
= mputprintf(output
->header
.global_vars
,
1237 "extern const int effective_module_lines[];\n" \
1238 "extern const char *effective_module_functions[];\n");
1243 void Module::generate_conversion_functions(output_struct
*output
)
1245 for (size_t i
= 0; i
< type_conv_v
.size(); i
++)
1247 ->gen_conv_func(&output
->source
.static_conversion_function_prototypes
,
1248 &output
->source
.static_conversion_function_bodies
,
1252 string
Module::add_literal(map
<string
, string
>& literals
, const string
& str
,
1255 if (literals
.has_key(str
)) return *literals
[str
];
1257 string
*literal
= new string(prefix
+Int2string(literals
.size()));
1258 literals
.add(str
, literal
);
1263 void Module::clear_literals(map
<string
, string
>& literals
)
1265 for (size_t i
= 0; i
< literals
.size(); i
++)
1266 delete literals
.get_nth_elem(i
);
1270 map
<string
, const char> Module::namespaces
;
1271 map
<string
, const char> Module::invented_prefixes
;
1272 size_t Module::default_namespace_attempt
= 0;
1273 size_t Module::replacement_for_empty_prefix
= (size_t)-1;
1275 Module::Module(moduletype_t p_mt
, Identifier
*p_modid
)
1276 : Scope(), moduletype(p_mt
), modid(p_modid
),
1277 imp_checked(false), gen_code(false), has_checksum(false),
1278 visible_mods(), module_checksum(),
1279 bs_literals(), bp_literals(), hs_literals(), hp_literals(), os_literals(),
1280 op_literals(), cs_literals(), us_literals(), pp_literals(), mp_literals(),
1281 oid_literals(), tmp_id_count(0),
1282 control_ns(p_mt
== MOD_ASN
? mcopystr("urn:oid:2.1.5.2.0.1") : NULL
),
1283 control_ns_prefix(p_mt
== MOD_ASN
? mcopystr("asn1") : NULL
),
1284 // only ASN.1 modules have default control namespace (X.693 amd1, 16.9)
1285 used_namespaces(), type_conv_v(), product_number(NULL
),
1286 suffix(0), release(UINT_MAX
), patch(UINT_MAX
), build(UINT_MAX
), extra(NULL
)
1289 FATAL_ERROR("NULL parameter: Common::Module::Module()");
1290 memset(module_checksum
, 0, sizeof(module_checksum
));
1291 set_scopeMacro_name(modid
->get_dispname());
1297 visible_mods
.clear();
1298 clear_literals(bs_literals
);
1299 clear_literals(bp_literals
);
1300 clear_literals(hs_literals
);
1301 clear_literals(hp_literals
);
1302 clear_literals(os_literals
);
1303 clear_literals(op_literals
);
1304 clear_literals(cs_literals
);
1305 clear_literals(pp_literals
);
1306 clear_literals(mp_literals
);
1307 for (size_t i
= 0; i
< us_literals
.size(); i
++)
1308 delete us_literals
.get_nth_elem(i
);
1309 us_literals
.clear();
1310 for (size_t i
= 0; i
< oid_literals
.size(); i
++)
1311 delete oid_literals
.get_nth_elem(i
);
1312 oid_literals
.clear();
1313 for (size_t i
= 0; i
< type_conv_v
.size(); i
++)
1314 delete type_conv_v
[i
];
1315 type_conv_v
.clear();
1317 Free(control_ns_prefix
);
1318 used_namespaces
.clear(); // all the values are NULL, no need to free
1319 // static members below; repeated clear()s are redundant but harmless
1321 invented_prefixes
.clear();
1322 Free(product_number
);
1326 Type
*Module::get_address_type()
1328 FATAL_ERROR("Common::Module::get_address_type()");
1332 string
Module::add_ustring_literal(const ustring
& ustr
)
1334 if (us_literals
.has_key(ustr
)) return *us_literals
[ustr
];
1336 string
*literal
= new string("us_" + Int2string(us_literals
.size()));
1337 us_literals
.add(ustr
, literal
);
1342 string
Module::add_objid_literal(const string
& oi_str
, const size_t nof_elems
)
1344 if(oid_literals
.has_key(oi_str
)) return oid_literals
[oi_str
]->oid_id
;
1346 OID_literal
*oi_struct
= new OID_literal
;
1347 oi_struct
->nof_elems
= nof_elems
;
1348 oi_struct
->oid_id
= "oi_" + Int2string(oid_literals
.size());
1349 oid_literals
.add(oi_str
, oi_struct
);
1350 return oi_struct
->oid_id
;
1354 void Module::add_type_conv(TypeConv
*p_conv
)
1356 if (p_conv
== NULL
) FATAL_ERROR("Module::add_type_conv()");
1357 Type
*p_from_type
= p_conv
->get_from_type();
1358 Type
*p_to_type
= p_conv
->get_to_type();
1359 if (!p_from_type
->is_structured_type()
1360 || !p_to_type
->is_structured_type())
1361 FATAL_ERROR("Module::add_type_conv()");
1362 if (p_from_type
== p_to_type
) {
1363 // Never add the same types.
1367 for (size_t i
= 0; i
< type_conv_v
.size(); i
++) {
1368 TypeConv
*conv
= type_conv_v
[i
];
1369 if (conv
->get_from_type() == p_from_type
1370 && conv
->get_to_type() == p_to_type
1371 && conv
->is_temp() == p_conv
->is_temp()) {
1372 // Same pair of types, both for values or templates. We're the
1373 // owners, deallocate.
1378 type_conv_v
.add(p_conv
);
1381 bool Module::needs_type_conv(Type
*p_from_type
, Type
*p_to_type
) const
1383 for (size_t i
= 0; i
< type_conv_v
.size(); i
++) {
1384 TypeConv
*conv
= type_conv_v
[i
];
1385 if (conv
->get_from_type() == p_from_type
1386 && conv
->get_to_type() == p_to_type
)
1392 void Module::chk_recursive(module_set_t
& checked_modules
)
1394 if (checked_modules
.has_key(this)) return;
1395 // this must be added to the set at the beginning
1396 // in order to deal with circular imports
1397 checked_modules
.add(this, 0);
1398 // check the imported modules first
1399 size_t nof_visible_mods
= visible_mods
.size();
1400 for (size_t i
= 0; i
< nof_visible_mods
; i
++) {
1401 Module
*m
= visible_mods
.get_nth_key(i
);
1402 if (m
!= this) m
->chk_recursive(checked_modules
);
1404 // then check the module itself
1405 chk(); // this is the only virtual call
1408 bool Module::is_visible(Module
*m
)
1410 collect_visible_mods();
1411 return visible_mods
.has_key(m
);
1414 void Module::get_visible_mods(module_set_t
& p_visible_mods
)
1416 if (visible_mods
.has_key(this)) {
1417 size_t nof_visible_mods
= visible_mods
.size();
1418 for (size_t i
= 0; i
< nof_visible_mods
; i
++) {
1419 Module
*m
= visible_mods
.get_nth_key(i
);
1420 if (!p_visible_mods
.has_key(m
)) p_visible_mods
.add(m
, 0);
1423 get_imported_mods(p_visible_mods
);
1427 void Module::write_checksum()
1429 fprintf(stderr
, "%-18s ", modid
->get_dispname().c_str());
1430 switch (moduletype
) {
1431 case MOD_TTCN
: fprintf(stderr
, "%-15s ", "TTCN-3"); break;
1432 case MOD_ASN
: fprintf(stderr
, "%-15s ", "ASN.1"); break;
1433 case MOD_UNKNOWN
: fprintf(stderr
, "%-15s ", "OTHER"); break;
1436 if (!has_checksum
) {
1437 fputc('\n', stderr
);
1441 size_t nof_checksum
= sizeof(module_checksum
);
1442 for (size_t i
= 0; i
< nof_checksum
; i
++) {
1443 fprintf(stderr
, "%02x", module_checksum
[i
]);
1446 if (release
<= 999999 && patch
< 30 && build
< 100) {
1447 char *product_identifier
=
1448 get_product_identifier(product_number
, suffix
, release
, patch
, build
, extra
);
1449 fprintf(stderr
, " %s", product_identifier
);
1450 Free(product_identifier
);
1453 fputc('\n', stderr
);
1456 char* Module::get_product_identifier(const char* product_number
,
1457 const unsigned int suffix
, unsigned int release
, unsigned int patch
,
1458 unsigned int build
, const char* extra
)
1460 expstring_t ret_val
= memptystr();
1461 if ( product_number
== NULL
1462 && suffix
== UINT_MAX
1463 && release
== UINT_MAX
1464 && patch
== UINT_MAX
1465 && build
== UINT_MAX
) {
1466 ret_val
= mputstr(ret_val
, "<RnXnn>");
1469 if (product_number
!= NULL
) {
1470 ret_val
= mputstr(ret_val
, product_number
);
1472 ret_val
= mputprintf(ret_val
, "/%d", suffix
);
1474 ret_val
= mputc(ret_val
, ' ');
1477 char* build_str
= buildstr(build
);
1478 ret_val
= mputprintf(ret_val
, "R%u%c%s%s", release
, eri(patch
), build_str
, extra
? extra
: "");
1483 void Module::collect_visible_mods()
1485 if (!visible_mods
.has_key(this)) {
1486 get_imported_mods(visible_mods
);
1487 if (!visible_mods
.has_key(this)) visible_mods
.add(this, 0);
1491 void Module::set_checksum(size_t checksum_len
,
1492 const unsigned char* checksum_ptr
)
1494 if (checksum_len
!= sizeof(module_checksum
))
1495 FATAL_ERROR("Module::set_checksum(): invalid length");
1496 memcpy(module_checksum
, checksum_ptr
, sizeof(module_checksum
));
1497 has_checksum
= true;
1500 void Module::set_controlns(char *ns
, char *prefix
)
1504 Free(control_ns_prefix
);
1505 control_ns_prefix
= prefix
;
1508 void Module::get_controlns(const char *&ns
, const char *&prefix
)
1511 prefix
= control_ns_prefix
;
1514 const size_t max_invented_prefixes
= 10000;
1515 void Module::add_namespace(const char *new_uri
, char *&new_prefix
)
1517 const bool prefix_is_empty
= new_prefix
&& !*new_prefix
;
1518 const string
key(new_prefix
? new_prefix
: "");
1519 if (new_prefix
&& !namespaces
.has_key(key
)) {
1520 namespaces
.add(key
, new_uri
);
1521 if (*new_prefix
== 0) { // first add of default namespace
1522 ++default_namespace_attempt
;
1524 return; // newly added
1526 else { // prefix already present (or we are required to invent one)
1528 const char *uri_value
= namespaces
[key
];
1529 if (!strcmp(uri_value
, new_uri
)) return; // same URI, same prefix: no-op
1532 // prefix already present but different URI,
1533 // or prefix is NULL (which means we must invent a prefix)
1535 if (new_prefix
&& *new_prefix
) {
1536 Free(new_prefix
); // prefix is not empty, discard it and start fresh
1537 new_prefix
= memptystr();
1540 const string
uri_key(new_uri
);
1541 if (invented_prefixes
.has_key(uri_key
)) {
1542 // we already made one up for this URI
1543 new_prefix
= mputstr(new_prefix
, invented_prefixes
[uri_key
]);
1544 return; // already there
1547 // make one up on the spot
1548 size_t iidx
= invented_prefixes
.size(); // "invented index"
1549 new_prefix
= mputprintf(new_prefix
, "tq%04lu", (unsigned long)iidx
++);
1550 string
made_up_prefix(new_prefix
);
1551 for (; iidx
< max_invented_prefixes
; ++iidx
) {
1552 if (namespaces
.has_key(made_up_prefix
)) {
1553 // Some pervert wrote an XSD with a namespace prefix like tq0007!
1554 // Make up another one in the same memory spot.
1555 sprintf(new_prefix
, "tq%04lu", (unsigned long)iidx
);
1556 made_up_prefix
= new_prefix
;
1561 if (iidx
>= max_invented_prefixes
) {
1562 Location loc
; // no particular location
1563 loc
.error("Internal limit: too many assigned prefixes");
1564 return; // not added
1566 invented_prefixes
.add(uri_key
, new_prefix
);
1567 namespaces
.add(made_up_prefix
, new_uri
);
1569 // Search for the newly added prefix and remember it.
1570 replacement_for_empty_prefix
= namespaces
.find_key(made_up_prefix
);
1572 if (prefix_is_empty
) {
1573 ++default_namespace_attempt
;
1575 return; // newly added
1580 static const string empty_prefix
;
1581 void Module::rename_default_namespace()
1583 if (default_namespace_attempt
< 2) return;
1584 // There was more than one default namespace. However, all but the first
1585 // are already renamed to tq%d.
1586 size_t di
= namespaces
.find_key(empty_prefix
); // keys are prefixes
1587 if (di
< namespaces
.size()) { // found it
1588 const char *last_remaining_def_namespace
= namespaces
.get_nth_elem(di
);
1589 // we can't change a key, we can only remove and re-add it
1590 namespaces
.erase(empty_prefix
);
1592 expstring_t empty_prefix_string
= NULL
; // force a made-up prefix
1593 add_namespace(last_remaining_def_namespace
, empty_prefix_string
);
1594 Free(empty_prefix_string
);
1596 else FATAL_ERROR("Module::rename_default_namespace");
1599 size_t Module::get_ns_index(const char *prefix
)
1601 size_t idx
= namespaces
.find_key(string(prefix
));
1602 if (idx
>= namespaces
.size()) { // not found
1603 // If the the caller asked for the empty prefix and it wasn't found
1604 // because it has been replaced, use the replacement.
1605 if (*prefix
== '\0' && replacement_for_empty_prefix
!= (size_t)-1) {
1606 idx
= replacement_for_empty_prefix
;
1608 else FATAL_ERROR("Module::get_ns_index()");
1611 // Remember that the index is used by this module
1612 if (!used_namespaces
.has_key(idx
)) {
1613 used_namespaces
.add(idx
, NULL
);
1618 string
Module::get_temporary_id()
1620 static const string
tmp_prefix("tmp_");
1621 return tmp_prefix
+ Int2string(tmp_id_count
++);
1624 void Module::generate_code(CodeGenHelper
& cgh
)
1627 nof_notupdated_files
+= 2;
1628 DEBUG(1, "Code not generated for module `%s'.",
1629 modid
->get_dispname().c_str());
1632 DEBUG(1, "Generating code for module `%s'.",
1633 modid
->get_dispname().c_str());
1635 // TODO: Always assume to have circular imports until
1636 // full program optimization is available,
1637 // this increases the size of the generated code,
1638 // but otherwise it is possible to create uncompilable code:
1639 // 1) let the project of module A and B refer to each other,
1640 // 2) A refers B, and compile A
1641 // 3) edit B to refer to A and compile it ...
1642 // As the code for A can not be rewritten the code will not compile
1643 cgh
.add_module(modid
->get_name(), modid
->get_ttcnname(),
1644 moduletype
== MOD_TTCN
, true);
1645 cgh
.set_current_module(modid
->get_ttcnname());
1647 // language specific parts (definitions, imports, etc.)
1648 //generate_code_internal(&target); <- needed to pass cgh
1649 generate_code_internal(cgh
);
1651 output_struct
* output
= cgh
.get_current_outputstruct();
1653 CodeGenHelper::update_intervals(output
);
1656 generate_literals(output
);
1657 // module level entry points
1658 generate_functions(output
);
1660 CodeGenHelper::update_intervals(output
); // maybe deeper in generate_functions
1662 // type conversion functions for type compatibility
1663 generate_conversion_functions(output
);
1665 CodeGenHelper::update_intervals(output
); // maybe deeper in conv_funcs
1667 /* generate the initializer function for the TTCN-3 profiler
1668 * (this is done at the end of the code generation, to make sure all code
1669 * lines have been added to the profiler database) */
1670 if (is_file_profiled(get_filename())) {
1671 output
->source
.global_vars
= mputstr(output
->source
.global_vars
,
1672 "\n/* Initializing TTCN-3 profiler */\n"
1673 "void init_ttcn3_profiler()\n"
1675 char* function_name
= 0;
1677 while (get_profiler_code_line(get_filename(), &function_name
, &line_no
)) {
1678 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
1679 " ttcn3_prof.create_line(ttcn3_prof.get_element(\"%s\"), %d);\n",
1680 get_filename(), line_no
);
1681 if (0 != function_name
) {
1682 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
1683 " ttcn3_prof.create_function(ttcn3_prof.get_element(\"%s\"), %d, \"%s\");\n",
1684 get_filename(), line_no
, function_name
);
1687 output
->source
.global_vars
= mputstr(output
->source
.global_vars
, "}\n");
1688 if (split_to_slices
) {
1689 output
->header
.global_vars
= mputstr(output
->header
.global_vars
,
1690 "extern void init_ttcn3_profiler();\n");
1694 generate the printing function for the types defined in this module
1695 and initialize the debugger with this module's global variables,
1696 component types and the components' variables */
1697 if (debugger_active
) {
1698 generate_debugger_functions(output
);
1699 generate_debugger_init(output
);
1703 void Module::dump(unsigned level
) const
1705 DEBUG(level
, "Module: %s", get_modid().get_dispname().c_str());
1708 // =================================
1709 // ===== Assignments
1710 // =================================
1712 Assignments
*Assignments::get_scope_asss()
1717 Assignment
*Assignments::get_ass_bySRef(Ref_simple
*p_ref
)
1719 if (!p_ref
|| !parent_scope
)
1720 FATAL_ERROR("NULL parameter: Common::Assignments::get_ass_bySRef()");
1721 if (!p_ref
->get_modid()) {
1722 const Identifier
*id
= p_ref
->get_id();
1723 if (id
&& has_local_ass_withId(*id
)) return get_local_ass_byId(*id
);
1725 return parent_scope
->get_ass_bySRef(p_ref
);
1728 bool Assignments::has_ass_withId(const Identifier
& p_id
)
1730 if (has_local_ass_withId(p_id
)) return true;
1731 else if (parent_scope
) return parent_scope
->has_ass_withId(p_id
);
1735 // =================================
1737 // =================================
1739 Assignment::Assignment(asstype_t p_asstype
, Identifier
*p_id
)
1740 : asstype(p_asstype
), id(p_id
), my_scope(0), checked(false),
1741 visibilitytype(PUBLIC
)
1743 if (!id
) FATAL_ERROR("Assignment::Assignment(): NULL parameter");
1746 Assignment::Assignment(const Assignment
& p
)
1747 : Node(p
), Location(p
), asstype(p
.asstype
), id(p
.id
->clone()), my_scope(0),
1748 checked(false), visibilitytype(p
.visibilitytype
)
1753 Assignment::~Assignment()
1758 Assignment::asstype_t
Assignment::get_asstype() const
1763 const char *Assignment::get_assname() const
1765 switch (get_asstype()) {
1769 if (my_scope
&& my_scope
->get_scope_mod()->get_moduletype() ==
1770 Module::MOD_ASN
) return "value";
1771 else return "constant";
1773 return "erroneous assignment";
1775 return "information object class";
1777 return "information object";
1779 return "information object set";
1783 return "external constant";
1785 return "module parameter";
1786 case A_MODULEPAR_TEMP
:
1787 return "template module parameter";
1792 case A_VAR_TEMPLATE
:
1793 return "template variable";
1799 case A_FUNCTION_RVAL
:
1800 case A_FUNCTION_RTEMP
:
1802 case A_EXT_FUNCTION
:
1803 case A_EXT_FUNCTION_RVAL
:
1804 case A_EXT_FUNCTION_RTEMP
:
1805 return "external function";
1812 return "value parameter";
1814 return "`out' value parameter";
1815 case A_PAR_VAL_INOUT
:
1816 return "`inout' value parameter";
1817 case A_PAR_TEMPL_IN
:
1818 return "template parameter";
1819 case A_PAR_TEMPL_OUT
:
1820 return "`out' template parameter";
1821 case A_PAR_TEMPL_INOUT
:
1822 return "`inout' template parameter";
1824 return "timer parameter";
1826 return "port parameter";
1832 string
Assignment::get_description()
1834 string
ret_val(get_assname());
1840 case A_PAR_VAL_INOUT
:
1841 case A_PAR_TEMPL_IN
:
1842 case A_PAR_TEMPL_OUT
:
1843 case A_PAR_TEMPL_INOUT
:
1846 // parameter is identified using its id
1847 ret_val
+= id
->get_dispname();
1852 case A_VAR_TEMPLATE
:
1854 // these can be both local and global
1855 if (is_local()) ret_val
+= id
->get_dispname();
1856 else ret_val
+= get_fullname();
1859 // the rest is always global
1860 ret_val
+= get_fullname();
1866 void Assignment::set_my_scope(Scope
*p_scope
)
1871 bool Assignment::is_local() const
1876 Setting
*Assignment::get_Setting()
1878 FATAL_ERROR("Common::Assignment::get_Setting()");
1882 Type
*Assignment::get_Type()
1884 FATAL_ERROR("Common::Assignment::get_Type()");
1888 Value
*Assignment::get_Value()
1890 FATAL_ERROR("Common::Assignment::get_Value()");
1894 Ttcn::Template
*Assignment::get_Template()
1896 FATAL_ERROR("Common::Assignment::get_Template()");
1900 bool Assignment::get_lazy_eval() const
1902 FATAL_ERROR("Common::Assignment::get_lazy_eval()");
1906 Ttcn::FormalParList
*Assignment::get_FormalParList()
1911 Ttcn::ArrayDimensions
*Assignment::get_Dimensions()
1916 Type
*Assignment::get_RunsOnType()
1921 void Assignment::chk_ttcn_id()
1923 if(!my_scope
) return;
1924 if(!get_id().get_has_valid(Identifier::ID_TTCN
)
1925 && my_scope
->get_parent_scope()==my_scope
->get_scope_mod()
1926 // <internal> or <error> ...
1927 && my_scope
->get_scope_mod()->get_modid().get_dispname()[0]!='<')
1928 warning("The identifier `%s' is not reachable from TTCN-3",
1929 get_id().get_dispname().c_str());
1932 // *this is the (var/const/modulepar/etc.) definition we want to access.
1933 // p_scope is the location from where we want to reach the definition.
1934 string
Assignment::get_genname_from_scope(Scope
*p_scope
,
1935 const char *p_prefix
)
1937 if (!p_scope
|| !my_scope
)
1938 FATAL_ERROR("Assignment::get_genname_from_scope()");
1941 Module
*my_mod
= my_scope
->get_scope_mod_gen();
1942 if ((my_mod
!= p_scope
->get_scope_mod_gen()) &&
1943 !Asn::Assignments::is_spec_asss(my_mod
)) {
1944 // when the definition is referred from another module
1945 // the reference shall be qualified with the namespace of my module
1946 ret_val
= my_mod
->get_modid().get_name();
1949 if (p_prefix
) ret_val
+= p_prefix
;
1950 ret_val
+= get_genname();
1951 // add the cast to real type if its a lazy formal paramter
1955 case A_PAR_TEMPL_IN
:
1956 if (get_lazy_eval() && p_prefix
==NULL
) {
1957 Type
* type
= get_Type();
1958 string type_genname
= (asstype
==A_PAR_TEMPL_IN
) ? type
->get_genname_template(p_scope
) : type
->get_genname_value(p_scope
);
1959 ret_val
= string("((") + type_genname
+ string("&)") + ret_val
+ string(")");
1969 const char *Assignment::get_module_object_name()
1971 if (!my_scope
) FATAL_ERROR("Assignment::get_module_object_name()");
1972 return "module_object";
1975 void Assignment::use_as_lvalue(const Location
&)
1977 FATAL_ERROR("Common::Assignment::use_as_lvalue()");
1980 void Assignment::generate_code(output_struct
*, bool)
1984 void Assignment::generate_code(CodeGenHelper
&)
1988 void Assignment::dump(unsigned level
) const
1990 DEBUG(level
, "Assignment: %s (%d)",
1991 id
->get_dispname().c_str(), asstype
);
1994 Ttcn::Group
* Assignment::get_parent_group()
1999 } // namespace Common