1 //
2 // ctable linked list routines
3 //
4 //
5 // $Id$
6 //
7 //#define LISTDEBUG
8 
9 
10 //
11 // ctable_ListInit - initialize a list -- zero out the row pointer from the list.
12 //
13 CTABLE_INTERNAL INLINE void
ctable_ListInit(ctable_BaseRow ** listPtr,CONST char * file,int line)14 ctable_ListInit (ctable_BaseRow **listPtr, CONST char *file, int line)
15 {
16 #ifdef LISTDEBUG
17     fprintf(stderr, "ctable_ListInit(0x%lx) at %s:%d\n", (long)listPtr, file, line);
18 #endif
19     *listPtr = NULL;
20 }
21 
22 #ifndef FULLSTATIC
23 //
24 // ctable_ListEmpty - return 1 if the list is empty, else 0.
25 //
26 CTABLE_INTERNAL INLINE int
ctable_ListEmpty(ctable_BaseRow * list)27 ctable_ListEmpty (ctable_BaseRow *list)
28 {
29 #ifdef LISTDEBUG
30     fprintf(stderr, "%d == ctable_ListEmpty(0x%lx)\n", (list == NULL), (long)list);
31 #endif
32     return (list == NULL);
33 }
34 #endif
35 
36 //
37 // ctable_ListRemove - remove a row from a list
38 //
39 CTABLE_INTERNAL INLINE void
ctable_ListRemove(ctable_BaseRow * row,int i)40 ctable_ListRemove (ctable_BaseRow *row, int i)
41 {
42 #ifdef LISTDEBUG
43     fprintf(stderr, "ctable_ListRemove(0x%lx, %d)\n", (long)row, i);
44 #endif
45 #ifdef SANITY_CHECKS
46     if(!row->_ll_nodes[i].prev) {
47 	Tcl_Panic("Removing row not in list (0x%lx, %d)!", (long)row, i);
48     }
49 #endif
50     // if there's an object following me, make his prev be my prev
51     if (row->_ll_nodes[i].next != NULL) {
52         row->_ll_nodes[i].next->_ll_nodes[i].prev = row->_ll_nodes[i].prev;
53     }
54 
55     // make my prev's next (or header) point to my next
56     *row->_ll_nodes[i].prev = row->_ll_nodes[i].next;
57 
58     // i'm removed
59     row->_ll_nodes[i].prev = NULL;
60 }
61 
62 //
63 // ctable_ListRemoveMightBeTheLastOne - remove a row from a list
64 //
65 CTABLE_INTERNAL INLINE int
ctable_ListRemoveMightBeTheLastOne(ctable_BaseRow * row,int i)66 ctable_ListRemoveMightBeTheLastOne (ctable_BaseRow *row, int i)
67 {
68     int mightBeTheLastOne;
69 
70 #ifdef LISTDEBUG
71     fprintf(stderr, "ctable_ListRemoveMightBeTheLastOne(0x%lx, %d)\n", (long)row, i);
72 #endif
73 #ifdef SANITY_CHECKS
74     if(!row->_ll_nodes[i].prev) {
75 	Tcl_Panic("Removing row not in list (0x%lx, %d)!", (long)row, i);
76     }
77 #endif
78     // if there's an object following me, make his prev be my prev
79     if (row->_ll_nodes[i].next != NULL) {
80         // set the next guy's prev ptr to be my prev ptr
81         row->_ll_nodes[i].next->_ll_nodes[i].prev = row->_ll_nodes[i].prev;
82 	mightBeTheLastOne = 0;
83     } else {
84 	// else note that there was nothing following me
85         mightBeTheLastOne = 1;
86     }
87 
88     // make my prev's next (or header) point to my next
89     *row->_ll_nodes[i].prev = row->_ll_nodes[i].next;
90 
91     // i'm removed
92     row->_ll_nodes[i].prev = NULL;
93 
94     return mightBeTheLastOne;
95 }
96 
97 
98 CTABLE_INTERNAL INLINE void
ctable_ListInsertHead(ctable_BaseRow ** listPtr,ctable_BaseRow * row,int i)99 ctable_ListInsertHead (ctable_BaseRow **listPtr, ctable_BaseRow *row, int i)
100 {
101 #ifdef LISTDEBUG
102     fprintf(stderr, "ctable_ListInsertHead(0x%lx, 0x%lx, %d)\n", (long)listPtr, (long)row, i);
103 #endif
104 #ifdef SANITY_CHECKS
105     if(row->_ll_nodes[i].prev) {
106 	Tcl_Panic("Inserting node twice (0x%lx, 0x%lx, %d)!", (long)listPtr, (long)row, i);
107     }
108 #endif
109 
110     // make the row's prev point to the address of the head pointer. Do this
111     // first so it'll be in place before the readers can see it.
112     row->_ll_nodes[i].prev = listPtr;
113     row->_ll_nodes[i].head = listPtr;
114 
115     // make the new row's next point to what the head currently points
116     // to, possibly NULL
117     if ((row->_ll_nodes[i].next = *listPtr) != NULL) {
118 
119         // it wasn't null, make the node pointed to by head's prev
120 	// point to the new row. We can do this now because the row
121 	// itself is fully initialised.
122 
123         (*listPtr)->_ll_nodes[i].prev = &row->_ll_nodes[i].next;
124     }
125 
126     // Make the head point to the new row. Do this last, so that
127     // all links in row are intact before it's seen by readers.
128     *listPtr = row;
129 
130 // printf ("insert head %lx i %d\n", (long unsigned int)listPtr, i);
131 }
132 
133 #ifndef FULLSTATIC
134 //
135 // ctable_ListInsertBefore - insert row2 before row1
136 //
137 CTABLE_INTERNAL INLINE void
ctable_ListInsertBefore(ctable_BaseRow * row1,ctable_BaseRow * row2,int i)138 ctable_ListInsertBefore (ctable_BaseRow *row1, ctable_BaseRow *row2, int i)
139 {
140     volatile ctable_BaseRow **row1prev;
141 
142 #ifdef LISTDEBUG
143     fprintf(stderr, "ctable_ListInsertBefore(0x%lx, 0x%lx, %d)\n", (long)row1, (long)row2, i);
144 #endif
145     // make row2's head point to row1's head
146     row2->_ll_nodes[i].head = row1->_ll_nodes[i].head;
147 
148     // make row2's prev point to row1's prev
149     row2->_ll_nodes[i].prev = row1->_ll_nodes[i].prev;
150 
151     // make row2's next point to row1
152     row2->_ll_nodes[i].next = row1;
153 
154     // get row1's prev before we overwrite it, because we need to link it last.
155     row1prev = (volatile ctable_BaseRow **)row1->_ll_nodes[i].prev;
156 
157     // make row1's prev point to row2's next
158     row1->_ll_nodes[i].prev = &row2->_ll_nodes[i].next;
159 
160     // make row1's prev's *next* point to row2, and do this last
161     *row1prev = row2;
162 }
163 #endif
164 
165 #ifndef FULLSTATIC
166 //
167 // ctable_ListInsertAfter - insert row2 after row1
168 //
169 CTABLE_INTERNAL INLINE void
ctable_ListInsertAfter(ctable_BaseRow * row1,ctable_BaseRow * row2,int i)170 ctable_ListInsertAfter (ctable_BaseRow *row1, ctable_BaseRow *row2, int i) {
171 #ifdef LISTDEBUG
172     fprintf(stderr, "ctable_ListInsertAfter(0x%lx, 0x%lx, %d)\n", (long)row1, (long)row2, i);
173 #endif
174     // make row2's head point to row1's head
175     row2->_ll_nodes[i].head = row1->_ll_nodes[i].head;
176 
177     // make row2's prev point to the address of row1's next
178     row2->_ll_nodes[i].prev = &row1->_ll_nodes[i].next;
179 
180     // set row2's next pointer to row1's next pointer and see if it's NULL
181     if ((row2->_ll_nodes[i].next = row1->_ll_nodes[i].next) != NULL) {
182 
183         // it wasn't, make row1's next's prev point to the address of
184 	// row2's next
185 
186         row1->_ll_nodes[i].next->_ll_nodes[i].prev = &row2->_ll_nodes[i].next;
187     }
188 
189     // make row1's next point to row2. This has to be last, so that the whole
190     // structure is in place before a reader can see it.
191     row1->_ll_nodes[i].next = row2;
192 }
193 #endif
194 
195 // vim: set ts=8 sw=4 sts=4 noet :
196