Compiler Options and COMP values on Disk (1360 Views)
Reply
Frequent Advisor
Homer Shoemaker
Posts: 74
Registered: ‎01-09-2008
Message 1 of 24 (1,360 Views)
Accepted Solution

Compiler Options and COMP values on Disk

rx2660, OpenVMS 8.4, COBOL v2.9

 

If I store a COMP type value on disk from a program compiled using the default (IEEE) floating point format for the HP COBOL complier on an IA64, and then I recompile that same program using another (G_FLOAT) floating point format, will my new program be able to read the previously written data from disk correctly?

 

 

Some background:

 

I have a call to LIB$WAIT in an include file that exists in almost every program in our application.  It is used for handling record locks when a program is operating in batch mode.  Apparently, LIB$WAIT depends on the binary representation of a floating point number passed to it  (in G_FLOAT format) rather than on the value itself.  The simple fix is to recompile using /FLOAT=G_FLOAT.   Maybe...

 

I also have many files with a lot of existing data stored as type COMP-3.  Before I change our build tool to use the new (older) float type, I want to be sure that  I won’t be creating more problems than I’m solving.  I’d rather not have to convert all my existing data, and I’d rather not have recompile ALL my programs at once.  Maybe the compiler and RMS are smart enough that I’m worrying about nothing.  I hope so.

 

I was going to write a test program to try this out, but I wondered if anyone else had already crossed this bridge?

 

Trusted Contributor
abrsvc
Posts: 367
Registered: ‎06-08-2010
Message 2 of 24 (1,358 Views)

Re: Compiler Options and COMP values on Disk

You have listed 2 different issues here.  Let me address the calls to LIB$WIAT first.

 

The call has an optional parameter as defined in the manual as follows:

         LIB$WAIT seconds [,flags] [,float-type]

 

Parameter 3 defines the floating type.  So the call can handle any type of floating binary value as long as you indicate the type properly.

 

 

Second:  The issue of binary data.

 

If you know that the binary data is of a particular format, then read it as such and convert it.  Anything stored using the COMP datatype wil be in the specific format of that datatype and not directly readable into another type without conversion.  The floating types are defind as particular groupings of bits with those bits "arranged" in a particular order.  (Please note that I am being ambiguous on purpose here).  Just as a simplistic example, reading a floating binary data area (longword) into an integer variable can lead to interesting results.  As the most clear example, assume a floating zero(0).  When read into an integer, the value is NOT zero as the actual bits for a floating point value of zero include a 1 somewhat in the middle of the longword.

 

Hope this helps a bit...

 

Dan

Honored Contributor
Steven Schweda
Posts: 9,096
Registered: ‎02-23-2005
Message 3 of 24 (1,352 Views)

Re: Compiler Options and COMP values on Disk

Trusted Contributor
abrsvc
Posts: 367
Registered: ‎06-08-2010
Message 4 of 24 (1,346 Views)

Re: Compiler Options and COMP values on Disk

RE: Steve

 

I'm sorry but you are wrong in this case.  Using the formatting capability of the printf hides the fact that the binary representation of the number is different for floating and integer.

 

I'm doing this from memory so I may be off by a bit or two, but the f_floating format is comprised of the following parts:

 

1) 1 bit for the sign

2) 7 bits for hte exponent

3) 24 bits for the fraction

 

Within the above, the exponent "value" for a zero is usually a 1 which would make bit #7 a 1 rather than a 0.  This means that the floating zero would be a 0080hex and not a 0000 as would be expected for an integer zero.

 

Similarly, the groupings of bits and how they are interpreted is different for IEEE and the VAX formats.

 

Dan

Honored Contributor
Steven Schweda
Posts: 9,096
Registered: ‎02-23-2005
Message 5 of 24 (1,342 Views)

Re: Compiler Options and COMP values on Disk

Honored Contributor
Steven Schweda
Posts: 9,096
Registered: ‎02-23-2005
Message 6 of 24 (1,340 Views)

Re: Compiler Options and COMP values on Disk

Acclaimed Contributor
Dennis Handly
Posts: 25,298
Registered: ‎03-06-2006
Message 7 of 24 (1,333 Views)

Re: Compiler Options and COMP values on Disk

[ Edited ]

>If I store a COMP type value on disk from a program compiled using the default (IEEE) floating point format

 

This shouldn't matter since COMP (usually) only contains fixed point data, not floating point.

 

>the value is NOT zero as the actual bits for a floating point value of zero include a 1 somewhat in the middle of the longword.

 

I'm not sure what floating point type you are talking about but it isn't IEEE, unless you are talking about -0.

Or are talking about IEEE floating point decimal where there are N values of zero, where the one with all bits zero wouldn't normally be produced or used.

 

>I'm sorry but you are wrong in this case.  Using the formatting capability of the printf hides the fact that the binary representation of the number is different for floating and integer.

 

As Steven says, not hardly.  His program (with %x and union) is proof of what he said.

 

>the f_floating format is comprised of the following parts:

>1) 1 bit for the sign  2) 7 bits for the exponent 3) 24 bits for the fraction

 

Yes.  But zero is treated special, in more ways than one.

Honored Contributor
John Gillings
Posts: 2,995
Registered: ‎07-31-2003
Message 8 of 24 (1,332 Views)

Re: Compiler Options and COMP values on Disk

Homer,

 

  No. Neither COBOL nor RMS "know" the data type on disk, so they can't do any conversions for you. I think Fortran had a mechanism to tell the compiler to do an on-the-fly conversion of specified fields, but I'm sure you don't want to rewrite everything in Fortran.

 

  From your description you have a large set of data files using one format and a tiny routine using the other. You want to make a major change to your data just to satisfy LIB$WAIT? Talk about tails wagging dogs!

 

  As Dan has explained, LIB$WAIT has a parameter to select the data type. That's your simplest solution. But even if we assume that wasn't available, it would be better to attack the little problem than change everything else to conform.

 

  Two simple ways to get around the problem. You could lie to the compiler, telling it the  F_FLOAT (note NOT G_FLOAT) parameter is really INTEGER and hardcode the appropriate F_FLOAT bit pattern into an INTEGER. Your code doesn't know it's floating data, so you're free to compile with IEEE for everything else.

 

Simple way to determine the right bit pattern (ie: INTEGER value), use DEBUG

 

$ run/debug any

         OpenVMS Alpha Debug64 Version V8.3-016

%DEBUG-I-INITIAL, Language: AMACRO, Module: .MAIN.

DBG> deposit/f_float r0=5.0
DBG> examin/hex r0
.MAIN.\START\%R0:       00000000000041A0
DBG>  examine/decimal r0
.MAIN.\START\%R0:       16800
DBG>

 

  So an INTEGER value 16800 will give a 5 second delay when passed to LIB$WAIT.

 

  Another way is to write a small jacket routine in whatever language you like, compiled with the appropriate floating point which performs whatever conversions are necessary (see routine CVT$CONVERT_FLOAT). If you only have one use for LIB$WAIT, you may not even need a conversion. Just write a routine called DELAY and leave the time interval hardcoded.

 

Note, G_FLOAT is as incompatible with F_FLOAT as IEEE. Passing G_FLOAT to LIB$WAIT won't work. There is another double precision floating format, D_FLOAT, which is an F_FLOAT value with an extra 32 bits of precision. This would be compatible with LIB$WAIT, but you really don't want to use D_FLOAT! I'd be aiming to migrate all programs and data to IEEE and forget the older formats ever existed.

A crucible of informative mistakes
Frequent Advisor
Homer Shoemaker
Posts: 74
Registered: ‎01-09-2008
Message 9 of 24 (1,325 Views)

Re: Compiler Options and COMP values on Disk

Thank you, all. 

 

I really thought that I would have to change my compiler option.  But since Dan seemed to think that I could actually make the call to LIB$WAIT work, I figured I'd give it another try.  The second question would be moot, if I could get the call to LIB$WAIT to work.

 

If the attachment worked, you can see the COBOL code, compiled with the default float type on the I64,  that demonstrates the call to LIB$WAIT working.

 

But even though FLOAT-TYPE  1 thru 5 returned a NORMAL status, only FLOAT-TYPE 4 created the 5 second delay.

 

 

Honored Contributor
John Gillings
Posts: 2,995
Registered: ‎07-31-2003
Message 10 of 24 (1,301 Views)

Re: Compiler Options and COMP values on Disk

Homer,

  

>But even though FLOAT-TYPE  1 thru 5 returned a NORMAL status, only FLOAT-TYPE 4 created the 5 second delay.

 

 Correct! Bits are bits. You store the value "5.0" as IEEE floating point, which is hex "40140000". LIB$WAIT interprets it as whatever data type you tell it. Interpreted as F, D, G or H float that bit pattern is 0.

 

DBG> dep/float r0=5.0
DBG> ex/hex r0
0\%R0:  4014000000000000
DBG>  ex/f_float r0
0\%R0:  0.0000000
DBG> ex/d_float r0
0\%R0:  0.000000000000000
DBG> ex/g_float r0
0\%R0:  0.000000000000000
DBG>  ex/h_float r0
0\%R0:  0.000000000000000000000000000000000
DBG> ex/float r0
0\%R0:  5.00000000000000
DBG> ex/extended_float r0
0\%R0:  5.00000000000000355705048749044295

 

 

A crucible of informative mistakes
Honored Contributor
Hein van den Heuvel
Posts: 6,588
Registered: ‎05-19-2003
Message 11 of 24 (1,291 Views)

Re: Compiler Options and COMP values on Disk

Howdie Homer !

 

A while back I had the challenge of a bunch of which could be compiled as IEEE or programs F_FLOAT, yet had to call LIB$WAIT the right way. Unfortunately, Cobol does not really have conditional compiles.

I opted for a dynamic solution.

What we did was to replace all existing calls to LIB$WAIT with LIB_WAIT.

That function figured out how it was compiled by checking the bit pattern for the floating point value.

When it recognized the value, it called LIB$WAIT with the required argument type flag.

I don't think you need this, but it may further the understanding (or the confusion :-).

 

Code below.

Cheers!

Hein

 

IDENTIFICATION DIVISION.
PROGRAM-ID. lib_wait.
AUTHOR. Hein van den Heuvel.
*
* This is a helper wrapper around LIB$WAIT to call it with the
* correct floating point variable type.
* The requirement is that this module is compiled with the same
* floating point option as the calling program
* The LIB$WAIT function itself expects a 4 bytes VAX / F_float
* if no further parameters are provided.
*
DATA DIVISION.
WORKING-STORAGE SECTION.
*
*
01 x_implementation_float       USAGE COMP-1 VALUE 0.001.
01 x_binary REDEFINES x_implementation_float PIC 9(9) USAGE COMP.
01 x_f_floating                 PIC 9(9) USAGE COMP VALUE 309279619.
01 x_IEEE_S_floating            PIC 9(9) USAGE COMP VALUE 981668463.
01 IEEE_S_floating              PIC 9(9) USAGE COMP VALUE 4.
01 return_status                PIC 9(9) USAGE COMP.
01 x_display                  PIC 9(9).

LINKAGE SECTION.
01 delay_time                   PIC 9(9) USAGE COMP.

PROCEDURE DIVISION USING delay_time GIVING return_status.
MY_MAIN SECTION.
MAIN.
*
* Find out what type the calling float is likely to be by
* comparing known binary representation for the float value 0.001
* Wanted to use 1.0 as sample value, but its IEEE_S binary value
* is 1065353216 which does not fit in PIC 9(9) COMP.
* PIC 9(10) gives an 8 byte, BINARY-LONG does not work on VAX.
*
    IF x_binary = x_f_floating
*Debug:
    DISPLAY "LIB_WAIT Compiled as F_float."
        CALL "lib$wait" USING BY REFERENCE delay_time
                        GIVING return_status
    ELSE
       IF x_binary = x_IEEE_S_floating
*Debug:
    DISPLAY "LIB_WAIT Compiled as IEEE_S_float."
           CALL "lib$wait" USING BY REFERENCE delay_time,
                        OMITTED, IEEE_S_floating GIVING return_status
       ELSE
           MOVE x_binary TO x_display
           DISPLAY "Value for 0.001 as COMP-1 in decimal",
                   " was unexepected : ", x_display
           CALL "sys$exit"  USING BY VALUE 16
       END-IF
    END-IF.

    EXIT PROGRAM.
END PROGRAM lib_wait.

 

 

 

 

 

Frequent Advisor
Homer Shoemaker
Posts: 74
Registered: ‎01-09-2008
Message 12 of 24 (1,276 Views)

Re: Compiler Options and COMP values on Disk

Hello Hein!

 

That is pretty cool.  I will remember that approach.  But you are correct, I don't need to do that here.  Even so, I always enjoy looking at an elegant solution.  It's the fun part of programming.

 

Thank you,

 

Homer

Honored Contributor
John Gillings
Posts: 2,995
Registered: ‎07-31-2003
Message 13 of 24 (1,248 Views)

Re: Compiler Options and COMP values on Disk

Yet another method of feline dermis removal...

 

Since the issue here is really the data type of the unit for specifying the delay time, we can get that out of the picture by writing a routine which uses a more tractable unit. Attached is a MACRO32 routine which accepts an INTEGER delay time expressed in thousanths of a second. The LIB$WAIT FLAG argument is optional.

 

 

        .TITLE WaitThousanths
;
;  Same as LIB$WAIT except the "seconds" argument is an INTEGER units 1/1000th second
;  this avoids issues of floating point incompatibility
;
        .ENTRY DELAY_THOUSANTHS,^M<>
        PUSHL #0                 ; default flags
        CMPL (AP),#2             ; check for flags argument
        BLSS NoFlag
          MOVL @8(AP),(SP)       ; copy flags argument
        NoFlag:
        PUSHL @4(AP)             ; copy delay argument
        CVTLF (SP),(SP)          ; convert to F_FLOAT
        DIVF  #^F1000.0,(SP)     ; convert to seconds
        PUSHAL 4(SP)             ; build argument list
        PUSHAL 4(SP)
        CALLS #2,G^LIB$WAIT      ; pass to LIBRTL
        RET
        .END

 

for a 5 second wait from COBOL

 

CALL "DELAY_THOUSANTHS" USING BY REFERENCE 5000.

 

If you need more precision than thousanths, just change the divisor (but I don't think you'll be able to reduce the granularity to less than 100ns).

 

A crucible of informative mistakes
Frequent Advisor
Homer Shoemaker
Posts: 74
Registered: ‎01-09-2008
Message 14 of 24 (1,243 Views)

Re: Compiler Options and COMP values on Disk

I gotta try that!

 

Thanks

Senior Member
Richard_Maher
Posts: 1
Registered: ‎04-09-2010
Message 15 of 24 (1,198 Views)

Re: Compiler Options and COMP values on Disk

Hi Homer,

 

1) If you're really talking "COMP-3" data then you're talking packed-decimal which will not be affected at all by your choice /FLOAT qualifier.

2) Because you are already using "include file[s]" it would not be unusual to have an architecture-specific COPY-book on the search list.

3) Hein is not entirely correct when he says " Unfortunately, Cobol does not really have conditional compiles" as can be seen in the attached example that works both on VAX and IA64.

 

Hope everyone had a great Christmas and all the best for the coming year!

 

Cheers Richard Maher

 

PS. On my Alpha and IA64 code I seem to be compiling with /FLOAT=D_FLOAT (where lib$wait is involved) for some reason but can't remember why?

Acclaimed Contributor
Dennis Handly
Posts: 25,298
Registered: ‎03-06-2006
Message 16 of 24 (1,188 Views)

Re: Compiler Options and COMP values on Disk

[ Edited ]

>3) Hein is not entirely correct when he says "Unfortunately, COBOL does not really have conditional compiles"

 

Right, the COBOL Standard only supported the DEBUG module.  But various vendors have added their own extensions, including COBOL II on MPE.

Honored Contributor
Hoff
Posts: 4,964
Registered: ‎01-29-2006
Message 17 of 24 (1,181 Views)

Re: Compiler Options and COMP values on Disk

Hein and Dennis are technically correct within the COBOL language (and outside of Richard's DEBUG pieces), but all of these fine folks are incorrect in common programming practice.

 

COBOL has had conditional compilation available for many, many years, and conditional compilation is part of the available language specifications.  Hein and Dennis are simply looking at the wrong language specifications. :-)

 

C.  I'ts not just the first letter of COBOL, it's an entirely functional preprocessor for COBOL.

 

Specifically, the command for conditional processing within COBOL is:

 

  C /PREPROCESS_ONLY=whatever-out.COB /DEFINE=whatever-define whatever-in.COB

 

This also works for Fortran, and for various other languages.

 

(For completeness: Fortran 95 does have its own syntax for conditional compilation, and it's probably feasible to port the coco preprocessing tool over to VMS.  gfortran uses the c preprocessor.  The OpenVMS Fortran compiler appears to lack this (optional) part of the standard, given the diagnostics showing for the syntax, and the OpenVMS Fortran compiler doesn't follow gfortran's lead of invoking cpp (C /PREPROCESS_ONLY) as part of its compilation.  The OpenVMS Fortran SPD also lacks any specific references to the conditional compilation support.  But I digress.)

 

Using C /PREPROCESS_ONLY is easier than rolling your own macro preprocessor for COBOL, but that works nicely, too, particularly if you're using Python, Lua or other text-savvy languages, and there are toolkits around.

 

It'd also be nice if the C preprocessor were callable and added into COBOL and Fortran compilations, but I'd hope that getting all of these languages forward to the current language standards (all three are woefully down-revision) should be a higher priority.

Trusted Contributor
Richard J Maher
Posts: 397
Registered: ‎12-26-2005
Message 18 of 24 (1,175 Views)

Re: Compiler Options and COMP values on Disk

> Hein and Dennis are technically correct within the COBOL language

> (and outside of Richard's DEBUG pieces), but all of these fine folks

> are incorrect in common programming practice.

 

Sorry "DEBUG pieces"? Which bit of the following are you struggling with: -

 

COBOL

  /CONDITIONALS

   /CONDITIONALS[=(character,...)]
   /NOCONDITIONALS                  (D)

   Controls whether the conditional compilation lines in a source
   program are compiled or treated as comments.  Specifying
   /CONDITIONALS results in all conditional compilation lines
   being compiled.

   Specifying /CONDITIONALS=(selector,...), where a selector is
   a list of one or more characters from A to Z, results in the
   selected conditional compilation lines being compiled.  If
   you specify more than one selector, separate them with commas
   and enclose the list in parentheses.

   The default, /NOCONDITIONALS, results in all conditional
   compilation lines being treated as comments during
   compilation.

 

Try compiling my demo_wait.cob with[out] /CONDITIONALS or /CONDITIONALS=F and compare the results. Leave out any debug qualifiers and sorry for having confused you by leaving the P1="Y" for debug code in a command file I copied.

 

I'm not saying it's as powerful as other languages (certainly not MACROs) but conditional compilation it has.

 

Having said that, I still maintain that options 1 and 2 from my previous post are the more common solutions to this "problem".

 

Regards Richard Maher

Honored Contributor
Hoff
Posts: 4,964
Registered: ‎01-29-2006
Message 19 of 24 (1,163 Views)

Re: Compiler Options and COMP values on Disk

Struggle?  Nah.  Here's what the COBOL SPD says about the conditionals feature I referred to as "DEBUG":   "Conditional compilation serves to make debugging easier."  Debugging.  Can it be used for more than that?  Sure.  That's why I wrote "outside of..." there.  But this extension is still very limited.

 

 

The following is composed in the input box...

 

#if WHAT_YOU_HAVE_WORKS_FOR_YOU

#pragma message ("then by all means use it")

#else

#if __VAX

VAX condional COBOL code here

#elif __ALPHA

Alpha-specific COBOL code here

#elif __IA64

Itanium-specific COBOL code here

#else

#pragma message ("who or what am I?")

#endif

#define SOMESPEC ddcu:[dir]file.ext

#define SOMEMACRO FOO(X) SOME-COBOL-STATEMENT x

#endif

 

As weak as C macros and the C preprocessor are for this sort of stuff, the DEC COBOL /CONDITIONAL extension pieces are yet weaker.

 

It's also possible to use this C preprocessor sequence for non-VMS (portable, conditional) COBOL, too, within the limits of common preprocessor statements.  (The C #pragma stuff  isn't necessarily portable, but that's typical of C and not specific to the use of the C preprocessor itself.)

 

As for "newer" COBOL 2002, that looks to be fairly fairly reasonable.  (Though I haven't looked to see if there are conditional compilaion capabilities available in 2002; I'd hope so; the DEC COBOL /CONDITIONAL stuff is an extension.)

Advisor
jreagan
Posts: 16
Registered: ‎09-10-2011
Message 20 of 24 (1,131 Views)

Re: Compiler Options and COMP values on Disk

Using the C preprocessor on COBOL code makes for odd debugging situations.  I'm not sure what the compiler will do for any #file or #line directives left in the output.  Using the language feature (while not the most flexable) gives the best debugging results.

Honored Contributor
Hoff
Posts: 4,964
Registered: ‎01-29-2006
Message 21 of 24 (1,128 Views)

Re: Compiler Options and COMP values on Disk

You're correct, John; I wouldn't expect nor suggest the use of #file or various of the C-ish #pragma directives here.

 

But as for using language features, that particular suggestion can cut both ways.  Porting code to VMS is getting more and more interesting as the years pass.  C99 use has become widespread in open source, and code dependent on the newer Fortran standards are increasingly common, too.  (I don't port as much COBOL around, but I'd be surprised if that code wasn't also encountering problems.)  And these feature deficits are often why I'm conditionalizing the source code.

 

Honored Contributor
Steven Schweda
Posts: 9,096
Registered: ‎02-23-2005
Message 22 of 24 (1,123 Views)

Re: Compiler Options and COMP values on Disk

Esteemed Contributor
H.Becker
Posts: 373
Registered: ‎04-09-2009
Message 23 of 24 (1,117 Views)

Re: Compiler Options and COMP values on Disk

>>>  I don't see "any #file or #line directives left in the output", and a "#" in column one seems to be pretty Fortran-compatible.  If a COBOL compiler is harder to satisfy, then additional options include writing one's own preprocessor, and filtering the output of a sub-ideal preprocessor.

or simply use gcc which has a -P option:  Inhibit generation of linemarkers in the output from the preprocessor. This might be useful when running the preprocessor on something that is not C code, and will be sent to a program which might be confused by the linemarkers.
Acclaimed Contributor
Dennis Handly
Posts: 25,298
Registered: ‎03-06-2006
Message 24 of 24 (1,111 Views)

Re: Compiler Options and COMP values on Disk

>I don't see "any #file or #line directives left in the output", and a "#" in column one seems to be pretty Fortran-compatible.

 

Well these lines:

# 1 "ALP$DKC0:[SMS.ITRC]arch_test_c.for;2"

 

The "#line" directive is C and C++ Standard.  But the preprocessor "# line-number [optional filename]" form is also pretty common.

 

>simply use gcc which has a -P option:

 

Right.

The opinions expressed above are the personal opinions of the authors, not of HP. By using this site, you accept the Terms of Use and Rules of Participation.