开发者

COBOL Question - UNICODE

We are currently looking to convert our legacy COBOL code from ANSII to UNICODE however we have come across a problem where just changing the PIC X fields to PIC N and setting NSYMBOL(NATIONAL) will cause problems when data structures contain a REDEFINES or RENAME statement with elementary DATA items using PIC 9 fields.

01 WS-RECORD PIC N(26).
01 WS-RECORD-1 REDEFINES WS-RECORD.
02 WS-NUM PIC 9(6).
02 WS-DATA PIC N(20).

MOVE N"123456ABCDEFGHIJKLM" TO WS-RECORD.

In the above the string being moved will be in UTF-16 format, therefore the field WS-NUM will be corrupt as it will contain X"310032003300" which is an invalid numeric, WS-DATA will contain X"3400350036004100..etc

The question is, when using NATIONAL (UTF-16) dat开发者_如何转开发a types how can numerics be handled so as to get the correct data after it has been redefined.

I can sort of get this to work doing the following but will get invalid data in other WS-RECORD.

MOVE 123456 TO WS-NUM.
MOVE N"ABCDEFGHIJKLM" TO WS_DATA.

The above will be correct, however if I examine WS-RECORD I will see ???ABCDEFGHIJKLM where ??? is X"313233343536" in hexi-decimal.

Our problem is that we have multiple data records depending on the record type identifier, we also use redefines on many of our LINKAGE ITEMS.

Has anyone had experience moving from legacy ASCII to UNICODE?


02 WS-NUM PIC 9(6) USAGE NATIONAL.

Should work (at least on IBM compilers).


A solution suggested by MicroFocus is below:-

The size of WS-NCHAR-1 and WS-NCHAR-FIELD are different sizes because the size of “pic 9(6)” is half the size of “pic n(6)”.

So the quick but untidy solution is to place a filler and then re-correct the field by using “FUNCTION DISPLAY-OF”, although this works the customer really needs to understand that the size of “pic n” is different to “pic 9”, hence care is needed when you use redefines and during conversion.

A tweaked example that should show you what I mean in code…

01 ONE-PICN           PIC N.
01 ONE-PIC9           PIC 9.

01 WS-NCHAR-FIELD     PIC N(20).   
01 WS-NCHAR-1 REDEFINES WS-NCHAR-FIELD.
   02  WS-NUM            PIC 9(6).
   02  FILLER            PIC X(6).
   02  WS-REST           PIC N(14).

DISPLAY "PIC N SIZE     : " length of ONE-PICN    
DISPLAY "PIC 9 SIZE     : " length of ONE-PIC9

DISPLAY "WS-NCHAR-FIELD : " length of WS-NCHAR-FIELD   
DISPLAY "WS-NCHAR-1     : " length of WS-NCHAR-1

DISPLAY "WS-REST        : " length of WS-REST    
DISPLAY "WS-NUM         : " length of WS-NUM

MOVE N"123456ABCDEFGHIJKLM"  TO WS-NCHAR-FIELD.

MOVE FUNCTION DISPLAY-OF(WS-NCHAR-FIELD(1:6),1252) TO WS-NUM


DISPLAY "WS-NUM     : " WS-NUM    DISPLAY "WS-REST    : " WS-REST

The above does not work for S9(n) COMP or S9(n)V9(n) ELEMENTRY ITEMS, with VISUAL COBOL I found that I could just MOVE numeric values directly into PIC N(n) ELEMENTS and then use FUNCTION NUMVAL() to obtain the actual numeric, I am yet to try with Signed/COMP and decimal fields.

Thanks all for your help.


If I understand you correctly, you want to convert X'3000' to X'30', X'3100' to X'31, and so on, through X'3900' to X'39'.

I looked through the MicroFocus documentation, and couldn't find an intrinsic function that would do this.

You could define your own procedure to do this.

The working storage for the procedure would look like this:

01  WS-NUMERIC-CONVERSION.
    05  WS-LOOP-COUNT                     PIC S9(04) COMP.
    05  WS-NATIONAL-POSITION              PIC S9(04) COMP.
    05  WS-NUMBER-OF-CHARACTERS           PIC S9(04) COMP.
    05  WS-NATIONAL-INPUT.
        10  WS-NATIONAL-INPUT-BYTE        PIC X
                                          OCCURS 40 TIMES.
    05  WS-ASCII-OUTPUT.
        10  WS-ASCII-OUTPUT-BYTE          PIC X
                                          OCCURS 20 TIMES.

The procedure would look like this:

NATIONAL-TO-ASCII.
    PERFORM VARYING WS-LOOP-COUNT FROM 1 BY 1
        UNTIL WS-LOOP-COUNT > WS-NUMBER-OF-CHARACTERS

        COMPUTE WS-NATIONAL-POSITION = WS-LOOP-COUNT + WS-LOOP-COUNT - 1
        MOVE WS-NATIONAL-INPUT-BYTE(WS-NATIONAL-POSITION)
            TO WS-ASCII-OUTPUT-BYTE(WS-LOOP-COUNT)
    END-PERFORM.

Calling the procedure would look like this:

05  WS-NATIONAL-NUMBER-X.
    10  WS-NATIONAL-NUMBER                 PIC N(06).
05  WS-ASCII-NUMBER-X.
    10  WS-ASCII-NUMBER                    PIC 9(06).


MOVE something TO WS-NATIONAL-NUMBER
MOVE WS-NATIONAL-NUMBER-X TO WS-NATIONAL-INPUT
MOVE +6 TO WS-NUMBER-OF-CHARACTERS
PERFORM NATIONAL-TO-ASCII
MOVE WS-ASCII-OUTPUT TO WS-ASCII-NUMBER-X
MOVE WS-ASCII-NUMBER TO something else

The procedure working storage that I defined handles a number up to 20 characters in length. If that's not enough, make the WS-NATIONAL-INPUT and WS-ASCII-OUTPUT fields bigger.


You can use the DISPLAY-OF FUNCTION and reference modification and add a filler to ensure the size is balanced, add a 78 to reduce magic number use!

Anyway, as I said its a bit dirty but works..

eg:

  MOVE FUNCTION DISPLAY-OF(WS-RECORD-1(
                 1:LENGTH OF WS-RECORD(1:6)),1252)

With the updated program being:

     78 NUM-SIZE  VALUE 6.

     01 WS-RECORD   PIC N(26).
     01 WS-RECORD-1 REDEFINES WS-RECORD.
       02 WS-NUM      PIC 9(NUM-SIZE).
       02 FILLER      PIC X(NUM-SIZE).
       02 WS-DATA     PIC N(20).


     MOVE N"123456ABCDEFGHIJKLM" TO WS-RECORD.

     DISPLAY "WS-NUM     : " WS-NUM
     DISPLAY "WS-DATA    : " WS-DATA

       MOVE FUNCTION DISPLAY-OF(WS-RECORD-1(
                 1:LENGTH OF WS-RECORD(1:NUM-SIZE)),1252)
              TO WS-NUM

     DISPLAY "WS-NUM     : " WS-NUM
     DISPLAY "WS-DATA    : " WS-DATA

(updated with a better solution)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜