Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 54 additions & 5 deletions cobj/codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ static const char *excp_current_program_id = NULL;
static const char *excp_current_section = NULL;
static const char *excp_current_paragraph = NULL;
static struct cb_program *current_prog;
static size_t *sgmt_sizes = NULL;
static size_t sgmt_count = 0;

extern int cb_default_byte_specified;
extern unsigned char cb_default_byte;
Expand Down Expand Up @@ -463,6 +465,7 @@ struct string_literal_cache {
enum cb_string_category category;
char *var_name;
struct string_literal_cache *next;
size_t *segment_sizes; /* segment sizes for strings concatenated with '&' */
};

int string_literal_id = 0;
Expand Down Expand Up @@ -531,7 +534,8 @@ static enum cb_string_category get_string_category(const unsigned char *s,
}

static void joutput_string_write(const unsigned char *s, int size,
enum cb_string_category category) {
enum cb_string_category category,
const size_t *tmp_sgmt_sizes) {
int i;

#ifdef I18N_UTF8
Expand All @@ -552,7 +556,11 @@ static void joutput_string_write(const unsigned char *s, int size,
} else {
joutput("CobolUtil.stringToBytes(");
}

if (tmp_sgmt_sizes) {
joutput_indent_level += 2;
joutput_newline();
joutput_prefix();
}
joutput("\"");

#ifdef I18N_UTF8
Expand All @@ -568,6 +576,8 @@ static void joutput_string_write(const unsigned char *s, int size,
}
#else
int output_multibyte = 0;
int sum_sgmt_size = 0;
int sgmt_index = 0;
for (i = 0; i < size; i++) {
int c = s[i];
if (!output_multibyte && (c == '\"' || c == '\\')) {
Expand All @@ -577,11 +587,33 @@ static void joutput_string_write(const unsigned char *s, int size,
} else {
joutput("%c", c);
}

// insert line breaks between segments concatenated with '&'
if (tmp_sgmt_sizes && i < size - 1) {
size_t segment_end_position =
sum_sgmt_size + tmp_sgmt_sizes[sgmt_index] - 1;
if (i == segment_end_position) {
joutput("\" + ");
joutput_newline();
joutput_prefix();
joutput("\"");
sum_sgmt_size += tmp_sgmt_sizes[sgmt_index];
sgmt_index++;
}
}
output_multibyte = !output_multibyte &&
((0x81 <= c && c <= 0x9f) || (0xe0 <= c && c <= 0xef));
}
#endif
joutput("\")");
if (tmp_sgmt_sizes) {
joutput("\"");
joutput_newline();
joutput_indent_level -= 2;
joutput_prefix();
joutput(")");
} else {
joutput("\")");
}
} else {
if (param_wrap_string_flag) {
joutput("CobolDataStorage.makeCobolDataStorage(");
Expand Down Expand Up @@ -631,6 +663,16 @@ static void joutput_string(const unsigned char *s, int size) {
new_literal_cache->var_name[var_name_length + 1 + i] = '\0';
}

// set segment sizes to new cache
if (sgmt_sizes) {
new_literal_cache->segment_sizes = cobc_malloc(sizeof(size_t) * sgmt_count);
memcpy(new_literal_cache->segment_sizes, sgmt_sizes,
sizeof(size_t) * sgmt_count);
sgmt_sizes = NULL;
} else {
new_literal_cache->segment_sizes = NULL;
}

// add the new cache to string_literal_list
new_literal_cache->next = string_literal_list;
string_literal_list = new_literal_cache;
Expand Down Expand Up @@ -658,7 +700,8 @@ static void joutput_all_string_literals() {
joutput_prefix();
joutput("public static final %s %s = ", data_type, l->var_name);
param_wrap_string_flag = l->param_wrap_string_flag;
joutput_string_write(l->string_value, l->size, l->category);
joutput_string_write(l->string_value, l->size, l->category,
l->segment_sizes);
joutput(";\n");
l = l->next;
}
Expand Down Expand Up @@ -2280,6 +2323,13 @@ static void joutput_initialize_one(struct cb_initialize *p, cb_tree x) {
/* Initialize by value */
if (p->val && f->values) {
cb_tree value = CB_VALUE(f->values);
struct cb_literal *l = CB_LITERAL_P(value) ? CB_LITERAL(value) : NULL;
// save the size information of '&' concatenated segments
if (l && l->segment_count > 0) {
sgmt_sizes = cobc_malloc(sizeof(size_t) * l->segment_count);
memcpy(sgmt_sizes, l->segment_sizes, sizeof(size_t) * l->segment_count);
sgmt_count = l->segment_count;
}

/* NATIONAL also needs no editing but mbchar conversion. */
if (CB_TREE_CATEGORY(x) == CB_CATEGORY_NATIONAL) {
Expand Down Expand Up @@ -2340,7 +2390,6 @@ static void joutput_initialize_one(struct cb_initialize *p, cb_tree x) {
/* We do not use joutput_move here because
we do not want to have the value be edited. */

struct cb_literal *l = CB_LITERAL(value);
static char *buff = NULL;
static int lastsize = 0;
if (!buff) {
Expand Down
56 changes: 55 additions & 1 deletion cobj/tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,31 @@ struct cb_literal *build_literal(enum cb_category category,
return p;
}

struct cb_literal *build_concat_literal(enum cb_category category,
const unsigned char *data, size_t size1,
size_t size2, size_t *sgmt_sizes,
size_t sgmt_count) {
struct cb_literal *p;
size_t size = size1 + size2;
p = make_tree(CB_TAG_LITERAL, category, sizeof(struct cb_literal));
p->data = cobc_malloc((size_t)(size + 1));
p->size = size;
memcpy(p->data, data, (size_t)size);

// set segment sizes
if (!sgmt_sizes) {
p->segment_sizes = cobc_malloc(sizeof(size_t) * 2);
p->segment_sizes[0] = size1;
} else {
p->segment_sizes = cobc_malloc(sizeof(size_t) * (sgmt_count + 1));
memcpy(p->segment_sizes, sgmt_sizes, sizeof(size_t) * sgmt_count);
}
p->segment_sizes[sgmt_count] = size2;
p->segment_count = sgmt_count + 1;

return p;
}

char *cb_name(cb_tree x) {
if (!treenamebuff) {
treenamebuff = cobc_malloc(COB_NORMAL_BUFF);
Expand Down Expand Up @@ -1030,21 +1055,40 @@ cb_tree cb_build_national_literal(const unsigned char *data, size_t size) {
return CB_TREE(build_literal(CB_CATEGORY_NATIONAL, data, size));
}

cb_tree cb_build_concat_alphanumeric_literal(const unsigned char *data,
size_t size1, size_t size2,
size_t *sgmt_sizes,
size_t sgmt_count) {
return CB_TREE(build_concat_literal(CB_CATEGORY_ALPHANUMERIC, data, size1,
size2, sgmt_sizes, sgmt_count));
}

cb_tree cb_build_concat_national_literal(const unsigned char *data,
size_t size1, size_t size2,
size_t *sgmt_sizes,
size_t sgmt_count) {
return CB_TREE(build_concat_literal(CB_CATEGORY_NATIONAL, data, size1, size2,
sgmt_sizes, sgmt_count));
}

cb_tree cb_concat_literals(cb_tree x1, cb_tree x2) {
unsigned char *buff;
cb_tree x;
unsigned char *data1;
unsigned char *data2;
size_t size1;
size_t size2;
struct cb_literal *l;

if (x1 == cb_error_node || x2 == cb_error_node) {
return cb_error_node;
}
if (CB_LITERAL_P(x1)) {
l = CB_LITERAL(x1);
data1 = CB_LITERAL(x1)->data;
size1 = CB_LITERAL(x1)->size;
} else if (CB_CONST_P(x1)) {
l = CB_LITERAL(x1);
size1 = 1;
if (x1 == cb_space) {
data1 = (unsigned char *)" ";
Expand Down Expand Up @@ -1090,8 +1134,18 @@ cb_tree cb_concat_literals(cb_tree x1, cb_tree x2) {
buff = cobc_malloc(size1 + size2 + 3);
memcpy(buff, data1, size1);
memcpy(buff + size1, data2, size2);
x = cb_build_alphanumeric_literal(buff, size1 + size2);
if (!l->segment_count) {
l->segment_count = 1;
}
if (x1->category == CB_CATEGORY_NATIONAL) {
x = cb_build_concat_national_literal(buff, size1, size2, l->segment_sizes,
l->segment_count);
} else {
x = cb_build_concat_alphanumeric_literal(
buff, size1, size2, l->segment_sizes, l->segment_count);
}
free(buff);

return x;
}

Expand Down
20 changes: 20 additions & 0 deletions cobj/tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -467,9 +467,17 @@ extern cb_tree cb_build_system_name(enum cb_system_name_category category,
* Literal
*/

struct cb_literal_segment {
size_t size;
unsigned char *data;
struct cb_literal_segment *next;
};

struct cb_literal {
struct cb_tree_common common;
size_t size;
size_t *segment_sizes; /* segment sizes for strings concatenated with '&' */
size_t segment_count;
unsigned char *data;
signed char all;
signed char sign; /* unsigned: 0 negative: -1 positive: 1 */
Expand All @@ -489,6 +497,14 @@ extern cb_tree cb_build_alphanumeric_literal(const unsigned char *data,
extern cb_tree cb_build_national_literal(const unsigned char *data,
size_t size);
extern cb_tree cb_concat_literals(cb_tree x1, cb_tree x2);
extern cb_tree cb_build_concat_alphanumeric_literal(const unsigned char *data,
size_t size1, size_t size2,
size_t *sgmt_sizes,
size_t sgmt_count);
extern cb_tree cb_build_concat_national_literal(const unsigned char *data,
size_t size1, size_t size2,
size_t *sgmt_sizes,
size_t sgmt_count);

/*
* Decimal
Expand Down Expand Up @@ -1438,6 +1454,10 @@ extern void level_except_error(cb_tree x, const char *clause);

struct cb_literal *build_literal(enum cb_category category,
const unsigned char *data, size_t size);
struct cb_literal *build_concat_literal(enum cb_category category,
const unsigned char *data, size_t size1,
size_t size2, size_t *sgmt_sizes,
size_t sgmt_count);

/* field.c */
extern size_t cb_needs_01;
Expand Down
3 changes: 2 additions & 1 deletion tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,8 @@ misc_DEPENDENCIES = \
misc.src/display-numeric-NUMERIC-class.at \
misc.src/display-inspect-sign.at \
misc.src/comp1-comp2.at \
misc.src/variable-length-file.at
misc.src/variable-length-file.at \
misc.src/convert-string-concat.at \

EXTRA_DIST = $(srcdir)/package.m4 \
$(TESTS) \
Expand Down
3 changes: 2 additions & 1 deletion tests/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -801,7 +801,8 @@ misc_DEPENDENCIES = \
misc.src/display-numeric-NUMERIC-class.at \
misc.src/display-inspect-sign.at \
misc.src/comp1-comp2.at \
misc.src/variable-length-file.at
misc.src/variable-length-file.at \
misc.src/convert-string-concat.at \

EXTRA_DIST = $(srcdir)/package.m4 \
$(TESTS) \
Expand Down
1 change: 1 addition & 0 deletions tests/misc.at
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,4 @@ m4_include([display-numeric-NUMERIC-class.at])
m4_include([display-inspect-sign.at])
m4_include([comp1-comp2.at])
m4_include([variable-length-file.at])
m4_include([convert-string-concat.at])
40 changes: 40 additions & 0 deletions tests/misc.src/convert-string-concat.at
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
AT_SETUP([convert '&' concatenated strings to Java])

AT_DATA([prog.cbl], [
IDENTIFICATION DIVISION.
PROGRAM-ID. prog.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 X-CONCAT PIC X(25) VALUE "abcde"
& "fghij"
& "klmno"
& "pqrst"
& "uvwxy".
01 N-CONCAT PIC N(25) VALUE "����������"
& "����������"
& "����������"
& "�����‚Ă�"
& "�Ȃɂʂ˂�".
PROCEDURE DIVISION.
MAIN-RTN.
DISPLAY X-CONCAT.
DISPLAY N-CONCAT.
STOP RUN.
])

AT_CHECK([${COMPILE} prog.cbl])
AT_CHECK([java prog], [0],
[abcdefghijklmnopqrstuvwxy
�����������������������������������‚ĂƂȂɂʂ˂�
])
AT_CHECK([grep -q ' "abcde" +' prog.java])
AT_CHECK([grep -q ' "fghij" +' prog.java])
AT_CHECK([grep -q ' "klmno" +' prog.java])
AT_CHECK([grep -q ' "pqrst" +' prog.java])
AT_CHECK([grep -q ' "uvwxy"' prog.java])
AT_CHECK([grep -q ' "����������" +' prog.java])
AT_CHECK([grep -q ' "����������" +' prog.java])
AT_CHECK([grep -q ' "����������" +' prog.java])
AT_CHECK([grep -q ' "�����‚Ă�" +' prog.java])
AT_CHECK([grep -q ' "�Ȃɂʂ˂�"' prog.java])
AT_CLEANUP