Cobol - question.
I have a written a sub-program with some procedures.
Is it possible to call this sub-program from different main programs at the same time passing all different variables.
Yes. You can call this subprogram from any main program. When you say different parameters, use USING clause to pass the corresponding values required for that particular sub program.
Off course you can call subprogram any time in main program. Subprogram will perform its function every time by accepting whatever parameters passed.
Related
It's not "Parameter" or "Argument", but "variable function" and "variable arguments", "variable number of arguments". I found this confusing and want to know what are these things.
I found it inside Programming in Lua First Edition 5.1
An important use for unpack is in a generic call mechanism. A generic call mechanism allows you to call any function, with any arguments, dynamically. In ANSI C, for instance, there is no way to do that. You can declare a function that receives a variable number of arguments (with stdarg.h) and you can call a variable function, using pointers to functions. However, you cannot call a function with a variable number of arguments: Each call you write in C has a fixed number of arguments and each argument has a fixed type. In Lua, if you want to call a variable function f with variable arguments in an array a, you simply write
That paragraph is rather sloppily written, construing "parameter" and "argument" and uses the bespoke term "variable function" for what I assume was intended to be "variadic function", which is what C actually has.
In any case, the point I believe this paragraph is intended to convey is the following.
C has variadic functions: functions which can take a variable number of parameters. This means you can call them with an arbitrary number of arguments, which the function will then process according to its needs. However, the sequence of arguments given to a function is always hard-coded at the call site. You cannot build a runtime list of values and pass each value to a variadic function as multiple distinct arguments, such that the function would see each value from the list as a separate parameter. At least, you cannot do this without hard-coding the length of the list at the call site.
In Lua, you can do this, taking a list of "arbitrary" length (arguments do have a maximum limit) and calling a function such that the function sees each value in the list as a distinct parameter. No matter the number of values in the list, f(unpack(list)) will pass each value as a separate parameter to f.
How does single assignment in Erlang lead to more readable code (referential transparency)?
Coding is easy, debugging is hard. Code to make debugging trivial. -- Barry Rountree
With a single assignment, you can be sure that variable has one value in the whole function body. It makes debugging much easier. You can put debugging and logging whenever you want. You can easily spot the place where it gains its value and so on. Isn't it obvious?
On of the goals of functional programs is to avoid side effects. In short this is a property of the code that it behaves exactly the same every time it's executed. That's why shared state is being avoided and why developers often frown upon the process dictionary in Erlang. A pure functional language wouldn't have any side effects. Various functional languages try to formalize code that produces side effects, like for example Haskell.
Obviously, if the value assigned to a variable can be changed, then the same function executed twice would produce different result depending on the value contained in the variable. In OOP output from a function executed on an object produces a result that depends on the state contained in that object. So you can't understand the code properly without knowing the state contained in the object as well.
With single assignment the output doesn't depend on the state but only on the arguments passed to the function. This is especially useful when something crashed and you have a stack trace or you log a debug output from a function. You can read the code and assign values to each variable knowing that nothing would have altered those values if the same code was to be executed again.
I am responsible for converting an old UNIX based COBOL batch application that was developed by a consultant back in the 1990s to a Windows environment but still in COBOL using Microfocus (Eclipse, etc).
This is a pretty straight-forward task except for one little glitch.
The old application never did any explicit file handling within the COBOL. That is there are no FDs, OPENs, READs, WRITEs or CLOSE commands in the COBOL programs. Instead they wrote a C program that would do one of those different functions based on parameters passed to it (including, but not limited to file name, rec length, and the function desired.)
I would like to rewrite that subroutine in COBOL, which would require very little modifications to the COBOL main programs being converted. That is, it would still call that subroutine, but it would now be in COBOL instead of C.
But the challenge is how to write that subroutine so that it is able to act on most any file. I would think I have to go the route of variable length records because they could literally be any length up to to-be-determined maximum size, but seems like it would be vulnerable to error (as it tries to open different types of files).
Does anybody have any experience on this or ideas on a task like this? If not,l I may have to go the blunt force route of replacing each call statement to that subroutine with the specific COBOL command (Open, Read, etc) that needs to be performed and obviously FD and SELECT for every file would need to be added to the main program.
Thanks in advance.
You might be able to
CALL "subprogram" USING fd-name
where fd-name is
FD fd-name.
...
So, yes? maybe?, you might be able to pull off a subprogram that can take generic COBOL files. But, then you get into matching record layouts and other fun things, so, be wary. This might not work COBOL to COBOL, but it does work COBOL to C and back, as you end up passing a reference to the file control block.
You'll likely be better off looking into stock system libraries. Things like CBL_OPEN_FILE and CBL_READ_FILE if they are available. This will give you a much closer match to streaming IO that will be assumed in the current C subprogram.
Or, as Bill is suggesting in the comments, try and figure out why C was used and if you don't want the foreign functions, just dig in and write new COBOL procedures, as that will likely read better in the end.
What is the difference between BY CONTENT and BY VALUE in a CALL statement in COBOL?
BY CONTENT on a CALL will copy the content of the identifier to a compiler-managed area of storage, which will then be passed to the CALLed program "by reference" implicitly.
This means the CALLed program can change the data, but no change made in the CALLed program will affect the original data in the CALLing program.
Any identifier, of any size valid for the compiler, can be used BY CONTENT (subject to any limits, if existing, which are documented for the specific compiler - you never know).
Although you can change the value in a CALLed program, it would seem a bit obscure to do so, at best.
BY VALUE is an entirely different beast. It is very limited, in that the value "passed" can be either an "integer" or a one-byte alphanumeric value. It can also be a literal.
The PROCEDURE DIVISION USING ... has to know, in the case of BY VALUE, that is is so, by specifying it in an equivalent manner to the CALL. BY REFERENCE and BY CONTENT on the CALL are both BY REFERENCE on the PROCEDURE DIVISION USING.
How this is implemented is down to the specific compiler. IBM Enterprise COBOL puts the value itself in the "parameter list".
Passing parameters by content is the same as passing by reference, except that the data is not copied back into the COBOL memory when the call has completed. Meaning that the original variable cannot be edited by the Called unit.
So the difference between BY CONTENT and BY VALUE is that in the case of BY VALUEonly the value gets passed and therefor not all kind of variables can be passed this way while BY CONTENT the pointer of a copied variable gets passed and in this way every type of variable can be passed.
See: http://documentation.microfocus.com/help/index.jsp?topic=%2Fcom.microfocus.eclipse.infocenter.visualcobol.eclipseux%2FGUID-EB09203C-3873-4DBE-9298-0C353BC0701A.html
By Reference:
When a parameter is passed by reference, a copy of the item in the JVM
COBOL is passed to the native code. When the call to the native has
finished, any changes to the information made in the native code are
copied back to the JVM COBOL. However, this does mean that memory is
shared between the JVM and native environments. In fact, what is
actually passed to the native code is a pointer to the copied data.
This is useful if you are calling non-COBOL programs. The implications
of this are very important, particularly in multi-threaded
environments. Any changes to reference parameters are not visible to
the JVM COBOL calling program until the call has completed.
Arbitrarily complex group items (within the memory limitations) can be
passed by reference. The group definition must be identical in the
native and JVM COBOL source code and it must not contain USAGE POINTER
items. Strings (java.lang.Strings) and tables (java.lang.byte arrays)
can be passed by reference. All other objects (types that inherit from
java.lang.Object, including valuetypes) cannot be passed by reference
(or by value - see below).
By Content
Passing parameters by content is the same as passing by reference,
except that the data is not copied back into the JVM COBOL memory when
the call has completed. Any item that can be passed by reference can
be passed by content.
By Value
In JVM COBOL, the only items that can be passed by value are as
follows: binary-long - the recommended type for passing by value pic
x(4) comp-x pic (9)9 comp pic s(9)9 comp pic (9)9 comp-5 pic s(9)9
comp-5
I need to pass the SYSUID and JOBID to the cobol program for logging purpose, how is this possible?,
can the same be passed as an input for a query in a JCL.
Thanks in advance.
SYSUID is simple, you just add it to the PARM parameter of your EXEC statement.
//ASTEP EXEC PGM=A#PGM,PARM='&SYSUID'
JOBID isn't available as a parameter. You will have to write COBOL code to chain through z/OS control blocks (see the Data Areas books at that link) if you need it. This can be done, but I don't recommend it.
If you actually want to get the job number, you write code to go to the PSA control block, which is at relative memory location 0. From there you get a pointer to the current TCB which is in the PSATOLD field of the PSA, from the TCB you get the TCBJSCBB field which is a pointer to the JSCB, from the TCBJSCBB fielf in the JSCB you get a pointer to the SSIB which contains the SSIBJBID field which is the job number. All of these control blocks, PSA, TCB, JSCB, and SSIB are documented (for z/OS 2.4) at the link above. And I reiterate that I don't recommend doing this.
There's a tutorial on chaining through z/OS control blocks in two parts from Longpela.
I agree with #cschneid that you don't want to do all of the pointer chaining just to get the job number. But of course we did do it while creating a "banner page printing" program. We based ours off the code at http://gsf-soft.com/Freeware/COB2JOB.shtml.
If you are comfortable with using SET ADDRESS OF items in the LINKAGE SECTION, REDEFINE--ing POINTER and COMP-5 items, along with creating 01 level structurs from assembler DSECTs, then by all means do it. As a lightweight COBOL subroutine, it's not that much more overhead than an assembler routine (but assembler is better). If you are comfortable with the REXX STORAGE function, you can look at Dave Alcock's IPLINFO program.
However, if the COBOL language constructs I mentioned are unknown to you, then write an assembler subroutine, or ask someone to write it.