Problem with COBOL move to comp-3 variable
Solution 1
In COBOL, Group level data are typeless and are moved without casting.
Element level data always have an associated data type. Typed
data are cast to match the type
of the receiving element during a MOVE
.
In the first instance you MOVE
a literal numeric value (112011
) to a packed decimal field and the compiler converts it to the correct data type in the process. Just as you would expect in any programming language.
In the second instance you MOVE
a literal value to a group item. Since this is a group item the compiler cannot 'know' the intended data type so it always does group moves as character data (no numeric conversions). This is fine when the receiving item has a PICTURE
clause that is compatible with character data - which FIELD-A
and FIELD-B
of SUB-STRUCT-1
are. There is no difference in the internal representation of a 9
when stored as PIC X
and when stored as PIC 9
. Both are assumed USAGE DISPLAY
.
Now when you do a group level move from SUB-STRUCT-1
to a COMP-3 (Packed Decimal) you effectively tell the compiler not to convert from DISPLAY
to COMP-3
format. And that is what you get.
Try the following modifications to your code. Using REDEFINES
creates
a numeric elementary item for the move. COBOL will do the appropriate
data conversions when moving elementary data.
01 STRUCT-2.
03 SUB-STRUCT-1.
05 FIELD-A PIC 9(2).
05 FIELD-B PIC 9(4).
03 SUB-STRUCT-1N REDEFINES
SUB-STRUCT-1 PIC 9(6).
03 SUB-STRUCT-2.
05 FIELD-A PIC 9(4).
05 FIELD-B PIC 9(2).
05 FIELD-C PIC 9(2).
03 SUB-STRUCT-2N REDEFINES
SUB-STRUCT-2 PIC 9(8).
And the following code:
* 3RD TEST:
MOVE 112011 TO SUB-STRUCT-1.
MOVE 20100113 TO SUB-STRUCT-2.
MOVE SUB-STRUCT-1N TO FIELD-A OF STRUCT-1
MOVE SUB-STRUCT-2N TO FIELD-B OF STRUCT-1
DISPLAY "SUB-STRUCT-1 : " SUB-STRUCT-1
DISPLAY "SUB-STRUCT-2 : " SUB-STRUCT-2
DISPLAY "FIELD-A : " FIELD-A OF STRUCT-1
DISPLAY "FIELD-B : " FIELD-B OF STRUCT-1
Beware: Moving character data into a COMP-3 field may give you the dreaded SOC7 data exception abend when the receiving item is referenced. This is because not all bit patterns are valid COMP-3 numbers.
Solution 2
You have 2 Issues.
COBOL has several Numeric Data Structures. Each has its own set of rules.
For PACKED DECIMAL ( COMP-3 )
• The numeric components of the PIC clause should ALWAYS add up to an ODD number.
• The decimal marker “V” determines the placement of the decimal point.
• The individual element MOVE and math functions will maintain the decimal value alignment – both high and low level truncation is possible
• Numeric data type conversion (zone decimal to packed & binary to packed) is handled for you.
e.g. S9(5)V9(2) COMP-3.
including the 2 decimal positions>
Length is calculated as ROUND UP[ (7 + 1) / 2] = 4 bytes
S9(6)V9(2) COMP-3.
including the 2 decimal positions > Length is calculated as ROUND UP[(8 + 1) / 2] = 5 bytes But the 1st ½ byte is un-addressable
The last ½ byte of the COMP-3 fields is the HEXIDECIMAL representation of the sign.
The sign ½ byte values are C = signed positive D = signed negative F = unsigned (non COBOL).
S9(6)V9(3) COMP-3 VALUE 123.45.
Length is calculated as ROUND UP[(9 + 1) / 2] = 5 bytes
Contains X’00 01 23 45 0C’
Note the decimal alignment & zero padding.
Group Level MOVE rules
COBOL Data field structures are define as hierarchical structures.
The 01 H-L group field – & any sub-group level field –
- Is almost always an implied CHARACTER string value
- If an individual element field is a 01 or 77 level – then it can be numeric.
- Individual element fields defined as a numeric under a group or sub-group level will be treated as numeric if referenced as an Individual element field.
- Numeric rules apply. o Right justify o decimal place alignment o pad H-L (½ bytes) with zeros o Numeric data type conversion
The receiving field of a MOVE or math calculation determines if a numeric data conversion will occur.
Numeric Data Conversion If you MOVE or perform a math calculation using any sending field type (group or element) to any receiving individual element field defined using a numeric PIC clause --- then numeric data conversion will occur for the receiving field. S0C7 abends occur when non-numeric data is MOVE ‘d to a receiving numerically defined field OR when math calculations are attempted using non-numeric data.
No Numeric Data Conversion
If you move any field type (group or element) to any group or sub-group level field then there will be NO numeric data conversion.
• Character MOVE rules apply.
• Left Justify & pad with spaces.
This is one of the primary causes of non-numeric data in a numerically defined field.
One of the primary uses of a sending group level MOVE containing numeric element fields to a receiving group level containing numeric element fields (mapped identically) is for re-initializing numeric element fields using 1 MOVE instruction.
A Clear Mask – or – a data propagation MOVE is also possible for table clears - where the table group level is greater than 255 bytes.
Related videos on Youtube
mmutilva
Updated on July 22, 2020Comments
-
mmutilva over 3 years
I'm having the following problem in a COBOL program running on OpenVMS.
I have the following variable declaration:
01 STRUCT-1. 02 FIELD-A PIC S9(6) COMP-3. 02 FIELD-B PIC S9(8) COMP-3. 01 STRUCT-2. 03 SUB-STRUCT-1. 05 FIELD-A PIC 9(2). 05 FIELD-B PIC 9(4). 03 SUB-STRUCT-2. 05 FIELD-A PIC 9(4). 05 FIELD-B PIC 9(2). 05 FIELD-C PIC 9(2).
And the following code:
* 1st Test: MOVE 112011 TO FIELD-A OF STRUCT-1 MOVE 20100113 TO FIELD-B OF STRUCT-1 DISPLAY "FIELD-A : " FIELD-A OF STRUCT-1 CONVERSION DISPLAY "FIELD-B : " FIELD-B OF STRUCT-1 CONVERSION * 2nd Test: MOVE 112011 TO SUB-STRUCT-1. MOVE 20100113 TO SUB-STRUCT-2. MOVE SUB-STRUCT-1 TO FIELD-A OF STRUCT-1 MOVE SUB-STRUCT-2 TO FIELD-B OF STRUCT-1 DISPLAY "SUB-STRUCT-1 : " SUB-STRUCT-1 DISPLAY "SUB-STRUCT-2 : " SUB-STRUCT-2 DISPLAY "FIELD-A : " FIELD-A OF STRUCT-1 CONVERSION DISPLAY "FIELD-B : " FIELD-B OF STRUCT-1 CONVERSION
Which outputs:
FIELD-A : 112011 FIELD-B : 20100113 SUB-STRUCT-1 : 112011 SUB-STRUCT-2 : 20100113 FIELD-A : 131323 FIELD-B : 23031303
Why
FIELD-A
andFIELD-B
hold values different from what I move into them in the second test?I've other moves from
DISPLAY
toCOMP-3
variables in my program where I don't get this behavior. -
David Thornley almost 14 yearsMan, this takes me back. I remember when we wanted to look at the last byte of packed decimal fields, because an "04" meant somebody had moved in a value with an EBCDIC space.
-
NealB almost 14 years@David Thornley. Close... EBCDIC space is hex "40". Today we use use an
IF NUMERIC
test on packed decimal fields to check for that sort of thing. Something that confuses many programmers is that theMOVE
doesn't blow up, but any computational reference to the field after that ends up giving a data exception abend (SOC7 in IBM land). Most people expect theMOVE
to blow them up. -
David Thornley almost 14 yearsNot just close: back in the day, when we packed fields, the last byte had the nybbles swapped, so a string ending 404040 hex would wind up as a packed decimal ending 4404 hex. (This wasn't actually COBOL, but the IBM 360 was specifically designed to run COBOL, having a single ASM instruction that did a formatted MOVE, so I figure my ASM experience is slightly relevant here.)
-
Bill Woodger almost 9 yearsThis is very largely nonsense, and trying to pick much useful out of it is an exercise in wasting time.