Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Cobol data type conversions

Status
Not open for further replies.

jnpoyser

IS-IT--Management
Sep 13, 2002
8
GB
Hi all,

I'm trying to convert some cobol 'comp' data types using VB or C. Some I've come accross so far are:

9(6) COMP-4
S9(9)V999 COMP-4
9(6) COMP

Are there any routines out there for conversion already? I've written a conversion routine for the unsigned comp-4, but under VB6 it just doesn't have the speed I need. I don't fancy writing one for the signed comp-4 - esp. when dealing with 2's compliment.

This would be straight forward if they 'fitted' into a standard windows-size data type, but alas not.

Help!! + thanks,

James.

 
James,
I stand ready to be corrected, but I think that COMP and COMP-4 are one and the same beast......
(unless somebody knows different!)

When you say you are looking to convert, are you converting programs, or the data?

Marc
 
Well, AFAIK, COMP-4 is implementor defined. In AcuCOBOL, it is 2's complement, machine-independent, binary number with the storage size dictated by the PICTURE clause (2, 4 or 8 bytes). On a big endian machine (e.g. IBM mainframe), COMP and COMP-4 are the same. On a little endian machine (e.g. Intel PC), they are different.

Basically, to convert, you need to reverse the byte order and then treat the result as the appropriately sized binary number and scale it as defined by the PICTURE clause.

Big endian vs little endian storage issues are encountered with various file types: .bmp, photoshop, DICOM, etc. Someone in the VB community likely has a good conversion routine that will deal with this stuff.


 
Hi James,

Mark is right. COMP, COMP-4, and BINARY are identical.

Their fields come in 3 flavors:
Code:
      half word  (2 bytes)
      full word  (4 bytes)
    double word  (8 bytes)
If you're coverting the data, you'll have to tell us what the VB/C equivs will look like. Here's a few examples of what the COBOL data looks like (on a mainframe - I can't speak for the PC:

NOTE: 2 digits = 1 byte; memory digits are in HEX notation.
Code:
+15 in PIC 9(6) COMP/COMP-4 in memory looks like 0000000F
-15 in PIC 9(6) COMP/COMP-4 in memory looks like 0000000F

+15 in PIC S9(9)V999 COMP/COMP-4 in memory looks like   
       000000000000000F
-15 in PIC S9(9)V999 COMP/COMP-4 in memory looks like   
       FFFFFFFFFFFFFFF1  (2s complement)
Some comments:

Because there's no sign in PIC 9(6), both pos and neg values are represented as pos.

If the PIC specifies 1-4 positions, a half word of mem is alloc; 5-8, a full word; 9-18, a double word.

HTH, Jack.



 
3gm,

Sorry for stepping on your reply. I was working on mine, then left the house, returned and submitted mine w/o checking. [blush]

Jack
 
I'm trying to convert data from a file and after examining the stucture in a hex editor, the S9(9)V999 comp-4 is stored in 6 bytes.

So does this stand?, would this be how 15 & -15 would be stored:

<FONT FACE=monospace>


+15 in PIC S9(9)V999 COMP/COMP-4 in memory looks like
00 00 00 00 00 0F

-15 in PIC S9(9)V999 COMP/COMP-4 in memory looks like
FF FF FF FF FF F1

</font>

If this is correct, can I presume that if the left most byte >= &H80 (i.e. the left most <i>bit</i> is 1) then the value is -ve?

Ok, now the tough bit - converting the -ve binary val to a 'real' number. Would this suffice:

if (left most byte) > &H80 then

real_value = input_value - 2^(number of bytes * 8)


So for the above example, where FFFFFFFFF1 = 281474976710641 we have:


real_value = 281474976710641 - 2^(6 * 8)
real_value = 281474976710641 - 281474976710656
real_value = -15




If the value was stored as a 4 or 8 byte value then VB would convert -ve's without any effort, but as the data files I have are storing it in 6 byte fields I need to use a routine like the above.

Thanks a million - James.









 
Hi James,

I'm a babe in the woods when it comes to VB (or any non COBOL language, except assembler), so this may sound like a silly ques.

Could you move the 6 byte field to an 8 byte work field already containing all binary zeros (binary ones, for a neg number), do what you have to do with it in the work field, then move back the low order six bytes of the work field to the orig field?

But remember, I'm talking from the viewpoint of my vast experience in the VB arena. :)

Regards, Jack.
 
Jack -

Great idea - not too sure if VB can do it though, I think it 'dumbs down' type conversion too much. I'll have a look into it.


James
 
Hi James,

If you can't find a way to do it from your own ken, float the ques at one of the VB forums here. They may be able to help.

Regards, Jack.
 
Aw, come on guys, don't send James off to hostile territory!

James, the trick is to assemble the four bytes into a string (in the example below, TheValue) and then play some games with Currency data type. (The following example assumes that you are working on big-endian data -- MSB is on the left. Little-endian is left as an exercise for the reader.)
Code:
Dim LDigit As Integer, RDigit As Integer, BIN As Currency
Dim BinDigit As Currency, ost as String
...
BIN = 0
For ii = 1 To 4
    LDigit = Asc(Mid$(TheValue, ii, 1))
    BinDigit = LDigit
    BinDigit = BinDigit / 10000
    BIN = (BIN * 256) + BinDigit
Next ii
ost = left$(Format$(BIN, &quot;00000000000000.0000&quot;), 14) & _
      right$(Format$(BIN, &quot;00000000000000.0000&quot;), 4)
At this point, ost is a string containing decimal digits that may be converted (using the normal Cxxx conversion functions available in VB).

When you want an answer, stick with the COBOL Forum. [pipe] Tom Morrison
 
James,

I also left how to deal with signed data as an exercise, but not intentionally. Guess I just had to post. [blush]

Here is a corrected example:
Code:
BIN = 0
SignChar = &quot; &quot;
LDigit = Asc(Left$(TheValue, 1))
If LDigit > 127 Then SignChar = &quot;-&quot;
For ii = 1 To i
    LDigit = Asc(Mid$(TheValue, ii, 1))
    If SignChar = &quot;-&quot; Then LDigit = (Not LDigit) And &HFF
    BinDigit = LDigit
    BinDigit = BinDigit / 10000
    BIN = (BIN * 256) + BinDigit
Next ii
If SignChar = &quot;-&quot; Then BIN = BIN + 0.0001
ost = SignChar & _
      left$(Format$(BIN, &quot;00000000000000.0000&quot;), 14) & _
     right$(Format$(BIN, &quot;00000000000000.0000&quot;), 4)
If the number is negative, generate the 1's complement, then add 1, which is the 2's complement.

Guess I should have said:
When you want both a wrong answer and a correct answer, stick with the COBOL Forum. [blush][blush] Tom Morrison
 
My example should work for any binary number up to about 62 bits. Note that a 63 bit binary number contain a value that is too large to be represented in 18 decimal digits. My example does not detect this type of overflow, though I am sure you could work that in if it is an issue. Tom Morrison
 
James,

I have looked at some of your other threads that seem to be related to this problem. You seem to have gone down a path using VB and/or C, but I have to wonder:

What is the original goal/problem?
It may be that there is a different solution...

Tom Morrison
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top