Outils pour utilisateurs

Outils du site


issue100:programmer_en_cobol

Ceci est une ancienne révision du document !


Ubuntu users are a modern people. We use tablets and smartphones that didn't exist ten years back. We wait impatiently for each succeeding version of Ubuntu to be more revolutionary than the last version, a mere six months back. Is this not progress? Is this not what the fast-paced twenty-first century is all about?

Writing about a programming language such as COBOL may come out as a bit odd. After all, the Common Business-Oriented Language was born in the year 1959, sometime during those Dark Ages when programming did not mean running a JavaScript in a Web browser, and computing was not all about connecting your touch-screen phone to the latest high-speed mobile network. In those days, even seeing a computer blink its lights at you must have been quite an experience. To measure the distance covered by informatics in the intervening 56 years, let us just say I would much prefer to drive every day an automobile built in 1959 (a Land Rover Series II would do very nicely, thank you) than a computer and compiler combination of the same vintage.

Just before year 2000 and the infamous “y2k bug” that was supposed to bite us all in the nose (but never quite did – because we were prepared for it!) it came to the attention of many IT department heads that a sizable portion of computer programs in use had been originally written in COBOL. This was true mainly in the finance industry. Having been passed from one generation of hardware to another, and recompiled several times in the process, the programs handled most core processes and were well placed to last longer than the human programmers that had created them in the first place – and who were at that time heading towards retirement, if not already there. A scarcity of programmers of the younger generations able to comprehend, let alone maintain, code written in COBOL, seemed to be on the cards. Fifteen years on, this still seems to be a bit of a concern even in year 2015, at least according to some. However, a large part of the programs must have needed to be re-written at some point if only to adapt to the needs of e-banking and e-business, and writing newer programs from scratch in COBOL is less often seen these days.

However, the COBOL language still seems to have been maintained, with even an object-oriented version being announced in 2002, and a more advanced standard published in 2014. IBM seems to be a major player in the field, although it also gives active support to other offerings (such as Java) for programming mainframes. On the GNU/Linux side, OpenCOBOL (http://www.opencobol.org/) appeared to give us the possibility of compiling working programs on the most recent Ubuntu systems, which has then been re-branded (superseded) by GNU Cobol since version 1.1.

It was mainly from a standpoint of historical interest that I installed this compiler, and managed to get an Euclidian Algorithm program up and running quite easily, with procedure calls and even some invocation of routines written in the C language by the side.

Installation

Installation is the usual procedure on *buntu systems, since OpenCOBOL is available directly from the repositories. Simply use your favorite software package manager to install package open-cobol:

aptitude install open-cobol

When this is installed, we can directly fire up the COBOL compiler in a terminal and investigate which version we are using:

cobc –version

cobc (OpenCOBOL) 1.1.0

Copyright (C) 2001-2009 Keisuke Nishida / Roger While

Built Nov 02 2013 00:16:01 Packaged Feb 06 2009 10:30:55 CET

As can be seen from the dates quoted, development of this compiler is not going along at the supersonic speeds seen in some open-source projects. However, this suits quite well the COBOL mindset that goes more for “steady does it” and “piano, piano si va lontano” than seeking out instant results.

The compiler documentation gives us some insight into which COBOL dialects are supported. The ground-breaking 2002 version is there, though the 2014 update is not (yet) there:

-std=<dialect> Compile for a specific dialect :

                        cobol2002   Cobol 2002                          cobol85     Cobol 85                          ibm         IBM Compatible                          mvs         MVS Compatible                          bs2000      BS2000 Compatible                          mf          Micro Focus     		 Compatible                          default     When not 				 specified

Compiling “Hello, world!”

A very basic program in traditional, old-style, fixed-format, COBOL runs like this:

IDENTIFICATION DIVISION.

PROGRAM-ID. HELLO-WORLD.

PROCEDURE DIVISION.

DISPLAY 'Hello, world'.
STOP RUN.

Note that this syntax - originally thought out for punched cards - is all about spacing. The first six characters on each line (columns 1 to 6) are reserved to identify each program line with a number – though nowadays numbers are no longer mandatory. Column 7 is an indicator area that can be used to mark a line as a commentary by inserting an asterisk “*” character in this space. Finally, only a maximum of 72 characters may be used in each line, thus leaving just 72 - 7 = 65 characters to write actual code in.

Fire up your favorite text editing program, and type or paste in this text. Save the file as “hello.cob” or “hello.cbl” – COBOL source code file extensions vary a bit. Unfortunately, there are not many text editors in Ubuntu that can handle COBOL syntax highlighting. However, the jedit program is available, easily installable from the repositories, and does just that quite well.

Once saved, let us compile our first program. We will need to use option “-x” to request the compiler to perform linkage as well as compilation proper, and produce an executable file:

cobc hello.cob -x

Here we have our source code, and the executable program, which can then be executed:

ls

hello hello.cob

./hello

Hello, world

It is noteworthy that, since I was doing this on a 64-bit version of Linux Mint, what the compiler produced is in fact a 64-bit executable file! I wonder what the original creators of the language would have thought of that:

ldd hello

      [...]
      /lib64/ld-linux-x86-64.so.2 (0x00007f277d149000)

Free-form and procedures

The programing world has gone forward a tad since the original specification for COBOL was published. Among other things, writing programs in ALL CAPITAL LETTERS is no longer considered the only true way of getting things done, and modern script-kiddies would have difficulties abiding with the very strict column syntax of earlier versions. This is why later COBOL dialects have progressively reduced the constraints on formal program presentation, giving us free-form syntax. Some of the parts, such as the identification division, no longer need to be specified. The same HelloWorld program may be written in free form in the following manner:

program-id. HelloWorld.

procedure division.

display "Hello, world".
stop run.

end program HelloWorld.

From the compiler's point of view, all we need to do is specify that we are going to use free-form, and the very same executable file may be produced:

cobc hello.cob -x -free

Let us now complicate things. We are now going to split the program up into two parts: a main procedure that will be invoked on program execution, and a sub-program (procedure) that actually does the dirty work when required by the main procedure. To go a step further, we will declare a variable and initialize it with the text to be displayed. The main program goes as follows:

program-id. HelloWorld.

data division.

working-storage section.
01 Greeting PIC X(15) value "Hello, world!".

procedure division.

call "TestSub" using Greeting.
stop run.

end program HelloWorld.

A new data division has appeared before the procedure division. This contains a working-storage section, which is where local variables are declared using the PIC syntax. Variables may be immediately initialized using the value keyword.

Now, for the procedure TestSub. This must be written in a new program-id section, that may be inserted within the same file as the main program. For example:

program-id. TestSub.

data division.

      linkage section.
      01 Grt PIC X(15).

procedure division using Grt.

      display "This is TestSub".
      display "Grt = " Grt.
      exit program.

end program TestSub.

In this case, procedure TestSub will be invoked by the main program using one parameter, the text to be displayed. We have also inserted a data division within the sub-program, declaring this parameter within the linkage section.

For clarity, the parameter name is “Grt” within the sub-program, and “Greeting” in the main. Just a word of warning: parameters are called by reference, so if changes were eventually to be made to “Grt” within the sub-program, these changes would then be maintained in Greeting when returning to the main procedure. Programmers should exercise caution, especially if accustomed to C's way of passing parameters (call by value). However, it should also be said that this feature facilitates returning values from a sub-program to the routine that invokes it.

Let's calculate a GCD

To illustrate parameter passing when using a procedure, let us use Euclid's Algorithm to compute the Greatest Common Divisor of two integer numbers. The main program will use three variables: A and B to store the two integers, and G for the result. The main program in itself is rather straightforward, the only noteworthy bit being the way in which parameter G is used to retrieve the result from the procedure back to the main program:

program-id. GCD.

data division.

      working-storage section.
      01 A PIC 9(15) value 245.
      01 B PIC 9(15) value 135.
      01 G PIC 9(15).

procedure division.

      call "EuclidianAlgorithm" using A, B, G.
      display "GCD of " A " and " B " is " G.
      stop run.

end program GCD.

Inside the EuclidianAlgorithm procedure, we will begin by making a copy of the two numbers A and B, into local storage. In this way we make sure no changes are made to their original values back in the main program. We will need both a linkage and a working-storage section in the data division, to keep track of incoming parameters and store local variables respectively. Finally, the COBOL way of constructing a “repeat until” structure may seem a bit weird to programmers using other languages, but it does work.

program-id. EuclidianAlgorithm.

data division.

      working-storage section.
      01 A PIC 9(15).
      01 B PIC 9(15).
      01 Q PIC 9(15).
      01 R PIC 9(15).
      linkage section.
      01 IN_A PIC 9(15).
      01 IN_B PIC 9(15).
      01 IN_G PIC 9(15).

procedure division using IN_A, IN_B, IN_G.

      Main.
      move IN_A to A.
      move IN_B to B.
      perform Loop with test after until R = 0.
      move A to IN_G.
      Loop.
      divide A by B giving Q remainder R.
      move B to A.
      move R to B.

end program EuclidianAlgorithm.

Once the file is compiled, we can execute the binary program:

cobc gcd.cob -x -free

./gcd

GCD of 000000000000245 and 000000000000135 is 000000000000005

Calling C code from COBOL

When generating the result above, I was not entirely satisfied with the presentation on screen. All those leading zeros seem rather gauche, to say the least. I would have much preferred a C-style printf function to format output, which unfortunately does not seem to be readily available in COBOL.

In the interest of tinkering a bit, instead of writing an equivalent procedure in pure COBOL, let us do so in C and invoke it from the COBOL main program. The C wrapper was built around two functions:

  • prettyNumber takes one of the numbers sent from the COBOL side of things, parses and prints it on-screen. As the numbers are each formatted as an array of 15 characters, a simple for loop is used to traverse the array, combined with the flag leading_zeros to indicate if we are still passing through leading zeros (TRUE) or have come into the main body of the number (FALSE).
  • Print is defined as an external function, and so is accessible from outside the C object file. It simply takes the three parameters A, B and G from the COBOL side, and writes them out using prettyNumber.

Inside the existing COBOL code, just one line needs to be changed in the main program. We replace

display “GCD of ” A “ and ” B “ is ” G.

with

call “Print” using A, B, G.

No further modifications need to be made to the code. However, compilation will be a tad more tricky, since we need to compile the C library first, and then give it to the COBOL compiler to link with the COBOL code and produce an executable file. So:

cc print.c -o print.o -c

cobc gcd-c.cob print.o -x -free

The “-c” flag tells the C compiler to halt once the object code is produced, before linking. The object file may then simply be added to the COBOL compiler's input file list. Execution is then performed in the usual way, producing much nicer visual results:

./gcd-c

GCD of 245 and 135 is 5

Conclusions

As stated at the beginning, the aims of this short piece were mostly to go back in time and see how the efforts of a dedicated group of programmers have made a rather ancient (in computer terms) programming language come back to life on a modern GNU/Linux distribution. Neither the hardware (laptop versus 1950's mainframe) nor the operating system (UNIX-like versus proprietary OS) have much to do with what the original COBOL designers were contending with – but this stuff works, and can give us a taste of how things were in the “good old days” of computation.

Although the language itself has seen some evolution since conception, general syntax and conception are visible to those of another age. This is not to say that modern trends such as object-oriented design or web service implementation could not be handled through COBOL. On the contrary, if sufficient interest were to be found to implement the necessary intermediate libraries, I see no reason why COBOL - and, specifically, Open/GNU COBOL - could not hold its own with more modern offerings. However, the necessary code would necessarily be seen as an additional layer on top on what is in essence a language from the 1950's – and so, such attachments may at times seem rather alien to the language's original philosophy.

On the other hand, handling communication with databases has always been one of the strengths of the COBOL environment; it was mostly built into the concept starting from day one. So, if or when the interested parties can finish linking up COBOL with existing database systems such as PostgreSQL or MariaBD (some work has already been done with Oracle) - or, even better, a generic SQL extension mechanism - this project could very well find its place in the modern world, at least where database back-end programming is concerned.

issue100/programmer_en_cobol.1440939043.txt.gz · Dernière modification : 2015/08/30 14:50 de auntiee