<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.0 20120330//EN" "JATS-archivearticle1.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink">
  <front>
    <journal-meta />
    <article-meta>
      <title-group>
        <article-title>Generation of Multipurpose Formal Models from Legacy Code</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Stepan Potiyenko</string-name>
          <email>stepan.potiyenko@gmail.com</email>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Alexander Kolchin</string-name>
          <email>kolchin_av@yahoo.com</email>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <aff id="aff0">
          <label>0</label>
          <institution>V.M. Glushkov Institute of cybernetics of National Academy of Sciences of Ukraine</institution>
          ,
          <addr-line>Academician Glushkov ave., 40, Kyiv, 03187</addr-line>
          ,
          <country country="UA">Ukraine</country>
        </aff>
      </contrib-group>
      <abstract>
        <p>In this paper a method for generation of formal models from legacy software systems code is proposed. The purpose of these models is to have a possibility of their application in different tasks such as automatic generation of executable tests, translation to modern programming languages, reverse engineering. The method pursues goals to decrease complexity of state space search and checking formulas satisfiability, and to help legacy systems understanding and re-implementing using modern technologies. We focused on formalization of COBOL memory model as the most common in legacy systems. Formal model is an attributed transition system with arbitrary control flow. We propose an algorithm for building enumerated types for any variables whose usage fulfills certain conditions, including translation procedure of numeric variables into enumerated ones. We consider a problem of translating non-comparable structures that overlap in memory (operator redefines in COBOL) and are copied or compared with each other. In opposite to the common approach of using union semantics (like union construction in C++), our method of structure fields decomposition has no drawbacks of unions and contributes to minimization of the bytewise approach. We have examined the developed method using examples of structures with both simple fields and arrays. Examples of implementation of the bytewise approach in Java and C++ languages are given for those variables that cannot be represented as enumerated or numeric attributes. We have successfully applied this approach to generate tests on mediumsized projects (up to 100 000 lines of code). The generated formal models were also used to debug the Cobol to Java translator and to extract business rules.</p>
      </abstract>
      <kwd-group>
        <kwd>Translation</kwd>
        <kwd>formal model</kwd>
        <kwd>legacy systems</kwd>
      </kwd-group>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>Introduction</title>
      <p>
        The problem of legacy code support is actual for several reasons — the number of specialists in
old programming languages is insufficient and constantly decreasing, support for hardware systems
(mainframe, etc.) is ending, while there is a need in the industry to develop new functionality and
integrate with modern technologies. Mainly, the problem is solved by migrating old systems to new
programming languages. Here a need for complete or partial automation arises, because, for example,
according to estimates in 2021, from 200 to 250 billion lines of code in the COBOL language are
running in the world [
        <xref ref-type="bibr" rid="ref1">1</xref>
        ]. Any automation begins with parsing the code and building some model with
defined goals. Existing works, as a rule, pursue one of the goals - translation of legacy code into
modern programming languages (COBOL translation into Java is very common), generation of
executable tests, reverse engineering (code classification and clustering, information extraction, etc.).
Models generated with a specific purpose, in addition to obvious advantages, have their
disadvantages.
      </p>
      <p>
        Conventional translators between languages generate intermediate models that are not very
different from code. Their main goal is to present the constructions of the source code in a form
convenient for further transformations. But the task of generating tests using such intermediate
models has the same complexity as with any code. At the same time, these models are often
unreadable and look even less understandable for human than the source code. For example, the
authors of [
        <xref ref-type="bibr" rid="ref2">2</xref>
        ] proposed a method of accurate translation of data types from legacy systems to Java
classes. They produce 2 Java interfaces and 4 classes with several methods each (50-100 lines of
code) to emulate two overlapping memory areas in COBOL language (7 lines with REDEFINES
statement) using the semantics of the union construct from C++ language. To minimize a number of
generated Java classes an algorithm for optimizing COBOL data structures based on similarities is
given in [
        <xref ref-type="bibr" rid="ref3">3</xref>
        ]. Manual work is often required [
        <xref ref-type="bibr" rid="ref4 ref5 ref6 ref7">4-7</xref>
        ] in order to produce formal models from which
automated test generation becomes possible.
      </p>
      <p>
        Reverse engineering tools implement various abstraction techniques and are not intended for
simulation. For the sake of a compact and clear presentation, a lot of information necessary for
translators and test generators is lost. For example, the Rigi system [
        <xref ref-type="bibr" rid="ref8">8</xref>
        ] represents dependencies
between code classes and functions in the form of a graph and divides it into subgraphs according to
various criteria, performs information extraction but omits the control flow and other details. In [
        <xref ref-type="bibr" rid="ref9">9</xref>
        ], a
method of slicing COBOL programs is proposed to help in understanding and maintaining systems.
The authors of [
        <xref ref-type="bibr" rid="ref10">10</xref>
        ] build a formal model for visualizing a legacy system at different levels, from
hardware to user interface. And in [
        <xref ref-type="bibr" rid="ref11">11</xref>
        ], a hypertext generator is proposed for navigating the data
types of COBOL programs (type explorer), where memory intersections (REDEFINES) are
considered as union.
      </p>
      <p>The goal of our work is to generate formal models with the following properties:
 less complexity in relation to direct modeling of the code, which is important in such tasks as
state space search, checking formulas satisfiability, test generation according to various coverage
criteria, behavior analysis and debugging;
 accurate mapping of model artifacts to terms of source code to obtain executable tests and the
possibility of translation into other languages;
 greater human understanding than the source code.</p>
      <p>
        This work is an evolution of the methods and systems described in [
        <xref ref-type="bibr" rid="ref12 ref13 ref14">12-14</xref>
        ]. We pay the main
attention to Cobol language, as it is the most widespread in the domain of legacy code, but we also
had examples of applying our work for older versions of Java and Visual Basic. In this paper, we
focus on the formalization of the memory model and also recall the general principles of building the
model from the source code.
      </p>
    </sec>
    <sec id="sec-2">
      <title>Formal model</title>
      <p>
        As a formal model we use attributed transition system [
        <xref ref-type="bibr" rid="ref17">17</xref>
        ], where transitions are represented by
tuples of the form (t,α,σ,β), where t is the name of the transition, α is its precondition, σ is an input or
output signal, and β is a postcondition. The precondition contains the first-order predicate logic
formula, and the postcondition contains a set of assignments of new values (expressions) to model
attributes. Signals can contain parameters in the form of constants or attributes. The semantics of
transitions is analogous to Dijkstra's guarded commands [
        <xref ref-type="bibr" rid="ref15">15</xref>
        ]: if the precondition of some transition t
is fulfilled in some state s, then the model can perform this transition and pass to a new state s'=t(s),
which differs from the previous one by the values of the assigned attributes in postcondition. Model
attributes are typed and can be integer, boolean or of enumerated types, and can also be arrays of
elements of these types. We prefer the enumerated types in formal models: first, in order to increase
the efficiency of symbolic computation, second, it significantly simplifies debugging and analysis of
system behavior [
        <xref ref-type="bibr" rid="ref13 ref16">13, 16</xref>
        ].
      </p>
      <p>To specify the control flow, directed graphs of the form CFG = (V, E) are used, where V is a set of
vertices, E is a set of edges specified by pairs of vertices. The vertices of the graph are either
transitions of the formal model or links to other graphs that implement the semantics of function calls
in the source code. Such a representation is comparable with the source code and is convenient for
saving, human reading, and further translation of the formal model.</p>
      <p>For a number of tasks, it is necessary to unfold all link-vertices by substitution into one CFGU
graph. Such tasks include the determination of data dependencies, the construction of def-use pairs,
and the search for cycles. Although explicit loops can be taken from the structure of the code, for
example, in the COBOL language, GO TO operator and fall through semantics between paragraphs
are often used, which can generate implicit loops. When constructing a CFGU graph, there is a size
problem because all reachable function call stacks must be expanded. It also makes it impossible to
fully support recursion, although it can be limited, but this also leads to an increase in size. One
method of solving this problem is to move the function call stack from the control flow to the data
flow. But in this work, we do not solve this problem, taking into account the practical applications in
which unfold approach was sufficient.</p>
    </sec>
    <sec id="sec-3">
      <title>Expressions translation</title>
      <p>Pre- and postconditions are represented in a form of abstract syntax trees (AST). Tree nodes
express operators or terminal symbols. Operators in order of priority descending (from high to low)
are the following:
 "[]" – access to an array element;
 " " – function call (typically, parentheses in source code);
 "abs" – integer modulus;
 "." – delimiter in full qualified names of fields of structures;
 "-", "!" – unary minus and negation;
 "*", "/" – arithmetic operations;
 "+", "-" – arithmetic operations;
 "&lt;", "&gt;", "&lt;=", "&gt;=", "==", "!=" – comparison operations;
 "&amp;&amp;" – conjunction (logical AND);
 "||" – disjunction (logical OR);
 "," – delimiter of parameters in function call;
 ":=" – assignment;
 ";" – delimiter of statements (currently used for several assignments in one CFG node);
Binary operators have right-side associativity besides binary minus and division – they are
leftsided.</p>
      <p>AST is independent on source code language and may contain any uninterpreted operators. We can
abstract them by changing to nondeterministic assignments and obtain upper approximation. The
same is fair for library functions, whose bodies are absent in code under analysis.</p>
      <p>One of the difficulties in language transformations is a data types emulation. Let’s consider main
data definitions in COBOL from the Figure 1.
level-number [data-name-1 | FILLER]
[REDEFINES data-name-2]
[{PICTURE | PIC} IS character-string]
[[USAGE IS] {BINARY | COMPUTATIONAL | COMP | DISPLAY | INDEX |</p>
      <p>PACKED-DECIMAL}]
[OCCURS integer-2 TIMES
[VALUE IS literal-1].
66 data-name-1 RENAMES data-name-2 [{THROUGH | THRU} data-name-3].
88 condition-name-1 {VALUE IS | VALUES ARE}</p>
      <p>{literal-1 [{THROUGH | THRU} literal-2]} ... .</p>
      <p>Figure 1: Subset of COBOL data definitions syntax</p>
      <p>Level numbers from 1 to 50 define hierarchy. A variable can appear to be a structure, which
contains all variables defined below with greater level up to the end of section or to a variable with the
same or lower level. There are special levels:
 level 66 is used to define alternative name data-name-1 of memory area containing given
variable data-name-2 or all variables from data-name-2 to data-name-3;
 level 88 does not set any variable but is used for comparison of a variable defined above 88th
level with defined value or a set of values.</p>
      <p>Types of variables can be binary integer or alphanumeric, the latter we name string. We don’t
consider floating point types here.</p>
      <sec id="sec-3-1">
        <title>We transform the names of 88th level as follows:</title>
        <p> All occurrences of names of 88th level with the only defined value are changed to comparison
of parent variable with this value or to corresponding assignment, depending on semantics in
source code.
 If a name of 88th level has a set of values every its occurrence is transformed to disjunction of
corresponding comparisons with parent variable.</p>
      </sec>
    </sec>
    <sec id="sec-4">
      <title>Enumerated types</title>
      <p>Formal model contains a set T of enumerated types. Every type Ti є T is an unordered set of
constants Ti = {e1, …, en} with defined operations "==" (equal) and "!=" (not equal). These operations
require strong type correspondence meaning that both arguments should have the same type.
Variables in these arguments are called connected. For example, predicate a == b[i] connects a
variable a and an array b, so that a must be of the same type as elements of the array b, but it's not fair
for index i. To generate first order predicate calculus formulas in a formal model we need to detect
variables from source code, which can be represented as attributes of enumerated types, and build a
set of these types.</p>
      <p>Corresponding algorithm in a form of pseudo code with self-explanatory operators is the
following:
// 1. Collect connected variables and their values from predicates
// they are comparison operators and assignments
for each variable v {
new set CVALS(v) = collect values for v
new set CVARS(v) = collect connected variables for v
}
// 2. Collect type groups
// they are pairs &lt;set of variables, set of values&gt;
new set G = 
for each variable v {
if exists pair &lt;VARS, VALS&gt;  G: v  VARS
then { // add v to existing group</p>
      <p>VARS = VARS  {v}  CVARS(v)</p>
      <p>VALS = VALS  CVALS(v)
} else { // add new group to G</p>
      <p>G = G  {&lt;{v}  CVARS(v), CVALS(v)&gt;}
}
}
// 3. Build enumerated types
// collect pairs &lt;set of attributes, set of enumerated elements&gt;
new set T = 
for each pair &lt;VARS, VALS&gt;  G {</p>
      <p>Boolean E = true
for each variable v  VARS {
if not (check enumerated types restrictions for v)
then E = false
}
if E
then {</p>
      <p>T = T  {&lt;create set of attributes from VARS, create set of elements
from VALS&gt;}</p>
      <p>G = G \ {&lt;VARS, VALS&gt;}
}
}
Figure 2: Algorithm for building enumerated types</p>
      <p>After completion we have two sets: T containing enumerated types in a form of pairs &lt;set of
attributes, set of elements of the type&gt;, and G with groups of variables which do not fulfill restrictions
for enumerated types. Variables from G become integer attributes or are processed bytewisely as
described below.</p>
      <sec id="sec-4-1">
        <title>Let’s specify the algorithm for COBOL language:</title>
        <p>1. Whole source code is analyzed and all predicates are collected. Predicates analysis allows to
detect variables connected by operators requiring strong types correspondence (assignment,
comparison). Also all occurring values are collected for each variable. Predicates analysis is
performed by the following rules:
MOVE VAL TO VAR1
VAR1 = VAL
VAR1 NOT = VAL</p>
      </sec>
      <sec id="sec-4-2">
        <title>VAR1 is not a structure</title>
      </sec>
      <sec id="sec-4-3">
        <title>VAL is a constant</title>
        <p>MOVE TERM TO VAR1(X:Y)
VAR1(X:Y) = TERM
VAR1(X:Y) NOT = TERM</p>
      </sec>
      <sec id="sec-4-4">
        <title>VAR1(X:Y) is reference modification</title>
        <p>MOVE VAR2(X:Y) TO VAR1
VAR1 = VAR2(X:Y)
VAR1 NOT = VAR2(X:Y)</p>
      </sec>
      <sec id="sec-4-5">
        <title>VAR2(X:Y) is reference modification</title>
        <p>MOVE TERM TO STR1
STR1 = TERM
STR1 NOT = TERM</p>
      </sec>
      <sec id="sec-4-6">
        <title>STR1 is a structure</title>
        <p>MOVE STR2 TO VAR1
VAR1 = STR2
VAR1 NOT = STR2</p>
      </sec>
      <sec id="sec-4-7">
        <title>STR2 is a structure</title>
        <p>VAR1 &gt; VAR2</p>
      </sec>
      <sec id="sec-4-8">
        <title>Constant VAL is added to the set of values CVALS(VAR1)</title>
      </sec>
      <sec id="sec-4-9">
        <title>This rule is also applied to predicates generated by procedure of variables decomposition.</title>
      </sec>
      <sec id="sec-4-10">
        <title>If X or Y is not a constant then the variable VAR1 is marked for</title>
        <p>bytewise processing. If it is a structure then all its fields are also
marked as bytewise. If TERM is a name of a variable then it is
also marked as bytewise (with all the fields in a case of
structure).</p>
      </sec>
      <sec id="sec-4-11">
        <title>If both X and Y are constants then the variable VAR1 is</title>
        <p>decomposed by the algorithm described below.</p>
      </sec>
      <sec id="sec-4-12">
        <title>If X or Y is not a constant then both variables (with all the fields</title>
        <p>in a case of structures) are marked for bytewise processing.</p>
      </sec>
      <sec id="sec-4-13">
        <title>If both X and Y are constants then the variable VAR2 is decomposed by the algorithm described below.</title>
      </sec>
      <sec id="sec-4-14">
        <title>If TERM is reference modification like VAR2(X:Y) then previous rule is applied.</title>
      </sec>
      <sec id="sec-4-15">
        <title>If TERM is a constant then we break it, as character string, into</title>
        <p>parts with lengths corresponding to STR1 fields. The predicate is
transformed to a sequence of predicates (sequence of
assignments, conjunction of equalities or disjunction of
inequalities).</p>
      </sec>
      <sec id="sec-4-16">
        <title>If TERM is a variable name (can be a structure) then it is</title>
        <p>decomposed by the algorithm described below.</p>
      </sec>
      <sec id="sec-4-17">
        <title>Previous rule is applied where arguments of the predicate are swapped, i.e. TERM is VAR1 and STR1 is STR2.</title>
      </sec>
      <sec id="sec-4-18">
        <title>If any variable VAR1 or VAR2 is not numeric by definition</title>
        <p>(PICTURE 9(N) or S9(N)) then both variables are marked for
bytewise processing. It is also fair to structures.</p>
      </sec>
      <sec id="sec-4-19">
        <title>Also operations &gt;=, &lt;, &lt;=, NOT &gt;, NOT &lt;</title>
        <p>Figure 3: Rules for analysis of COBOL statements
2. Connected variables are merged into groups so that all variables in each group have the same
type. So, the set VALS of all found values of these variables forms a set of elements of
corresponding enumerated type. Also auxiliary element OTHER is added for an abstract
representation of other values which don't occur in code.
3. Enumerated type is generated for each group where all variables fulfill the following
restrictions:
 no &gt;, &gt;=, &lt;, &lt;= comparisons with other variables or expressions (comparisons with numeric
constants are allowed);
 no arithmetic operations;
 no occurrences of a variable as an array index;
 no operations over strings (like concatenation or substring), no substring operations with
variable indices;
 no operator REDEFINES in DATA DIVISION (*)
 no operations over whole structures if a variable is a field of structure (*).
4. For groups where restrictions marked with asterisk (*) are not fulfilled, a method for variables
decomposition is applied (described below). It produces new variables and new groups and this
algorithm is repeated for them.</p>
      </sec>
      <sec id="sec-4-20">
        <title>Names of attributes in the formal model are built as full qualified name of corresponding variable (names of all structures above this variable are appropriately joined).</title>
      </sec>
    </sec>
    <sec id="sec-5">
      <title>Translation of numeric constants</title>
      <p>Enumerated types are created for groups where variables are compared with numeric constants by
operations &gt;, &gt;=, &lt;, &lt;= by the following algorithm:
1. Build a set of intervals I. Initially, I = {(-,+)}. Every constant c which occurs in
comparison operations &gt;, &gt;=, &lt;, &lt;=, ==, != with a variable from current group, splits the interval
from І which contains c to three: c  (n,m)  (n,m)  I  I = (I \ {(n,m)})  {(n,c),[c,c],(c,m)}.
2. Create enumerated type T from the set of intervals І, where one and only one element
corresponds to each interval.
3. For each predicate with comparison &gt;, &gt;=, &lt;, &lt;=, ==, != of a variable from current group with
a constant, calculate a subset of allowed intervals from I and substitute this predicate with
disjunction of equalities of the variable with corresponding elements of the type T.
For example, let we have predicates v &lt; 0 and v &gt;= 5. Then:</p>
      <p>
        I = {(-,0), [0,0], (0,5), [
        <xref ref-type="bibr" rid="ref5 ref5">5,5</xref>
        ], (5,+)}, T = {LS_0, EQ_0, GT_0_LS_5, EQ_5, GT_5},
v &lt; 0  v == LS_0, v &gt;= 5  v == EQ_5 || v == GT_5.
      </p>
    </sec>
    <sec id="sec-6">
      <title>Numeric variables</title>
      <p>Binary variables of Cobol language (BINARY, COMPUTATIONAL or COMP) are translated to
integer attributes. According to the Cobol description, a binary variable with a PICTURE description
of four or fewer decimal digits (S9(1) to S9(4) and 9(1) to 9 (4)) occupies 2 bytes; five to nine
decimal digits, 4 bytes; and 10 to 18 decimal digits, 8 bytes. We abstract of the variables size while
creating integer attributes, however, it is important for the bytewise approach.</p>
      <p>Numeric variables (not binary) with PICTURE description 9(N) or S9(N) are translated to integer
attributes in the same way as binary but differ in bytewise representation. Each digit occupies one
byte with a code of digit symbol.</p>
      <p>If all integer variables from a particular type group fulfill restrictions of enumerated types then an
enumerated type and attributes are created.</p>
    </sec>
    <sec id="sec-7">
      <title>Decomposition of variables</title>
      <p>
        In the case when different structures are compared with each other, one is assigned to another, or
they overlap in memory using the REDEFINES operator, it is necessary to bring them to one common
structure. To work with structures overlapping in memory, it is common to use union semantics [
        <xref ref-type="bibr" rid="ref11 ref2">2,
11</xref>
        ], but this has the disadvantage of not being able to use two fields of different structures at the same
time. In C++, the field to which the last assignment was made is considered active, and the behavior
when reading inactive fields is undefined. In Java, there is no direct analogue of union, and even if to
make an implementation with data copying between fields, difficulties arise when the field types are
not comparable. In general, for non-comparable structures, the bytewise approach is used, where, in
one way or another, each byte of the variable is processed separately. This leads both to an increase in
the number of states during modeling, and to the impossibility of reading and understanding such
artifacts by a human. To avoid the bytewise approach, we suggest making the minimum necessary
decomposition of the fields of the structures. For simplicity, it is better to show the algorithm on
examples.
      </p>
      <p>Example 1. Let we have two non-comparable structures STR1 and STR2 with lengths 5 and 6 that
overlap in memory (starting from the same address). We will present a version of translation into a
Java class using the bytewise approach:
01 STR1.</p>
      <p>05 A PIC X(2).</p>
      <p>05 B PIC X(3).
01 STR2 REDEFINES STR1.</p>
      <p>05 C PIC X(1).
05 D PIC X(2).
05 E PIC X(3).</p>
      <p>
        public class STR1 {
char[] data = new char[
        <xref ref-type="bibr" rid="ref6">6</xref>
        ];
String getA() {
      </p>
      <p>return String.valueOf(data,0,2);
}
String setA(String s) {
for (int i = 0; i &lt; 2; i++)
if (i &lt; s.length())</p>
      <p>data[i] = s.charAt(i);
else</p>
      <p>data[i] = ' ';
}
...</p>
      <p>String getE() {</p>
      <p>return String.valueOf(data,3,3);
}
String setE(String s) {
for (int i = 0; i &lt; 3; i++)
if (i &lt; s.length())</p>
      <p>data[3 + i] = s.charAt(i);
else</p>
      <p>data[3 + i] = ' ';
}</p>
      <sec id="sec-7-1">
        <title>Fields of these structures overlap in memory as shown in the Figure 5. Let’s divide all fields of one structure by boundaries of fields of another, and vice versa, as in the Figure 6.</title>
        <p>A_FIELD1 A_FIELD2
C D_FIELD1
Figure 6: Fields decomposition</p>
        <p>B_FIELD1
D_FIELD2</p>
        <p>B_FIELD2
E_FIELD1</p>
        <p>E_FIELD2</p>
        <p>Now, we can map fields of structures one-to-one and apply the algorithm for building enumerated
types.</p>
        <p>Besides overlaps in memory (REDEFINES), decomposition is required for statements STR1 =
STR2 and MOVE STR1 TO STR2. To do this, align the structures along the left edge and make a
similar decomposition, as well as transform the statements accordingly, as in the Figure 7.
STR1 = STR2 is transformed to:
A_FIELD1 = C AND A_FIELD2 = D_FIELD1 AND … AND E_FIELD2 = SPACE
MOVE STR1 TO STR2 is transformed to:
C := A_FIELD1; D_FIELD1 := A_FIELD2; …; E_FIELD2 := SPACE;
Figure 7: Statements transformation</p>
        <p>When comparing and assigning alphanumeric variables of different lengths in Cobol, the shorter
one is prolonged by spaces, hence the SPACE in the E_FIELD2 field.</p>
        <p>Example 2. Take the structure STR2 from the example 1 and the variable N defined as
01 N PIC 9(4). In the case of numeric variables, they must be right-aligned and leading zeroes are
provided for shorter one. Then, for the statements STR2 = N and MOVE N TO STR2, decomposition
is shown in the Figure 8.
0 0
C D_FIELD1
Figure 8: Fields decomposition</p>
        <p>N_RFIELD2
D_FIELD2</p>
        <p>N_RFIELD1</p>
        <p>E</p>
        <p>Analogous decomposition is applied by substrings boundaries in the statement VAR(X:Y)
(reference modification) with constant indices. Next consider arrays.</p>
        <p>Example 3. Let the structure STR1 contains an array of structures ARR1 with length of 3
elements, see the Figure 9.
01 STR1.</p>
        <p>05 ARR1 OCCURS 3 TIMES.</p>
        <p>10 A PIC X(1).</p>
        <p>10 B PIC X(2).</p>
      </sec>
      <sec id="sec-7-2">
        <title>In this case of decomposition it’s required to unfold the array by elements as in the Figure 10.</title>
        <p>A_1 B_1 A_2 B_2_FIELD1 B_2_FIELD2 A_3
C D_FIELD1 D_FIELD2 E F_FIELD1 F_FIELD2
Figure 10: Fields decomposition
B_3</p>
        <p>In some cases, we can avoid unfolding arrays. We have developed a procedure for determining
such cases and show one of them in the following example.</p>
        <p>Example 4. Take the structure STR1 from the example 3 and the variable 01 S PIC X(12).
Variable S is 12 bytes long, while the entire array ARR1 is 9 bytes. Then the variable S can be
divided into a corresponding array and a tail of length 3, and the structure STR1 will remain
unchanged, see the Figure 11.
01 STR1.</p>
        <p>05 ARR1 OCCURS 3 TIMES.</p>
        <p>10 A PIC X(1).</p>
        <p>10 B PIC X(2).</p>
        <p>In general, decomposition of variables allows to group new fields of different structures and build
enumerated types for them. In the worst case, variables will be split into fields of one byte each,
which is equivalent to the bytewise approach.</p>
      </sec>
    </sec>
    <sec id="sec-8">
      <title>The bytewise approach</title>
      <p>The bytewise approach is used in cases where the constraints of enumerated types are not met and
integer attributes cannot be generated, for example:
 VAR(X:Y) (reference modification) – access to a substring with variable indices;
 STRING – operation of concatenation of several values into one;
 Comparisons &gt;, &gt;=, &lt;, &lt;= of non-numeric variables or structures requires lexicographical
processing.</p>
      <p>For bytewise processing, variables are represented as arrays of integers in the formal model. Each
element of the array corresponds to one byte of memory.</p>
      <p>The bytewise approach generates complex formulas or even behaviors implemented by source
code language operators. We consider them as atomic transitions, and implement them as external
functions in the C++ language, the calls of which are located in the preconditions and postconditions
of model transitions. Thus, during simulation, we avoid generating many unnecessary states, but
completely preserve the semantics of the source code. The Figure 12 shows the implementation of one
of the simple functions cobol_move_int, which is used for bytewise processing of the construction
MOVE N TO VAR, where N is an integer number, VAR is not a binary variable (there is another
function for binary).
void cobol_move_int(int attr, int number) {
// attr – identifier of an attribute in the model, the attribute must be an array of integers
// number – a number to be written as a string
string str = to_string(abs(number)); // convert modulus of the number to a string
int lens = str.length(); // length of the string
int len = get_array_size(attr); // length of the array
int symb = 0;
for (int i = 0; i &lt; len; ++i) { // for each byte of the array attr
if (i &lt; len - lens)</p>
      <p>symb = '0'; // fill the beginning by zeroes
else if (i == len - lens &amp;&amp; number &lt; 0)
// set a flag of negative number according to Cobol semantics
symb = str[0] | 0b01000000;
else</p>
      <p>symb = str[i + lens - len]; // take current symbol of the string
set_array_value(attr, i, symb); // write the symbol in the array
}
return 0;
}
Figure 12: Implementation of cobol_move_int function</p>
      <p>Such external functions are implemented to simulate all cases of accessing variables in bytewise
representation – for writing strings, filling with one character (LOW-VALUE, SPACE, ZERO, etc.),
writing and extracting numbers in alphanumeric and binary representations, comparing alphanumeric,
numeric binary and non-binary variables in various combinations, value type checks.</p>
    </sec>
    <sec id="sec-9">
      <title>Conclusions</title>
      <p>
        The proposed method of building formal models was applied to several medium-sized projects
(10,000 – 100,000 lines of code) for further use in test generation [
        <xref ref-type="bibr" rid="ref13 ref14">13, 14</xref>
        ] and behavior analysis [
        <xref ref-type="bibr" rid="ref12 ref16">12,
16</xref>
        ] and showed its viability. The specifics of projects in the Cobol language is such that the definition
of static memory (DATA DIVISION) occupies most of the code, so the generated models contain
significantly fewer transitions than lines of code. The methods of constructing enumerated types and
decomposing variables made it possible to effectively search the state space for the purpose of
generating executable tests. Automated testing of the production version of the Cobol to Java
translator on a banking project was performed and 5 defects were found in the translator and 2 in the
source code. On larger projects, the method of variables decomposition played a special role, it
reduced the size of memory that is processed bytewisely, on average, by 3 times. This not only
increased the efficiency of test generation and allowed to reach more coverage, but also significantly
simplified the models for human understanding and reduced the time to debug the tests and the
systems under testing.
      </p>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          [1]
          <string-name>
            <given-names>Patrick</given-names>
            <surname>Stanard</surname>
          </string-name>
          ,
          <article-title>A history of COBOL, why it's so popular today, where to find COBOL talent and the benefits of migrating to v6.3</article-title>
          . https://techchannel.com/Enterprise/03/2021/businesssystems-cobol. (
          <year>2021</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          [2]
          <string-name>
            <given-names>M.</given-names>
            <surname>Ceccato</surname>
          </string-name>
          ,
          <string-name>
            <given-names>T.R.</given-names>
            <surname>Dean</surname>
          </string-name>
          ,
          <string-name>
            <given-names>P.</given-names>
            <surname>Tonella</surname>
          </string-name>
          ,
          <string-name>
            <given-names>D.</given-names>
            <surname>Marchignoli</surname>
          </string-name>
          ,
          <article-title>Data Model Reverse Engineering in Migrating a Legacy System to Java</article-title>
          , Reverse Engineering,
          <year>2008</year>
          . WCRE '
          <volume>08</volume>
          . 15th Working Conference on , vol., no., pp.
          <fpage>177</fpage>
          -
          <lpage>186</lpage>
          . (
          <year>2008</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          [3]
          <string-name>
            <given-names>Yohei</given-names>
            <surname>Ueda</surname>
          </string-name>
          ,
          <string-name>
            <given-names>Moriyoshi</given-names>
            <surname>Ohara</surname>
          </string-name>
          .
          <article-title>Refactoring of COBOL data models based on similarities of data field name</article-title>
          . (
          <year>2014</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          [4]
          <string-name>
            <given-names>European</given-names>
            <surname>Telecommunications Standards</surname>
          </string-name>
          <article-title>Institute</article-title>
          . TTCN-3:
          <string-name>
            <given-names>Core</given-names>
            <surname>Language</surname>
          </string-name>
          .
          <source>ES 201 873-1 4.11.1</source>
          . (
          <year>2019</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref5">
        <mixed-citation>
          [5]
          <string-name>
            <given-names>International</given-names>
            <surname>Telecommunications Union. Message Sequence</surname>
          </string-name>
          Charts
          <string-name>
            <surname>Z.</surname>
          </string-name>
          <year>120</year>
          . (
          <year>2011</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref6">
        <mixed-citation>
          [6]
          <string-name>
            <given-names>A.</given-names>
            <surname>Letichevsky</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J.</given-names>
            <surname>Kapitonova</surname>
          </string-name>
          ,
          <string-name>
            <given-names>V.</given-names>
            <surname>Kotlyarov</surname>
          </string-name>
          ,
          <string-name>
            <given-names>V.</given-names>
            <surname>Volkov</surname>
          </string-name>
          ,
          <string-name>
            <given-names>A. Letichevsky</given-names>
            <surname>Jr.</surname>
          </string-name>
          , and
          <string-name>
            <given-names>T.</given-names>
            <surname>Weigert</surname>
          </string-name>
          ,
          <article-title>Semantics of Message Sequence Charts</article-title>
          .
          <source>Proc. 12th International SDL Forum: Model Driven, LNCS</source>
          , vol.
          <volume>3530</volume>
          , pp.
          <fpage>117</fpage>
          -
          <lpage>132</lpage>
          . (
          <year>2005</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref7">
        <mixed-citation>
          [7]
          <string-name>
            <given-names>M.</given-names>
            <surname>Wynne</surname>
          </string-name>
          and
          <string-name>
            <given-names>A.</given-names>
            <surname>Hellesoy</surname>
          </string-name>
          ,
          <source>The Cucumber Book. The Pragmatic Bookshelf</source>
          . (
          <year>2012</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref8">
        <mixed-citation>
          [8]
          <string-name>
            <surname>Holger</surname>
            <given-names>M.</given-names>
          </string-name>
          <string-name>
            <surname>Kienle</surname>
          </string-name>
          ,
          <article-title>Hausi A. Müller, Rigi - An environment for software reverse engineering, exploration, visualization, and redocumentation</article-title>
          ,
          <source>Science of Computer Programming</source>
          , Volume
          <volume>75</volume>
          , Issue 4, pp.
          <fpage>247</fpage>
          -
          <lpage>263</lpage>
          . (
          <year>2010</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref9">
        <mixed-citation>
          [9]
          <string-name>
            <given-names>Ákos</given-names>
            <surname>Hajnal</surname>
          </string-name>
          &amp; István
          <string-name>
            <surname>Forgács</surname>
          </string-name>
          ,
          <article-title>A demand-driven approach to slicing legacy COBOL systems</article-title>
          .
          <source>Journal of Software Maintenance</source>
          ,
          <volume>24</volume>
          , pp.
          <fpage>67</fpage>
          -
          <lpage>82</lpage>
          . (
          <year>2012</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref10">
        <mixed-citation>
          [10]
          <string-name>
            <given-names>A.</given-names>
            <surname>Sivagnana Ganesan</surname>
          </string-name>
          ,
          <string-name>
            <given-names>T.</given-names>
            <surname>Chithralekha</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Rajapandian</surname>
          </string-name>
          ,
          <article-title>A Formal Model for Legacy System Understanding</article-title>
          .
          <source>I.J. Intelligent Systems and Applications</source>
          ,
          <volume>10</volume>
          , pp.
          <fpage>27</fpage>
          -
          <lpage>41</lpage>
          . (
          <year>2018</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref11">
        <mixed-citation>
          [11]
          <string-name>
            <surname>Arie</surname>
            <given-names>van Deursen</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Leon Moone</surname>
          </string-name>
          ,
          <source>Exploring Legacy Systems Using Types. Proceedings Seventh Working Conference on Reverse Engineering. IEEE</source>
          , pp.
          <fpage>32</fpage>
          -
          <lpage>41</lpage>
          . (
          <year>2000</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref12">
        <mixed-citation>
          [12]
          <string-name>
            <surname>А. Guba</surname>
          </string-name>
          , et al.,
          <article-title>A method for business logic extraction from legacy COBOL code of industrial systems</article-title>
          .
          <source>In: Proceedings of the 10th International Conference on Programming UkrPROG2016, CEUR-WS</source>
          , vol.
          <volume>1631</volume>
          , pp.
          <fpage>17</fpage>
          -
          <lpage>25</lpage>
          (
          <year>2016</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref13">
        <mixed-citation>
          [13]
          <string-name>
            <given-names>T.</given-names>
            <surname>Weigert</surname>
          </string-name>
          , et al.,
          <article-title>Generating test suites to validate legacy systems</article-title>
          .
          <source>In: Fonseca i Casas</source>
          ,
          <string-name>
            <given-names>P.</given-names>
            ,
            <surname>Sancho</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            -R.,
            <surname>Sherratt</surname>
          </string-name>
          ,
          <string-name>
            <surname>E. (eds.) SAM</surname>
          </string-name>
          <year>2019</year>
          .
          <article-title>LNCS</article-title>
          , vol.
          <volume>11753</volume>
          , pp.
          <fpage>3</fpage>
          -
          <lpage>23</lpage>
          . Springer, Cham (
          <year>2019</year>
          ). https://doi.org/10.1007/978-3-
          <fpage>030</fpage>
          -30690-
          <issue>8</issue>
          _
          <fpage>1</fpage>
        </mixed-citation>
      </ref>
      <ref id="ref14">
        <mixed-citation>
          [14]
          <string-name>
            <given-names>A.</given-names>
            <surname>Kolchin</surname>
          </string-name>
          ,
          <string-name>
            <given-names>S.</given-names>
            <surname>Potiyenko</surname>
          </string-name>
          , T. Weigert,
          <article-title>Challenges for automated, model-based test scenario generation</article-title>
          .
          <source>Comm. Comput. Inf. Sci</source>
          .
          <volume>1078</volume>
          ,
          <fpage>182</fpage>
          -
          <lpage>194</lpage>
          . (
          <year>2019</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref15">
        <mixed-citation>
          [15]
          <string-name>
            <surname>Edsger</surname>
            <given-names>W.</given-names>
          </string-name>
          <string-name>
            <surname>Dijkstra</surname>
          </string-name>
          ,
          <article-title>Guarded commands, nondeterminacy and formal derivation of programs</article-title>
          .
          <source>Communications of the ACM 18.8</source>
          (
          <issue>1975</issue>
          ), pp.
          <fpage>453</fpage>
          -
          <lpage>457</lpage>
          . (
          <year>1975</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref16">
        <mixed-citation>
          [16]
          <string-name>
            <given-names>A.</given-names>
            <surname>Kolchin</surname>
          </string-name>
          ,
          <article-title>Interactive method for cumulative analysis of software formal models behavior</article-title>
          .
          <source>Proc. of the 11th Int. Conf. on Programming UkrPROG'</source>
          <year>2018</year>
          ,
          <article-title>CEUR-</article-title>
          WS vol.
          <volume>2139</volume>
          , pp.
          <fpage>115</fpage>
          -
          <lpage>123</lpage>
          . (
          <year>2018</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref17">
        <mixed-citation>
          [17]
          <string-name>
            <given-names>A.</given-names>
            <surname>Letichevsky</surname>
          </string-name>
          ,
          <string-name>
            <given-names>A.</given-names>
            <surname>Godlevsky</surname>
          </string-name>
          ,
          <string-name>
            <surname>O.</surname>
          </string-name>
          <article-title>Letychevskyy (jr</article-title>
          .),
          <string-name>
            <given-names>S.</given-names>
            <surname>Potiyenko</surname>
          </string-name>
          ,
          <string-name>
            <given-names>V.</given-names>
            <surname>Peschanenko</surname>
          </string-name>
          ,
          <article-title>Properties of VRS predicate transformer</article-title>
          .
          <source>Cybernetics and System Analysis</source>
          , vol.
          <volume>46</volume>
          , pp.
          <fpage>521</fpage>
          -
          <lpage>532</lpage>
          . (
          <year>2010</year>
          )
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>