Re: Compiler error in z/OS C compiler
Am 01.04.2014 01:16, schrieb Andrew Rowley: On 1/04/2014 9:37, Bernd Oppolzer wrote: How do you solve the problem that a pointer coming from a PL/1 module (or ASSEMBLER) and possibly having the high order bit on is not accepted from the C module as a valid pointer and that the results, if you use this pointer, are unpredictable or undefined, as stated by the C manuals? And: if you try to clean the first bit of this pointer by casting it to an unsigned int and switching the bit off, then you get this logic removed from the object code by the optimizer, because the optimizer (of the C compiler) THINKS that a C pointer never has the high order bit set, so there is no need to execute this logic? Perhaps the answer is to make the parameter an unsigned int, and avoid telling C it is a pointer until you have verified that it is indeed a valid pointer i.e. the routine takes an unsigned int and returns a C pointer. Thank you; if there is no other solution to this problem, this could indeed be a workaround. It would look very ugly, because we had to change the prototypes of the C functions and do some casting on entry to the functions, but it would sure work. To make it more understandable, there could be some sort of typedef typedef unsigned int PLI_PTR; and then the type PL!_PTR is used on the function prototypes. Then a function or macro is coded that translates the PLI_PTRs passed to real C pointers, possibly checking for NULL() - translating to the C constant NULL - and switching the high order bit off. Thanks again ... Of course, you might run into the same problem if the function is inlined into code that has already defined it as a pointer. When receiving these pointers from PL/1, are the received parameters required to be defined as pointers? Can you generally receive them as unsigned int, and use your routine to turn unsigned int into C pointers? Of course, if there is a calling convention for calling C from PL/1 that handles pointers automatically, that would be preferable. Regards Andrew Rowley -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
In cae1xxdeqycdbu6n4y38jj8veuccappsokfxcadjwbkrpda5...@mail.gmail.com, on 03/31/2014 at 10:49 AM, John Gilmore jwgli...@gmail.com said: In PL/I, however, the parentheses are required (because PL/I has no reserved words, only keywords in context). Thus IF ARG = NULL then RETURN SYSNULL ELSE RETURN ARG; must necessarily become IF ARG = NULL then RETURN (SYSNULL) ELSE RETURN(ARG) ; Still wrong. See 6.13.2 Return from a function -- Shmuel (Seymour J.) Metz, SysProg and JOAT ISO position; see http://patriot.net/~shmuel/resume/brief.html We don't care. We don't have to care, we're Congress. (S877: The Shut up and Eat Your spam act of 2003) -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
typedef unsigned int PLI_PTR; #define PLI_PTR_TO_C_PTR(p) (void *) ((p) == 0xFF00 ? 0 : (p) 0x7FFF) usage example: int func (PLI_PTR a, PLI_PTR b) { some_type *parm1 = PLI_PTR_TO_C_PTR (a); another_type *parm2 = PLI_PTR_TO_C_PTR (b); if (parm1 == NULL) ... } func in this example is an external function called from PL/1 that gets two pointers BYVALUE that could be NULL() - or scalar types by reference - and may have the high order bit set. The macro PLI_PTR_TO_C_PTR translates the PL/1 NULL() pattern to the C constant NULL and - otherwise - switches the high order bit off. Should work; I didn't test it. If the expression is not allowed as an initializer (I'm not sure at the moment), definition and initialization have to be separated. Kind regards Bernd Am 01.04.2014 16:24, schrieb John Gilmore: Implementation dependencies are in general undesirable, but inter-language linkages of the kind being talked about here are always and ineluctably doubly implementation-dependent. Consider now the PL/I statements declare pbs32_sysnull_image static aligned bit(32) initial(''b4) ; declare p pointer, pbs32 aligned bit(32) based(addr(p)), addr builtin ; pbs32 = pbs32_sysnull_image ; This kind of brutal data-type punning, common in assembly language, is anathema to little old ladies of both sexes in statement-level languages. It nevertheless has its uses; it is direct and efficient, and, whether written in C or PL/I, it will not be optimized away. John Gilmore, Ashland, MA 01721 - USA -- 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
Re: Compiler error in z/OS C compiler
of course, all those problems are easily solved when coding some small ASSEMBLER subprograms. I did this in fact, when we had some problems in the past with the 0C8 abends due to high order bits set in passed addresses (call an ASSEMBLER subprogram to switch OFF the PSW mask bit for 0C8 on entry to the C module - which the site wanted to be ON in the normal case - and switch it ON again, when leaving the C module). The solution with ASSEMBLER subprograms of course has the drawback that you have to link the subprogram, that is, you have some impact on the compile and link JCL, which is not always desirable, and: you have to provide at least minimal linkage conventions, while a C solution, as I provided it in my other post, can be inlined in the generated C code without this overhead. The key is indeed, as Andrew Rowley pointed it out: if you don't tell the C compiler that the pointer coming from PL/1 is a pointer, the C compiler will not treat it as a 31 bit value, so you can manipulate it before casting it to a pointer ... at least I hope so. I see no reason, why the solution proposed by Andrew should not work. Kind regards Bernd Am 01.04.2014 16:44, schrieb Charles Mills: Perhaps write the cleanup function in assembler? This is obviously a trivial problem in assembler. None of the inconvenience of strong typing to get in your way LOL. Charles -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
Well we do not want to have to check to see if things are changed every time we leave the building. We have more than enough to do as it is. John T. Abell President International Software Products Tel: 800-295-7608 Ext: 224 International: 1-416-593-5578 Ext: 224 Fax: 800-295-7609 International: 1-416-593-5579 E-mail: john.ab...@intnlsoftwareproducts.com Web: www.ispinfo.com This email may contain confidential and privileged material for the sole use of the intended recipient(s). Any review, use, retention, distribution or disclosure by others is strictly prohibited. If you are not the intended recipient (or authorized to receive on behalf of the named recipient), please contact the sender by reply email and delete all copies of this message. Also,email is susceptible to data corruption, interception, tampering, unauthorized amendment and viruses. We only send and receive emails on the basis that we are not liable for any such corruption, interception, tampering, amendment or viruses or any consequence thereof. -Original Message- From: IBM Mainframe Discussion List [mailto:IBM-MAIN@LISTSERV.UA.EDU] On Behalf Of Bernd Oppolzer Sent: Tuesday, April 01, 2014 11:08 AM To: IBM-MAIN@LISTSERV.UA.EDU Subject: Re: Compiler error in z/OS C compiler of course, all those problems are easily solved when coding some small ASSEMBLER subprograms. I did this in fact, when we had some problems in the past with the 0C8 abends due to high order bits set in passed addresses (call an ASSEMBLER subprogram to switch OFF the PSW mask bit for 0C8 on entry to the C module - which the site wanted to be ON in the normal case - and switch it ON again, when leaving the C module). The solution with ASSEMBLER subprograms of course has the drawback that you have to link the subprogram, that is, you have some impact on the compile and link JCL, which is not always desirable, and: you have to provide at least minimal linkage conventions, while a C solution, as I provided it in my other post, can be inlined in the generated C code without this overhead. The key is indeed, as Andrew Rowley pointed it out: if you don't tell the C compiler that the pointer coming from PL/1 is a pointer, the C compiler will not treat it as a 31 bit value, so you can manipulate it before casting it to a pointer ... at least I hope so. I see no reason, why the solution proposed by Andrew should not work. Kind regards Bernd Am 01.04.2014 16:44, schrieb Charles Mills: Perhaps write the cleanup function in assembler? This is obviously a trivial problem in assembler. None of the inconvenience of strong typing to get in your way LOL. Charles -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN --- This email is free from viruses and malware because avast! Antivirus protection is active. http://www.avast.com -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
I found it in my archives, from 1995. External ASSEMBLER function, callable from C - and PL/1 - , to switch the 0C8 mask bit on or off. Some of you might understand the German comments. * ** * * * SETFOFL - OC8-MASKENBIT AUS- ODER ANMACHEN * * * * AUTOR: BERND OPPOLZER / CA. 1995 * * * * UEBERNAHME IN CP0030 IM NOVEMBER 2002 * * * * PROTOTYP: extern int setfofl (int *modus); * * * * AUFRUFBEISPIEL: * * * * modus = 0; * * modusalt = setfofl (modus); * * * * MODUS = NEUER MODUS; ALTER MODUS WIRD ALS * * FUNKTIONSERGEBNIS ZURUECKGEGEBEN * * * ** * SETFOFL CSECT STM 14,12,12(13)VERKUERZTE OS-KONVENTIONEN BALR 11,0 USING *,11 * XR2,2 PROGRAMMMASKENBIT NACH R2 IPM 2 LR4,2 UND NACH R4 N 2,=X'0800' FIXED OVERFLOW BIT SRA 2,27NACH RECHTS AUF 1-ER-POSITION * N 4,=X'F7FF' BIT IN R4 AUSKNIPSEN * L 3,0(1) UEBERGEBENEN WERT HOLEN L 3,0(3) UND NOCHMAL WG. CALL-BY-REF N 3,=X'0001' ALLES WEG AUSSER RECHTES BIT SLA 3,27AUF POSITION DES FOFL-BITS OR4,3 UND REINWURSTELN SPM 4 UND INS PSW DAMIT * LR15,2RUECKGABE AN DEN RUFER L 14,12(13) LM0,12,20(13) BR14 * END Am 01.04.2014 17:08, schrieb Bernd Oppolzer: of course, all those problems are easily solved when coding some small ASSEMBLER subprograms. I did this in fact, when we had some problems in the past with the 0C8 abends due to high order bits set in passed addresses (call an ASSEMBLER subprogram to switch OFF the PSW mask bit for 0C8 on entry to the C module - which the site wanted to be ON in the normal case - and switch it ON again, when leaving the C module). The solution with ASSEMBLER subprograms of course has the drawback that you have to link the subprogram, that is, you have some impact on the compile and link JCL, which is not always desirable, and: you have to provide at least minimal linkage conventions, while a C solution, as I provided it in my other post, can be inlined in the generated C code without this overhead. The key is indeed, as Andrew Rowley pointed it out: if you don't tell the C compiler that the pointer coming from PL/1 is a pointer, the C compiler will not treat it as a 31 bit value, so you can manipulate it before casting it to a pointer ... at least I hope so. I see no reason, why the solution proposed by Andrew should not work. Kind regards Bernd Am 01.04.2014 16:44, schrieb Charles Mills: Perhaps write the cleanup function in assembler? This is obviously a trivial problem in assembler. None of the inconvenience of strong typing to get in your way LOL. Charles -- 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
Re: Compiler error in z/OS C compiler
John Gilmore wrote: Implementation dependencies are in general undesirable, but inter-language linkages of the kind being talked about here are always and ineluctably doubly implementation-dependent. Consider now the PL/I statements declare pbs32_sysnull_image static aligned bit(32) initial(''b4) ; declare p pointer, pbs32 aligned bit(32) based(addr(p)), addr builtin ; pbs32 = pbs32_sysnull_image ; This kind of brutal data-type punning, common in assembly language, is anathema to little old ladies of both sexes in statement-level languages. It nevertheless has its uses; it is direct and efficient, and, whether written in C or PL/I, it will not be optimized away. John Gilmore, Ashland, MA 01721 - USA -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN Actually - if I'm reading your PL/I correctly, it's quite possible to be surprisingly optimized (and likely not what you wanted it to do) in ANSI C. I think the equivalent C code would be: int pbs32_sysnull_image = 0; void *p; int * pbs32 = p; *pbs32 = pbs32_sysnull_image; If the intent is to set 'p' to all zeros, then this will not necessarily be the case in ANSI C. The C compiler is allowed to optimize based on types; so the assignment of the 'int' type in the assignment statement is not obliged to be seen as a write to the datum 'p'. Then, if you had something like this: p = somewhere; *pbs32 = pbs32_sysnull_image; if(p == somewhere) { printf(fail...\n); } A valid ANSI C implementation, with a reasonable optimizer, can correctly translate this program so that you see fail... printed out. What you have done here is techinically illegal, and the compiler is free to do what it wants. Having said that, many compilers only do this if you have an option to allow it.. because many programmers find it surprising. I'm not sure what PL/I would have to say about it. - Dave Rivers - -- riv...@dignus.comWork: (919) 676-0847 Get your mainframe programming tools at http://www.dignus.com -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
In 533766af.3000...@t-online.de, on 03/30/2014 at 01:34 AM, Bernd Oppolzer bernd.oppol...@t-online.de said: And my experience is that over 90 percent of them have no clue what the descriptor logic of PL/1 is all about, Nor should they. They should, however, understand the DECLARE statement. in C you have to do by reference explicitly by passing pointers That's by value, and one of the pitfalls of C. This is different from every other programming language. Neither ALGOL 60 nor Ada allows mismatched parameters, and they are far from the only ones that type-check. BTW: is this kind of flexibility - adjustable lengths inside structures - really useful? Yes. -- Shmuel (Seymour J.) Metz, SysProg and JOAT ISO position; see http://patriot.net/~shmuel/resume/brief.html We don't care. We don't have to care, we're Congress. (S877: The Shut up and Eat Your spam act of 2003) -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
Of all the languages which I have personally used. I loved Borland's Delphi (loosely base on Modula II) the best. On Sun, Mar 30, 2014 at 8:22 AM, Shmuel Metz (Seymour J.) shmuel+ibm-m...@patriot.net wrote: In 533766af.3000...@t-online.de, on 03/30/2014 at 01:34 AM, Bernd Oppolzer bernd.oppol...@t-online.de said: And my experience is that over 90 percent of them have no clue what the descriptor logic of PL/1 is all about, Nor should they. They should, however, understand the DECLARE statement. in C you have to do by reference explicitly by passing pointers That's by value, and one of the pitfalls of C. This is different from every other programming language. Neither ALGOL 60 nor Ada allows mismatched parameters, and they are far from the only ones that type-check. BTW: is this kind of flexibility - adjustable lengths inside structures - really useful? Yes. -- Shmuel (Seymour J.) Metz, SysProg and JOAT ISO position; see http://patriot.net/~shmuel/resume/brief.html We don't care. We don't have to care, we're Congress. (S877: The Shut up and Eat Your spam act of 2003) -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN -- There is nothing more pleasant than traveling and meeting new people! Genghis Khan Maranatha! John McKown -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
Just use C++ with has references void func( int ref ) { ref++ } On 30/03/2014 9:22 PM, Shmuel Metz (Seymour J.) wrote: In 533766af.3000...@t-online.de, on 03/30/2014 at 01:34 AM, Bernd Oppolzer bernd.oppol...@t-online.de said: And my experience is that over 90 percent of them have no clue what the descriptor logic of PL/1 is all about, Nor should they. They should, however, understand the DECLARE statement. in C you have to do by reference explicitly by passing pointers That's by value, and one of the pitfalls of C. This is different from every other programming language. Neither ALGOL 60 nor Ada allows mismatched parameters, and they are far from the only ones that type-check. BTW: is this kind of flexibility - adjustable lengths inside structures - really useful? Yes. -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
On Mon, 31 Mar 2014 06:58:46 -0500, John McKown wrote: Of all the languages which I have personally used. I loved Borland's Delphi (loosely base on Modula II) the best. I was absolutely blown away when I first saw Delphi - not so much with the language itself, but that IDE !!! What an eye opener. I see a couple of versions still with doco in the bookcase in the (home) office - next to the CD of battle-chess. Ahhh, thems was the days ... :0) Now every time you turn around there's another language to look into. Lua, now what did I do with that lua ... Shane . -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
On 31/03/2014 8:44 PM, Shane Ginnane wrote: On Mon, 31 Mar 2014 06:58:46 -0500, John McKown wrote: Of all the languages which I have personally used. I loved Borland's Delphi (loosely base on Modula II) the best. I was absolutely blown away when I first saw Delphi - not so much with the language itself, but that IDE !!! What an eye opener. I see a couple of versions still with doco in the bookcase in the (home) office - next to the CD of battle-chess. Ahhh, thems was the days ... :0) Now every time you turn around there's another language to look into. Lua, now what did I do with that lua ... You will pleased to know that Lua on z will be coming this year (compliments from my employers) with lots of goodies and execution speed that can show Java a clean pair of heels in 8 out of 10 benchtests that run sub-second. It's small, it's fast and it's dead easy to learn! I will pencil you in as an alpha tester Shane! How about this for iterating a 500 cylinder QSAM file in 1 cpusec? local f, msg = io.open(arg 1 , rb, type=record, noseek) if not f then error(msg) end repeat local rec = f:read(*r) until not rec Shane . -- 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
Re: Compiler error in z/OS C compiler
On Mon, Mar 31, 2014 at 8:10 AM, David Crayford dcrayf...@gmail.com wrote: On 31/03/2014 8:44 PM, Shane Ginnane wrote: On Mon, 31 Mar 2014 06:58:46 -0500, John McKown wrote: Of all the languages which I have personally used. I loved Borland's Delphi (loosely base on Modula II) the best. I was absolutely blown away when I first saw Delphi - not so much with the language itself, but that IDE !!! What an eye opener. I see a couple of versions still with doco in the bookcase in the (home) office - next to the CD of battle-chess. Ahhh, thems was the days ... :0) Now every time you turn around there's another language to look into. Lua, now what did I do with that lua ... You will pleased to know that Lua on z will be coming this year (compliments from my employers) with lots of goodies and execution speed that can show Java a clean pair of heels in 8 out of 10 benchtests that run sub-second. I hate to have to ask, but will it have a cost, or be freely licensed? This place won't spend money. Even to save money. Especially on the z. It's small, it's fast and it's dead easy to learn! I will pencil you in as an alpha tester Shane! How about this for iterating a 500 cylinder QSAM file in 1 cpusec? local f, msg = io.open(arg 1 , rb, type=record, noseek) if not f then error(msg) end repeat local rec = f:read(*r) until not rec Shane . -- 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 -- There is nothing more pleasant than traveling and meeting new people! Genghis Khan Maranatha! John McKown -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
On 31/03/2014 10:13 PM, John McKown wrote: You will pleased to know that Lua on z will be coming this year (compliments from my employers) with lots of goodies and execution speed that can show Java a clean pair of heels in 8 out of 10 benchtests that run sub-second. I hate to have to ask, but will it have a cost, or be freely licensed? This place won't spend money. Even to save money. Especially on the z. Good question. The base product will be free with optional paid support, so free as in beer unless you want to run it in production in which case you will probably want support. The value add libraries like CICS etc are likely to be licensed. The base will include heaps of goodies like web frameworks etc so you should be able to cut some tasty code for free! -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
This thread has drifted horribly -- or wonderfully, if you prefer. Returning to the original question, everything I know about PL/I could be engraved on the head of a pin, but the thought occurred to me: why shoehorn this problem into a language where it does not seem to fit? Why not write a function directly in PL/I something like IF ARG = NULL then RETURN SYSNULL ELSE RETURN ARG; ? Charles -Original Message- From: IBM Mainframe Discussion List [mailto:IBM-MAIN@LISTSERV.UA.EDU] On Behalf Of Bernd Oppolzer Sent: Thursday, March 27, 2014 8:51 AM To: IBM-MAIN@LISTSERV.UA.EDU Subject: Compiler error in z/OS C compiler Hello mainframe C users, today I observed an error in the C compiler, which made me think again about the optimization strategy of the z/OS C compiler. I wrote a small C function; the purpose was to translate pointer values coming from PL/1 modules from NULL() values - PL/1 builtin NULL() yields 0xFF00 - to real NULLs - 0x - or PL/1 SYSNULL. This is what I did: /**/ /* */ /* PLI/1 NULL () = SYSNULL () */ /* */ /**/ static void *pli_null_to_sysnull (void *ptr) { unsigned int ppli = (unsigned int) ptr; #ifdef COMPERR printf (Ausgabe in pli_null_to_sysnull wg. Comp-Fehler: %x\n, ppli); #endif if (ppli == 0xff00u) { return NULL; } else { return ptr; } } -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
Many C programmers have the habit of, for clarity, enclosing the returned expression of a RTETURN statement in parentheses, which C neither requires no objects to. In PL/I, however, the parentheses are required (because PL/I has no reserved words, only keywords in context). Thus IF ARG = NULL then RETURN SYSNULL ELSE RETURN ARG; must necessarily become IF ARG = NULL then RETURN (SYSNULL) ELSE RETURN(ARG) ; Bernd would, I should guess, respond to this suggestion by noting that, while it will do the job, its use would require changes in many PL/I source programs and thast they be recompoiled and retested, his more testicular approach makes the required change in just one place. John Gilmore, Ashland, MA 01721 - USA -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
Two typo corrections, for which I apologize: o RTETURN == RETURN o IF ARG = NULL then RETURN(SYSNULL) ELSE RETURN (ARG) ; == IF ARG = NULL then RETURN(SYSNULL) ; ELSE RETURN (ARG) ; John Gilmore, Ashland, MA 01721 - USA -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
Well, I think I indicated that my PL/I knowledge was minimal. I was trying to illustrate a concept, not write a tutorial on PL/I syntax. From your response, I would guess I was eminently successful at my intended task. I guess it's the nature of IBM-MAIN: the more irrelevant the nit, the greater the likelihood of a thorough and tedious correction. I did miss or forget that the idea of his C routine was to go into his C library routines and correct PL/I NULLs; it was not intended to be called from recompoiled PL/I so as to provide an appropriate form of nulls to various library routines. I withdraw the suggestion. Charles -Original Message- From: IBM Mainframe Discussion List [mailto:IBM-MAIN@LISTSERV.UA.EDU] On Behalf Of John Gilmore Sent: Monday, March 31, 2014 8:49 AM To: IBM-MAIN@LISTSERV.UA.EDU Subject: Re: Compiler error in z/OS C compiler Many C programmers have the habit of, for clarity, enclosing the returned expression of a RTETURN statement in parentheses, which C neither requires no objects to. In PL/I, however, the parentheses are required (because PL/I has no reserved words, only keywords in context). Thus IF ARG = NULL then RETURN SYSNULL ELSE RETURN ARG; must necessarily become IF ARG = NULL then RETURN (SYSNULL) ELSE RETURN(ARG) ; Bernd would, I should guess, respond to this suggestion by noting that, while it will do the job, its use would require changes in many PL/I source programs and thast they be recompoiled and retested, his more testicular approach makes the required change in just one place. -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
We discussed this further with some co-workers on my customers site. There are some more aspects of this discussion: a) the C language manual at one certain point states what are pointers acceptable to C and what are not. From the wording there it sounds as if pointers that come from parameters from other languages (not C) were not acceptable to C - only addresses resulting from parameters from other C functions !!! If this is true ... how do I do inter-language calls between PL/1 and C successfully? b) we are somehow concerned about parameter addresses having the high order bit on ... we regularly put the high order bit on on all parameter lists built by our PL/1 routines for the last parameter (we have ASSEMBLER interface modules between the PL/1 and C routines) ... so it is common for the C routines to get parameter addresses with the high bit on from PL/1 callers. c) in some of our C modules, we have logic to CLEAN some parameter addresses to 31 bit values - this was because of problems we had with 0C8 abends in the past. The logic looks like this: #ifdef HOST #define CLEAN_PTR(x)((void *)((unsigned int )(x) 0x7fff)) #else #define CLEAN_PTR(x)(x) #endif (#define HOST is present, when compiling on the mainframe) we now are concerned that the logic will be probably thrown away by the optimizer, if we recompile those modules ... if CLEAN_PTR is applied to a ptr and the ptr is supposed to be always 31 bit, the bit operation does make no sense at all. But: this worked for us in the past. Maybe the whole problem could be solved easily if the compiler did not throw away logic due to optimization considerations in certain special cases; for example: if there are typecasts of pointers to unsigned int involved. Such a solution would be really helpful and also solve my original problem. Kind regards Bernd Am 31.03.2014 20:27, schrieb Charles Mills: Well, I think I indicated that my PL/I knowledge was minimal. I was trying to illustrate a concept, not write a tutorial on PL/I syntax. From your response, I would guess I was eminently successful at my intended task. I guess it's the nature of IBM-MAIN: the more irrelevant the nit, the greater the likelihood of a thorough and tedious correction. I did miss or forget that the idea of his C routine was to go into his C library routines and correct PL/I NULLs; it was not intended to be called from recompoiled PL/I so as to provide an appropriate form of nulls to various library routines. I withdraw the suggestion. Charles -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
On 3/31/2014 4:02 PM, Bernd Oppolzer wrote: We discussed this further with some co-workers on my customers site. There are some more aspects of this discussion: a) the C language manual at one certain point states what are pointers acceptable to C and what are not. From the wording there it sounds as if pointers that come from parameters from other languages (not C) were not acceptable to C - only addresses resulting from parameters from other C functions !!! If this is true ... how do I do inter-language calls between PL/1 and C successfully? Ahem. http://www.trainersfriend.com/Language_Environment_courses/m520descr.htm -Steve Comstock b) we are somehow concerned about parameter addresses having the high order bit on ... we regularly put the high order bit on on all parameter lists built by our PL/1 routines for the last parameter (we have ASSEMBLER interface modules between the PL/1 and C routines) ... so it is common for the C routines to get parameter addresses with the high bit on from PL/1 callers. c) in some of our C modules, we have logic to CLEAN some parameter addresses to 31 bit values - this was because of problems we had with 0C8 abends in the past. The logic looks like this: #ifdef HOST #define CLEAN_PTR(x)((void *)((unsigned int )(x) 0x7fff)) #else #define CLEAN_PTR(x)(x) #endif (#define HOST is present, when compiling on the mainframe) we now are concerned that the logic will be probably thrown away by the optimizer, if we recompile those modules ... if CLEAN_PTR is applied to a ptr and the ptr is supposed to be always 31 bit, the bit operation does make no sense at all. But: this worked for us in the past. Maybe the whole problem could be solved easily if the compiler did not throw away logic due to optimization considerations in certain special cases; for example: if there are typecasts of pointers to unsigned int involved. Such a solution would be really helpful and also solve my original problem. Kind regards Bernd Am 31.03.2014 20:27, schrieb Charles Mills: Well, I think I indicated that my PL/I knowledge was minimal. I was trying to illustrate a concept, not write a tutorial on PL/I syntax. From your response, I would guess I was eminently successful at my intended task. I guess it's the nature of IBM-MAIN: the more irrelevant the nit, the greater the likelihood of a thorough and tedious correction. I did miss or forget that the idea of his C routine was to go into his C library routines and correct PL/I NULLs; it was not intended to be called from recompoiled PL/I so as to provide an appropriate form of nulls to various library routines. I withdraw the suggestion. Charles -- 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
Re: Compiler error in z/OS C compiler
Am 01.04.2014 00:11, schrieb Steve Comstock: On 3/31/2014 4:02 PM, Bernd Oppolzer wrote: We discussed this further with some co-workers on my customers site. There are some more aspects of this discussion: a) the C language manual at one certain point states what are pointers acceptable to C and what are not. From the wording there it sounds as if pointers that come from parameters from other languages (not C) were not acceptable to C - only addresses resulting from parameters from other C functions !!! If this is true ... how do I do inter-language calls between PL/1 and C successfully? Ahem. http://www.trainersfriend.com/Language_Environment_courses/m520descr.htm -Steve Comstock How do you solve the problem that a pointer coming from a PL/1 module (or ASSEMBLER) and possibly having the high order bit on is not accepted from the C module as a valid pointer and that the results, if you use this pointer, are unpredictable or undefined, as stated by the C manuals? And: if you try to clean the first bit of this pointer by casting it to an unsigned int and switching the bit off, then you get this logic removed from the object code by the optimizer, because the optimizer (of the C compiler) THINKS that a C pointer never has the high order bit set, so there is no need to execute this logic? In the past, we were able to clean the first bit, because the logic was NOT removed, but from the compiler error we faced in the last few days it seems that now the C compiler (at OPT(2)) believes that all pointers are limited to 31 bit and that logic dealing with the high order bit is unnecessary and can therefore be removed ... Kind regards Bernd -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
On Mon, 31 Mar 2014 17:33:48 -0500, John Gilmore wrote: ... I do not think your omisses, a semicolon and some framing parentheses, are mortal (or indeed even venial) sins. Moreover, what you wrote is substantively correct. On the other hand I do think it important to correct code examples that appear here. Many of our lurkers copy these snippets uncritically. Indeed. I try (although only when I remember) to identify my untested samples/suggestions as such. -- gil -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
On 1/04/2014 9:37, Bernd Oppolzer wrote: How do you solve the problem that a pointer coming from a PL/1 module (or ASSEMBLER) and possibly having the high order bit on is not accepted from the C module as a valid pointer and that the results, if you use this pointer, are unpredictable or undefined, as stated by the C manuals? And: if you try to clean the first bit of this pointer by casting it to an unsigned int and switching the bit off, then you get this logic removed from the object code by the optimizer, because the optimizer (of the C compiler) THINKS that a C pointer never has the high order bit set, so there is no need to execute this logic? Perhaps the answer is to make the parameter an unsigned int, and avoid telling C it is a pointer until you have verified that it is indeed a valid pointer i.e. the routine takes an unsigned int and returns a C pointer. Of course, you might run into the same problem if the function is inlined into code that has already defined it as a pointer. When receiving these pointers from PL/1, are the received parameters required to be defined as pointers? Can you generally receive them as unsigned int, and use your routine to turn unsigned int into C pointers? Of course, if there is a calling convention for calling C from PL/1 that handles pointers automatically, that would be preferable. Regards Andrew Rowley -- and...@blackhillsoftware.com +61 413 302 386 -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
John, the problem is that if you initialize a PL/1 structure by simply writing STRUCT = ''; and the structure contains pointers, these pointers are initialized to NULL, not SYSNULL. Admitted: I did not check so far if there is a compiler option to change this behaviour, but even if there was one, it would be hard to convince the compiler people responsible for the PL/1 compiler to set this option, given the large and unflexible organization I am working with. To have the pointers initialized by SYSNULL, you have to write STRUCT = ''; folllowed by STRUCT.ptr1 = SYSNULL (); STRUCT.ptr2 = SYSNULL (); STRUCT.ptr3 = SYSNULL (); STRUCT.ptr4 = SYSNULL (); ... for every pointer inside the structure (and there are many). This still may be okay. The problem occurs, when you change the structure definition (which is part of an include file), you add a pointer there, and you DON'T WANT that all your callers have to change their source code. Simple recompile should be sufficient. That was our use case. So I decided to do the NULL to SYSNULL translation on the C side. INIT on the structure definition is no option; the initialization must be done by the caller at a certain point in time. Maybe this topic should be moved to the PL/1 list ... to see if there is a nice solution on the PL/1 side. Moving hex zeroes to the struct is no option, too, because there are possible DEC FIXED fields in it, which should be initialized to zeroes properly. Kind regards Bernd Am 28.03.2014 15:36, schrieb John Gilmore: Bernd, I do not know what control you have over user code that invokes yours, but PL/I has for long supported the use of sysnull rather than null, i.e., '0'B4 instead of 'FF00'B4 as the null, points-nowhere, EOL, pointer value. Moreover, a PL/I preprocessor procedure that 1) replaces all instances of null in a PL/I source program with instances of sysnull and 2) ensures that any PL/I source program that then contains one or more instances of sysnull also contains one and only one instance of the declaration declare sysnull builtin ; is easy to construct. (I have one that you are welcome to have a copy of.) I am not sure that I fully understand your users' problems, but null should long since have been eliminated from their source programs, and a compile-time solution is much to be preferred to an execution-time one. John Gilmore, Ashland, MA 01721 - USA -- 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
Re: Compiler error in z/OS C compiler
Bernd, Now that I have a better understanding of the full dimensions your problem I will give it some further thought, and it may be that I will be abe to make further suggestions. In passing let me note that the usages whatever = null() ; whatever = sysnull() ; are necessary and appropriate only in the absence of a declaration of the form declare [sys]null builtin ; When such a declaration is not present they make it clear to the compiler that a BIF reference is meant. (Neither null nor sysnull is a PL/I keyword.) When a declaration for the appropriate BIF is provided the paired parentheses without argument can and should be dispensed with; one of pointer reference = null ; pointer reference = sysnull ; is sufficient. In my own PL/I programming I avoid the construction structure = '' ; I prefer to define/generate and [perhaps only partially] initialize a static structure the value of which can be assigned to instances of a structure at any time.For, say, declare 1 cb based, /* chaining block */ 2 fcp pointer, /* forward chaining */ 2 bcp pointer, /* back chaining */ 2 obp pointer ; /* - object */ I would write something like declare 1 cb_anfänglich static, 2 fcp pointer initial(sysnull), 2 bcp pointer initial(sysnull), 2 obp pointer initial(sysnull) ; . . . cbp-cb = cb_anfänglich ; Schemes of this sort can be very largely automated; but they are not of course suitable for old code, where introducing them would require too many changes. John Gilmore, Ashland, MA 01721 - USA -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
In 53369a68.4060...@t-online.de, on 03/29/2014 at 11:03 AM, Bernd Oppolzer bernd.oppol...@t-online.de said: PL/1, BTW, does other strange things using descriptors, FSVO strange. PL/I supports call by reference, and the locator/descriptor is simply the mechanism used by current implementations, not something that your PL/I code deals with explicitly. From my perspective, it's C that is strange. -- Shmuel (Seymour J.) Metz, SysProg and JOAT ISO position; see http://patriot.net/~shmuel/resume/brief.html We don't care. We don't have to care, we're Congress. (S877: The Shut up and Eat Your spam act of 2003) -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
Am 30.03.2014 00:41, schrieb Shmuel Metz (Seymour J.): In 53369a68.4060...@t-online.de, on 03/29/2014 at 11:03 AM, Bernd Oppolzer bernd.oppol...@t-online.de said: PL/1, BTW, does other strange things using descriptors, FSVO strange. PL/I supports call by reference, and the locator/descriptor is simply the mechanism used by current implementations, not something that your PL/I code deals with explicitly. From my perspective, it's C that is strange. At our site we have hundreds of programmers who are working with PL/1, some of them for more then 20 years, and I sometimes do programming classes for them. And my experience is that over 90 percent of them have no clue what the descriptor logic of PL/1 is all about, for example adjustable lenghts of char strings within structures. If you pass a structure, then a structure descriptor is built, and the char strings inside this structure may have different lengths in the subprogram (or even CHAR (*)). Most people think that the structures are simply overlaid when passed as arguments (like trivial by reference mechanisms in other programming languages, for example Pascal; and C, but in C you have to do by reference explicitly by passing pointers) and have no idea of the structure descriptors and their effects. For example: a receiving structure containing a CHAR instead of a PIC (of same length) is supposed to work by most of my students at first ... before I tell them that the descriptors look totally different and they will probably get 0C4 abends, when doing this. This is different from every other programming language. I call that strange, because most programmers, even some considering themselves as experienced, don't master this concept. At the same time, our management thinks, that PL/1 is easy to learn and that there is no need to invest in training ... BTW: is this kind of flexibility - adjustable lengths inside structures - really useful? It works only for CHAR strings, for DEC FIXED etc. the lengths have to be the same on both sides; there is no length information in the descriptor for scalar components of the structure. But if you need to change a structure definition, which is part of a programming interface, it is also common that you have to change the size of the DEC FIXED fields inside of some structures. The newer PL/1 versions allow NODESCRIPTOR (and BYVALUE, BTW) ... this is nice; you can choose what kind of parameter passing mechanism you want, depending on your needs. The PL/1 descriptor mechanism is a proprietary PL/1 solution which - for example - rules out C callers, but also COBOL and FORTRAN callers, IMO; probably every caller that is not PL/1. Because at our site we want every function to be callable from every of the 3 supported languages (ASSEMBLER, PL/1, C), we work without descriptors since 1980 ... even before NODESCRIPTOR was available. You can achieve this with some tricks even with old PL/1 compilers. (This is because it was an ASSEMBLER only shop first, PL/1 was the second language and appeared ca. 1980. C appeared ca. 1990. The architects decided in 1980 that they didn't want descriptor interfaces). -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
On Mar 27, 2014, at 6:44 PM, Charles Mills charl...@mcn.org wrote: I have no idea how a particular C compiler would behave but I think the problem is that any time you do anything resembling void *foo; int bar = (int)foo; then what you get is what you get. We all know that a 32-bit address and a 32-bit integer are the same thing to the z architecture, but to the C compiler they are distinct, and the conversion from one to the other is whatever the C compiler makes it. My Kernighan Ritchie says (A6.6) a pointer may be converted to an integral type ... the mapping function is ... implementation dependent. - I wonder, what if the OP reversed the casting and instead coded if ( ptr == (void *)0xff00 ) ... Is that legal? (Can you cast a constant to a void* ? My MS VS C++ just let me do it.) Would that work? Charles -Original Message- From: IBM Mainframe Discussion List [mailto:IBM-MAIN@LISTSERV.UA.EDU] On Behalf Of David Crayford Sent: Thursday, March 27, 2014 3:56 PM To: IBM-MAIN@LISTSERV.UA.EDU Subject: Re: Compiler error in z/OS C compiler I wonder if C99 intptr_t and uintptr_t would solve the problem. -- 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
Re: Compiler error in z/OS C compiler
I examined the problem further, using the following code: #include stdio.h #include stdlib.h #include string.h /**/ /* */ /* PLI/1 NULL () = SYSNULL () */ /* */ /**/ static void pli1_null_to_sysnull (void *pptr) { char *cp = pptr; if (memcmp (cp, \xff\x00\x00\x00, 4) == 0) { *cp = 0x00; } } /**/ /* */ /* PLI/1 NULL () = SYSNULL () */ /**/ /**/ static void *pli2_null_to_sysnull (void *ptr) { unsigned int ppli = (unsigned int) ptr; if (ppli == 0xff00u) { return NULL; } else { return ptr; } } /**/ /* */ /* PLI/1 NULL () = SYSNULL () */ /* */ /**/ static void *pli3_null_to_sysnull (void *ptr) { if (ptr == (void *) 0xff00u) { return NULL; } else { return ptr; } } int main (void) { char *ptr; memcpy (ptr, \xff\x00\x00\x00, 4), printf (ptr before pli1...: %p\n, ptr); pli1_null_to_sysnull (ptr); printf (ptr after pli1: %p\n, ptr); memcpy (ptr, \xff\x00\x00\x00, 4), printf (ptr before pli2...: %p\n, ptr); ptr = pli2_null_to_sysnull (ptr); printf (ptr after pli2: %p\n, ptr); memcpy (ptr, \xff\x00\x00\x00, 4), printf (ptr before pli3...: %p\n, ptr); ptr = pli3_null_to_sysnull (ptr); printf (ptr after pli3: %p\n, ptr); return 0; } The results are: for OPT(2): ptr before pli1...: FF00 ptr after pli1: 0 ptr before pli2...: FF00 ptr after pli2: FF00 ptr before pli3...: FF00 ptr after pli3: FF00 for OPT(0): ptr before pli1...: FF00 ptr after pli1: 0 ptr before pli2...: FF00 ptr after pli2: 0 ptr before pli3...: FF00 ptr after pli3: 0 so the problem is a problem of the optimization; and: the cast of the constant to (void *) - see pli3_... - doesn't help. Then I tried it again, replacing the 0xFF00 constants by 0x7F00 (which doesn't help me, because PL/1 NULL Builtin yields 0xFF00, and that is what I was trying to translate). But: this time it worked, even with OPT(2). So the problem is indeed the high order bit of the address value; C thinks that a comparison with an unsigned int constant having the high order bit on can NEVER be true. At least the optimizer at level OPT(2) thinks so and throws away the logic doing such comparisons. Now for me the problem is temporarily solved, because I understand the source of the problem, I have a workaround (pli1_...), and I hope that the compiler people at my customers' site will send the problem to IBM. Thank you all, kind regards Bernd Am 28.03.2014 03:53, schrieb Bernd Oppolzer: That looks good and indeed more naturally to me, I will give it a try ... tomorrow. Thank you. Bernd Am 28.03.2014 00:44, schrieb Charles Mills: I wonder, what if the OP reversed the casting and instead coded if ( ptr == (void *)0xff00 ) ... Is that legal? (Can you cast a constant to a void* ? My MS VS C++ just let me do it.) Would that work? Charles -- 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
Re: Compiler error in z/OS C compiler
And sorry for the typo, that if statement should have read: if (ppli == (uintptr_t) 0xff00u) Not unitptr_t. Peter -Original Message- From: IBM Mainframe Discussion List [mailto:IBM-MAIN@LISTSERV.UA.EDU] On Behalf Of Farley, Peter x23353 Sent: Friday, March 28, 2014 9:01 AM To: IBM-MAIN@LISTSERV.UA.EDU Subject: Re: Compiler error in z/OS C compiler Bernd, ISTM that the url provided by Charles Mills yesterday evening to the securecoding.cert.org site is right on target. The example on that page about using type uintptr_t would seem to apply exactly to your case. If I were you I would try the uintptr_t solution using both optimization and no optimization. If I understand that page correctly, you might want to try the code this way: /**/ /* */ /* PLI/1 NULL () = SYSNULL () */ /**/ /**/ static void *pli2_null_to_sysnull (void *ptr) { uintptr_t ppli = (uintptr_t) ptr; if (ppli == (unitptr_t) 0xff00u) { return NULL; } else { return ptr; } } HTH Peter -Original Message- From: IBM Mainframe Discussion List [mailto:IBM-MAIN@LISTSERV.UA.EDU] On Behalf Of Bernd Oppolzer Sent: Friday, March 28, 2014 7:18 AM To: IBM-MAIN@LISTSERV.UA.EDU Subject: Re: Compiler error in z/OS C compiler I examined the problem further, using the following code: Examples snipped so the problem is a problem of the optimization; and: the cast of the constant to (void *) - see pli3_... - doesn't help. Then I tried it again, replacing the 0xFF00 constants by 0x7F00 (which doesn't help me, because PL/1 NULL Builtin yields 0xFF00, and that is what I was trying to translate). But: this time it worked, even with OPT(2). So the problem is indeed the high order bit of the address value; C thinks that a comparison with an unsigned int constant having the high order bit on can NEVER be true. At least the optimizer at level OPT(2) thinks so and throws away the logic doing such comparisons. Now for me the problem is temporarily solved, because I understand the source of the problem, I have a workaround (pli1_...), and I hope that the compiler people at my customers' site will send the problem to IBM. Thank you all, kind regards Bernd Am 28.03.2014 03:53, schrieb Bernd Oppolzer: That looks good and indeed more naturally to me, I will give it a try ... tomorrow. Thank you. Bernd Am 28.03.2014 00:44, schrieb Charles Mills: I wonder, what if the OP reversed the casting and instead coded if ( ptr == (void *)0xff00 ) ... Is that legal? (Can you cast a constant to a void* ? My MS VS C++ just let me do it.) Would that work? Charles -- This message and any attachments are intended only for the use of the addressee and may contain information that is privileged and confidential. If the reader of the message is not the intended recipient or an authorized representative of the intended recipient, you are hereby notified that any dissemination of this communication is strictly prohibited. If you have received this communication in error, please notify us immediately by e-mail and delete the message and any attachments from your system. -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN This message and any attachments are intended only for the use of the addressee and may contain information that is privileged and confidential. If the reader of the message is not the intended recipient or an authorized representative of the intended recipient, you are hereby notified that any dissemination of this communication is strictly prohibited. If you have received this communication in error, please notify us immediately by e-mail and delete the message and any attachments from your system. -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
Peter, thank you. I read all this carefully, and the link that Charles Mills provided, too, but I still think that things are different here. The situations described on that site don't fit exactly to my situation. The unsigned int in my case is large enough to take the address value (32 bits vs 31 bits), so there should be no problem with that. The main problem comes from the fact that PL/1 decided long ago in history that the BUILTIN function NULL which is a pointer that points nowhere is implemented as 0xFF00 instead of 0x ... which makes some sense, because access to 0xFF00 (which is in fact 0x7F00) will probably abend 0C4 on read, when access to 0x doesn't. But anyway: if PL/1 callers pass a structure containing pointers to C, and they initialize the structure simply by assigning the empty string to it, all pointers will contain NULL(), that is 0xFF00. So the C functions receiving such structures have to cope with this. That's why I would like to check if a pointer contains 0xFF00. It should not be that hard ... just because C thinks that there are no pointers having the high order bit on doesn't mean that other languages think so, too. After all, C is a language on the mainframe and should try to work together with other languages that exist on the mainframe ... or is that a too practical point of view? Let's see ... maybe we get help from IBM on this ... I had a similar problem some months ago and got it fixed in the end. Kind regards Bernd Am 28.03.2014 14:05, schrieb Farley, Peter x23353: And sorry for the typo, that if statement should have read: if (ppli == (uintptr_t) 0xff00u) Not unitptr_t. Peter -Original Message- From: IBM Mainframe Discussion List [mailto:IBM-MAIN@LISTSERV.UA.EDU] On Behalf Of Farley, Peter x23353 Sent: Friday, March 28, 2014 9:01 AM To: IBM-MAIN@LISTSERV.UA.EDU Subject: Re: Compiler error in z/OS C compiler Bernd, ISTM that the url provided by Charles Mills yesterday evening to the securecoding.cert.org site is right on target. The example on that page about using type uintptr_t would seem to apply exactly to your case. If I were you I would try the uintptr_t solution using both optimization and no optimization. If I understand that page correctly, you might want to try the code this way: /**/ /* */ /* PLI/1 NULL () = SYSNULL () */ /**/ /**/ static void *pli2_null_to_sysnull (void *ptr) { uintptr_t ppli = (uintptr_t) ptr; if (ppli == (unitptr_t) 0xff00u) { return NULL; } else { return ptr; } } HTH Peter -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
Bernd Oppolzer wrote: Thank you all for your valuable suggestions. The compiler is z/OS XL/C V1.13 and V1.11 - well, in fact, I didn't test it with the 1.11. version. I observed the problem on the site with the 1.13 version. This is part of the PL/1 interface for my XML parser. I had to do a rollout today on three different sites of my customers; that's why there are different versions of the compiler. The site with the 1.11. compiler is on z/OS v1.13, but still uses the old compiler. I found a workaround in the meantime, this way: /**/ /* */ /* PLI/1 NULL () = SYSNULL () */ /* */ /**/ static void pli_null_to_sysnull (void *pptr) { char *cp = pptr; if (memcmp (cp, \xff\x00\x00\x00, 4) == 0) { *cp = 0x00; } } Hi Bernd, I think that's incorrect - it's comparing what cp _points to_ with 0xff00 - instead of the value of cp. If you wanted to do the comparison suggested from your original post, wouldn't it correctly be this: memcmp(cp, \xff\x0\x0\x0, 4); That would compare the value of cp with 0xff00. It's a rather round-a-bout way to make it happen.., I'm kinda still of the opinion that something else is going on. - Dave Rivers - -- riv...@dignus.comWork: (919) 676-0847 Get your mainframe programming tools at http://www.dignus.com -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
Farley, Peter x23353 wrote: And sorry for the typo, that if statement should have read: if (ppli == (uintptr_t) 0xff00u) Not unitptr_t. Peter I'm not sure uintptr_t is going to make much difference... it's just a typedef to (unsigned long). It _should_ be completely equivalent to doing: if ( ppli == (unsigned long) 0xff00u ) and since the type of 0xff00u is already (unsigned int), casting it to (unsigned long) _shouldn't_ make any difference in a 32-bit environment. (see /usr/include/stding.h for the definition of uintptr_t - it's just a type that is appropriately defined for the hardware environemnt, nothing more magical than that.) - Dave Rivers - -- riv...@dignus.comWork: (919) 676-0847 Get your mainframe programming tools at http://www.dignus.com -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
Before I get some remarks on this: I just realized that NULL returning 0xFF00 was designed when we still had 24 bit addressing, so there must have been other reasons for this design decision. Am 28.03.2014 14:39, schrieb Bernd Oppolzer: The unsigned int in my case is large enough to take the address value (32 bits vs 31 bits), so there should be no problem with that. The main problem comes from the fact that PL/1 decided long ago in history that the BUILTIN function NULL which is a pointer that points nowhere is implemented as 0xFF00 instead of 0x ... which makes some sense, because access to 0xFF00 (which is in fact 0x7F00) will probably abend 0C4 on read, when access to 0x doesn't. -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
Bernd, Have you looked at the code generated for: static void *pli_null_to_sysnull (void *ptr) //static void *pli_null_to_sysnull (unsigned int ptr) { // unsigned int ppli = (unsigned int) ptr; #ifdef COMPERR printf (Ausgabe in pli_null_to_sysnull wg. Comp-Fehler: %x\n, ppli); #endif // if (ptr == 0xff00u) if (!memcmp(ptr,\0xff\0x00\0x00,4)) { return NULL; } else { return (void *)ptr; } } First, note that my character constant is \0xff\0x00\0x00. It leaves off the last \0x00 that you had because, by definition, every C string ends with a 0\x00. When I did a C99 with -O2 (the UNIX command, since I do my C work in UNIX, the code for that function was in lined as follows (stripping out some uneeded stuff) LR r0,r13(my comment: point to start of DSA) AHI r0,H'160' (my comment: add in offset of somedata from start of DSA) + CLC somedata(4,r13,160),+CONSTANT_AREA(r1,0) (my comment: actually address of somedata) + BNE @1L6 * //static void *pli_null_to_sysnull (unsigned int ptr) * { * // unsigned int ppli = (unsigned int) ptr; * #ifdef COMPERR * printf (Ausgabe in pli_null_to_sysnull * wg. Comp-Fehler: %x\n, ppli); * #endif * // if (ptr == 0xff00u) * if (!memcmp(ptr,\0xff\0x00\0x00,4)) * { *return NULL; LA r0,0 +@1L6 DS 0H Constant Area 000130 FF00 C1A4A287 81828540 89954097|Ausgabe in p| 000140 93896D95 A493936D A3966DA2 A8A295A4|li_null_to_sysnu| 000150 939340A6 874B40C3 96949760 C6858893|ll wg. Comp-Fehl| 000160 85997A40 6CA7406C A71500 |er: %x %x.. | It don't get no better than this! However the comments on the CLC are confusing in that they seem to say that the comparison is for the value of somearea whereas the reality is that it is comparing the address of somearea, as best as I can tell. If not, there there is a whole 'nother bug! On Fri, Mar 28, 2014 at 8:39 AM, Bernd Oppolzer bernd.oppol...@t-online.dewrote: Peter, thank you. I read all this carefully, and the link that Charles Mills provided, too, but I still think that things are different here. The situations described on that site don't fit exactly to my situation. The unsigned int in my case is large enough to take the address value (32 bits vs 31 bits), so there should be no problem with that. The main problem comes from the fact that PL/1 decided long ago in history that the BUILTIN function NULL which is a pointer that points nowhere is implemented as 0xFF00 instead of 0x ... which makes some sense, because access to 0xFF00 (which is in fact 0x7F00) will probably abend 0C4 on read, when access to 0x doesn't. But anyway: if PL/1 callers pass a structure containing pointers to C, and they initialize the structure simply by assigning the empty string to it, all pointers will contain NULL(), that is 0xFF00. So the C functions receiving such structures have to cope with this. That's why I would like to check if a pointer contains 0xFF00. It should not be that hard ... just because C thinks that there are no pointers having the high order bit on doesn't mean that other languages think so, too. After all, C is a language on the mainframe and should try to work together with other languages that exist on the mainframe ... or is that a too practical point of view? Let's see ... maybe we get help from IBM on this ... I had a similar problem some months ago and got it fixed in the end. Kind regards Bernd Am 28.03.2014 14:05, schrieb Farley, Peter x23353: And sorry for the typo, that if statement should have read: if (ppli == (uintptr_t) 0xff00u) Not unitptr_t. Peter -Original Message- From: IBM Mainframe Discussion List [mailto:IBM-MAIN@LISTSERV.UA.EDU] On Behalf Of Farley, Peter x23353 Sent: Friday, March 28, 2014 9:01 AM To: IBM-MAIN@LISTSERV.UA.EDU Subject: Re: Compiler error in z/OS C compiler Bernd, ISTM that the url provided by Charles Mills yesterday evening to the securecoding.cert.org site is right on target. The example on that page about using type uintptr_t would seem to apply exactly to your case. If I were you I would try the uintptr_t solution using both optimization and no optimization. If I understand that page correctly, you might want to try the code this way: /**/ /* */ /* PLI/1 NULL () = SYSNULL () */ /**/ /**/ static void *pli2_null_to_sysnull (void *ptr) { uintptr_t ppli = (uintptr_t) ptr; if (ppli == (unitptr_t) 0xff00u) { return NULL; } else { return ptr; } } HTH Peter
Re: Compiler error in z/OS C compiler
On 28 March 2014 09:47, Bernd Oppolzer bernd.oppol...@t-online.de wrote: I just realized that NULL returning 0xFF00 was designed when we still had 24 bit addressing, so there must have been other reasons for this design decision. I remember heated discussions on this matter at my university computer centre in the early 1970s, long before 31-bit addressing on S/370. At the time it was very common for assembler code to use the high byte of a fullword address to hold flags of various kinds, and the notion of indicating a NULL pointer out of band is attractive. Some people even then had a longer view, and understood well that 24-bit addressing would not do forever, and that something would have to be done. One can see the evolution of this thinking in (IBM and others') assembler coding style as flags were moved out of high address bytes. Another thing to consider is that pointers in C and PL/I are, in their different ways, both opaque objects with only certain defined external properties, and various implementation details. For example, in the PL/I Checkout Compiler, pointers were, iirc, 128-bits, and carried various information far beyond the address that allowed the production of useful run-time debugging messages. In C, pointers are very clearly not addresses at all. Look at the semantics of adding an integer to a pointer (which is defined in the language, and is not just an implementation detail): if your pointer is to an array of, say, ints, if you add 1 to it it will point to the next int in the array, not to the next byte within the current int. PL/I has its Unspec Built In Function, and C has its cast, but both when applied to pointers have implementation defined results. Perhaps your solution lies not in the C language, but in the compiler-defined external linkage conventions, some of which can be chosen by various pragmas. Tony H. -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
Bernd, I do not know what control you have over user code that invokes yours, but PL/I has for long supported the use of sysnull rather than null, i.e., '0'B4 instead of 'FF00'B4 as the null, points-nowhere, EOL, pointer value. Moreover, a PL/I preprocessor procedure that 1) replaces all instances of null in a PL/I source program with instances of sysnull and 2) ensures that any PL/I source program that then contains one or more instances of sysnull also contains one and only one instance of the declaration declare sysnull builtin ; is easy to construct. (I have one that you are welcome to have a copy of.) I am not sure that I fully understand your users' problems, but null should long since have been eliminated from their source programs, and a compile-time solution is much to be preferred to an execution-time one. John Gilmore, Ashland, MA 01721 - USA -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
On Thu, Mar 27, 2014 at 10:51 AM, Bernd Oppolzer bernd.oppol...@t-online.de wrote: Hello mainframe C users, today I observed an error in the C compiler, which made me think again about the optimization strategy of the z/OS C compiler. I wrote a small C function; the purpose was to translate pointer values coming from PL/1 modules from NULL() values - PL/1 builtin NULL() yields 0xFF00 - to real NULLs - 0x - or PL/1 SYSNULL. This is what I did: /**/ /* */ /* PLI/1 NULL () = SYSNULL () */ /* */ /**/ static void *pli_null_to_sysnull (void *ptr) { unsigned int ppli = (unsigned int) ptr; #ifdef COMPERR printf (Ausgabe in pli_null_to_sysnull wg. Comp-Fehler: %x\n, ppli); #endif if (ppli == 0xff00u) I would replace the line above with: if ( (unsigned int)ppli == 0xff00u) /* coerce ppli to an unsigned int */ { return NULL; } else { return ptr; } } snip -- There is nothing more pleasant than traveling and meeting new people! Genghis Khan Maranatha! John McKown -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
Sorry, I missed that you already did that. On Thu, Mar 27, 2014 at 11:05 AM, John McKown john.archie.mck...@gmail.comwrote: On Thu, Mar 27, 2014 at 10:51 AM, Bernd Oppolzer bernd.oppol...@t-online.de wrote: Hello mainframe C users, today I observed an error in the C compiler, which made me think again about the optimization strategy of the z/OS C compiler. I wrote a small C function; the purpose was to translate pointer values coming from PL/1 modules from NULL() values - PL/1 builtin NULL() yields 0xFF00 - to real NULLs - 0x - or PL/1 SYSNULL. This is what I did: /**/ /* */ /* PLI/1 NULL () = SYSNULL () */ /* */ /**/ static void *pli_null_to_sysnull (void *ptr) { unsigned int ppli = (unsigned int) ptr; #ifdef COMPERR printf (Ausgabe in pli_null_to_sysnull wg. Comp-Fehler: %x\n, ppli); #endif if (ppli == 0xff00u) I would replace the line above with: if ( (unsigned int)ppli == 0xff00u) /* coerce ppli to an unsigned int */ { return NULL; } else { return ptr; } } snip -- There is nothing more pleasant than traveling and meeting new people! Genghis Khan Maranatha! John McKown -- There is nothing more pleasant than traveling and meeting new people! Genghis Khan Maranatha! John McKown -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
Perhaps turn off optimization and see what the raw compiler produces? That may provide a hint to a solution, or it may just leave the function to do what you want and you will have accomplished your task. BTW, why a static function? Could that be affecting the way the compiler optimization treats the code? HTH Peter -Original Message- From: IBM Mainframe Discussion List [mailto:IBM-MAIN@LISTSERV.UA.EDU] On Behalf Of Bernd Oppolzer Sent: Thursday, March 27, 2014 11:51 AM To: IBM-MAIN@LISTSERV.UA.EDU Subject: Compiler error in z/OS C compiler Hello mainframe C users, today I observed an error in the C compiler, which made me think again about the optimization strategy of the z/OS C compiler. I wrote a small C function; the purpose was to translate pointer values coming from PL/1 modules from NULL() values - PL/1 builtin NULL() yields 0xFF00 - to real NULLs - 0x - or PL/1 SYSNULL. This is what I did: /**/ /* */ /* PLI/1 NULL () = SYSNULL () */ /* */ /**/ static void *pli_null_to_sysnull (void *ptr) { unsigned int ppli = (unsigned int) ptr; #ifdef COMPERR printf (Ausgabe in pli_null_to_sysnull wg. Comp-Fehler: %x\n, ppli); #endif if (ppli == 0xff00u) { return NULL; } else { return ptr; } } the caller then did something like ptr = pli_null_to sysnull (ptr); now: if the printf inside the function was there (that is, COMPERR was #defined), all went OK; the ptr was translated as desired. but: if the printf was not there (no #define for COMPERR), the function was completely thrown away by the optimizer, and the ptr remained unchanged. That looks as if the compiler guessed that the condition (ppli == 0xff00u) can never be true. But because ppli is an unsigned int, and int has size 32, of course it can (and it does, as we can see in the case when printf is present). What happens here? I believe that the compiler THINKS that because the value of ppli comes from a casted pointer and pointers have 31 bits in z/OS, the value of ppli can never have the high order bit on. But that's just plain wrong, as we see here, if the pointer comes from a PL/1 module, for example, and contains NULL(). That's just the case that I want to deal with, here. We had such problems before, when, for example, pointers coming from outside into C modules had the high order bit on, and the C runtime got into serious troubles with this. Is this a variant of that same old story? What do you think? I found a workaround in the meantime, and I asked our compiler people to send the problem to IBM. But I would like to hear some opinions from the list, too: do you consider the function valid in the z/OS context or not? After all, I expect C to help me even in the systems programming business; I would be very disappointed if for such easy tasks already I had to use ASSEMBLER subprograms. Kind regards Bernd -- This message and any attachments are intended only for the use of the addressee and may contain information that is privileged and confidential. If the reader of the message is not the intended recipient or an authorized representative of the intended recipient, you are hereby notified that any dissemination of this communication is strictly prohibited. If you have received this communication in error, please notify us immediately by e-mail and delete the message and any attachments from your system. -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
I *think* the C standard basically says that you do integer arithmetic (that would include compares) on pointers at your own peril. Charles -Original Message- From: IBM Mainframe Discussion List [mailto:IBM-MAIN@LISTSERV.UA.EDU] On Behalf Of Farley, Peter x23353 Sent: Thursday, March 27, 2014 9:26 AM To: IBM-MAIN@LISTSERV.UA.EDU Subject: Re: Compiler error in z/OS C compiler Perhaps turn off optimization and see what the raw compiler produces? That may provide a hint to a solution, or it may just leave the function to do what you want and you will have accomplished your task. BTW, why a static function? Could that be affecting the way the compiler optimization treats the code? HTH Peter -Original Message- From: IBM Mainframe Discussion List [mailto:IBM-MAIN@LISTSERV.UA.EDU] On Behalf Of Bernd Oppolzer Sent: Thursday, March 27, 2014 11:51 AM To: IBM-MAIN@LISTSERV.UA.EDU Subject: Compiler error in z/OS C compiler Hello mainframe C users, today I observed an error in the C compiler, which made me think again about the optimization strategy of the z/OS C compiler. I wrote a small C function; the purpose was to translate pointer values coming from PL/1 modules from NULL() values - PL/1 builtin NULL() yields 0xFF00 - to real NULLs - 0x - or PL/1 SYSNULL. This is what I did: /**/ /* */ /* PLI/1 NULL () = SYSNULL () */ /* */ /**/ static void *pli_null_to_sysnull (void *ptr) { unsigned int ppli = (unsigned int) ptr; #ifdef COMPERR printf (Ausgabe in pli_null_to_sysnull wg. Comp-Fehler: %x\n, ppli); #endif if (ppli == 0xff00u) { return NULL; } else { return ptr; } } the caller then did something like ptr = pli_null_to sysnull (ptr); now: if the printf inside the function was there (that is, COMPERR was #defined), all went OK; the ptr was translated as desired. but: if the printf was not there (no #define for COMPERR), the function was completely thrown away by the optimizer, and the ptr remained unchanged. That looks as if the compiler guessed that the condition (ppli == 0xff00u) can never be true. But because ppli is an unsigned int, and int has size 32, of course it can (and it does, as we can see in the case when printf is present). What happens here? I believe that the compiler THINKS that because the value of ppli comes from a casted pointer and pointers have 31 bits in z/OS, the value of ppli can never have the high order bit on. But that's just plain wrong, as we see here, if the pointer comes from a PL/1 module, for example, and contains NULL(). That's just the case that I want to deal with, here. We had such problems before, when, for example, pointers coming from outside into C modules had the high order bit on, and the C runtime got into serious troubles with this. Is this a variant of that same old story? What do you think? I found a workaround in the meantime, and I asked our compiler people to send the problem to IBM. But I would like to hear some opinions from the list, too: do you consider the function valid in the z/OS context or not? After all, I expect C to help me even in the systems programming business; I would be very disappointed if for such easy tasks already I had to use ASSEMBLER subprograms. -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
Thank you all for your valuable suggestions. The compiler is z/OS XL/C V1.13 and V1.11 - well, in fact, I didn't test it with the 1.11. version. I observed the problem on the site with the 1.13 version. This is part of the PL/1 interface for my XML parser. I had to do a rollout today on three different sites of my customers; that's why there are different versions of the compiler. The site with the 1.11. compiler is on z/OS v1.13, but still uses the old compiler. I found a workaround in the meantime, this way: /**/ /* */ /* PLI/1 NULL () = SYSNULL () */ /* */ /**/ static void pli_null_to_sysnull (void *pptr) { char *cp = pptr; if (memcmp (cp, \xff\x00\x00\x00, 4) == 0) { *cp = 0x00; } } of course, this is completely different and avoids the unsigned int comparison completely, but that solves my problem :-) For the error, I observed by looking at the PSEUDO ASSEMBLY LISTING, that the IBM compiler removed the function calls and the function completely. There was only the source statements in the ASSEMBLY LISTING, no code produced. I didn't check if the function was inlined in the printf case, but I think so. Kind regards Bernd Am 27.03.2014 18:05, schrieb Thomas David Rivers: Bernd Oppolzer wrote: Hello mainframe C users, That looks as if the compiler guessed that the condition (ppli == 0xff00u) can never be true. But because ppli is an unsigned int, and int has size 32, of course it can (and it does, as we can see in the case when printf is present). The value 0xff00 is also an unsigned int, if 'ppli' is an unsigned int (with an indeterminant value) then the comparison is quite valid and can't be elided. Recall that hex constants (those beginning with 0x) are unsigned-int by definition in the C standard. And, certainly, when you cast a pointer to an unsigned it, the compiler should not apply an special consideration to the definition of pointers in 31-bit mode. Although, you _could_ decide that a pointer can't have its upper bit set, it's quite clear that it often does. The IBM compiler could be misapplying range optimizations, assuming that a 31-pointer is in the range [0x0 .. 0x7fff] and therefor could never be equal to 0xff00... but, that would be quite a stretch. If they are doing this, I can bet your report to IBM will cause an option to be added to quit doing it :-) You might want to check to see if the function has been in-lined, and if so, perhaps the parameter was a known constant or a value of a known range... which would give the compiler the flexibility to do what you observed. When I compiled your example (removing the 'static' modifier) I got this with the Dignus compiler: * *** if (ppli == 0xff00u) C 2,@lit_217_2 BNE @L3 (where @lit_217_2 was your value) and I doing the same with the IBM compiler, I got this: 21 | * if (ppli == 0xff00u) 68 5520 305221 | CL r2,=F'-16777216' 6C 4770 303E21 |BNE @1L1 which looks rather similar (both compiled with -O.) Which version of the IBM compiler are you using? - Dave Rivers - -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
static function, because the function is only of local interest and should not be visible to the linkage editor (that's the way to do this in C - they saved keywords - that's a sad story; external functions are static, too. It would be much better, if there was a keyword local to express the same thing. Unfortunately, every function not marked with static is external by default. Some people do #define Local static because of this. Kind regards Bernd Am 27.03.2014 17:26, schrieb Farley, Peter x23353: Perhaps turn off optimization and see what the raw compiler produces? That may provide a hint to a solution, or it may just leave the function to do what you want and you will have accomplished your task. BTW, why a static function? Could that be affecting the way the compiler optimization treats the code? HTH Peter -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
https://www.ibm.com/developerworks/community/blogs/5894415f-be62-4bc0-81c5-3956e82276f3/entry/ab_use_of_the_ansi_c_aliasing_rules?lang=en On 27 Mar 2014, at 11:51 pm, Bernd Oppolzer bernd.oppol...@t-online.de wrote: Hello mainframe C users, today I observed an error in the C compiler, which made me think again about the optimization strategy of the z/OS C compiler. I wrote a small C function; the purpose was to translate pointer values coming from PL/1 modules from NULL() values - PL/1 builtin NULL() yields 0xFF00 - to real NULLs - 0x - or PL/1 SYSNULL. This is what I did: /**/ /* */ /* PLI/1 NULL () = SYSNULL () */ /* */ /**/ static void *pli_null_to_sysnull (void *ptr) { unsigned int ppli = (unsigned int) ptr; #ifdef COMPERR printf (Ausgabe in pli_null_to_sysnull wg. Comp-Fehler: %x\n, ppli); #endif if (ppli == 0xff00u) { return NULL; } else { return ptr; } } the caller then did something like ptr = pli_null_to sysnull (ptr); now: if the printf inside the function was there (that is, COMPERR was #defined), all went OK; the ptr was translated as desired. but: if the printf was not there (no #define for COMPERR), the function was completely thrown away by the optimizer, and the ptr remained unchanged. That looks as if the compiler guessed that the condition (ppli == 0xff00u) can never be true. But because ppli is an unsigned int, and int has size 32, of course it can (and it does, as we can see in the case when printf is present). What happens here? I believe that the compiler THINKS that because the value of ppli comes from a casted pointer and pointers have 31 bits in z/OS, the value of ppli can never have the high order bit on. But that's just plain wrong, as we see here, if the pointer comes from a PL/1 module, for example, and contains NULL(). That's just the case that I want to deal with, here. We had such problems before, when, for example, pointers coming from outside into C modules had the high order bit on, and the C runtime got into serious troubles with this. Is this a variant of that same old story? What do you think? I found a workaround in the meantime, and I asked our compiler people to send the problem to IBM. But I would like to hear some opinions from the list, too: do you consider the function valid in the z/OS context or not? After all, I expect C to help me even in the systems programming business; I would be very disappointed if for such easy tasks already I had to use ASSEMBLER subprograms. Kind regards Bernd -- 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
Re: Compiler error in z/OS C compiler
I wonder if C99 intptr_t and uintptr_t would solve the problem. On 28 Mar 2014, at 6:42 am, Charles Mills charl...@mcn.org wrote: https://www.securecoding.cert.org/confluence/display/seccode/INT36-C.+Conver ting+a+pointer+to+integer+or+integer+to+pointer -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
I have no idea how a particular C compiler would behave but I think the problem is that any time you do anything resembling void *foo; int bar = (int)foo; then what you get is what you get. We all know that a 32-bit address and a 32-bit integer are the same thing to the z architecture, but to the C compiler they are distinct, and the conversion from one to the other is whatever the C compiler makes it. My Kernighan Ritchie says (A6.6) a pointer may be converted to an integral type ... the mapping function is ... implementation dependent. - I wonder, what if the OP reversed the casting and instead coded if ( ptr == (void *)0xff00 ) ... Is that legal? (Can you cast a constant to a void* ? My MS VS C++ just let me do it.) Would that work? Charles -Original Message- From: IBM Mainframe Discussion List [mailto:IBM-MAIN@LISTSERV.UA.EDU] On Behalf Of David Crayford Sent: Thursday, March 27, 2014 3:56 PM To: IBM-MAIN@LISTSERV.UA.EDU Subject: Re: Compiler error in z/OS C compiler I wonder if C99 intptr_t and uintptr_t would solve the problem. -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
On Thu, Mar 27, 2014 at 12:31 PM, Bernd Oppolzer bernd.oppol...@t-online.de wrote: Thank you all for your valuable suggestions. The compiler is z/OS XL/C V1.13 and V1.11 - well, in fact, I didn't test it with the 1.11. version. I observed the problem on the site with the 1.13 version. This is part of the PL/1 interface for my XML parser. I had to do a rollout today on three different sites of my customers; that's why there are different versions of the compiler. The site with the 1.11. compiler is on z/OS v1.13, but still uses the old compiler. I found a workaround in the meantime, this way: /**/ /* */ /* PLI/1 NULL () = SYSNULL () */ /* */ /**/ static void pli_null_to_sysnull (void *pptr) { char *cp = pptr; if (memcmp (cp, \xff\x00\x00\x00, 4) == 0) { *cp = 0x00; } } Enclose memcmp in parenthesis, (memcmp)(...), to force the compile to generate code which calls memcmp instead of generating inline code. of course, this is completely different and avoids the unsigned int comparison completely, but that solves my problem :-) For the error, I observed by looking at the PSEUDO ASSEMBLY LISTING, that the IBM compiler removed the function calls and the function completely. There was only the source statements in the ASSEMBLY LISTING, no code produced. I didn't check if the function was inlined in the printf case, but I think so. Kind regards Bernd Am 27.03.2014 18:05, schrieb Thomas David Rivers: Bernd Oppolzer wrote: Hello mainframe C users, That looks as if the compiler guessed that the condition (ppli == 0xff00u) can never be true. But because ppli is an unsigned int, and int has size 32, of course it can (and it does, as we can see in the case when printf is present). The value 0xff00 is also an unsigned int, if 'ppli' is an unsigned int (with an indeterminant value) then the comparison is quite valid and can't be elided. Recall that hex constants (those beginning with 0x) are unsigned-int by definition in the C standard. And, certainly, when you cast a pointer to an unsigned it, the compiler should not apply an special consideration to the definition of pointers in 31-bit mode. Although, you _could_ decide that a pointer can't have its upper bit set, it's quite clear that it often does. The IBM compiler could be misapplying range optimizations, assuming that a 31-pointer is in the range [0x0 .. 0x7fff] and therefor could never be equal to 0xff00... but, that would be quite a stretch. If they are doing this, I can bet your report to IBM will cause an option to be added to quit doing it :-) You might want to check to see if the function has been in-lined, and if so, perhaps the parameter was a known constant or a value of a known range... which would give the compiler the flexibility to do what you observed. When I compiled your example (removing the 'static' modifier) I got this with the Dignus compiler: * *** if (ppli == 0xff00u) C 2,@lit_217_2 BNE @L3 (where @lit_217_2 was your value) and I doing the same with the IBM compiler, I got this: 21 | * if (ppli == 0xff00u) 68 5520 305221 | CL r2,=F'-16777216' 6C 4770 303E21 |BNE @1L1 which looks rather similar (both compiled with -O.) Which version of the IBM compiler are you using? - Dave Rivers - -- 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
Re: Compiler error in z/OS C compiler
That looks good and indeed more naturally to me, I will give it a try ... tomorrow. Thank you. Bernd Am 28.03.2014 00:44, schrieb Charles Mills: I wonder, what if the OP reversed the casting and instead coded if ( ptr == (void *)0xff00 ) ... Is that legal? (Can you cast a constant to a void* ? My MS VS C++ just let me do it.) Would that work? Charles -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
Am 28.03.2014 02:41, schrieb Sam Siegel: Enclose memcmp in parenthesis, (memcmp)(...), to force the compile to generate code which calls memcmp instead of generating inline code. This was the workaround I found for the original problem, and it worked perfectly; I like the memcmp being implemented by inline code ... no problem with that. -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
Re: Compiler error in z/OS C compiler
On 28/03/2014 1:05 AM, Thomas David Rivers wrote: The IBM compiler could be misapplying range optimizations, assuming that a 31-pointer is in the range [0x0 .. 0x7fff] and therefor could never be equal to 0xff00... but, that would be quite a stretch. If they are doing this, I can bet your report to IBM will cause an option to be added to quit doing it :-) I think you've hit the nail on the head Dave! I bet if the OP changed the constant to 0x7f00 it would work! Time for somebody to open an PMR -- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN