1 /*
2  *  nsfInt.h --
3  *
4  *      Declarations of the internally used API Functions of the Next
5  *      Scripting Framework.
6  *
7  *  Copyright (C) 1999-2018 Gustaf Neumann (a, b)
8  *  Copyright (C) 1999-2007 Uwe Zdun (a, b)
9  *  Copyright (C) 2011-2018 Stefan Sobernig (b)
10  *
11  * (a) University of Essen
12  *     Specification of Software Systems
13  *     Altendorferstrasse 97-101
14  *     D-45143 Essen, Germany
15  *
16  * (b) Vienna University of Economics and Business
17  *     Institute of Information Systems and New Media
18  *     A-1020, Welthandelsplatz 1
19  *     Vienna, Austria
20  *
21  * This work is licensed under the MIT License
22  * https://www.opensource.org/licenses/MIT
23  *
24  * Copyright:
25  *
26  * Permission is hereby granted, free of charge, to any person obtaining a
27  * copy of this software and associated documentation files (the "Software"),
28  * to deal in the Software without restriction, including without limitation
29  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
30  * and/or sell copies of the Software, and to permit persons to whom the
31  * Software is furnished to do so, subject to the following conditions:
32  *
33  * The above copyright notice and this permission notice shall be included in
34  * all copies or substantial portions of the Software.
35  *
36  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
37  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
39  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
40  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
41  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
42  * DEALINGS IN THE SOFTWARE.
43  *
44  */
45 
46 #ifndef _nsf_int_h_
47 #define _nsf_int_h_
48 
49 /*
50  * Well behaved compiler with C99 support should define __STDC_VERSION__
51  */
52 #if defined(__STDC_VERSION__)
53 # if __STDC_VERSION__ >= 199901L
54 #  define NSF_HAVE_C99
55 # endif
56 #endif
57 
58 /*
59  * Starting with Visual Studio 2013, Microsoft provides C99 library support.
60  */
61 #if (!defined(NSF_HAVE_C99)) && defined(_MSC_VER) && (_MSC_VER >= 1800)
62 # define NSF_HAVE_C99
63 #endif
64 
65 #if defined(_MSC_VER) && _MSC_VER < 1800
66 # undef HAVE_INTTYPES_H
67 #else
68 # define HAVE_INTTYPES_H 1
69 #include <inttypes.h>
70 #endif
71 
72 #if !defined(HAVE_INTTYPES_H)
73 # if !defined(__PRIPTR_PREFIX)
74 #  if defined(_LP64) || defined(_I32LPx) || defined(HAVE_64BIT) || defined(_WIN64) || defined(_WIN32)
75 #   if defined(_WIN32)
76 #    define __PRIPTR_PREFIX "ll"
77 #   else
78 #    define __PRIPTR_PREFIX "l"
79 #   endif
80 #  else
81 #   define __PRIPTR_PREFIX
82 #  endif
83 # endif
84 # ifndef PRIxPTR
85 #  define PRIxPTR    __PRIPTR_PREFIX "x"
86 # endif
87 #endif
88 
89 
90 /*
91  * Boolean type "bool" and constants
92  */
93 #ifdef NSF_HAVE_C99
94    /*
95     * C99
96     */
97 # include <stdbool.h>
98 # define NSF_TRUE                    true
99 # define NSF_FALSE                   false
100 #else
101    /*
102     * Not C99
103     */
104 # if defined(__cplusplus)
105    /*
106     * C++ is similar to C99, but no include necessary
107     */
108 #  define NSF_TRUE                    true
109 #  define NSF_FALSE                   false
110 # else
111    /*
112     * If everything fails, use int type and int values for bool
113     */
114 typedef int bool;
115 #  define NSF_TRUE                    1
116 #  define NSF_FALSE                   0
117 # endif
118 #endif
119 
120 
121 /*
122  * MinGW and MinGW-w64 provide both MSCRT-compliant and ANSI-compliant
123  * implementations of certain I/O operations (e.g., *printf()). By
124  * setting __USE_MINGW_ANSI_STDIO to 1 explicitly, we can assume the
125  * ANSI versions.
126  *
127  * Note: It is sufficient to test for __MINGW32__ to trap all MinGW
128  * tool chains, including 64bit versions. See
129  * https://sourceforge.net/p/predef/wiki/Compilers/#mingw-and-mingw-w64
130  */
131 
132 #if defined(__MINGW32__) && !defined(__USE_MINGW_ANSI_STDIO)
133 # define __USE_MINGW_ANSI_STDIO 1
134 #endif
135 
136 #include <tclInt.h>
137 #include "nsf.h"
138 
139 #include <stdlib.h>
140 #include <string.h>
141 #include <assert.h>
142 
143 #if defined(HAVE_TCL_COMPILE_H)
144 # include <tclCompile.h>
145 #endif
146 
147 #if __GNUC_PREREQ(2, 95)
148 /* Use gcc branch prediction hint to minimize cost of e.g. DTrace
149  * ENABLED checks.
150  */
151 #  define unlikely(x) (__builtin_expect((x), 0))
152 #  define likely(x) (__builtin_expect((x), 1))
153 #else
154 #  define unlikely(x) (x)
155 #  define likely(x) (x)
156 #endif
157 
158 #if __GNUC_PREREQ(2, 96)
159 # define pure __attribute__((pure))
160 #else
161 # define pure
162 #endif
163 
164 #if __GNUC_PREREQ(3, 3)
165 # define nonnull(ARGS) __attribute__((__nonnull__(ARGS)))
166 #else
167 # define nonnull(ARGS)
168 #endif
169 
170 #if __GNUC_PREREQ(4, 9)
171 # define returns_nonnull __attribute__((returns_nonnull))
172 #else
173 # define returns_nonnull
174 #endif
175 
176 #define nonnull_assert(assertion) assert((assertion))
177 /*
178  * Tries to use gcc __attribute__ unused and mangles the name, so the
179  * attribute could not be used, if declared as unused.
180  */
181 #ifdef UNUSED
182 #elif __GNUC_PREREQ(2, 7)
183 # define UNUSED(x) UNUSED_ ## x __attribute__((unused))
184 #elif defined(__LCLINT__)
185 # define UNUSED(x) /*@unused@*/ (x)
186 #else
187 # define UNUSED(x) (x)
188 #endif
189 
190 #if defined(NSF_DTRACE)
191 # include "nsfDTrace.h"
192 # define NSF_DTRACE_METHOD_ENTRY_ENABLED()		unlikely(NSF_METHOD_ENTRY_ENABLED())
193 # define NSF_DTRACE_METHOD_RETURN_ENABLED()		unlikely(NSF_METHOD_RETURN_ENABLED())
194 # define NSF_DTRACE_OBJECT_ALLOC_ENABLED()		unlikely(NSF_OBJECT_ALLOC_ENABLED())
195 # define NSF_DTRACE_OBJECT_FREE_ENABLED()		unlikely(NSF_OBJECT_FREE_ENABLED())
196 # define NSF_DTRACE_CONFIGURE_PROBE_ENABLED()		unlikely(NSF_CONFIGURE_PROBE_ENABLED())
197 # define NSF_DTRACE_METHOD_ENTRY(a0, a1, a2, a3, a4)	NSF_METHOD_ENTRY((a0), (a1), (a2), (a3), (a4))
198 # define NSF_DTRACE_METHOD_RETURN(a0, a1, a2, a3)	NSF_METHOD_RETURN((a0), (a1), (a2), (a3))
199 # define NSF_DTRACE_OBJECT_ALLOC(a0, a1)		NSF_OBJECT_ALLOC((a0), (a1))
200 # define NSF_DTRACE_OBJECT_FREE(a0, a1)		NSF_OBJECT_FREE((a0), (a1))
201 # define NSF_DTRACE_CONFIGURE_PROBE(a0, a1)		NSF_CONFIGURE_PROBE((a0), (a1))
202 #else
203 # define NSF_DTRACE_METHOD_ENTRY_ENABLED()		0
204 # define NSF_DTRACE_METHOD_RETURN_ENABLED()		0
205 # define NSF_DTRACE_OBJECT_ALLOC_ENABLED()		0
206 # define NSF_DTRACE_OBJECT_FREE_ENABLED()		0
207 # define NSF_DTRACE_CONFIGURE_PROBE_ENABLED()		0
208 # define NSF_DTRACE_METHOD_ENTRY(a0, a1, a2, a3, a4)	{}
209 # define NSF_DTRACE_METHOD_RETURN(a0, a1, a2, a3)	{}
210 # define NSF_DTRACE_OBJECT_ALLOC(a0, a1)		{}
211 # define NSF_DTRACE_OBJECT_FREE(a0, a1)		{}
212 # define NSF_DTRACE_CONFIGURE_PROBE(a0, a1)		{}
213 #endif
214 
215 
216 #ifdef DMALLOC
217 #  include "dmalloc.h"
218 #endif
219 
220 /*
221  * Makros
222  */
223 
224 #if defined(PRE86)
225 # define Tcl_NRCallObjProc(interp, proc, cd, objc, objv) \
226   (*(proc))((cd), (interp), (objc), (objv))
227 #endif
228 
229 #ifdef NSF_MEM_COUNT
230 EXTERN int nsfMemCountInterpCounter;
231 typedef struct NsfMemCounter {
232   int peak;
233   int count;
234 } NsfMemCounter;
235 #  define MEM_COUNT_ALLOC(id,p) NsfMemCountAlloc((id), (p))
236 #  define MEM_COUNT_FREE(id,p) NsfMemCountFree((id), (p))
237 #  define MEM_COUNT_INIT() NsfMemCountInit()
238 #  define MEM_COUNT_RELEASE() NsfMemCountRelease()
239 #else
240 #  define MEM_COUNT_ALLOC(id,p)
241 #  define MEM_COUNT_FREE(id,p)
242 #  define MEM_COUNT_INIT()
243 #  define MEM_COUNT_RELEASE()
244 #endif
245 
246 # define STRING_NEW(target, p, l)  {char *tempValue = ckalloc((unsigned)(l)+1u); strncpy((tempValue), (p), (l)+1u); *((tempValue)+(l)) = '\0'; target = tempValue; MEM_COUNT_ALLOC(#target, (target));}
247 # define STRING_FREE(key, p)  MEM_COUNT_FREE((key), (p)); ckfree((char*)(p))
248 
249 #define DSTRING_INIT(dsPtr) Tcl_DStringInit(dsPtr); MEM_COUNT_ALLOC("DString",(dsPtr))
250 #define DSTRING_FREE(dsPtr) \
251   if ((dsPtr)->string != (dsPtr)->staticSpace) {Tcl_DStringFree(dsPtr);} MEM_COUNT_FREE("DString",(dsPtr))
252 
253 #if defined(USE_ASSOC_DATA)
254 # define RUNTIME_STATE(interp) ((NsfRuntimeState*)Tcl_GetAssocData((interp), "NsfRuntimeState", NULL))
255 #else
256 # define RUNTIME_STATE(interp) ((NsfRuntimeState*)((Interp*)(interp))->globalNsPtr->clientData)
257 #endif
258 
259 #define nr_elements(arr)  ((int) (sizeof(arr) / sizeof((arr)[0])))
260 
261 /*
262  * Tcl 8.6 uses (unsigned) per default
263  */
264 # define NEW(type) \
265   (type *)ckalloc((unsigned)sizeof(type)); MEM_COUNT_ALLOC(#type, NULL)
266 # define NEW_ARRAY(type,n) \
267   (type *)ckalloc((unsigned)sizeof(type)*(unsigned)(n)); MEM_COUNT_ALLOC(#type "*", NULL)
268 # define FREE(type, var) \
269   ckfree((char*) (var)); MEM_COUNT_FREE(#type,(var))
270 
271 #define isAbsolutePath(m) (*(m) == ':' && (m)[1] == ':')
272 #define isArgsString(m) (\
273 	*(m)   == 'a' && (m)[1] == 'r' && (m)[2] == 'g' && (m)[3] == 's' && \
274 	(m)[4] == '\0')
275 #define isBodyString(m) (\
276 	*(m)   == 'b' && (m)[1] == 'o' && (m)[2] == 'd' && (m)[3] == 'y' && \
277 	(m)[4] == '\0')
278 #define isCheckString(m) (\
279 	*(m)   == 'c' && (m)[1] == 'h' && (m)[2] == 'e' && (m)[3] == 'c' && \
280 	(m)[4] == 'k' && (m)[5] == '\0')
281 #define isCheckObjString(m) (\
282 	*(m)   == 'c' && (m)[1] == 'h' && (m)[2] == 'e' && (m)[3] == 'c' && \
283 	(m)[4] == 'k' && (m)[5] == 'o' && (m)[6] == 'b' && (m)[7] == 'j' && \
284 	(m)[8] == '\0')
285 #define isCreateString(m) (\
286 	*(m)   == 'c' && (m)[1] == 'r' && (m)[2] == 'e' && (m)[3] == 'a' && \
287 	(m)[4] == 't' && (m)[5] == 'e' && (m)[6] == '\0')
288 #define isTypeString(m) (\
289 	*(m)   == 't' && (m)[1] == 'y' && (m)[2] == 'p' && (m)[3] == 'e' && \
290 	(m)[4] == '\0')
291 #define isObjectString(m) (\
292 	*(m)   == 'o' && (m)[1] == 'b' && (m)[2] == 'j' && (m)[3] == 'e' && \
293 	(m)[4] == 'c' && (m)[5] == 't' && (m)[6] == '\0')
294 #define isClassString(m) (\
295 	*(m)   == 'c' && (m)[1] == 'l' && (m)[2] == 'a' && (m)[3] == 's' && \
296 	(m)[4] == 's' && (m)[5] == '\0')
297 
298 #if (defined(sun) || defined(__hpux)) && !defined(__GNUC__)
299 #  define USE_ALLOCA
300 #endif
301 
302 #if defined(__IBMC__) && !defined(__GNUC__)
303 # if __IBMC__ >= 0x0306
304 #  define USE_ALLOCA
305 # else
306 #  define USE_MALLOC
307 # endif
308 #endif
309 
310 #if defined(VISUAL_CC)
311 #  define USE_MALLOC
312 #endif
313 
314 #if 1
315 # define NSF_STACK_ALLOCATED_OBJV 32
316 # define ALLOC_ON_STACK(type,n,var) \
317   type *(var); type stack_allocated_##var[NSF_STACK_ALLOCATED_OBJV];	\
318   if (likely((n) < NSF_STACK_ALLOCATED_OBJV)) { (var) = &stack_allocated_##var[0]; } else { (var) = NEW_ARRAY(type, (n)); }
319 # define FREE_ON_STACK(type, var) \
320   if ((var) != &stack_allocated_##var[0]) { FREE(type *, var);}
321 #elif defined(__GNUC__) && !defined(USE_ALLOCA) && !defined(USE_MALLOC)
322 # if !defined(NDEBUG)
323 #  define ALLOC_ON_STACK(type,n,var) \
324   int __##var##_count = (n); type __##var[(n)+2];			\
325   type *(var) = __##var + 1; (var)[-1] = var[__##var##_count] = (type)0xdeadbeaf
326 #  define FREE_ON_STACK(type,var)                                       \
327   assert((var)[-1] == (var)[__##var##_count] && (var)[-1] == (type)0xdeadbeaf)
328 # else
329 #  define ALLOC_ON_STACK(type,n,var) type (var)[(n)]
330 #  define FREE_ON_STACK(type,var)
331 # endif
332 #elif defined(USE_ALLOCA)
333 #  define ALLOC_ON_STACK(type,n,var) type *(var) = (type *)alloca((n)*sizeof(type))
334 #  define FREE_ON_STACK(type,var)
335 #else
336 #  define ALLOC_ON_STACK(type,n,var) type *(var) = (type *)ckalloc((n)*sizeof(type))
337 #  define FREE_ON_STACK(type,var) ckfree((char*)(var))
338 #endif
339 
340 #ifdef USE_ALLOCA
341 # include <alloca.h>
342 #endif
343 
344 #if !defined(NDEBUG)
345 # define ISOBJ(o) ((o) != NULL && ISOBJ_(o))
346 # define ISOBJ_(o) ((o) != (void*)0xdeadbeaf && (((o)->typePtr != NULL) ? ((o)->typePtr->name != NULL) : ((o)->bytes != NULL)) && (((o)->bytes != NULL) ? (o)->length >= -1 : 1) && (o)->refCount >= 0)
347 #else
348 # define ISOBJ(o)
349 #endif
350 
351 #define NSF_ABBREV_MIN_CHARS 4
352 /*
353  * This was defined to be inline for anything !sun or __IBMC__ >= 0x0306,
354  * but __hpux should also be checked - switched to only allow in gcc - JH
355  */
356 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
357 # define NSF_INLINE inline
358 #else
359 # define NSF_INLINE
360 #endif
361 
362 #ifdef USE_TCL_STUBS
363 # define DECR_REF_COUNT(A) \
364   MEM_COUNT_FREE("INCR_REF_COUNT" #A,(A)); assert((A)->refCount > -1);	\
365   Tcl_DecrRefCount(A)
366 # define DECR_REF_COUNT2(name,A)					\
367   MEM_COUNT_FREE("INCR_REF_COUNT-" name,(A)); assert((A)->refCount > -1); \
368   Tcl_DecrRefCount(A)
369 #else
370 # define DECR_REF_COUNT(A) \
371   MEM_COUNT_FREE("INCR_REF_COUNT" #A,(A)); TclDecrRefCount(A)
372 # define DECR_REF_COUNT2(name,A)				\
373   MEM_COUNT_FREE("INCR_REF_COUNT-" name,(A)); TclDecrRefCount(A)
374 #endif
375 
376 #define INCR_REF_COUNT(A) MEM_COUNT_ALLOC("INCR_REF_COUNT" #A,(A)); Tcl_IncrRefCount((A))
377 #define INCR_REF_COUNT2(name,A) \
378   /*fprintf(stderr, "c '%s'\n", ObjStr(A));*/				\
379   MEM_COUNT_ALLOC("INCR_REF_COUNT-" name,(A)); Tcl_IncrRefCount((A))
380 
381 #define ObjStr(obj) ((obj)->bytes) ? ((obj)->bytes) : Tcl_GetString(obj)
382 #define ObjTypeStr(obj) (((obj)->typePtr != NULL) ? ((obj)->typePtr->name) : "NONE")
383 #define ClassName(cl) (((cl) != NULL) ? ObjStr((cl)->object.cmdName) : "NULL")
384 #define ClassName_(cl) (ObjStr((cl)->object.cmdName))
385 #define ObjectName(object) (((object) != NULL) ? ObjStr((object)->cmdName) : "NULL")
386 #define ObjectName_(object) (ObjStr((object)->cmdName))
387 
388 #ifdef OBJDELETION_TRACE
389 # define PRINTOBJ(ctx,object) \
390   fprintf(stderr, "  %s %p %s oid=%p teardown=%p destroyCalled=%d\n", \
391 	  (ctx),(object),(object)->teardown?ObjStr((object)->cmdName):"(deleted)", \
392 	  (object)->id, (object)->teardown,                                 \
393 	  ((object)->flags & NSF_DESTROY_CALLED))
394 #else
395 # define PRINTOBJ(ctx,object)
396 #endif
397 
398 /*
399  * When an integer is printed, it might take so many digits
400  */
401 #define LONG_AS_STRING 32
402 
403 /* TCL_CONTINUE is defined as 4, from 5 on we can
404    use app-specific return codes */
405 #define NSF_CHECK_FAILED 6
406 
407 
408 /*
409   The NsfConfigEnabled() macro allows for querying whether a
410   configuration macro (NSF_*; see above) is actually defined (and
411   whether it expands to 1). This macro can be used both in CPP
412   expressions (e.g., "#if NsfConfigEnabled(...)") and in C expressions
413   (e.g., "if(NsfConfigEnabled(...))")
414 */
415 
416 #define NsfConfigEnabled__NOOP(...)
417 #define NsfConfigEnabled__open (
418 #define NsfConfigEnabled__close )
419 #define NsfConfigEnabled__caller(macro, args) macro args
420 #define NsfConfigEnabled__helper_1 NsfConfigEnabled__close NsfConfigEnabled__open 1
421 #define NsfConfigEnabled__(x) (NsfConfigEnabled__caller(NsfConfigEnabled__NOOP, \
422 						       NsfConfigEnabled__open \
423 						       NsfConfigEnabled__helper_##x \
424 						       NsfConfigEnabled__close) + 0)
425 #define NsfConfigEnabled_(x) NsfConfigEnabled__(x)
426 #define NsfConfigEnabled(x) NsfConfigEnabled_(NSF_##x)
427 
428 
429 /*
430  *
431  * Next Scripting Structures
432  *
433  */
434 
435 /*
436  * Filter structures
437  */
438 typedef struct NsfFilterStack {
439   Tcl_Command currentCmdPtr;
440   Tcl_Obj *calledProc;
441   struct NsfFilterStack *nextPtr;
442 } NsfFilterStack;
443 
444 
445 /*
446  * Assertion structures
447  */
448 
449 typedef struct NsfTclObjList {
450   Tcl_Obj *content;
451   Tcl_Obj *payload;
452   struct NsfTclObjList *nextPtr;
453 } NsfTclObjList;
454 
455 typedef struct NsfProcAssertion {
456   NsfTclObjList *pre;
457   NsfTclObjList *post;
458 } NsfProcAssertion;
459 
460 typedef struct NsfAssertionStore {
461   NsfTclObjList *invariants;
462   Tcl_HashTable procs;
463 } NsfAssertionStore;
464 
465 typedef enum { /* powers of 2; add to ALL, if default; */
466   CHECK_NONE     = 0,
467   CHECK_CLINVAR  = 1,
468   CHECK_OBJINVAR = 2,
469   CHECK_PRE      = 4,
470   CHECK_POST     = 8,
471   CHECK_INVAR    = CHECK_CLINVAR + CHECK_OBJINVAR,
472   CHECK_ALL      = CHECK_INVAR   + CHECK_PRE + CHECK_POST
473 } CheckOptions;
474 
475 void NsfAssertionRename(Tcl_Interp *interp, Tcl_Command cmd,
476 			  NsfAssertionStore *as,
477 			  char *oldSimpleCmdName, char *newName);
478 /*
479  * mixins
480  */
481 typedef struct NsfMixinStack {
482   Tcl_Command currentCmdPtr;
483   struct NsfMixinStack *nextPtr;
484 } NsfMixinStack;
485 
486 /*
487  * Generic command pointer list
488  */
489 typedef struct NsfCmdList {
490   Tcl_Command cmdPtr;
491   ClientData clientData;
492   struct NsfClass *clorobj;
493   struct NsfCmdList *nextPtr;
494 } NsfCmdList;
495 
496 typedef void (NsfFreeCmdListClientData) (NsfCmdList*);
497 
498 /* for incr string */
499 typedef struct NsfStringIncrStruct {
500   char *buffer;
501   char *start;
502   size_t bufSize;
503   size_t length;
504 } NsfStringIncrStruct;
505 
506 
507 /*
508  * cmd flags
509  */
510 
511 #define NSF_CMD_CALL_PROTECTED_METHOD		0x00010000
512 #define NSF_CMD_CALL_PRIVATE_METHOD		0x00020000
513 #define NSF_CMD_REDEFINE_PROTECTED_METHOD	0x00040000
514 /* NSF_CMD_NONLEAF_METHOD is used to flag, if a Method implemented via cmd calls "next" */
515 #define NSF_CMD_NONLEAF_METHOD			0x00080000
516 #define NSF_CMD_CLASS_ONLY_METHOD		0x00100000
517 #define NSF_CMD_DEPRECATED_METHOD		0x00200000
518 #define NSF_CMD_DEBUG_METHOD			0x00400000
519 
520 /*
521  * traceEvalFlags controlling NsfDStringEval
522  */
523 #define NSF_EVAL_SAVE                    0x01u  /* save interp context */
524 #define NSF_EVAL_NOPROFILE               0x02u  /* no profile below this call */
525 #define NSF_EVAL_DEBUG                   0x04u  /* call is a debug call, prevent recursion */
526 #define NSF_EVAL_LOG                     0x08u  /* call is a log call, prevent recursion */
527 #define NSF_EVAL_DEPRECATED              0x10u  /* call is a deprecated call, prevent recursion */
528 
529 #define NSF_EVAL_PREVENT_RECURSION (NSF_EVAL_DEBUG|NSF_EVAL_LOG|NSF_EVAL_DEPRECATED)
530 
531 /*
532  * object flags ...
533  */
534 
535 /* DESTROY_CALLED indicates that destroy was called on obj */
536 #define NSF_DESTROY_CALLED                 0x0001u
537 /* INIT_CALLED indicates that init was called on obj */
538 #define NSF_INIT_CALLED                    0x0002u
539 /* MIXIN_ORDER_VALID set when mixin order is valid */
540 #define NSF_MIXIN_ORDER_VALID              0x0004u
541 /* MIXIN_ORDER_DEFINED set, when mixins are defined for obj */
542 #define NSF_MIXIN_ORDER_DEFINED            0x0008u
543 #define NSF_MIXIN_ORDER_DEFINED_AND_VALID  0x000cu
544 /* FILTER_ORDER_VALID set, when filter order is valid */
545 #define NSF_FILTER_ORDER_VALID             0x0010u
546 /* FILTER_ORDER_DEFINED set, when filters are defined for obj */
547 #define NSF_FILTER_ORDER_DEFINED           0x0020u
548 #define NSF_FILTER_ORDER_DEFINED_AND_VALID 0x0030u
549 /* class and object properties for objects */
550 #define NSF_IS_CLASS                       0x0040u
551 #define NSF_IS_ROOT_META_CLASS             0x0080u
552 #define NSF_IS_ROOT_CLASS                  0x0100u
553 #define NSF_IS_SLOT_CONTAINER              0x0200u
554 #define NSF_KEEP_CALLER_SELF               0x0400u
555 #define NSF_PER_OBJECT_DISPATCH            0x0800u
556 #define NSF_HAS_PER_OBJECT_SLOTS           0x1000u
557 #define NSF_IS_AUTONAMED                   0x2000u
558 /* deletion states */
559 #define NSF_DESTROY_CALLED_SUCCESS       0x010000u /* requires flags to be int, not short */
560 #define NSF_DURING_DELETE                0x020000u
561 #define NSF_DELETED                      0x040000u
562 #define NSF_RECREATE                     0x080000u
563 #define NSF_TCL_DELETE                   0x100000u
564 
565 
566 /* method invocations */
567 #define NSF_ARG_METHOD_INVOCATION	     (NSF_ARG_ALIAS|NSF_ARG_FORWARD|NSF_ARG_INITCMD|NSF_ARG_CMD)
568 #define NSF_ARG_METHOD_CALL		     (NSF_ARG_ALIAS|NSF_ARG_FORWARD)
569 
570 /* Disallowed parameter options */
571 #define NSF_DISALLOWED_ARG_METHOD_PARAMETER  (NSF_ARG_METHOD_INVOCATION|NSF_ARG_NOCONFIG|NSF_ARG_SLOTSET|NSF_ARG_SLOTINITIALIZE)
572 #define NSF_DISALLOWED_ARG_SETTER	     (NSF_ARG_SWITCH|NSF_ARG_SUBST_DEFAULT|NSF_DISALLOWED_ARG_METHOD_PARAMETER)
573 /*#define NSF_DISALLOWED_ARG_OBJECT_PARAMETER  (NSF_ARG_SWITCH)*/
574 #define NSF_DISALLOWED_ARG_OBJECT_PARAMETER  0
575 #define NSF_DISALLOWED_ARG_VALUECHECK	     (NSF_ARG_SUBST_DEFAULT|NSF_ARG_METHOD_INVOCATION|NSF_ARG_SWITCH|NSF_ARG_CURRENTLY_UNKNOWN|NSF_ARG_SLOTSET|NSF_ARG_SLOTINITIALIZE)
576 
577 /* flags for ParseContext */
578 #define NSF_PC_MUST_DECR		     0x0001u
579 #define NSF_PC_IS_DEFAULT		     0x0002u
580 #define NSF_PC_INVERT_DEFAULT		     0x0010u
581 
582 #define NSF_PC_STATUS_MUST_DECR		     0x0001u
583 #define NSF_PC_STATUS_FREE_OBJV		     0x0002u
584 #define NSF_PC_STATUS_FREE_CD		     0x0004u
585 
586 
587 /* method types */
588 #define NSF_METHODTYPE_ALIAS     0x0001
589 #define NSF_METHODTYPE_SCRIPTED  0x0002
590 #define NSF_METHODTYPE_SETTER    0x0004
591 #define NSF_METHODTYPE_FORWARDER 0x0008
592 #define NSF_METHODTYPE_OBJECT    0x0010
593 #define NSF_METHODTYPE_NSFPROC   0x0020
594 #define NSF_METHODTYPE_OTHER     0x0100
595 #define NSF_METHODTYPE_BUILTIN   NSF_METHODTYPE_ALIAS|NSF_METHODTYPE_SETTER|NSF_METHODTYPE_FORWARDER|NSF_METHODTYPE_OTHER
596 #define NSF_METHODTYPE_ALL       NSF_METHODTYPE_SCRIPTED|NSF_METHODTYPE_BUILTIN|NSF_METHODTYPE_OBJECT
597 
598 
599 #define NsfObjectSetClass(object) \
600 	(object)->flags |= NSF_IS_CLASS
601 #define NsfObjectClearClass(object) \
602 	(object)->flags &= ~NSF_IS_CLASS
603 #define NsfObjectIsClass(object) \
604 	((object)->flags & NSF_IS_CLASS)
605 #define NsfObjectToClass(object) \
606 	(NsfClass *)((((NsfObject *)object)->flags & NSF_IS_CLASS) ? object : NULL)
607 
608 
609 /*
610  * object and class internals
611  */
612 
613 typedef struct NsfParamDefs {
614   Nsf_Param *paramsPtr;
615   int nrParams;
616   int refCount;
617   int serial;
618 } NsfParamDefs;
619 
620 typedef struct NsfParsedParam {
621   NsfParamDefs *paramDefs;
622   int possibleUnknowns;
623 } NsfParsedParam;
624 
625 typedef struct NsfObjectOpt {
626   NsfAssertionStore *assertions;
627   NsfCmdList *objFilters;
628   NsfCmdList *objMixins;
629   ClientData clientData;
630   const char *volatileVarName;
631 #if defined(PER_OBJECT_PARAMETER_CACHING)
632   NsfParsedParam *parsedParamPtr;
633   unsigned int classParamPtrEpoch;
634 #endif
635   CheckOptions checkoptions;
636 } NsfObjectOpt;
637 
638 typedef struct NsfObject {
639   Tcl_Obj *cmdName;
640   Tcl_Command id;
641   Tcl_Interp *teardown;
642   struct NsfClass *cl;
643   TclVarHashTable *varTablePtr;
644   Tcl_Namespace *nsPtr;
645   NsfObjectOpt *opt;
646   struct NsfCmdList *filterOrder;
647   struct NsfCmdList *mixinOrder;
648   NsfFilterStack *filterStack;
649   NsfMixinStack *mixinStack;
650   int refCount;
651   unsigned int flags;
652   short activationCount;
653 } NsfObject;
654 
655 typedef struct NsfClassOpt {
656   NsfCmdList *classFilters;
657   NsfCmdList *classMixins;
658   NsfCmdList *isObjectMixinOf;
659   NsfCmdList *isClassMixinOf;
660   NsfAssertionStore *assertions;
661   Tcl_Obj *mixinRegObjs;
662 #ifdef NSF_OBJECTDATA
663   Tcl_HashTable *objectdata;
664 #endif
665   Tcl_Command id;
666   ClientData clientData;
667 } NsfClassOpt;
668 
669 typedef struct NsfClass {
670   struct NsfObject        object;
671   struct NsfClasses      *super;
672   struct NsfClasses      *sub;
673   struct NsfObjectSystem *osPtr;
674   struct NsfClasses      *order;
675   Tcl_HashTable           instances;
676   Tcl_Namespace          *nsPtr;
677   NsfParsedParam         *parsedParamPtr;
678   NsfClassOpt            *opt;
679   short                   color;
680 } NsfClass;
681 
682 typedef struct NsfClasses {
683   struct NsfClass   *cl;
684   ClientData         clientData;
685   struct NsfClasses *nextPtr;
686 } NsfClasses;
687 
688 /*
689  * needed in nsf.c and in nsfShadow
690  */
691 #define NSF_PROC_FLAG_AD           0x01u
692 #define NSF_PROC_FLAG_CHECK_ALWAYS 0x02u
693 
694 typedef struct NsfProcClientData {
695   Tcl_Obj       *procName;
696   Tcl_Command    cmd;
697   Tcl_Command    wrapperCmd;
698   NsfParamDefs  *paramDefs;
699   unsigned int   flags;
700   Tcl_Interp    *interp;
701 } NsfProcClientData;
702 
703 typedef enum SystemMethodsIdx {
704   NSF_c_alloc_idx,
705   NSF_c_create_idx,
706   NSF_c_dealloc_idx,
707   NSF_c_configureparameter_idx,
708   NSF_c_recreate_idx,
709   NSF_o_cleanup_idx,
710   NSF_o_configure_idx,
711   NSF_o_configureparameter_idx,
712   NSF_o_defaultmethod_idx,
713   NSF_o_destroy_idx,
714   NSF_o_init_idx,
715   NSF_o_move_idx,
716   NSF_o_unknown_idx,
717   NSF_s_get_idx,
718   NSF_s_set_idx
719 } SystemMethodsIdx;
720 
721 #if !defined(NSF_C)
722 EXTERN const char *Nsf_SystemMethodOpts[];
723 #else
724 const char *Nsf_SystemMethodOpts[] = {
725   "-class.alloc",
726   "-class.create",
727   "-class.dealloc",
728   "-class.configureparameter",
729   "-class.recreate",
730   "-object.cleanup",
731   "-object.configure",
732   "-object.configureparameter",
733   "-object.defaultmethod",
734   "-object.destroy",
735   "-object.init",
736   "-object.move",
737   "-object.unknown",
738   "-slot.get",
739   "-slot.set",
740   NULL
741 };
742 #endif
743 
744 typedef struct NsfObjectSystem {
745   NsfClass     *rootClass;
746   NsfClass     *rootMetaClass;
747   unsigned int  overloadedMethods;
748   unsigned int  definedMethods;
749   Tcl_Obj      *methods[NSF_s_set_idx+2];
750   const char   *methodNames[NSF_s_set_idx+2];
751   Tcl_Obj      *handles[NSF_s_set_idx+2];
752   struct NsfObjectSystem *nextPtr;
753   char          protected[NSF_s_set_idx+2];
754 } NsfObjectSystem;
755 
756 
757 /*
758  * Next Scripting global names and strings
759  *
760  * We provide enums for efficient lookup for corresponding string
761  * names and Tcl_Objs via global arrays. The "constant" Tcl_Objs are
762  * built at start-up-time via Nsf_Init().
763  */
764 
765 typedef enum {
766   NSF_EMPTY, NSF_ZERO, NSF_ONE,
767   /* methods called internally */
768   NSF_CONFIGURE, NSF_INITIALIZE, NSF_GET_PARAMETER_SPEC,
769   NSF_SLOT_GET, NSF_SLOT_SET,
770   /* var names */
771   NSF_AUTONAMES, NSF_DEFAULTMETACLASS, NSF_DEFAULTSUPERCLASS,
772   NSF_ARRAY_INITCMD, NSF_ARRAY_CMD,
773   NSF_ARRAY_ALIAS, NSF_ARRAY_PARAMETERSYNTAX,
774   NSF_POSITION, NSF_POSITIONAL, NSF_CONFIGURABLE, NSF_PARAMETERSPEC,
775   /* object/class names */
776   NSF_METHOD_PARAMETER_SLOT_OBJ,
777   /* constants */
778   NSF_ALIAS, NSF_ARGS, NSF_CMD, NSF_FILTER, NSF_FORWARD,
779   NSF_METHOD,  NSF_OBJECT, NSF_SETTER, NSF_SETTERNAME, NSF_VALUECHECK,
780   NSF_GUARD_OPTION, NSF___UNKNOWN__, NSF_ARRAY, NSF_GET, NSF_SET, NSF_OPTION_STRICT, NSF_SCRIPT,
781   NSF_OBJECT_UNKNOWN_HANDLER, NSF_ARGUMENT_UNKNOWN_HANDLER,
782   NSF_PARSE_ARGS,
783   /* Partly redefined Tcl commands; leave them together at the end */
784   NSF_EXPR, NSF_FORMAT, NSF_INFO_BODY, NSF_INFO_FRAME, NSF_INTERP,
785   NSF_STRING_IS, NSF_EVAL, NSF_DISASSEMBLE,
786   NSF_RENAME
787 } NsfGlobalNames;
788 #if !defined(NSF_C)
789 EXTERN const char *NsfGlobalStrings[];
790 #else
791 const char *NsfGlobalStrings[] = {
792   "", "0", "1",
793   /* methods called internally */
794   "configure", "initialize", "getParameterSpec",
795   "value=get", "value=set",
796   /* var names */
797   "__autonames", "__default_metaclass", "__default_superclass", "__initcmd", "__cmd",
798   "::nsf::alias", "::nsf::parameter::syntax",
799   "position", "positional", "configurable", "parameterSpec",
800   /* object/class names */
801   "::nx::methodParameterSlot",
802   /* constants */
803   "alias", "args", "cmd", "filter",  "forward",
804   "method", "object", "setter", "settername", "valuecheck",
805   "-guard", "__unknown__", "::array", "get", "set", "-strict", "script",
806   /* nsf Tcl commands */
807   "::nsf::object::unknown",
808   "::nsf::argument::unknown",
809   "::nsf::parseargs",
810   /* Tcl commands */
811   "expr", "format", "::tcl::info::body", "::tcl::info::frame", "interp",
812   "::tcl::string::is", "::eval", "::tcl::unsupported::disassemble",
813   "rename"
814 };
815 #endif
816 
817 #define NsfGlobalObjs RUNTIME_STATE(interp)->methodObjNames
818 
819 /*
820  * Interface for Tcl_Obj types
821  */
822 EXTERN Tcl_ObjType NsfMixinregObjType;
823 EXTERN int NsfMixinregGet(Tcl_Interp *interp, Tcl_Obj *obj, NsfClass **classPtr, Tcl_Obj **guardObj)
824   nonnull(1) nonnull(2) nonnull(3) nonnull(4);
825 EXTERN int NsfMixinregInvalidate(Tcl_Interp *interp, Tcl_Obj *obj)
826   nonnull(1) nonnull(2);
827 
828 EXTERN Tcl_ObjType NsfFilterregObjType;
829 EXTERN int NsfFilterregGet(Tcl_Interp *interp, Tcl_Obj *obj, Tcl_Obj **filterObj, Tcl_Obj **guardObj)
830   nonnull(1) nonnull(2) nonnull(3) nonnull(4);
831 
832 EXTERN NsfClassOpt *NsfRequireClassOpt(NsfClass *class)
833   nonnull(1) returns_nonnull;
834 
835 
836 /*
837  * Next Scripting ShadowTclCommands
838  */
839 typedef struct NsfShadowTclCommandInfo {
840   TclObjCmdProcType proc;
841   ClientData clientData;
842   int nrArgs;
843 } NsfShadowTclCommandInfo;
844 typedef enum {SHADOW_LOAD=1, SHADOW_UNLOAD=0, SHADOW_REFETCH=2} NsfShadowOperations;
845 
846 
847 typedef enum {NSF_PARAMS_NAMES, NSF_PARAMS_LIST,
848 	      NSF_PARAMS_PARAMETER, NSF_PARAMS_SYNTAX} NsfParamsPrintStyle;
849 
850 int NsfCallCommand(Tcl_Interp *interp, NsfGlobalNames name,
851 		     int objc, Tcl_Obj *const objv[])
852   nonnull(1) nonnull(4);
853 
854 int NsfShadowTclCommands(Tcl_Interp *interp, NsfShadowOperations load)
855   nonnull(1);
856 
857 Tcl_Obj *NsfMethodObj(const NsfObject *object, int methodIdx)
858   nonnull(1) pure;
859 
860 int NsfReplaceCommandCleanup(Tcl_Interp *interp, Tcl_Obj *nameObj, NsfShadowTclCommandInfo *ti)
861   nonnull(1) nonnull(2) nonnull(3);
862 
863 int NsfReplaceCommand(Tcl_Interp *interp, Tcl_Obj *nameObj,
864 		      Tcl_ObjCmdProc *nsfReplacementProc,
865 		      ClientData cd,
866 		      NsfShadowTclCommandInfo *ti)
867   nonnull(1) nonnull(2) nonnull(5);
868 
869 
870 /*
871  * Next Scripting CallStack
872  */
873 typedef struct NsfCallStackContent {
874   NsfObject *self;
875   NsfClass *cl;
876   Tcl_Command cmdPtr;
877   NsfFilterStack *filterStackEntry;
878   Tcl_Obj *const* objv;
879   int objc;
880   unsigned int flags;
881 #if defined(NSF_PROFILE) || defined(NSF_DTRACE)
882   long int startUsec;
883   long int startSec;
884   const char *methodName;
885 #endif
886   unsigned short frameType;
887 } NsfCallStackContent;
888 
889 #define NSF_CSC_TYPE_PLAIN                    0u
890 #define NSF_CSC_TYPE_ACTIVE_MIXIN             1u
891 #define NSF_CSC_TYPE_ACTIVE_FILTER            2u
892 #define NSF_CSC_TYPE_INACTIVE                 4u
893 #define NSF_CSC_TYPE_INACTIVE_MIXIN           5u
894 #define NSF_CSC_TYPE_INACTIVE_FILTER          6u
895 #define NSF_CSC_TYPE_GUARD                 0x10u
896 #define NSF_CSC_TYPE_ENSEMBLE              0x20u
897 
898 #define NSF_CSC_CALL_IS_NEXT                  1u
899 #define NSF_CSC_CALL_IS_GUARD                 2u
900 #define NSF_CSC_CALL_IS_ENSEMBLE              4u
901 #define NSF_CSC_CALL_IS_COMPILE               8u
902 
903 
904 #define NSF_CSC_IMMEDIATE           0x000000100u
905 #define NSF_CSC_FORCE_FRAME         0x000000200u
906 #define NSF_CSC_CALL_NO_UNKNOWN     0x000000400u
907 #define NSF_CSC_CALL_IS_NRE         0x000002000u
908 #define NSF_CSC_MIXIN_STACK_PUSHED  0x000004000u
909 #define NSF_CSC_FILTER_STACK_PUSHED 0x000008000u
910 #define NSF_CSC_METHOD_IS_UNKNOWN   0x000010000u
911 
912 /* flags for call method */
913 #define NSF_CM_NO_UNKNOWN           0x000000001u
914 #define NSF_CM_NO_SHIFT             0x000000002u
915 #define NSF_CM_IGNORE_PERMISSIONS   0x000000004u
916 #define NSF_CM_NO_OBJECT_METHOD     0x000000008u
917 #define NSF_CM_SYSTEM_METHOD        0x000000010u
918 #define NSF_CM_LOCAL_METHOD         0x000000020u
919 #define NSF_CM_INTRINSIC_METHOD     0x000000040u
920 #define NSF_CM_KEEP_CALLER_SELF     0x000000080u
921 #define NSF_CM_ENSEMBLE_UNKNOWN     0x008000000u
922 
923 
924 #define NSF_CSC_COPY_FLAGS          (NSF_CSC_MIXIN_STACK_PUSHED|NSF_CSC_FILTER_STACK_PUSHED|NSF_CSC_IMMEDIATE|NSF_CSC_FORCE_FRAME|NSF_CM_LOCAL_METHOD)
925 
926 #define NSF_VAR_TRIGGER_TRACE    1
927 #define NSF_VAR_REQUIRE_DEFINED  2
928 #define NSF_VAR_ISARRAY          4
929 
930 /*
931  * Tcl uses 01 and 02, TclOO uses 04 and 08, so leave some space free
932  * for further extensions of Tcl and tcloo...
933  */
934 #define FRAME_IS_NSF_OBJECT  0x10000u
935 #define FRAME_IS_NSF_METHOD  0x20000u
936 #define FRAME_IS_NSF_CMETHOD 0x40000u
937 #define FRAME_VAR_LOADED     0x80000u
938 
939 #if defined(NRE)
940 # define NRE_SANE_PATCH 1
941 # define NsfImmediateFromCallerFlags(flags) \
942   (((flags) & (NSF_CSC_CALL_IS_NRE|NSF_CSC_IMMEDIATE)) == NSF_CSC_CALL_IS_NRE ? 0 : NSF_CSC_IMMEDIATE)
943 # if defined(NRE_SANE_PATCH)
944 #  define NsfNRRunCallbacks(interp, result, rootPtr) TclNRRunCallbacks(interp, result, rootPtr)
945 #  if !defined(TclStackFree)
946 #   define TclStackFree(interp, ptr) ckfree(ptr)
947 #   define TclStackAlloc(interp, size) ckalloc(size)
948 #  endif
949 # else
950 #  define NsfNRRunCallbacks(interp, result, rootPtr) TclNRRunCallbacks(interp, result, rootPtr, 0)
951 #  define TEOV_callback NRE_callback
952 # endif
953 #endif
954 
955 #if defined(NSF_PROFILE)
956 typedef struct NsfProfile {
957   long int overallTime;
958   long int startSec;
959   long int startUSec;
960   Tcl_HashTable objectData;
961   Tcl_HashTable methodData;
962   Tcl_HashTable procData;
963   Tcl_DString traceDs;
964   int depth;
965   int verbose;
966   Tcl_Obj *shadowedObjs;
967   NsfShadowTclCommandInfo *shadowedTi;
968   int inmemory;
969 } NsfProfile;
970 
971 # define NSF_PROFILE_TIME_DATA struct Tcl_Time profile_trt
972 # define NSF_PROFILE_CALL(interp, object, methodName) \
973   Tcl_GetTime(&profile_trt);			\
974   NsfProfileTraceCall(interp, object, NULL, methodName)
975 # define NSF_PROFILE_EXIT(interp, object, methodName) \
976   NsfProfileTraceExit(interp, object, NULL, methodName, &profile_trt)
977 #else
978 # define NSF_PROFILE_TIME_DATA
979 # define NSF_PROFILE_CALL(interp, object, methodName)
980 # define NSF_PROFILE_EXIT(interp, object, methodName)
981 #endif
982 
983 typedef struct NsfList {
984   void           *data;
985   Tcl_Obj        *obj;
986   struct NsfList *nextPtr;
987 } NsfList;
988 
989 typedef struct NsfDList {
990   void  **data;
991   size_t  size;
992   size_t  avail;
993   void   *static_data[30];
994 } NsfDList;
995 
996 
997 typedef struct NsfRuntimeState {
998   /*
999    * The defined object systems
1000    */
1001   struct NsfObjectSystem *objectSystems;
1002   /*
1003    * namespaces and cmds
1004    */
1005   Tcl_Namespace *NsfNS;           /* the ::nsf namespace */
1006   Tcl_Namespace *NsfClassesNS;    /* the ::nsf::classes namespace, where classes are created physically */
1007   Tcl_ObjCmdProc *objInterpProc;  /* cached result of TclGetObjInterpProc() */
1008   Tcl_Command colonCmd;           /* cmdPtr of cmd ":" to dispatch via cmdResolver */
1009   Proc fakeProc;                  /* dummy proc structure, used for C-implemented methods with local scope */
1010   Tcl_Command currentMixinCmdPtr; /* cmdPtr of currently active mixin, used for "info activemixin" */
1011   unsigned int objectMethodEpoch;
1012   unsigned int instanceMethodEpoch;
1013 #if defined(PER_OBJECT_PARAMETER_CACHING)
1014   unsigned int classParamPtrEpoch;
1015 #endif
1016   unsigned int overloadedMethods; /* bit-array for tracking overloaded methods */
1017   Tcl_Obj **methodObjNames;       /* global objects of nsf */
1018   struct NsfShadowTclCommandInfo *tclCommands; /* shadowed Tcl commands */
1019 
1020 #if defined(CHECK_ACTIVATION_COUNTS)
1021   NsfClasses *cscList;
1022 #endif
1023   int errorCount;        /* keep track of number of errors to avoid potential error loops */
1024   int unknown;           /* keep track whether an unknown method is currently called */
1025   /*
1026    * Configure options. The following do*-flags could be moved into a
1027    * bit-array, but we have only one state per interp, so the win on
1028    * memory is very little.
1029    */
1030   int logSeverity;
1031   int debugCallingDepth;
1032   unsigned int doCheckArguments;
1033   unsigned int doCheckResults;
1034   int doFilters;
1035   int doKeepcmds;
1036   int doProfile;
1037   int doTrace;
1038   unsigned int preventRecursionFlags;
1039   int doClassConverterOmitUnknown;
1040   int doSoftrecreate;
1041   int exitHandlerDestroyRound;          /* shutdown handling */
1042 
1043   Tcl_HashTable activeFilterTablePtr;   /* keep track of defined filters */
1044   NsfList *freeListPtr;                 /* list of elements to free when interp shuts down */
1045   NsfDList freeDList;
1046 #if defined(NSF_PROFILE)
1047   NsfProfile profile;
1048 #endif
1049 #if defined(NSF_STACKCHECK)
1050   void *bottomOfStack;
1051   void *maxStack;
1052 #endif
1053   ClientData clientData;
1054   NsfStringIncrStruct iss; /* used for new to create new symbols */
1055   short guardCount;        /* keep track of guard invocations */
1056 } NsfRuntimeState;
1057 
1058 #define NSF_EXITHANDLER_OFF 0
1059 #define NSF_EXITHANDLER_ON_SOFT_DESTROY 1
1060 #define NSF_EXITHANDLER_ON_PHYSICAL_DESTROY 2
1061 
1062 
1063 #ifdef NSF_OBJECTDATA
1064 EXTERN void
1065 NsfSetObjectData(struct NsfObject *object, struct NsfClass *class, ClientData data)
1066   nonnull(1) nonnull(2) nonnull(3);
1067 EXTERN int
1068 NsfGetObjectData(struct NsfObject *object, struct NsfClass *class, ClientData *data)
1069   nonnull(1) nonnull(2) nonnull(3);
1070 EXTERN int
1071 NsfUnsetObjectData(struct NsfObject *object, struct NsfClass *class)
1072   nonnull(1) nonnull(2);
1073 EXTERN void
1074 NsfFreeObjectData(NsfClass *class)
1075   nonnull(1);
1076 #endif
1077 
1078 /*
1079  * Prototypes for method definitions
1080  */
1081 EXTERN Tcl_ObjCmdProc NsfObjDispatch;
1082 
1083 /*
1084  *  NsfObject Reference Accounting
1085  */
1086 EXTERN void NsfCleanupObject_(NsfObject *object) nonnull(1);
1087 
1088 #if defined(NSFOBJ_TRACE)
1089 # define NsfObjectRefCountIncr(object)		\
1090   ((NsfObject *)(object))->refCount++;		\
1091   fprintf(stderr, "RefCountIncr %p count=%d %s\n", (object), ((NsfObject *)(object))->refCount, \
1092 	  ((NsfObject *)object)->cmdName?ObjStr(((NsfObject *)(object))->cmdName):"no name");   \
1093   MEM_COUNT_ALLOC("NsfObject.refCount", (object))
1094 # define NsfObjectRefCountDecr(object)					\
1095   (object)->refCount--;							\
1096   fprintf(stderr, "RefCountDecr %p count=%d\n", (object), (object)->refCount); \
1097   MEM_COUNT_FREE("NsfObject.refCount", (object))
1098 #else
1099 # define NsfObjectRefCountIncr(object)          \
1100   (object)->refCount++;                         \
1101   MEM_COUNT_ALLOC("NsfObject.refCount", (object))
1102 # define NsfObjectRefCountDecr(object)		\
1103   (object)->refCount--;				\
1104   MEM_COUNT_FREE("NsfObject.refCount", (object))
1105 #endif
1106 
1107 /*
1108  *
1109  *  Internally used API functions
1110  *
1111  */
1112 #if defined(NRE)
1113 # include "stubs8.6/nsfIntDecls.h"
1114 #else
1115 # include "stubs8.5/nsfIntDecls.h"
1116 #endif
1117 
1118 /*
1119  * Profiling functions
1120  */
1121 
1122 EXTERN void NsfDeprecatedCmd(Tcl_Interp *interp, const char *what, const char *oldCmd, const char *newCmd)
1123   nonnull(1) nonnull(2) nonnull(3) nonnull(4);
1124 EXTERN void NsfProfileDeprecatedCall(Tcl_Interp *interp, NsfObject *object, NsfClass *class,
1125 				     const char *methodName, const char *altMethod)
1126   nonnull(1) nonnull(2) nonnull(4) nonnull(5);
1127 EXTERN void NsfProfileDebugCall(Tcl_Interp *interp, NsfObject *object, NsfClass *class, const char *methodName,
1128 				int objc, Tcl_Obj **objv)
1129   nonnull(1) nonnull(4);
1130 EXTERN void NsfProfileDebugExit(Tcl_Interp *interp, NsfObject *object, NsfClass *class, const char *methodName,
1131 		    long startSec, long startUsec)
1132   nonnull(1) nonnull(4);
1133 
1134 #if defined(NSF_PROFILE)
1135 EXTERN void NsfProfileRecordMethodData(Tcl_Interp* interp, NsfCallStackContent *cscPtr)
1136   nonnull(1) nonnull(2);
1137 EXTERN void NsfProfileRecordProcData(Tcl_Interp *interp, const char *methodName, long startSec, long startUsec)
1138   nonnull(1) nonnull(2);
1139 EXTERN void NsfProfileInit(Tcl_Interp *interp) nonnull(1);
1140 EXTERN void NsfProfileFree(Tcl_Interp *interp) nonnull(1);
1141 EXTERN void NsfProfileClearData(Tcl_Interp *interp) nonnull(1);
1142 EXTERN void NsfProfileGetData(Tcl_Interp *interp) nonnull(1);
1143 EXTERN int NsfProfileTrace(Tcl_Interp *interp, int withEnable, int withVerbose, int withDontsave, Tcl_Obj *builtinObjs);
1144 
1145 EXTERN void NsfProfileTraceCall(Tcl_Interp *interp, NsfObject *object, NsfClass *class, const char *methodName)
1146   nonnull(1) nonnull(2) nonnull(4);
1147 EXTERN void NsfProfileTraceExit(Tcl_Interp *interp, NsfObject *object, NsfClass *class, const char *methodName,
1148 				struct Tcl_Time *callTime)
1149   nonnull(1) nonnull(2) nonnull(4) nonnull(5);
1150 EXTERN void NsfProfileTraceCallAppend(Tcl_Interp *interp, const char *label)
1151   nonnull(1) nonnull(2);
1152 EXTERN void NsfProfileTraceExitAppend(Tcl_Interp *interp, const char *label, double duration)
1153   nonnull(1) nonnull(2);
1154 
1155 EXTERN NsfCallStackContent *NsfCallStackGetTopFrame(const Tcl_Interp *interp, Tcl_CallFrame **framePtrPtr)
1156   nonnull(1);
1157 #endif
1158 
1159 /*
1160  * MEM Counting
1161  */
1162 #ifdef NSF_MEM_COUNT
1163 void NsfMemCountAlloc(const char *id, const void *p) nonnull(1);
1164 void NsfMemCountFree(const char *id, const void *p) nonnull(1);
1165 void NsfMemCountInit(void);
1166 void NsfMemCountRelease(void);
1167 #endif /* NSF_MEM_COUNT */
1168 
1169 /*
1170  * TCL_STACK_ALLOC_TRACE
1171  */
1172 #if defined(TCL_STACK_ALLOC_TRACE)
1173 # define NsfTclStackFree(interp,ptr,msg) \
1174   fprintf(stderr, "---- TclStackFree %p %s\n", ptr, msg);\
1175   TclStackFree(interp,ptr)
1176 
1177 static char *
NsfTclStackAlloc(Tcl_Interp * interp,size_t size,char * msg)1178 NsfTclStackAlloc(Tcl_Interp *interp, size_t size, char *msg) {
1179   char *ptr = TclStackAlloc(interp, size);
1180   fprintf(stderr, "---- TclStackAlloc %p %s\n", ptr, msg);
1181   return ptr;
1182 }
1183 #else
1184 # define NsfTclStackFree(interp,ptr,msg) TclStackFree(interp,ptr)
1185 # define NsfTclStackAlloc(interp,size,msg) TclStackAlloc(interp,size)
1186 #endif
1187 
1188 /*
1189  * bytecode support
1190  */
1191 #ifdef NSF_BYTECODE
1192 typedef struct NsfCompEnv {
1193   int bytecode;
1194   Command *cmdPtr;
1195   CompileProc *compileProc;
1196   Tcl_ObjCmdProc *callProc;
1197 } NsfCompEnv;
1198 
1199 typedef enum {INST_INITPROC, INST_NEXT, INST_SELF, INST_SELF_DISPATCH,
1200 	      LAST_INSTRUCTION} NsfByteCodeInstructions;
1201 
1202 Tcl_ObjCmdProc NsfInitProcNSCmd, NsfSelfDispatchCmd,
1203   NsfNextObjCmd, NsfGetSelfObjCmd;
1204 
1205 EXTERN NsfCompEnv *NsfGetCompEnv(void);
1206 int NsfDirectSelfDispatch(ClientData cd, Tcl_Interp *interp,
1207 		     int objc, Tcl_Obj *const objv[])
1208   nonnull(1) nonnull(2);
1209 #endif
1210 
1211 EXTERN int NsfGetClassFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
1212 			      NsfClass **classPtr, bool withUnknown)
1213   nonnull(1) nonnull(2) nonnull(3);
1214 
1215 EXTERN int NsfObjWrongArgs(Tcl_Interp *interp, const char *msg,
1216 			   Tcl_Obj *cmdNameObj, Tcl_Obj *methodPathObj,
1217 			   const char *arglist)
1218   nonnull(1) nonnull(2);
1219 
1220 EXTERN const char *NsfMethodName(Tcl_Obj *methodObj)
1221   nonnull(1) returns_nonnull;
1222 
1223 EXTERN void NsfInitPkgConfig(Tcl_Interp *interp)
1224   nonnull(1);
1225 
1226 EXTERN void NsfDStringArgv(Tcl_DString *dsPtr, int objc, Tcl_Obj *const objv[])
1227   nonnull(1) nonnull(3);
1228 
1229 EXTERN Tcl_Obj *NsfMethodNamePath(Tcl_Interp *interp,
1230 				  Tcl_CallFrame *framePtr,
1231 				  const char *methodName)
1232   nonnull(1) nonnull(3) returns_nonnull;
1233 
1234 EXTERN int NsfDStringEval(Tcl_Interp *interp, Tcl_DString *dsPtr, const char *context,
1235 			  unsigned int traceEvalFlags)
1236   nonnull(1) nonnull(2) nonnull(3);
1237 
1238 
1239 /*
1240  * Definition of methodEpoch macros
1241  */
1242 #if defined(METHOD_OBJECT_TRACE)
1243 # define NsfInstanceMethodEpochIncr(msg) \
1244   RUNTIME_STATE(interp)->instanceMethodEpoch++;	\
1245   fprintf(stderr, "+++ instanceMethodEpoch %d %s\n", RUNTIME_STATE(interp)->instanceMethodEpoch, msg)
1246 # define NsfObjectMethodEpochIncr(msg) \
1247   RUNTIME_STATE(interp)->objectMethodEpoch++;	\
1248   fprintf(stderr, "+++ objectMethodEpoch %d %s\n", RUNTIME_STATE(interp)->objectMethodEpoch, msg)
1249 #else
1250 # define NsfInstanceMethodEpochIncr(msg) RUNTIME_STATE(interp)->instanceMethodEpoch++
1251 # define NsfObjectMethodEpochIncr(msg)   RUNTIME_STATE(interp)->objectMethodEpoch++
1252 #endif
1253 
1254 #if defined(PER_OBJECT_PARAMETER_CACHING)
1255 # define NsfClassParamPtrEpochIncr(msg)   RUNTIME_STATE(interp)->classParamPtrEpoch++
1256 #else
1257 # define NsfClassParamPtrEpochIncr(msg)
1258 #endif
1259 
1260 /*
1261  * NsfFlag type
1262  */
1263 EXTERN Tcl_ObjType NsfFlagObjType;
1264 EXTERN int NsfFlagObjSet(Tcl_Interp      *UNUSED(interp),
1265 			 Tcl_Obj         *objPtr,
1266 			 Nsf_Param const *baseParamPtr,
1267 			 int              serial,
1268 			 Nsf_Param const *paramPtr,
1269 			 Tcl_Obj         *payload,
1270 			 unsigned int     flags);
1271 typedef struct {
1272   const Nsf_Param *signature;
1273   Nsf_Param const *paramPtr;
1274   Tcl_Obj         *payload;
1275   int              serial;
1276   unsigned int     flags;
1277 } NsfFlag;
1278 
1279 #define NSF_FLAG_DASHDAH		0x01
1280 #define NSF_FLAG_CONTAINS_VALUE		0x02
1281 
1282 /*
1283  * NsfMethodContext type
1284  */
1285 EXTERN Tcl_ObjType NsfInstanceMethodObjType;
1286 EXTERN Tcl_ObjType NsfObjectMethodObjType;
1287 
1288 EXTERN int NsfMethodObjSet(
1289     Tcl_Interp  *UNUSED(interp),
1290     Tcl_Obj     *objPtr,
1291     const Tcl_ObjType *objectType,
1292     void        *context,
1293     unsigned int methodEpoch,
1294     Tcl_Command  cmd,
1295     NsfClass    *class,
1296     unsigned int flags
1297 ) nonnull(1) nonnull(2) nonnull(3) nonnull(4) nonnull(6);
1298 
1299 
1300 
1301 
1302 typedef struct {
1303   void        *context;
1304   Tcl_Command  cmd;
1305   NsfClass    *cl;
1306   unsigned int methodEpoch;
1307   unsigned int flags;
1308 } NsfMethodContext;
1309 
1310 /* functions from nsfUtil.c */
1311 char *Nsf_ltoa(char *buf, long i, int *lengthPtr)
1312   nonnull(1) nonnull(3);
1313 
1314 char *NsfStringIncr(NsfStringIncrStruct *iss)
1315   nonnull(1);
1316 
1317 void NsfStringIncrInit(NsfStringIncrStruct *iss)
1318   nonnull(1);
1319 
1320 void NsfStringIncrFree(NsfStringIncrStruct *iss)
1321   nonnull(1);
1322 
1323 
1324 /*
1325  *  Interface for NSF's custom hash tables supporting function
1326  *  pointers as keys.
1327  *
1328  */
1329 
1330 typedef void (Nsf_AnyFun)(void);
1331 
1332 EXTERN void Nsf_InitFunPtrHashTable(Tcl_HashTable *tablePtr)
1333   nonnull(1);
1334 EXTERN Tcl_HashEntry *Nsf_CreateFunPtrHashEntry(Tcl_HashTable *tablePtr, Nsf_AnyFun *key, int *isNew)
1335   nonnull(1) nonnull(2);
1336 EXTERN Tcl_HashEntry *Nsf_FindFunPtrHashEntry(Tcl_HashTable *tablePtr, Nsf_AnyFun *key)
1337   nonnull(1) nonnull(2);
1338 
1339 
1340 /*
1341  * NSF enumeration-type interface
1342  */
1343 EXTERN void Nsf_EnumerationTypeInit(void);
1344 EXTERN void Nsf_EnumerationTypeRelease(void);
1345 
1346 EXTERN const char *Nsf_EnumerationTypeGetDomain(Nsf_TypeConverter *converter)
1347   nonnull(1);
1348 
1349 /*
1350  * NSF command definitions interface
1351  */
1352 EXTERN void Nsf_CmdDefinitionInit(void);
1353 EXTERN void Nsf_CmdDefinitionRelease(void);
1354 EXTERN Nsf_methodDefinition *Nsf_CmdDefinitionGet(Tcl_ObjCmdProc *proc)
1355   nonnull(1);
1356 
1357 
1358 #ifndef HAVE_STRNSTR
1359 char *strnstr(const char *buffer, const char *needle, size_t buffer_len) pure;
1360 #endif
1361 
1362 /*
1363    In ANSI mode (ISO C89/90) compilers such as gcc and clang do not
1364    define the va_copy macro. However, they *do* in reasonably recent
1365    versions provide a prefixed (__*) one. The by-feature test below
1366    falls back to the prefixed version, if available, and provides a
1367    more general fallback to a simple assignment; this is primarily for
1368    MSVC; admittedly, this simplification is not generally portable to
1369    platform/compiler combos other than x86, but the best I can think of right
1370    now. One might constrain the assignment-fallback to a platform and
1371    leave va_copy undefined in uncaught platform cases (?).
1372 */
1373 #ifndef va_copy
1374 #ifdef	__va_copy
1375 #define	va_copy(dest,src) __va_copy((dest),(src))
1376 #else
1377 #define va_copy(dest,src) ((dest) = (src))
1378 #endif
1379 #endif
1380 
1381 /* In Tcl 8.6 (tclInt.h), vsnprintf is mapped to _vsnprintf. In Tcl
1382    8.5, this is missing from tclInt.h. So ... */
1383 
1384 #if defined(PRE86) && defined(_MSC_VER)
1385 #define vsnprintf _vsnprintf
1386 #endif
1387 
1388 /*
1389  * There are six whitespace characters in Tcl, which serve as element
1390  * separators in string representations of Tcl lists. See tclUtil.c
1391  */
1392 
1393 #define NsfHasTclSpace(str) \
1394   (strpbrk((str), " \t\n\r\v\f") != NULL)
1395 
1396 #define NsfMax(a,b) ((a) > (b) ? a : b)
1397 #define NsfMin(a,b) ((a) < (b) ? a : b)
1398 
1399 #define NsfCallStackFindLastInvocation(interp, offset, framePtrPtr) \
1400   NsfCallStackFindCallingContext((interp), (offset), (framePtrPtr), NULL)
1401 
1402 #endif /* _nsf_int_h_ */
1403