Can't comment and other problems with Cobol - cobol

Currently learning Cobol in a course in Uni and there are several errors to my code that simply baffles me.
1) I can't comment on anything pass line 1. I put the * in col7 and it still doesn't work.
2) There seems to be a problem with all of my IF statements that I can't pinpoint. Specifically, it keeps telling me what ELSE is doing there. Also the compiler keeps telling me that the variable 'ohour-ihour', or any variables I use in COMPUTE, doesn't exist.
It would be really helpful if anyone can point out what I'm doing wrong :(
02 IN.
03 ihour pic 99.
03 imin pic 99.
02 OUT.
03 ohour pic 99.
03 omin pic 99.
...
IF ihour<ohour
COMPUTE thour=ohour-ihour.
ELSE
COMPUTE thour=ihour-ohour.
END-IF.

One thing you can't do is use words which are "reserved", which mean something specific to COBOL, for user-defined names. An example from your code is IN.
There are few hyphenated reserved-words, so a good way to avoid accidental use (now or if added to the language later) is to not use "one word" user-defined names. In fact, it is good practice, as in most languages, to use good, descriptive, used-defined names.
Another problem in your code is the use of full-stop/period. The . you have used within an IF has terminated the IF, so the ELSE is invalid.
As mentioned, data-names are generally hyphenated through practice, - is valid in a user-defined name and is used in much the same way (conventionally) as other languages use _. So when you have written ohour minus ihour as ohour-ihour, you haven't actually done that, but you've used a user-defined name, ohour-ihour, instead, which obviously isn't defined.
02 some-nice-descriptive-name.
03 ihour pic 99.
03 imin pic 99.
02 some-othe-nice-descriptive-name.
03 ohour pic 99.
03 omin pic 99.
...
IF ihour < ohour
COMPUTE thour = ohour - ihour
ELSE
COMPUTE thour = ihour - ohour
END-IF
.
Try the above instead. Only use full-stop/period where needed. Review COBOL questions here to get some ideas of common advice, practice and style.
You haven't included an example of the failing comment, so I can't comment on that. Show an example, and let us know compiler and OS.

Try to use *> to comment line instead of *.
The asterisk character is can be used only in fixed format on column 7.
It seems you are not using fixed format but free format. So you have to use combination of two characters *> as it is written in COBOL standard. Pages 22 and 23
http://www.cobolstandard.info/wg4/open/WD1-10-pdf.zip
or see:
http://www.opencobol.org/modules/newbb/viewtopic.php?topic_id=612&forum=1

Related

Decode a Binary Coded Decimal

I have a field pic X(03) with a date in it as X'160101' format yymmdd.
I will like to know how to convert it to pic x(06).
So far I tried to move it back to a 9(03) comp and move the
9(03) comp to a 9(06) but it didn't work.
How can I do this?
What you have is a Binary Coded Decimal (BCD). That is, the data is held in a binary field, but it is the decimal representation, not the binary, which is important for the value. X'160101' in would be 1,442,049. X'160201' would be 1,442,305. So if you were able to treat it as a binary field (you'd have to prepend a binary zero to make it the correct length for a binary field) you'd have to do some silly calculation.
So you do something different, and easier. BCD is not a native COBOL datatype. PACKED-DECIMAL (often the same as COMP-3/COMPUTATIONAL-3) is a BCD-type which includes a sign-value in the low-order (right-most) half-byte. So not quite a BCD, but you can treat your BCD as PACKED-DECIMAL like this:
01 BCD-TO-PACKED.
05 BTP-SOURCE-BCD PIC XXX.
05 BTP-PACKED-ZERO PACKED-DECIMAL PIC 9 VALUE ZERO.
01 FILLER
REDEFINES BCD-TO-PACKED.
05 BTP-PACKED-TO-MOVE
PAKCED-DECIMAL PIC 9(6)V9.
01 DATE-AS-PIC-X PIC X(6).
01 DATA-AS-CHARACTER-NUMERIC
REDEFINES DATE-AS-PIC-X PIC 9(6).
MOVE your-source-value TO BTP-SOURCE-BCD
MOVE BTP-PACKED-TO-MOVE TO DATA-AS-CHARACTER-NUMERIC
After that you can happily reference DATE-AS-PIC-X to do whatever you want with it.
BCD-TO-PACKED is a four-byte group field which, through the VALUE clause and through nothing ever changing, has, in the last by X'0F'. That's an unsigned packed-decimal field with one digit and a value of zero.
Then you do the X-to-X MOVE for BTP-SOURCE-BCD. BCD-TO-PACKED now looks like this: X'1601010F'. Which is perfectly valid for a packed-decimal field. You could divide that by 10 to get your date (REDEFINES it as PACKED-DECIMAL PIC 9(7)) but why waste CPU?
Instead, in the REDEFINES you define one decimal place (V9). When the compiler generates the code to MOVE that to another numeric field with no decimal places, the source decimal place(s) are just dropped off. Presto! Divide by 10 without dividing.
Note: The data-names chosen are to aid the explanation. You should make yours meaningful to the data, not just use "trite" names. "Character numeric" is called USAGE DISPLAY in COBOL, it is the default if a USAGE is not supplied. The word USAGE is rarely used itself. So USAGE DISPLAY is what you have when there is a PIC X or PIC 9 field with no other usage.
Note: You should probably not be using two-digit years. You won't be able to deal with dates earlier than 2000 or later than 2199. Historical use of two-digit years was due to expensive disk storage and "data redundancy" (all century values were 19, so why hold the value 19 80 different times for the same account). If using two-digit years, ensure that there is something somewhere which is relevant to the century.
Note: If you attempt to MOVE a PIC X field to a numeric field, the compiler will assume that you have valid character numbers in the field, which is one reason your original attempt failed.
If you search stackoverflow, you should find the answer (this has already been answered).
But Create a fields like (my-date-x holds the date):
03 my-date-x pic x(3).
03 my-date-9 pic 9(6).
03 date-ymdv0 pic 9(6)v9 comp-3.
03 date-x pic x(3) redefines date-ymdv0.
And the code is
Move 0 to date-ymdv0
Move my-date-x to date-x
Move date-ymdv0 to my-date-9
The reason it works is for 9(6)v9 comp3 160101 is stored as x'1601010c'
which is what you have (+ a 0c at the end).

How to use file descriptions in cobol?

I have seen in some of the tutorials that the records are declared only in file description(FD) and in some tutorials they have declared the record in Working storage section and used it.What is the difference between the both.
In some programs it is like this
FD STUDENT
01 FS-EMP-REC.
02 FS-EMP-ID PIC X(07).
02 FS-EMP-NAME PIC X(20).
02 FS-EMP-ACCT PIC X(06).
01 WS-EMP-REC.
02 WS-EMP-ID PIC X(07).
02 WS-EMP-NAME PIC X(20).
02 WS-EMP-ACCT PIC X(06).
In some tutorials it is (FD alone)
01 FS-EMP-REC.
02 FS-EMP-ID PIC X(07).
02 FS-EMP-NAME PIC X(20).
02 FS-EMP-ACCT PIC X(06).
What is the difference?
It can be a question of coding style. Some people just always use READ ... INTO ... or do a MOVE of the 01 under the FD to an 01 in the WORKING-STORAGE. Often the 01 in the FILE SECTION will just be defined with an elementary FILLER to describe the length of the input record.
Sometimes there is a specific need to do this, if the particular COBOL being used limits the use of the data in the FD (in Enterprise COBOL you can't SET an address for something in the FILE SECTION, and DB2 requires a known address, so can't be in the FILE SECTION, for instance).
People tend to think it is "safer" to use the WORKING-STORAGE, but this is not the case. People also think it easier to locate information in the WORKING-STORAGEwhen a program fails.
The READ ... INTO ... requires an extra transfer of the data, so will be "slower", but that is only a problem in extreme situations.
You'll see both in programs, as you already have done, and there is no hard-and-fast answer as to why one program uses on, and another the other. Mostly it will just make no difference at all.
With READ ... INTO ... the record will still also be available in the FILE SECTION.
Unless necessary, I don't use READ ... INTO ... myself, but many people think programs won't work properly if you don't use it :-)
Just be aware of the two different ways, and use the way that those you are coding with use.

How to assign a field inside a nested record in COBOL

I'm quite the noob on COBOL i bought myself one of those "for dummies" type book but it lacks some depth.
I'm trying to assign and retrieve the value of a field from a nested record. I'm trying per my book suggested, this :
WRITE REPORT-LINE FROM DATE OF HEADER
AFTER ADVANCING PAGE.
WRITE REPORT-LINE FROM INSTITUTION OF HEADER
AFTER 1.
WRITE REPORT-LINE FROM BRANCH OF HEADER
AFTER 1.
WRITE REPORT-LINE FROM DIVISION OF HEADER
AFTER 1.
WRITE REPORT-LINE FROM FILLER-LINE
The layout for my header is this one:
01 HEADER.
02 DATE.
03 O-MONTH PIC ZZ.
03 FILLER PIC X(01) VALUE '/'.
03 O-DAY PIC 99.
03 FILLER PIC X(01) VALUE '/'.
03 O-YEAR PIC 99.
03 FILLER PIC X(116) VALUE SPACES.
03 PAGE PIC A(4) VALUE 'PAGE'.
03 FILLER PIC X(1) VALUE SPACE.
So basically my question is, How for example will I access 0-DAY field of the record DATE from HEADER?
Both for assignment and retrieval. Will it be something like:
MOVE 21 TO 0-DAY OF DATE OF HEADER.
Firstly avoid data-names which are "words". DATE for instance is a word, SOMETHNG-DATE or DATE-SOMETHING are not.
DATE itself is a Reserved Word in COBOL, so I think it unlikely that your example will compile. A word like HEADER could easily become reserved in the future (although these days the standards committee try to avoid that).
HEADER is a group-item. DATE is a group item. The other fields are elementary items. We don't regard structures such as this as "nested", just as group-items which must contain at least one elementary item.
The only time you need to use OF/IN is when there are non-unique names (which you should avoid).
So:
MOVE 21 TO 0-DAY
Will work, as long as 0-DAY is not a duplicate name. The syntax you showed will also work, but why add all the extra for no point, it is just increasing the possibility of a typo, and making the next reader think that your program has non-unique names.
Try to avoid full-stops/periods in the PROCEDURE DIVISION except for those which are necessary (after the PROCEDURE DIVISION header, before a paragraph/SECTION after a paragraph/SECTION label, before the end of the program).

cobol move statement

say i have one 02 level variable as a part of cobybook (testcopy)
02 level-1-var
05 var-1
05 var-2
05 var-3
05 var-4
I use this copybook twice in my program.
01 usage-1.
copy testcopy.
01 usage-2.
copy testcopy.
I now want to move only 2 level 05 varibale of usage-1 to usage-2.
is there any way i can avoid 2 move statements?
and use something like
MOVE (var-2, var-3) of usage-1 TO
(var-2, var-3) of usage-2
I am new to cobol and was wondering if this could be done.. this can save a lot of move statements in my program..(improve performance)
No, not in standard COBOL, although some implementations may well have extensions for that sort of thing. If concise code is one of your requirements, I probably wouldn't have picked COBOL as the ideal language :-)
You probably need to do it in two:
move var-2 of usage-1 to var-2 of usage-2.
move var-3 of usage-1 to var-3 of usage-2.
If you're willing to do a bit of a change to your copybook, something like (a):
02 level-1-var
05 var-1
05 var-2-and-3
09 var-2
09 var-3
05 var-4
you may find that you can then do it with:
move var-2-and-3 of usage-1 to var-2-and-3 of usage-2.
(a) Obviously, I've just mirrored what you had in the question. You'll almost certainly need pic clauses on that data (and probably some more . characters).
This type of requirement is directly answered by the MOVE CORRESPONDING verb. MOVE CORRESPONDING takes group levels for its operands and moves like-named elementary items from one to the other, with several restrictions, which include like data classes (i.e., no mixed alphanumeric and numeric). The Fine Manual for your implementation contains all the restrictions.
If I remember correctly, MOVE CORRESPONDING is also an optional feature, so some compilers may not support it.
MOVE CORRESPONDING and your request is one of those things that triggers strong opinions in the COBOL world. Some say that you should use COPY REPLACING to generate unique data names and code all the MOVEs. Others say what you are doing is fine. My view is that "it depends". If it's a very simple program, I might take the MOVE CORRESPONDING path, but if there is significant business logic, then I would rather code everything.
Your best bet is to make your copybook such that you can have a "prefix" for each field, and then use REPLACING to provide different prefixes for the different COPY statements. Then you don't have to code OF/IN for all the fields, and it will make the program and the listing clearer.
Paxdiablo's is the neatest way to do what you want, although the reason you want to do it would have been interesting.
I'm surprised no-one mentioned "reference modification":
MOVE usage-1 ( 3 : 5 ) TO usage-2 ( 3 : 5)
Where 3 is the start position in the data and 5 is the length. I much prefer Paxdiablo's defintion to this.
Not so surprised that no-one suggested RENAMES.
01 A-TABLE.
05 A-T-1 PIC XX.
05 A-T-2 PIC X.
05 A-T-3 PIC 9.
05 A-T-4 PIC XXX.
05 A-T-5 PIC X(4).
66 A-TABLE-EXTRA RENAMES A-T-2 THRU A-T-3.
01 B-TABLE.
05 B-T-1 PIC XX.
05 B-T-2 PIC X.
05 B-T-3 PIC 9.
05 B-T-4 PIC XXX.
05 B-T-5 PIC X(4).
66 B-TABLE-EXTRA RENAMES B-T-2 THRU B-T-3.
MOVE A-TABLE-EXTRA TO B-TABLE-EXTRA
Like the MOVE CORRESPONDING, this is to be avoided (same reasons as my comment, plus no-one uses Level 66's, so no-one knows what they do).
Another way is by REDEFINES for each of your Level 01s, but why even go to that bother.

COBOL keyword REDEFINES

May I ask, what is the usage of the keyword REDEFINES in COBOL?
I can not understand the manual's definition.
What is the meaning of the following code?
01 WS_CHARGE_TXT_8X PIC X(08) VALUE "10000000".
01 WS_CHARGE_NUM_8 REDEFINES WS_CHARGE_TXT_8X.
05 WS_CHARGE_8 PIC 9(05)V9(03).
Thank you!
Basically Redefines reuses the spaces so in the above example WS_CHARGE_TXT_8X and WS_CHARGE_8 will point to the same block of memory. This allows you to look at a block of memory in different ways, in this case the variable can be viewed as a text PIC X and a signed numeric PIC S9. The -8X to -8 in the variable name is just stylistic to indicate the variable is being recast to another type or format to other programmers.
In the above example
the value of WS_CHARGE_TXT_8X is
"10000000"
the value of WS_CHARGE_8 is
of 10000.000.
If you moved 123.456 to WS_CHARGE_8 the value of WS_CHARGE_TXT_8X "00123456".
A more useful example is
03 Birth-Date-YYYYMMDD pic 9(8).
03 filler redefines Birth-Date-YYYYMMDD.
05 Birth-Date-YYYY pic 9(4).
05 Birth-Date-MM pic 99.
05 Birth-Date-DD pic 99.
In this case you can access the whole date Birth-Date-YYYYMMDD or the year / month / day individually (Birth-Date-YYYY etc).
It is analogous to union in 'C'.
It saves working storage space, and MOVE statements, and is also useful for transposing arrays of PIC(X), or accessing repeated fields as an array.
In the OP's case a numeric "type" is being created for the char contents of the prototype field.
A REDEFINES allows a different data description for storage which has already been defined.
That might be to allow entirely different data to be held there.
05 RL-AGENT-DATA.
...
05 RL-CUSTOMER-DATA REDEFINES RL-AGENT-DATA.
...
Or to give a description which allows a use of a part of the data, as in Bruce's example.
Or to use a piece of data that is the same, but for a different purpose:
05 INPUT-AMOUNT PIC X(10).
05 INPUT-AMOUNT-NUMERIC REDEFINES PIC 9(8)V99.
Whatever is in INPUT-AMOUNT it can be reported without problem, but only if it is a valid numeric (by testng it for NUMERIC), is INPUT-AMOUNT-NUMERIC used for some purpose.
Note that each 01 subsequent to the first under an FD is an "implicit REDEFINES".
Note also that items in the LINKAGE SECTION have the effect of "redefining" "something", even though if the address of the data is from a CALLing program, the definition is often the same as the original definition, and should usually at least match the PICtures of the original.

Resources