Skip to content

Commit

Permalink
Fix STRING/UNSTRING/INSPECT bug
Browse files Browse the repository at this point in the history
  • Loading branch information
ddeclerck committed Dec 19, 2024
1 parent 4750170 commit e7fe42e
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 6 deletions.
7 changes: 7 additions & 0 deletions libcob/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@

2024-12-18 David Declerck <[email protected]>

* string.c: fix a bug where the source of STRING/UNSTRING/INSPECT
is overwritten, by restoring the *_copy fields that were removed
with the change on 2024-02-26

2024-12-11 Emilien Lemaire <[email protected]>

* fileio.c: fixed Bug #1032 by always using global thread-static variable
Expand Down Expand Up @@ -296,6 +302,7 @@
* common.c: add missing include libxml/parser.h

2024-02-26 Boris Eng <[email protected]>

FR #488: using state structures instead of state vars for strings
* strings.c: moved static variables to structures

Expand Down
42 changes: 36 additions & 6 deletions libcob/strings.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,17 @@ struct cob_inspect_state {
size_t size;
cob_u32_t replacing; /* marker about current operation being INSPECT REPLACING */
int sign;
cob_field var_copy; /* use a copy to account for overwritten temporary field, see cob_inspect_init_common_intern */
enum inspect_type type;
};

struct cob_string_state {
cob_field *dst;
cob_field *ptr;
cob_field *dlm;
cob_field dst_copy; /* use a copy to account for overwritten temporary field, see cob_string_init_intern */
cob_field ptr_copy; /* use a copy to account for overwritten temporary field, see cob_string_init_intern */
cob_field dlm_copy; /* use a copy to account for overwritten temporary field, see cob_string_delimited_intern */
int offset; /* value associated with WITH POINTER clauses */
};

Expand All @@ -81,6 +85,8 @@ struct cob_unstring_state {
the maximum needed (amount of DELIMITED BY),
actual size of dlm_list is calculated by
dlm_list_size * sizeof(dlm_struct) */
cob_field src_copy; /* use a copy to account for overwritten temporary field, see cob_unstring_init_intern */
cob_field ptr_copy; /* use a copy to account for overwritten temporary field, see cob_unstring_init_intern */
int offset;
unsigned int count;
unsigned int ndlms;
Expand Down Expand Up @@ -507,7 +513,11 @@ cob_inspect_init_common_intern (struct cob_inspect_state *st, cob_field *var)
/* it is allowed to TRANSFORM / INSPECT a numeric display signed element;
if it isn't stored separately we need to "remove" it here and add it back
in inspect_finish; note: we only handle NUMERIC DISPLAY here */
st->var = var;
/* var may be a temporary field (created from refmod or indexing),
which might be overwritten between subsequent calls to the
different cob_inspect_* functions */
st->var_copy = *var;
st->var = &st->var_copy;
st->sign = cob_real_get_sign (var, 0);
} else {
st->var = NULL;
Expand Down Expand Up @@ -918,8 +928,16 @@ cob_inspect_finish (void)
static void
cob_string_init_intern (struct cob_string_state *st, cob_field *dst, cob_field *ptr)
{
st->dst = dst;
st->ptr = ptr;
/* dst and ptr may be temporary fields (created from refmod or indexing),
which might be overwritten between subsequent calls to the
different cob_string_* functions */
st->dst_copy = *dst;
st->dst = &st->dst_copy;
st->ptr = NULL;
if (ptr) {
st->ptr_copy = *ptr;
st->ptr = &st->ptr_copy;
}
st->offset = 0;
cobglobptr->cob_exception_code = 0;

Expand All @@ -939,8 +957,12 @@ cob_string_init (cob_field *dst, cob_field *ptr)
static void
cob_string_delimited_intern (struct cob_string_state *st, cob_field *dlm)
{
/* dlm may be a temporary field (created from refmod or indexing),
which might be overwritten between subsequent calls to the
different cob_string_* functions */
if (dlm) {
st->dlm = dlm;
st->dlm_copy = *dlm;
st->dlm = &st->dlm_copy;
} else {
st->dlm = NULL;
}
Expand Down Expand Up @@ -1026,8 +1048,16 @@ cob_unstring_init_intern (
const size_t num_dlm
)
{
st->src = src;
st->ptr = ptr;
/* src and ptr may be temporary fields (created from refmod or indexing),
which might be overwritten between subsequent calls to the
different cob_unstring_* functions */
st->src_copy = *src;
st->src = &st->src_copy;
st->ptr = NULL;
if (ptr) {
st->ptr_copy = *ptr;
st->ptr = &st->ptr_copy;
}

st->offset = 0;
st->count = 0;
Expand Down
70 changes: 70 additions & 0 deletions tests/testsuite.src/run_misc.at
Original file line number Diff line number Diff line change
Expand Up @@ -2949,6 +2949,76 @@ AT_CHECK([$COBCRUN_DIRECT ./prog], [0],
AT_CLEANUP


AT_SETUP([STRING preserve source])
AT_KEYWORDS([runmisc])

AT_DATA([prog.cob], [
IDENTIFICATION DIVISION.
PROGRAM-ID. prog.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 SRC.
10 SRC-X PIC X(3) VALUE "123".
10 SRC-Y PIC X(8) VALUE SPACES.
01 DST OCCURS 1.
10 DST-X PIC X(8) VALUE SPACES.
PROCEDURE DIVISION.
DISPLAY "SRC-Y BEFORE: '" SRC-Y "'".
STRING "DATA " SRC-X(1:3) INTO DST (1).
DISPLAY "SRC-Y AFTER: '" SRC-Y "'".
DISPLAY "DST-X AFTER: '" DST-X (1) "'".
STOP RUN.
])

AT_CHECK([$COMPILE prog.cob], [0], [], [])
AT_CHECK([$COBCRUN_DIRECT ./prog], [0],
[SRC-Y BEFORE: ' '
SRC-Y AFTER: ' '
DST-X AFTER: 'DATA 123'
], [])

AT_CLEANUP


AT_SETUP([INSPECT preserve source])
AT_KEYWORDS([runmisc])

AT_DATA([prog.cob], [
IDENTIFICATION DIVISION.
PROGRAM-ID. prog.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 SRC OCCURS 1.
10 SRC-X PIC S9(3) VALUE 123.
10 SRC-Y PIC S9(3) VALUE 456.
01 DST OCCURS 1.
10 DST-X PIC S9(7) VALUE -6540321.
PROCEDURE DIVISION.
DISPLAY "SRC-X BEFORE: '" SRC-X (1) "'".
DISPLAY "SRC-Y BEFORE: '" SRC-Y (1) "'".
DISPLAY "DST-X BEFORE: '" DST-X (1) "'".
INSPECT DST-X (1) REPLACING
LEADING "654" BY SRC-X (1)
ALL "321" BY SRC-Y (1).
DISPLAY "SRC-X AFTER: '" SRC-X (1) "'".
DISPLAY "SRC-Y AFTER: '" SRC-Y (1) "'".
DISPLAY "DST-X AFTER: '" DST-X (1) "'".
STOP RUN.
])

AT_CHECK([$COMPILE prog.cob], [0], [], [])
AT_CHECK([$COBCRUN_DIRECT ./prog], [0],
[SRC-X BEFORE: '+123'
SRC-Y BEFORE: '+456'
DST-X BEFORE: '-6540321'
SRC-X AFTER: '+123'
SRC-Y AFTER: '+456'
DST-X AFTER: '-1230456'
], [])

AT_CLEANUP


AT_SETUP([UNSTRING DELIMITED ALL LOW-VALUE])
AT_KEYWORDS([runmisc])

Expand Down

0 comments on commit e7fe42e

Please sign in to comment.