Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

527 lines
17 KiB

  1. /* Copyright (c) 1997 Microsoft Corporation */
  2. /* See the .C test code at the end of this file for examples of how to use
  3. this stuff.
  4. */
  5. #ifndef _LISTS_H
  6. #define _LISTS_H
  7. #define LIST_ROOT(name, type) struct name {type *Root;}
  8. #define LIST_MEMBER(type) struct { type **Prev; type *Next;}
  9. /* Note! Prev is the ADDRESS of the previous next element ptr */
  10. #define LIST_INSERT_ROOT(root,element,field)\
  11. { if(((element)->field.Next = (root)->Root) != 0)\
  12. (root)->Root->field.Prev = &(element)->field.Next;\
  13. (root)->Root = (element);\
  14. (element)->field.Prev = &(root)->Root;\
  15. }
  16. #define LIST_DELETE(element,field)\
  17. {\
  18. if((element)->field.Next)\
  19. (element)->field.Next->field.Prev = (element)->field.Prev;\
  20. if ((element)->field.Prev)\
  21. {\
  22. *(element)->field.Prev = (element)->field.Next;\
  23. (element)->field.Prev = 0;\
  24. }\
  25. (element)->field.Next = 0;\
  26. }
  27. #define LIST_INITIALIZE(root)\
  28. {\
  29. (root)->Root = 0;\
  30. }
  31. #define LIST_INITIALIZE_MEMBER(element,field)\
  32. { (element)->field.Next = 0;\
  33. (element)->field.Prev = 0;\
  34. }
  35. #define LIST_ORPHAN_MEMBER(element,field) (!((element)->field.Prev))
  36. #define LIST_FIRST(root) (root)->Root
  37. #define LIST_NEXT(element,field) (element)->field.Next
  38. #define TAIL_QUEUE_INITIALIZE(root)\
  39. {\
  40. (root)->First = NULL;\
  41. (root)->Last = &(root)->First;\
  42. }
  43. #define TAIL_QUEUE_ROOT(name,type)\
  44. struct name\
  45. { type *First;\
  46. type **Last;\
  47. }/* NOTE! This is the address of the last Next pointer. */
  48. #define TAIL_QUEUE_MEMBER(type)\
  49. struct\
  50. { type *Next;\
  51. type **Prev; /* NOTE! Address of previous Next element ptr */\
  52. }
  53. #define TAIL_QUEUE_INSERT_END(root,element,field)\
  54. { (element)->field.Prev = (root)->Last;\
  55. (element)->field.Next = 0;\
  56. *(root)->Last = (element);\
  57. (root)->Last = &(element)->field.Next;\
  58. }
  59. #define TAIL_QUEUE_DELETE(root,element,field)\
  60. {\
  61. if (((element)->field.Next) != NULL)\
  62. (element)->field.Next->field.Prev = (element)->field.Prev;\
  63. else\
  64. (root)->Last = (element)->field.Prev;\
  65. *(element)->field.Prev = (element)->field.Next;\
  66. (element)->field.Next = 0;\
  67. (element)->field.Prev = 0;\
  68. }
  69. #define TAIL_QUEUE_FIRST(root) (root)->First
  70. #define TAIL_QUEUE_NEXT(element,field) (element)->field.Next
  71. #define CIRCLE_QUEUE_ROOT(name,type)\
  72. struct name\
  73. { type *Last;\
  74. type *First;\
  75. }
  76. #define CIRCLE_QUEUE_MEMBER(type)\
  77. struct\
  78. { type *Prev;\
  79. type *Next;\
  80. }
  81. #define CIRCLE_QUEUE_INITIALIZE(root,type)\
  82. { (root)->Last = (type *)(root);\
  83. (root)->First = (type *)(root);\
  84. }
  85. #define CIRCLE_QUEUE_INITIALIZE_MEMBER(element,field)\
  86. { (element)->field.Next = (element)->field.Prev = 0;\
  87. }
  88. #define CIRCLE_QUEUE_INSERT_END(root,type,element,field)\
  89. { (element)->field.Prev = (root)->Last;\
  90. (element)->field.Next = (type *)(root);\
  91. if((root)->First != (type *)(root))\
  92. (root)->Last->field.Next = (element);\
  93. else\
  94. (root)->First = (element);\
  95. (root)->Last = (element);\
  96. }
  97. #define CIRCLE_QUEUE_INSERT_ROOT(root,type,element,field)\
  98. { (element)->field.Prev = (type *)(root);\
  99. (element)->field.Next = (root)->First;\
  100. if ((root)->Last != (void *)(root))\
  101. (root)->First->field.Prev = (element);\
  102. else\
  103. (root)->Last = (element);\
  104. (root)->First = (element);\
  105. }
  106. #define CIRCLE_QUEUE_INSERT_PREVIOUS(root,current_element,element,field)\
  107. { (element)->field.Prev = (current_element)->field.Prev;\
  108. (element)->field.Next = (current_element);\
  109. if ((current_element)->field.Prev != (void *)(root))\
  110. (current_element)->field.Prev->field.Next = (element);\
  111. else\
  112. (root)->First = (element);\
  113. (current_element)->field.Prev = (element);\
  114. }
  115. #define CIRCLE_QUEUE_DELETE(root,element,field)\
  116. { if((element)->field.Next != (void *)(root))\
  117. (element)->field.Next->field.Prev = (element)->field.Prev;\
  118. else\
  119. (root)->Last = (element)->field.Prev;\
  120. if((element)->field.Prev != (void *)(root))\
  121. (element)->field.Prev->field.Next = (element)->field.Next;\
  122. else\
  123. (root)->First = (element)->field.Next;\
  124. (element)->field.Next = 0;\
  125. (element)->field.Prev = 0;\
  126. }
  127. #define CIRCLE_QUEUE_FIRST(root)\
  128. ((root)->First == (void *) (root)? 0: (root)->First)
  129. #define CIRCLE_QUEUE_LAST(root)\
  130. ((root)->Last == (void *) (root)? 0: (root)->Last)
  131. #define CIRCLE_QUEUE_NEXT(root,element,field)\
  132. ((void *) (element)->field.Next == (void *) (root)? 0: (element)->field.Next)
  133. #define CIRCLE_QUEUE_PREVIOUS(root,element,field)\
  134. ((element)->field.Prev == (void *) (root)? 0: (element)->field.Prev)
  135. //---------------------------------------------------------------------
  136. // To support singly linked lists with no deletion of entries. Useful
  137. // for active lists (Active Lights etc.)
  138. struct CListEntry
  139. {
  140. CListEntry() {m_pNext = NULL;}
  141. virtual ~CListEntry() {delete m_pNext;}
  142. void Append(CListEntry* p) {p->m_pNext = m_pNext; m_pNext = p;}
  143. CListEntry * m_pNext;
  144. };
  145. ///////////////////////////////////////////////////////////////////////////////
  146. #if 0
  147. /*
  148. Test code. Strip it out, put it in a .C (or .CPP) file and compile it as a
  149. console app to test this stuff. It should run without any assertion failures.
  150. Also, use this as example code.
  151. */
  152. #include <stdio.h>
  153. #include <stdlib.h>
  154. #include <assert.h>
  155. void TestList(void)
  156. {
  157. struct Foo
  158. {
  159. int a;
  160. LIST_MEMBER(Foo) ListStuff;
  161. int b;
  162. };
  163. struct Foo MyFoo1, MyFoo2, MyFoo3, *pFoo = 0;
  164. LIST_ROOT(sRoot, Foo) MyListRoot;
  165. fputs("Testing LIST.\n",stdout);
  166. LIST_INITIALIZE(&MyListRoot);
  167. LIST_INITIALIZE_MEMBER(&MyFoo1,ListStuff);
  168. MyFoo1.a = 0x1A; MyFoo1.b = 0x1B;
  169. LIST_INITIALIZE_MEMBER(&MyFoo2,ListStuff);
  170. MyFoo2.a = 0x2A; MyFoo2.b = 0x2B;
  171. LIST_INITIALIZE_MEMBER(&MyFoo3,ListStuff);
  172. MyFoo3.a = 0x3A; MyFoo3.b = 0x3B;
  173. assert(LIST_ORPHAN_MEMBER(&MyFoo3,ListStuff));
  174. LIST_INSERT_ROOT(&MyListRoot,&MyFoo3,ListStuff);
  175. assert(!LIST_ORPHAN_MEMBER(&MyFoo3,ListStuff));
  176. LIST_INSERT_ROOT(&MyListRoot,&MyFoo2,ListStuff);
  177. LIST_INSERT_ROOT(&MyListRoot,&MyFoo1,ListStuff);
  178. assert(!LIST_ORPHAN_MEMBER(&MyFoo1,ListStuff));
  179. assert(!LIST_ORPHAN_MEMBER(&MyFoo2,ListStuff));
  180. assert(!LIST_ORPHAN_MEMBER(&MyFoo3,ListStuff));
  181. pFoo = LIST_FIRST(&MyListRoot);
  182. assert(pFoo);
  183. assert(pFoo->a == 0x1A);
  184. assert(pFoo->b == 0x1B);
  185. pFoo = LIST_NEXT(pFoo,ListStuff);
  186. assert(pFoo);
  187. assert(pFoo->a == 0x2A);
  188. assert(pFoo->b == 0x2B);
  189. pFoo = LIST_NEXT(pFoo,ListStuff);
  190. assert(pFoo);
  191. assert(pFoo->a == 0x3A);
  192. assert(pFoo->b == 0x3B);
  193. pFoo = LIST_NEXT(pFoo,ListStuff);
  194. assert(pFoo == 0);
  195. /* Delete member 2. */
  196. pFoo = LIST_FIRST(&MyListRoot);
  197. pFoo = LIST_NEXT(pFoo,ListStuff);
  198. LIST_DELETE(pFoo,ListStuff);
  199. assert(pFoo->a == 0x2A);/* Make sure we have the right member. */
  200. assert(pFoo->b == 0x2B);/* And the data is intact. */
  201. assert(LIST_NEXT(pFoo,ListStuff) == 0);
  202. /* Make sure that there are only members 1 and 3 in the list now. */
  203. pFoo = LIST_FIRST(&MyListRoot);
  204. assert(pFoo);
  205. assert(pFoo->a == 0x1A);
  206. assert(pFoo->b == 0x1B);
  207. pFoo = LIST_NEXT(pFoo,ListStuff);
  208. assert(pFoo);
  209. assert(pFoo->a == 0x3A);
  210. assert(pFoo->b == 0x3B);
  211. assert(LIST_NEXT(pFoo,ListStuff) == 0);
  212. /* Delete member 3. */
  213. pFoo = LIST_FIRST(&MyListRoot);
  214. pFoo = LIST_NEXT(pFoo,ListStuff);
  215. LIST_DELETE(pFoo,ListStuff);
  216. assert(pFoo->a == 0x3A);/* Make sure we have the right member. */
  217. assert(pFoo->b == 0x3B);/* And the data is intact. */
  218. assert(LIST_NEXT(pFoo,ListStuff) == 0);
  219. /* Delete member 1. */
  220. pFoo = LIST_FIRST(&MyListRoot);
  221. LIST_DELETE(pFoo,ListStuff);
  222. assert(pFoo->a == 0x1A);/* Make sure we have the right member. */
  223. assert(pFoo->b == 0x1B);/* And the data is intact. */
  224. assert(LIST_NEXT(pFoo,ListStuff) == 0);
  225. assert(LIST_FIRST(&MyListRoot) == 0);
  226. LIST_INSERT_ROOT(&MyListRoot,&MyFoo2,ListStuff);
  227. LIST_INSERT_ROOT(&MyListRoot,&MyFoo1,ListStuff);
  228. /* Delete member 1 while there are other members in the list. */
  229. pFoo = LIST_FIRST(&MyListRoot);
  230. LIST_DELETE(pFoo,ListStuff);
  231. assert(pFoo->a == 0x1A);/* Make sure we have the right member. */
  232. assert(pFoo->b == 0x1B);/* And the data is intact. */
  233. assert(LIST_NEXT(pFoo,ListStuff) == 0);
  234. assert(LIST_FIRST(&MyListRoot) == &MyFoo2);
  235. assert(MyFoo1.a == 0x1A); assert(MyFoo1.b == 0x1B);
  236. assert(MyFoo2.a == 0x2A); assert(MyFoo2.b == 0x2B);
  237. assert(MyFoo3.a == 0x3A); assert(MyFoo3.b == 0x3B);
  238. fputs("List passed.\n", stdout);
  239. }
  240. void TestTailQueue(void)
  241. {
  242. struct Foo
  243. {
  244. int a;
  245. TAIL_QUEUE_MEMBER(Foo) TQStuff;
  246. int b;
  247. };
  248. struct Foo MyFoo1, MyFoo2, MyFoo3, *pFoo = 0;
  249. TAIL_QUEUE_ROOT(sRoot, Foo) MyTQRoot;
  250. fputs("Testing TAIL_QUEUE.\n",stdout);
  251. TAIL_QUEUE_INITIALIZE(&MyTQRoot);
  252. MyFoo1.a = 0x1A; MyFoo1.b = 0x1B;
  253. MyFoo2.a = 0x2A; MyFoo2.b = 0x2B;
  254. MyFoo3.a = 0x3A; MyFoo3.b = 0x3B;
  255. TAIL_QUEUE_INSERT_END(&MyTQRoot,&MyFoo1,TQStuff);
  256. TAIL_QUEUE_INSERT_END(&MyTQRoot,&MyFoo2,TQStuff);
  257. TAIL_QUEUE_INSERT_END(&MyTQRoot,&MyFoo3,TQStuff);
  258. pFoo = TAIL_QUEUE_FIRST(&MyTQRoot);
  259. assert(pFoo);
  260. assert(pFoo->a == 0x1A);
  261. assert(pFoo->b == 0x1B);
  262. pFoo = TAIL_QUEUE_NEXT(pFoo,TQStuff);
  263. assert(pFoo);
  264. assert(pFoo->a == 0x2A);
  265. assert(pFoo->b == 0x2B);
  266. pFoo = TAIL_QUEUE_NEXT(pFoo,TQStuff);
  267. assert(pFoo);
  268. assert(pFoo->a == 0x3A);
  269. assert(pFoo->b == 0x3B);
  270. pFoo = TAIL_QUEUE_NEXT(pFoo,TQStuff);
  271. assert(pFoo == 0);
  272. /* Delete member 2. */
  273. pFoo = TAIL_QUEUE_FIRST(&MyTQRoot);
  274. pFoo = TAIL_QUEUE_NEXT(pFoo,TQStuff);
  275. TAIL_QUEUE_DELETE(&MyTQRoot,pFoo,TQStuff);
  276. assert(pFoo->a == 0x2A);/* Make sure we have the right member. */
  277. assert(pFoo->b == 0x2B);/* And the data is intact. */
  278. assert(TAIL_QUEUE_NEXT(pFoo,TQStuff) == 0);
  279. /* Make sure that there are only members 1 and 3 in the list now. */
  280. pFoo = TAIL_QUEUE_FIRST(&MyTQRoot);
  281. assert(pFoo);
  282. assert(pFoo->a == 0x1A);
  283. assert(pFoo->b == 0x1B);
  284. pFoo = TAIL_QUEUE_NEXT(pFoo,TQStuff);
  285. assert(pFoo);
  286. assert(pFoo->a == 0x3A);
  287. assert(pFoo->b == 0x3B);
  288. assert(TAIL_QUEUE_NEXT(pFoo,TQStuff) == 0);
  289. /* Delete member 3. */
  290. pFoo = TAIL_QUEUE_FIRST(&MyTQRoot);
  291. pFoo = TAIL_QUEUE_NEXT(pFoo,TQStuff);
  292. TAIL_QUEUE_DELETE(&MyTQRoot,pFoo,TQStuff);
  293. assert(pFoo->a == 0x3A);/* Make sure we have the right member. */
  294. assert(pFoo->b == 0x3B);/* And the data is intact. */
  295. assert(TAIL_QUEUE_NEXT(pFoo,TQStuff) == 0);
  296. /* Delete member 1. */
  297. pFoo = TAIL_QUEUE_FIRST(&MyTQRoot);
  298. TAIL_QUEUE_DELETE(&MyTQRoot,pFoo,TQStuff);
  299. assert(pFoo->a == 0x1A);/* Make sure we have the right member. */
  300. assert(pFoo->b == 0x1B);/* And the data is intact. */
  301. assert(TAIL_QUEUE_NEXT(pFoo,TQStuff) == 0);
  302. assert(TAIL_QUEUE_FIRST(&MyTQRoot) == 0);
  303. TAIL_QUEUE_INSERT_END(&MyTQRoot,&MyFoo1,TQStuff);
  304. TAIL_QUEUE_INSERT_END(&MyTQRoot,&MyFoo2,TQStuff);
  305. /* Delete member 1 while there are other members in the list. */
  306. pFoo = TAIL_QUEUE_FIRST(&MyTQRoot);
  307. TAIL_QUEUE_DELETE(&MyTQRoot,pFoo,TQStuff);
  308. assert(pFoo->a == 0x1A);/* Make sure we have the right member. */
  309. assert(pFoo->b == 0x1B);/* And the data is intact. */
  310. assert(TAIL_QUEUE_NEXT(pFoo,TQStuff) == 0);
  311. assert(TAIL_QUEUE_FIRST(&MyTQRoot) == &MyFoo2);
  312. assert(MyFoo1.a == 0x1A); assert(MyFoo1.b == 0x1B);
  313. assert(MyFoo2.a == 0x2A); assert(MyFoo2.b == 0x2B);
  314. assert(MyFoo3.a == 0x3A); assert(MyFoo3.b == 0x3B);
  315. fputs("Tail Queue passed.\n", stdout);
  316. }
  317. void TestCircleQueue(void)
  318. {
  319. enum {END,ROOT,PREVIOUS,DONE} WhichInsert = END;
  320. int i;
  321. struct Foo
  322. {
  323. int a;
  324. CIRCLE_QUEUE_MEMBER(Foo) CQStuff;
  325. int b;
  326. };
  327. struct Foo MyFoo1, MyFoo2, MyFoo3, *pFoo = 0;
  328. CIRCLE_QUEUE_ROOT(sRoot, Foo) MyCQRoot;
  329. fputs("Testing CIRCLE_QUEUE.\n",stdout);
  330. while(WhichInsert != DONE)
  331. {
  332. CIRCLE_QUEUE_INITIALIZE(&MyCQRoot,Foo);
  333. MyFoo1.a = 0x1A; MyFoo1.b = 0x1B;
  334. MyFoo2.a = 0x2A; MyFoo2.b = 0x2B;
  335. MyFoo3.a = 0x3A; MyFoo3.b = 0x3B;
  336. switch(WhichInsert)
  337. {
  338. case END:
  339. CIRCLE_QUEUE_INSERT_END(&MyCQRoot,Foo,&MyFoo1,CQStuff);
  340. CIRCLE_QUEUE_INSERT_END(&MyCQRoot,Foo,&MyFoo2,CQStuff);
  341. CIRCLE_QUEUE_INSERT_END(&MyCQRoot,Foo,&MyFoo3,CQStuff);
  342. WhichInsert = ROOT;
  343. break;
  344. case ROOT:
  345. CIRCLE_QUEUE_INSERT_ROOT(&MyCQRoot,Foo,&MyFoo3,CQStuff);
  346. CIRCLE_QUEUE_INSERT_ROOT(&MyCQRoot,Foo,&MyFoo2,CQStuff);
  347. CIRCLE_QUEUE_INSERT_ROOT(&MyCQRoot,Foo,&MyFoo1,CQStuff);
  348. WhichInsert = PREVIOUS;
  349. break;
  350. case PREVIOUS:
  351. CIRCLE_QUEUE_INSERT_ROOT(&MyCQRoot,Foo,&MyFoo3,CQStuff);
  352. CIRCLE_QUEUE_INSERT_PREVIOUS(&MyCQRoot,&MyFoo3,&MyFoo2,CQStuff);
  353. CIRCLE_QUEUE_INSERT_PREVIOUS(&MyCQRoot,&MyFoo2,&MyFoo1,CQStuff);
  354. WhichInsert = DONE;
  355. break;
  356. default:
  357. assert(0);
  358. }
  359. pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
  360. assert(pFoo);
  361. assert(pFoo->a == 0x1A);
  362. assert(pFoo->b == 0x1B);
  363. pFoo = CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff);
  364. assert(pFoo);
  365. assert(pFoo->a == 0x2A);
  366. assert(pFoo->b == 0x2B);
  367. pFoo = CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff);
  368. assert(pFoo);
  369. assert(pFoo->a == 0x3A);
  370. assert(pFoo->b == 0x3B);
  371. pFoo = CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff);
  372. assert(pFoo == 0);
  373. pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
  374. assert(CIRCLE_QUEUE_PREVIOUS(&MyCQRoot,pFoo,CQStuff) == 0);
  375. pFoo = CIRCLE_QUEUE_LAST(&MyCQRoot);
  376. assert(pFoo == &MyFoo3);
  377. assert(CIRCLE_QUEUE_PREVIOUS(&MyCQRoot,pFoo,CQStuff) == &MyFoo2);
  378. assert(CIRCLE_QUEUE_PREVIOUS(&MyCQRoot,&MyFoo2,CQStuff) == &MyFoo1);
  379. /* Delete member 2. */
  380. pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
  381. pFoo = CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff);
  382. CIRCLE_QUEUE_DELETE(&MyCQRoot,pFoo,CQStuff);
  383. assert(pFoo->a == 0x2A);/* Make sure we have the right member. */
  384. assert(pFoo->b == 0x2B);/* And the data is intact. */
  385. assert(CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff) == 0);
  386. /* Make sure that there are only members 1 and 3 in the list now. */
  387. pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
  388. assert(pFoo);
  389. assert(pFoo->a == 0x1A);
  390. assert(pFoo->b == 0x1B);
  391. pFoo = CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff);
  392. assert(pFoo);
  393. assert(pFoo->a == 0x3A);
  394. assert(pFoo->b == 0x3B);
  395. assert(CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff) == 0);
  396. /* Delete member 3. */
  397. pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
  398. pFoo = CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff);
  399. CIRCLE_QUEUE_DELETE(&MyCQRoot,pFoo,CQStuff);
  400. assert(pFoo->a == 0x3A);/* Make sure we have the right member. */
  401. assert(pFoo->b == 0x3B);/* And the data is intact. */
  402. assert(CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff) == 0);
  403. /* Delete member 1. */
  404. pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
  405. CIRCLE_QUEUE_DELETE(&MyCQRoot,pFoo,CQStuff);
  406. assert(pFoo->a == 0x1A);/* Make sure we have the right member. */
  407. assert(pFoo->b == 0x1B);/* And the data is intact. */
  408. assert(CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff) == 0);
  409. assert(CIRCLE_QUEUE_FIRST(&MyCQRoot) == 0);
  410. CIRCLE_QUEUE_INSERT_END(&MyCQRoot,Foo,&MyFoo1,CQStuff);
  411. CIRCLE_QUEUE_INSERT_END(&MyCQRoot,Foo,&MyFoo2,CQStuff);
  412. /* Delete member 1 while there are other members in the list. */
  413. pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
  414. CIRCLE_QUEUE_DELETE(&MyCQRoot,pFoo,CQStuff);
  415. assert(pFoo->a == 0x1A);/* Make sure we have the right member. */
  416. assert(pFoo->b == 0x1B);/* And the data is intact. */
  417. assert(CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff) == 0);
  418. assert(CIRCLE_QUEUE_FIRST(&MyCQRoot) == &MyFoo2);
  419. assert(MyFoo1.a == 0x1A); assert(MyFoo1.b == 0x1B);
  420. assert(MyFoo2.a == 0x2A); assert(MyFoo2.b == 0x2B);
  421. assert(MyFoo3.a == 0x3A); assert(MyFoo3.b == 0x3B);
  422. }
  423. fputs("Circle Queue passed.\n", stdout);
  424. }
  425. int main()
  426. {
  427. TestList();
  428. TestTailQueue();
  429. TestCircleQueue();
  430. fputs("All tests passed.", stdout);
  431. return EXIT_SUCCESS;
  432. }
  433. #endif /* End of test code. */
  434. #endif // !_LISTS_H