************************************************************************
*  Barcode & OCR Package for SAP R/3: Barcode Conversion Program
*  Version: v1.04 
*  Date of last change: 29.Jun.2005
*  COPYRIGHT: RICOH TECHNO SYSTEMS CO.LTD. H.YAMADA: 2001/12/29; 
*             EDSC: 2002-2005; 
************************************************************************
*  OUTLINE:
*
*  BARCODE TYPES:
*    - Code 128 auto-switch
*    - Code 128 A
*    - Code 128 B
*    - Code 128 C
*    - UCC/EAN-128
*    - UPC-128/SSCC-18
*    - Code 39 (+CHK)
*    - Code 39 Extended (+CHK)
*    - PZN
*    - Code 93 (+CHK)
*    - Code 93 Extended (+CHK)
*    - Codabar (+CHK AIM)
*    - 2/5 Interleaved (+CHK)
*    - 2/5 Industrial (+CHK)
*    - 2/5 Matrix (+CHK)
*    - MSI/Plessey (+CHK)
*    - POSTNET 5, 9, 11
*    - EAN-13 (+2/5-digit supplement)
*    - EAN-8  (+2/5-digit supplement)
*    - UPC-A  (+2/5-digit supplement)
*    - UPC-E  (+2/5-digit supplement)
*
*  EXAMPLES FOR PROGRAM CALL:
*
*    ABAP/4:
*      PERFORM CONVERT_ABAP(ZABCP) USING parm1 parm2 parm3 parm4.
*        parm1: <barcode type>
*        parm2: <input data>
*        parm3: <output data>
*        parm4: <status>
*
*    SAPscript:
*      /: DEFINE &TYPE& = '<barcode type>'.
*      /: DEFINE &IN_DATA& = '<input data>'.
*      /: DEFINE &OUT_DATA& = ''.
*      /: DEFINE &STATUS& = ''.
*      /: PERFORM CONVERT IN PROGRAM ZABCP
*      /: USING &TYPE&
*      /: USING &IN_DATA&
*      /: CHANGING &OUT_DATA&
*      /: CHANGING &STATUS&
*      /: ENDPERFORM.
*
*  STATUS CODES:
*      0: NO_ERROR
*      1: INVALID_BARCODE_TYPE
*      2: INVALID_LENGTH
*      3: ILLEGAL_CHAR
*      4: UNEXPECTED_CHAR
*      5: INVALID_SAPSCRIPT_NAME
*
************************************************************************
REPORT ZABCP.

CONSTANTS:
  MAX_LEN            TYPE I VALUE 256,
  BARCODE_TYPE_LEN   TYPE I VALUE 16.

* -- for CODE128
CONSTANTS:
  MODE_C_CHAR(01)    TYPE X VALUE 'C3',
  MODE_B_CHAR(01)    TYPE X VALUE 'C4',
  MODE_A_CHAR(01)    TYPE X VALUE 'C5',
  FNC1_CHAR(01)      TYPE X VALUE 'C6',
  SHIFT_CHAR(01)     TYPE X VALUE 'C2',
  START_CHAR_A(01)   TYPE X VALUE 'C7',
  START_CHAR_B(01)   TYPE X VALUE 'C8',
  START_CHAR_C(01)   TYPE X VALUE 'C9',
  X1F(01)            TYPE X VALUE '1F',
  X20(01)            TYPE X VALUE '20',
  X60(01)            TYPE X VALUE '60',
  CODEA(01)          TYPE X VALUE '85',
  CODEB(01)          TYPE X VALUE '86',
  CODEC(01)          TYPE X VALUE '87',
  CODESHIFT(01)      TYPE X VALUE '80',
  CODEFNC1(01)       TYPE X VALUE '81',
  CODEFNC2(01)       TYPE X VALUE '82',
  CODEFNC3(01)       TYPE X VALUE '83',
  END_CHAR(01)       TYPE X VALUE 'CA',
  SPACE_CHAR(01)     TYPE X VALUE '20',
  SPACE_END_CHAR(02) TYPE X VALUE '20CA',
  INSTOFSPACE(01)    TYPE C VALUE '°',
  AMP2CHAR(04)       TYPE C VALUE '<38>'.

* -- for EAN & UPC
CONSTANTS:
  POOLD_CONV(20)     TYPE X VALUE
                       '30C031C132C233C334C435C536C637C738C839C9'.

* -- Status code definitions
CONSTANTS :
  NO_ERROR(01)               TYPE C VALUE '0',
  INVALID_BARCODE_TYPE(01)   TYPE C VALUE '1',
  INVALID_LENGTH(01)         TYPE C VALUE '2',
  ILLEGAL_CHAR(01)           TYPE C VALUE '3',
  UNEXPECTED_CHAR(01)        TYPE C VALUE '4',
  INVALID_SAPSCRIPT_NAME(01) TYPE C VALUE '5'.

* -- Error message definitions
CONSTANTS :
  INVALID_BARCODE_TYPE_S(29)
    TYPE C VALUE      '(TYPE) Invalid barcode type :',
  INVALID_LENGTH_S(42)
    TYPE C VALUE      '(IN_DATA) Invalid length. Length must be :',
  ILLEGAL_CHAR_S(29)
    TYPE C VALUE      '(IN_DATA) Illegal character :',
  UNEXPECTED_CHAR_S1(21)
    TYPE C VALUE      '(IN_DATA) Character (',
  UNEXPECTED_CHAR_S2(34)
    TYPE C VALUE      ') unexpected/illegal at position :',
  INVALID_SAPSCRIPT_NAME_S(46)
    TYPE C VALUE      'Invalid SAPScript parameter name. It must be :'.

* -- Global variables
DATA:
  W_TOTAL1 TYPE P,
  W_TOTAL2 TYPE P,
  W_MOD   LIKE SY-FDPOS,
  W_256X(MAX_LEN) TYPE X,
  W_DIGIT,
  W_DIGITX TYPE X,
  W_INPUT(MAX_LEN),
  W_INPUT2(MAX_LEN),
  W_TEMP(129),
  W_SUPP(16),
  W_WEIGHT TYPE P.

DATA:
  BEGIN OF WORK,
    TEXT(MAX_LEN) TYPE C,
  END OF WORK.

DATA:
  BEGIN OF WORK2,
    HEXA(MAX_LEN) TYPE X,
  END OF WORK2.

DATA:
  EVEN_FG.

* -- for EBCDIC/ASCII conversion
DATA:
  FLG_SYS_EBCDIC(01) TYPE C VALUE ' ',
  TMPX            TYPE X,
  ASC2EBC_000(64) TYPE X,
  ASC2EBC_064(64) TYPE X,
  ASC2EBC_128(64) TYPE X,
  ASC2EBC_192(64) TYPE X,
  EBC2ASC_000(64) TYPE X,
  EBC2ASC_064(64) TYPE X,
  EBC2ASC_128(64) TYPE X,
  EBC2ASC_192(64) TYPE X.


*---------------------------------------------------------------------*
*       FORM TEST                                                     *
*---------------------------------------------------------------------*
*       ........                                                      *
* added 040616/dk;
*---------------------------------------------------------------------*
*---------------------------------------------------------------------*

* -- uncomment for testing
*  PERFORM TEST1.

FORM TEST1.

* -- simulate EBCDIC
  FLG_SYS_EBCDIC = 'X'.
  PERFORM CVT_EBC_INIT.

  DATA:
    parm(MAX_LEN) TYPE C VALUE 'Hello Dolly !$#@~',
    parmx1(MAX_LEN) TYPE X,
    parmx2(MAX_LEN) TYPE X,
    parmx3(MAX_LEN) TYPE X.

  WRITE parm TO parmx1.
    MOVE parmx1 TO parmx2.
  PERFORM CVT_ASC2EBC USING parmx2.
    MOVE parmx2 TO parmx3.
  PERFORM CVT_EBC2ASC USING parmx3.
    break-point.

ENDFORM.

FORM TEST2.

  DATA:
    parm1(BARCODE_TYPE_LEN) TYPE C VALUE 'CD128B',
    parm2(MAX_LEN)          TYPE C VALUE 'Hello',
    parm3(MAX_LEN)          TYPE C VALUE ' ',
    parm4(1)                TYPE C VALUE ' '.

  PERFORM CONVERT_ABAP USING parm1 parm2 parm3 parm4.
    break-point.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM CONVERT                                                  *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  IN_PAR                                                        *
*  -->  OUT_PAR                                                       *
*---------------------------------------------------------------------*
FORM CONVERT TABLES IN_PAR STRUCTURE ITCSY
                   OUT_PAR STRUCTURE ITCSY.

  DATA:
    BARCODE_TYPE(BARCODE_TYPE_LEN) TYPE C,
    INPUT_DATA(MAX_LEN)            TYPE C,
    OUTPUT_DATA(MAX_LEN)           TYPE C,
    ST(1)                          TYPE C.

  READ TABLE IN_PAR WITH KEY 'TYPE'.
  IF SY-SUBRC = 0.
    BARCODE_TYPE = IN_PAR-VALUE.
    READ TABLE IN_PAR WITH KEY 'IN_DATA'.
    IF SY-SUBRC = 0.
      INPUT_DATA = IN_PAR-VALUE.
      PERFORM CONVERT_ABAP USING BARCODE_TYPE INPUT_DATA OUTPUT_DATA ST.
    ELSE.
      CONCATENATE INVALID_SAPSCRIPT_NAME_S 'IN_DATA' INTO OUTPUT_DATA.
      ST = INVALID_SAPSCRIPT_NAME.
    ENDIF.
  ELSE.
    CONCATENATE INVALID_SAPSCRIPT_NAME_S 'TYPE' INTO OUTPUT_DATA.
    ST = INVALID_SAPSCRIPT_NAME.
  ENDIF.

  READ TABLE OUT_PAR WITH KEY 'OUT_DATA'.
  IF SY-SUBRC = 0.
    OUT_PAR-VALUE = OUTPUT_DATA.
    MODIFY OUT_PAR INDEX SY-TABIX.
  ELSE.
    ST = INVALID_SAPSCRIPT_NAME.
  ENDIF.
  READ TABLE OUT_PAR WITH KEY 'STATUS'.
  IF SY-SUBRC = 0.
    OUT_PAR-VALUE = ST.
    MODIFY OUT_PAR INDEX SY-TABIX.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM CONVERT_ABAP                                             *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM CONVERT_ABAP USING TYPE INPUT OUTPUT STATUS.

  IF TYPE CP '*128*' OR TYPE CP 'CD39E*' OR TYPE CP 'CD93E*'.
    MOVE INPUT TO WORK2.
  ENDIF.
  MOVE INPUT TO WORK.

* -- detect if ASCII or EBCDIC system; added 040616/dk;
  WRITE 'A' TO TMPX.
  IF TMPX = 'C1'.
    FLG_SYS_EBCDIC = 'X'.
    PERFORM CVT_EBC_INIT.
  ENDIF.

  STATUS = NO_ERROR.

  CASE TYPE.

    WHEN 'CD128' OR 'CD128A' OR 'CD128B' OR 'CD128C'.
      PERFORM ROUTINE_128 USING TYPE WORK2-HEXA OUTPUT STATUS.

    WHEN 'EAN128'.
      PERFORM ROUTINE_128 USING TYPE WORK2-HEXA OUTPUT STATUS.

    WHEN 'UPC128'.
      PERFORM ROUTINE_128 USING TYPE WORK2-HEXA OUTPUT STATUS.

    WHEN 'CD39' OR
           'CD39_S'    OR 'CD39_N'    OR 'CD39_F'    OR 'CD39_H' OR
         'CD39_X' OR
           'CD39_X_S'  OR 'CD39_X_N'  OR 'CD39_X_F'  OR 'CD39_X_H'.
      PERFORM ROUTINE_CD39 USING TYPE WORK-TEXT OUTPUT STATUS.

    WHEN 'PZN'.
      PERFORM ROUTINE_PZN USING TYPE WORK-TEXT OUTPUT STATUS.

    WHEN 'CD39E' OR
           'CD39E_S'   OR 'CD39E_N'   OR 'CD39E_F'   OR 'CD39E_H' OR
         'CD39E_X' OR
           'CD39E_X_S' OR 'CD39E_X_N' OR 'CD39E_X_F' OR 'CD39E_X_H'.
      PERFORM ROUTINE_CD39HEX USING TYPE WORK2-HEXA OUTPUT STATUS.

    WHEN 'CD93'        OR 'CD93_N'    OR 'CD93_F'    OR 'CD93_H'.
      PERFORM ROUTINE_CD93 USING TYPE WORK-TEXT OUTPUT STATUS.

    WHEN 'CD93E'       OR 'CD93E_N'   OR 'CD93E_F'   OR 'CD93E_H'.
      PERFORM ROUTINE_CD93HEX USING TYPE WORK2-HEXA OUTPUT STATUS.

    WHEN 'CODA'     OR 'CODA_N'     OR 'CODA_H'     OR 'CODA_F'    OR
         'CODA_AIM' OR 'CODA_AIM_N' OR 'CODA_AIM_H' OR 'CODA_AIM_F'.
      PERFORM ROUTINE_CODA USING TYPE WORK-TEXT OUTPUT STATUS.

    WHEN '25INT' OR '25INT_X' OR 'GPAG'.
      PERFORM ROUTINE_INT USING TYPE WORK-TEXT OUTPUT STATUS.

    WHEN '25IND' OR
           '25IND_S'   OR '25IND_N'   OR '25IND_H'   OR '25IND_F' OR
         '25IND_X' OR
           '25IND_X_S' OR '25IND_X_N' OR '25IND_X_H' OR '25IND_X_F'.
      PERFORM ROUTINE_25IND USING TYPE WORK-TEXT OUTPUT STATUS.

    WHEN '25MAT' OR
           '25MAT_S'   OR '25MAT_N'   OR '25MAT_H'   OR '25MAT_F' OR
         '25MAT_X' OR
           '25MAT_X_S' OR '25MAT_X_N' OR '25MAT_X_H' OR '25MAT_X_F'.
      PERFORM ROUTINE_25IND USING TYPE WORK-TEXT OUTPUT STATUS.

    WHEN 'MSI' OR
           'MSI_S'      OR 'MSI_N'      OR 'MSI_H'      OR 'MSI_F'
      OR 'MSI_10' OR
           'MSI_10_S'   OR 'MSI_10_N'   OR 'MSI_10_H'   OR 'MSI_10_F'
      OR 'MSI_1010' OR
           'MSI_1010_S' OR 'MSI_1010_N' OR 'MSI_1010_H' OR 'MSI_1010_F'.
*     -- At this moment, we do not support modulo 11 check digit.
*     OR 'MSI_1110' OR
*          'MSI_1110_S' OR 'MSI_1110_N' OR 'MSI_1110_H' OR 'MSI_1110_F'.
      PERFORM ROUTINE_MSI USING TYPE WORK-TEXT OUTPUT STATUS.

    WHEN 'POSTNET5' OR 'POSTNET9' OR 'POSTNET11'.
      PERFORM ROUTINE_POSTNET USING TYPE WORK-TEXT OUTPUT STATUS.

    WHEN 'EAN13'   OR 'EAN132'   OR 'EAN135' OR
         'EAN13BM' OR 'EAN132BM' OR 'EAN135BM'.
      PERFORM ROUTINE_EAN13 USING TYPE WORK-TEXT OUTPUT STATUS.

    WHEN 'EAN8'    OR 'EAN82'    OR 'EAN85'  OR 'EANV'.
      PERFORM ROUTINE_EAN8  USING TYPE WORK-TEXT OUTPUT STATUS.

    WHEN 'UPCA'    OR 'UPCA2'    OR 'UPCA5'.
      PERFORM ROUTINE_UPCA  USING TYPE WORK-TEXT OUTPUT STATUS.

    WHEN 'UPCE'    OR 'UPCE2'    OR 'UPCE5'.
      PERFORM ROUTINE_UPCE  USING TYPE WORK-TEXT OUTPUT STATUS.

    WHEN OTHERS.
      CONCATENATE INVALID_BARCODE_TYPE_S TYPE INTO OUTPUT.
      STATUS = INVALID_BARCODE_TYPE.

  ENDCASE.

  CASE STATUS.
    WHEN NO_ERROR.
    WHEN INVALID_BARCODE_TYPE.
      IF OUTPUT = SPACE.
        CONCATENATE INVALID_BARCODE_TYPE_S TYPE INTO OUTPUT.
      ENDIF.
    WHEN INVALID_LENGTH.
      IF OUTPUT = SPACE.
        CONCATENATE INVALID_LENGTH_S INPUT INTO OUTPUT.
      ENDIF.
    WHEN ILLEGAL_CHAR.
      IF OUTPUT = SPACE.
        CONCATENATE ILLEGAL_CHAR_S INPUT INTO OUTPUT.
      ENDIF.
    WHEN UNEXPECTED_CHAR.
      IF OUTPUT = SPACE.
        CONCATENATE UNEXPECTED_CHAR_S1 UNEXPECTED_CHAR_S2 INPUT
          INTO OUTPUT.
      ENDIF.
    WHEN INVALID_SAPSCRIPT_NAME.
      IF OUTPUT = SPACE.
        OUTPUT = INVALID_SAPSCRIPT_NAME_S.
      ENDIF.
    WHEN OTHERS.
      IF OUTPUT = SPACE.
        OUTPUT =
          'UNEXPECTED ERROR OCCURRED. PLEASE ASK TECHNICAL SUPPORT.'.
      ENDIF.
  ENDCASE.

  IF STATUS = NO_ERROR.

*   -- added 25INT*; (remapping all incompatible chars); 041221/ws 
    IF TYPE CP '*128*' OR TYPE CP 'CD39*' OR TYPE CP 'CD93*' OR TYPE CP
'25INT*'.
      PERFORM REMAP_INCOMPATIBLES USING OUTPUT.
    ENDIF.

*   -- & -> <38> ROUTINE ; added 040211/Nom;
    IF TYPE CP '*128*' OR TYPE CP '25INT*' OR TYPE CP 'GPAG'.
      PERFORM CONVERT_AMP USING OUTPUT.
    ENDIF.

  ENDIF.

  IF TYPE CP '*128*' OR TYPE CP 'CD39E*' OR TYPE CP 'CD93E*'.
    MOVE OUTPUT TO WORK2.
  ELSE.
    MOVE OUTPUT TO WORK.
  ENDIF.

ENDFORM.


*---------------------------------------------------------------------*
*       FORM REMAP_INCOMPATIBLES                                      *
*---------------------------------------------------------------------*
*       ........                                                      *
* Name changed: (old name: CONVERT_SPACE) 041221/ws                   *
* (Using TRANSLATE instead of "DO LOOP")                             *
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*---------------------------------------------------------------------*
FORM REMAP_INCOMPATIBLES USING OUTPUT.

  CONSTANTS:
*   -- for re-mapping incompatible chars (20->B0, 7F->BF);
*      041220/ws: new; added 7F->BF;
    REMAP_VECTOR(4) TYPE X VALUE '20B07FBF'.

  DATA :
    LENGTH TYPE I,
    W_DATA(MAX_LEN) TYPE C.

  W_DATA = OUTPUT.
  LENGTH = STRLEN( OUTPUT ).
  CLEAR : OUTPUT.

  TRANSLATE W_DATA USING REMAP_VECTOR.

  CONCATENATE OUTPUT W_DATA+0(LENGTH) INTO OUTPUT.

ENDFORM.


*---------------------------------------------------------------------*
*       FORM CONVERT_AMP                                              *
*---------------------------------------------------------------------*
*       ........                                                      *
* & -> <38> ROUTINE; added 040211/Nom;
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*---------------------------------------------------------------------*
FORM CONVERT_AMP USING OUTPUT.

  DATA :
    LENGTH TYPE I,
    W_DATA(MAX_LEN) TYPE C.

  W_DATA = OUTPUT.
  LENGTH = STRLEN( OUTPUT ).
  CLEAR : OUTPUT.

  DO LENGTH TIMES.
    IF W_DATA+0(01) = '&'.
      CONCATENATE OUTPUT AMP2CHAR INTO OUTPUT.
    ELSE.
      CONCATENATE OUTPUT W_DATA+0(01) INTO OUTPUT.
    ENDIF.
    SHIFT W_DATA.
  ENDDO.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM ROUTINE_CD39                                             *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM ROUTINE_CD39 USING TYPE INPUT OUTPUT STATUS.

  CONSTANTS:
    W_MOD43(43) VALUE '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%'.

  DATA :
    LENGTH TYPE I,
    W_DATA(MAX_LEN) TYPE C,
    CHKDGT_FLG TYPE I.

  CLEAR:W_TOTAL1.

  IF TYPE = 'CD39'   OR
       TYPE = 'CD39_S'   OR TYPE = 'CD39_N'   OR
       TYPE = 'CD39_F'   OR TYPE = 'CD39_H'   OR
     TYPE = 'CD39_X' OR
       TYPE = 'CD39_X_S' OR TYPE = 'CD39_X_N' OR
       TYPE = 'CD39_X_F' OR TYPE = 'CD39_X_H'.
    PERFORM TOUPPER USING INPUT W_INPUT.
    W_DATA = W_INPUT.
  ELSE.
    W_DATA = W_INPUT = INPUT.
  ENDIF.

* -- calculate check digit ?
  IF TYPE = 'CD39_X' OR
       TYPE = 'CD39_X_S'  OR TYPE = 'CD39_X_N'  OR
       TYPE = 'CD39_X_H'  OR TYPE = 'CD39_X_F'  OR
     TYPE = 'CD39E_X' OR
       TYPE = 'CD39E_X_S' OR TYPE = 'CD39E_X_N' OR
       TYPE = 'CD39E_X_H' OR TYPE = 'CD39E_X_F'.
    CHKDGT_FLG = 1.
  ELSE.
    CHKDGT_FLG = 0.
  ENDIF.

* -- check data and calculate check digit

  LENGTH = STRLEN( W_INPUT ).

  DO LENGTH TIMES.
    IF W_MOD43 CS W_INPUT+0(1).
    ENDIF.
    IF SY-FDPOS < 43.
      IF CHKDGT_FLG = 1.
        IF W_INPUT+0(1) = SPACE.
          W_TOTAL1 = W_TOTAL1 + 38.
        ELSE.
          W_TOTAL1 = W_TOTAL1 + SY-FDPOS.
        ENDIF.
      ENDIF.
      SHIFT W_INPUT.
    ELSE.
      CONCATENATE ILLEGAL_CHAR_S W_INPUT+0(1) INTO OUTPUT.
      STATUS = ILLEGAL_CHAR.
      EXIT.
    ENDIF.
  ENDDO.

  IF STATUS = NO_ERROR.
    IF CHKDGT_FLG = 1.
      W_MOD = W_TOTAL1 MOD 43.
      W_DIGIT = W_MOD43+W_MOD(1).
    ENDIF.
    CASE TYPE.
      WHEN 'CD39' OR 'CD39_S' OR 'CD39E' OR 'CD39E_S'.
        CONCATENATE '*' W_DATA '*' INTO OUTPUT.
      WHEN 'CD39_X_S' OR 'CD39E_X_S' OR 'CD39_X' OR 'CD39E_X'.
        IF W_DIGIT = SPACE.
          CONCATENATE '*' W_DATA ' *' INTO OUTPUT.
        ELSE.
          CONCATENATE '*' W_DATA W_DIGIT '*' INTO OUTPUT.
        ENDIF.
      WHEN 'CD39_F' OR 'CD39E_F'.
        CONCATENATE ')' W_DATA ')' INTO OUTPUT.
      WHEN 'CD39_X_F' OR 'CD39E_X_F'.
        IF W_DIGIT = SPACE.
          CONCATENATE ')' W_DATA ' )' INTO OUTPUT.
        ELSE.
          CONCATENATE ')' W_DATA W_DIGIT ')' INTO OUTPUT.
        ENDIF.
      WHEN 'CD39_N' OR 'CD39E_N'.
        CONCATENATE '(' W_DATA '(' INTO OUTPUT.
      WHEN 'CD39_X_N' OR 'CD39E_X_N'.
        IF W_DIGIT = SPACE.
          CONCATENATE '(' W_DATA ' (' INTO OUTPUT.
        ELSE.
          CONCATENATE '(' W_DATA W_DIGIT '(' INTO OUTPUT.
        ENDIF.
      WHEN 'CD39_H' OR 'CD39E_H'.
        CONCATENATE '<38>' W_DATA '<38>' INTO OUTPUT.
      WHEN 'CD39_X_H' OR 'CD39E_X_H'.
        IF W_DIGIT = SPACE.
          CONCATENATE '<38>' W_DATA ' <38>' INTO OUTPUT.
        ELSE.
          CONCATENATE '<38>' W_DATA W_DIGIT '<38>' INTO OUTPUT.
        ENDIF.
    ENDCASE.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM ROUTINE_PZN                                              *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM ROUTINE_PZN USING TYPE INPUT OUTPUT STATUS.

  CONSTANTS:
    W_MOD43(43) VALUE '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%'.

  DATA:
    LENGTH TYPE I.

  W_INPUT = INPUT.
  CLEAR:W_TOTAL1.

  LENGTH = STRLEN( W_INPUT ).

  IF LENGTH <> 6.
    CONCATENATE INVALID_LENGTH_S ' 6' INTO OUTPUT.
    STATUS = INVALID_LENGTH.
  ENDIF.

  DO 6 TIMES.
    IF W_MOD43 CS W_INPUT+0(1).
    ENDIF.
    IF SY-FDPOS < 43.
      IF W_INPUT+0(1) = SPACE.
        W_TOTAL1 = W_TOTAL1 + 38 * ( SY-INDEX + 1 ).
      ELSE.
        W_TOTAL1 = W_TOTAL1 + SY-FDPOS * ( SY-INDEX + 1 ).
      ENDIF.
      SHIFT W_INPUT.
    ELSE.
      CONCATENATE ILLEGAL_CHAR_S W_INPUT+0(1) INTO OUTPUT.
      STATUS = ILLEGAL_CHAR.
      EXIT.
    ENDIF.
  ENDDO.

  IF STATUS = NO_ERROR.
    W_MOD = W_TOTAL1 MOD 11.
    IF W_MOD = 10.
      CONCATENATE ILLEGAL_CHAR_S 'Check digit = 10' INTO OUTPUT.
      STATUS = ILLEGAL_CHAR.
    ELSE.
      W_DIGIT = W_MOD43+W_MOD(1).
      CONCATENATE '*-' INPUT W_DIGIT '*' INTO OUTPUT.
    ENDIF.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM ROUTINE_CD39HEX                                          *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM ROUTINE_CD39HEX USING TYPE INPUT OUTPUT STATUS.

  DATA:
    INPUT_DATA(MAX_LEN) TYPE X,
    CONV_DATA(MAX_LEN)  TYPE C.

  INPUT_DATA = INPUT.

  PERFORM CONVERT_CD39 USING INPUT_DATA CONV_DATA STATUS.
  IF STATUS = NO_ERROR.
    PERFORM ROUTINE_CD39 USING TYPE CONV_DATA OUTPUT STATUS.
  ELSE.
    OUTPUT = CONV_DATA.
  ENDIF.
ENDFORM.

*---------------------------------------------------------------------*
*       FORM CONVERT_CD39                                             *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  INDATA                                                        *
*  -->  OUTDATA                                                       *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM CONVERT_CD39 USING INDATA OUTDATA STATUS.

  DATA:
    SPACE_CNT TYPE I,
    LENGTH TYPE I,
    OUTLEN TYPE I,
    W_INDATA(MAX_LEN) TYPE X,
    SPACE_CHAR(01) TYPE X VALUE '20',
    W_CHAR(02) TYPE C.

  W_INDATA = INDATA.
  LENGTH = STRLEN( W_INDATA ).

  DO LENGTH TIMES.
    IF W_INDATA+0(01) = '20'.
      SPACE_CNT = SPACE_CNT + 1.
    ELSE.
      PERFORM CONVERT_CD39CHAR USING W_INDATA+0(01) W_CHAR STATUS.
      IF STATUS = NO_ERROR.
        IF SPACE_CNT = 0.
          CONCATENATE OUTDATA W_CHAR INTO OUTDATA.
        ELSE.
          OUTLEN = STRLEN( OUTDATA ) + SPACE_CNT.
          OUTDATA+OUTLEN(02) = W_CHAR.
          SPACE_CNT = 0.
        ENDIF.
      ELSE.
        CONCATENATE ILLEGAL_CHAR_S W_INDATA+0(01) INTO OUTDATA.
        EXIT.
      ENDIF.
    ENDIF.
    SHIFT W_INDATA.
  ENDDO.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM ROUTINE_CD93                                             *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM ROUTINE_CD93 USING TYPE INPUT OUTPUT STATUS.

  DATA:
    LENGTH           TYPE I,
    W_DATA(MAX_LEN)  TYPE C,
    FIRST_DIGIT(01)  TYPE C,
    SECOND_DIGIT(01) TYPE C.

  IF TYPE = 'CD93' OR
       TYPE = 'CD93_N' OR TYPE = 'CD93_H' OR TYPE = 'CD93_F'.
    PERFORM TOUPPER USING INPUT W_INPUT.
  ELSE.
    W_INPUT = INPUT.
  ENDIF.
  W_DATA = W_INPUT.

* -- calculate 1st check digit
  PERFORM CD93_CHECKDIGIT USING 1 W_INPUT FIRST_DIGIT OUTPUT STATUS.
  IF STATUS = NO_ERROR.
    CONCATENATE W_DATA FIRST_DIGIT INTO W_INPUT.

*   -- calculate 2nd check digit
    PERFORM CD93_CHECKDIGIT USING 2 W_INPUT SECOND_DIGIT OUTPUT STATUS.
    IF STATUS = NO_ERROR.
      CASE TYPE.
        WHEN 'CD93' OR 'CD93_N' OR 'CD93E' OR 'CD93E_N'.
          IF FIRST_DIGIT = SPACE.
            CONCATENATE '(' W_DATA INTO OUTPUT.
            LENGTH = STRLEN( OUTPUT ).
            OUTPUT+LENGTH(02) = SECOND_DIGIT.
            CONCATENATE OUTPUT ')' INTO OUTPUT.
          ELSE.
            IF SECOND_DIGIT = SPACE.
              CONCATENATE '(' W_DATA FIRST_DIGIT ' )' INTO OUTPUT.
            ELSE.
              CONCATENATE '(' W_DATA FIRST_DIGIT SECOND_DIGIT ')' INTO
                   OUTPUT.
            ENDIF.
          ENDIF.
        WHEN 'CD93_H' OR 'CD93E_H'.
          IF FIRST_DIGIT = SPACE.
            CONCATENATE '"' W_DATA INTO OUTPUT.
            LENGTH = STRLEN( OUTPUT ).
            OUTPUT+LENGTH(02) = SECOND_DIGIT.
            CONCATENATE OUTPUT '#' INTO OUTPUT.
          ELSE.
            IF SECOND_DIGIT = SPACE.
              CONCATENATE '"' W_DATA FIRST_DIGIT ' #' INTO OUTPUT.
            ELSE.
              CONCATENATE '"' W_DATA FIRST_DIGIT SECOND_DIGIT '#' INTO
                     OUTPUT.
            ENDIF.
          ENDIF.
        WHEN 'CD93_F' OR 'CD93E_F'.
          IF FIRST_DIGIT = SPACE.
            CONCATENATE '&' W_DATA INTO OUTPUT.
            LENGTH = STRLEN( OUTPUT ).
            OUTPUT+LENGTH(02) = SECOND_DIGIT.
            CONCATENATE OUTPUT '''' INTO OUTPUT.
          ELSE.
            IF SECOND_DIGIT = SPACE.
              CONCATENATE '&' W_DATA FIRST_DIGIT ' ''' INTO OUTPUT.
            ELSE.
              CONCATENATE '&' W_DATA FIRST_DIGIT SECOND_DIGIT '''' INTO
                          OUTPUT.
            ENDIF.
          ENDIF.
      ENDCASE.
    ENDIF.

  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM CD93_CHECKDIGIT                                          *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  ORDINAL                                                       *
*  -->  STRING                                                        *
*  -->  DIGIT                                                         *
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM CD93_CHECKDIGIT USING ORDINAL STRING DIGIT OUTPUT STATUS.

  CONSTANTS:
    W_CODE93(47) TYPE C VALUE
      '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%abcd'.
  DATA:
    LENGTH TYPE I,
    COUNTER1 TYPE I,
    COUNTER2 TYPE I,
    NO TYPE I,
    W_DATA(MAX_LEN) TYPE C,
    W_POS LIKE SY-FDPOS.

  CLEAR: W_TOTAL1.

  IF ORDINAL = 1.
    NO = 20.
  ELSE.
    NO = 15.
  ENDIF.

  LENGTH = STRLEN( STRING ).
  COUNTER1 = LENGTH - 1.
  COUNTER2 = 1.

  DO LENGTH TIMES.
    W_DATA = STRING.
    SHIFT W_DATA BY COUNTER1 PLACES.
    IF W_CODE93 CS  W_DATA+0(1).
    ENDIF.
    W_POS = SY-FDPOS.
    IF W_POS < 47.
      IF W_DATA+0(1) = SPACE.
        W_TOTAL1 = W_TOTAL1 + ( 38 * COUNTER2 ).
      ELSE.
*   -- if data is lowercase 'a' ?
        IF W_DATA+0(1) CP '#a'.
          W_TOTAL1 = W_TOTAL1 + ( 43 * COUNTER2 ).
        ELSE.
*   -- if data is lowercase 'b' ?
          IF W_DATA+0(1) CP '#b'.
            W_TOTAL1 = W_TOTAL1 + ( 44 * COUNTER2 ).
          ELSE.
*   -- if data is lowercase 'c' ?
            IF W_DATA+0(1) CP '#c'.
              W_TOTAL1 = W_TOTAL1 + ( 45 * COUNTER2 ).
            ELSE.
*   -- if data is lowercase 'd' ?
              IF W_DATA+0(1) CP '#d'.
                W_TOTAL1 = W_TOTAL1 + ( 46 * COUNTER2 ).
              ELSE.
                W_TOTAL1 = W_TOTAL1 + ( W_POS * COUNTER2 ).
              ENDIF.
            ENDIF.
          ENDIF.
        ENDIF.
      ENDIF.
    ELSE.
      CONCATENATE ILLEGAL_CHAR_S W_DATA+0(1) INTO OUTPUT.
      STATUS = ILLEGAL_CHAR.
      EXIT.
    ENDIF.
    COUNTER1 = COUNTER1 - 1.
    IF COUNTER2 = NO.
      COUNTER2 = 1.
    ELSE.
      COUNTER2 = COUNTER2 + 1.
    ENDIF.
  ENDDO.

  IF STATUS = NO_ERROR.
*   -- calculate Modulo 47
    W_MOD = W_TOTAL1 MOD 47.
    DIGIT = W_CODE93+W_MOD(1).
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM ROUTINE_CD93HEX                                          *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM ROUTINE_CD93HEX USING TYPE INPUT OUTPUT STATUS.

  DATA:
    INPUT_DATA(MAX_LEN) TYPE X,
    CONV_DATA(MAX_LEN)  TYPE C.

  INPUT_DATA = INPUT.
  CLEAR : CONV_DATA.
  PERFORM CONVERT_CD93 USING INPUT_DATA CONV_DATA STATUS.
  IF STATUS = NO_ERROR.
    PERFORM ROUTINE_CD93 USING TYPE CONV_DATA OUTPUT STATUS.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM CONVERT_CD93                                             *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  INDATA                                                        *
*  -->  OUTDATA                                                       *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM CONVERT_CD93 USING INDATA OUTDATA STATUS.

  DATA:
    SPACE_CNT         TYPE I,
    COUNTER           TYPE I,
    LENGTH            TYPE I,
    OUTLEN            TYPE I,
    W_INDATA(MAX_LEN) TYPE X,
    SPACE_CHAR(01)    TYPE X VALUE '20',
    W_CHAR(02)        TYPE C.

  W_INDATA = INDATA.
  LENGTH = STRLEN( W_INDATA ).

  DO LENGTH TIMES.
    IF W_INDATA+0(01) = '20'.
      SPACE_CNT = SPACE_CNT + 1.
    ELSE.
      PERFORM CONVERT_CD93CHAR USING W_INDATA+0(01) W_CHAR STATUS.
      IF STATUS = NO_ERROR.
        IF SPACE_CNT = 0.
          CONCATENATE OUTDATA W_CHAR INTO OUTDATA.
        ELSE.
          OUTLEN = STRLEN( OUTDATA ) + SPACE_CNT.
          OUTDATA+OUTLEN(02) = W_CHAR.
          SPACE_CNT = 0.
        ENDIF.
      ELSE.
        CONCATENATE ILLEGAL_CHAR_S W_INDATA+0(01) INTO OUTDATA.
        EXIT.
      ENDIF.
    ENDIF.
    SHIFT W_INDATA.
  ENDDO.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM ROUTINE_128                                              *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM ROUTINE_128 USING TYPE INPUT OUTPUT STATUS.

  CASE TYPE.
    WHEN 'CD128'.
      PERFORM MODULE_128  USING TYPE INPUT OUTPUT STATUS.
    WHEN 'CD128A'.
      PERFORM MODULE_128A USING TYPE INPUT OUTPUT STATUS.
    WHEN 'CD128B'.
      PERFORM MODULE_128A USING TYPE INPUT OUTPUT STATUS.
    WHEN 'CD128C'.
      PERFORM MODULE_128A USING TYPE INPUT OUTPUT STATUS.
    WHEN 'UPC128'.
      PERFORM MODULE_128A USING TYPE INPUT OUTPUT STATUS.
    WHEN 'EAN128'.
      PERFORM MODULE_128  USING TYPE INPUT OUTPUT STATUS.
  ENDCASE.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM ROUTINE_MSI                                              *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM ROUTINE_MSI USING TYPE INPUT OUTPUT STATUS.

  DATA :
    SAVED_INPUT(20) TYPE C,
    LENGTH          TYPE I.

* -- get input data length
  LENGTH = STRLEN( INPUT ).
* -- numeric check
  PERFORM ISDIGIT USING INPUT LENGTH STATUS.
  IF STATUS <> NO_ERROR.
    CONCATENATE ILLEGAL_CHAR_S 'Alphabet is not allowed' INPUT
                INTO OUTPUT.
  ENDIF.

  W_INPUT = INPUT.
  SAVED_INPUT = INPUT.

  IF STATUS = NO_ERROR.
    CASE TYPE.

      WHEN 'MSI_10'   OR 'MSI_10_S'   OR 'MSI_10_N'
                      OR 'MSI_10_H'   OR 'MSI_10_F'.
        PERFORM MODULE_10 USING W_INPUT LENGTH.
        W_DIGIT = W_MOD.
        CONCATENATE INPUT W_DIGIT INTO SAVED_INPUT.

      WHEN 'MSI_1010' OR 'MSI_1010_S' OR 'MSI_1010_N'
                      OR 'MSI_1010_H' OR 'MSI_1010_F'.
        PERFORM MODULE_10 USING W_INPUT LENGTH.
        W_DIGIT = W_MOD.
        CONCATENATE INPUT W_DIGIT INTO W_INPUT.
        SAVED_INPUT = W_INPUT.
        LENGTH = STRLEN( W_INPUT ).
        PERFORM MODULE_10 USING W_INPUT LENGTH.
        W_DIGIT = W_MOD.
        CONCATENATE SAVED_INPUT W_DIGIT INTO SAVED_INPUT.

      WHEN 'MSI_1110' OR 'MSI_1110_S' OR 'MSI_1110_N'
                      OR 'MSI_1110_H' OR 'MSI_1110_F'.
        PERFORM MODULE_11 USING INPUT LENGTH.
        W_DIGIT = W_MOD.
        CONCATENATE INPUT W_DIGIT INTO W_INPUT.
        SAVED_INPUT = W_INPUT.
        LENGTH = STRLEN( W_INPUT ).
        PERFORM MODULE_10 USING W_INPUT LENGTH.
        W_DIGIT = W_MOD.
        CONCATENATE SAVED_INPUT W_DIGIT INTO SAVED_INPUT.

    ENDCASE.
  ENDIF.

  IF STATUS = NO_ERROR.
    CASE TYPE.
      WHEN 'MSI'   OR 'MSI_10'   OR 'MSI_1010'   OR 'MSI_1110'   OR
           'MSI_S' OR 'MSI_10_S' OR 'MSI_1010_S' OR 'MSI_1110_S'.
        CONCATENATE 'A' SAVED_INPUT 'B' INTO OUTPUT.
      WHEN 'MSI_N' OR 'MSI_10_N' OR 'MSI_1010_N' OR 'MSI_1110_N'.
        CONCATENATE 'C' SAVED_INPUT 'D' INTO OUTPUT.
      WHEN 'MSI_H' OR 'MSI_10_H' OR 'MSI_1010_H' OR 'MSI_1110_H'.
        CONCATENATE 'E' SAVED_INPUT 'F' INTO OUTPUT.
      WHEN 'MSI_F' OR 'MSI_10_F' OR 'MSI_1010_F' OR 'MSI_1110_F'.
        CONCATENATE 'G' SAVED_INPUT 'H' INTO OUTPUT.
    ENDCASE.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM ROUTINE_UPCA                                             *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM ROUTINE_UPCA USING TYPE INPUT OUTPUT STATUS.

  DATA :
    W_CONV(32) TYPE C,
    LENGTH     TYPE I.

  W_INPUT = INPUT.
  CLEAR:W_SUPP.
  LENGTH = STRLEN( W_INPUT ).

  CASE TYPE.

    WHEN 'UPCA'.
      IF LENGTH = 11.
        W_INPUT = INPUT.
        W_INPUT2 = INPUT.
        PERFORM ISDIGIT USING W_INPUT LENGTH STATUS.
        IF STATUS = NO_ERROR.
          PERFORM MODULE_10W3 USING W_INPUT LENGTH.
        ELSE.
          CONCATENATE ILLEGAL_CHAR_S 'Alphabet is not allowed' W_INPUT
                      INTO OUTPUT.
        ENDIF.
      ELSE.
        CONCATENATE INVALID_LENGTH_S '11' INTO OUTPUT.
        STATUS = INVALID_LENGTH.
      ENDIF.

    WHEN 'UPCA2'.
      IF LENGTH = 13.
        W_SUPP = INPUT+11(02).
        W_INPUT = INPUT+0(11).
        W_INPUT2 = INPUT+0(11).
        PERFORM ISDIGIT USING INPUT LENGTH STATUS.
        IF STATUS = NO_ERROR.
          PERFORM MODULE_10W3 USING W_INPUT 11.
          PERFORM ADD2_CONVERT USING W_SUPP.
        ELSE.
          CONCATENATE ILLEGAL_CHAR_S 'Alphabet is not allowed' W_INPUT
                      INTO OUTPUT.
        ENDIF.
      ELSE.
        CONCATENATE INVALID_LENGTH_S '13' INTO OUTPUT.
        STATUS = INVALID_LENGTH.
      ENDIF.

    WHEN 'UPCA5'.
      IF LENGTH = 16.
        W_SUPP = INPUT+11(05).
        W_INPUT = INPUT+0(11).
        W_INPUT2 = INPUT+0(11).
        PERFORM ISDIGIT USING INPUT LENGTH STATUS.
        IF STATUS = NO_ERROR.
          PERFORM MODULE_10W3 USING W_INPUT 11.
          PERFORM ADD5_CONVERT USING W_SUPP.
        ELSE.
          CONCATENATE ILLEGAL_CHAR_S 'Alphabet is not allowed' W_INPUT
                      INTO OUTPUT.
        ENDIF.
      ELSE.
        CONCATENATE INVALID_LENGTH_S '16' INTO OUTPUT.
        STATUS = INVALID_LENGTH.
      ENDIF.

  ENDCASE.

  IF STATUS = NO_ERROR.
    W_DIGIT = W_MOD.
    PERFORM UPCA_CONVERT USING W_INPUT2 W_DIGIT W_SUPP OUTPUT.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM ROUTINE_EAN8                                             *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM ROUTINE_EAN8 USING TYPE INPUT OUTPUT STATUS.

  DATA :
    W_CONV(32) TYPE C,
    LENGTH     TYPE I.

  CONSTANTS:
    EAN8_CONV(20)   TYPE C VALUE '0A1B2C3D4E5F6G7H8I9J',
    POOLD_DUMMY(01) TYPE X VALUE 'CA'.

  W_INPUT = INPUT.
  CLEAR:W_SUPP.
  LENGTH = STRLEN( W_INPUT ).

  CASE TYPE.

    WHEN 'EAN8'.
      IF LENGTH = 7.
        W_INPUT = W_INPUT2 = INPUT.
        PERFORM ISDIGIT USING W_INPUT LENGTH STATUS.
        IF STATUS = NO_ERROR.
          PERFORM MODULE_10W3 USING W_INPUT LENGTH.
        ELSE.
          CONCATENATE ILLEGAL_CHAR_S 'Alphabet is not allowed' W_INPUT
                      INTO OUTPUT.
        ENDIF.
      ELSE.
        CONCATENATE INVALID_LENGTH_S '7' INTO OUTPUT.
        STATUS = INVALID_LENGTH.
      ENDIF.

    WHEN 'EANV'.
      IF LENGTH = 7.
        W_INPUT = W_INPUT2 = INPUT.
        IF W_INPUT+0(01) = '0'.
          PERFORM ISDIGIT USING W_INPUT LENGTH STATUS.
          IF STATUS = NO_ERROR.
            PERFORM MODULE_10W3 USING W_INPUT LENGTH.
          ELSE.
            CONCATENATE ILLEGAL_CHAR_S 'Alphabet is not allowed'
                        W_INPUT INTO OUTPUT.
          ENDIF.
        ELSE.
          CONCATENATE UNEXPECTED_CHAR_S1 W_INPUT+0(01)
                      UNEXPECTED_CHAR_S2 '1' INTO OUTPUT.
          STATUS = UNEXPECTED_CHAR.
        ENDIF.
      ELSE.
        CONCATENATE INVALID_LENGTH_S '7' INTO OUTPUT.
        STATUS = INVALID_LENGTH.
      ENDIF.

    WHEN 'EAN82'.
      IF LENGTH = 9.
        W_SUPP = INPUT+7(02).
        W_INPUT = INPUT+0(07).
        W_INPUT2 = INPUT+0(07).
        PERFORM ISDIGIT USING INPUT LENGTH STATUS.
        IF STATUS = NO_ERROR.
          PERFORM MODULE_10W3 USING W_INPUT 7.
          PERFORM ADD2_CONVERT USING W_SUPP.
        ELSE.
          CONCATENATE ILLEGAL_CHAR_S 'Alphabet is not allowed' W_INPUT
                      INTO OUTPUT.
        ENDIF.
      ELSE.
        CONCATENATE INVALID_LENGTH_S '9' INTO OUTPUT.
        STATUS = INVALID_LENGTH.
      ENDIF.

    WHEN 'EAN85'.
      IF LENGTH = 12.
        W_SUPP = INPUT+7(05).
        W_INPUT = INPUT+0(07).
        W_INPUT2 = INPUT+0(07).
        PERFORM ISDIGIT USING INPUT LENGTH STATUS.
        IF STATUS = NO_ERROR.
          PERFORM MODULE_10W3 USING W_INPUT 7.
          PERFORM ADD5_CONVERT USING W_SUPP.
        ELSE.
          CONCATENATE ILLEGAL_CHAR_S 'Alphabet is not allowed' W_INPUT
                      INTO OUTPUT.
        ENDIF.
      ELSE.
        CONCATENATE INVALID_LENGTH_S '12' INTO OUTPUT.
        STATUS = INVALID_LENGTH.
      ENDIF.

  ENDCASE.

  IF STATUS = NO_ERROR.
    W_DIGIT = W_MOD.
*   -- width adjustment POOLD_DUMMY
    IF TYPE = 'EAN82' OR TYPE = 'EAN85'.
       CONCATENATE '(' W_INPUT2+0(04) '-' W_INPUT2+4(03)
                     W_DIGIT '(' POOLD_DUMMY W_SUPP INTO W_CONV.
    ELSE.
       CONCATENATE '(' W_INPUT2+0(04) '-' W_INPUT2+4(03)
                     W_DIGIT '(' INTO W_CONV.
    ENDIF.
    TRANSLATE W_CONV+6(04) USING EAN8_CONV.
    OUTPUT = W_CONV.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM ROUTINE_UPCE                                             *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM ROUTINE_UPCE USING TYPE INPUT OUTPUT STATUS.

  DATA :
    W_CONV(32) TYPE C,
    LENGTH     TYPE I.

  W_INPUT = INPUT.
  CLEAR:W_SUPP.
  LENGTH = STRLEN( W_INPUT ).

  CASE TYPE.

    WHEN 'UPCE'.
      IF LENGTH = 7.
        W_INPUT = W_INPUT2 = INPUT.
        PERFORM EXPAND_UPCE USING W_INPUT.
        PERFORM ISDIGIT USING W_INPUT LENGTH STATUS.
        IF STATUS = NO_ERROR.
          PERFORM MODULE_10W3 USING W_INPUT 11.
        ELSE.
          CONCATENATE ILLEGAL_CHAR_S 'Alphabet is not allowed' W_INPUT
                      INTO OUTPUT.
        ENDIF.
      ELSE.
        CONCATENATE INVALID_LENGTH_S '7' INTO OUTPUT.
        STATUS = INVALID_LENGTH.
      ENDIF.

    WHEN 'UPCE2'.
      IF LENGTH = 9.
        W_SUPP = INPUT+7(02).
        W_INPUT = INPUT+0(07).
        W_INPUT2 = INPUT+0(07).
        PERFORM ISDIGIT USING INPUT LENGTH STATUS.
        IF STATUS = NO_ERROR.
          PERFORM EXPAND_UPCE USING W_INPUT.
          PERFORM MODULE_10W3 USING W_INPUT 11.
          PERFORM ADD2_CONVERT USING W_SUPP.
        ELSE.
          CONCATENATE ILLEGAL_CHAR_S 'Alphabet is not allowed' W_INPUT
                      INTO OUTPUT.
        ENDIF.
      ELSE.
        CONCATENATE INVALID_LENGTH_S '9' INTO OUTPUT.
        STATUS = INVALID_LENGTH.
      ENDIF.

    WHEN 'UPCE5'.
      IF LENGTH = 12.
        W_SUPP = INPUT+7(05).
        W_INPUT = INPUT+0(07).
        W_INPUT2 = INPUT+0(07).
        PERFORM ISDIGIT USING INPUT LENGTH STATUS.
        IF STATUS = NO_ERROR.
          PERFORM EXPAND_UPCE USING W_INPUT.
          PERFORM MODULE_10W3 USING W_INPUT 11.
          PERFORM ADD5_CONVERT USING W_SUPP.
        ELSE.
          CONCATENATE ILLEGAL_CHAR_S 'Alphabet is not allowed' W_INPUT
                      INTO OUTPUT.
        ENDIF.
      ELSE.
        CONCATENATE INVALID_LENGTH_S '12' INTO OUTPUT.
        STATUS = INVALID_LENGTH.
      ENDIF.

  ENDCASE.

  IF STATUS = NO_ERROR.
    W_DIGIT = W_MOD.
    PERFORM UPCE_CONVERT USING W_INPUT2 W_DIGIT W_SUPP OUTPUT STATUS.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM EXPAND_UPCE                                              *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  INPUT                                                         *
*---------------------------------------------------------------------*
FORM EXPAND_UPCE USING INPUT.

  DATA:
    W_INDATA(32) TYPE C.

  W_INDATA = INPUT.
  CASE W_INDATA+6(01).
    WHEN '0'.
      CONCATENATE W_INDATA+0(03) '00000' W_INDATA+3(03) INTO INPUT.
    WHEN '1'.
      CONCATENATE W_INDATA+0(03) '10000' W_INDATA+3(03) INTO INPUT.
    WHEN '2'.
      CONCATENATE W_INDATA+0(03) '20000' W_INDATA+3(03) INTO INPUT.
    WHEN '3'.
      CONCATENATE W_INDATA+0(04) '00000' W_INDATA+4(02) INTO INPUT.
    WHEN '4'.
      CONCATENATE W_INDATA+0(05) '00000' W_INDATA+5(01) INTO INPUT.
    WHEN '5' OR '6' OR '7' OR '8' OR '9'.
      CONCATENATE W_INDATA+0(06) '0000'  W_INDATA+6(01) INTO INPUT.
  ENDCASE.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM ROUTINE_INT                                              *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM ROUTINE_INT USING TYPE INPUT OUTPUT STATUS.

  DATA :
    LENGTH TYPE I.

  W_INPUT = W_INPUT2 = INPUT.
  LENGTH = STRLEN( W_INPUT ).
  PERFORM ISDIGIT USING W_INPUT LENGTH STATUS.

  IF STATUS = NO_ERROR.
    CASE TYPE.

      WHEN '25INT'.
        W_MOD = LENGTH MOD 2.
        IF W_MOD = 1.
          SHIFT W_INPUT BY SY-FDPOS PLACES.
          IF W_INPUT = SPACE.
            CONCATENATE INVALID_LENGTH_S 'even length'
                        W_INPUT INTO OUTPUT.
            STATUS = INVALID_LENGTH.
          ELSE.
            CONCATENATE ILLEGAL_CHAR_S W_INPUT INTO OUTPUT.
            STATUS = ILLEGAL_CHAR.
          ENDIF.
        ENDIF.

      WHEN '25INT_X'.
        W_MOD = LENGTH MOD 2.
        IF W_MOD = 0.
          SHIFT W_INPUT BY SY-FDPOS PLACES.
          IF W_INPUT = SPACE.
            CONCATENATE INVALID_LENGTH_S 'odd length' W_INPUT INTO
                        OUTPUT.
            STATUS = INVALID_LENGTH.
          ELSE.
            CONCATENATE ILLEGAL_CHAR_S W_INPUT INTO OUTPUT.
            STATUS = ILLEGAL_CHAR.
          ENDIF.
        ENDIF.
        IF STATUS = NO_ERROR.
          PERFORM MODULE_10W3 USING W_INPUT LENGTH.
        ENDIF.

      WHEN 'GPAG'.
        IF LENGTH = 11 OR LENGTH = 13.
          PERFORM MODULE_10W49 USING W_INPUT LENGTH.
        ELSE.
          CONCATENATE INVALID_LENGTH_S '11 OR 13' W_INPUT INTO OUTPUT.
          STATUS = INVALID_LENGTH.
        ENDIF.

    ENDCASE.

  ELSE.
    CONCATENATE ILLEGAL_CHAR_S 'Alphabet is not allowed' W_INPUT
                INTO OUTPUT.
  ENDIF.

  IF STATUS = NO_ERROR.
    IF TYPE = '25INT_X' OR TYPE = 'GPAG'.
      W_DIGIT = W_MOD.
      CONCATENATE W_INPUT2 W_DIGIT INTO W_INPUT2.
    ENDIF.
    PERFORM INTERLEAVED USING W_INPUT2 OUTPUT.
    CONCATENATE '!' OUTPUT '"' INTO OUTPUT.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM ROUTINE_25IND                                            *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM ROUTINE_25IND USING TYPE INPUT OUTPUT STATUS.

  DATA :
    LENGTH TYPE I.

  W_INPUT = INPUT.
* -- numeric check
  LENGTH = STRLEN( W_INPUT ).
  PERFORM ISDIGIT USING W_INPUT LENGTH STATUS.

  IF STATUS = NO_ERROR.

    IF TYPE = '25IND_X' OR
         TYPE = '25IND_X_S' OR TYPE = '25IND_X_N' OR
         TYPE = '25IND_X_H' OR TYPE = '25IND_X_F' OR
       TYPE = '25MAT_X' OR
         TYPE = '25MAT_X_S' OR TYPE = '25MAT_X_N' OR
         TYPE = '25MAT_X_H' OR TYPE = '25MAT_X_F'.
*     -- Calculate checksum
      W_INPUT2 = INPUT.
      PERFORM MODULE_10W3 USING W_INPUT LENGTH.
      W_DIGIT = W_MOD.
      CONCATENATE W_INPUT2 W_DIGIT INTO OUTPUT.
    ELSE.
      OUTPUT = INPUT.
    ENDIF.

    IF STATUS = NO_ERROR.
      CASE TYPE.
        WHEN '25IND'   OR '25IND_X'   OR '25MAT'   OR '25MAT_X'   OR
             '25IND_S' OR '25IND_X_S' OR '25MAT_S' OR '25MAT_X_S'.
          CONCATENATE 'A' OUTPUT 'B' INTO OUTPUT.
        WHEN '25IND_N' OR '25IND_X_N' OR '25MAT_N' OR '25MAT_X_N'.
          CONCATENATE 'C' OUTPUT 'D' INTO OUTPUT.
        WHEN '25IND_H' OR '25IND_X_H' OR '25MAT_H' OR '25MAT_X_H'.
          CONCATENATE 'E' OUTPUT 'F' INTO OUTPUT.
        WHEN '25IND_F' OR '25IND_X_F' OR '25MAT_F' OR '25MAT_X_F'.
          CONCATENATE 'G' OUTPUT 'H' INTO OUTPUT.
      ENDCASE.
    ENDIF.
  ELSE.
    CONCATENATE ILLEGAL_CHAR_S 'Alphabet is not allowed' W_INPUT
                INTO OUTPUT.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM INTERLEAVED                                              *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  INDATA                                                        *
*  -->  OUTDATA                                                       *
*---------------------------------------------------------------------*
FORM INTERLEAVED USING INDATA OUTDATA.

  DATA :
    COUNTER TYPE I,
    COUNTER1 TYPE I,
    OUTPUT_COUNTER TYPE I,
    LENGTH  TYPE I,
    W_INDATA(MAX_LEN) TYPE C,
    W_TOTAL TYPE I,
    W_DATA1 TYPE I,
    W_DATA2 TYPE I.
  CONSTANTS:
    W_CD100(100) TYPE X VALUE
 '232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445
464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F60616263646566676869
6A6B6C6D6E6F707172737475767778797A7B7C7D7E7FC0C1C2C3C4C5C6'.

  FIELD-SYMBOLS : <FS>.
  CLEAR:COUNTER, OUTPUT_COUNTER.

  W_INDATA = INDATA.
  LENGTH = STRLEN( W_INDATA ) / 2.

  DO LENGTH TIMES.
    W_DATA1 = W_INDATA+COUNTER(01).
    COUNTER1 = COUNTER + 1.
    W_DATA2 = W_INDATA+COUNTER1(01).
    W_TOTAL = 10 * W_DATA1 + W_DATA2.
    ASSIGN OUTDATA+OUTPUT_COUNTER(01) TO <FS> TYPE 'X'.
    MOVE W_CD100+W_TOTAL(01) TO <FS>.
    OUTPUT_COUNTER = OUTPUT_COUNTER + 1.
    COUNTER = COUNTER + 2.
  ENDDO.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM ROUTINE_CODA                                             *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM ROUTINE_CODA USING TYPE INPUT OUTPUT STATUS.

  CONSTANTS:
    W_CODA(20)          VALUE '0123456789-$:/.+ABCD',
    CHANGE_H(08) TYPE C VALUE 'AFBGCHDI',
    CHANGE_F(08) TYPE C VALUE 'AJBKCLDM'.

  DATA :
    LENGTH TYPE I,
    POS TYPE I,
    LAST_CHAR(01) TYPE C.

  W_INPUT = INPUT.
  CLEAR:W_TOTAL1.

* -- check data and calculate check digit
  LENGTH = STRLEN( W_INPUT ).
  DO LENGTH TIMES.
    IF W_CODA CA  W_INPUT+0(1).
    ENDIF.
    IF SY-INDEX = 1 OR SY-INDEX = LENGTH.
      IF SY-FDPOS BETWEEN 16 AND 19.
        IF TYPE = 'CODA_AIM_N' OR TYPE = 'CODA_AIM_H' OR
           TYPE = 'CODA_AIM_F' OR TYPE = 'CODA_AIM'.
          W_TOTAL1 = W_TOTAL1 + SY-FDPOS.
        ENDIF.
        SHIFT W_INPUT.
      ELSE.
        CONCATENATE ILLEGAL_CHAR_S W_INPUT+0(1)
        ' Start/Stop char only allows A, B, C or D ' INTO OUTPUT.
        STATUS = ILLEGAL_CHAR.
        EXIT.
      ENDIF.
    ELSE.
      IF SY-FDPOS < 16.
        IF TYPE = 'CODA_AIM_N' OR TYPE = 'CODA_AIM_H' OR
           TYPE = 'CODA_AIM_F' OR TYPE = 'CODA_AIM'.
          W_TOTAL1 = W_TOTAL1 + SY-FDPOS.
        ENDIF.
        SHIFT W_INPUT.
      ELSE.
        CONCATENATE ILLEGAL_CHAR_S W_INPUT+0(1) ' It only allows '
              W_CODA INTO OUTPUT.
        STATUS = ILLEGAL_CHAR.
        EXIT.
      ENDIF.
    ENDIF.
  ENDDO.

  IF STATUS = NO_ERROR.
    IF TYPE = 'CODA_AIM' OR TYPE = 'CODA_AIM_N' OR
       TYPE = 'CODA_AIM_H' OR TYPE = 'CODA_AIM_F'.
      W_MOD = 16 - ( W_TOTAL1 MOD 16 ).
      IF W_MOD = 16.
        W_MOD = 0.
      ENDIF.
      W_DIGIT = W_CODA+W_MOD(1).
    ENDIF.
    W_INPUT = INPUT.
    POS = LENGTH - 1.
    LAST_CHAR = W_INPUT+POS(01).
    CASE TYPE.
      WHEN 'CODA' OR 'CODA_N'.
        OUTPUT = INPUT.
      WHEN 'CODA_H'.
        OUTPUT = INPUT.
        TRANSLATE OUTPUT USING CHANGE_H.
      WHEN 'CODA_F'.
        OUTPUT = INPUT.
        TRANSLATE OUTPUT USING CHANGE_F.
      WHEN 'CODA_AIM' OR 'CODA_AIM_N'.
        W_INPUT+POS(01) = W_DIGIT.
        CONCATENATE W_INPUT LAST_CHAR INTO OUTPUT.
      WHEN 'CODA_AIM_H'.
        W_INPUT+POS(01) = W_DIGIT.
        CONCATENATE W_INPUT LAST_CHAR INTO OUTPUT.
        TRANSLATE OUTPUT USING CHANGE_H.
      WHEN 'CODA_AIM_F'.
        W_INPUT+POS(01) = W_DIGIT.
        CONCATENATE W_INPUT LAST_CHAR INTO OUTPUT.
        TRANSLATE OUTPUT USING CHANGE_F.
    ENDCASE.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM ROUTINE_EAN13                                            *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM ROUTINE_EAN13 USING TYPE INPUT OUTPUT STATUS.

  DATA :
    W_CONV(40)    TYPE C,
    LENGTH        TYPE I,
    W_INDATA(40)  TYPE C,
    W_COUNTRY(01) TYPE C.

  CONSTANTS :
    POOLD_DUMMY(01) TYPE X VALUE 'CA'.

  W_INPUT = W_INDATA = INPUT.
  CLEAR:W_SUPP.
  LENGTH = STRLEN( W_INPUT ).
  PERFORM ISDIGIT USING W_INPUT LENGTH STATUS.

  IF STATUS = NO_ERROR.
    CASE TYPE.

      WHEN 'EAN13' OR 'EAN13BM'.
        IF LENGTH = 12.
          W_INPUT = W_INPUT2 = INPUT.
          PERFORM MODULE_10W3 USING W_INPUT LENGTH.
        ELSE.
          CONCATENATE INVALID_LENGTH_S '12 ' W_INPUT INTO OUTPUT.
          STATUS = INVALID_LENGTH.
        ENDIF.

      WHEN 'EAN132' OR 'EAN132BM'.
        IF LENGTH = 14.
          W_SUPP = W_INDATA+12(02).
          W_INPUT = W_INDATA+0(12).
          W_INPUT2 = W_INDATA+0(12).
          PERFORM MODULE_10W3 USING W_INPUT 12.
          PERFORM ADD2_CONVERT USING W_SUPP.
        ELSE.
          CONCATENATE INVALID_LENGTH_S '14 ' INPUT INTO OUTPUT.
          STATUS = INVALID_LENGTH.
        ENDIF.

      WHEN 'EAN135' OR 'EAN135BM'.
        IF LENGTH = 17.
          W_SUPP = W_INDATA+12(05).
          W_INPUT = W_INDATA+0(12).
          W_INPUT2 = W_INDATA+0(12).
          PERFORM MODULE_10W3 USING W_INPUT 12.
          PERFORM ADD5_CONVERT USING W_SUPP.
        ELSE.
          CONCATENATE INVALID_LENGTH_S '17 ' INPUT INTO OUTPUT.
          STATUS = INVALID_LENGTH.
        ENDIF.

    ENDCASE.
  ELSE.
    CONCATENATE ILLEGAL_CHAR_S 'Alphabet is not allowed' INPUT
                INTO OUTPUT.
  ENDIF.

  IF STATUS = NO_ERROR.
    W_DIGIT = W_MOD.
    CONCATENATE '(' W_INPUT2+1(06) '-' W_INPUT2+7(05) W_DIGIT
      '(' INTO W_CONV.
    PERFORM EAN13_CONVERT USING W_CONV W_INPUT2+0(01).
    IF TYPE = 'EAN13' OR TYPE = 'EAN132' OR TYPE = 'EAN135'.
      PERFORM COUNTRY_CONVERT USING W_INPUT2+0(01) W_COUNTRY.
      CONCATENATE W_COUNTRY W_CONV INTO W_CONV.
    ENDIF.
*   -- width adjustment POOLD_DUMMY
    IF TYPE = 'EAN132' OR TYPE = 'EAN135'.
      CONCATENATE W_CONV POOLD_DUMMY W_SUPP INTO W_CONV.
    ELSE.
      CONCATENATE W_CONV W_SUPP INTO W_CONV.
    ENDIF.
    OUTPUT = W_CONV.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM ROUTINE_POSTNET                                          *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM ROUTINE_POSTNET USING TYPE INPUT OUTPUT STATUS.

  DATA :
    LENGTH TYPE I.

  W_INPUT = INPUT.
  LENGTH = STRLEN( W_INPUT ).
* -- numeric check
  PERFORM ISDIGIT USING INPUT LENGTH STATUS.
  IF STATUS = NO_ERROR.
    CASE TYPE.

      WHEN 'POSTNET5'.
        IF LENGTH = 5.
          PERFORM POSTNET_CD USING INPUT LENGTH.
        ELSE.
          CONCATENATE INVALID_LENGTH_S '5 ' W_INPUT INTO OUTPUT.
          STATUS = INVALID_LENGTH.
        ENDIF.

      WHEN 'POSTNET9'.
        IF LENGTH = 9.
          PERFORM POSTNET_CD USING INPUT LENGTH.
        ELSE.
          CONCATENATE INVALID_LENGTH_S '9 ' W_INPUT INTO OUTPUT.
          STATUS = INVALID_LENGTH.
        ENDIF.

      WHEN 'POSTNET11'.
        IF LENGTH = 11.
          PERFORM POSTNET_CD USING INPUT LENGTH.
        ELSE.
          CONCATENATE INVALID_LENGTH_S '11 ' W_INPUT INTO OUTPUT.
          STATUS = INVALID_LENGTH.
        ENDIF.

    ENDCASE.

    IF STATUS = NO_ERROR.
      W_DIGIT = W_MOD.
      CONCATENATE '*' INPUT W_DIGIT '*' INTO OUTPUT.
    ENDIF.

  ELSE.
    CONCATENATE ILLEGAL_CHAR_S 'Alphabet is not allowed' INPUT
                INTO OUTPUT.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM COUNTRY_CONVERT                                          *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  COUNTRY                                                       *
*  -->  DIGIT                                                         *
*---------------------------------------------------------------------*
FORM COUNTRY_CONVERT USING COUNTRY DIGIT.

  DATA:
    COUNTRY_CHAR(01) TYPE C.

  COUNTRY_CHAR = COUNTRY.
  TRANSLATE COUNTRY_CHAR USING POOLD_CONV.
  DIGIT = COUNTRY_CHAR.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM UPCA_CONVERT                                             *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  W_INPUT                                                       *
*  -->  W_DIGIT                                                       *
*  -->  W_SUPP                                                        *
*  -->  OUTPUT                                                        *
*---------------------------------------------------------------------*
FORM UPCA_CONVERT USING W_INPUT W_DIGIT W_SUPP OUTPUT.

  DATA:
    START_CHAR(01)  TYPE C,
    SECOND_CHAR(01) TYPE C,
    RIGHT_SIDE(05)  TYPE C,
    LAST_CHAR(01)   TYPE C,
    DIGIT_CHAR(01)  TYPE C,
    W_INPUT3(MAX_LEN).

  CONSTANTS:
    DATA_CONV(20) TYPE C VALUE '0A1B2C3D4E5F6G7H8I9J',
    POOLA1_CONV(20) TYPE X VALUE
      '30D031D132D233D334D435D536D637D738D839D9',
    POOLC1_CONV(20) TYPE X VALUE
      '30E031E132E233E334E435E536E637E738E839E9'.

  W_INPUT3   = W_INPUT.
  START_CHAR = W_INPUT+0(01).
  TRANSLATE START_CHAR USING POOLD_CONV.
  SECOND_CHAR = W_INPUT+0(01).
  TRANSLATE SECOND_CHAR USING POOLA1_CONV.
  DIGIT_CHAR = W_DIGIT.
  TRANSLATE DIGIT_CHAR USING POOLD_CONV.
  RIGHT_SIDE = W_INPUT+6(05).
  TRANSLATE RIGHT_SIDE USING DATA_CONV.
  LAST_CHAR = W_DIGIT.
  TRANSLATE LAST_CHAR USING POOLC1_CONV.

  CONCATENATE START_CHAR '(' SECOND_CHAR W_INPUT3+1(05) '-'
    RIGHT_SIDE LAST_CHAR '(' DIGIT_CHAR W_SUPP INTO OUTPUT.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM UPCE_CONVERT                                             *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  W_INPUT2                                                      *
*  -->  W_DIGIT                                                       *
*  -->  W_SUPP                                                        *
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM UPCE_CONVERT USING W_INPUT2 W_DIGIT W_SUPP OUTPUT STATUS.

  DATA:
    W_INDATA(32)   TYPE C,
    START_CHAR(01) TYPE C,
    DIGIT_CHAR(01) TYPE C.

  W_INDATA = W_INPUT2.
  START_CHAR = W_INDATA+0(01).
  TRANSLATE START_CHAR USING POOLD_CONV.
  DIGIT_CHAR = W_DIGIT.
  TRANSLATE DIGIT_CHAR USING POOLD_CONV.

  IF W_INDATA+0(01) = '0'.
    PERFORM CODING_E0 USING W_INDATA+1(06) W_DIGIT.
  ELSE.
    IF W_INDATA+0(01) = '1'.
      PERFORM CODING_E1 USING W_INDATA+1(06) W_DIGIT.
    ELSE.
      CONCATENATE UNEXPECTED_CHAR_S1 W_INDATA+0(01) UNEXPECTED_CHAR_S2
        ' 1' INTO OUTPUT.
      STATUS = UNEXPECTED_CHAR.
    ENDIF.
  ENDIF.

  IF STATUS = NO_ERROR.
    CONCATENATE START_CHAR '(' W_INDATA+1(06) ')' DIGIT_CHAR  W_SUPP
       INTO OUTPUT.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM ADD2_CONVERT                                             *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  ADDITION                                                      *
*---------------------------------------------------------------------*
FORM ADD2_CONVERT USING ADDITION.

  DATA:
    COUNTER(02)    TYPE N,
    REMAIN(01)     TYPE N,
    W_ADDITION(02) TYPE C.

  CONSTANTS:
    POOLE_CONV(20) TYPE C VALUE '0M1N2O3P4Q5R6S7T8U9V',
    POOLF_CONV(20) TYPE C VALUE '0m1n2o3p4q5r6s7t8u9v'.

  W_ADDITION = ADDITION.
  COUNTER = ADDITION.
  REMAIN = COUNTER MOD 4.

  CASE REMAIN.
    WHEN 0.
      TRANSLATE W_ADDITION       USING POOLE_CONV.
    WHEN 1.
      TRANSLATE W_ADDITION+0(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+1(01) USING POOLF_CONV.
    WHEN 2.
      TRANSLATE W_ADDITION+0(01) USING POOLF_CONV.
      TRANSLATE W_ADDITION+1(01) USING POOLE_CONV.
    WHEN 3.
      TRANSLATE W_ADDITION       USING POOLF_CONV.
  ENDCASE.

  CONCATENATE ' #' W_ADDITION+0(01) '$' W_ADDITION+1(01)
              INTO  ADDITION.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM ADD5_CONVERT                                             *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  ADDITION                                                      *
*---------------------------------------------------------------------*
FORM ADD5_CONVERT USING ADDITION.

  DATA:
    COUNTER1(03)   TYPE N,
    COUNTER2(03)   TYPE N,
    REMAIN(01)     TYPE N,
    W_ADDITION(05) TYPE C.

  CONSTANTS:
    POOLE_CONV(20) TYPE C VALUE '0M1N2O3P4Q5R6S7T8U9V',
    POOLF_CONV(20) TYPE C VALUE '0m1n2o3p4q5r6s7t8u9v'.

  W_ADDITION = ADDITION.
  COUNTER1 = ADDITION+0(01).
  COUNTER1 = COUNTER1 + W_ADDITION+2(01).
  COUNTER1 = COUNTER1 + W_ADDITION+4(01).
  COUNTER1 = COUNTER1 * 3.
  COUNTER2 = ADDITION+1(01).
  COUNTER2 = COUNTER2 + W_ADDITION+3(01).
  COUNTER2 = COUNTER2 * 9.
  COUNTER1 = COUNTER1 + COUNTER2.
  REMAIN = COUNTER1 MOD 10.

  CASE REMAIN.
    WHEN 0.
      TRANSLATE W_ADDITION+0(01) USING POOLF_CONV.
      TRANSLATE W_ADDITION+1(01) USING POOLF_CONV.
      TRANSLATE W_ADDITION+2(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+3(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+4(01) USING POOLE_CONV.
    WHEN 1.
      TRANSLATE W_ADDITION+0(01) USING POOLF_CONV.
      TRANSLATE W_ADDITION+1(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+2(01) USING POOLF_CONV.
      TRANSLATE W_ADDITION+3(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+4(01) USING POOLE_CONV.
    WHEN 2.
      TRANSLATE W_ADDITION+0(01) USING POOLF_CONV.
      TRANSLATE W_ADDITION+1(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+2(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+3(01) USING POOLF_CONV.
      TRANSLATE W_ADDITION+4(01) USING POOLE_CONV.
    WHEN 3.
      TRANSLATE W_ADDITION+0(01) USING POOLF_CONV.
      TRANSLATE W_ADDITION+1(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+2(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+3(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+4(01) USING POOLF_CONV.
    WHEN 4.
      TRANSLATE W_ADDITION+0(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+1(01) USING POOLF_CONV.
      TRANSLATE W_ADDITION+2(01) USING POOLF_CONV.
      TRANSLATE W_ADDITION+3(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+4(01) USING POOLE_CONV.
    WHEN 5.
      TRANSLATE W_ADDITION+0(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+1(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+2(01) USING POOLF_CONV.
      TRANSLATE W_ADDITION+3(01) USING POOLF_CONV.
      TRANSLATE W_ADDITION+4(01) USING POOLE_CONV.
    WHEN 6.
      TRANSLATE W_ADDITION+0(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+1(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+2(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+3(01) USING POOLF_CONV.
      TRANSLATE W_ADDITION+4(01) USING POOLF_CONV.
    WHEN 7.
      TRANSLATE W_ADDITION+0(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+1(01) USING POOLF_CONV.
      TRANSLATE W_ADDITION+2(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+3(01) USING POOLF_CONV.
      TRANSLATE W_ADDITION+4(01) USING POOLE_CONV.
    WHEN 8.
      TRANSLATE W_ADDITION+0(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+1(01) USING POOLF_CONV.
      TRANSLATE W_ADDITION+2(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+3(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+4(01) USING POOLF_CONV.
    WHEN 9.
      TRANSLATE W_ADDITION+0(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+1(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+2(01) USING POOLF_CONV.
      TRANSLATE W_ADDITION+3(01) USING POOLE_CONV.
      TRANSLATE W_ADDITION+4(01) USING POOLF_CONV.
  ENDCASE.

  CONCATENATE ' #' W_ADDITION+0(01) '$' W_ADDITION+1(01) '$'
    W_ADDITION+2(01) '$' W_ADDITION+3(01) '$' W_ADDITION+4(01)
    INTO ADDITION.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM EAN13_CONVERT                                            *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*---------------------------------------------------------------------*
FORM EAN13_CONVERT USING OUTPUT TYPE.

  DATA:
    W_CONV(32) TYPE C.

  CONSTANTS:
    RIGHT_CONV(20) TYPE C VALUE '0A1B2C3D4E5F6G7H8I9J',
    LEFT_CONV(20)  TYPE C VALUE '0a1b2c3d4e5f6g7h8i9j'.

  W_CONV = OUTPUT.
* -- left side conversion
  CASE TYPE.
    WHEN 0.
    WHEN 1.
      TRANSLATE W_CONV+3(01) USING LEFT_CONV.
      TRANSLATE W_CONV+5(01) USING LEFT_CONV.
      TRANSLATE W_CONV+6(01) USING LEFT_CONV.
    WHEN 2.
      TRANSLATE W_CONV+3(01) USING LEFT_CONV.
      TRANSLATE W_CONV+4(01) USING LEFT_CONV.
      TRANSLATE W_CONV+6(01) USING LEFT_CONV.
    WHEN 3.
      TRANSLATE W_CONV+3(01) USING LEFT_CONV.
      TRANSLATE W_CONV+4(01) USING LEFT_CONV.
      TRANSLATE W_CONV+5(01) USING LEFT_CONV.
    WHEN 4.
      TRANSLATE W_CONV+2(01) USING LEFT_CONV.
      TRANSLATE W_CONV+5(01) USING LEFT_CONV.
      TRANSLATE W_CONV+6(01) USING LEFT_CONV.
    WHEN 5.
      TRANSLATE W_CONV+2(01) USING LEFT_CONV.
      TRANSLATE W_CONV+3(01) USING LEFT_CONV.
      TRANSLATE W_CONV+6(01) USING LEFT_CONV.
    WHEN 6.
      TRANSLATE W_CONV+2(01) USING LEFT_CONV.
      TRANSLATE W_CONV+3(01) USING LEFT_CONV.
      TRANSLATE W_CONV+4(01) USING LEFT_CONV.
    WHEN 7.
      TRANSLATE W_CONV+2(01) USING LEFT_CONV.
      TRANSLATE W_CONV+4(01) USING LEFT_CONV.
      TRANSLATE W_CONV+6(01) USING LEFT_CONV.
    WHEN 8.
      TRANSLATE W_CONV+2(01) USING LEFT_CONV.
      TRANSLATE W_CONV+4(01) USING LEFT_CONV.
      TRANSLATE W_CONV+5(01) USING LEFT_CONV.
    WHEN 9.
      TRANSLATE W_CONV+2(01) USING LEFT_CONV.
      TRANSLATE W_CONV+3(01) USING LEFT_CONV.
      TRANSLATE W_CONV+5(01) USING LEFT_CONV.
  ENDCASE.

* -- right side conversion.
  TRANSLATE W_CONV+8(06) USING RIGHT_CONV.

  OUTPUT = W_CONV.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM CODING_E1                                                *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  DATA                                                          *
*---------------------------------------------------------------------*
FORM CODING_E1 USING DATA TYPE.

  CONSTANTS:
    CONV(20) TYPE C VALUE '0a1b2c3d4e5f6g7h8i9j'.

  DATA:
    COUNTER LIKE SY-INDEX,
    W_INDATA(32) TYPE C.

  W_INDATA = DATA.
  CASE TYPE.
    WHEN 0.
      TRANSLATE W_INDATA+3(01) USING CONV.
      TRANSLATE W_INDATA+4(01) USING CONV.
      TRANSLATE W_INDATA+5(01) USING CONV.
    WHEN 1.
      TRANSLATE W_INDATA+2(01) USING CONV.
      TRANSLATE W_INDATA+4(01) USING CONV.
      TRANSLATE W_INDATA+5(01) USING CONV.
    WHEN 2.
      TRANSLATE W_INDATA+2(01) USING CONV.
      TRANSLATE W_INDATA+3(01) USING CONV.
      TRANSLATE W_INDATA+5(01) USING CONV.
    WHEN 3.
      TRANSLATE W_INDATA+2(01) USING CONV.
      TRANSLATE W_INDATA+3(01) USING CONV.
      TRANSLATE W_INDATA+4(01) USING CONV.
    WHEN 4.
      TRANSLATE W_INDATA+1(01) USING CONV.
      TRANSLATE W_INDATA+4(01) USING CONV.
      TRANSLATE W_INDATA+5(01) USING CONV.
    WHEN 5.
      TRANSLATE W_INDATA+1(01) USING CONV.
      TRANSLATE W_INDATA+2(01) USING CONV.
      TRANSLATE W_INDATA+5(01) USING CONV.
    WHEN 6.
      TRANSLATE W_INDATA+1(01) USING CONV.
      TRANSLATE W_INDATA+2(01) USING CONV.
      TRANSLATE W_INDATA+3(01) USING CONV.
    WHEN 7.
      TRANSLATE W_INDATA+1(01) USING CONV.
      TRANSLATE W_INDATA+3(01) USING CONV.
      TRANSLATE W_INDATA+5(01) USING CONV.
    WHEN 8.
      TRANSLATE W_INDATA+1(01) USING CONV.
      TRANSLATE W_INDATA+3(01) USING CONV.
      TRANSLATE W_INDATA+4(01) USING CONV.
    WHEN 9.
      TRANSLATE W_INDATA+1(01) USING CONV.
      TRANSLATE W_INDATA+2(01) USING CONV.
      TRANSLATE W_INDATA+4(01) USING CONV.
  ENDCASE.

  DATA = W_INDATA.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM CODING_E0                                                *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  DATA                                                          *
*---------------------------------------------------------------------*
FORM CODING_E0 USING DATA TYPE.

  CONSTANTS:
    CONV(20) TYPE C VALUE '0a1b2c3d4e5f6g7h8i9j'.

  DATA:
    W_INDATA(32) TYPE C.

  W_INDATA = DATA.
  CASE TYPE.
    WHEN 0.
      TRANSLATE W_INDATA+0(01) USING CONV.
      TRANSLATE W_INDATA+1(01) USING CONV.
      TRANSLATE W_INDATA+2(01) USING CONV.
    WHEN 1.
      TRANSLATE W_INDATA+0(01) USING CONV.
      TRANSLATE W_INDATA+1(01) USING CONV.
      TRANSLATE W_INDATA+3(01) USING CONV.
    WHEN 2.
      TRANSLATE W_INDATA+0(01) USING CONV.
      TRANSLATE W_INDATA+1(01) USING CONV.
      TRANSLATE W_INDATA+4(01) USING CONV.
    WHEN 3.
      TRANSLATE W_INDATA+0(01) USING CONV.
      TRANSLATE W_INDATA+1(01) USING CONV.
      TRANSLATE W_INDATA+5(01) USING CONV.
    WHEN 4.
      TRANSLATE W_INDATA+0(01) USING CONV.
      TRANSLATE W_INDATA+2(01) USING CONV.
      TRANSLATE W_INDATA+3(01) USING CONV.
    WHEN 5.
      TRANSLATE W_INDATA+0(01) USING CONV.
      TRANSLATE W_INDATA+3(01) USING CONV.
      TRANSLATE W_INDATA+4(01) USING CONV.
    WHEN 6.
      TRANSLATE W_INDATA+0(01) USING CONV.
      TRANSLATE W_INDATA+4(01) USING CONV.
      TRANSLATE W_INDATA+5(01) USING CONV.
    WHEN 7.
      TRANSLATE W_INDATA+0(01) USING CONV.
      TRANSLATE W_INDATA+2(01) USING CONV.
      TRANSLATE W_INDATA+4(01) USING CONV.
    WHEN 8.
      TRANSLATE W_INDATA+0(01) USING CONV.
      TRANSLATE W_INDATA+2(01) USING CONV.
      TRANSLATE W_INDATA+5(01) USING CONV.
    WHEN 9.
      TRANSLATE W_INDATA+0(01) USING CONV.
      TRANSLATE W_INDATA+3(01) USING CONV.
      TRANSLATE W_INDATA+5(01) USING CONV.
  ENDCASE.

  DATA = W_INDATA.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM MODULE_10                                                *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  INPUT                                                         *
*  -->  LENGTH                                                        *
*---------------------------------------------------------------------*
FORM MODULE_10 USING INPUT LENGTH.

  DATA:
    EVEN TYPE I.

  CLEAR: EVEN_FG.
  CLEAR: W_TOTAL1 , W_TOTAL2 , W_TEMP.

  EVEN = LENGTH MOD 2.

  DO LENGTH TIMES.
    IF W_INPUT = SPACE.
      EXIT.
    ENDIF.
    IF EVEN = 0.
      W_TOTAL2 = W_TOTAL2 + W_INPUT+0(1).
      EVEN = 1.
    ELSE.
      CONCATENATE W_TEMP W_INPUT+0(01) INTO W_TEMP.
      EVEN = 0.
    ENDIF.
    SHIFT W_INPUT.

  ENDDO.
  W_TEMP = W_TEMP * 2.

  DO MAX_LEN TIMES.
    IF W_TEMP = SPACE.
      EXIT.
    ENDIF.
    W_TOTAL1 = W_TOTAL1 + W_TEMP+0(1).
    SHIFT W_TEMP.
  ENDDO.

  W_TOTAL1 = W_TOTAL1 + W_TOTAL2.
  W_MOD = W_TOTAL1 MOD 10.
  IF W_MOD > 0.
    W_MOD = 10 - W_MOD.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM POSTNET_CD                                               *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  INPUT                                                         *
*  -->  LENGTH                                                        *
*---------------------------------------------------------------------*
FORM POSTNET_CD USING INPUT LENGTH.

  CLEAR: W_TOTAL1, W_TEMP.

  W_TEMP = INPUT.

  DO LENGTH TIMES.
    W_TOTAL1 = W_TOTAL1 + W_TEMP+0(1).
    SHIFT W_TEMP.
  ENDDO.

  W_MOD = W_TOTAL1 MOD 10.
  IF W_MOD > 0.
    W_MOD = 10 - W_MOD.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM MODULE_10W3                                              *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  W_INPUT                                                       *
*  -->  LENGTH                                                        *
*---------------------------------------------------------------------*
FORM MODULE_10W3 USING W_INPUT LENGTH.

  DATA:
    EVEN  TYPE I.
  DATA:
    W_NUM TYPE N.

  EVEN = LENGTH MOD 2.
  IF EVEN = 0.
    EVEN_FG = 'X'.
  ELSE.
    CLEAR: EVEN_FG.
  ENDIF.
  CLEAR:W_TOTAL1.

  DO LENGTH TIMES.
    IF W_INPUT = SPACE.
      EXIT.
    ENDIF.
    W_NUM = W_INPUT+0(1).
    IF EVEN_FG = ' '.
      W_TOTAL1 = W_TOTAL1 + ( W_NUM * 3 ).
      EVEN_FG = 'X'.
    ELSE.
      W_TOTAL1 = W_TOTAL1 + W_NUM.
      EVEN_FG = ' '.
    ENDIF.
    SHIFT W_INPUT.
  ENDDO.

  W_MOD = W_TOTAL1 MOD 10.
  IF W_MOD > 0.
    W_MOD = 10 - W_MOD.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM MODULE_10W49                                             *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  INPUT                                                         *
*  -->  LENGTH                                                        *
*---------------------------------------------------------------------*
FORM MODULE_10W49 USING INPUT LENGTH.

  CLEAR: EVEN_FG.
  CLEAR: W_TOTAL1.

  DO LENGTH TIMES.
    IF W_INPUT = SPACE.
      EXIT.
    ENDIF.
    IF EVEN_FG = ' '.
      W_TOTAL1 = W_TOTAL1 + ( W_INPUT+0(1) * 4 ).
      EVEN_FG = 'X'.
    ELSE.
      W_TOTAL1 = W_TOTAL1 + ( W_INPUT+0(1) * 9 ).
      EVEN_FG = ' '.
    ENDIF.
    SHIFT W_INPUT.
  ENDDO.

  W_MOD = W_TOTAL1 MOD 10.
  IF W_MOD > 0.
    W_MOD = 10 - W_MOD.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM MODULE_11                                                *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  INPUT                                                         *
*  -->  LENGTH                                                        *
*---------------------------------------------------------------------*
FORM MODULE_11 USING INPUT LENGTH.

  CLEAR: W_TOTAL1.

  W_WEIGHT = ( LENGTH MOD 7 ) + 2.

  DO LENGTH TIMES.
    IF W_INPUT = SPACE.
      EXIT.
    ELSE.
      IF W_WEIGHT = 1.
        W_WEIGHT = 7.
      ENDIF.
      W_TOTAL1 = W_TOTAL1 + ( W_INPUT+0(1) * W_WEIGHT ).
      W_WEIGHT = W_WEIGHT - 1.
      SHIFT W_INPUT.
    ENDIF.
  ENDDO.

  W_MOD = W_TOTAL1 MOD 11.
  CASE W_MOD.
    WHEN 0.
      W_MOD = 1.
    WHEN 1.
      W_MOD = 0.
    WHEN OTHERS.
      W_MOD = 11 - W_MOD.
  ENDCASE.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM ISDIGIT                                                  *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  INPUT                                                         *
*  -->  LENGTH                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM ISDIGIT USING INPUT LENGTH STATUS.

  DATA :
    COUNTER           TYPE I,
    W_INPUT3(MAX_LEN) TYPE C.

  W_INPUT3 = INPUT.
  DO LENGTH TIMES.
    IF W_INPUT3+0(01) BETWEEN '0' AND '9'.
      STATUS = NO_ERROR.
    ELSE.
      STATUS = ILLEGAL_CHAR.
      EXIT.
    ENDIF.
    SHIFT W_INPUT3.
  ENDDO.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM DIGIT_LEN_HEX                                            *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  INPUT                                                         *
*  -->  LENGTH                                                        *
*  -->  DIGITS                                                        *
*---------------------------------------------------------------------*
FORM DIGIT_LEN_HEX USING INPUT LENGTH DIGITS.

  DATA :
    COUNTER           TYPE I,
    W_INPUT3(MAX_LEN) TYPE X.

  DIGITS = LENGTH.
  COUNTER = 0.
  W_INPUT3 = INPUT.

  DO LENGTH TIMES.
    COUNTER = SY-INDEX - 1.
    IF W_INPUT3+0(01) BETWEEN '30' AND '39'.
    ELSE.
      DIGITS = COUNTER.
      EXIT.
    ENDIF.
    SHIFT W_INPUT3.
  ENDDO.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM ISDIGIT_HEX                                              *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  INPUT                                                         *
*  -->  LENGTH                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM ISDIGIT_HEX USING INPUT LENGTH STATUS.

  DATA :
    COUNTER TYPE I,
    W_INPUT3(MAX_LEN) TYPE X.
  CONSTANTS :
    0CHAR TYPE X VALUE '30',
    9CHAR TYPE X VALUE '39'.

  W_INPUT3 = INPUT.

  DO LENGTH TIMES.
    IF W_INPUT3+0(01) BETWEEN 0CHAR AND 9CHAR.
      STATUS = NO_ERROR.
    ELSE.
      STATUS = ILLEGAL_CHAR.
      EXIT.
    ENDIF.
    SHIFT W_INPUT3.
  ENDDO.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM MODULE_128A                                              *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM MODULE_128A USING TYPE INPUT OUTPUT STATUS.

  DATA:
    LENGTH             TYPE I,
    EVEN               TYPE I,
    COUNTER            TYPE I,
    WORK_AREA(MAX_LEN) TYPE X.

  CLEAR : W_TOTAL1.
* -- initialize working area
  DO MAX_LEN TIMES.
    COUNTER = SY-INDEX - 1.
    W_256X+COUNTER(01) = SPACE_CHAR.
  ENDDO.

  WORK_AREA = INPUT.

* -- EBCDIC->ASCII conversion if necessary; added 040616/dk;
  IF FLG_SYS_EBCDIC = 'X'.
    PERFORM CVT_EBC2ASC USING WORK_AREA.
  ENDIF.

  CASE TYPE.

    WHEN 'CD128A'.
      CONCATENATE START_CHAR_A WORK_AREA INTO W_256X.

    WHEN 'CD128B'.
      CONCATENATE START_CHAR_B WORK_AREA INTO W_256X.

    WHEN 'CD128C'.
      LENGTH = STRLEN( WORK_AREA ).
      EVEN = LENGTH MOD 2.
      IF EVEN = 0.
        PERFORM ISDIGIT_HEX USING WORK_AREA LENGTH STATUS.
        IF STATUS = NO_ERROR.
          PERFORM CONVERT_CD128C USING WORK_AREA LENGTH W_256X.
          CONCATENATE START_CHAR_C W_256X INTO W_256X.
        ELSE.
          CONCATENATE ILLEGAL_CHAR_S 'Alphabet is not allowed' INPUT
                      INTO OUTPUT.
        ENDIF.
      ELSE.
        STATUS = INVALID_LENGTH.
        CONCATENATE INVALID_LENGTH_S ' even' INPUT INTO OUTPUT.
      ENDIF.

    WHEN 'UPC128'.
      LENGTH = STRLEN( WORK_AREA ).
      IF LENGTH = 19.
        PERFORM ISDIGIT_HEX USING WORK_AREA LENGTH STATUS.
        IF STATUS = NO_ERROR.
          W_INPUT = WORK-TEXT.
          PERFORM MODULE_10W3 USING W_INPUT LENGTH.
          W_DIGIT = W_MOD.
          CONCATENATE WORK_AREA W_DIGIT INTO WORK_AREA.
          PERFORM CONVERT_CD128C USING WORK_AREA 20 W_256X.
          CONCATENATE START_CHAR_C FNC1_CHAR W_256X INTO W_256X.
        ELSE.
          CONCATENATE ILLEGAL_CHAR_S 'Alphabet is not allowed' W_INPUT
                      INTO OUTPUT.
        ENDIF.
      ELSE.
        STATUS = INVALID_LENGTH.
        CONCATENATE INVALID_LENGTH_S '19:' W_INPUT INTO OUTPUT.
      ENDIF.

  ENDCASE.

  IF STATUS = NO_ERROR.
    WORK_AREA = W_256X.
    PERFORM MODULE_103 USING TYPE W_DIGITX STATUS.
    IF STATUS = NO_ERROR.
      IF W_DIGITX = '20'.
        CONCATENATE WORK_AREA SPACE_END_CHAR INTO OUTPUT.
      ELSE.
        CONCATENATE WORK_AREA W_DIGITX END_CHAR INTO OUTPUT.
      ENDIF.

*     -- ASCII->EBCDIC conversion if necessary; added 040616/dk;
      IF FLG_SYS_EBCDIC = 'X'.
        PERFORM CVT_ASC2EBC USING OUTPUT.
      ENDIF.

    ELSE.
      CONCATENATE ILLEGAL_CHAR_S 'Illegal character is included '
                  INPUT INTO OUTPUT.
    ENDIF.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM MODULE_128                                               *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM MODULE_128 USING TYPE INPUT OUTPUT STATUS.

  DATA:
    LENGTH              TYPE I,
    REMAIN_LEN          TYPE I,
    IDX                 TYPE I,
    FWD_POS             TYPE I,
    COUNTER             TYPE I,
    OUTPUT_POS          TYPE I,
    DIGITS              TYPE I,
    RC(01)              TYPE C,
    WORK_MODEC(01)      TYPE X,
    MODE(01)            TYPE X,
    WORK_AREA(MAX_LEN)  TYPE X,
    WORK_AREA2(MAX_LEN) TYPE X.

  CLEAR : W_TOTAL1.

* -- initialize working area
  DO MAX_LEN TIMES.
    COUNTER = SY-INDEX - 1.
    W_256X+COUNTER(01) = SPACE_CHAR.
  ENDDO.

  WORK_AREA = INPUT.

* -- EBCDIC->ASCII conversion if necessary; added 040616/dk;
  IF FLG_SYS_EBCDIC = 'X'.
    PERFORM CVT_EBC2ASC USING WORK_AREA.
  ENDIF.

* -- length check
  LENGTH = STRLEN( WORK_AREA ).
  IF LENGTH < 2.
    CONCATENATE INVALID_LENGTH_S 'greater than 2' INTO OUTPUT.
    STATUS = INVALID_LENGTH.
    EXIT.
  ENDIF.

* -- determine start mode
* -- check the first 2 bytes for mode C
  PERFORM ISDIGIT_HEX USING WORK_AREA 2 RC.
  IF RC = NO_ERROR.
    W_256X+0(01) = START_CHAR_C.
    MODE = MODE_C_CHAR.
  ELSE.
*   -- check the first 1 byte for mode A and B
    IF WORK_AREA+0(01) > X1F.
      W_256X+0(01) = START_CHAR_B.
      MODE = MODE_B_CHAR.
    ELSE.
      W_256X+0(01) = START_CHAR_A.
      MODE = MODE_A_CHAR.
    ENDIF.
  ENDIF.

* -- EAN128 needs FNC1 char after start char
  IF TYPE = 'EAN128'.
    W_256X+1(01) = FNC1_CHAR.
    OUTPUT_POS = 2.
  ELSE.
    OUTPUT_POS = 1.
  ENDIF.

* -- making output data.
  COUNTER = 0.
  DO LENGTH TIMES.

    WORK_AREA2 = WORK_AREA+COUNTER.
    IF MODE = MODE_C_CHAR.
      PERFORM CONVERT_CD128C USING WORK_AREA2(02) 2
                              W_256X+OUTPUT_POS(01).
      COUNTER = COUNTER + 2.
    ELSE.
      W_256X+OUTPUT_POS(01) = WORK_AREA2(01).
      COUNTER = COUNTER + 1.
    ENDIF.
    IF COUNTER >= LENGTH.
      EXIT.
    ENDIF.
    OUTPUT_POS = OUTPUT_POS + 1.
    WORK_AREA2 = WORK_AREA+COUNTER.
    REMAIN_LEN = STRLEN( WORK_AREA2 ).
*   -- calculate remaining numeric char length
    PERFORM DIGIT_LEN_HEX USING WORK_AREA2 REMAIN_LEN DIGITS.

*   -- in mode A
    IF MODE = MODE_A_CHAR.
      IF WORK_AREA2(01) > X60 OR WORK_AREA2(01) = CODEB.
        MODE = MODE_B_CHAR.
        W_256X+OUTPUT_POS(01) = MODE_B_CHAR.
        OUTPUT_POS = OUTPUT_POS + 1.
        IF WORK_AREA2(01) = CODEB.
          COUNTER = COUNTER + 1.
        ENDIF.
      ELSE.
*       -- over 4 numeric chars remaining change to mode C
        IF DIGITS >= 4 OR WORK_AREA2(01) = CODEC.
          MODE = MODE_C_CHAR.
          W_256X+OUTPUT_POS(01) = MODE_C_CHAR.
          OUTPUT_POS = OUTPUT_POS + 1.
          IF WORK_AREA2(01) = CODEC.
            COUNTER = COUNTER + 1.
          ENDIF.
        ELSE.
*         -- case in shift code
          FWD_POS = COUNTER + 1.
          IF WORK_AREA2(01) = CODESHIFT
             OR ( WORK_AREA2(01) > X60 AND
                NOT ( REMAIN_LEN > 1 AND WORK_AREA2+1(01) > X60 )
                ).
            W_256X+OUTPUT_POS(01) = SHIFT_CHAR.
            OUTPUT_POS = OUTPUT_POS + 1.
            IF WORK_AREA2(01) = CODESHIFT.
              COUNTER = COUNTER + 1.
            ENDIF.
          ENDIF.
        ENDIF.
      ENDIF.
    ELSE.

*     -- in mode B
      IF MODE = MODE_B_CHAR.
        IF WORK_AREA2(01) < X20 OR WORK_AREA2(01) = CODEA.
          MODE = MODE_A_CHAR.
          W_256X+OUTPUT_POS(01) = MODE_A_CHAR.
          OUTPUT_POS = OUTPUT_POS + 1.
          IF WORK_AREA2(01) = CODEA.
            COUNTER = COUNTER + 1.
          ENDIF.
        ELSE.
*         -- over 4 numeric chars remaining change to mode C
          IF DIGITS >= 4 OR WORK_AREA2(01) = CODEC.
            MODE = MODE_C_CHAR.
            W_256X+OUTPUT_POS(01) = MODE_C_CHAR.
            OUTPUT_POS = OUTPUT_POS + 1.
            IF WORK_AREA2(01) = CODEC.
              COUNTER = COUNTER + 1.
            ENDIF.
          ELSE.
*           -- case in shift code
            FWD_POS = COUNTER + 1.
            IF WORK_AREA2(01) = CODESHIFT OR
             ( WORK_AREA2(01) < X20 AND NOT ( REMAIN_LEN > 1 AND
             WORK_AREA2+1(01) < X20 ) ).
              W_256X+OUTPUT_POS(01) = SHIFT_CHAR.
              OUTPUT_POS = OUTPUT_POS + 1.
              IF WORK_AREA2(01) = CODESHIFT.
                COUNTER = COUNTER + 1.
              ENDIF.
            ENDIF.
          ENDIF.
        ENDIF.
      ELSE.

*       -- in mode C
        IDX = COUNTER + 1.
        IF WORK_AREA2(01) < X20 OR
           WORK_AREA2(01) = CODEA OR
          ( DIGITS = 1 AND REMAIN_LEN > 0 AND WORK_AREA2+1(01) < X20 ).
          MODE = MODE_A_CHAR.
          W_256X+OUTPUT_POS(01) = MODE_A_CHAR.
          OUTPUT_POS = OUTPUT_POS + 1.
          IF WORK_AREA2(01) = CODEA.
            COUNTER = COUNTER + 1.
          ENDIF.
        ELSE.
          IF DIGITS < 2 OR WORK_AREA2(01) = CODEB.
            MODE = MODE_B_CHAR.
            W_256X+OUTPUT_POS(01) = MODE_B_CHAR.
            OUTPUT_POS = OUTPUT_POS + 1.
            IF WORK_AREA2(01) = CODEB.
              COUNTER = COUNTER + 1.
            ENDIF.
          ENDIF.
        ENDIF.
      ENDIF.
    ENDIF.

  ENDDO.

* -- calculate checksum.
  IF STATUS = NO_ERROR.
    WORK_AREA = W_256X.
    PERFORM MODULE_103 USING TYPE W_DIGITX STATUS.
    IF STATUS = NO_ERROR.
      IF W_DIGITX = '20'.
        CONCATENATE WORK_AREA SPACE_END_CHAR INTO OUTPUT.
      ELSE.
        CONCATENATE WORK_AREA W_DIGITX END_CHAR INTO OUTPUT.
      ENDIF.

*     -- ASCII->EBCDIC conversion if necessary; added 040616/dk;
      IF FLG_SYS_EBCDIC = 'X'.
        PERFORM CVT_ASC2EBC USING OUTPUT.
      ENDIF.

    ELSE.
      CONCATENATE ILLEGAL_CHAR_S ' ' INPUT INTO OUTPUT.
    ENDIF.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM CONVERT_CD128C                                           *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  INDATA                                                        *
*  -->  LENGTH                                                        *
*  -->  OUTDATA                                                       *
*---------------------------------------------------------------------*
FORM CONVERT_CD128C USING INDATA LENGTH OUTDATA.

  DATA :
    COUNTER            TYPE I,
    COUNTER1           TYPE I,
    OUTPUT_COUNTER     TYPE I,
    HALF_LENGTH        TYPE I,
    W_TOTAL(06)        TYPE N,
    W_DATA1(02)        TYPE C,
    W_DATA2(02)        TYPE C,
    WORK_AREA(MAX_LEN) TYPE X.

  CONSTANTS:
    W_CD100(100) TYPE X VALUE
'B02122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F4041424
34445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666
768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7FC0C1C2C3'.

  FIELD-SYMBOLS : <FS>.
  CLEAR:COUNTER, OUTPUT_COUNTER.

  HALF_LENGTH = LENGTH / 2.
  WORK_AREA = INDATA.

  DO HALF_LENGTH TIMES.
    W_DATA1 = WORK_AREA+COUNTER(01).
    COUNTER1 = COUNTER + 1.
    W_DATA2 = WORK_AREA+COUNTER1(01).
    W_TOTAL = 10 * W_DATA1+1(01) + W_DATA2+1(01).
    ASSIGN OUTDATA+OUTPUT_COUNTER(01) TO <FS> TYPE 'X'.
    MOVE W_CD100+W_TOTAL(01) TO <FS>.
    OUTPUT_COUNTER = OUTPUT_COUNTER + 1.
    COUNTER = COUNTER + 2.
  ENDDO.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM MODULE_103                                               *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM MODULE_103 USING TYPE W_DIGITX STATUS.

  DATA:
    LENGTH      TYPE I,
    COUNTER     TYPE I,
    REF_POS     TYPE I,
    W_FIRST(01) TYPE C VALUE ' ',
    MODE(01)    TYPE X.

  CONSTANTS:
    MAX_REF_LEN         TYPE I VALUE 106,
    REF_A(MAX_REF_LEN)  TYPE X VALUE
'202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F4041424
34445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F000102030405060
708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1FC0C1C2C3C4C5C6C7C8C9',
    REF_B(MAX_REF_LEN)  TYPE X VALUE
'202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F4041424
34445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666
768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7FC0C1C2C3C4C5C6C7C8C9',
    REF_C(MAX_REF_LEN)  TYPE X VALUE
'B02122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F4041424
34445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666
768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7FC0C1C2C3C4C5C6C7C8C9',
    REF_CD(MAX_REF_LEN) TYPE X VALUE
'202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F4041424
34445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666
768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7FC0C1C2C3C4C5C6C7C8C9'.

  DATA:
    W_REF_A(MAX_REF_LEN) TYPE X,
    W_REF_B(MAX_REF_LEN) TYPE X,
    W_REF_C(MAX_REF_LEN) TYPE X.

  W_WEIGHT = 1.
  CLEAR : W_TOTAL1.
  LENGTH = STRLEN( W_256X ).
  IF TYPE = 'CD128' OR TYPE = 'EAN128'.
    CASE W_256X+0(01).
      WHEN START_CHAR_A.
        MODE = MODE_A_CHAR.
      WHEN START_CHAR_B.
        MODE = MODE_B_CHAR.
      WHEN START_CHAR_C.
        MODE = MODE_C_CHAR.
    ENDCASE.
  ENDIF.

  W_REF_A = REF_A.
  W_REF_B = REF_B.
  W_REF_C = REF_C.

  DO LENGTH TIMES.
    REF_POS = MAX_REF_LEN.
    CASE TYPE.

      WHEN 'CD128' OR 'EAN128'.
        DO MAX_REF_LEN TIMES.
          COUNTER = SY-INDEX - 1.
          CASE MODE.
            WHEN MODE_A_CHAR.
              IF W_256X(01) = W_REF_A(01).
                REF_POS = COUNTER.
                IF W_256X(01) = MODE_B_CHAR OR W_256X(01) = MODE_C_CHAR.
                  MODE = W_256X(01).
                ENDIF.
                EXIT.
              ENDIF.
              SHIFT W_REF_A.
            WHEN MODE_B_CHAR.
              IF W_256X(01) = W_REF_B(01).
                REF_POS = COUNTER.
                IF W_256X(01) = MODE_A_CHAR OR W_256X(01) = MODE_C_CHAR.
                  MODE = W_256X(01).
                ENDIF.
                EXIT.
              ENDIF.
              SHIFT W_REF_B.
            WHEN MODE_C_CHAR.
              IF W_256X(01) = W_REF_C(01).
                REF_POS = COUNTER.
                IF W_256X(01) = MODE_A_CHAR OR W_256X(01) = MODE_B_CHAR.
                  MODE = W_256X(01).
                ENDIF.
                EXIT.
              ENDIF.
              SHIFT W_REF_C.
          ENDCASE.
        ENDDO.

      WHEN 'CD128A'.
        DO MAX_REF_LEN TIMES.
          COUNTER = SY-INDEX - 1.
          IF W_256X(01) = W_REF_A(01).
            REF_POS = COUNTER.
            EXIT.
          ENDIF.
          SHIFT W_REF_A.
        ENDDO.

      WHEN 'CD128B'.
        DO MAX_REF_LEN TIMES.
          COUNTER = SY-INDEX - 1.
          IF W_256X(01) = W_REF_B(01).
            REF_POS = COUNTER.
            EXIT.
          ENDIF.
          SHIFT W_REF_B.
        ENDDO.

      WHEN 'CD128C' OR 'UPC128'.
        DO MAX_REF_LEN TIMES.
          COUNTER = SY-INDEX - 1.
          IF W_256X(01) = W_REF_C(01).
            REF_POS = COUNTER.
            EXIT.
          ENDIF.
          SHIFT W_REF_C.
        ENDDO.

    ENDCASE.

    IF REF_POS < MAX_REF_LEN.
      W_TOTAL1 = W_TOTAL1 + REF_POS * W_WEIGHT.
      IF W_WEIGHT = 1 AND W_FIRST = ' '.
        W_FIRST = 'X'.
      ELSE.
        W_WEIGHT = W_WEIGHT + 1.
      ENDIF.
      SHIFT W_256X.
    ELSE.
      STATUS = ILLEGAL_CHAR.
      EXIT.
    ENDIF.

    W_REF_A = REF_A.
    W_REF_B = REF_B.
    W_REF_C = REF_C.

  ENDDO.

  IF STATUS = NO_ERROR.
    W_MOD = W_TOTAL1 MOD 103.
    W_DIGITX = REF_CD+W_MOD(01).
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM TOUPPER                                                  *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  INPUT                                                         *
*  -->  OUTPUT                                                        *
*---------------------------------------------------------------------*
FORM TOUPPER USING INPUT OUTPUT.

  DATA:
    LENGTH             TYPE I,
    SPACE_CNT          TYPE I,
    OUTLEN             TYPE I,
    LOWER_FLG          TYPE I,
    W_INDATA(MAX_LEN)  TYPE C,
    W_OUTDATA(MAX_LEN) TYPE C.

  W_INDATA = INPUT.
  LENGTH = STRLEN( W_INDATA ).
  CLEAR : W_OUTDATA.
  LOWER_FLG = SPACE_CNT = 0.

  DO LENGTH TIMES.

    IF W_INDATA+0(01) = SPACE.
      SPACE_CNT = SPACE_CNT + 1.
      SHIFT W_INDATA.
      CONTINUE.
    ENDIF.

    OUTLEN = STRLEN( W_OUTDATA ) + SPACE_CNT.

    IF W_INDATA+0(01) CP '#a'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'A' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'A'.
      ENDIF.
    ENDIF.

    IF W_INDATA+0(01) CP '#b'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'B' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'B'.
      ENDIF.
    ENDIF.

    IF W_INDATA+0(01) CP '#c'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'C' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'C'.
      ENDIF.
    ENDIF.

    IF W_INDATA+0(01) CP '#d'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'D' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'D'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#e'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'E' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'E'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#f'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'F' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'F'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#g'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'G' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'G'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#h'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'H' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'H'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#i'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'I' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'I'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#j'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'J' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'J'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#k'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'K' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'K'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#l'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'L' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'L'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#m'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'M' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'M'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#n'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'N' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'N'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#o'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'O' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'O'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#p'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'P' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'P'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#q'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'Q' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'Q'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#r'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'R' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'R'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#s'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'S' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'S'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#t'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'T' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'T'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#u'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'U' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'U'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#v'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'V' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'V'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#w'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'W' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'W'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#x'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'X' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'X'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#y'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'Y' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'Y'.
      ENDIF.
    ENDIF.
    IF W_INDATA+0(01) CP '#z'.
      LOWER_FLG = 1.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA 'Z' INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = 'Z'.
      ENDIF.
    ENDIF.

    IF LOWER_FLG = 0.
      IF SPACE_CNT = 0.
        CONCATENATE W_OUTDATA W_INDATA+0(01) INTO W_OUTDATA.
      ELSE.
        W_OUTDATA+OUTLEN(01) = W_INDATA+0(01).
      ENDIF.
    ENDIF.

    SHIFT W_INDATA.
    SPACE_CNT = LOWER_FLG = 0.

  ENDDO.

  OUTPUT = W_OUTDATA.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM CONVERT_CD39CHAR                                         *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  INPUT                                                         *
*  -->  OUTPUT                                                        *
*---------------------------------------------------------------------*
FORM CONVERT_CD39CHAR USING INPUT OUTPUT STATUS.

  CASE INPUT.
    WHEN '00'.      OUTPUT = '%U'.
    WHEN '01'.      OUTPUT = '$A'.
    WHEN '02'.      OUTPUT = '$B'.
    WHEN '03'.      OUTPUT = '$C'.
    WHEN '04'.      OUTPUT = '$D'.
    WHEN '05'.      OUTPUT = '$E'.
    WHEN '06'.      OUTPUT = '$F'.
    WHEN '07'.      OUTPUT = '$G'.
    WHEN '08'.      OUTPUT = '$H'.
    WHEN '09'.      OUTPUT = '$I'.
    WHEN '0A'.      OUTPUT = '$J'.
    WHEN '0B'.      OUTPUT = '$K'.
    WHEN '0C'.      OUTPUT = '$L'.
    WHEN '0D'.      OUTPUT = '$M'.
    WHEN '0E'.      OUTPUT = '$N'.
    WHEN '0F'.      OUTPUT = '$O'.
    WHEN '10'.      OUTPUT = '$P'.
    WHEN '11'.      OUTPUT = '$Q'.
    WHEN '12'.      OUTPUT = '$R'.
    WHEN '13'.      OUTPUT = '$S'.
    WHEN '14'.      OUTPUT = '$T'.
    WHEN '15'.      OUTPUT = '$U'.
    WHEN '16'.      OUTPUT = '$V'.
    WHEN '17'.      OUTPUT = '$W'.
    WHEN '18'.      OUTPUT = '$X'.
    WHEN '19'.      OUTPUT = '$Y'.
    WHEN '1A'.      OUTPUT = '$Z'.
    WHEN '1B'.      OUTPUT = '%A'.
    WHEN '1C'.      OUTPUT = '%B'.
    WHEN '1D'.      OUTPUT = '%C'.
    WHEN '1E'.      OUTPUT = '%D'.
    WHEN '1F'.      OUTPUT = '%E'.
    WHEN '20'.      OUTPUT = ' '.
    WHEN '21'.      OUTPUT = '/A'.
    WHEN '22'.      OUTPUT = '/B'.
    WHEN '23'.      OUTPUT = '/C'.
    WHEN '24'.      OUTPUT = '/D'.
    WHEN '25'.      OUTPUT = '/E'.
    WHEN '26'.      OUTPUT = '/F'.
    WHEN '27'.      OUTPUT = '/G'.
    WHEN '28'.      OUTPUT = '/H'.
    WHEN '29'.      OUTPUT = '/I'.
    WHEN '2A'.      OUTPUT = '/J'.
    WHEN '2B'.      OUTPUT = '/K'.
    WHEN '2C'.      OUTPUT = '/L'.
    WHEN '2D'.      OUTPUT = '/M'.
    WHEN '2E'.      OUTPUT = '/N'.
    WHEN '2F'.      OUTPUT = '/O'.
    WHEN '30'.      OUTPUT = '0'.
    WHEN '31'.      OUTPUT = '1'.
    WHEN '32'.      OUTPUT = '2'.
    WHEN '33'.      OUTPUT = '3'.
    WHEN '34'.      OUTPUT = '4'.
    WHEN '35'.      OUTPUT = '5'.
    WHEN '36'.      OUTPUT = '6'.
    WHEN '37'.      OUTPUT = '7'.
    WHEN '38'.      OUTPUT = '8'.
    WHEN '39'.      OUTPUT = '9'.
    WHEN '3A'.      OUTPUT = '/Z'.
    WHEN '3B'.      OUTPUT = '%F'.
    WHEN '3C'.      OUTPUT = '%G'.
    WHEN '3D'.      OUTPUT = '%H'.
    WHEN '3E'.      OUTPUT = '%I'.
    WHEN '3F'.      OUTPUT = '%J'.
    WHEN '40'.      OUTPUT = '%V'.
    WHEN '41'.      OUTPUT = 'A'.
    WHEN '42'.      OUTPUT = 'B'.
    WHEN '43'.      OUTPUT = 'C'.
    WHEN '44'.      OUTPUT = 'D'.
    WHEN '45'.      OUTPUT = 'E'.
    WHEN '46'.      OUTPUT = 'F'.
    WHEN '47'.      OUTPUT = 'G'.
    WHEN '48'.      OUTPUT = 'H'.
    WHEN '49'.      OUTPUT = 'I'.
    WHEN '4A'.      OUTPUT = 'J'.
    WHEN '4B'.      OUTPUT = 'K'.
    WHEN '4C'.      OUTPUT = 'L'.
    WHEN '4D'.      OUTPUT = 'M'.
    WHEN '4E'.      OUTPUT = 'N'.
    WHEN '4F'.      OUTPUT = 'O'.
    WHEN '50'.      OUTPUT = 'P'.
    WHEN '51'.      OUTPUT = 'Q'.
    WHEN '52'.      OUTPUT = 'R'.
    WHEN '53'.      OUTPUT = 'S'.
    WHEN '54'.      OUTPUT = 'T'.
    WHEN '55'.      OUTPUT = 'U'.
    WHEN '56'.      OUTPUT = 'V'.
    WHEN '57'.      OUTPUT = 'W'.
    WHEN '58'.      OUTPUT = 'X'.
    WHEN '59'.      OUTPUT = 'Y'.
    WHEN '5A'.      OUTPUT = 'Z'.
    WHEN '5B'.      OUTPUT = '%K'.
    WHEN '5C'.      OUTPUT = '%L'.
    WHEN '5D'.      OUTPUT = '%M'.
    WHEN '5E'.      OUTPUT = '%N'.
    WHEN '5F'.      OUTPUT = '%O'.
    WHEN '60'.      OUTPUT = '%W'.
    WHEN '61'.      OUTPUT = '+A'.
    WHEN '62'.      OUTPUT = '+B'.
    WHEN '63'.      OUTPUT = '+C'.
    WHEN '64'.      OUTPUT = '+D'.
    WHEN '65'.      OUTPUT = '+E'.
    WHEN '66'.      OUTPUT = '+F'.
    WHEN '67'.      OUTPUT = '+G'.
    WHEN '68'.      OUTPUT = '+H'.
    WHEN '69'.      OUTPUT = '+I'.
    WHEN '6A'.      OUTPUT = '+J'.
    WHEN '6B'.      OUTPUT = '+K'.
    WHEN '6C'.      OUTPUT = '+L'.
    WHEN '6D'.      OUTPUT = '+M'.
    WHEN '6E'.      OUTPUT = '+N'.
    WHEN '6F'.      OUTPUT = '+O'.
    WHEN '70'.      OUTPUT = '+P'.
    WHEN '71'.      OUTPUT = '+Q'.
    WHEN '72'.      OUTPUT = '+R'.
    WHEN '73'.      OUTPUT = '+S'.
    WHEN '74'.      OUTPUT = '+T'.
    WHEN '75'.      OUTPUT = '+U'.
    WHEN '76'.      OUTPUT = '+V'.
    WHEN '77'.      OUTPUT = '+W'.
    WHEN '78'.      OUTPUT = '+X'.
    WHEN '79'.      OUTPUT = '+Y'.
    WHEN '7A'.      OUTPUT = '+Z'.
    WHEN '7B'.      OUTPUT = '%P'.
    WHEN '7C'.      OUTPUT = '%Q'.
    WHEN '7D'.      OUTPUT = '%R'.
    WHEN '7E'.      OUTPUT = '%S'.
    WHEN '7F'.      OUTPUT = '%T'.
    WHEN OTHERS.    STATUS = ILLEGAL_CHAR.
  ENDCASE.
ENDFORM.

*---------------------------------------------------------------------*
*       FORM CONVERT_CD93CHAR                                         *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  INPUT                                                         *
*  -->  OUTPUT                                                        *
*  -->  STATUS                                                        *
*---------------------------------------------------------------------*
FORM CONVERT_CD93CHAR USING INPUT OUTPUT STATUS.

  CASE INPUT.
    WHEN '00'.      OUTPUT = 'bU'.
    WHEN '01'.      OUTPUT = 'aA'.
    WHEN '02'.      OUTPUT = 'aB'.
    WHEN '03'.      OUTPUT = 'aC'.
    WHEN '04'.      OUTPUT = 'aD'.
    WHEN '05'.      OUTPUT = 'aE'.
    WHEN '06'.      OUTPUT = 'aF'.
    WHEN '07'.      OUTPUT = 'aG'.
    WHEN '08'.      OUTPUT = 'aH'.
    WHEN '09'.      OUTPUT = 'aI'.
    WHEN '0A'.      OUTPUT = 'aJ'.
    WHEN '0B'.      OUTPUT = 'aK'.
    WHEN '0C'.      OUTPUT = 'aL'.
    WHEN '0D'.      OUTPUT = 'aM'.
    WHEN '0E'.      OUTPUT = 'aN'.
    WHEN '0F'.      OUTPUT = 'aO'.
    WHEN '10'.      OUTPUT = 'aP'.
    WHEN '11'.      OUTPUT = 'aQ'.
    WHEN '12'.      OUTPUT = 'aR'.
    WHEN '13'.      OUTPUT = 'aS'.
    WHEN '14'.      OUTPUT = 'aT'.
    WHEN '15'.      OUTPUT = 'aU'.
    WHEN '16'.      OUTPUT = 'aV'.
    WHEN '17'.      OUTPUT = 'aW'.
    WHEN '18'.      OUTPUT = 'aX'.
    WHEN '19'.      OUTPUT = 'aY'.
    WHEN '1A'.      OUTPUT = 'aZ'.
    WHEN '1B'.      OUTPUT = 'bA'.
    WHEN '1C'.      OUTPUT = 'bB'.
    WHEN '1D'.      OUTPUT = 'bC'.
    WHEN '1E'.      OUTPUT = 'bD'.
    WHEN '1F'.      OUTPUT = 'bE'.
    WHEN '20'.      OUTPUT = ' '.
    WHEN '21'.      OUTPUT = 'cA'.
    WHEN '22'.      OUTPUT = 'cB'.
    WHEN '23'.      OUTPUT = 'cC'.
    WHEN '24'.      OUTPUT = 'cD'.
    WHEN '25'.      OUTPUT = 'cE'.
    WHEN '26'.      OUTPUT = 'cF'.
    WHEN '27'.      OUTPUT = 'cG'.
    WHEN '28'.      OUTPUT = 'cH'.
    WHEN '29'.      OUTPUT = 'cI'.
    WHEN '2A'.      OUTPUT = 'cJ'.
    WHEN '2B'.      OUTPUT = 'cK'.
    WHEN '2C'.      OUTPUT = 'cL'.
    WHEN '2D'.      OUTPUT = 'cM'.
    WHEN '2E'.      OUTPUT = 'cN'.
    WHEN '2F'.      OUTPUT = 'cO'.
    WHEN '30'.      OUTPUT = '0'.
    WHEN '31'.      OUTPUT = '1'.
    WHEN '32'.      OUTPUT = '2'.
    WHEN '33'.      OUTPUT = '3'.
    WHEN '34'.      OUTPUT = '4'.
    WHEN '35'.      OUTPUT = '5'.
    WHEN '36'.      OUTPUT = '6'.
    WHEN '37'.      OUTPUT = '7'.
    WHEN '38'.      OUTPUT = '8'.
    WHEN '39'.      OUTPUT = '9'.
    WHEN '3A'.      OUTPUT = 'cZ'.
    WHEN '3B'.      OUTPUT = 'bF'.
    WHEN '3C'.      OUTPUT = 'bG'.
    WHEN '3D'.      OUTPUT = 'bH'.
    WHEN '3E'.      OUTPUT = 'bI'.
    WHEN '3F'.      OUTPUT = 'bJ'.
    WHEN '40'.      OUTPUT = 'bV'.
    WHEN '41'.      OUTPUT = 'A'.
    WHEN '42'.      OUTPUT = 'B'.
    WHEN '43'.      OUTPUT = 'C'.
    WHEN '44'.      OUTPUT = 'D'.
    WHEN '45'.      OUTPUT = 'E'.
    WHEN '46'.      OUTPUT = 'F'.
    WHEN '47'.      OUTPUT = 'G'.
    WHEN '48'.      OUTPUT = 'H'.
    WHEN '49'.      OUTPUT = 'I'.
    WHEN '4A'.      OUTPUT = 'J'.
    WHEN '4B'.      OUTPUT = 'K'.
    WHEN '4C'.      OUTPUT = 'L'.
    WHEN '4D'.      OUTPUT = 'M'.
    WHEN '4E'.      OUTPUT = 'N'.
    WHEN '4F'.      OUTPUT = 'O'.
    WHEN '50'.      OUTPUT = 'P'.
    WHEN '51'.      OUTPUT = 'Q'.
    WHEN '52'.      OUTPUT = 'R'.
    WHEN '53'.      OUTPUT = 'S'.
    WHEN '54'.      OUTPUT = 'T'.
    WHEN '55'.      OUTPUT = 'U'.
    WHEN '56'.      OUTPUT = 'V'.
    WHEN '57'.      OUTPUT = 'W'.
    WHEN '58'.      OUTPUT = 'X'.
    WHEN '59'.      OUTPUT = 'Y'.
    WHEN '5A'.      OUTPUT = 'Z'.
    WHEN '5B'.      OUTPUT = 'bK'.
    WHEN '5C'.      OUTPUT = 'bL'.
    WHEN '5D'.      OUTPUT = 'bM'.
    WHEN '5E'.      OUTPUT = 'bN'.
    WHEN '5F'.      OUTPUT = 'bO'.
    WHEN '60'.      OUTPUT = 'bW'.
    WHEN '61'.      OUTPUT = 'dA'.
    WHEN '62'.      OUTPUT = 'dB'.
    WHEN '63'.      OUTPUT = 'dC'.
    WHEN '64'.      OUTPUT = 'dD'.
    WHEN '65'.      OUTPUT = 'dE'.
    WHEN '66'.      OUTPUT = 'dF'.
    WHEN '67'.      OUTPUT = 'dG'.
    WHEN '68'.      OUTPUT = 'dH'.
    WHEN '69'.      OUTPUT = 'dI'.
    WHEN '6A'.      OUTPUT = 'dJ'.
    WHEN '6B'.      OUTPUT = 'dK'.
    WHEN '6C'.      OUTPUT = 'dL'.
    WHEN '6D'.      OUTPUT = 'dM'.
    WHEN '6E'.      OUTPUT = 'dN'.
    WHEN '6F'.      OUTPUT = 'dO'.
    WHEN '70'.      OUTPUT = 'dP'.
    WHEN '71'.      OUTPUT = 'dQ'.
    WHEN '72'.      OUTPUT = 'dR'.
    WHEN '73'.      OUTPUT = 'dS'.
    WHEN '74'.      OUTPUT = 'dT'.
    WHEN '75'.      OUTPUT = 'dU'.
    WHEN '76'.      OUTPUT = 'dV'.
    WHEN '77'.      OUTPUT = 'dW'.
    WHEN '78'.      OUTPUT = 'dX'.
    WHEN '79'.      OUTPUT = 'dY'.
    WHEN '7A'.      OUTPUT = 'dZ'.
    WHEN '7B'.      OUTPUT = 'bP'.
    WHEN '7C'.      OUTPUT = 'bQ'.
    WHEN '7D'.      OUTPUT = 'bR'.
    WHEN '7E'.      OUTPUT = 'bS'.
    WHEN '7F'.      OUTPUT = 'bT'.
    WHEN OTHERS.    STATUS = ILLEGAL_CHAR.
  ENDCASE.
ENDFORM.

*---------------------------------------------------------------------*
*       FORM CVT_EBC_INIT                                             *
*---------------------------------------------------------------------*
*       ........                                                      *
* added 040617/dk;
*---------------------------------------------------------------------*
*  -->  PARM                                                          *
*---------------------------------------------------------------------*
FORM CVT_EBC_INIT.

* -- ASCII to EBCDIC vector

  ASC2EBC_000(64) =
'00010203372D2E2F1605150B0C0D0E0F101112133C3D322618193F271C1D1E1F404F7F7
B5B6C507D4D5D5C4E6B604B61F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F'.
  ASC2EBC_064(64) =
'7CC1C2C3C4C5C6C7C8C9D1D2D3D4D5D6D7D8D9E2E3E4E5E6E7E8E963ECFC5F6D7981828
3848586878889919293949596979899A2A3A4A5A6A7A8A943BBDC5907'.
  ASC2EBC_128(64) =
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'.
  ASC2EBC_192(64) =
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'.

* -- load variable portion into vector dynamically
  WRITE '!' TO ASC2EBC_000+33(1).
  WRITE '"' TO ASC2EBC_000+34(1).
  WRITE '#' TO ASC2EBC_000+35(1).
  WRITE '$' TO ASC2EBC_000+36(1).
  WRITE '@' TO ASC2EBC_064+00(1).
  WRITE '[' TO ASC2EBC_064+27(1).
  WRITE '\' TO ASC2EBC_064+28(1).
  WRITE ']' TO ASC2EBC_064+29(1).
  WRITE '^' TO ASC2EBC_064+30(1).
  WRITE '`' TO ASC2EBC_064+32(1).
  WRITE '{' TO ASC2EBC_064+59(1).
  WRITE '|' TO ASC2EBC_064+60(1).
  WRITE '}' TO ASC2EBC_064+61(1).
  WRITE '~' TO ASC2EBC_064+62(1).

* -- load C0..CA into vector (Code 128 control chars)
  WRITE 'À' TO ASC2EBC_192+00(1).
  WRITE 'Á' TO ASC2EBC_192+01(1).
  WRITE 'Â' TO ASC2EBC_192+02(1).
  WRITE 'Ã' TO ASC2EBC_192+03(1).
  WRITE 'Ä' TO ASC2EBC_192+04(1).
  WRITE 'Å' TO ASC2EBC_192+05(1).
  WRITE 'Æ' TO ASC2EBC_192+06(1).
  WRITE 'Ç' TO ASC2EBC_192+07(1).
  WRITE 'È' TO ASC2EBC_192+08(1).
  WRITE 'É' TO ASC2EBC_192+09(1).
  WRITE 'Ê' TO ASC2EBC_192+10(1).


* -- EBCDIC to ASCII vector

  EBC2ASC_000(64) =
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'.
  EBC2ASC_064(64) =
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'.
  EBC2ASC_128(64) =
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'.
  EBC2ASC_192(64) =
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'.

* -- compute EBC2ASC vector from ASC2EBC;
  DATA:
    VASCX TYPE X, VASCDIVI TYPE I, VASCMODI TYPE I,
    VEBCX TYPE X, VEBCDIVI TYPE I, VEBCMODI TYPE I.

  DO 128 TIMES.
    VASCX = SY-INDEX - 1.

    VASCDIVI = VASCX DIV 64.
    VASCMODI = VASCX MOD 64.
    CASE VASCDIVI.
      WHEN 0.
        VEBCX = ASC2EBC_000+VASCMODI(1).
      WHEN 1.
        VEBCX = ASC2EBC_064+VASCMODI(1).
    ENDCASE.

    VEBCDIVI = VEBCX DIV 64.
    VEBCMODI = VEBCX MOD 64.
    CASE VEBCDIVI.
      WHEN 0.
        EBC2ASC_000+VEBCMODI(1) = VASCX.
      WHEN 1.
        EBC2ASC_064+VEBCMODI(1) = VASCX.
      WHEN 2.
        EBC2ASC_128+VEBCMODI(1) = VASCX.
      WHEN 3.
        EBC2ASC_192+VEBCMODI(1) = VASCX.
    ENDCASE.

  ENDDO.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM CVT_EBC2ASC                                              *
*---------------------------------------------------------------------*
*       ........                                                      *
* added 040616/dk;
*---------------------------------------------------------------------*
*  -->  PARMX                                                          *
*---------------------------------------------------------------------*
FORM CVT_EBC2ASC USING PARMX.

  DATA:
    POS           TYPE I,
    VALCURX       TYPE X,
    VALDIVI       TYPE I,
    VALMODI       TYPE I,
    BUFX(MAX_LEN) TYPE X.

  MOVE PARMX TO BUFX.

  DO MAX_LEN TIMES.
    POS = SY-INDEX - 1.
    VALCURX = BUFX+POS(1).
    VALDIVI = VALCURX DIV 64.
    VALMODI = VALCURX MOD 64.
    CASE VALDIVI.
      WHEN 0.
        BUFX+POS(1) = EBC2ASC_000+VALMODI(1).
      WHEN 1.
        BUFX+POS(1) = EBC2ASC_064+VALMODI(1).
      WHEN 2.
        BUFX+POS(1) = EBC2ASC_128+VALMODI(1).
      WHEN 3.
        BUFX+POS(1) = EBC2ASC_192+VALMODI(1).
    ENDCASE.
  ENDDO.

  MOVE BUFX TO PARMX.

ENDFORM.

*---------------------------------------------------------------------*
*       FORM CVT_ASC2EBC                                              *
*---------------------------------------------------------------------*
*       ........                                                      *
* added 040616/dk;
*---------------------------------------------------------------------*
*  -->  PARMX                                                          *
*---------------------------------------------------------------------*
FORM CVT_ASC2EBC USING PARMX.

  DATA:
    POS           TYPE I,
    VALCURX       TYPE X,
    VALDIVI       TYPE I,
    VALMODI       TYPE I,
    BUFX(MAX_LEN) TYPE X.

  MOVE PARMX TO BUFX.

  DO MAX_LEN TIMES.
    POS = SY-INDEX - 1.
    VALCURX = BUFX+POS(1).
    VALDIVI = VALCURX DIV 64.
    VALMODI = VALCURX MOD 64.
    CASE VALDIVI.
      WHEN 0.
        BUFX+POS(1) = ASC2EBC_000+VALMODI(1).
      WHEN 1.
        BUFX+POS(1) = ASC2EBC_064+VALMODI(1).
      WHEN 2.
        BUFX+POS(1) = ASC2EBC_128+VALMODI(1).
      WHEN 3.
        BUFX+POS(1) = ASC2EBC_192+VALMODI(1).
    ENDCASE.
  ENDDO.

  MOVE BUFX TO PARMX.

ENDFORM.

*---------------------------------------------------------------------*
*       END                                                           *
*---------------------------------------------------------------------*
