/branches/SN-NG4.3-autoconf/db4/test/scr023/q.c

https://gitlab.com/OpenSourceMirror/sourcenav · C · 840 lines · 706 code · 103 blank · 31 comment · 159 complexity · 52fbdb7de0ae2290162ea1a849ed8760 MD5 · raw file

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