diff --git a/configure.ac b/configure.ac index 345336997e..188d5bbcfb 100644 --- a/configure.ac +++ b/configure.ac @@ -1232,6 +1232,13 @@ AH_VERBATIM([MACOS_ARM64],[ #endif ]) +AH_VERBATIM([MDSPLUS_USE_FFI],[ +// List of platforms that need libffi for variadic functions. +#if defined(MACOS_ARM64) +#define MDSPLUS_USE_FFI +#endif +]) + dnl add here what goes on bottom of mdsconfig.h AH_BOTTOM( #endif // _MSC_VER else diff --git a/include/libroutines.h b/include/libroutines.h index f3726de0ea..0f0edcf157 100644 --- a/include/libroutines.h +++ b/include/libroutines.h @@ -16,6 +16,22 @@ /// defined in MdsShr.so extern void *LibCallg(); + +#ifdef MDSPLUS_USE_FFI +extern void *LibCallgFfi(); +enum MDS_FFI_Rtype { + MDS_FFI_RTN_VOID = 0, + MDS_FFI_RTN_POINTER = 1, + MDS_FFI_RTN_INT32 = 2, + MDS_FFI_RTN_INT64 = 3 +}; +#endif +#ifdef MDSPLUS_USE_FFI +#define LIB_CALL_G(args, routine, fixed, rtype) (int)(intptr_t)LibCallgFfi(args, routine, fixed, rtype) +#else +#define LIB_CALL_G(args, routine, fixed, rtype) (int)(intptr_t)LibCallg(args, routine) +#endif + extern int LibCreateVmZone(ZoneList **const zone); extern int LibDeleteVmZone(ZoneList **const zone); extern int LibResetVmZone(ZoneList **const zone); diff --git a/java/mdsplus-api/src/main/java/mds/Mds.java b/java/mdsplus-api/src/main/java/mds/Mds.java index 702ff3fdbb..08dc086eff 100644 --- a/java/mdsplus-api/src/main/java/mds/Mds.java +++ b/java/mdsplus-api/src/main/java/mds/Mds.java @@ -569,8 +569,8 @@ protected final int MdsEND_ARG() if (this.mds_end_arg == 0) try { - if (this.getDescriptor("TdiShr->TdiPi(val(0),val(1))").toLong() == 1) // - this.mds_end_arg = 1; + if (this.getDescriptor("TdiShr->TdiPi#1(val(0),val(1))").toLong() == 1) + this.mds_end_arg = 1; else this.mds_end_arg = -1; } diff --git a/java/mdsplus-api/src/test/java/mds/MdsShr_Test.java b/java/mdsplus-api/src/test/java/mds/MdsShr_Test.java index 03d7794230..de2d920344 100644 --- a/java/mdsplus-api/src/test/java/mds/MdsShr_Test.java +++ b/java/mdsplus-api/src/test/java/mds/MdsShr_Test.java @@ -43,7 +43,7 @@ public final void testMdsCompress() throws MdsException { ARRAY ca; Assert.assertEquals("Set_Range(15000,0 /*** etc. ***/)", MdsShr_Test.mds.getString( - "_a=DATA(0:29999:2);_s=MdsShr->MdsCompress(0,0,xd(_a),xd(_a));_s=TdiShr->TdiDecompile(xd(_a),xd(_a),val(1));_a")); + "_a=DATA(0:29999:2);_s=MdsShr->MdsCompress(0,0,xd(_a),xd(_a));_s=TdiShr->TdiDecompile#1(xd(_a),xd(_a),val(1));_a")); Assert.assertEquals("Set_Range(15000,0 /*** etc. ***/)", (ca = MdsShr_Test.mdsshr.mdsCompress(null, new Range(0, 29999, 2).getDataA())).decompile()); Assert.assertEquals(10, ca.getDataA().toInt(5)); diff --git a/java/mdsplus-api/src/test/java/mds/data/descriptor/Descriptor_A_Test.java b/java/mdsplus-api/src/test/java/mds/data/descriptor/Descriptor_A_Test.java index becb24ca6b..580b668a96 100644 --- a/java/mdsplus-api/src/test/java/mds/data/descriptor/Descriptor_A_Test.java +++ b/java/mdsplus-api/src/test/java/mds/data/descriptor/Descriptor_A_Test.java @@ -56,7 +56,7 @@ public final void testARRAY() throws MdsException { 8, 0, 5, 4, 16, 0, 0, 0, 0, 0, 48, 1, 8, 0, 0, 0, 0, 16, -91, -44, -24, 0, 0, 0 }, test.serializeArray()); Assert.assertEquals("ABS([1000000000000QU])", Descriptor_A_Test.mds.getString( - "_a=*;_s=MdsShr->MdsSerializeDscIn(ref($),xd(_a));_s=TdiShr->TdiDecompile(xd(_a),xd(_a),val(1));_a", + "_a=*;_s=MdsShr->MdsSerializeDscIn(ref($),xd(_a));_s=TdiShr->TdiDecompile#1(xd(_a),xd(_a),val(1));_a", Function.ABS(new Uint64Array(1000000000000l)).serializeDsc())); Assert.assertEquals("Build_Signal([1D0,2D0,3D0], *, [1Q,2Q,3Q])", new Signal(new Float64Array(1, 2, 3), null, new Int64Array(1, 2, 3)).decompile()); diff --git a/java/mdsplus-api/src/test/java/mds/data/descriptor/Descriptor_CA_Test.java b/java/mdsplus-api/src/test/java/mds/data/descriptor/Descriptor_CA_Test.java index 637d3fccd7..88cef78f3f 100644 --- a/java/mdsplus-api/src/test/java/mds/data/descriptor/Descriptor_CA_Test.java +++ b/java/mdsplus-api/src/test/java/mds/data/descriptor/Descriptor_CA_Test.java @@ -51,7 +51,7 @@ public final void testARRAY() throws MdsException { 8, 0, 5, 4, 16, 0, 0, 0, 0, 0, 48, 1, 8, 0, 0, 0, 0, 16, -91, -44, -24, 0, 0, 0 }, test.serializeArray()); Assert.assertEquals("ABS([1000000000000QU])", Descriptor_CA_Test.mds.getString( - "_a=*;_s=MdsShr->MdsSerializeDscIn(ref($),xd(_a));_s=TdiShr->TdiDecompile(xd(_a),xd(_a),val(1));_a", + "_a=*;_s=MdsShr->MdsSerializeDscIn(ref($),xd(_a));_s=TdiShr->TdiDecompile#1(xd(_a),xd(_a),val(1));_a", Function.ABS(new Uint64Array(1000000000000l)).serializeDsc())); Assert.assertEquals("Build_Signal([1D0,2D0,3D0], *, [1Q,2Q,3Q])", new Signal(new Float64Array(1, 2, 3), null, new Int64Array(1, 2, 3)).decompile()); diff --git a/javamds/mdsobjects.c b/javamds/mdsobjects.c index 8cf411be12..8b7310345e 100644 --- a/javamds/mdsobjects.c +++ b/javamds/mdsobjects.c @@ -1441,7 +1441,7 @@ JNIEXPORT jobject JNICALL Java_MDSplus_Data_compile(JNIEnv *env, arglist[varIdx++] = &outXd; arglist[varIdx++] = MdsEND_ARG; *(int *)&arglist[0] = varIdx - 1; - status = (int)(intptr_t)LibCallg(arglist, TdiCompile); + status = LIB_CALL_G(arglist, TdiCompile, 1, MDS_FFI_RTN_INT32); (*env)->ReleaseStringUTFChars(env, jexpr, expr); for (i = 0; i < numArgs; i++) FreeDescrip(arglist[2 + i]); @@ -1553,7 +1553,7 @@ JNIEXPORT jobject JNICALL Java_MDSplus_Data_execute(JNIEnv *env, arglist[varIdx++] = &outXd; arglist[varIdx++] = MdsEND_ARG; *(int *)&arglist[0] = varIdx - 1; - status = (int)(intptr_t)LibCallg(arglist, TdiCompile); + status = LIB_CALL_G(arglist, TdiCompile, 1, MDS_FFI_RTN_INT32); (*env)->ReleaseStringUTFChars(env, jexpr, expr); for (i = 0; i < numArgs; i++) FreeDescrip(arglist[2 + i]); @@ -2235,7 +2235,7 @@ JNIEXPORT jobject JNICALL Java_MDSplus_Tree_compile(JNIEnv *env, arglist[varIdx++] = &outXd; arglist[varIdx++] = MdsEND_ARG; *(int *)&arglist[0] = varIdx - 1; - status = (int)(intptr_t)LibCallg(arglist, _TdiCompile); + status = LIB_CALL_G(arglist, _TdiCompile, 2, MDS_FFI_RTN_INT32); (*env)->ReleaseStringUTFChars(env, jexpr, expr); for (i = 0; i < numArgs; i++) FreeDescrip(arglist[3 + i]); @@ -2291,7 +2291,7 @@ JNIEXPORT jobject JNICALL Java_MDSplus_Tree_execute(JNIEnv *env, arglist[varIdx++] = &outXd; arglist[varIdx++] = MdsEND_ARG; *(int *)&arglist[0] = varIdx - 1; - status = (int)(intptr_t)LibCallg(arglist, _TdiExecute); + status = LIB_CALL_G(arglist, _TdiExecute, 2, MDS_FFI_RTN_INT32); (*env)->ReleaseStringUTFChars(env, jexpr, expr); for (i = 0; i < numArgs; i++) FreeDescrip(arglist[3 + i]); @@ -2331,7 +2331,7 @@ JNIEXPORT jobject JNICALL Java_MDSplus_Tree_data(JNIEnv *env, arglist[3] = &outXd; arglist[4] = MdsEND_ARG; *(int *)&arglist[0] = 4; - status = (int)(intptr_t)LibCallg(arglist, _TdiData); + status = LIB_CALL_G(arglist, _TdiData, 2, MDS_FFI_RTN_INT32); FreeDescrip(arglist[2]); if (STATUS_NOT_OK) { @@ -2370,7 +2370,7 @@ JNIEXPORT jobject JNICALL Java_MDSplus_Tree_evaluate(JNIEnv *env, arglist[3] = &outXd; arglist[4] = MdsEND_ARG; *(int *)&arglist[0] = 4; - status = (int)(intptr_t)LibCallg(arglist, _TdiEvaluate); + status = LIB_CALL_G(arglist, _TdiEvaluate, 2, MDS_FFI_RTN_INT32); FreeDescrip(arglist[2]); if (STATUS_NOT_OK) { diff --git a/mdslib/MdsLib.c b/mdslib/MdsLib.c index 2f74566e8e..c52f38723b 100644 --- a/mdslib/MdsLib.c +++ b/mdslib/MdsLib.c @@ -30,6 +30,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include static int MdsCONNECTION = -1; #define NDESCRIP_CACHE 1024 #ifndef _CLIENT_ONLY @@ -42,7 +43,6 @@ extern int TdiExecute(mdsdsc_t *, ...); extern int TdiCompile(mdsdsc_t *, ...); extern int TdiData(mdsdsc_t *, ...); extern int TdiCvt(mdsdsc_t *, ...); -extern void *LibCallg(); extern int TreeFindNode(); extern int TreePutRecord(); extern int TreeWait(); @@ -640,7 +640,7 @@ static inline int mds_value_vargs(va_list incrmtr, int connection, arglist[argidx++] = (void *)&xd1; arglist[argidx++] = MdsEND_ARG; *(int *)&arglist[0] = argidx - 1; - status = (int)(intptr_t)LibCallg(arglist, TdiExecute); + status = LIB_CALL_G(arglist, TdiExecute, 1, MDS_FFI_RTN_INT32); if (STATUS_OK) { @@ -898,7 +898,7 @@ static inline int mds_value2_vargs(va_list incrmtr, int connection, arglist[argidx++] = (void *)&xd1; arglist[argidx++] = MdsEND_ARG; *(int *)&arglist[0] = argidx - 1; - status = (int)(intptr_t)LibCallg(arglist, TdiExecute); + status = LIB_CALL_G(arglist, TdiExecute, 1, MDS_FFI_RTN_INT32); if (STATUS_OK) { @@ -1062,7 +1062,7 @@ static inline int mds_put_vargs(va_list incrmtr, int connection, char *pathname, arglist[argidx++] = MdsEND_ARG; *(int *)&arglist[0] = argidx - 1; - status = (int)(intptr_t)LibCallg(arglist, TdiCompile); + status = LIB_CALL_G(arglist, TdiCompile, 1, MDS_FFI_RTN_INT32); if (STATUS_OK) { @@ -1205,7 +1205,7 @@ static int mds_put2_vargs(va_list incrmtr, int connection, char *pathname, arglist[argidx++] = MdsEND_ARG; *(int *)&arglist[0] = argidx - 1; - status = (int)(intptr_t)LibCallg(arglist, TdiCompile); + status = LIB_CALL_G(arglist, TdiCompile, 1, MDS_FFI_RTN_INT32); if (STATUS_OK) { @@ -1334,7 +1334,7 @@ extern EXPORT int *cdescr(int dtype, void *data, ...) va_end(incrmtr); arglist[argidx++] = MdsEND_ARG; *(int *)&arglist[0] = argidx - 1; - status = (int)(intptr_t)LibCallg(arglist, descr); + status = LIB_CALL_G(arglist, descr, 3, MDS_FFI_RTN_INT32); return (&status); } #endif diff --git a/mdslibidl/MdsLibIdl.c b/mdslibidl/MdsLibIdl.c index 404e676f85..a782a5b982 100644 --- a/mdslibidl/MdsLibIdl.c +++ b/mdslibidl/MdsLibIdl.c @@ -380,7 +380,7 @@ EXPORT int IdlMdsValue(int argc, void **argv) arglist[argidx++] = (void *)&tmp; arglist[argidx++] = MdsEND_ARG; *(long *)&arglist[0] = argidx; - status = (int)(intptr_t)LibCallg(arglist, TdiExecute); + status = LIB_CALL_G(arglist, TdiExecute, 1, MDS_FFI_RTN_INT32); if (STATUS_OK) { status = TdiData(tmp.pointer, &mdsValueAnswer MDS_END_ARG); @@ -626,7 +626,7 @@ EXPORT int IdlMdsPut(int argc, void **argv) arglist[argidx++] = (void *)&tmp; arglist[argidx++] = MdsEND_ARG; *(int *)&arglist[0] = argidx; - status = (int)(intptr_t)LibCallg(arglist, TdiCompile); + status = LIB_CALL_G(arglist, TdiCompile, 1, MDS_FFI_RTN_INT32); if (STATUS_OK) { status = TreePutRecord(nid, (struct descriptor *)&tmp, 0); diff --git a/mdsobjects/cpp/mdsdata.c b/mdsobjects/cpp/mdsdata.c index 0ae3e82b9c..75a59a2eb4 100644 --- a/mdsobjects/cpp/mdsdata.c +++ b/mdsobjects/cpp/mdsdata.c @@ -497,11 +497,11 @@ void *compileFromExprWithArgs(char *expr, int nArgs, void **args, void *tree, if (ctx) { - status = *retStatus = (int)(intptr_t)LibCallg(arglist, _TdiCompile); + status = *retStatus = LIB_CALL_G(arglist, _TdiCompile, 2, MDS_FFI_RTN_INT32); } else { - status = *retStatus = (int)(intptr_t)LibCallg(arglist, TdiCompile); + status = *retStatus = LIB_CALL_G(arglist, TdiCompile, 1, MDS_FFI_RTN_INT32); } if (STATUS_NOT_OK) return NULL; diff --git a/mdsobjects/cpp/mdsobjects.c b/mdsobjects/cpp/mdsobjects.c index 170c98a9a2..78099b85bc 100644 --- a/mdsobjects/cpp/mdsobjects.c +++ b/mdsobjects/cpp/mdsobjects.c @@ -987,7 +987,7 @@ JNIEXPORT jobject JNICALL Java_mdsdata_Data_compileWithArgs( arglist[varIdx++] = (struct descriptor *)&outXd; arglist[varIdx++] = MdsEND_ARG; *(int *)&arglist[0] = varIdx - 1; - LibCallg(arglist, TdiCompile); + LIB_CALL_G(arglist, TdiCompile, 1, MDS_FFI_RTN_INT32); for (i = 0; i < argLen; i++) freeDescrip(arglist[2 + i]); (*env)->ReleaseStringUTFChars(env, jexpr, expr); diff --git a/mdsobjects/cpp/testing/MdsExpressionCompileTest.cpp b/mdsobjects/cpp/testing/MdsExpressionCompileTest.cpp index f72862ef91..47c72c33dd 100644 --- a/mdsobjects/cpp/testing/MdsExpressionCompileTest.cpp +++ b/mdsobjects/cpp/testing/MdsExpressionCompileTest.cpp @@ -51,7 +51,7 @@ const char *PubCmds[] = { const int PubNCmd = sizeof(PubCmds) / sizeof(*PubCmds); const char *TreeCmds[] = { - "_a=*;ext_function('TreeShr','TreeCtx')", + "_a=*;TreeShr->TreeCtx()", }; const int TreeNCmd = sizeof(TreeCmds) / sizeof(*TreeCmds); diff --git a/mdsshr/librtl.c b/mdsshr/librtl.c index f6d883b3ac..a561462886 100644 --- a/mdsshr/librtl.c +++ b/mdsshr/librtl.c @@ -38,6 +38,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include <_mdsshr.h> @@ -62,8 +63,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "mdsthreadstatic.h" +#ifdef MDSPLUS_USE_FFI +#include +#endif + #define LIBRTL_SRC +#define LIBCALLG_MAX_ARGS 32 + typedef struct { char *env; @@ -280,6 +287,81 @@ EXPORT void *LibCallg(void **const a, void *(*const routine)()) return 0; } + +#ifdef MDSPLUS_USE_FFI +// This routine can call many external functions, but not all. +// Each parameter can be passed by reference or by value. +// However call-by-value must have a "size" that fits in a pointer. +// If the external function does not fit that constraint, users will have to write a shim function. +EXPORT void *LibCallgFfi(void **const a, void *(*const routine)(), int num_fixed_args, int rtype) +{ + assert(routine); // in DEBUG mode checks for stack corruption + + // The "a" parameter is the arglist for the "routine" and contains the following: + // arglist[0] = N (total number of args excluding first and last elements of vector) + // arglist[1] = expression for TDI intrinsics, otherwise an ordinary arg + // arglist[2 .. N-1] = variable args (pointer to descriptors) + // arglist[N] = result xd1 descriptor + // arglist[N+1] = NULL + int num_args = *(int *)a & 0xff; + + // Usually the check for non-variadic routines,and the associated call of LibCallg(), is + // done prior to calling this function. + if (num_fixed_args == 0) { + return LibCallg(a, routine); + + } else { + ffi_cif cif; + ffi_type *arg_types[LIBCALLG_MAX_ARGS]; + void *values[LIBCALLG_MAX_ARGS]; + void *result; + + if (num_args > LIBCALLG_MAX_ARGS) { + printf("Error - currently no more than %d arguments supported on external calls\n", LIBCALLG_MAX_ARGS); + return 0; + } + + if ((num_fixed_args < 1) || (num_fixed_args > num_args)) { + printf("Error - number of 'fixed' arguments must be in the range 1 through %d\n", num_args); + return 0; + } + + // Skip over first element because it is number of args, not an actual argument + for (int i=0; i #include #include +#include #include "devroutines.h" static void Load(Widget w); @@ -418,6 +419,7 @@ static int ReadChannel(InStoreStruct * setup, int chunk, int samples, unsigned s return status; } +// Usually called without a function, but once is called with TdiData(). static int AccessTraq(InStoreStruct * setup, int data, int memsize, void *arglist, int (*routine) (struct descriptor *,...)) { @@ -434,15 +436,18 @@ static int AccessTraq(InStoreStruct * setup, int data, int memsize, void *arglis for (try = 0; (try < 30) && (!(CamQ(0) & 1)) && (STATUS_OK); try++) { if (arglist && !called) { called = 1; - LibCallg(arglist, routine); + assert(routine == &TdiData); + // Only called with TdiData() which is an intrinsic thus MDS_FFI_RTN_INT32 + status = LIB_CALL_G(arglist, routine, 1, MDS_FFI_RTN_INT32); } else DevWait((float).001); piomem(17, 0, &data, memsize); } if (try == 30) status = DEV$_CAM_NOSQ; - if (arglist && !called) - LibCallg(arglist, routine); + if (arglist && !called) { + status = LIB_CALL_G(arglist, routine, 1, MDS_FFI_RTN_INT32); + } return status; } diff --git a/tdi/remote/MdsValue.fun b/tdi/remote/MdsValue.fun index b1323e38d2..8d9f076b19 100644 --- a/tdi/remote/MdsValue.fun +++ b/tdi/remote/MdsValue.fun @@ -17,7 +17,7 @@ call: mdsvalue('2+3 * $,',_p1); if(mdscurrent() == 'local') { return(execute(_p1,_p2,_p3,_p4,_p5,_p6,_p7,_p8,_p9,_p10,_p11,_p12,_p13,_p14,_p15,_p16,_p17,_p18,_p10,_p20)); } else { - _oo = "build_call(24,'TdiShrExt','rMdsValue',descr(_p1"; + _oo = "build_call(24,'TdiShrExt','rMdsValue#1',descr(_p1"; /* loop through verifying parameters */ for(_i=2;_i<=20; _i++) { _ss = '_p'//trim(adjustl(_i)); diff --git a/tdishr/TdiCall.c b/tdishr/TdiCall.c index f288432580..2a7cbcd114 100644 --- a/tdishr/TdiCall.c +++ b/tdishr/TdiCall.c @@ -65,49 +65,70 @@ extern int tdi_put_ident(); _Pragma("GCC diagnostic ignored \"-Wcast-function-type\"") #endif - static inline int interlude(dtype_t rtype, mdsdsc_t **newdsc, + // num_fixed_args is unused on all platforms except those that use libffi + static inline int interlude(dtype_t rtype, int bypass_ffi, __attribute__((unused)) int num_fixed_args, mdsdsc_t **newdsc, int (*routine)(), void **result, int *max) { switch (rtype) { case DTYPE_MISSING: - { - LibCallg(newdsc, routine); + *max = 0; + if (bypass_ffi) { + LibCallg(newdsc, routine); + } else { +#ifdef MDSPLUS_USE_FFI + LibCallgFfi(newdsc, routine, num_fixed_args, MDS_FFI_RTN_VOID); +#endif + } break; - } case DTYPE_C: case DTYPE_T: case DTYPE_POINTER: case DTYPE_DSC: - { - void *(*called_p)() = (void *(*)())LibCallg; - void **result_p = (void *)result; *max = sizeof(void *); - *result_p = called_p(newdsc, routine); + void **result_p = (void *)result; + void *(*called_p)() = (void *(*)())LibCallg; + if (bypass_ffi) { + *result_p = called_p(newdsc, routine); + } else { +#ifdef MDSPLUS_USE_FFI + *result_p = (void *) LibCallgFfi(newdsc, routine, num_fixed_args, MDS_FFI_RTN_POINTER); +#endif + } break; - } case DTYPE_D: case DTYPE_G: case DTYPE_FC: case DTYPE_FSC: case DTYPE_Q: case DTYPE_QU: - { // 8 bytes - int64_t (*called_q)() = (int64_t(*)())LibCallg; - int64_t *result_q = (int64_t *)result; + // 8 bytes *max = sizeof(int64_t); - *result_q = called_q(newdsc, routine); + int64_t *result_q = (int64_t *)result; + int64_t (*called_q)() = (int64_t(*)())LibCallg; + if (bypass_ffi) { + *result_q = called_q(newdsc, routine); + } else { +#ifdef MDSPLUS_USE_FFI + *result_q = (int64_t) LibCallgFfi(newdsc, routine, num_fixed_args, MDS_FFI_RTN_INT64); +#endif + } break; - } // case DTYPE_F: // case DTYPE_FS: default: - { // 4 bytes - int32_t (*called_int)() = (int32_t(*)())LibCallg; - int32_t *result_int = (int32_t *)result; + // 4 bytes *max = sizeof(int32_t); - *result_int = called_int(newdsc, routine); - } + int32_t *result_int = (int32_t *)result; + int32_t (*called_int)() = (int32_t(*)())LibCallg; + if (bypass_ffi) { + *result_int = called_int(newdsc, routine); + } else { +#ifdef MDSPLUS_USE_FFI + *result_int = (int32_t) LibCallgFfi(newdsc, routine, num_fixed_args, MDS_FFI_RTN_INT32); +#endif + } + break; } return 1; } @@ -115,13 +136,29 @@ _Pragma("GCC diagnostic ignored \"-Wcast-function-type\"") int get_routine(int narg, mdsdsc_t *list[], int (**proutine)()) { mdsdsc_xd_t image = EMPTY_XD, entry = EMPTY_XD; + mdsdsc_t new_entry = {0, DTYPE_T, CLASS_S, NULL }; + if (narg > 255 + 2) return TdiNDIM_OVER; int status = TdiData(list[0], &image MDS_END_ARG); if (STATUS_OK) status = TdiData(list[1], &entry MDS_END_ARG); - if (STATUS_OK) - status = TdiFindImageSymbol(image.pointer, entry.pointer, proutine); + + // Given "#" extract just the function name + if (STATUS_OK) { + char *c_entry = MdsDescrToCstring(entry.pointer); + char *hash_ptr = strrchr(c_entry, '#'); + if (hash_ptr == NULL) { + status = TdiFindImageSymbol(image.pointer, entry.pointer, proutine); + } else { + *hash_ptr = '\0'; + new_entry.length = strlen(c_entry); + new_entry.pointer = c_entry; + status = TdiFindImageSymbol(image.pointer, &new_entry, proutine); + } + free(c_entry); + } + if (STATUS_NOT_OK) printf("%s\n", LibFindImageSymbolErrString()); MdsFree1Dx(&entry, NULL); @@ -163,7 +200,27 @@ int tdi_call(dtype_t rtype, int narg, mdsdsc_t *list[], mdsdsc_xd_t *out_ptr, cl unsigned short code; mdsdsc_t dx = {0, rtype == DTYPE_C ? DTYPE_T : rtype, CLASS_S, result}; unsigned char origin[255]; - mdsdsc_t *newdsc[256] = {0}; + mdsdsc_t *newdsc[256] = {0}; // one bigger than origin because also has descriptor for result + + #ifdef MDSPLUS_USE_FFI + // Given "#" extract just the number of fixed args + char *c_entry = MdsDescrToCstring(list[1]); + char *hash_ptr = strrchr(c_entry, '#'); + int bypass_ffi = TRUE; + int num_fixed_args = 0; + if (hash_ptr != NULL) { + hash_ptr++; + num_fixed_args = atoi(hash_ptr); + } + if (num_fixed_args != 0) { + bypass_ffi = FALSE; + } + free(c_entry); + #else + int bypass_ffi = TRUE; // for Linux, Windows and MacOS(Intel) + int num_fixed_args = 0; + #endif + *(int *)&newdsc[0] = narg - 2; for (j = 2; j < narg && STATUS_OK; ++j) { @@ -245,7 +302,7 @@ int tdi_call(dtype_t rtype, int narg, mdsdsc_t *list[], mdsdsc_xd_t *out_ptr, cl } } if (STATUS_OK) - status = interlude(rtype, newdsc, routine, (void **)result, &max); + status = interlude(rtype, bypass_ffi, num_fixed_args, newdsc, routine, (void **)result, &max); if (!out_ptr) goto skip; if (STATUS_OK) diff --git a/tdishr/TdiDoTask.c b/tdishr/TdiDoTask.c index c4fa1d87f5..0fa511bc9e 100644 --- a/tdishr/TdiDoTask.c +++ b/tdishr/TdiDoTask.c @@ -96,7 +96,7 @@ static int Doit(struct descriptor_routine *ptask, status = TdiData(pmethod->method, &method_d MDS_END_ARG); if (STATUS_OK) status = TdiGetNid(pmethod->object, &nid); - status = (int)(intptr_t)LibCallg(arglist, TreeDoMethod); + status = LIB_CALL_G(arglist, TreeDoMethod, 2, MDS_FFI_RTN_INT32); FREED_NOW(&method_d); status = TdiPutLong(&status, out_ptr); break; diff --git a/tdishr/TdiExtFunction.c b/tdishr/TdiExtFunction.c index cdc195e07b..96cf17e862 100644 --- a/tdishr/TdiExtFunction.c +++ b/tdishr/TdiExtFunction.c @@ -55,14 +55,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -extern int TdiFaultHandler(); extern int TdiData(mdsdsc_t *, ...); extern int TdiDoFun(); -extern int TdiGetLong(); -extern int TdiAllocated(mdsdsc_t *, ...); -extern int tdi_put_ident(); -extern int TdiCompile(mdsdsc_t *, ...); -extern int TdiEvaluate(mdsdsc_t *, ...); static const struct descriptor_d EMPTY_D = {0, DTYPE_T, CLASS_D, 0}; @@ -74,17 +68,6 @@ int TdiFindImageSymbol(struct descriptor_d *image, struct descriptor_d *entry, extern int TdiFindSymbol(); -struct _tmp -{ - int n; - struct descriptor_xd a[253]; -}; -static void tmp_cleanup(void *tmp_in) -{ - struct _tmp *tmp = (struct _tmp *)tmp_in; - for (; --tmp->n >= 0;) - MdsFree1Dx(&tmp->a[tmp->n], NULL); -} int Tdi1ExtFunction(opcode_t opcode __attribute__((unused)), int narg, struct descriptor *list[], struct descriptor_xd *out_ptr) { @@ -100,95 +83,22 @@ int Tdi1ExtFunction(opcode_t opcode __attribute__((unused)), int narg, if (STATUS_NOT_OK) goto done; /************************** - Quickly do known functions. + Quickly do known TDI functions. **************************/ - int (*routine)(); if (image.length == 0) { status = StrUpcase((struct descriptor *)&entry, (struct descriptor *)&entry); if (STATUS_OK) status = TdiDoFun(&entry, narg - 2, &list[2], out_ptr); - goto done; - } - status = TdiFindImageSymbol(&image, &entry, &routine); - /********************************************** - Requires: image found and routine symbol found. - **********************************************/ - if (STATUS_OK) - { - int j = 0; - struct _tmp tmp = {0}; - pthread_cleanup_push(tmp_cleanup, (void *)&tmp); - status = MDSplusSUCCESS; - struct descriptor_function *pfun; - struct descriptor *new[256]; - *(int *)&new[0] = narg - 1; - new[narg - 1] = (struct descriptor *)out_ptr; - unsigned short code; - for (j = 2; j < narg && STATUS_OK; ++j) - { - pfun = (struct descriptor_function *)(new[j - 1] = list[j]); - if (pfun) - { - if (pfun->dtype == DTYPE_FUNCTION) - { - /**************************************** - Special forms used for VMS and LIB calls. - ****************************************/ - code = *(unsigned short *)pfun->pointer; - if (code == OPC_DESCR) - { - tmp.a[tmp.n] = EMPTY_XD; - status = TdiData(pfun->arguments[0], &tmp.a[tmp.n] MDS_END_ARG); - new[j - 1] = (struct descriptor *)tmp.a[tmp.n++].pointer; - } - else if (code == OPC_REF) - { - tmp.a[tmp.n] = EMPTY_XD; - status = TdiData(pfun->arguments[0], &tmp.a[tmp.n] MDS_END_ARG); - if (STATUS_NOT_OK) - break; // .pointer == NULL - new[j - 1] = (struct descriptor *)tmp.a[tmp.n++].pointer->pointer; - } - else if (code == OPC_VAL) - status = TdiGetLong(pfun->arguments[0], &new[j - 1]); - else if (code == OPC_PRIVATE || code == OPC_PUBLIC) - goto ident; - } - else if (pfun->dtype == DTYPE_IDENT) - { - ident:; - /************************************ - Handle multiple outputs to variables. - So far only DSQL needs this. - ************************************/ - unsigned char test; - struct descriptor dtest = {sizeof(test), DTYPE_BU, CLASS_S, 0}; - dtest.pointer = (char *)&test; - status = TdiAllocated((mdsdsc_t *)pfun, &dtest MDS_END_ARG); - if (status && !test) - { - status = tdi_put_ident(pfun, 0); - } - } - } - } - /************************* - Same form as system calls. - Watch, may not be XD. - *************************/ - if (STATUS_OK) - { - struct descriptor_s out = {sizeof(void *), DTYPE_POINTER, CLASS_S, - LibCallg(&new[0], routine)}; - MdsCopyDxXd((struct descriptor *)&out, out_ptr); - } - pthread_cleanup_pop(1); + } else { + printf("\n"); + printf("** The EXT_FUNCTION(, , ...) feature has been removed. **\n"); + printf("** Please rewrite using the BUILD_CALL (aka ->) function. **\n\n"); + status = MDSplusERROR; } - else - printf("%s\n", LibFindImageSymbolErrString()); + done:; FREED_NOW(&entry); FREED_NOW(&image); diff --git a/tdishr/TdiExtPython.c b/tdishr/TdiExtPython.c index 93ac13ecca..186d1428a4 100644 --- a/tdishr/TdiExtPython.c +++ b/tdishr/TdiExtPython.c @@ -90,7 +90,11 @@ static int (*PyCallable_Check)() = NULL; static void (*PyErr_Clear)() = NULL; static PyObject *(*PyImport_AddModule)() = NULL; static PyObject *(*PyModule_AddObject)() = NULL; +#ifdef MACOS_ARM64 +static PyObject *(*PyObject_CallFunctionObjArgs)(void *, ...) = NULL; +#else static PyObject *(*PyObject_CallFunctionObjArgs)() = NULL; +#endif static PyObject *(*PyString_FromString)() = NULL; // callPyFunction static PyObject *_Py_NoneStruct = NULL; @@ -101,7 +105,11 @@ static int (*PyObject_IsSubclass)() = NULL; static void *(*PyLong_AsVoidPtr)() = NULL; static PyObject *(*PyObject_GetAttrString)() = NULL; // args_to_tuple +#ifdef MACOS_ARM64 +static PyObject *(*PyObject_CallFunction)(void *, void *, ...) = NULL; +#else static PyObject *(*PyObject_CallFunction)() = NULL; +#endif static PyObject *(*PyTuple_New)() = NULL; static void (*PyTuple_SetItem)() = NULL; #ifdef USE_EXECFILE diff --git a/tdishr/TdiLex.l b/tdishr/TdiLex.l index 6e6df859bf..1418cc1923 100644 --- a/tdishr/TdiLex.l +++ b/tdishr/TdiLex.l @@ -159,7 +159,7 @@ int ([[:digit:]][[:alnum:]]*) float ({f0}|{f1}|{f2}|{f3}) ident ([[:alpha:]$_]{anum}*) path (((("\\"({ident}"::")?|[.:])?{ident})|(".-"("."?"-")*))([.:]{ident})*) -libcall ("->"{anum}+(":"|"..")?) +libcall ("->"{anum}+("#"{int})?(":"|"..")?) comment ("/*"(\n|[^\*]+|\*+[^/\*])*\*+"/") sqtext ("\'"(\n|\\.|[^'\\])*"\'") dqtext ("\""(\n|\\.|[^"\\])*"\"") diff --git a/treeshr/TreeDoMethod.c b/treeshr/TreeDoMethod.c index dcfbd55add..4858bb88f3 100644 --- a/treeshr/TreeDoMethod.c +++ b/treeshr/TreeDoMethod.c @@ -171,6 +171,10 @@ int _TreeDoMethodA(void *dbid, mdsdsc_t *nid_dsc, mdsdsc_t *method_ptr, status = TdiINVDTYDSC; goto end; } + // MACOS_ARM64: If the device calls a variadic function, then the call + // to _LibCallg() will segfault on Apple Silicon. However, it is unlikely + // that Apple Silicon will be used for data acquistion servers (which are + // typically Linux). Thus leaving this "as is" until bugs are reported. void (*addr)(); status = LibFindImageSymbol(conglom_ptr->image, &method, &addr); if (STATUS_OK)