BTW:

this comment and the pragma

|#pragma linkage(_printf4,OS) /*function will be called from assembler|

seems sort of ill-fated to me.

At my old customer's site (which is again my customer since 2021), we always had the paradigm that every module must be able to call every other module, no matter what the programming language is,
and the calling module needs not know the language of the module called.

We support PL/1, C and ASSEMBLER.

The interfaces (parameter structures) are defined in a language independent way in a global repository, and macros usable in the three languages are derived automatically from this repository. There are more things to tell like interface version control; automatic up-levelling, if versions of interfaces at call time don't match etc. ... and test tools which support isolated component tests, where the test cases are also built
starting from the interface definitions etc. etc.

This said, call by value in C is - at this customer's site - only allowed for local functions, but not when calling external modules (which may be in C, PL/1 or ASSEMBLER). In the second case, only call by reference (that is: pointer to structures) is possible,
because that works in all three languages.

Of course, it is kind of hard, if a 3rd party software supplier wants to get his software introduced in this environment ... but it's possible, anyway. Several suppliers did it successfully, after we explained them,
what to do (with our help, of course).

Kind regards

Bernd


Am 31.03.2023 um 01:54 schrieb Bernd Oppolzer:

The function @PRINTF4 is also shown in the IBM example:

|/* this example demonstrates C/Assembler ILC */ /* part 3 of 3 (other files are CCNGCA2, CCNGCA4) */ /*******************************************************\ * This routine is an interface between assembler code * * and the C/C++ library function printf(). * * OS linkage will not tolerate C-style variable length * * parameter lists, so this routine is specific to a * * formatting string and a single 4-byte substitution * * parameter. It's specified as an int here. * * This object wil be named @PRINTF4. * /*******************************************************/ #pragma linkage(_printf4,OS) /*function will be called from assembler*/ #include <stdio.h> #pragma map(_printf4,“@PRINTF4”) int _printf4(char *str,int i) { return printf(str,i); /* call runtime library function */ }|


what you see here is the special behaviour because of the #pragma linkage(...,OS) ..
this is NOT the standard behaviour of C.

The parameter int i is passed BY ADDR in this case ...
with the #pragma you can override nomal C "by value" behaviour (which means, that the function cannot be called by "normal" C, which doesn't know about
this #pragma).

We never allowed the use of #pragma linkage at our site ... that's why we had to build the glue functions to support the 3rd party package in the 1990s. (Or, IIRC,
we asked the supplier of the software to do this for money).

Kind regards

Bernd



Am 31.03.2023 um 01:42 schrieb Bernd Oppolzer:
See answers below

Am 31.03.2023 um 01:23 schrieb Paul Gilmartin:
On Thu, 30 Mar 2023 23:39:30 +0200, Bernd Oppolzer wrote:
"call by value" in my understanding means, that values are passed, not
addressed.
With the mainframe (or z/OS and CMS) linkage convention, this means,
that values
and not addresses are in the reg1 parameter list.

What happens if there are more value parameters than the total capacity of registers? (But do I misunderstand?  Is the "reg1 parameter list" not actual registers but the storage addressed by GR1 in the CALL macrlo?  If so, it's no practical limit.)

reg1 parameter list is the address list which register 1 points to.
So there is no practical limit on the size of the parameter list.

Of course, it is impractical to pass large structures or arrays by value,
but that's what every C tutorial will tell you ...


see above. Because the values entered into the reg1 list "by value" can
be negative integers
(or other types, which need more that 4 bytes), the VL convention cannot
be used by C callers

Hmmm.  In <https://www.ibm.com/docs/en/zos/2.5.0?topic=programs-calling-c-code-from-assembler-c-example>
I see:
          EDCPRLG
          LA    1,ADDR_BLK              parameter address block in r1
          L     15,=V(@PRINTF4)         address of routine
          BALR  14,15                   call @PRINTF4
          EDCEPIL
ADDR_BLK DC   A(FMTSTR)                parameter address block with..
          DC   A(X'80000000'+INTVAL)    ..high bit on the last address
*   ...
INTVAL   DC   F'222'            The integer value displayed
*
Isn't the "X'80000000'" setting the VL bit?
(I note that's a CD not an EQU.  But the reg1 PL contains an address not a value.)

Again, either the caller or the called routine could be able
to convert addresses to values.

This @PRINTF4 cannot be the same as normal PRINTF;
it must be a glue function or similar to allow an ASSEMBLER function to call normal PRINTF.

(only guessing, because the FMTSTR is not shown here).

If normal PRINTF is called, the sequence should look like this:

         LA    1,ADDR_BLK              parameter address block in r1
         L     15,=V(PRINTF)           address of routine
         BALR  14,15                   call normal PRINTF

...

ADDR_BLK DC   A(FMTSTR)                parameter address block with..
         DC   F(222)
FMTSTR   DC   C'output of integer %d using printf'
         DC   X'00'

As you can see, because the integer value can be positive or negative,
there is no way to mark the last parameter with the leftmost bit.

Old story from my old customer:

sometime we had to introduce 3rd party software (written in C) which had to be called from PL/1 routines. PL/1 at that time only had call by reference, but the routines of the 3rd party software used call by value in their interfaces or APIs.

We had to provide so-called "glue functions" for every function of the 3rd party software, that had a call by value parameter ... the call by value parameter
was a reference-parameter in "our" interface, callable by PL/1, and then
the glue function called the 3rd party function, using the by-value interface.

This was in the 1990s ... today BYVALUE is supported by native PL/1.

Maybe the same is going on here with that @PRINTF4 interface ??

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN

Reply via email to