IBM Mainframe Forum Index
 
Log In
 
IBM Mainframe Forum Index Mainframe: Search IBM Mainframe Forum: FAQ Register
 

Setting Address of FD record to a Pointer in Working storage


IBM Mainframe Forums -> COBOL Programming
Post new topic   Reply to topic
View previous topic :: View next topic  
Author Message
vishalbshah

New User


Joined: 01 Dec 2006
Posts: 61
Location: Pune

PostPosted: Wed Apr 04, 2012 6:06 pm
Reply with quote

Hi,

I am having a batch process which writes a File (OPEN mode OUTPUT).
There are some details which are to be written by a Called sub-module.

I want to pass address of FD record to sub-module. I tried using a working storage pointer and passed the same in the interface, but when I am using below statement :

SET WW-POINTER TO ADDRESS OF FSU-INPUT-RECORD (FD record at 01)

I am getting below compilation error:

"ADDRESS OF" operand "FSU-INPUT-RECORD" was found as the sending operand of a "SET" statement, but was not a "LINKAGE SECTION", "WORKING-STORAGE SECTION" or "LOCAL-STORAGE SECTION" item, or was a level-66 or level item.
The statement was discarded.

Can someone please, explain why we can not set an ADDRESS OF a record under FD to another variable in LINKAGE or get it in a working storage pointer ?
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Wed Apr 04, 2012 7:16 pm
Reply with quote

Code:
FD blah-blah.
01  RECORD-SUBORDINATE-TO-FD.
    05  FILLER PIC X(20).

CALL "PROGA" USING RECORD-SUBORDINATE-TO-FD ...


Why do you feel the need to mess around with pointers?

EDIT: And why wasn't this posted in the Cobol forum?

Further EDIT: Referring to your closing line, because that is the way they have defined it for the compiler. Why that, you'd have to do your own digging. Speculation? Cos people think they have to use pointers all the time :-)
Back to top
View user's profile Send private message
vishalbshah

New User


Joined: 01 Dec 2006
Posts: 61
Location: Pune

PostPosted: Wed Apr 04, 2012 7:27 pm
Reply with quote

Hi Bill,

Thanks for the reply, it makes sense.

I want to understand the fundamental difference between FD record and Working storage or Linkage Record.

Working storage has a memory address in Program main Memory

Linkage Section gets address from whether calling module or from other Pointer.

When we read a file does the FD record gets address in main memory or it is Buffer ?

When we write a record does FD record hold an address in Main memory or it is a buffer ?

I am trying to understand when and how does the FD record gets and address and if it gets an address why we can't assign the same address to a different variable in Linkage or pass it to any of the pointer ?
Back to top
View user's profile Send private message
Robert Sample

Global Moderator


Joined: 06 Jun 2008
Posts: 8700
Location: Dubuque, Iowa, USA

PostPosted: Wed Apr 04, 2012 7:38 pm
Reply with quote

When you read or write a file, the data is in the buffer -- which, in turn, is in memory controlled by the operating system, NOT by your program. Since this memory is controlled by the operating system and not by your program, I suspect that's the reason you cannot use the buffer address in a SET statement. The buffer is allocated in memory when the file is opened. However, the buffer memory does not have data until you read a record or until you move data to it for a write (either directly via a MOVE or indirectly via WRITE ... FROM).

But the short answer is -- the compiler won't let you do it, so find another way. The reason why doesn't really matter.
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Wed Apr 04, 2012 7:39 pm
Reply with quote

The current record is sitting in memory "somewhere". Depending on code used and compiler options that might be in a "buffer" or a "record area".

Definitely for a buffer the problem is this: You read another record, the address of the 01 subordinate to the FD changes, but nothing is going to take the time to re-establish the address in a pointer.

This can't happen with W-S.

This can happen with the Linkage Section, but the validity of an address is down to the programmer and the system is not going to up and change it.

OK. There are nuances with all of the above. For instance, if you CALL with the 01 subordinate to an FD you could set the address of the linkage section item to a pointer, so you'd get a pointer to the 01 under an FD - and it's value wouldn't be any use after the next IO associated with that FD. I'd avoid it unless there was an absolute specific need for it which couldn't be handled in another, clearer, way.

As I say, if you want to find out the real reason presented publicly for this, you'll probably have to do your own digging. "POINTER" came to Cobol at some time, and at some time IBM adopted that and either went with a "standard" or "non-standard" implementation of it. "Somewhere" this is recorded in some shape or form.

If you are trying to achieve something specific, let us know and we can see about suggestions.
Back to top
View user's profile Send private message
Bill O'Boyle

CICS Moderator


Joined: 14 Jan 2008
Posts: 2501
Location: Atlanta, Georgia, USA

PostPosted: Wed Apr 04, 2012 8:00 pm
Reply with quote

Generally speaking, POINTERS used by Cobol programmers needs to be approached with caution as they may be foreign to new Coboler's, such as those migrating from JAVA because JAVA doesn't offer this ability (at least, the last time I looked).

Unless you fully understand the concept of POINTER's (similar to memory-addresses in Assembler), it may not be such a good idea to pursue their usage.

Beginning with COBOL II V4, POINTER's were introduced to Cobol. But, using the ADDRESS OF concept was only available to 01 and 77 Linkage Section items. It wasn't until OS/390 Cobol 2.2.1 was addressability to Working-Storage items introduced as well a non-01 and non-77 level Linkage items.

Prior to 2.2.1, you'd have to use a rudimentary Sub-Program to establish addressability to any WS item as well as non-01 and non-77 Linkage items.

These Sub-Programs were very common and were either written in a HLL or Assembler and are probably being used to this day, even in shops that are using 2.2.1 or greater because, as the old saying goes, "If it ain't broke, don't fix it", prevails with wisdom. icon_wink.gif
Back to top
View user's profile Send private message
vishalbshah

New User


Joined: 01 Dec 2006
Posts: 61
Location: Pune

PostPosted: Wed Apr 04, 2012 8:10 pm
Reply with quote

Hi Guys,

Thanks for the reply.

I think it matches with my initial understanding of Address for FD, Working Storage and Linkage Sections.

In our project we have long chain of Call modules and we use Pointers in the interfaces ( sometimes Pointer to Copybook which has list of Pointers!) instead of bulk of data to transfer like a request or response (could go up to 1000000 bytes).

For me it is important to understand which Data I have pass as it is as a Bulk (FD record in this case) and for which ones I could just pass a pointer.

I think from above discussion I could understand that Buffer area keeps on changing after every read , in my case I am writing a file so would expect Buffer area for FD record to remain same till File gets closed and reopened.

But it is the fact that as we can Move the data To and From this Buffer (FD record) doesn't actually qualify it for passing its address to another variable.

I am taking it as a Compiler's precaution to avoid any mishaps (SOC4 etc.) rather than anything else as this is just like any other memory area which got to have the address and programs should be able to access it infact "Move" already does the same.

Please, correct me if I am wrong!
Back to top
View user's profile Send private message
Robert Sample

Global Moderator


Joined: 06 Jun 2008
Posts: 8700
Location: Dubuque, Iowa, USA

PostPosted: Wed Apr 04, 2012 8:20 pm
Reply with quote

Quote:
in my case I am writing a file so would expect Buffer area for FD record to remain same till File gets closed and reopened.
You are absolutely wrong here. The buffer area is filled, and once written (via a COBOL WRITE) a new buffer is used for the next record. Hence the buffer address changes with every record. Depending upon the DCB characteristics, the number of buffers being used can vary -- DCB=BUFNO=5 is the default for QSAM files, but can be changed. The buffers get reused after all of them have been filled, but you don't necessarily know when that occurs.
Back to top
View user's profile Send private message
Bill O'Boyle

CICS Moderator


Joined: 14 Jan 2008
Posts: 2501
Location: Atlanta, Georgia, USA

PostPosted: Wed Apr 04, 2012 8:21 pm
Reply with quote

Unless the sub-programs being used in your shop are returning the address of a Linkage or WS item, when a sub-program is called and it's passed a CALL USING "parm, parm" and when it receives control, the parms that had been passed resolve as individual addresses, not the data itself.

So for example, if you have three parms, each being 1M in length, when the sub-program gains control, the only thing that it knows about is an Address, used to establish addressability to an 01 Cobol Linkage area or (in Assembler), a DSECT.

This is a concept not fully understood by many Newbies/Freshers. Perhaps (and I'll raise this again) is due to their prior or current JAVA background?
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Wed Apr 04, 2012 10:35 pm
Reply with quote

vishalbshah wrote:
Hi Guys,

Thanks for the reply.

I think it matches with my initial understanding of Address for FD, Working Storage and Linkage Sections.

In our project we have long chain of Call modules and we use Pointers in the interfaces ( sometimes Pointer to Copybook which has list of Pointers!) instead of bulk of data to transfer like a request or response (could go up to 1000000 bytes).

For me it is important to understand which Data I have pass as it is as a Bulk (FD record in this case) and for which ones I could just pass a pointer.

I think from above discussion I could understand that Buffer area keeps on changing after every read , in my case I am writing a file so would expect Buffer area for FD record to remain same till File gets closed and reopened.

But it is the fact that as we can Move the data To and From this Buffer (FD record) doesn't actually qualify it for passing its address to another variable.

I am taking it as a Compiler's precaution to avoid any mishaps (SOC4 etc.) rather than anything else as this is just like any other memory area which got to have the address and programs should be able to access it infact "Move" already does the same.

Please, correct me if I am wrong!


As Mr Bill has said, only addresses are passed from calling to called program.

In the Cobol program you could define a 100 meg table, "pass" the table to the called program - all the called program would "receive" would be an 8-byte address. It is then up to the called program to "map" the 100 meg of data correctly. There is nothing to indicate the layout, or even the length, of the data that is communicated between caller/called program.

Robert has covered the write. Yes, mostly your address for the 01 will be changing each time you write. I have no idea what you mean by "doesn't actually qualify it for passing its address to another variable".

The MOVE does not come into it. Your Cobol program has the (changing) address of the record area/position in buffer for that FD. Any MOVEs related to the FD subordinate items of any sort is done by a displacement from the address of the start of the current record and the compiler "cleverly" keeps itself informed of the position of records in storage.

I do not know why you can't use pointers for the FILE SECTION. As I have said, if you really want to find out, you'll have to do your own research. Speculation based on nothing won't do it.

The reason you seemed to want to know in this case has evaporated now that you are aware that "passing data" between Cobol programs on an IBM mainframe is no more than passing addresses.

If you have a different purpose in mind, let us know.
Back to top
View user's profile Send private message
Peter cobolskolan

Active User


Joined: 06 Feb 2012
Posts: 104
Location: Sweden

PostPosted: Thu Apr 05, 2012 12:53 am
Reply with quote

The solution to the problem is not pointers!
The FD can be defined as EXTERNAL, and has to be defined in both programs with this attribute and same name.
With this in place, one program can Read, another can Write a.s.o. If you handle File Status in your program, declare the variable on 77 or 01 level and mark it as External.
The record description following the FD can, if you like, have different names.
Also note that 77 and 01 elementary data items and 01 Group Items can have this attribute, must be declared with same name in the programs, and are in reallity the same physical memory and easilly shared.
More to find out in the manual!
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Thu Apr 05, 2012 3:42 am
Reply with quote

Quote:
I am having a batch process which writes a File (OPEN mode OUTPUT).
There are some details which are to be written by a Called sub-module.


I suppose it comes to what we make of this in the context of the rest of the initial post.

I think this means "I have a called Cobol module which needs to access the current record on the file xyz" in the context of the rest of the post, which is only mentioning the 01 level, so surely can't be actually to do with writing a file from a different module.

I can't say I'm keen on the idea of distributing io functions across multiple modules through the use of GLOBAL. I can't think why a good design would make that a good idea. To add it to a bad design would compound existing problems, probably.

I'm perfectly happy to be shot down on this, if someone can argue it well, but it doesn't sound like a good idea to me for a typical (if there is such a thing) mainframe Cobol batch system.
Back to top
View user's profile Send private message
dbzTHEdinosauer

Global Moderator


Joined: 20 Oct 2006
Posts: 6966
Location: porcelain throne

PostPosted: Thu Apr 05, 2012 5:05 am
Reply with quote

well, the idea of external or global was made for those who do not understand modular programming.

TS has done a poor job of describing the process.

if both main and submodule write to the file,
it would seem logical to have 1 submodule that would write to the file.

if the ts is too inexperienced to handle that,
he should stick with passing data down to the submodule and then upon completion of the CALL,
the mainmodle should interrogate the the submodules supplied data
and write that to the file.

as far as passing the FD, he can't do it because ibm will not allow him to do it.
the absolute (as well as the relative) address of the current record (in the buffer)
changes with every write.

If the TS was an experienced programmer,
he would us the work-area option on all I/O (wager he doesn't)
and then the passing of the data would not be a problem. (he could set a pointer to the working-storage area).

as Bill mentioned, for VS COBOL and COBOL II, it required a submodule
purpose of which was to set the address of a linkage item pointer to the address of a linkage item.

E-COBOL did away with the restrictions and we can set pointers for nearly everythig,
except FD 01's, probably because they would require a reSET after every i/o.
and since ibm strongly suggests that the work-area option be used with file i/o, (RTFM!)
and there are no restrictions for pointers and working-storage,
ibm sorta solved the problem the idiot that started this topic has stumbled into.
again, the boys from the tin cans worry incessantly about memory,
and even though most of the time the fault is with leakage and other
pisspoor programming,
memory is not that big a problem on the mainframe,
certainly not enough to warrant reading and writing in the buffer,
especially when you don't have a clue as to what is going on

i employ pointers prolifically, only problem is the amount of training
that i must invariably provide
to a majority of any programming staff for which i have a contract.

as far as global is concerned,
that is something that cobol was forced to incorporate due to the tin cans and their programming methods/languages.
(it seems the boys from the little boxes do not understand addressing)

even though it is all addresses and passing the addresses,
it seems it is an easier concept to say global,
and any data that is so marked,
is accessable to any module who wants to address that data using the "GOBAL" syntax.

as far as Bill W's comment is concerned, i totally agree with him,
this is just a piece of shit program and the 5lbs bag has him stumped.
modular programming means each module has a function to perform,
it does not mean that each module should be capable of the same i/o.
but that is a sermon for another time.
Back to top
View user's profile Send private message
Peter cobolskolan

Active User


Joined: 06 Feb 2012
Posts: 104
Location: Sweden

PostPosted: Thu Apr 05, 2012 9:46 am
Reply with quote

Comment on Global attribute.
- The Global attribute makes a FD global within the same load-module, but in embedded programs, either directly contained or indirectly contained, which is one (1) load-module and "programs-in-programs" and the FD is specified once.
- The External attribute makes an FD common/accessible to programs in different load-modules, that have descibed the FD with external attribute, in the same run-unit, but Not in embedded programs.
Back to top
View user's profile Send private message
vishalbshah

New User


Joined: 01 Dec 2006
Posts: 61
Location: Pune

PostPosted: Thu Apr 05, 2012 11:54 am
Reply with quote

Guys,

I appreciate your help and suggestions!

The reason why we use Pointer explicitly in the interface is to avoid having to code a long list of USING variable as well ....

we not only Pass the request and response between modules but also pass address of cached parameters which any of the called modules can search.

Let me give an example....

we deal with customer data (sending and receiving). The request for data could be fulfilled via accessing various tables.

we cache the parameters in memory (pointers of those are in interface) and search them as and when required to know which module to invoke to get the next set of requested data.

Now in this already established environment we have been give a task to produce a batch file which contains a customer details, built by information available on various tables so in this case we need to invoke modules to write a single record of the output file.

The problem is the interface between programs is fixed and allows Filler for pointer (4 characters).

I was planning to use it to hold pointer of FD record so that even Called modules could populate some of the customer details in it and finally I could write in the new module.

Alternatively, I will have to define a new interface for every detail and would need to pass the address of that in the Interface from every module.

I want to avoid more changes.....

Waiting for your suggestions !!!
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Thu Apr 05, 2012 1:29 pm
Reply with quote

What is the purpose of this?

Quote:
avoid having to code a long list of USING variable as well


There can be "good" reasons for doing this and "bad" reasons for doing this. Just wondering if you know why in your case.

Terminology is important if you are going to use it.

"Cached" doesn't mean, in a terminology sense, what you think it does.

"characters" doesn't really describe your 4-byte-long filler.

The answers you are seeking are in dbz's post, but we can't tell which part as you are still unclear about what is going on.

Presumably you main program has a driver file. You mention "tables" so let's assume that DB2 is involved along the way.

Now, where does the file you want to write to come into it? You want to write to it "in more than one module" or you want to have access to an input record "in more than one module"?

Just to run something by you again. One of those tiresome things on the CALL USING works like this. The address of the item is stored in a particular place by the calling program. The called program picks up the address from a particular place solely on the basis of the order of items on the PROCEDURE DIVISION USING, first on call using address is first on procedure division using, etc. No other information is passed about the data. No length. No description. Nothing. Nothing is moved around. The "matching up" of the data items is down to the programmers writing the code. The description of the data in the called program is down to the programmer writing it (though often a copybook).

Understand this fully and you'll realise that what you say about your "interface" is not relevant.

Quote:
I want to avoid more changes.....


Then the system should be designed (properly) in the first place.

If you have to wedge something in later, sometimes that takes (a lot) more effort.

Remember than number one priority is getting it right. Number two is getting it right when it is maintained. Don't try anything so "clever" that you clobber the next person along, even if it is just spending hours working out what is going on. At 3am, that is not good. You spend the time now, and do it properly, not just in a way to avoid things...
Back to top
View user's profile Send private message
dbzTHEdinosauer

Global Moderator


Joined: 20 Oct 2006
Posts: 6966
Location: porcelain throne

PostPosted: Thu Apr 05, 2012 2:28 pm
Reply with quote

use the work-area option for the file i/o in mainmodule
and set pointer to address of work-area.

suggest you consider another line of work.
thinking logically and building from simple concepts seems to be a stumbling block of yours.
Back to top
View user's profile Send private message
vishalbshah

New User


Joined: 01 Dec 2006
Posts: 61
Location: Pune

PostPosted: Thu Apr 05, 2012 5:51 pm
Reply with quote

Guys,

I got that even if I SAY CALL USING WW-REC it is only tht eaddress of WW-REC which is getting transferred.

The reason we are using Pointers is we have a very long list of Parameters and Data to be passed between modules

Don't want to write CALL USING WW-REC1, WW-PRM1, WW-PRM2, WW-PRM3..... and Same in PROCEDURE DIVISION USING ......

ok, let me put the exact situation once again.

we are building core software for entity which has multiple regional instances.

The way we build the software is allowing regional Plug-in to fit in the process to cater for regional functionality.

As the interface between Regional and Core could vary from one functionality to the other there is standard interface containing pointer for Interface (both eh Regional and Could)

Now I am writing a program which prepares file with customers details:

1) Individual Details (Customer no, DOB, Birthplace etc.)
2) Document Details ( Passport, Licence etc.)
3) Address Details (Home, Correspondence etc.)
4) Transaction Details (Payments)

The way we want to design it the details 1 ,2 & 3 are in Core software but the Transaction details varies from region to region.

Transaction details may be present in one region it may not be in other region it is entirely up to the regions.

As my File record consist of all 4 segment out of which 3 I can build from Core module and for the 4th segment I need to invoke regional module.

So, I need to allow the Regional Module the access to the FD record (i.e. pointer) I can't pass the FD record as it is in the interface because the Interface between Core and regional Module is fixed and I can't change it.

Now, keeping this situation in mind please suggest me how should I design my Core module such that it allows Regional Module to Add Transaction details to the FD record and when the control comes back to the Core module it can Write the file from that FD record.

Alternatively I could define a new Copybook for Transaction Details and pass the address of that in the strandard Interface and get it populated in the Regional Module. Once the control comes back i am moving the fields from this to FD and then Writing the record.

Hope this explains why I am keen on pointer rather than whole FD record being passed between Core and Regional Module.
Back to top
View user's profile Send private message
dbzTHEdinosauer

Global Moderator


Joined: 20 Oct 2006
Posts: 6966
Location: porcelain throne

PostPosted: Thu Apr 05, 2012 7:51 pm
Reply with quote

i reiterate, you need to find a new job category.
something that does not require thought, listening, comprehension or logic.

we never said that you should abandon the pointer concept
(well, yes we did when we found that you lack in skills and knowledge)
but we suggested ways to incorporate this new concept into your existing pointer.
you can not address the FD 01 level with a Pointer.
you have to use work-area option on the write
and to these work-areas (defined in working-storage) you can address with pointers..

you need four structures in working storage to resemble the four different records in you file.

set pointers to the address of each structure.

let the untermodule(s) populate these structures at will.

you need four writes
write record from work-area1
write record from work-area2
write record from work-area3
write record from work-area4

if the four structures differ in length,
you need to define your file as variable length,
and have either:
four 01 levels in you FD, each with an appropriate length
or
a structure that varies from ? to ? depending on work-area-length

happy easter.
Back to top
View user's profile Send private message
Nic Clouston

Global Moderator


Joined: 10 May 2007
Posts: 2454
Location: Hampshire, UK

PostPosted: Fri Apr 06, 2012 3:27 pm
Reply with quote

It seems to be an architectural thing and can only be resolved by talking it out between the members of your team. We can only generalise and give hints and tips but your team are the ones who know the system and all its ins and outs.
Back to top
View user's profile Send private message
View previous topic :: :: View next topic  
Post new topic   Reply to topic View Bookmarks
All times are GMT + 6 Hours
Forum Index -> COBOL Programming

 


Similar Topics
Topic Forum Replies
No new posts Copy only TEXT or String from a record SYNCSORT 4
No new posts combine multiple unique records into ... DFSORT/ICETOOL 2
No new posts SORT on detail record, then repeat he... DFSORT/ICETOOL 3
No new posts how to complete the end of a record w... DFSORT/ICETOOL 2
No new posts Sort based on the record type DFSORT/ICETOOL 1
Search our Forums:

Back to Top