COBOL TIPS #29
by
Shawn M. Gordon
President S.M.Gordon & Associates

Howdy avid readers, as promised, over the next three or four months I will be presenting my view of C from a COBOL perspective.  Now I originally taught myself C about 8 years a go, I then took a few classes to fill in the missing bits.  I was so keen on C when I first started looking at it, I was ready to rewrite everything from COBOL to C, but as I looked closer at the C language, and realized that it was a terrible choice from a business perspective, I started to change my mind about it.

Now C does have it's uses as a high level assembler, which it was originally designed for, it's just not a good business language.  Non of this obviates the need for some of us to have to learn the language, so hopefully what I can do with this series is help make the transition a little easier, or give you ammo to show to those executives who keep reading in Computerworld that everything must be "open" and in "C" and "UNIX".

There may be some very minor error's in my code examples, they are meant to illustrate a point.  So those of you who know something I don't, please keep the hate mail to a minimum, but all useful, constructive, and friendly input is appreciated.

Remember, this is not intended to teach you the C language, it is meant to point you in the right direction when trying to come up with command equivalencies so you have a better starting point.  Remember that C and COBOL come from completely different roots, this is what makes comparisons very difficult, and it is also why making comparisons to PASCAL is very easy.  I will do my best to logically group and compare different aspects of the two languages.  

Preprocessor

COBOL gives us a couple of options for sharing previously defined record layouts and variable declarations.  The easiest and most straight forward is the $INCLUDE 'filename'. This will take an MPE numbered file and copy it into the source file at compile time. This works just fine if you aren't worried about modifying any of the statements.

The more versatile option is to use COBEDIT and maintain a COPYLIB.  This is a KSAM file that contains all the different sequences of COBOL commands that you are interested in maintaining in a global area.  The advantage to using the COPY command to retrieve members from a COPYLIB is that you can do dynamic text replacement.  So if you want to define your customer master data set twice, once for the data set and once for a file, you could have set up a prefix that in the COPYLIB that you could change at compile time by using the command;

COPY textname REPLACING ==pseudo-text-1== BY ==pseudo-text-2==. 

Thus eliminating the need to maintain two different definitions in your COPYLIB.

While C does have an 'include' statement, it doesn't have an equivalent to the COPY statement.  However, by using the '#if', '#ifdef', '#elif' and '#ifndef' commands you can control what files get included at compile time. Say for example you are coding some sort of portable application and you have defined different file I/O functions in different files to accommodate your different platforms.  You could control it very easily with the following construct;

#define SYS "HP3000"
#if SYS == "HP3000"
#include "hp3kio.h"
#elif SYS == "VAX"
#include "vaxio.h"
#elif SYS == "AS400"
 #include "as4io.h"
#endif

There are several important things here to learn; First off the #define command is actually almost the same as the $DEFINE in COBOL.  They both allow you to define and name a macro, this macro will create "in-line" code, so it will generate more efficient, if slightly larger code.  However the COBOL define statement can be as long as you want, whereas many C compilers restrict you to just the line that contains the #define statement.  Passing parameters to a C macro is more confusing is well, just make sure to sprinkle liberally with parentheses to ensure the order of precedence.

The #define can also work rather like an 88 level variable in COBOL, for example;

#define FALSE 0
#define TRUE !FALSE

I could then say 'if FALSE' just like in COBOL with an 88.  The advantage here is that I can define TRUE to be 'not' FALSE by use of the ! (which means not) in the second #define statement.  This doesn't really have an equivalent in COBOL.

Now that I have explained just enough about the #define statement to get us through our first example, why don't I finish explaining the example.

Since we have defined SYS to be equal to the character string HP3000 the first #if statement will be true and the file hp3kio.h will be copied into the program at compile time.  The #elif is a really stupid way of saying 'else if', only the assembler gods know why they chose to abbreviate it the way they did.  So if we want to compile our code to run on a VAX we would only need to change the #define line, and then our code will run on a VAX if we have done our initial setup correctly.

Believe it or not you could accomplish almost the same thing using the little known and rarely used compiler switches available in COBOL.  By using the following commands you could accomplish a similar affect.

$SET X0=OFF
$IF X0=OFF
COPY HP3KIO
$IF X0=ON
COPY VAXIO
$IF

It is important to note that while COBOL is not case sensitive, C is.  So myvar, Myvar, and MYVAR would actually be three different things.  An informal standard that I have seen is that all your 'regular' C code is in lower case and any macros and sometimes functions, that you define are done in upper case to make it quick and easy to distinguish between what is part of C and what is yours.  This isn't a bad idea at all.

One last note while we are talking about getting started, is how to put comments in your code.  In COBOL you put a * in column 7 and then type whatever you want, or you can use the last 5 characters of each line to put something meaningful. C is a little like SPL in the way it deal's with comments.  Your comments must be enclosed in matching /* ... */, this can occur on a line with commands, by itself, or spread across lines.  Here are a few examples;

 /*  here is my comment  */
 /*
 here is another comment
 that spans multiple lines
 */
    a=b;  /* here is a comment on a line with a command */

That's all for this month, next month I will be covering variable declarations, and you would be amazed at how much text it is going to take to cover that topic.