summaryrefslogtreecommitdiffstats
path: root/generic/tclNRE.h
blob: d74010537361454c61b9175c5a49f3dd920e652a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/* **********************************************
 * NRE internals   
 * **********************************************
 */

#define NRE_STACK_DEBUG         0
#define NRE_STACK_SIZE        100


/*
 * This is the main data struct for representing NR commands. It is designed
 * to fit in sizeof(Tcl_Obj) in order to exploit the fastest memory allocator
 * available.
 */

/*
 * Inline versions of Tcl_NRAddCallback and friends
 */

#define TOP_CB(iPtr) (((Interp *)(iPtr))->execEnvPtr->callbackPtr)

#define TclNRAddCallback(interp,postProcPtr,data0,data1,data2,data3)	\
    do {								\
	NRE_callback *cbPtr;						\
	ALLOC_CB(interp, cbPtr);					\
	INIT_CB(cbPtr, postProcPtr,data0,data1,data2,data3);		\
    } while (0)

#define INIT_CB(cbPtr, postProcPtr,data0,data1,data2,data3)		\
    do {								\
	cbPtr->procPtr = (postProcPtr);					\
	cbPtr->data[0] = (ClientData)(data0);				\
	cbPtr->data[1] = (ClientData)(data1);				\
	cbPtr->data[2] = (ClientData)(data2);				\
	cbPtr->data[3] = (ClientData)(data3);				\
    } while (0)

#if NRE_STACK_DEBUG

typedef struct NRE_callback {
    Tcl_NRPostProc *procPtr;
    ClientData data[4];
    struct NRE_callback *nextPtr;
} NRE_callback;

#define POP_CB(interp, cbPtr)                      \
    do {                                           \
        cbPtr = TOP_CB(interp);                    \
        TOP_CB(interp) = cbPtr->nextPtr;           \
    } while (0)

#define ALLOC_CB(interp, cbPtr)			\
    do {					\
	cbPtr = ckalloc(sizeof(NRE_callback));	\
	cbPtr->nextPtr = TOP_CB(interp);	\
	TOP_CB(interp) = cbPtr;			\
    } while (0)
    
#define FREE_CB(interp, ptr)			\
    ckfree((char *) (ptr))

#define NEXT_CB(ptr)  (ptr)->nextPtr

#else /* not debugging the NRE stack */

typedef struct NRE_callback {
    Tcl_NRPostProc *procPtr;
    ClientData data[4];
} NRE_callback;

typedef struct NRE_stack {
    struct NRE_callback items[NRE_STACK_SIZE];
    struct NRE_stack *next;
} NRE_stack;

#define POP_CB(interp, cbPtr)			\
    (cbPtr) = TOP_CB(interp)--

#define ALLOC_CB(interp, cbPtr)					\
    do {							\
	ExecEnv *eePtr = ((Interp *) interp)->execEnvPtr;	\
	NRE_stack *this = eePtr->NRStack;			\
								\
	if (eePtr->callbackPtr &&					\
		(eePtr->callbackPtr < &this->items[NRE_STACK_SIZE-1])) { \
	    (cbPtr) = ++eePtr->callbackPtr;				\
	} else {							\
	    (cbPtr) = TclNewCallback(interp);				\
	}								\
    } while (0)

#define FREE_CB(interp, cbPtr)

#define NEXT_CB(ptr) TclNextCallback(ptr)

MODULE_SCOPE NRE_callback *TclNewCallback(Tcl_Interp *interp);
MODULE_SCOPE NRE_callback *TclPopCallback(Tcl_Interp *interp);
MODULE_SCOPE NRE_callback *TclNextCallback(NRE_callback *ptr);

#endif