Using data
Where fields can be defined
Fields can be defined in classes and in a data division or DATA statement for subroutines, functions, methods, or the main routine. For example, you can define fields as follows:
class ab ,a10 subroutine record ac ,d2 proc begin data ad ,i4 end endsubroutine endclass
Data organization
Data can be located in static records, local records, common records, class records, class fields, literals, global data sections, and procedure division DATA statements.
Defining a record
Records are areas of computer memory in which dynamic data is stored during program execution. All Synergy DBL data is stored in records. Each record consists of one or more fields, which may or may not be part of a group.
The record itself may or may not be part of a class. If it is part of a class, it is called a class record.
Each routine can have local record areas that it alone can access. In addition to local areas, a routine can define or access shareable data areas using common records or global data sections.
A record’s fields determine the internal layout of the data area associated with that record. Data is stored sequentially in the order that the fields are declared in your data division. The total size of a record is the sum of the sizes of the data areas allocated to all of its fields, including any field alignment.
A record can be named or unnamed. If you name a record, you can use the name to refer to the entire data space allocated to that record. For example, you probably use record names in Synergy DBL I/O statements to read records from data files. If you refer to a record in your procedure division, Synergy DBL treats the record as an alpha field. A named record cannot be larger than 65,535 bytes on a 32-bit machine running traditional Synergy.
With named records, the record definition often reflects the structure of records in the data file. The contents of the record area are processed, and the information is transmitted to or received from the data file.
Most programs, however, also require working storage for values that are not associated with data file I/O activity. Some examples of working storage variables are as follows:
- Loop-control variables
- Internal processing flags
- Variables to hold transitional results
Here’s where unnamed records become useful: usually you’ll want to declare this type of variable as part of one or more unnamed work records. The record definition allocates a section of data space to hold the working variables required by your program.
Sometimes you’ll want some variables in a subroutine to maintain their contents between calls to the subroutine. Defining the variables in a static record does the trick. In a static record, the data areas are permanent and are therefore maintained between subroutine calls.
To allocate read-only data space, you can also define literal data space that is either local, global, or external (allocated in a previous routine).
Local records
Use the RECORD statement to define local records. (When you’re defining a local record, the RECORD statement must not be part of a GLOBAL-ENDGLOBAL statement block.) The local record and all of its fields and groups are called local variables.
Only the routine that defines a local variable can directly access that variable; a local variable cannot be referenced directly by any other routine. However, local data can be referenced indirectly as an argument in a subroutine, provided the calling program specifies the name of a local variable in the XCALL statement that calls the subroutine.
See RECORD-ENDRECORD for syntax.
A record’s size is the total size of its fields.
Defining a common record
Use the COMMON statement to define records that are accessible to other subroutines or the main routine. COMMON enables routines to share common records and variables without having to pass the data as arguments. Using common data to pass information between a main routine and its subroutines is often faster than using subroutine arguments.
Common data remains resident in memory for as long as the program is running.
The COMMON statement has two forms: GLOBAL COMMON and EXTERNAL COMMON. The GLOBAL COMMON form creates new data space, while the EXTERNAL COMMON form references data that must be defined elsewhere. You can use the GLOBAL COMMON statement to define a shared data record and its component fields in either the main routine or a subroutine. (In previous versions of Synergy DBL, the COMMON statement could only define data in the main routine, because there were no EXTERNAL or GLOBAL qualifiers.)
Using EXTERNAL COMMON statements establishes references to data areas in the defining routine. Since the physical layout of a common record is defined by the GLOBAL COMMON declaration, the layout is not known while the referring routines are being compiled. Because Synergy DBL cannot check the layouts during compilation of EXTERNAL COMMON statements, the compiler creates a symbolic reference to the named common variable. Linking (the process that combines the main routine and its subroutines into an executable program) determines the correct data address for each symbolic reference. Each external common variable references data starting at the same point as the corresponding global common variable.
Only the starting point of each external common variable is fixed while a program is being linked. The compiler can’t check the sizes or types of the individual fields for the same reason it can’t check the overall field layout. For example, subroutine A can declare a field named cust to be 15 characters long, while subroutine B can declare the same field to be only 8 characters long. In this situation, only the first 8 characters of subroutine A’s field are referenced. If subroutine B declares cust to be 23 characters long, the entire cust field of subroutine A, as well as the 8 characters that follow it, are referenced.
Synergy DBL stores data declared as common in a separate space from data that is local to a routine. Therefore, the data space of a record that follows a common is not contiguous with the data space of the common.
See COMMON-ENDCOMMON for syntax.
Defining a literal
The LITERAL statement defines read-only data (which is placed in a shareable read-only segment on OpenVMS). Literal data is only emitted by the compiler if it is a global literal or if any of the literal fields is accessed in the compilation unit. If unnamed literal sections are encountered and do not have overlays or use the @position field qualifier, only those literals that are used are emitted, and all integer literals are aligned on native boundaries.
A literal is undefined until the place it is to be used is known. (If literals are passed or used in places that take argument types, they are converted implicitly to the correct type. For example, “123” passed to n or i is passed as an int.) If the type cannot be determined at that point, the defaults for literals are as follows:
Literal |
Default type |
---|---|
Alpha (such as “abc”) |
a |
Decimal (such as “123”) |
decimal |
Implied-decimal (such as “345.45”) |
d. |
Note that passing implied literals works differently in Synergy .NET than in C#. For example, passing 12.3 to Add() would give a boxed decimal in Synergy .NET, but a boxed double in C#.
Defining a global data section
Global data sections are shared data areas that are defined by the name of the area rather than the record or field name. Use the RECORD statement within a GLOBAL-ENDGLOBAL statement block to define shared data in a global data section. Each GLOBAL statement names a data area that is independent of and accessible to any routine; you can define a global data section in one place and then reference it anywhere. Synergy DBL allocates global data space to global data sections in the order in which the records are declared in the data division.
Objects cannot be defined in a global data section. |
Here’s an example of a global data declaration:
global data section glb record alex fld1a ,a6 fld2a ,d3.2 record mary fld1m ,d2 fld2m ,d7 endglobal
The example above defines a reference to a global data section named glb. The routine declares the first 18 characters of the global area and divides them into two consecutive global records, alex and mary, of 9 characters each.
The largest uniquely named global data section definition determines the size of that global area. For example, if global data section glb is also referenced in another routine as being 193 characters long, glb is established as 193 characters long when the program is executed. The example definition above references only the first 18 characters of the global area.
Be careful when changing the size of a global data section: If an ELB increases the defined size of a global data section that’s owned externally, and no programs are relinked against the ELB, executing those programs could cause memory access violations. If you change the size of a global data section, all programs that use it must be relinked. |
Because the Synergy compiler has no way of knowing whether other routines are referring to a given global area, you must make sure that all of the necessary routines assign the same name to that global area. When you reference the same data in another routine, the names of the global data sections must be the same.
Global variables serve an important function when you are developing libraries of interrelated subroutines or when you need a scratch data area. Like common variables, when you use global variables, your subroutines can share different data sets without affecting the routines that called them. Because the calling routines are not concerned with the content and layout of global areas, you don’t have to modify your routines when you change these areas.
The main difference between common data and global data is in the way the data is accessed. While common variables are accessed relative to the name of each common variable, global data section variables are accessed relative to the name of the global data section. Think of global data sections as overlaid record groups, with each routine defining its own layout of a given global data section and the size of each named section being the size of the largest definition.
Synergy DBL stores data of different types in separate spaces. For example, all static record data is gathered together, even if other types of data types are declared between static record data. Therefore, the data space of a record that follows a global data section is not contiguous with the data space of the global data section.
Do not depend on the relative placement of one global variable to another. |
See GLOBAL-ENDGLOBAL and RECORD-ENDRECORD for syntax.
Defining data in the procedure division
The DATA statement enables you to define data in the procedure division. See DATA for more information.
The scope of the data is the BEGIN-END block in which it is defined. (In Synergy .NET, if the DATA statement is not contained in a BEGIN-END block, the scope is the method in which the data is defined.) Data variables are not initialized unless they are objects or have an initial value specified. In other words, they operate the same as stack records.
Data layout
Defining a group
A group is a subrecord within a record, structure, or class or within the layout of an argument passed as an alpha field. Fields or other group declarations can be members of a group. Groups are defined by the GROUP statement, and they enable you to maintain record arrays easily. See GROUP-ENDGROUP for more information.
A field or group inside a common record defines a global definition or reference. However, a field inside a group within a common record is always local.
For example, let’s assume you have the following declaration:
global common pet ,a ;Global reference dog ,a5 ;Global reference cat ,a3 ;Global reference group breed ,a ;Global reference long_hair ,a4 ;Local reference short_hair ,a4 ;Local reference group color ,a ;Local reference white ,a3 ;Local reference calico ,a3 ;Local reference endgroup endgroup
Pet, dog, cat, and breed are all global data, but long_hair, short_hair, color, white, and calico are local. This means that an EXTERNAL COMMON reference to pet in another routine is valid, but a reference to white is not. (A linker error will be generated.)
Global definitions and references are only made on fields and on groups at the outermost level. (In the example above, breed is the group at the outermost level.) All references to or definitions of fields and subgroups within a group are relative to the beginning of that group. See Variable path specifications for more information about referencing a field within a group.
Defining a structure
There are three kinds of structures: local routine structures, global structures (defined outside a routine or class), and class structures. All structures are defined by the STRUCTURE statement. Fields and groups can be members of a structure. See STRUCTURE-ENDSTRUCTURE for more information.
Using a structure with a structfield
A structfield is a named reference to a structure and an allocation of memory onto which the structure is mapped. You can use a structfield as a record wherever a Synergy record can be used (in other words, with I/O routines).
When a structure is used through the structfield syntax, all fields in the structfield are initialized according to the following precedence rules:
1. | Use the initial field value if it has been specified. |
2. | Use the default value based on the field type. |
To access a structfield, prefix the field name with the locally declared variable name (var1 in the example below) that represents the structure. For example,
var1.field1 = 5 x = var1.field1
See structure for an example of how to declare a field as a structure and use that structure.
Sometimes you must redefine the format of a data area. For example, if you have a data file whose records are all the same size but have different layouts, as determined by a record-type variable in each record, you will probably want your program to use the same area of internal storage repeatedly during different stages of execution.
In Synergy DBL, records, commons, literals, groups, and fields can overlay one another, thus giving your data several different layouts without defining any new data. When you define an alternate layout for a data area, you must include an “overlay indicator” immediately after the name of the alternate layout in your record definition. The overlay indicator looks like this:
,X
If the alternate layout is not named, place the overlay indicator where you would otherwise specify the name. The presence of the overlay indicator causes the field definitions that follow it to reference the data area in the most recently defined nonoverlay data area.
You can also use the field position indicator (@) to specify an overlay. See Specifying a field position indicator.
The following rules apply to overlays:
- Initial values are not allowed in overlays.
- A global common can only overlay another global common.
- An external common cannot overlay anything. This is because it is only a reference to a global common data space. Any overlay indicators are ignored.
- A (local) record can only overlay another (local) record. The overlaying record cannot be longer than the record being overlaid.
- A stack record can only overlay another stack record.
- A static record can only overlay another static record.
- (Traditional Synergy) A (local) record, can overlay a named global common or external common. The overlaying record cannot be longer than the global/external common being overlaid. (This functionality is supported for backward compatibility only. While you may encounter code that does this, we don’t recommend it.)
- A (local) literal can only overlay another (local) literal; the overlaid literal must be named.
- A global literal can only overlay another global literal; the overlaid literal must be named.
- An external literal cannot overlay anything. This is because it is only a reference to a global literal data space. Any overlay indicators are ignored.
- A loose class field cannot be used with the @position syntax.
- When a record or group contains object fields, the record or group cannot be overlaid with ,X, and neither can the fields using the @position syntax to overlay the object fields. A named record, group, or common that contains object fields cannot be used in any statement (including the result of an assignment statement) that modifies the record or group. To clear such records or groups, use the INIT statement instead.
Here are some examples of overlaid and nonoverlaid records:
record info ;Named nonoverlaid record time ,d6 date ,d6 record ,x ;Unnamed overlay record hr ,d2 min ,d2 sec ,d2 record ,x ;Unnamed overlay record current ,d12 global common cmn1 ;Named global common c_id ,a4 c_code ,d2 c_name ,a20 global common ,x ;Named global common overlay c_key ,a6
Variable hr refers to the first two characters of variable time, variable min refers to the next two characters of variable time, and variable sec refers to the last two characters of variable time. Variable current refers to the entire data area allocated to info. Variable c_key refers to the first two fields defined in cmn1: c_id and c_code.