Problem with COBOL move to comp-3 variable

37,179

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 –

  1. Is almost always an implied CHARACTER string value
  2. If an individual element field is a 01 or 77 level – then it can be numeric.
  3. 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.
  4. 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.

Share:
37,179

Related videos on Youtube

mmutilva
Author by

mmutilva

Updated on July 22, 2020

Comments

  • mmutilva
    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 and FIELD-B hold values different from what I move into them in the second test?

    I've other moves from DISPLAY to COMP-3 variables in my program where I don't get this behavior.

  • David Thornley
    David Thornley almost 14 years
    Man, 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
    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 the MOVE 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 the MOVE to blow them up.
  • David Thornley
    David Thornley almost 14 years
    Not 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
    Bill Woodger almost 9 years
    This is very largely nonsense, and trying to pick much useful out of it is an exercise in wasting time.

Related