Commit 14e21cff authored by ebensza's avatar ebensza
Browse files

implemented new code splitting mechanism (split to equal slices)



Change-Id: Ifd2fa1b9e2ce3a57f442a08a3ea692c434dced06
Signed-off-by: default avatarebensza <bence.janos.szabo@ericsson.com>
parent 26e035f1
This diff is collapsed.
......@@ -12,12 +12,14 @@
* Forstner, Matyas
* Kovacs, Ferenc
* Raduly, Csaba
* Szabo, Bence Janos
* Szabo, Janos Zoltan – initial implementation
*
******************************************************************************/
#include "Code.hh"
#include "../common/memory.h"
#include "error.h"
#include "CodeGenHelper.hh"
#include <ctype.h>
......@@ -54,6 +56,31 @@ namespace Common {
output->functions.init_comp = NULL;
output->functions.start = NULL;
output->functions.control = NULL;
output->intervals.pre_things_size = 0;
output->intervals.methods_size = 0;
output->intervals.function_bodies_size = 0;
output->intervals.static_conversion_function_bodies_size = 0;
output->intervals.static_function_bodies_size = 0;
output->intervals.methods_max_size = 1;
output->intervals.function_bodies_max_size = 1;
output->intervals.static_conversion_function_bodies_max_size = 1;
output->intervals.static_function_bodies_max_size = 1;
if (CodeGenHelper::GetInstance().get_split_mode() == CodeGenHelper::SPLIT_TO_SLICES) {
output->intervals.methods = (size_t*)Malloc(output->intervals.methods_max_size * sizeof(size_t));
output->intervals.function_bodies = (size_t*)Malloc(output->intervals.function_bodies_max_size * sizeof(size_t));
output->intervals.static_conversion_function_bodies = (size_t*)Malloc(output->intervals.static_conversion_function_bodies_max_size * sizeof(size_t));
output->intervals.static_function_bodies = (size_t*)Malloc(output->intervals.static_function_bodies_max_size * sizeof(size_t));
output->intervals.methods[0] = 0;
output->intervals.function_bodies[0] = 0;
output->intervals.static_conversion_function_bodies[0] = 0;
output->intervals.static_function_bodies[0] = 0;
} else {
output->intervals.methods = NULL;
output->intervals.function_bodies = NULL;
output->intervals.static_conversion_function_bodies = NULL;
output->intervals.static_function_bodies = NULL;
}
}
void Code::merge_output(output_struct *dest, output_struct *src)
......@@ -142,6 +169,10 @@ namespace Common {
Free(output->functions.init_comp);
Free(output->functions.start);
Free(output->functions.control);
Free(output->intervals.methods);
Free(output->intervals.function_bodies);
Free(output->intervals.static_conversion_function_bodies);
Free(output->intervals.static_function_bodies);
init_output(output);
}
......
......@@ -9,6 +9,7 @@
* Balasko, Jeno
* Baranyi, Botond
* Raduly, Csaba
* Szabo, Bence Janos
* Zalanyi, Balazs Andor
*
******************************************************************************/
......@@ -20,7 +21,7 @@
#include <cstring>
namespace Common {
CodeGenHelper* CodeGenHelper::instance = 0;
CodeGenHelper::generated_output_t::generated_output_t() :
......@@ -100,7 +101,8 @@ const char* const CodeGenHelper::typetypemap[] = {
};
CodeGenHelper::CodeGenHelper() :
split_mode(SPLIT_NONE)
split_mode(SPLIT_NONE),
slice_num(1)
{
if (instance != 0)
FATAL_ERROR("Attempted to create a second code generator.");
......@@ -115,14 +117,38 @@ CodeGenHelper& CodeGenHelper::GetInstance() {
void CodeGenHelper::set_split_mode(split_type st) {
split_mode = st;
if (split_mode == SPLIT_TO_SLICES) {
split_to_slices = true;
} else {
split_to_slices = false;
}
}
bool CodeGenHelper::set_split_mode(const char* type) {
if (strcmp(type, "none") == 0)
int n;
if (strcmp(type, "none") == 0) {
split_mode = SPLIT_NONE;
else if (strcmp(type, "type") == 0)
split_to_slices = false;
} else if (strcmp(type, "type") == 0) {
split_mode = SPLIT_BY_KIND;
else
split_to_slices = false;
} else if ((n = atoi(type))) {
size_t length = strlen(type);
for (int i=0;i<length; i++) {
if (!isdigit(type[i])) {
ERROR("The number argument of -U must be a valid number.");
break;
}
}
split_mode = SPLIT_TO_SLICES;
if (n < 1 || n > 999999) {
ERROR("The number argument of -U must be between 1 and 999999.");
return false;
}
slice_num = n;
split_to_slices = slice_num > 1; // slice_num == 1 has no effect
} else
return false;
return true;
}
......@@ -155,6 +181,128 @@ void CodeGenHelper::set_current_module(const string& name) {
current_module = name;
}
void CodeGenHelper::update_intervals(output_struct* const output) {
if(instance->split_mode != SPLIT_TO_SLICES) return;
size_t tmp;
// 1. check if some characters are added to the charstring
// 2. increment size variable
// 3. if size is bigger than the array's size, then double the array size
// 4. store new end position
// class_defs are not counted as they will be in the header
tmp = mstrlen(output->source.function_bodies);
if (output->intervals.function_bodies[output->intervals.function_bodies_size] < tmp) {
output->intervals.function_bodies_size++;
if (output->intervals.function_bodies_size > output->intervals.function_bodies_max_size) {
output->intervals.function_bodies_max_size *= 2;
output->intervals.function_bodies = (size_t*)Realloc(output->intervals.function_bodies, output->intervals.function_bodies_max_size * sizeof(size_t));
}
output->intervals.function_bodies[output->intervals.function_bodies_size] = tmp;
}
tmp = mstrlen(output->source.methods);
if (output->intervals.methods[output->intervals.methods_size] < tmp) {
output->intervals.methods_size++;
if (output->intervals.methods_size > output->intervals.methods_max_size) {
output->intervals.methods_max_size *= 2;
output->intervals.methods = (size_t*)Realloc(output->intervals.methods, output->intervals.methods_max_size * sizeof(size_t));
}
output->intervals.methods[output->intervals.methods_size] = tmp;
}
tmp = mstrlen(output->source.static_conversion_function_bodies);
if (output->intervals.static_conversion_function_bodies[output->intervals.static_conversion_function_bodies_size] < tmp) {
output->intervals.static_conversion_function_bodies_size++;
if (output->intervals.static_conversion_function_bodies_size > output->intervals.static_conversion_function_bodies_max_size) {
output->intervals.static_conversion_function_bodies_max_size *= 2;
output->intervals.static_conversion_function_bodies = (size_t*)Realloc(output->intervals.static_conversion_function_bodies, output->intervals.static_conversion_function_bodies_max_size * sizeof(size_t));
}
output->intervals.static_conversion_function_bodies[output->intervals.static_conversion_function_bodies_size] = tmp;
}
tmp = mstrlen(output->source.static_function_bodies);
if (output->intervals.static_function_bodies[output->intervals.static_function_bodies_size] < tmp) {
output->intervals.static_function_bodies_size++;
if (output->intervals.static_function_bodies_size > output->intervals.static_function_bodies_max_size) {
output->intervals.static_function_bodies_max_size *= 2;
output->intervals.static_function_bodies = (size_t*)Realloc(output->intervals.static_function_bodies, output->intervals.static_function_bodies_max_size * sizeof(size_t));
}
output->intervals.static_function_bodies[output->intervals.static_function_bodies_size] = tmp;
}
}
//Advised to call update_intervals before this
size_t CodeGenHelper::size_of_sources(output_struct * const output) {
size_t size = 0;
// Calculate global var and string literals size
output->intervals.pre_things_size = mstrlen(output->source.global_vars) + mstrlen(output->source.string_literals);
// Class_defs, static_conversion_function_prototypes, static_function_prototypes are in the header,
// and includes are not counted
size = output->intervals.pre_things_size +
output->intervals.function_bodies[output->intervals.function_bodies_size] +
output->intervals.methods[output->intervals.methods_size] +
output->intervals.static_conversion_function_bodies[output->intervals.static_conversion_function_bodies_size] +
output->intervals.static_function_bodies[output->intervals.static_function_bodies_size];
return size;
}
size_t CodeGenHelper::get_next_chunk_pos(const output_struct * const from, output_struct * const to, const size_t base_pos, const size_t chunk_size) {
size_t pos = 0; // Holds the position from the beginning
pos += from->intervals.pre_things_size;
if (pos > base_pos) {
to->source.global_vars = mputstr(to->source.global_vars, from->source.global_vars);
to->source.string_literals = mputstr(to->source.string_literals, from->source.string_literals);
}
get_chunk_from_poslist(from->source.methods, to->source.methods, from->intervals.methods, from->intervals.methods_size, base_pos, chunk_size, pos);
get_chunk_from_poslist(from->source.function_bodies, to->source.function_bodies, from->intervals.function_bodies, from->intervals.function_bodies_size, base_pos, chunk_size, pos);
get_chunk_from_poslist(from->source.static_function_bodies, to->source.static_function_bodies, from->intervals.static_function_bodies, from->intervals.static_function_bodies_size, base_pos, chunk_size, pos);
get_chunk_from_poslist(from->source.static_conversion_function_bodies, to->source.static_conversion_function_bodies, from->intervals.static_conversion_function_bodies, from->intervals.static_conversion_function_bodies_size, base_pos, chunk_size, pos);
return pos;
}
//if from null return.
void CodeGenHelper::get_chunk_from_poslist(const char* from, char *& to, const size_t interval_array[], const size_t interval_array_size, const size_t base_pos, const size_t chunk_size, size_t& pos) {
if (from == NULL) return;
// If we have enough to form a chunk
// pos is unsigned so it can't be negative
if (pos > base_pos && pos - base_pos >= chunk_size) return;
size_t tmp = pos;
pos += interval_array[interval_array_size];
if (pos > base_pos) { // If we haven't finished with this interval_array
if (pos - base_pos >= chunk_size) { // It is a good chunk, but make it more precise because it may be too big
int ind = 0;
for (int i = 0; i <= interval_array_size; i++) {
if (tmp + interval_array[i] <= base_pos) { // Find the pos where we left off
ind = i;
} else if (tmp + interval_array[i] - base_pos >= chunk_size) {
// Found the first optimal position that is a good chunk
to = mputstrn(to, from + interval_array[ind], interval_array[i] - interval_array[ind]);
pos = tmp + interval_array[i];
return;
}
}
} else { // We can't form a new chunk from the remaining characters
int ind = 0;
for (int i = 0; i <= interval_array_size; i++) {
if (tmp + interval_array[i] <= base_pos) {
ind = i;
} else {
break;
}
}
// Put the remaining characters
to = mputstrn(to, from + interval_array[ind], interval_array[interval_array_size] - interval_array[ind]);
pos = tmp + interval_array[interval_array_size];
}
}
}
output_struct* CodeGenHelper::get_outputstruct(Ttcn::Definition* def) {
string key = get_key(*def);
const string& new_name = current_module + key;
......@@ -237,6 +385,8 @@ string CodeGenHelper::get_key(Ttcn::Definition& def) const {
break;
case SPLIT_BY_HEURISTICS:
break;
case SPLIT_TO_SLICES:
break;
}
return retval;
}
......@@ -268,6 +418,8 @@ string CodeGenHelper::get_key(Type& type) const {
break;
case SPLIT_BY_HEURISTICS:
break;
case SPLIT_TO_SLICES:
break;
}
return retval;
}
......@@ -286,12 +438,123 @@ void CodeGenHelper::write_output() {
go->modulename = modules[j]->name;
go->module_dispname = modules[j]->dispname;
go->os.source.includes = mcopystr(
"\n//This file intentionally empty."
"\n//This file is intentionally empty."
"\n#include <version.h>\n");
generated_code.add(fname, go);
}
}
}
} else if (split_mode == SPLIT_TO_SLICES && slice_num > 0) {
// The strategy is the following:
// Goal: Get files with equal size
// Get the longest file's length and divide it by slice_num (chunk_size)
// We split every file to chunk_size sized chunks
size_t max = 0;
// Calculate maximum character length
for (j = 0; j < generated_code.size(); j++) {
update_intervals(&generated_code.get_nth_elem(j)->os);
size_t num_of_chars = size_of_sources(&generated_code.get_nth_elem(j)->os);
if (max < num_of_chars) {
max = num_of_chars;
}
}
// Calculate ideal chunk size
size_t chunk_size = max / slice_num;
string fname;
for (j = 0; j < modules.size(); j++) {
generated_output_t *output = generated_code[modules[j]->dispname];
// Just to be sure that everything is in the right place
update_intervals(&output->os);
// Move static function prototypes to header (no longer static)
output->os.header.function_prototypes = mputstr(output->os.header.function_prototypes, output->os.source.static_function_prototypes);
Free(output->os.source.static_function_prototypes);
output->os.source.static_function_prototypes = NULL;
output->os.header.function_prototypes = mputstr(output->os.header.function_prototypes, output->os.source.static_conversion_function_prototypes);
Free(output->os.source.static_conversion_function_prototypes);
output->os.source.static_conversion_function_prototypes = NULL;
// Move internal class definitions to the header
output->os.header.class_defs = mputstr(output->os.header.class_defs, output->os.source.class_defs);
Free(output->os.source.class_defs);
output->os.source.class_defs = NULL;
update_intervals(&output->os);
size_t num_of_chars = size_of_sources(&output->os);
char buffer[13]= ""; // Max is 999999 should be enough (checked in main.cc) | 6 digit + 2 underscore + part
// If we need to split
if (num_of_chars >= chunk_size) {
size_t base_pos = 0;
for (unsigned int i = 0; i < slice_num; i++) {
if (i == 0) { // The first slice has the module's name
fname = output->module_dispname;
} else {
sprintf(buffer, "_part_%d", (int)i);
fname = output->module_dispname + "_" + buffer;
}
if (i == 0 || !generated_code.has_key(fname)) {
generated_output_t* go = new generated_output_t;
go->filename = buffer;
go->modulename = output->modulename;
go->module_dispname = output->module_dispname;
size_t act_pos = get_next_chunk_pos(&output->os, &go->os, base_pos, chunk_size);
// True if the file is not empty
if (act_pos > base_pos) {
go->os.source.includes = mputstr(go->os.source.includes, output->os.source.includes);
} else {
go->os.source.includes = mcopystr(
"\n//This file is intentionally empty."
"\n#include <version.h>\n");
}
// First slice: copy header and other properties and replace the original output struct
if (i == 0) {
go->has_circular_import = output->has_circular_import;
go->is_module = output->is_module;
go->is_ttcn = output->is_ttcn;
go->os.header.class_decls = mputstr(go->os.header.class_decls, output->os.header.class_decls);
go->os.header.class_defs = mputstr(go->os.header.class_defs, output->os.header.class_defs);
go->os.header.function_prototypes = mputstr(go->os.header.function_prototypes, output->os.header.function_prototypes);
go->os.header.global_vars = mputstr(go->os.header.global_vars, output->os.header.global_vars);
go->os.header.includes = mputstr(go->os.header.includes, output->os.header.includes);
go->os.header.testport_includes = mputstr(go->os.header.testport_includes, output->os.header.testport_includes);
go->os.header.typedefs = mputstr(go->os.header.typedefs, output->os.header.typedefs);
generated_code[modules[j]->dispname] = go;
} else {
generated_code.add(fname, go);
}
base_pos = act_pos;
} else {
// TODO: error handling: there is a module which has the same name as the
// numbered splitted file. splitting by type does not have this error
// handling so don't we
}
}
// Extra safety. If something is missing after the splitting, put the remaining
// things to the last file. (Should never happen)
if (base_pos < num_of_chars) {
get_next_chunk_pos(&output->os, &generated_code[fname]->os, base_pos, num_of_chars);
}
delete output;
} else {
// Create empty files.
for (i = 1; i < slice_num; i++) {
sprintf(buffer, "_part_%d", (int)i);
fname = output->module_dispname + "_" + buffer;
if (!generated_code.has_key(fname)) {
generated_output_t* go = new generated_output_t;
go->filename = buffer;
go->modulename = modules[j]->name;
go->module_dispname = modules[j]->dispname;
go->os.source.includes = mcopystr(
"\n//This file is intentionally empty."
"\n#include <version.h>\n");
generated_code.add(fname, go);
}
}
}
}
}
generated_output_t* go;
for (i = 0; i < generated_code.size(); i++) {
......
......@@ -8,6 +8,7 @@
* Contributors:
* Balasko, Jeno
* Raduly, Csaba
* Szabo, Bence Janos
* Zalanyi, Balazs Andor
*
******************************************************************************/
......@@ -26,14 +27,15 @@ class Definition;
}
namespace Common {
class CodeGenHelper {
public:
enum split_type {
SPLIT_NONE, ///< original code generation
SPLIT_BY_KIND, ///< place different kind of types in their own file
SPLIT_BY_NAME, ///< place all definitions/assignments in their own file
SPLIT_BY_HEURISTICS ///< heuristic function will decide the structure
SPLIT_BY_HEURISTICS,///< heuristic function will decide the structure
SPLIT_TO_SLICES ///< split large files into smaller ones
};
private:
......@@ -57,6 +59,7 @@ private:
output_map_t generated_code;
split_type split_mode;
unsigned int slice_num;
struct module_names_t {
string name;
......@@ -86,6 +89,14 @@ public:
void finalize_generation(Type* type);
void set_current_module(const string& name);
static void update_intervals(output_struct* const output);
size_t size_of_sources(output_struct * const output);
size_t get_next_chunk_pos(const output_struct * const from, output_struct * const to, const size_t base_pos, const size_t chunk_size);
void get_chunk_from_poslist(const char* from, char *& to, const size_t interval_array[], const size_t interval_array_size, const size_t base_pos, const size_t chunk_size, size_t& pos);
void write_output();
......
......@@ -8,6 +8,7 @@
* Contributors:
* Balasko, Jeno
* Raduly, Csaba
* Szabo, Bence Janos
*
******************************************************************************/
#include "TypeCompat.hh"
......@@ -323,12 +324,12 @@ void TypeConv::gen_conv_func(char **p_prototypes, char **p_bodies,
string to_name = m_is_temp ? m_to->get_genname_template(p_mod)
: m_to->get_genname_value(p_mod);
*p_prototypes = mputprintf(*p_prototypes,
"static boolean %s(%s& p_to_v, const %s& p_from_v);\n",
get_conv_func(m_from, m_to, p_mod).c_str(), to_name.c_str(),
"%sboolean %s(%s& p_to_v, const %s& p_from_v);\n",
split_to_slices ? "" : "static ", get_conv_func(m_from, m_to, p_mod).c_str(), to_name.c_str(),
from_name.c_str());
*p_bodies = mputprintf(*p_bodies,
"static boolean %s(%s& p_to_v, const %s& p_from_v)\n{\n",
get_conv_func(m_from, m_to, p_mod).c_str(), to_name.c_str(),
"%sboolean %s(%s& p_to_v, const %s& p_from_v)\n{\n",
split_to_slices ? "" : "static ", get_conv_func(m_from, m_to, p_mod).c_str(), to_name.c_str(),
from_name.c_str());
switch (m_to->get_typetype()) {
case Type::T_SEQ_A:
......
......@@ -12,6 +12,7 @@
* Delic, Adam
* Raduly, Csaba
* Szabados, Kristof
* Szabo, Bence Janos
* Pandi, Krisztian
*
******************************************************************************/
......@@ -53,6 +54,7 @@ void Type::generate_code(output_struct *target)
{
if (code_generated) return;
generate_code_embedded_before(target);
CodeGenHelper::update_intervals(target); // TODO: class and template separate everywhere?
// escape from recursion loops
if (code_generated) return;
code_generated = true;
......@@ -101,11 +103,14 @@ void Type::generate_code(output_struct *target)
break;
} // switch
}
CodeGenHelper::update_intervals(target);
generate_code_embedded_after(target);
CodeGenHelper::update_intervals(target);
if (!is_asn1()) {
if (has_done_attribute()) generate_code_done(target);
if (sub_type) sub_type->generate_code(*target);
}
CodeGenHelper::update_intervals(target);
}
void Type::generate_code_include(const string& sourcefile, output_struct *target)
......@@ -434,8 +439,8 @@ void Type::generate_code_typedescriptor(output_struct *target)
void Type::generate_code_berdescriptor(output_struct *target)
{
const char *gennameown_str = get_genname_own().c_str();
char *str = mprintf("static const ASN_Tag_t %s_tag_[] = { ",
gennameown_str);
char *str = mprintf("%sconst ASN_Tag_t %s_tag_[] = { ",
split_to_slices ? "" : "static ", gennameown_str);
Tags *joinedtags = build_tags_joined();
size_t tagarraysize = joinedtags->get_nof_tags();
for (size_t i = 0; i < tagarraysize; i++) {
......@@ -720,7 +725,11 @@ void Type::generate_code_textdescriptor(output_struct *target)
case T_BOOL:
if (textattrib->true_params || textattrib->false_params) {
target->source.global_vars = mputprintf(target->source.global_vars,
"static const TTCN_TEXTdescriptor_bool %s_bool_ = {", gennameown_str);
"%sconst TTCN_TEXTdescriptor_bool %s_bool_ = {", split_to_slices ? "" : "static ", gennameown_str);
if (split_to_slices) {
target->header.global_vars = mputprintf(target->header.global_vars,
"extern const TTCN_TEXTdescriptor_bool %s_bool_;\n", gennameown_str);
}
if (textattrib->true_params &&
textattrib->true_params->encode_token) {
target->source.global_vars = mputprintf(target->source.global_vars,
......@@ -779,8 +788,12 @@ void Type::generate_code_textdescriptor(output_struct *target)
break;
case T_ENUM_T:
target->source.global_vars = mputprintf(target->source.global_vars,
"static const TTCN_TEXTdescriptor_enum %s_enum_[] = { ",
gennameown_str);
"%sconst TTCN_TEXTdescriptor_enum %s_enum_[] = { ",
split_to_slices ? "" : "static ", gennameown_str);
if (split_to_slices) {
target->header.global_vars = mputprintf(target->header.global_vars,
"extern const TTCN_TEXTdescriptor_enum %s_enum_[];\n", gennameown_str);
}
for (size_t i = 0; i < t->u.enums.eis->get_nof_eis(); i++) {
if (i > 0) target->source.global_vars =
mputstr(target->source.global_vars, ", ");
......@@ -845,8 +858,12 @@ void Type::generate_code_textdescriptor(output_struct *target)
textattrib->decoding_params.convert!=0 ||
textattrib->decoding_params.just!=1 ){
target->source.global_vars=mputprintf(target->source.global_vars,
"static const TTCN_TEXTdescriptor_param_values %s_par_ = {",
gennameown_str);
"%sconst TTCN_TEXTdescriptor_param_values %s_par_ = {",
split_to_slices ? "" : "static ", gennameown_str);
if (split_to_slices) {
target->header.global_vars=mputprintf(target->header.global_vars,
"extern const TTCN_TEXTdescriptor_param_values %s_par_;\n", gennameown_str);
}
target->source.global_vars=mputprintf(target->source.global_vars,
"{%s,%s,%i,%i,%i,%i},{%s,%s,%i,%i,%i,%i}};\n"
,textattrib->coding_params.leading_zero?"true":"false"
......@@ -868,8 +885,12 @@ void Type::generate_code_textdescriptor(output_struct *target)
case T_SEQOF:
case T_SETOF:
target->source.global_vars=mputprintf(target->source.global_vars,
"static const TTCN_TEXTdescriptor_param_values %s_par_ = {",
gennameown_str);
"%sconst TTCN_TEXTdescriptor_param_values %s_par_ = {",
split_to_slices ? "" : "static ", gennameown_str);
if (split_to_slices) {
target->header.global_vars=mputprintf(target->header.global_vars,
"extern const TTCN_TEXTdescriptor_param_values %s_par_;\n", gennameown_str);
}
target->source.global_vars=mputprintf(target->source.global_vars,
"{%s,%s,%i,%i,%i,%i},{%s,%s,%i,%i,%i,%i}};\n"
,textattrib->coding_params.leading_zero?"true":"false"
......@@ -2040,7 +2061,7 @@ void Type::generate_code_Array(output_struct *target)
"};\n\n",
own_name,
u.array.dimension->get_value_type(u.array.element_type, my_scope).c_str());
target->source.class_defs = mputprintf(target->source.class_defs,
target->source.methods = mputprintf(target->source.methods,
"const TTCN_Typedescriptor_t* %s::get_elem_descr() const { return &%s_descr_; }\n\n",
own_name, u.array.element_type->get_genname_typedescriptor(my_scope).c_str());
} else {
......@@ -2696,8 +2717,11 @@ void Type::generate_code_object(const_def *cdef, Scope *p_scope,
if (prefix) {
cdef->decl = mputprintf(cdef->decl, "extern const %s& %s;\n",
type_name_str, name_str);
cdef->def = mputprintf(cdef->def, "static %s %s%s;\n"
"const %s& %s = %s%s;\n", type_name_str, prefix, name_str,
if (split_to_slices) {
cdef->decl = mputprintf(cdef->decl, "extern %s %s%s;\n", type_name_str, prefix, name_str);
}
cdef->def = mputprintf(cdef->def, "%s%s %s%s;\n"
"const %s& %s = %s%s;\n", split_to_slices ? "" : "static ", type_name_str, prefix, name_str,
type_name_str, name_str, prefix, name_str);
} else {
cdef->decl = mputprintf(cdef->decl, "extern %s %s;\n",
......@@ -2720,8 +2744,8 @@ void Type::generate_code_object(const_def *cdef, GovernedSimple *p_setting)
FATAL_ERROR("Type::generate_code_object()");
}
if (p_setting->get_err_descr()) {
cdef->def = p_setting->get_err_descr()->generate_code_str(cdef->def,
p_setting->get_genname_prefix() + p_setting->get_genname_own());