"I'd be perfectly happy for someone to tell me I missed some obvious compiler option or did something else really stupid."
Found this on another website ... The issue was with the search order. Although I did search(/usr/metal/include) from with in my JCL I didn't proceed it with a nosearch option, so string.h was getting picked up from the standard system libraries instead of the version included with Metal C. I've pasted my optfile dataset I passed to the CPARM below for reference. //OPTIONS DD * SO LIST LONG NOXREF CSECT METAL LP64 NOSEARCH search(/usr/include/metal/) Joe On Mon, Jan 11, 2021 at 12:39 PM Dennis Fitzpatrick <den...@dcfitz.com> wrote: > I'm a developer working with a client to develop Metal C functions for > their products. Up until recently I've defined __METAL_STATIC and linked > with SCCR3BND. I decided recently to play with the dynamic library in > LPALIB so I removed that #define. What I'm getting is compile errors on the > substitution macros from metal.h. That is the first problem. I decided to > try and circumvent the compile errors and I think I found a bug in the > memcmp library function. That is the second problem. I'm really hoping > someone will tell me I missed something really obvious or missed some > maintenance. > > I created a trivial sample program to demonstrate: > > /* > Sample for Metal C > */ > > #include <stdio.h> > #include <stdlib.h> > > int main(int argc, char** argv) > { > char* xarg = "abcd"; > void *mem = malloc(64); > memset(mem, 0x0f, 64); > memcpy(mem, xarg, sizeof(xarg)); > int mcmp = memcmp(mem, xarg, sizeof(xarg)); > free(mem); > } > Of course, this compiles and runs just fine on Visual Studio where I do my > initial development. On z/OS XLC though I get errors like the following: > > 12 | memset(mem, 0x0f, 64); > | 12 > 12 + ((___MEMSET * ) ( (*(struct __cvt_s * __ptr32 * > __ptr32)16) -> __cvtecvt -> __ecvtsdc -> __sdca\+ 12 > ===========> > ....b...........a................................................................................. > *=ERROR===========> a - CCN3275 Unexpected text ')' encountered. > *=ERROR===========> b - CCN3045 Undeclared identifier ___MEMSET. > 12 +libv31 -> __libfunc[33] ))(mem, 0x0f, 64); > + 12 > ===========> > .........................................c........................................................ > *=ERROR===========> c - CCN3277 Syntax error: possible missing ')' or ','? > > The header file include list is exactly what I expect: > > 1 /usr/include/metal/stdio.h > 2 /usr/include/metal/metal.h > 3 /usr/include/metal/stddef.h > 4 /usr/include/metal/stdlib.h > 5 /usr/include/metal/builtins.h > > Looking through all of the layers in the metal.h header started me looking > for aspirin. I decided to push forward as an exercise by defining my own > structures to use the Metal C function vector. I already had many of the > standard z/OS structures mapped and added my own mapping of sys_libv31_s > with real function prototypes: > > struct sys_libv31_s > { > void (*_em_0)(); > int (*_em_abs)(int,int); // 1 > int (*_em_atoi)(char*); // 2 > long (*_em_atol)(char*); // 3 > long long (*_em_atoll)(char*); // 4 > void* (*_em_calloc)(size_t); // 5 > > And my own substitution macros to remove the metal.h definition and put in > my own EMCALL reference: > > #define EMCALL(_t, _n) > (##_t)(*(CVTPTR->CVTECVT->ECVTSDC->sdcalibv31->_em_##_n)) > #define em_0 EMCALL(void, em_0) > #undef abs // 1 > #define abs EMCALL(int, abs) > #undef atoi // 2 > #define atoi EMCALL(int atoi) > #undef atol // 3 > #define atol EMCALL(long, atol) > #undef atoll // 4 > #define atoll EMCALL(long long, atoll) > #undef calloc // 5 > #define calloc EMCALL(void *, calloc) > > I can't give you the whole thing as it is too much to extract from client > proprietary material. Hopefully, this is enough to get the gist. > > Now this is where I believe I found a bug in the memcmp function returning > an invalid result and also a potential S0C4. With getting all of my code to > compile I found things taking some weird code paths. I tracked it down to a > memcmp and setup the code in the sample above to test it. I found the > memcmp above returns an invalid result, 0x0f, even though the memory is > equal. I went into TEST and disassembled the code and got this: > > > 1F24CD78. STM R14,R3,12(R13) > > 1F24CD7C. LR R15,R13 > > 1F24CD7E. L R13,8(,R13) > > 1F24CD82. ST R15,4(,R13) > > 1F24CD86. STMH R14,R3,80(R13) > > 1F24CD8C. L R14,0(,R1) > > 1F24CD90. L R2,4(,R1) > > 1F24CD94. ICM R0,15,8(R1) > > 1F24CD98. BRC 8,*+52 > > 1F24CD9C. LR R1,R0 > > 1F24CD9E. LLGC R15,0(,R14) > > 1F24CDA4. LLGC R3,0(,R2) > > 1F24CDAA. LA R14,1(,R14) > > 1F24CDAE. LA R2,1(,R2) > > 1F24CDB2. CR R15,R3 > > 1F24CDB4. BRC 7,*+36 > > 1F24CDB8. LLGC R15,0(,R14) > > 1F24CDBE. LLGC R3,0(,R2) > > 1F24CDC4. BRCT R1,*-26 > > 1F24CDC8. BRC 15,*+16 > > 1F24CDCC. LLGC R15,0(,R14) > > 1F24CDD2. LLGC R3,0(,R2) > > 1F24CDD8. SLR R15,R3 > > 1F24CDDA. LMH R14,R3,80(R13) > > 1F24CDE0. L R13,4(,R13) > > 1F24CDE4. L R14,12(,R13) > > 1F24CDE8. LM R1,R3,24(R13) > > 1F24CDEC. BCR 15,R14 > > The important thing is that the loop uses R14 & R2 as the character > pointers and R1 as the count. The loop at D9E loads the first bytes of each > memory area. Then it increments the pointers, does the compare, and if NE > branches to *+36 (DCC). It then reloads R15 & R3 but the pointers have > already been incremented. It calculates the difference of the two bytes as > the return value. This gets the two random bytes after the memory area to > compute the result which is an incorrout and a possible S0C4. Similarly, it > uses those same next bytes if the result is BRC NE falls through giving > random results and/or S0C4 if the strings are equal. > > I thought I was totally delusional at this point since how could any code > work if the memcmp library function was bad. Then I further found that > metal/builtin.h overrides the library call and causes a fair number of > these critical library functions to be inlined by the compiler which of > course generates good code. I also verified that none of my old links with > SCCR3BND pull in any of the library memory functions (memcmp, memcpy, etc.) > along with a bunch of other stdlib functions which builtin.h overrides. > > I'd be perfectly happy for someone to tell me I missed some obvious > compiler option or did something else really stupid. > > > Dennis C. Fitzpatrick > den...@dcfitz.com<mailto:den...@dcfitz.com> > H: 630.325.6184 > W: 630.325.6137 > M: 630.660.8040 > > > ---------------------------------------------------------------------- > 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