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.

518 lines
16 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. #if __cplusplus
  8. extern "C" {
  9. #endif
  10. #define LIST_ROOT(name, type) struct name {struct type *Root;}
  11. #define LIST_MEMBER(type) struct { struct type **Prev; struct type *Next;}
  12. /* Note! Prev is the ADDRESS of the previous next element ptr */
  13. #define LIST_INSERT_ROOT(root,element,field)\
  14. { if(((element)->field.Next = (root)->Root) != 0)\
  15. (root)->Root->field.Prev = &(element)->field.Next;\
  16. (root)->Root = (element);\
  17. (element)->field.Prev = &(root)->Root;\
  18. }
  19. #define LIST_DELETE(element,field)\
  20. {\
  21. if((element)->field.Next)\
  22. (element)->field.Next->field.Prev = (element)->field.Prev;\
  23. *(element)->field.Prev = (element)->field.Next;\
  24. (element)->field.Next = 0;\
  25. (element)->field.Prev = 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. { struct type *First;\
  46. struct type **Last;\
  47. }/* NOTE! This is the address of the last Next pointer. */
  48. #define TAIL_QUEUE_MEMBER(type)\
  49. struct\
  50. { struct type *Next;\
  51. struct 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. { struct type *Last;\
  74. struct type *First;\
  75. }
  76. #define CIRCLE_QUEUE_MEMBER(type)\
  77. struct\
  78. { struct type *Prev;\
  79. struct 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. #if 0
  136. /*
  137. Test code. Strip it out, put it in a .C (or .CPP) file and compile it as a
  138. console app to test this stuff. It should run without any assertion failures.
  139. Also, use this as example code.
  140. */
  141. #include <stdio.h>
  142. #include <stdlib.h>
  143. #include <assert.h>
  144. #include "lists.h"
  145. void TestList(void)
  146. {
  147. struct Foo
  148. {
  149. int a;
  150. LIST_MEMBER(Foo) ListStuff;
  151. int b;
  152. };
  153. struct Foo MyFoo1, MyFoo2, MyFoo3, *pFoo = 0;
  154. LIST_ROOT(sRoot, Foo) MyListRoot;
  155. fputs("Testing LIST.\n",stdout);
  156. LIST_INITIALIZE(&MyListRoot);
  157. LIST_INITIALIZE_MEMBER(&MyFoo1,ListStuff);
  158. MyFoo1.a = 0x1A; MyFoo1.b = 0x1B;
  159. LIST_INITIALIZE_MEMBER(&MyFoo2,ListStuff);
  160. MyFoo2.a = 0x2A; MyFoo2.b = 0x2B;
  161. LIST_INITIALIZE_MEMBER(&MyFoo3,ListStuff);
  162. MyFoo3.a = 0x3A; MyFoo3.b = 0x3B;
  163. assert(LIST_ORPHAN_MEMBER(&MyFoo3,ListStuff));
  164. LIST_INSERT_ROOT(&MyListRoot,&MyFoo3,ListStuff);
  165. assert(!LIST_ORPHAN_MEMBER(&MyFoo3,ListStuff));
  166. LIST_INSERT_ROOT(&MyListRoot,&MyFoo2,ListStuff);
  167. LIST_INSERT_ROOT(&MyListRoot,&MyFoo1,ListStuff);
  168. assert(!LIST_ORPHAN_MEMBER(&MyFoo1,ListStuff));
  169. assert(!LIST_ORPHAN_MEMBER(&MyFoo2,ListStuff));
  170. assert(!LIST_ORPHAN_MEMBER(&MyFoo3,ListStuff));
  171. pFoo = LIST_FIRST(&MyListRoot);
  172. assert(pFoo);
  173. assert(pFoo->a == 0x1A);
  174. assert(pFoo->b == 0x1B);
  175. pFoo = LIST_NEXT(pFoo,ListStuff);
  176. assert(pFoo);
  177. assert(pFoo->a == 0x2A);
  178. assert(pFoo->b == 0x2B);
  179. pFoo = LIST_NEXT(pFoo,ListStuff);
  180. assert(pFoo);
  181. assert(pFoo->a == 0x3A);
  182. assert(pFoo->b == 0x3B);
  183. pFoo = LIST_NEXT(pFoo,ListStuff);
  184. assert(pFoo == 0);
  185. /* Delete member 2. */
  186. pFoo = LIST_FIRST(&MyListRoot);
  187. pFoo = LIST_NEXT(pFoo,ListStuff);
  188. LIST_DELETE(pFoo,ListStuff);
  189. assert(pFoo->a == 0x2A);/* Make sure we have the right member. */
  190. assert(pFoo->b == 0x2B);/* And the data is intact. */
  191. assert(LIST_NEXT(pFoo,ListStuff) == 0);
  192. /* Make sure that there are only members 1 and 3 in the list now. */
  193. pFoo = LIST_FIRST(&MyListRoot);
  194. assert(pFoo);
  195. assert(pFoo->a == 0x1A);
  196. assert(pFoo->b == 0x1B);
  197. pFoo = LIST_NEXT(pFoo,ListStuff);
  198. assert(pFoo);
  199. assert(pFoo->a == 0x3A);
  200. assert(pFoo->b == 0x3B);
  201. assert(LIST_NEXT(pFoo,ListStuff) == 0);
  202. /* Delete member 3. */
  203. pFoo = LIST_FIRST(&MyListRoot);
  204. pFoo = LIST_NEXT(pFoo,ListStuff);
  205. LIST_DELETE(pFoo,ListStuff);
  206. assert(pFoo->a == 0x3A);/* Make sure we have the right member. */
  207. assert(pFoo->b == 0x3B);/* And the data is intact. */
  208. assert(LIST_NEXT(pFoo,ListStuff) == 0);
  209. /* Delete member 1. */
  210. pFoo = LIST_FIRST(&MyListRoot);
  211. LIST_DELETE(pFoo,ListStuff);
  212. assert(pFoo->a == 0x1A);/* Make sure we have the right member. */
  213. assert(pFoo->b == 0x1B);/* And the data is intact. */
  214. assert(LIST_NEXT(pFoo,ListStuff) == 0);
  215. assert(LIST_FIRST(&MyListRoot) == 0);
  216. LIST_INSERT_ROOT(&MyListRoot,&MyFoo2,ListStuff);
  217. LIST_INSERT_ROOT(&MyListRoot,&MyFoo1,ListStuff);
  218. /* Delete member 1 while there are other members in the list. */
  219. pFoo = LIST_FIRST(&MyListRoot);
  220. LIST_DELETE(pFoo,ListStuff);
  221. assert(pFoo->a == 0x1A);/* Make sure we have the right member. */
  222. assert(pFoo->b == 0x1B);/* And the data is intact. */
  223. assert(LIST_NEXT(pFoo,ListStuff) == 0);
  224. assert(LIST_FIRST(&MyListRoot) == &MyFoo2);
  225. assert(MyFoo1.a == 0x1A); assert(MyFoo1.b == 0x1B);
  226. assert(MyFoo2.a == 0x2A); assert(MyFoo2.b == 0x2B);
  227. assert(MyFoo3.a == 0x3A); assert(MyFoo3.b == 0x3B);
  228. fputs("List passed.\n", stdout);
  229. }
  230. void TestTailQueue(void)
  231. {
  232. struct Foo
  233. {
  234. int a;
  235. TAIL_QUEUE_MEMBER(Foo) TQStuff;
  236. int b;
  237. };
  238. struct Foo MyFoo1, MyFoo2, MyFoo3, *pFoo = 0;
  239. TAIL_QUEUE_ROOT(sRoot, Foo) MyTQRoot;
  240. fputs("Testing TAIL_QUEUE.\n",stdout);
  241. TAIL_QUEUE_INITIALIZE(&MyTQRoot);
  242. MyFoo1.a = 0x1A; MyFoo1.b = 0x1B;
  243. MyFoo2.a = 0x2A; MyFoo2.b = 0x2B;
  244. MyFoo3.a = 0x3A; MyFoo3.b = 0x3B;
  245. TAIL_QUEUE_INSERT_END(&MyTQRoot,&MyFoo1,TQStuff);
  246. TAIL_QUEUE_INSERT_END(&MyTQRoot,&MyFoo2,TQStuff);
  247. TAIL_QUEUE_INSERT_END(&MyTQRoot,&MyFoo3,TQStuff);
  248. pFoo = TAIL_QUEUE_FIRST(&MyTQRoot);
  249. assert(pFoo);
  250. assert(pFoo->a == 0x1A);
  251. assert(pFoo->b == 0x1B);
  252. pFoo = TAIL_QUEUE_NEXT(pFoo,TQStuff);
  253. assert(pFoo);
  254. assert(pFoo->a == 0x2A);
  255. assert(pFoo->b == 0x2B);
  256. pFoo = TAIL_QUEUE_NEXT(pFoo,TQStuff);
  257. assert(pFoo);
  258. assert(pFoo->a == 0x3A);
  259. assert(pFoo->b == 0x3B);
  260. pFoo = TAIL_QUEUE_NEXT(pFoo,TQStuff);
  261. assert(pFoo == 0);
  262. /* Delete member 2. */
  263. pFoo = TAIL_QUEUE_FIRST(&MyTQRoot);
  264. pFoo = TAIL_QUEUE_NEXT(pFoo,TQStuff);
  265. TAIL_QUEUE_DELETE(&MyTQRoot,pFoo,TQStuff);
  266. assert(pFoo->a == 0x2A);/* Make sure we have the right member. */
  267. assert(pFoo->b == 0x2B);/* And the data is intact. */
  268. assert(TAIL_QUEUE_NEXT(pFoo,TQStuff) == 0);
  269. /* Make sure that there are only members 1 and 3 in the list now. */
  270. pFoo = TAIL_QUEUE_FIRST(&MyTQRoot);
  271. assert(pFoo);
  272. assert(pFoo->a == 0x1A);
  273. assert(pFoo->b == 0x1B);
  274. pFoo = TAIL_QUEUE_NEXT(pFoo,TQStuff);
  275. assert(pFoo);
  276. assert(pFoo->a == 0x3A);
  277. assert(pFoo->b == 0x3B);
  278. assert(TAIL_QUEUE_NEXT(pFoo,TQStuff) == 0);
  279. /* Delete member 3. */
  280. pFoo = TAIL_QUEUE_FIRST(&MyTQRoot);
  281. pFoo = TAIL_QUEUE_NEXT(pFoo,TQStuff);
  282. TAIL_QUEUE_DELETE(&MyTQRoot,pFoo,TQStuff);
  283. assert(pFoo->a == 0x3A);/* Make sure we have the right member. */
  284. assert(pFoo->b == 0x3B);/* And the data is intact. */
  285. assert(TAIL_QUEUE_NEXT(pFoo,TQStuff) == 0);
  286. /* Delete member 1. */
  287. pFoo = TAIL_QUEUE_FIRST(&MyTQRoot);
  288. TAIL_QUEUE_DELETE(&MyTQRoot,pFoo,TQStuff);
  289. assert(pFoo->a == 0x1A);/* Make sure we have the right member. */
  290. assert(pFoo->b == 0x1B);/* And the data is intact. */
  291. assert(TAIL_QUEUE_NEXT(pFoo,TQStuff) == 0);
  292. assert(TAIL_QUEUE_FIRST(&MyTQRoot) == 0);
  293. TAIL_QUEUE_INSERT_END(&MyTQRoot,&MyFoo1,TQStuff);
  294. TAIL_QUEUE_INSERT_END(&MyTQRoot,&MyFoo2,TQStuff);
  295. /* Delete member 1 while there are other members in the list. */
  296. pFoo = TAIL_QUEUE_FIRST(&MyTQRoot);
  297. TAIL_QUEUE_DELETE(&MyTQRoot,pFoo,TQStuff);
  298. assert(pFoo->a == 0x1A);/* Make sure we have the right member. */
  299. assert(pFoo->b == 0x1B);/* And the data is intact. */
  300. assert(TAIL_QUEUE_NEXT(pFoo,TQStuff) == 0);
  301. assert(TAIL_QUEUE_FIRST(&MyTQRoot) == &MyFoo2);
  302. assert(MyFoo1.a == 0x1A); assert(MyFoo1.b == 0x1B);
  303. assert(MyFoo2.a == 0x2A); assert(MyFoo2.b == 0x2B);
  304. assert(MyFoo3.a == 0x3A); assert(MyFoo3.b == 0x3B);
  305. fputs("Tail Queue passed.\n", stdout);
  306. }
  307. void TestCircleQueue(void)
  308. {
  309. enum {END,ROOT,PREVIOUS,DONE} WhichInsert = END;
  310. int i;
  311. struct Foo
  312. {
  313. int a;
  314. CIRCLE_QUEUE_MEMBER(Foo) CQStuff;
  315. int b;
  316. };
  317. struct Foo MyFoo1, MyFoo2, MyFoo3, *pFoo = 0;
  318. CIRCLE_QUEUE_ROOT(sRoot, Foo) MyCQRoot;
  319. fputs("Testing CIRCLE_QUEUE.\n",stdout);
  320. while(WhichInsert != DONE)
  321. {
  322. CIRCLE_QUEUE_INITIALIZE(&MyCQRoot,Foo);
  323. MyFoo1.a = 0x1A; MyFoo1.b = 0x1B;
  324. MyFoo2.a = 0x2A; MyFoo2.b = 0x2B;
  325. MyFoo3.a = 0x3A; MyFoo3.b = 0x3B;
  326. switch(WhichInsert)
  327. {
  328. case END:
  329. CIRCLE_QUEUE_INSERT_END(&MyCQRoot,Foo,&MyFoo1,CQStuff);
  330. CIRCLE_QUEUE_INSERT_END(&MyCQRoot,Foo,&MyFoo2,CQStuff);
  331. CIRCLE_QUEUE_INSERT_END(&MyCQRoot,Foo,&MyFoo3,CQStuff);
  332. WhichInsert = ROOT;
  333. break;
  334. case ROOT:
  335. CIRCLE_QUEUE_INSERT_ROOT(&MyCQRoot,Foo,&MyFoo3,CQStuff);
  336. CIRCLE_QUEUE_INSERT_ROOT(&MyCQRoot,Foo,&MyFoo2,CQStuff);
  337. CIRCLE_QUEUE_INSERT_ROOT(&MyCQRoot,Foo,&MyFoo1,CQStuff);
  338. WhichInsert = PREVIOUS;
  339. break;
  340. case PREVIOUS:
  341. CIRCLE_QUEUE_INSERT_ROOT(&MyCQRoot,Foo,&MyFoo3,CQStuff);
  342. CIRCLE_QUEUE_INSERT_PREVIOUS(&MyCQRoot,&MyFoo3,&MyFoo2,CQStuff);
  343. CIRCLE_QUEUE_INSERT_PREVIOUS(&MyCQRoot,&MyFoo2,&MyFoo1,CQStuff);
  344. WhichInsert = DONE;
  345. break;
  346. default:
  347. assert(0);
  348. }
  349. pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
  350. assert(pFoo);
  351. assert(pFoo->a == 0x1A);
  352. assert(pFoo->b == 0x1B);
  353. pFoo = CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff);
  354. assert(pFoo);
  355. assert(pFoo->a == 0x2A);
  356. assert(pFoo->b == 0x2B);
  357. pFoo = CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff);
  358. assert(pFoo);
  359. assert(pFoo->a == 0x3A);
  360. assert(pFoo->b == 0x3B);
  361. pFoo = CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff);
  362. assert(pFoo == 0);
  363. pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
  364. assert(CIRCLE_QUEUE_PREVIOUS(&MyCQRoot,pFoo,CQStuff) == 0);
  365. pFoo = CIRCLE_QUEUE_LAST(&MyCQRoot);
  366. assert(pFoo == &MyFoo3);
  367. assert(CIRCLE_QUEUE_PREVIOUS(&MyCQRoot,pFoo,CQStuff) == &MyFoo2);
  368. assert(CIRCLE_QUEUE_PREVIOUS(&MyCQRoot,&MyFoo2,CQStuff) == &MyFoo1);
  369. /* Delete member 2. */
  370. pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
  371. pFoo = CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff);
  372. CIRCLE_QUEUE_DELETE(&MyCQRoot,pFoo,CQStuff);
  373. assert(pFoo->a == 0x2A);/* Make sure we have the right member. */
  374. assert(pFoo->b == 0x2B);/* And the data is intact. */
  375. assert(CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff) == 0);
  376. /* Make sure that there are only members 1 and 3 in the list now. */
  377. pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
  378. assert(pFoo);
  379. assert(pFoo->a == 0x1A);
  380. assert(pFoo->b == 0x1B);
  381. pFoo = CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff);
  382. assert(pFoo);
  383. assert(pFoo->a == 0x3A);
  384. assert(pFoo->b == 0x3B);
  385. assert(CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff) == 0);
  386. /* Delete member 3. */
  387. pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
  388. pFoo = CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff);
  389. CIRCLE_QUEUE_DELETE(&MyCQRoot,pFoo,CQStuff);
  390. assert(pFoo->a == 0x3A);/* Make sure we have the right member. */
  391. assert(pFoo->b == 0x3B);/* And the data is intact. */
  392. assert(CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff) == 0);
  393. /* Delete member 1. */
  394. pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
  395. CIRCLE_QUEUE_DELETE(&MyCQRoot,pFoo,CQStuff);
  396. assert(pFoo->a == 0x1A);/* Make sure we have the right member. */
  397. assert(pFoo->b == 0x1B);/* And the data is intact. */
  398. assert(CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff) == 0);
  399. assert(CIRCLE_QUEUE_FIRST(&MyCQRoot) == 0);
  400. CIRCLE_QUEUE_INSERT_END(&MyCQRoot,Foo,&MyFoo1,CQStuff);
  401. CIRCLE_QUEUE_INSERT_END(&MyCQRoot,Foo,&MyFoo2,CQStuff);
  402. /* Delete member 1 while there are other members in the list. */
  403. pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
  404. CIRCLE_QUEUE_DELETE(&MyCQRoot,pFoo,CQStuff);
  405. assert(pFoo->a == 0x1A);/* Make sure we have the right member. */
  406. assert(pFoo->b == 0x1B);/* And the data is intact. */
  407. assert(CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff) == 0);
  408. assert(CIRCLE_QUEUE_FIRST(&MyCQRoot) == &MyFoo2);
  409. assert(MyFoo1.a == 0x1A); assert(MyFoo1.b == 0x1B);
  410. assert(MyFoo2.a == 0x2A); assert(MyFoo2.b == 0x2B);
  411. assert(MyFoo3.a == 0x3A); assert(MyFoo3.b == 0x3B);
  412. }
  413. fputs("Circle Queue passed.\n", stdout);
  414. }
  415. int main()
  416. {
  417. TestList();
  418. TestTailQueue();
  419. TestCircleQueue();
  420. fputs("All tests passed.", stdout);
  421. return EXIT_SUCCESS;
  422. }
  423. #endif /* End of test code. */
  424. #if __cplusplus
  425. }
  426. #endif
  427. #endif // !_LISTS_H