How to Automatically Convert COBOL to Go
Although COBOL can be considered a legacy language, there are still billions of lines of COBOL in production. Modernizing these systems which are costly to run and maintain is a challenge. One solution to this issue is a COBOL to Go transpiler that I want to present in this article.
COBOL
COBOL first appeared in 1959 and is a compiled language designed for business use. Today, mainly big financial institutions and government agencies have systems running COBOL in production. It is deployed often on mainframe computers, for example the Z Mainframe running z/OS by IBM. It is a sizable market because roughly 10,000 mainframe computers operate worldwide.
Although object-oriented features are now also available, COBOL is mainly a procedural and imperative language.
This is a simple hello word program in COBOL:
hello.cob
* Sample COBOL program
IDENTIFICATION DIVISION.
PROGRAM-ID. hello.
PROCEDURE DIVISION.
DISPLAY "Hello, world!".
STOP RUN.
You can try it out on your own computer, for example with GnuCOBOL by running the following compile command:
$ cobc -x hello.cob
$ ./hello
Go
Go is a statically typed, compiled high-level programming language designed at Google by Robert Griesemer, Rob Pike, and Ken Thompson. Its advantages are the low entry barrier for new developers and that it is a compiled language with fast execution.
Thus, it is a good choice when trying to modernize legacy COBOL applications. The Go source code is easy to understand even for programmers new to Go.
That is an advantage because the market for COBOL software developers is challenging, as I describe in the next section.
Market for COBOL Programmers
Many big companies who have running systems in COBOL struggle in attracting programmers who can maintain these systems. The average age of COBOL software developers is high and there are few young developers who want to learn COBOL.
This is a risk for the companies who have many billions of lines of COBOL in production. That is why a possible migration solution like COBOL-to-Go from Enno Richter comes in handy.
COBOL-to-Go Converter
The senior COBOL programmer Enno Richter with many decades (50 years) of experience in COBOL programming developed a COBOL to Go transpiler called COBOL-to-Go. The transpiler evolved from an older RPG-to-COBOL project. It supports the COBOL-85 standard, but features of newer COBOL standards can be added on demand.
One of its advantages is that the resulting Go code is easy to read and clearly structured. There is no runtime system necessary and thus the resulting Go code remains independent from the COBOL-to-Go system. Go compiles to many operating systems and thus the COBOL program can run on potentially many operating systems.
All rights of the resulting Go code remain with the COBOL code copyright holders.
There are alternative COBOL transpilers, like a COBOL to Java transpiler in the market, but Enno Richter claims the results of his Go transpiler are easier to understand and maintain.
Example Code
The following snippet shows the COBOL code on the left hand side and the resulting transpiled Go code on the right hand side. You might need to scroll horizontally to see the resulting Go Code:
* :00190: // 00190: *
*----------------------------------------------------------------* :00191: // 00191: *----------------------------------------------------------------
**------* *-----------------------------------------------------** :00192: // 00192: **------* *-----------------------------------------------------*
** 30 * * P R O G R A M M A B L A U F ** :00193: // 00193: ** 30 * * P R O G R A M M A B L A U F *
**------* *-----------------------------------------------------** :00194: // 00194: **------* *-----------------------------------------------------*
PROCEDURE DIVISION. :00195:
**---------------------------------------------------------------* :00196: // 00196: **---------------------------------------------------------------
** V e r a r b e i t u n g * :00197: // 00197: ** V e r a r b e i t u n g
**---------------------------------------------------------------* :00198: // 00198: **---------------------------------------------------------------
DISPLAY "Test_02400_START --------". :00199: erse.DISlx(&DIS, "Test_02400_START --------") // COBZEI:00199
ersestr1 = erse.DISout(fDISPLAY, &DIS, " ") // COBZEI:00199
* :00200: // 00200: *
* :00201: // 00201: *
**-----------------------------------------------------------* :00202: // 00202: **-----------------------------------------------------------*
** IF LITERAL --- NUMERISCH (Struktur) * :00203: // 00203: ** IF LITERAL --- NUMERISCH (Struktur) *
**-----------------------------------------------------------* :00204: // 00204: **-----------------------------------------------------------*
* IF 12 > BBB-8 :00205: // 00205: * IF 12 > BBB-8
* MOVE SPACE TO BBB-1 :00206: // 00206: * MOVE SPACE TO BBB-1
* END-IF. :00207: // 00207: * END-IF.
* :00208: // 00208: *
* :00209: // 00209: *
**-----------------------------------------------------------* :00210: // 00210: **-----------------------------------------------------------*
** IF NUMERISCH (Struktur) --- LITERAL * :00211: // 00211: ** IF NUMERISCH (Struktur) --- LITERAL *
**-----------------------------------------------------------* :00212: // 00212: **-----------------------------------------------------------*
* IF BBB-8 > 12 :00213: // 00213: * IF BBB-8 > 12
* MOVE SPACE TO BBB-1 :00214: // 00214: * MOVE SPACE TO BBB-1
* END-IF. :00215: // 00215: * END-IF.
* :00216: // 00216: *
* :00217: // 00217: *
**-----------------------------------------------------------* :00218: // 00218: **-----------------------------------------------------------*
** IF LITERAL --- NUMERISCH (Nativ) * :00219: // 00219: ** IF LITERAL --- NUMERISCH (Nativ) *
**-----------------------------------------------------------* :00220: // 00220: **-----------------------------------------------------------*
* IF 12 > Z3 :00221: // 00221: * IF 12 > Z3
* MOVE SPACE TO BBB-1 :00222: // 00222: * MOVE SPACE TO BBB-1
* END-IF. :00223: // 00223: * END-IF.
* :00224: // 00224: *
* :00225: // 00225: *
**-----------------------------------------------------------* :00226: // 00226: **-----------------------------------------------------------*
** IF NUMERISCH (Nativ) --- LITERAL * :00227: // 00227: ** IF NUMERISCH (Nativ) --- LITERAL *
**-----------------------------------------------------------* :00228: // 00228: **-----------------------------------------------------------*
* IF Z3 > 12 :00229: // 00229: * IF Z3 > 12
* MOVE SPACE TO BBB-1 :00230: // 00230: * MOVE SPACE TO BBB-1
* END-IF. :00231: // 00231: * END-IF.
* :00232: // 00232: *
* :00233: // 00233: *
**-----------------------------------------------------------* :00234: // 00234: **-----------------------------------------------------------*
** IF NUMERISCH (Struktur) ---- NUMERISCH (Struktur) * :00235: // 00235: ** IF NUMERISCH (Struktur) ---- NUMERISCH (Struktur) *
**-----------------------------------------------------------* :00236: // 00236: **-----------------------------------------------------------*
IF BBB_8 > HHH :00237: if erse.IFNCVCV(&BBB_8_cv, ">", &HHH_cv) {
MOVE SPACE TO BBB_1 :00238: erse.MVACVLI(&BBB_1_cv,"SPACE") // COBZEI:00238
END-IF. :00239: } // ENDIF
* :00240: // 00240: *
* :00241: // 00241: *
**-----------------------------------------------------------* :00242: // 00242: **-----------------------------------------------------------*
** P R O G R A M M - E N D E * :00243: // 00243: ** P R O G R A M M - E N D E *
**-----------------------------------------------------------* :00244: // 00244: **-----------------------------------------------------------*
DISPLAY "Test_02400 ENDE -------------". :00245: erse.DISlx(&DIS, "Test_02400 ENDE -------------") // COBZEI:00245
ersestr1 = erse.DISout(fDISPLAY, &DIS, " ") // COBZEI:00245
STOP RUN. :00246: //---------------------------------------------------------------
// STOP-RUN (Ende der Programmlogik)
//---------------------------------------------------------------
os.Exit(0)
**--------------------------------------------------------------** :00247: // 00247: **--------------------------------------------------------------*
** Ende : ** :00248: // 00248: ** Ende : *
** ~~Projekt~111COBOL~Sourcen~Test_02400.cbl (2023-04-20 ** :00249: // 00249: ** //Projekt/111COBOL/Sourcen/Test_02400.cbl (2023-04-20 *
* ** :00250: // 00250: * *
**--------------------------------------------------------------** :00251: // 00251: **--------------------------------------------------------------*
As you can see, the resulting Go code is easy to understand and maintainable.
Enno Richter is looking for collaboration companies who can distribute his valuable project. If you are interested, write me a message or contact Enno Richter directly.
Conclusion
With this article I hope you could see that there are solutions to the issue of a lack of COBOL programmers in the market. One such solution is the COBOL-to-Go transpiler that might be the missing piece of your COBOL migration.
References
- Enno Richter Software: https://www.richter-software.de
- COBOL-to-Go: https://www.richter-software.de/fileadmin/pdf/COBOL-to-Go_Marketing_Folien_Web_Deutsch.pdf
- GnuCOBOL: https://gnucobol.sourceforge.io
- COBOL Programming Course: https://openmainframeproject.org/projects/cobol-programming-course
Cover photo by Pete Linforth from Pixabay
Published
22 Jul 2024