5

I'm entirely new to COBOL. I have a small COBOL program and a small C file. According to this article: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.ceea400/sdtpt.htm the equivalent of a C signed integer in COBOL is

PIC S9(9) USAGE IS BINARY

I want to call the functions in the C file from COBOL, and display the result in COBOL. I am able to call the function, and it seems to behave as expected, data being passed as expected, but I'm not able to display the binary value with DISPLAY in COBOL.

My COBOL program:

   IDENTIFICATION DIVISION.
   PROGRAM-ID. MSQLTST5_COBHELPER.

   DATA DIVISION.
   WORKING-STORAGE SECTION.
   01 SQLCODE PIC S9(9) USAGE IS BINARY VALUE 100.


   PROCEDURE DIVISION.
   HEAD SECTION.

   MAIN.

       DISPLAY "COBOL, sqlcode is: " SQLCODE.
       CALL "CONNECT_DEFAULT" USING SQLCODE.
       DISPLAY "COBOL, sqlcode is: " SQLCODE.

       STOP RUN.

   END PROGRAM MSQLTST5_COBHELPER.

The C function I'm calling:

void connect_default(int* sqlcode)
{
    printf("C, sqlcode is: %d\n", *sqlcode);
    // internal code that places the expected error code -14006 in the variable sqlcode
    printf("C, sqlcode is: %d\n", *sqlcode);
}

The output of running my COBOL program:

COBOL, sqlcode is: d
C, sqlcode is: 100
C, sqlcode is: -14006
COBOL, sqlcode is: J▒▒▒

It seems that the variable does indeed have the value 100 that I gave it, and then is passed correctly between C and COBOL, but when I ask COBOL to display the variable it seems to try to pick out the character that has the given ASCII code, rather than the numerical value, as the character 'd', which has the ASCII code 100, is displayed rather than the number 100.

How do I display this value as a numeric value in COBOL?

Helena
  • 1,041
  • 2
  • 12
  • 24
  • Can't you transfer the contents of the `SQLCODE` field to a `USAGE DISPLAY` field using the `MOVE` instruction? If you're lucky, it'll convert the binary number to a numeric one. – MC Emperor Mar 06 '18 at 08:50
  • That does indeed seem to have done something along the lines of what I want, but I'm not sure what is actually displayed. The value 100 is displayed as "00000010{" and the value -14006 is displayed as "00001400O". Perhaps this is just a formatting issue. – Helena Mar 06 '18 at 08:55
  • Indeed; my guess is that you used a `PIC S9(9) USAGE DISPLAY` field, am I correct? – MC Emperor Mar 06 '18 at 08:58
  • Yes, that is correct, that's how I interpreted your comment. – Helena Mar 06 '18 at 09:00
  • Let me add this as an answer. – MC Emperor Mar 06 '18 at 09:03

4 Answers4

9

Why don't you transfer the contents of the SQLCODE field to a USAGE DISPLAY field using the MOVE instruction? It'll convert the binary number to a numeric one.

If the formatting is strange — here is why:

Signed numeric pictures without the SIGN SEPARATE clause must somehow include the sign without taking up space, so most compilers combine the last digit with the sign of the number. Most conventions use J for −1 till R for −9. They also pad the number with leading zeros. So -14006 will convert to 00001400O, because the last digit is a 6, and because it must be conbined with the minus sign, the last digit becomes -6, which is represented by an O. Roughly the same reasoning counts for 00000010{.

In order to reformat the number, you could actually use another picture, like

pic S9(9) sign leading separate

That will display -14006 as -000014006

MC Emperor
  • 22,334
  • 15
  • 80
  • 130
  • That did indeed display it as such, thank you very much for your help! – Helena Mar 06 '18 at 09:17
  • 2
    As an additional note: as of Enterprise COBOL V5 (I guess - I know for sure it's in V5.2) there's a compile-option DISPSIGN(SEP) that will automatically generate a separate sign for all `DISPLAY`s of signed numeric items. – piet.t Mar 06 '18 at 12:54
  • 2
    There is also the difference between COMP/Binary and COMP-5 to consider when the value is set by a non-COBOL program. If this is running on a mainframe there is the TRUNC(BIN) compile option to make all COMP/Binary fields behave as if they are defined as COMP-5. – cschneid Mar 06 '18 at 14:18
  • If you going to be working with interlanguage calls, the book [Language Environment Writing Interlanguage Communication Applications](https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.3.0/com.ibm.zos.v2r3.ceeam00/toc.htm) (2.3 link) is invaluable. Also, the [Enterprise COBOL Programming Guide](https://www.ibm.com/support/knowledgecenter/en/SS6SG3_6.2.0/kc_gen/master_map-gen1.html) (6.2 link) has lots of useful information. – zarchasmpgmr Mar 07 '18 at 16:25
4

This should achieve your intended results.

IDENTIFICATION DIVISION.
PROGRAM-ID. MSQLTST5_COBHELPER.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 SQLCODE PIC S9(9) USAGE IS BINARY VALUE 100.
01 SQLCODE-E PIC -9(9).

PROCEDURE DIVISION.
HEAD SECTION.

MAIN.
    PERFORM DISPLAY-SQLCODE.
    CALL "CONNECT_DEFAULT" USING SQLCODE.
    PERFORM DISPLAY-SQLCODE.

STOP RUN.

DISPLAY-SQLCODE.
    MOVE SQLCODE TO SQLCODE-E.
    DISPLAY "COBOL, sqlcode is: " SQLCODE-E.

END PROGRAM MSQLTST5_COBHELPER.
Kennah
  • 487
  • 1
  • 5
  • 16
3

The standard way to do this is to move the binary field to a "numeric edited" field:

01 DISPLAY-SQLCODE PIC -(9)9.

Then

MOVE SQLCODE TO DISPLAY-SQLCODE

Full example:

IDENTIFICATION DIVISION.
PROGRAM-ID. MSQLTST5_COBHELPER.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 SQLCODE PIC S9(9) USAGE IS BINARY VALUE 100.
01 DISPLAY-SQLCODE PIC -(9)9.


PROCEDURE DIVISION.
HEAD SECTION.

MAIN.

    MOVE SQLCODE TO DISPLAY-SQLCODE
    DISPLAY "COBOL, sqlcode is: " DISPLAY-SQLCODE
    CALL "CONNECT_DEFAULT" USING SQLCODE
    MOVE SQLCODE TO DISPLAY-SQLCODE
    DISPLAY "COBOL, sqlcode is: " DISPLAY-SQLCODE

    STOP RUN
    .

END PROGRAM MSQLTST5_COBHELPER.
Scott Nelson
  • 568
  • 2
  • 17
0

Move the variable to the display field and then just display the field

01 WS-FIELD-FOR-DISPLAY PIC -(9)9.
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129