/branches/SN-NG4-solaris_fixes/db4/test/scr023/q.c

https://gitlab.com/OpenSourceMirror/sourcenav · C · 834 lines · 706 code · 102 blank · 26 comment · 159 complexity · 714fcbe745eb1ce88a06f2978961f73a MD5 · raw file

  1. #include <sys/types.h>
  2. #include <sys/time.h>
  3. #include <assert.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <unistd.h>
  8. #include "queue.h"
  9. #include "shqueue.h"
  10. typedef enum {
  11. FORWARD_WALK_FAILED = 1,
  12. FOREACH_WALK_FAILED,
  13. LIST_END_NOT_MARKED_FAILURE,
  14. PREV_WALK_FAILED,
  15. REVERSE_FOREACH_WALK_FAILED,
  16. EXPECTED_HEAD_FAILED
  17. } FAILURE_REASON;
  18. const char *failure_reason_names[] = {
  19. "",
  20. "walking the list using the _NEXT forward failed",
  21. "walking the list using the _FOREACH macro failed",
  22. "what was expected to be the last element wasn't marked as such",
  23. "walking the list using the _PREV macro failed",
  24. "walking the list using the _REVERSE_FOREACH macro failed",
  25. "expected to be at the head of the list"
  26. };
  27. SH_LIST_HEAD(sh_lq);
  28. struct sh_le {
  29. char content;
  30. SH_LIST_ENTRY sh_les;
  31. };
  32. /* create a string from the content of a list queue */
  33. char *
  34. sh_l_as_string(l)
  35. struct sh_lq *l;
  36. {
  37. static char buf[1024];
  38. struct sh_le *ele = SH_LIST_FIRST(l, sh_le);
  39. int i = 1;
  40. buf[0] = '"';
  41. while (ele != NULL) {
  42. buf[i] = ele->content;
  43. ele = SH_LIST_NEXT(ele, sh_les, sh_le);
  44. if (ele != NULL)
  45. buf[++i] = ' ';
  46. i++;
  47. }
  48. buf[i++] = '"';
  49. buf[i] = '\0';
  50. return buf;
  51. }
  52. /* init a list queue */
  53. struct sh_lq *
  54. sh_l_init(items)
  55. const char *items;
  56. {
  57. const char *c = items;
  58. struct sh_le *ele = NULL, *last_ele = (struct sh_le*)-1;
  59. struct sh_lq *l = calloc(1, sizeof(struct sh_lq));
  60. SH_LIST_INIT(l);
  61. while (*c != '\0') {
  62. if (c[0] != ' ') {
  63. last_ele = ele;
  64. ele = calloc(1, sizeof(struct sh_le));
  65. ele->content = c[0];
  66. if (SH_LIST_EMPTY(l))
  67. SH_LIST_INSERT_HEAD(l, ele, sh_les, sh_le);
  68. else
  69. SH_LIST_INSERT_AFTER(
  70. last_ele, ele, sh_les, sh_le);
  71. }
  72. c++;
  73. }
  74. return (l);
  75. }
  76. struct sh_lq *
  77. sh_l_remove_head(l)
  78. struct sh_lq *l;
  79. {
  80. struct sh_le *ele = SH_LIST_FIRST(l, sh_le);
  81. SH_LIST_REMOVE_HEAD(l, sh_les, sh_le);
  82. if (ele != NULL)
  83. free(ele);
  84. return (l);
  85. }
  86. struct sh_lq *
  87. sh_l_remove_tail(l)
  88. struct sh_lq *l;
  89. {
  90. struct sh_le *ele = SH_LIST_FIRST(l, sh_le);
  91. if (SH_LIST_EMPTY(l))
  92. return (l);
  93. while (SH_LIST_NEXT(ele, sh_les, sh_le) != NULL)
  94. ele = SH_LIST_NEXT(ele, sh_les, sh_le);
  95. if (ele) {
  96. SH_LIST_REMOVE(ele, sh_les, sh_le);
  97. free(ele);
  98. }
  99. return (l);
  100. }
  101. struct sh_lq *
  102. sh_l_remove_item(l, item)
  103. struct sh_lq *l;
  104. const char *item;
  105. {
  106. struct sh_le *ele = SH_LIST_FIRST(l, sh_le);
  107. while (ele != NULL) {
  108. if (ele->content == item[0])
  109. break;
  110. ele = SH_LIST_NEXT(ele, sh_les, sh_le);
  111. }
  112. if (ele)
  113. SH_LIST_REMOVE(ele, sh_les, sh_le);
  114. return (l);
  115. }
  116. struct sh_lq *
  117. sh_l_insert_head(l, item)
  118. struct sh_lq *l;
  119. const char *item;
  120. {
  121. struct sh_le *ele = calloc(1, sizeof(struct sh_le));
  122. ele->content = item[0];
  123. SH_LIST_INSERT_HEAD(l, ele, sh_les, sh_le);
  124. return (l);
  125. }
  126. struct sh_lq *
  127. sh_l_insert_tail(l, item)
  128. struct sh_lq *l;
  129. const char *item;
  130. {
  131. struct sh_le *ele = NULL;
  132. struct sh_le *last_ele = SH_LIST_FIRST(l, sh_le);
  133. if (last_ele != NULL)
  134. while (SH_LIST_NEXT(last_ele, sh_les, sh_le) != NULL)
  135. last_ele = SH_LIST_NEXT(last_ele, sh_les, sh_le);
  136. if (last_ele == NULL) {
  137. ele = calloc(1, sizeof(struct sh_le));
  138. ele->content = item[0];
  139. SH_LIST_INSERT_HEAD(l, ele, sh_les, sh_le);
  140. } else {
  141. ele = calloc(1, sizeof(struct sh_le));
  142. ele->content = item[0];
  143. SH_LIST_INSERT_AFTER(last_ele, ele, sh_les, sh_le);
  144. }
  145. return (l);
  146. }
  147. struct sh_lq *
  148. sh_l_insert_before(l, item, before_item)
  149. struct sh_lq *l;
  150. const char *item;
  151. const char *before_item;
  152. {
  153. struct sh_le *ele = NULL;
  154. struct sh_le *before_ele = SH_LIST_FIRST(l, sh_le);
  155. while (before_ele != NULL) {
  156. if (before_ele->content == before_item[0])
  157. break;
  158. before_ele = SH_LIST_NEXT(before_ele, sh_les, sh_le);
  159. }
  160. if (before_ele != NULL) {
  161. ele = calloc(1, sizeof(struct sh_le));
  162. ele->content = item[0];
  163. SH_LIST_INSERT_BEFORE(l, before_ele, ele, sh_les, sh_le);
  164. }
  165. return (l);
  166. }
  167. struct sh_lq *
  168. sh_l_insert_after(l, item, after_item)
  169. struct sh_lq *l;
  170. const char *item;
  171. const char *after_item;
  172. {
  173. struct sh_le *ele = NULL;
  174. struct sh_le *after_ele = SH_LIST_FIRST(l, sh_le);
  175. while (after_ele != NULL) {
  176. if (after_ele->content == after_item[0])
  177. break;
  178. after_ele = SH_LIST_NEXT(after_ele, sh_les, sh_le);
  179. }
  180. if (after_ele != NULL) {
  181. ele = calloc(1, sizeof(struct sh_le));
  182. ele->content = item[0];
  183. SH_LIST_INSERT_AFTER(after_ele, ele, sh_les, sh_le);
  184. }
  185. return (l);
  186. }
  187. void
  188. sh_l_discard(l)
  189. struct sh_lq *l;
  190. {
  191. struct sh_le *ele = NULL;
  192. while ((ele = SH_LIST_FIRST(l, sh_le)) != NULL) {
  193. SH_LIST_REMOVE(ele, sh_les, sh_le);
  194. free(ele);
  195. }
  196. free(l);
  197. }
  198. int
  199. sh_l_verify(l, items)
  200. struct sh_lq *l;
  201. const char *items;
  202. {
  203. const char *c = items;
  204. struct sh_le *ele = NULL, *lele = NULL;
  205. int i = 0, nele = 0;
  206. while (*c != '\0') {
  207. if (c[0] != ' ')
  208. nele++;
  209. c++;
  210. }
  211. /* use the FOREACH macro to walk the list */
  212. c = items;
  213. i = 0;
  214. SH_LIST_FOREACH(ele, l, sh_les, sh_le) {
  215. if (ele->content != c[0])
  216. return (FOREACH_WALK_FAILED);
  217. i++;
  218. c +=2;
  219. }
  220. if (i != nele)
  221. return (FOREACH_WALK_FAILED);
  222. i = 0;
  223. if (items[0] != '\0') {
  224. /* walk the list forward */
  225. c = items;
  226. ele = SH_LIST_FIRST(l, sh_le);
  227. while (*c != '\0') {
  228. lele = ele;
  229. if (c[0] != ' ') {
  230. if (ele->content != c[0])
  231. return (FORWARD_WALK_FAILED);
  232. i++;
  233. ele = SH_LIST_NEXT(ele, sh_les, sh_le);
  234. }
  235. c++;
  236. }
  237. ele = lele;
  238. if (i != nele)
  239. return (FOREACH_WALK_FAILED);
  240. /* ele should be the last element in the list... */
  241. /* ... so sle_next should be -1 */
  242. if (ele->sh_les.sle_next != -1)
  243. return (LIST_END_NOT_MARKED_FAILURE);
  244. /* and NEXT needs to be NULL */
  245. if (SH_LIST_NEXT(ele, sh_les, sh_le) != NULL)
  246. return (LIST_END_NOT_MARKED_FAILURE);
  247. /*
  248. * walk the list backwards using PREV macro, first move c
  249. * back a bit
  250. */
  251. c--;
  252. i = 0;
  253. while (c >= items) {
  254. if (c[0] != ' ') {
  255. lele = ele;
  256. if (ele->content != c[0])
  257. return (PREV_WALK_FAILED);
  258. ele = SH_LIST_PREV(ele, sh_les, sh_le);
  259. i++;
  260. }
  261. c--;
  262. }
  263. ele = lele;
  264. if (i != nele)
  265. return (PREV_WALK_FAILED);
  266. if (ele != SH_LIST_FIRST(l, sh_le))
  267. return (EXPECTED_HEAD_FAILED);
  268. }
  269. return (0);
  270. }
  271. SH_TAILQ_HEAD(sh_tq);
  272. struct sh_te {
  273. char content;
  274. SH_TAILQ_ENTRY sh_tes;
  275. };
  276. /* create a string from the content of a list queue */
  277. char *
  278. sh_t_as_string(l)
  279. struct sh_tq *l;
  280. {
  281. static char buf[1024];
  282. struct sh_te *ele = SH_TAILQ_FIRST(l, sh_te);
  283. int i = 1;
  284. buf[0] = '"';
  285. while (ele != NULL) {
  286. buf[i] = ele->content;
  287. ele = SH_TAILQ_NEXT(ele, sh_tes, sh_te);
  288. if (ele != NULL)
  289. buf[++i] = ' ';
  290. i++;
  291. }
  292. buf[i++] = '"';
  293. buf[i] = '\0';
  294. return (buf);
  295. }
  296. /* init a tail queue */
  297. struct sh_tq *
  298. sh_t_init(items)
  299. const char *items;
  300. {
  301. const char *c = items;
  302. struct sh_te *ele = NULL, *last_ele = (struct sh_te*)-1;
  303. struct sh_tq *l = calloc(1, sizeof(struct sh_tq));
  304. SH_TAILQ_INIT(l);
  305. while (*c != '\0') {
  306. if (c[0] != ' ') {
  307. ele = calloc(1, sizeof(struct sh_te));
  308. ele->content = c[0];
  309. if (SH_TAILQ_EMPTY(l))
  310. SH_TAILQ_INSERT_HEAD(l, ele, sh_tes, sh_te);
  311. else
  312. SH_TAILQ_INSERT_AFTER(
  313. l, last_ele, ele, sh_tes, sh_te);
  314. last_ele = ele;
  315. }
  316. c++;
  317. }
  318. return (l);
  319. }
  320. struct sh_tq *
  321. sh_t_remove_head(l)
  322. struct sh_tq *l;
  323. {
  324. struct sh_te *ele = SH_TAILQ_FIRST(l, sh_te);
  325. if (ele != NULL)
  326. SH_TAILQ_REMOVE(l, ele, sh_tes, sh_te);
  327. free(ele);
  328. return (l);
  329. }
  330. struct sh_tq *
  331. sh_t_remove_tail(l)
  332. struct sh_tq *l;
  333. {
  334. struct sh_te *ele = SH_TAILQ_FIRST(l, sh_te);
  335. if (SH_TAILQ_EMPTY(l))
  336. return (l);
  337. while (SH_TAILQ_NEXT(ele, sh_tes, sh_te) != NULL)
  338. ele = SH_TAILQ_NEXT(ele, sh_tes, sh_te);
  339. if (ele != NULL) {
  340. SH_TAILQ_REMOVE(l, ele, sh_tes, sh_te);
  341. free(ele);
  342. }
  343. return (l);
  344. }
  345. struct sh_tq *
  346. sh_t_remove_item(l, item)
  347. struct sh_tq *l;
  348. const char *item;
  349. {
  350. struct sh_te *ele = SH_TAILQ_FIRST(l, sh_te);
  351. while (ele != NULL) {
  352. if (ele->content == item[0])
  353. break;
  354. ele = SH_TAILQ_NEXT(ele, sh_tes, sh_te);
  355. }
  356. if (ele != NULL)
  357. SH_TAILQ_REMOVE(l, ele, sh_tes, sh_te);
  358. return (l);
  359. }
  360. struct sh_tq *
  361. sh_t_insert_head(l, item)
  362. struct sh_tq *l;
  363. const char *item;
  364. {
  365. struct sh_te *ele = calloc(1, sizeof(struct sh_te));
  366. ele->content = item[0];
  367. SH_TAILQ_INSERT_HEAD(l, ele, sh_tes, sh_te);
  368. return (l);
  369. }
  370. struct sh_tq *
  371. sh_t_insert_tail(l, item)
  372. struct sh_tq *l;
  373. const char *item;
  374. {
  375. struct sh_te *ele = 0;
  376. ele = calloc(1, sizeof(struct sh_te));
  377. ele->content = item[0];
  378. SH_TAILQ_INSERT_TAIL(l, ele, sh_tes);
  379. return l;
  380. }
  381. struct sh_tq *
  382. sh_t_insert_before(l, item, before_item)
  383. struct sh_tq *l;
  384. const char *item;
  385. const char *before_item;
  386. {
  387. struct sh_te *ele = NULL;
  388. struct sh_te *before_ele = SH_TAILQ_FIRST(l, sh_te);
  389. while (before_ele != NULL) {
  390. if (before_ele->content == before_item[0])
  391. break;
  392. before_ele = SH_TAILQ_NEXT(before_ele, sh_tes, sh_te);
  393. }
  394. if (before_ele != NULL) {
  395. ele = calloc(1, sizeof(struct sh_te));
  396. ele->content = item[0];
  397. SH_TAILQ_INSERT_BEFORE(l, before_ele, ele, sh_tes, sh_te);
  398. }
  399. return (l);
  400. }
  401. struct sh_tq *
  402. sh_t_insert_after(l, item, after_item)
  403. struct sh_tq *l;
  404. const char *item;
  405. const char *after_item;
  406. {
  407. struct sh_te *ele = NULL;
  408. struct sh_te *after_ele = SH_TAILQ_FIRST(l, sh_te);
  409. while (after_ele != NULL) {
  410. if (after_ele->content == after_item[0])
  411. break;
  412. after_ele = SH_TAILQ_NEXT(after_ele, sh_tes, sh_te);
  413. }
  414. if (after_ele != NULL) {
  415. ele = calloc(1, sizeof(struct sh_te));
  416. ele->content = item[0];
  417. SH_TAILQ_INSERT_AFTER(l, after_ele, ele, sh_tes, sh_te);
  418. }
  419. return (l);
  420. }
  421. void
  422. sh_t_discard(l)
  423. struct sh_tq *l;
  424. {
  425. struct sh_te *ele = NULL;
  426. while ((ele = SH_TAILQ_FIRST(l, sh_te)) != NULL) {
  427. SH_TAILQ_REMOVE(l, ele, sh_tes, sh_te);
  428. free(ele);
  429. }
  430. free(l);
  431. }
  432. int
  433. sh_t_verify(l, items)
  434. struct sh_tq *l;
  435. const char *items;
  436. {
  437. const char *c = items, *b = NULL;
  438. struct sh_te *ele = NULL, *lele = NULL;
  439. int i = 0, nele = 0;
  440. while (*c != '\0') {
  441. if (c[0] != ' ')
  442. nele++;
  443. c++;
  444. }
  445. /* use the FOREACH macro to walk the list */
  446. c = items;
  447. i = 0;
  448. SH_TAILQ_FOREACH(ele, l, sh_tes, sh_te) {
  449. if (ele->content != c[0])
  450. return (FOREACH_WALK_FAILED);
  451. i++;
  452. c +=2;
  453. }
  454. if (i != nele)
  455. return (FOREACH_WALK_FAILED);
  456. i = 0;
  457. if (items[0] != '\0') {
  458. /* walk the list forward */
  459. c = items;
  460. ele = SH_TAILQ_FIRST(l, sh_te);
  461. while (*c != '\0') {
  462. lele = ele;
  463. if (c[0] != ' ') {
  464. if (ele->content != c[0])
  465. return (FORWARD_WALK_FAILED);
  466. i++;
  467. ele = SH_TAILQ_NEXT(ele, sh_tes, sh_te);
  468. }
  469. c++;
  470. }
  471. if (i != nele)
  472. return (FOREACH_WALK_FAILED);
  473. if (lele != SH_TAILQ_LAST(l, sh_tes, sh_te))
  474. return (LIST_END_NOT_MARKED_FAILURE);
  475. ele = lele;
  476. /* ele should be the last element in the list... */
  477. /* ... so sle_next should be -1 */
  478. if (ele->sh_tes.stqe_next != -1)
  479. return (LIST_END_NOT_MARKED_FAILURE);
  480. /* and NEXT needs to be NULL */
  481. if (SH_TAILQ_NEXT(ele, sh_tes, sh_te) != NULL)
  482. return (LIST_END_NOT_MARKED_FAILURE);
  483. /* walk the list backwards using SH_LIST_PREV macro */
  484. c--;
  485. b = c;
  486. i = 0;
  487. while (c >= items) {
  488. if (c[0] != ' ') {
  489. lele = ele;
  490. if (ele->content != c[0])
  491. return (PREV_WALK_FAILED);
  492. ele = SH_TAILQ_PREV(l, ele, sh_tes, sh_te);
  493. i++;
  494. }
  495. c--;
  496. }
  497. ele = lele;
  498. if (i != nele)
  499. return (PREV_WALK_FAILED);
  500. if (ele != SH_TAILQ_FIRST(l, sh_te))
  501. return (-1);
  502. /* c should be the last character in the array, walk backwards
  503. from here using FOREACH_REVERSE and check the values again */
  504. c = b;
  505. i = 0;
  506. ele = SH_TAILQ_LAST(l, sh_tes, sh_te);
  507. SH_TAILQ_FOREACH_REVERSE(ele, l, sh_tes, sh_te) {
  508. if (ele->content != c[0])
  509. return (REVERSE_FOREACH_WALK_FAILED);
  510. i++;
  511. c -=2;
  512. }
  513. if (i != nele)
  514. return (REVERSE_FOREACH_WALK_FAILED);
  515. }
  516. return (0);
  517. }
  518. int
  519. sh_t_verify_TAILQ_LAST(l, items)
  520. struct sh_tq *l;
  521. const char *items;
  522. {
  523. const char *c = items;
  524. struct sh_te *ele = NULL;
  525. c = items;
  526. while (*c != '\0') {
  527. c++;
  528. }
  529. if (c == items) {
  530. /* items is empty, so last should be NULL */
  531. if (SH_TAILQ_LAST(l, sh_tes, sh_te) != NULL)
  532. return (-1);
  533. } else {
  534. c--;
  535. ele = SH_TAILQ_LAST(l, sh_tes, sh_te);
  536. if (ele->content != c[0])
  537. return (-1);
  538. }
  539. return (0);
  540. }
  541. typedef void *qds_t;
  542. struct {
  543. const char *name;
  544. qds_t *(*f_init)(const char *);
  545. qds_t *(*f_remove_head)(qds_t *);
  546. qds_t *(*f_remove_tail)(qds_t *);
  547. qds_t *(*f_remove_item)(qds_t *, const char *);
  548. qds_t *(*f_insert_head)(qds_t *, const char *);
  549. qds_t *(*f_insert_tail)(qds_t *, const char *);
  550. qds_t *(*f_insert_before)(qds_t *, const char *, const char *);
  551. qds_t *(*f_insert_after)(qds_t *, const char *, const char *);
  552. qds_t *(*f_discard)(qds_t *);
  553. char *(*f_as_string)(qds_t *);
  554. int (*f_verify)(qds_t *, const char *);
  555. } qfns[]= {
  556. { "sh_list",
  557. (qds_t*(*)(const char *))sh_l_init,
  558. (qds_t*(*)(qds_t *))sh_l_remove_head,
  559. (qds_t*(*)(qds_t *))sh_l_remove_tail,
  560. (qds_t*(*)(qds_t *, const char *))sh_l_remove_item,
  561. (qds_t*(*)(qds_t *, const char *))sh_l_insert_head,
  562. (qds_t*(*)(qds_t *, const char *))sh_l_insert_tail,
  563. (qds_t*(*)(qds_t *, const char *, const char *))sh_l_insert_before,
  564. (qds_t*(*)(qds_t *, const char *, const char *))sh_l_insert_after,
  565. (qds_t*(*)(qds_t *))sh_l_discard,
  566. (char *(*)(qds_t *))sh_l_as_string,
  567. (int(*)(qds_t *, const char *))sh_l_verify },
  568. { "sh_tailq",
  569. (qds_t*(*)(const char *))sh_t_init,
  570. (qds_t*(*)(qds_t *))sh_t_remove_head,
  571. (qds_t*(*)(qds_t *))sh_t_remove_tail,
  572. (qds_t*(*)(qds_t *, const char *))sh_t_remove_item,
  573. (qds_t*(*)(qds_t *, const char *))sh_t_insert_head,
  574. (qds_t*(*)(qds_t *, const char *))sh_t_insert_tail,
  575. (qds_t*(*)(qds_t *, const char *, const char *))sh_t_insert_before,
  576. (qds_t*(*)(qds_t *, const char *, const char *))sh_t_insert_after,
  577. (qds_t*(*)(qds_t *))sh_t_discard,
  578. (char *(*)(qds_t *))sh_t_as_string,
  579. (int(*)(qds_t *, const char *))sh_t_verify }
  580. };
  581. typedef enum {
  582. INSERT_BEFORE,
  583. INSERT_AFTER,
  584. INSERT_HEAD,
  585. INSERT_TAIL,
  586. REMOVE_HEAD,
  587. REMOVE_ITEM,
  588. REMOVE_TAIL,
  589. } OP;
  590. const char *op_names[] = {
  591. "INSERT_BEFORE",
  592. "INSERT_AFTER",
  593. "INSERT_HEAD",
  594. "INSERT_TAIL",
  595. "REMOVE_HEAD",
  596. "REMOVE_ITEM",
  597. "REMOVE_TAIL" };
  598. struct {
  599. char *init; /* initial state. */
  600. char *final; /* final state. */
  601. char *elem; /* element to operate on */
  602. char *insert; /* element to insert */
  603. OP op; /* operation. */
  604. } ops[] = {
  605. /* most operations on a empty list */
  606. { "", "", NULL, NULL, REMOVE_HEAD },
  607. { "", "", NULL, NULL, REMOVE_TAIL },
  608. { "", "A", NULL, "A", INSERT_HEAD },
  609. { "", "A", NULL, "A", INSERT_TAIL },
  610. /* all operations on a one element list */
  611. { "A", "", NULL, NULL, REMOVE_HEAD },
  612. { "A", "", NULL, NULL, REMOVE_TAIL },
  613. { "A", "", "A", NULL, REMOVE_ITEM },
  614. { "B", "A B", NULL, "A", INSERT_HEAD },
  615. { "A", "A B", NULL, "B", INSERT_TAIL },
  616. { "B", "A B", "B", "A", INSERT_BEFORE },
  617. { "A", "A B", "A", "B", INSERT_AFTER },
  618. /* all operations on a two element list */
  619. { "A B", "B", NULL, NULL, REMOVE_HEAD },
  620. { "A B", "A", NULL, NULL, REMOVE_TAIL },
  621. { "A B", "A", "B", NULL, REMOVE_ITEM },
  622. { "A B", "B", "A", NULL, REMOVE_ITEM },
  623. { "B C", "A B C", NULL, "A", INSERT_HEAD },
  624. { "A B", "A B C", NULL, "C", INSERT_TAIL },
  625. { "B C", "A B C", "B", "A", INSERT_BEFORE },
  626. { "A C", "A B C", "C", "B", INSERT_BEFORE },
  627. { "A C", "A B C", "A", "B", INSERT_AFTER },
  628. { "A C", "A C B", "C", "B", INSERT_AFTER },
  629. /* all operations on a three element list */
  630. { "A B C", "B C", NULL, NULL, REMOVE_HEAD },
  631. { "A B C", "A B", NULL, NULL, REMOVE_TAIL },
  632. { "A B C", "A B", "C", NULL, REMOVE_ITEM },
  633. { "A B C", "A C", "B", NULL, REMOVE_ITEM },
  634. { "A B C", "B C", "A", NULL, REMOVE_ITEM },
  635. { "B C D", "A B C D", NULL, "A", INSERT_HEAD },
  636. { "A B C", "A B C D", NULL, "D", INSERT_TAIL },
  637. { "A B C", "X A B C", "A", "X", INSERT_BEFORE },
  638. { "A B C", "A X B C", "B", "X", INSERT_BEFORE },
  639. { "A B C", "A B X C", "C", "X", INSERT_BEFORE },
  640. { "A B C", "A X B C", "A", "X", INSERT_AFTER },
  641. { "A B C", "A B X C", "B", "X", INSERT_AFTER },
  642. { "A B C", "A B C X", "C", "X", INSERT_AFTER },
  643. };
  644. int
  645. main(argc, argv)
  646. int argc;
  647. char *argv[];
  648. {
  649. void *list;
  650. int fc, tc; /* tc is total count, fc is failed count */
  651. int eval, i, t, result;
  652. eval = 0;
  653. for (t = 0; t < sizeof(qfns) / sizeof(qfns[0]); ++t) {
  654. fc = tc = 0;
  655. printf("TESTING: %s\n", qfns[t].name);
  656. for (i = 0; i < sizeof(ops) / sizeof(ops[0]); i++) {
  657. list = qfns[t].f_init(ops[i].init);
  658. result = qfns[t].f_verify(list, ops[i].init);
  659. if (result == 0) {
  660. fc++;
  661. putchar('.');
  662. } else {
  663. putchar('+'); /* + means failed before op */
  664. printf("\nVerify failed: %s\n",
  665. failure_reason_names[result]);
  666. eval = 1;
  667. }
  668. if (!strcmp("sh_tailq", qfns[t].name)) {
  669. result =
  670. sh_t_verify_TAILQ_LAST(list, ops[i].init);
  671. }
  672. #ifdef VERBOSE
  673. printf("\ncase %d %s in %s init: \"%s\" desired: \"%s\" elem: \"%s\" insert: \"%s\"\n",
  674. i, op_names[ops[i].op], qfns[t].name,
  675. ops[i].init, ops[i].final,
  676. ops[i].elem, ops[i].insert);
  677. fflush(stdout);
  678. #endif
  679. tc++;
  680. switch (ops[i].op) {
  681. case REMOVE_HEAD:
  682. qfns[t].f_remove_head(list);
  683. break;
  684. case REMOVE_TAIL:
  685. qfns[t].f_remove_tail(list);
  686. break;
  687. case REMOVE_ITEM:
  688. qfns[t].f_remove_item(list, ops[i].elem);
  689. break;
  690. case INSERT_HEAD:
  691. qfns[t].f_insert_head(list, ops[i].insert);
  692. break;
  693. case INSERT_TAIL:
  694. qfns[t].f_insert_tail(list, ops[i].insert);
  695. break;
  696. case INSERT_BEFORE:
  697. qfns[t].f_insert_before(
  698. list, ops[i].insert, ops[i].elem);
  699. break;
  700. case INSERT_AFTER:
  701. qfns[t].f_insert_after(
  702. list, ops[i].insert, ops[i].elem);
  703. break;
  704. }
  705. if (!strcmp("sh_tailq", op_names[ops[i].op])) {
  706. result = sh_t_verify_TAILQ_LAST(list,
  707. ops[i].final);
  708. }
  709. if (result == 0)
  710. result = qfns[t].f_verify(list, ops[i].final);
  711. if (result == 0) {
  712. fc++;
  713. putchar('.');
  714. } else {
  715. putchar('*'); /* * means failed after op */
  716. printf("\ncase %d %s in %s init: \"%s\" desired: \"%s\" elem: \"%s\" insert: \"%s\" got: %s - %s\n",
  717. i, op_names[ops[i].op], qfns[t].name,
  718. ops[i].init, ops[i].final,
  719. ops[i].elem, ops[i].insert,
  720. qfns[t].f_as_string(list),
  721. failure_reason_names[result]);
  722. fflush(stdout);
  723. eval = 1;
  724. }
  725. tc++;
  726. qfns[t].f_discard(list);
  727. }
  728. printf("\t%0.2f%% passed (%d/%d).\n",
  729. (((double)fc/tc) * 100), fc, tc);
  730. }
  731. return (eval);
  732. }