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

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

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

ASCII and EBCDIC independent code! 1

Status
Not open for further replies.

wahlers

Programmer
May 13, 2004
142
NL
Question: Any bright suggestions for handling platform dependent codes?

For example:
----------------

I see some sources using hex values (e.g. for carriage return).
This is great but there are (at least 2) distinguish differently coding schemes, namely:
ASCII
EBCDIC

(and of course there is UNICODE...but it uses 2 bytes,
I have no experience with unicode. anybody????)

This means that any program using hex values is tight to a specific scheme (or worse still a esotoric dialect of a scheme!).

I wonder if it was possible to make each source independent of the coding scheme environment.
On the top of my hat I came up with something like this:

Code:
01  workingStorageFields.
  05  getCode          PIC  X(08) VALUE 'getCode'.
  05  LineFeedChar     PIC  X(01).
  05  returnFlag.
    88  returnOK       VALUE  '0'.
    88  returnNOTok    VALUE  '0'.
  05  forMethod        PIC  X(20).
    88  ..........     VALUE '........'.
    88  lineFeed       VALUE 'lineFeed'.
    88  ..........     VALUE '........'.

SET   lineFeed    IN  forMethod  TO  TRUE

CALL  getCode     USING
, by reference    returnFlag
, by content      forMethod
, by reference    lineFeedChar
END-CALL

IF  returnOK
, MOVE lineFeedChar  TO  ......
, .... and the rest of the code ...
,


NOTE:
Don't be surprised by the structure of the next source
program. I am used to method programming. Normally I would even use ENTRYs (non standard!) so I can use different linkage values in the same source program.

The called (sub)program looks more or less like this:

Code:
PROGRAM-ID.  getCode.

01  privateData.
  05  theLetter-a       PIC  X(01) VALUE 'a'.
  05  invokeGetHEXcode.
    10  theEnvironment  PIC  X(01).
      88  EBCDIC        VALUE 'E'.
      88  ASCII         VALUE 'A'.
      88  ELBONIAN      VALUE 'Z'.
    10  invokeMethod    PIC  X(20).

LINKAGE-SECTION.

01  returnFlag          PIC  X(01).
  88  returnOK          VALUE  '0'.
  88  returnNOTok       VALUE  '1'.

01  theMethod           PIC  X(20).

01  returnHEXcode       PIC  X(01).

PROCEDURE DIVISION USING  returnFlag
                          theMethod
                          returnHEXcode
                          .
    EVALUATE  TRUE
    ,  WHEN  theLetter-a  =  x'81'
    ,        SET  EBCDIC       TO  TRUE
    ,        PERFORM  getHEXcode
    ,
    ,  WHEN  theLetter-a  =  x'61'
    ,        SET  ASCII        TO  TRUE
    ,        PERFORM  getHEXcode
    , 
*// from elbonia! see: Dilbert cartoons.
    ,  WHEN  theLetter-a  =  x'**'
    ,        SET  ELBONIAN     TO  TRUE
    ,        PERFORM  getHEXcode
    ,
    ,  WHEN  OTHER
    ,        SET  returnNOTok  TO  TRUE
    ,
    END-EVALUATE

    GOBACK
    .

getHEXcode.

    SET   returnOK      TO  TRUE
    MOVE  theMethod     TO  invokeMethod

    CALL  invokeGetHEXcode USING
    , by reference returnHEXcode
    ON EXCEPTION
    , SET  returnNOTok  TO  TRUE
    END-CALL
    .

IDENTIFICATION DIVISION.
PROGRAM-ID. AlineFeed.
DATA DIVISION.
LINKAGE SECTION.
01  returnField  PIC  X(01).
  88  lineFeed  VALUE x'0A'.
PROCEDURE DIVISION USING  returnField.
    SET  lineFeed  TO  TRUE
    GOBACK
    .
END PROGRAM  AlineFeed.

IDENTIFICATION DIVISION.
PROGRAM-ID. ElineFeed.
DATA DIVISION.
LINKAGE SECTION.
01  returnField  PIC  X(01).
  88  lineFeed  VALUE x'15'.
PROCEDURE DIVISION USING  returnField.
    SET  lineFeed  TO  TRUE
    GOBACK
    .
END PROGRAM  ElineFeed.

IDENTIFICATION DIVISION.
PROGRAM-ID. ZlineFeed.
DATA DIVISION.
LINKAGE SECTION.
01  returnField  PIC  X(01).
  88  lineFeed  VALUE x'**'.
                        ^^ works in Elbonia!
PROCEDURE DIVISION USING  returnField.
    SET  lineFeed  TO  TRUE
    GOBACK
    .
END PROGRAM  ZlineFeed.

IDENTIFICATION DIVISION.
PROGRAM-ID. AcarriageReturn.
DATA DIVISION.
LINKAGE SECTION.
01  returnField  PIC  X(01).
PROCEDURE DIVISION USING  returnField.
    CALL 'EcarriageReturn' USING  returnField
    GOBACK
    .
END PROGRAM  AcarriageReturn.

IDENTIFICATION DIVISION.
PROGRAM-ID. EcarriageReturn.
DATA DIVISION.
LINKAGE SECTION.
01  returnField  PIC  X(01).
  88  carriageReturn  VALUE x'0D'.
PROCEDURE DIVISION USING  returnField.
    SET  carriageReturn  TO  TRUE
    GOBACK
    .
END PROGRAM  EcarriageReturn.

END PROGRAM  getCode.


Notice that with the coding above that within the program it is not possible to accidently override the return value with some other value. This is because these values are private data protected by the contained programs.

Notice that the carriage return for ASCII is the same as for EBCDIC (and this is true!). And this carriage return value is coded and guarded in only one place (EcarriageReturn).

I am just fishing for similar codes and solutions...anybody?
 
Wim -

Why not simply define a copybook for the SPECIAL-NAMES paragraph that is specific to the target platform? For instance:

Code:
     SYMBOLIC CHARACTERS
         NULL IS 1        
         ETX IS 4        
         BELL IS 8        
         LINE-FEED IS 11                   
         CARRIAGE-RETURN IS 14       
         ESCAPE IS 28                     
         HOME IS 73                       
         DELETELINE IS 78

I think this would solve your problem in a straightforward, standard way.

Regards.

Glenn
 
To: Glenn

I think you miss the point (or I miss your point)!

The whole idea is that you don't know (or need to know) on which platform you are. It could either be ASCII based or EBCDIC based.

The idea is that you don't have to do any recoding (or copy replacement) when you migrate to another platform.

I know your solution looks simple but:
All things you don't have to do you also don't have to document either!
Changing copybooks needs to be documented and maintained.
That is the reason way I (sort of) wrote this single common routine.

(p.s. I know you pay a performance penalty for invoking and executing this routine, but that is not the issue here).

I hope explanation clears the confusion.
My apologies if I wasn't clear enough.


Regards, Wim Ahlers.
 
Wim -

I understand (I think) your goal in writing the code. It does avoid having to know what code set you're using.
However, I find your code to be voluminous and complex (and, as you point out incurs a (substantial?) performance penalty).

I think you don't appreciate the simplicity of the approach I am advocating. I would not change copybook names, I would advocate simply having two versions of the same copybook (e.g. when I install my software on an ASCII machine, I install the ASCII version of copybook X; on and EBCDIC machine, I install the EBCDIC version of copybook X). This only needs to be done once, when the software is first installed. (And I think it is highly likely that there are other platform-dependent things that will have to be handled at install time.) Yes, if codes are added to the list over time, both versions of the copybook need to be maintained, but there's no operational risk there, failure to do so simply incurs a compile error.

If I wanted a run-time approach to this, I think I would choose something more like having a code table copied into any program that needed these codes. I would then have PROCEDURE DIVISION copybook that called a subroutine to initialize the code table by moving in the appropriate string. Relatively fast and easy for the average joe to understand.

Glenn
 
To: 3gm

My code complex?
Yes!
My code voluminous?
Yes!

My code complex?
No!
My code voluminous?
No!

Yes complex and voluminous when you are thinking lineair and single server and non-resuable.

No complex and voluminous when you are thinking non-lineair and multiple server and reusable.

My program is a collection of individual programs (call it functions or methods) gathered around centralised private data of which some methods are publicly exposed.
If this sounds like I just described a class then you are absolutely right!
It is both a different way of thinking and a different way of programming.
With this way of programming I can shield the user from the internal complexities.
The user being a programmer using (invoking) a certain publicly available class method.
The penalty I pay (using a non-object oriented language like COBOL-85) is a more elaborate source. This is because every single piece of data or function is (and must be) potentially reusable.
In the end a well-defined class library saves time (and money!).

When you start with coding reusable code you have to multiply the time, effort and cost with a factor X.
(X depends on tools, complexity of the system, the organisation and above all the knowledge and willingness of the IT personel involved).

You are free to provide a standard lineair procedural piece of code.

Regards, Wim Ahlers.

 
A relatively easy solution to the problem (as I see it) is to:

A) Do a test (as in the original) to see if
"A" = X"C1"

If so, you are in an EBCDIC run-time environment (if not you are PROBABLY in an ASCII environment, but you could check for that too).

B) If you are in an EBCDIC environment, then use the ANSI/ISO Standard "CODE-SET" clause to convert files (possibly temporarily) to ASCII - if you want this. (All conforming compilers need to support the STANDARD-1 Configuration Section) clause.

C) If you are in an ASCII environment and you want to get EBCDIC output *and* your environment supports this, then check for an EBCDIC option for the Configuration Section (and use the CODE-SET clause).

***

If you are running in an ASCII environment and want to create EBCDIC files - but your Operating System (compiler) doesn't support this, then you have a "problem" - but I would ask WHY you are doing this - and whether an FTP or other "solution" wouldn't be better in the first place.

NOTE:
At least for the IBM enviorntment, there are MULTIPLE "EBCDIC" code-pages - based on the national character set in use.

Bill Klein
 
To: WMK (and others)

I am aware of the multiple schemes.
It is this what I like to control (e.g. in Germany they use characters like ü, in france ë, á and in Norway characters I can not readily produce right now).

Actually I wrote a nice common function in Norway.
Except you cannot use it in Germany exactly because of the character set!

I know this is solved by unicode. But this includes a 2-byte implementation for every character.
So, on top of the original question (I did ask this before, but):
Has anybody experience using unicode in COBOL?


Kind regards, Wim Ahlers.
 
If running with a current IBM mainframe compiler, it is relatively easy to convert from one code-page to another - via the NATIONAL-OF and DISPLAY-OF intrinsic functions (from the 2002 ISO Standard) *with* the IBM extension of using the "CCSID". For example (of what *is* in use today), see:




Bill Klein
 
To: WMK

Thanks for the tip.
You said ISO 2002.
Regretfully I am a little bit behind (COBOL-85).
However, I must also aim for the future.
I have to study it, see how it works and see what I can use (now).

To all:

Does anybody has an example (program) handling unicode?
(thus admitting I have no experience using unicode!)


Regards, Wim Ahlers.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top