theKernel 10.0
Loading...
Searching...
No Matches
MkCall_tcl.c
Go to the documentation of this file.
1
9/* LABEL-NO */
10
11#include "LibMkKernel_tcl.h"
12#include "mk_check_tcl.h"
13#include <tclInt.h>
14
15/*****************************************************************************/
16/* */
17/* Proc-Call */
18/* */
19/*****************************************************************************/
20
22{
24 if ((*skipP) >= objc) {
25 WrongNumArgs(hdl,(*skipP), objc, -999, +999, arg);
26 goto error;
27 }
28 Tcl_ResetResult(interp);
29 OT_OBJ_T argO = objv[(*skipP)++];
30
31 int myobjc;
32 Tcl_Obj **myobjv;
33 check_LNG (Tcl_ListObjGetElements(interp, argO, &myobjc, &myobjv)) goto tcl_error;
34
35 // BUG-FIX: set the "default" value for "NULL" = ""
36 // defined in: ./lib_TCL.tcl → map_M2C
37 // mark=MK_NULL
38 if (myobjc == 0) goto null; /* empty list */
39 if (Tcl_GetObjectFromObj (interp, myobjv[0])) { /* method? */
40 if (myobjc > 1 && OT_LNG_NULL_IS(myobjv[1])) goto null;
41 } else {
42 Tcl_ResetResult(interp);
43 if (OT_LNG_NULL_IS(myobjv[0])) goto null; /* proc */
44 }
45
46 struct MkCallS *call = *retP;
47
48 if (*retP == NULL) {
49 call = *retP = MkSysCalloc(MK_ERROR_PANIC,1,sizeof(struct MkCallS));
50 call->isAlloc = true;
51 }
52
53 call->signature = MkCallS_SIG;
54 call->mth = argO;
55 call->hdl = hdl;
56 call->interp = interp;
57 call->mkrt = MK_RT_PTR;
58 call->nsO = STRN2VAL(Tcl_GetCurrentNamespace(interp)->fullName);
59
60 OT_REF_INCR(call->mth);
61 OT_REF_INCR(call->nsO);
62
63//colorGREEN("call<%p>, type<%d>, nsO<%p>",call,call->type,call->nsO);
64
65 return MK_OK;
66tcl_error:
68error:
69 return MkErrorStack_0E();
70null:
71 *retP = NULL;
72 return MK_OK;
73}
74
75#define mycheck_LNG(val) \
76 check_LNG(val) { \
77 OT_ERROR_LNG_2_META(hdl); \
78 goto error; \
79 }
80
81#define mycheck_NULL(var) \
82 check_NULL(var) { \
83 OT_ERROR_LNG_2_META(hdl); \
84 goto error; \
85 }
86
87#define mycheck_NULL_2(var,str) \
88 check_NULL(var) { \
89 MkErrorSetC_2M(hdl,str); \
90 goto error; \
91 }
92
93#define myListObjIndex(itp,lst,idx) ({ \
94 OT_OBJ_T _ret; \
95 mycheck_LNG(Tcl_ListObjIndex(itp,lst,idx,&_ret)); \
96 mycheck_NULL_2(_ret,"LIST-IDX-LOOKUP-ERROR at " #lst "' index '" #idx "'"); \
97 _ret; \
98})
99
100#define myListObjPop(itp,lst) ({ \
101 OT_OBJ_T _ret = myListObjIndex(itp,lst,0); \
102 Tcl_IncrRefCount(_ret); \
103 mycheck_LNG(Tcl_ListObjReplace(itp,lst,0,1,0,NULL)); \
104 _ret; \
105})
106
107#define myListObjLength(itp,lst) ({ \
108 int _len=0; \
109 mycheck_LNG(Tcl_ListObjLength(itp, lst, &_len)); \
110 _len; \
111})
112
113#define myGetBooleanFromObj(itp,lngO) ({ \
114 int _retB = 0; \
115 mycheck_LNG(Tcl_GetBooleanFromObj(itp,lngO,&_retB)); \
116 ( _retB > 0 ); \
117})
118
119#define myEvalObjvAR(frm,itp,opt,objc,objv) ({ \
120 OT_OBJ_T _ret = MK(EvalObjvAR)(MK_RT_CALL frm, itp, opt, objc, objv); \
121 mycheck_NULL(_ret); \
122 _ret; \
123})
124
125#define myGetObjectFromObj(itp,_mng,slf) ({ \
126 OT_SELF_T _ret = Tcl_GetObjectFromObj(itp,slf); \
127 check_NULL(_ret) { \
128 MkErrorSetC_2M(_mng,Tcl_GetStringResult (itp)); \
129 goto error; \
130 } \
131 _ret; \
132})
133
134#define myWrongTypeOfStaticArgError(exp,cls,got) \
135 MkErrorVD("WrongTypeOfStaticArgError", "expect type '%s' for class '%s', but got '%s'", exp, cls, got ); \
136 goto error;
137
138static enum MkErrorE NS(sProcResolve_StaticMethod)(
141 MK_MNG hdl,
142 struct MkCallS *call,
143 OT_OBJ_T clsO,
144 OT_OBJ_T *mthOP,
145 bool needArg,
146 bool needError
147) {
148 enum MkErrorE ret = MK_OK;
149 OT_OBJ_T mthO = *mthOP;
150
151//X0(hdl)
152//printXLng(hdl,clsO)
153//printXLng(hdl,mthO)
154
155 // is a "PRIVATE/PUBLIC method"
156 // call: info object methods -all -private
157 OT_OBJ_T mthL = NULL;
158 {
159 RL_init( RL_O(0,RG(infoObjectMethodsCmd)) RL_NewS(2,"-all") RL_NewS(3,"-private") ) RL_O(1,clsO);
160 mthL = myEvalObjvAR(varframe,interp,TCL_EVAL_GLOBAL,4,RL_data);
161 }
162
163 // search for the meth, result: >0 found, -1 = not found
164 // lsearch -exact mthL mthO
165 OT_OBJ_T isMthO = NULL;
166 {
167 RL_init( RL_NewS(0,"lsearch") RL_NewS(1,"-exact") ) ; RL_O(2,mthL) ; RL_O(3,mthO)
168 isMthO = myEvalObjvAR(varframe,interp,TCL_EVAL_GLOBAL, 4, RL_data);
169 }
170
171 int mthIdx;
172 mycheck_LNG(Tcl_GetIntFromObj(interp,isMthO,&mthIdx));
173
174 if (mthIdx == -1) {
175 RL_init( RL_O(0,RG(infoClassSuperclassesCmd)) ) ; RL_O(1,clsO)
176
177 // CURRENT class has NO method -> continue with superclass
178 // call: info class subclasses CLASS
179 OT_OBJ_T superclassesL = myEvalObjvAR(varframe,interp,TCL_EVAL_GLOBAL, 2, RL_data);
180
181//printXLng(hdl,superclassesL)
182
183 // get superclassesL as objv
184 int objc;
185 OT_OBJ_T *objv;
186 mycheck_LNG(Tcl_ListObjGetElements(interp,superclassesL,&objc,&objv));
187 for (int i=0; i<objc; i++) {
188 check_META(NS(sProcResolve_StaticMethod)(OT_VARFRAME_CALL,interp,hdl,call,objv[i],mthOP,true,false)) continue;
189 // ok found something
190 goto end;
191 }
192 if (needError) {
193 myWrongTypeOfStaticArgError("static Callable", VAL2STR(clsO), VAL2STR(mthO));
194 } else {
195 goto error;
196 }
197 goto end;
198
199 } else {
200
201 // get static "my"
202 OT_SELF_T object = myGetObjectFromObj(interp,hdl,clsO);
203 OT_OBJ_T myCmdO = MK(GetMyFromObject)(interp,object);
204 check_NULL(myCmdO) {
206 goto error;
207 }
208
209 call->type = MkCallS_static;
210 call->my = myCmdO;
211 Tcl_IncrRefCount(myCmdO);
212 call->mth = mthO;
213 Tcl_IncrRefCount(mthO);
214 *mthOP = NULL;
215 }
216
217end:
218//printTxt("OK");
219 return ret;
220
221error:
222
223 call->type = MkCallS_error;
224 call->my = NULL;
225 call->mth = NULL;
226
227//printXTxt(hdl,"ERROR");
228//printXTxt(hdl,MkErrorGetText_0E());
229//printXTxt(hdl,Tcl_GetStringResult(interp));
230 return MK_ERROR;
231}
232
233#if 0
234 #define dbgMsg(fmt,...) printV(fmt,__VA_ARGS__)
235 #define dbgObj(obj) printLngObj(obj)
236#else
237 #define dbgMsg(fmt,...)
238 #define dbgObj(obj)
239#endif
240
241enum MkErrorE NS(ProcResolve) (
244 MK_MNG hdl,
245 struct MkCallS *call
246) {
247//L0
249 enum MkErrorE ret = MK_OK;
250 OT_OBJ_T arg0 = NULL;
251 OT_OBJ_T arg1 = NULL;
252 OT_OBJ_T tstO = Tcl_DuplicateObj(call->mth);
253
254 if (call->nsPtr == NULL) {
255 call->nsPtr = Tcl_FindNamespace(interp,VAL2STR(call->nsO),NULL,TCL_GLOBAL_ONLY);
256 if (call->nsPtr == NULL) return MK_OK ; // instance namespace already deleted
257 }
258
259 Namespace * savedNsPtr = NULL;
260 Tcl_Command procCmd = NULL;
261 Interp *iPtr = (Interp *) interp;
262
263 // check if "arg0" is an object or class
264 arg0 = myListObjPop(interp,tstO);
265
266dbgMsg("nsPtr<%p>", call->nsPtr)
267
268 savedNsPtr = iPtr->varFramePtr->nsPtr;
269 iPtr->varFramePtr->nsPtr = (Namespace *) call->nsPtr;
270
271dbgObj(arg0);
272
273 //Tcl_Command procCmd = Tcl_FindCommand (interp,Tcl_GetString(arg0),call->ns,0);
274 procCmd = Tcl_GetCommandFromObj (interp,arg0);
275
276dbgMsg("procCmd<%p>", procCmd)
277
278 if (procCmd != NULL) {
279
280 OT_SELF_T obj0 = Tcl_GetObjectFromObj(interp,arg0);
281 Tcl_ResetResult(interp);
282
283 if (obj0 != NULL) {
284dbgMsg("%s","object")
285 // first is NON "proc" and "object" → interface, method (own or other)
286
287 arg1 = myListObjPop(interp,tstO);
288
289 // check if "arg0" is an "instance" or "class"
290 OT_CLS_T cls0 = Tcl_GetObjectAsClass(obj0);
291
292 if (cls0 != NULL) {
293dbgMsg("%s","class method")
294 // class method -> static
295 check_META(NS(sProcResolve_StaticMethod)( OT_VARFRAME_CALL,interp,hdl,call,arg0,&arg1,true,true)) goto error;
296 } else {
297dbgMsg("%s","instance method")
298 // instance method
299 OT_OBJ_T myCmdO = MK(GetMyFromObject)(interp,obj0);
300 check_NULL(myCmdO) {
302 goto error;
303 }
304
306 call->my = myCmdO;
307 Tcl_IncrRefCount(myCmdO);
308 call->mth = arg1;
309 Tcl_IncrRefCount(arg1);
310 arg1 = NULL;
311 }
312
313 } else {
314
315dbgMsg("%s","proc")
316 call->type = MkCallS_proc;
317 call->mth = arg0;
318 Tcl_IncrRefCount(arg0);
319 arg0 = NULL;
320 }
321
322 } else {
323dbgMsg("%s","NON proc instance method")
324 // first is NON "proc" and NON "object" → method on OWN class
325 call->type = MkCallS_own_method;
326 call->my = NULL;
327 call->mth = arg0;
328 Tcl_IncrRefCount(arg0);
329 arg0 = NULL;
330 }
331
332 // resolve additional arguments
333 int tstOLen = myListObjLength(interp, tstO);
334 if (tstOLen > MkProcResolve_maxArgsLen) {
335 MkErrorSetV_2M(hdl, "expect max '%d' additional arguments to callback but got '%d' "
336 "with '%s'", MkProcResolve_maxArgsLen, tstOLen, Tcl_GetString(tstO));
337 goto error;
338 } else if (tstOLen > 0) {
339 call->args = tstO;
340 Tcl_IncrRefCount(tstO);
341 tstO = NULL;
342 } else {
343 call->args = NULL;
344 }
345
346end:
351 if (savedNsPtr) iPtr->varFramePtr->nsPtr = savedNsPtr;
352 return ret;
353
354error:
355 ret = MkErrorStack_1M(hdl);
356 if (savedNsPtr) iPtr->varFramePtr->nsPtr = savedNsPtr;
357 goto end;
358}
359
360// **********************************************************************
361
362/*
363[ObjectDeleteCall signature]
364 callback-args := typeName:MK_STRN[in], typeHdl:MK_HDL[in], objHdl:MK_HDL[in]
365 [static] proc callback { callback-args ?additional-args...? } ...
366 MkObjectC DeleteCallbackSetup "NAME" callback "FILTER"
367 [instance] ::oo::class create XXX {
368 method callback { callback-args ?additional-args...? } ...
369 }
370 MkObjectC DeleteCallbackSetup "NAME" [list [self] callback] "FILTER"
371 [class] ::oo::class create YYY {
372 self method callback { callback-args ?additional-args...? } ...
373 }
374 MkObjectC DeleteCallbackSetup "NAME" [list YYY callback] "FILTER"
375[ObjectDeleteCall signature]
376*/
377
378enum MkErrorE NS(ObjectDeleteCall) ( MkObjectDeleteCallF_ARGS )
379{
381
382 // if NO self object is available than NO callback is called
383 if (!MkSelfExists(obj)) return MK_OK;
384
385 // 1. setup environment
387 if (interp==NULL || Tcl_InterpDeleted(interp)) return MK_OK;
388
389 // 2. setup arguments
390 struct MkCallS *call = __data__;
392 int objc = 0;
393
394 //Tcl_ResetResult(interp);
395//printLLngObj(call->mth);
396
397 // 3. setup my
398rescan:
399 switch (call->type) {
401//printLTxt("MkCallS_own_method");
402 return MkErrorSetC_1E("MkCallS_own_method not supported");
403 break;
405 case MkCallS_static:
406//printLTxt("MkCallS_other_method OR MkCallS_static");
407 objv[objc++] = call->my;
408 break;
409 case MkCallS_proc:
410//printLTxt("MkCallS_proc");
411 break;
412 case MkCallS_init: {
413 check_META(MK(ProcResolve)(MK_RT_CALL interp, call->hdl, call)) goto error_mq;
414 goto rescan;
415 }
416 case MkCallS_error:
417//printLTxt("MkCallS_error");
418 goto error;
419 case MkCallS_null:
420//printLTxt("MkCallS_null");
421 return MK_OK;
422 }
423
424 // 4. setup methode
425 if (call->mth) objv[objc++] = call->mth;
426
427 // 5. setup OBJ arg
428 switch (call->type) {
430 case MkCallS_static:
431 case MkCallS_proc:
432 objv[objc++] = STR2VAL(typeName,-1);
433 objv[objc++] = HDL2VAL(typeHdl);
434 objv[objc++] = HDL2VAL(objHdl);
435 break;
437 case MkCallS_init:
438 break;
439 case MkCallS_error:
440 goto error;
441 case MkCallS_null:
442 return MK_OK;
443 }
444
445 if (call->args) MK(ProcResolveAppendArgs)(call,&objc,objv);
446
447 // 3. call the callback
448 // require "MK(EvalObjv)" to cleanup "objv"
449 int ret = MK(EvalObjv) (interp, objc, objv, TCL_EVAL_GLOBAL);
450
451//printV("ret=%i, code=%s\n", ret, MkLogErrorE(MkErrorGetCode_0E()))
452
453 if (ret == TCL_OK) {
454 Tcl_ResetResult(interp);
455 return MkErrorGetCode_0E();
456 }
457
458error:
460
461error_mq:
462 return MkErrorStack_0E();
463}
464
465void NS(ObjectDeleteFree) ( MkObjectDeleteFreeF_ARGS )
466{
467 if ( MK_RT_REF.mkThreadData.ptr == NULL || Tcl_InterpDeleted(MK_RT_REF.mkThreadData.ptr)) return;
468 MK(CallFree)(dataP);
469}
470
tag: nhi1-release-250425
#define HDL2VAL(nat)
#define check_NULL(code)
#define MK(n)
#define VAL2STR(obj)
Tcl_Class OT_CLS_T
#define OT_VARFRAME_DELETE
#define RL_NewS(num, str)
#define MkCallS_SIG
#define OT_Check_ARGS
#define STR2VAL(ptr, len)
#define check_META(code)
#define NS(n)
#define OT_SETUP_doc
#define RL_O(num, obj)
#define check_LNG(code)
#define OT_ERROR_LNG_2_META(m)
#define OT_VARFRAME_CALL
Tcl_Object OT_SELF_T
#define MkProcResolve_maxArgsLen
#define RL_init(code)
#define OT_REF_DECR_AND_NULL(_obj)
#define RG(_key)
#define OT_REF_INCR(_obj)
#define OT_VARFRAME_CREATE
Tcl_Interp * OT_ENV_T
Tcl_Obj * OT_OBJ_T
#define STRN2VAL(nat)
#define OT_VARFRAME_ARGS
#define SETUP_interp
#define dbgObj(obj)
Definition MkCall_tcl.c:238
#define mycheck_LNG(val)
Definition MkCall_tcl.c:75
#define myWrongTypeOfStaticArgError(exp, cls, got)
Definition MkCall_tcl.c:134
#define myEvalObjvAR(frm, itp, opt, objc, objv)
Definition MkCall_tcl.c:119
#define myGetObjectFromObj(itp, _mng, slf)
Definition MkCall_tcl.c:125
#define myListObjLength(itp, lst)
Definition MkCall_tcl.c:107
#define dbgMsg(fmt,...)
Definition MkCall_tcl.c:237
#define myListObjPop(itp, lst)
Definition MkCall_tcl.c:100
#define MkErrorGetCode_0E()
#define MkErrorStack_1M(err)
#define MkErrorStack_0E()
#define MkErrorSetC_1E(message)
#define MkErrorSetV_2M(err, printfmt,...)
#define MK_ERROR_PANIC
MkErrorE
collection for the different error-codes …
@ MK_ERROR
(persistent) raise an error-event, the calling-fucntion is interrupted.
@ MK_OK
(persistent) everything is OK.
MK_PTRB * MK_MNG
managed object pointer, datatype will be checked at runtime
MK_PTRB * MK_CBP
generic pointer to call-back data
static bool MkSelfExists(MK_OBJN obj)
Check if the MkObjectS::self exists …
MK_PTR MkSysCalloc(MK_OBJN fmtobj, size_t const nmemb, size_t const size)
calloc syscall with tclmkkernel error plugin
#define MkObjectDeleteCallF_CHECK
validate call to MkObjectDeleteCallF
#define MkObjectDeleteCallF_ARGS
the MkObjectDeleteCallF arguments with default names
#define MkObjectDeleteFreeF_ARGS
the MkObjectDeleteFreeF arguments with default names
#define MK_RT_PTR
#define MK_RT_CALL
#define MK_RT_ARGS
#define MK_RT_REF
#define WrongNumArgs(...)
MK_EXTERN enum MkErrorE MK_DECL MK CheckCallable(OT_Check_ARGS, MK_CBP *)
enum MkCallS::@0 type
OT_OBJ_T mth
OT_ENV_T interp
OT_OBJ_T args
OT_NS_T nsPtr
OT_OBJ_T nsO
MK_SIG signature
OT_OBJ_T my