cobol move statement - cobol

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.

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).

Is it possible to MOVE to a variable name created during runtime?

I am writing a program that changes the colour of a field if is it a duplicate record. To do this I am using a nested perform to compare each item to each other. When it finds a duplicate I would like to MOVE DFHRED to that specific field for example CRS1AC. My issue is that I don't know how to reference the field I am trying to change the colour of once I've found that is it a duplicate, how do I do this? Here are the fields which are in the MAP file that I am trying to move the colour to if a duplicate exists...
01 CRS1AC PIC X.
01 CRS1BC PIC X.
01 CRS2AC PIC X.
01 CRS2BC PIC X.
01 CRS3AC PIC X.
01 CRS3BC PIC X.
01 CRS4AC PIC X.
01 CRS4BC PIC X.
01 CRS5AC PIC X.
01 CRS5BC PIC X.
here is my table setup...
01 TABLES.
05 TBL-CRS-ENTRIES PIC S9(3) COMP-3 VALUE 5.
05 TBL-CRS-VALUES PIC X(4) OCCURS 10 TIMES.
05 CRS-TBL REDEFINES TBL-CRS-VALUES
PIC X(8) OCCURS 5 TIMES.
05 SUB-1 PIC S9(3) COMP-3 VALUE 1.
05 SUB-2 PIC S9(3) COMP-3 VALUE 1.
& here is the code that checks for duplicates
PERFORM VARYING SUB-1 FROM 1 BY 1 UNTIL SUB-1 > TBL-CRS-ENTRIES
PERFORM VARYING SUB-2 FROM 1 BY 1 UNTIL SUB-2 > SUB-1 - 1
IF CRS-TBL(SUB-1) = CRS-TBL(SUB-2)
*if there is a match it should change the colour to red.
* for example a match at CRS1AC & CRS1BC match CRS3AC & CRS3BC
*this is my attempt at trying make the variable name.
MOVE DFHRED TO CRS(SUB-1)AC
MOVE DFHRED TO CRS(SUB-1)BC
MOVE DFHRED TO CRS(SUB-2)AC
MOVE DFHRED TO CRS(SUB-2)BC
PERFORM 999-DUPLICATE-RECORD
END-IF
END-PERFORM
END-PERFORM.
GOBACK.
So, if 'PSYC 1000' = 'PSYC 1000' & the name of those fields are..
'CRS1AC+CRS1BC = CRS3AC+CRS3BC' <--- these are the fields I want to change the color of.
I've researched this heavily & still cannot find a solution.
Hope this makes sense I know its all over the place, for further clarification please ask & if complete program code is required I can provide it.
No, it is not possible to do what you want how you want.
COBOL is a compiled language. What is relevant about that is that you cannot make up the names of identifiers (variables) at run-time. Once a COBOL program is compiled, that is it, no more changes to the source for that executable version.
Where to go then?
You say this is part of your MAP.
01 CRS1AC PIC X.
01 CRS1BC PIC X.
01 CRS2AC PIC X.
01 CRS2BC PIC X.
01 CRS3AC PIC X.
01 CRS3BC PIC X.
01 CRS4AC PIC X.
01 CRS4BC PIC X.
01 CRS5AC PIC X.
01 CRS5BC PIC X.
But, because of those level-numbers of 01 those aren't part of anything, except the SECTION they belong to within the DATA DIVISION.
So you need to show your full, actual, MAP.
There is not an especially cute way, so what you have to do is REDEFINES the entire MAP, with an OCCURS which represents each screen-line for this portion of the screen (or entire screen, depends on the design) and define those attribute bytes within the OCCURS item.
What is really exciting about this is getting it all to line-up, by hand.
Now your program.
Your loops are wrong. You execute the inner-loop five times for each iteration of the outer-loop. Which means you are doing far more comparisons than necessary.
This is unwieldy:
SUB-2 > SUB-1 - 1
For that line of code, this would be better:
SUB-2 EQUAL TO SUB-1
The fifth outer-iteration is not required at all, because there are no values to compare to other than those which have already been compared (so the result will be the same, so why bother?).
Consider changing the definition of the identifiers (variables) you are using as subscripts and your total of entries to BINARY or COMP or COMP-4 (they all mean the same thing).
Consider giving them more meaningful names than SUB-1, SUB-2. It will make the code "read" better, which always helps.
Here's your data-defintion:
01 TABLES.
05 TBL-CRS-ENTRIES PIC S9(3) COMP-3 VALUE 5.
05 TBL-CRS-VALUES PIC X(4) OCCURS 10 TIMES.
05 CRS-TBL REDEFINES TBL-CRS-VALUES
PIC X(8) OCCURS 5 TIMES.
05 SUB-1 PIC S9(3) COMP-3 VALUE 1.
05 SUB-2 PIC S9(3) COMP-3 VALUE 1.
Some other things to make things easier for yourself:
Don't code identifiers (variables) after an OCCURS. It doesn't greatly matter in itself when there is no DEPENDING ON on the OCCURS, but since it does matter for that, why not be consistent (consistency is great, because when you are looking for a problem and you find inconsistency, it tells something about the writer of that particular bit of code).
Don't REDEFINES items which are defined with OCCURS. Even if you are using an old compiler (either you've put incorrect code here, or you are doing that) that gives you at least a Caution message. Try an experiment. Show that definition to a colleague, and ask them "what does this actually do?" Then show to another. And a third. If they all immediately reply, accurately, what it does, then you have a site with outstanding knowledge. You haven't, so don't do that.
Don't make identifiers signed, unless they can contain negative values. Then the reader can look at the definition and know it can't contain a negative value. Don't fall for "oh, we do it for performance". Name the compiler and show the compile options, and I'll show you what it is "gaining", or losing.
Don't use VALUE clauses for initial values of identifiers used as subscripts. Set them to their initial value before you use them. Unless you have tortuous code setting the value at the end of the current processing so it is ready for the next processing, all you are doing is confusing the human-reader. If there is a VALUE clause, it should be necessary.
Do give everything a good, descriptive, name, if it is being used. If something does not need a name, use FILLER to define it (often).
Your definition could be done like this:
01 some-meaningful-name
05 TBL-CRS-ENTRIES BINARY PIC 9(4) VALUE 5.
05 also-meaningful BINARY PIC 9(4).
05 meaningful-also BINARY PIC 9(4).
05 another-meaningful-name.
10 FILLER OCCURS 10 TIMES.
15 TBL-CRS-VALUES PIC X(4).
05 FILLER REDEFINES another-meaningful-name.
10 FILLER OCCURS 5 TIMES.
15 CRS-TBL PIC X(8).
Source code is for two things: for the compiler to convert into executable code; for the human reader to understand what has been coded. The compiler does not care about formatting the code. So format the code for the human reader. Even little things help:
IF CRS-TBL(SUB-1) = CRS-TBL(SUB-2)
Vs
IF CRS-TBL ( W-ORIGINAL-ITEM )
EQUAL TO CRS-TBL ( W-NEW-ITEM )

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.

Can't comment and other problems with 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

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