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.

266 lines
6.3KB

  1. /*
  2. Stack filter
  3. Copyright (C) 2002 Robert Lipe, robertlipe+source@gpsbabel.org
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
  15. */
  16. #include "defs.h"
  17. #include "filterdefs.h"
  18. #include <stdlib.h>
  19. #if FILTERS_ENABLED
  20. #define MYNAME "Stack filter"
  21. static char* opt_push = NULL;
  22. static char* opt_copy = NULL;
  23. static char* opt_pop = NULL;
  24. static char* opt_append = NULL;
  25. static char* opt_discard = NULL;
  26. static char* opt_replace = NULL;
  27. static char* opt_swap = NULL;
  28. static char* opt_depth = NULL;
  29. static char* nowarn = NULL;
  30. static int warnings_enabled = 1;
  31. static int swapdepth = 0;
  32. static
  33. arglist_t stackfilt_args[] = {
  34. {
  35. "push", &opt_push, "Push waypoint list onto stack", NULL,
  36. ARGTYPE_BEGIN_EXCL | ARGTYPE_BEGIN_REQ | ARGTYPE_BOOL, ARG_NOMINMAX
  37. },
  38. {
  39. "pop", &opt_pop, "Pop waypoint list from stack", NULL,
  40. ARGTYPE_BOOL, ARG_NOMINMAX
  41. },
  42. {
  43. "swap", &opt_swap, "Swap waypoint list with <depth> item on stack",
  44. NULL, ARGTYPE_END_EXCL | ARGTYPE_END_REQ | ARGTYPE_BOOL, ARG_NOMINMAX
  45. },
  46. {
  47. "copy", &opt_copy, "(push) Copy waypoint list", NULL,
  48. ARGTYPE_BOOL, ARG_NOMINMAX
  49. },
  50. {
  51. "append", &opt_append, "(pop) Append list", NULL,
  52. ARGTYPE_BEGIN_EXCL | ARGTYPE_BOOL, ARG_NOMINMAX
  53. },
  54. {
  55. "discard", &opt_discard, "(pop) Discard top of stack",
  56. NULL, ARGTYPE_BOOL, ARG_NOMINMAX
  57. },
  58. {
  59. "replace", &opt_replace, "(pop) Replace list (default)",
  60. NULL, ARGTYPE_END_EXCL | ARGTYPE_BOOL, ARG_NOMINMAX
  61. },
  62. {
  63. "depth", &opt_depth, "(swap) Item to use (default=1)",
  64. NULL, ARGTYPE_INT, "0", NULL
  65. },
  66. {
  67. "nowarn", &nowarn, "Suppress cleanup warning", NULL,
  68. ARGTYPE_BOOL | ARGTYPE_HIDDEN, ARG_NOMINMAX
  69. },
  70. ARG_TERMINATOR
  71. };
  72. struct stack_elt {
  73. queue waypts;
  74. queue routes;
  75. queue tracks;
  76. unsigned int waypt_ct;
  77. int route_count;
  78. int track_count;
  79. struct stack_elt* next;
  80. }* stack = NULL;
  81. void
  82. stackfilt_process(void)
  83. {
  84. struct stack_elt* tmp_elt = NULL;
  85. queue* elem = NULL;
  86. queue* tmp = NULL;
  87. queue tmp_queue;
  88. unsigned int tmp_count;
  89. if (opt_push) {
  90. tmp_elt = (struct stack_elt*)xmalloc(sizeof(struct stack_elt));
  91. QUEUE_MOVE(&(tmp_elt->waypts), &waypt_head);
  92. tmp_elt->waypt_ct = waypt_count();
  93. set_waypt_count(0);
  94. tmp_elt->next = stack;
  95. stack = tmp_elt;
  96. if (opt_copy) {
  97. QUEUE_FOR_EACH(&(stack->waypts), elem, tmp) {
  98. waypt_add(new Waypoint(*(Waypoint*)elem));
  99. }
  100. }
  101. tmp = NULL;
  102. route_backup(&(tmp_elt->route_count), &tmp);
  103. QUEUE_MOVE(&(tmp_elt->routes), tmp);
  104. xfree(tmp);
  105. if (!opt_copy) {
  106. route_flush_all_routes();
  107. }
  108. tmp = NULL;
  109. track_backup(&(tmp_elt->track_count), &tmp);
  110. QUEUE_MOVE(&(tmp_elt->tracks), tmp);
  111. xfree(tmp);
  112. if (!opt_copy) {
  113. route_flush_all_tracks();
  114. }
  115. } else if (opt_pop) {
  116. tmp_elt = stack;
  117. if (!tmp_elt) {
  118. fatal(MYNAME ": stack empty\n");
  119. }
  120. if (opt_append) {
  121. QUEUE_FOR_EACH(&(stack->waypts), elem, tmp) {
  122. waypt_add((Waypoint*)elem);
  123. }
  124. route_append(&(stack->routes));
  125. route_flush(&(stack->routes));
  126. track_append(&(stack->tracks));
  127. route_flush(&(stack->tracks));
  128. } else if (opt_discard) {
  129. waypt_flush(&(stack->waypts));
  130. route_flush(&(stack->routes));
  131. route_flush(&(stack->tracks));
  132. } else {
  133. waypt_flush(&waypt_head);
  134. QUEUE_MOVE(&(waypt_head), &(stack->waypts));
  135. set_waypt_count(stack->waypt_ct);
  136. route_restore(&(stack->routes));
  137. track_restore(&(stack->tracks));
  138. }
  139. stack = tmp_elt->next;
  140. xfree(tmp_elt);
  141. } else if (opt_swap) {
  142. tmp_elt = stack;
  143. while (swapdepth > 1) {
  144. if (!tmp_elt->next) {
  145. fatal(MYNAME ": swap with nonexistent element\n");
  146. }
  147. tmp_elt = tmp_elt->next;
  148. swapdepth--;
  149. }
  150. QUEUE_MOVE(&tmp_queue, &(tmp_elt->waypts));
  151. QUEUE_MOVE(&(tmp_elt->waypts), &waypt_head);
  152. QUEUE_MOVE(&waypt_head, &tmp_queue);
  153. QUEUE_MOVE(&tmp_queue, &(tmp_elt->routes));
  154. tmp = NULL;
  155. route_backup(&(tmp_elt->route_count), &tmp);
  156. QUEUE_MOVE(&(tmp_elt->routes), tmp);
  157. xfree(tmp);
  158. route_restore(&tmp_queue);
  159. QUEUE_MOVE(&tmp_queue, &(tmp_elt->tracks));
  160. tmp = NULL;
  161. track_backup(&(tmp_elt->track_count), &tmp);
  162. QUEUE_MOVE(&(tmp_elt->tracks), tmp);
  163. xfree(tmp);
  164. track_restore(&tmp_queue);
  165. tmp_count = waypt_count();
  166. set_waypt_count(tmp_elt->waypt_ct);
  167. tmp_elt->waypt_ct = tmp_count;
  168. }
  169. }
  170. void
  171. stackfilt_init(const char* args)
  172. {
  173. int invalid = 0;
  174. if (nowarn) {
  175. warnings_enabled = 0;
  176. }
  177. if (opt_depth) {
  178. swapdepth = atoi(opt_depth);
  179. }
  180. if (opt_push) {
  181. if (opt_pop || opt_append || opt_discard || opt_replace ||
  182. opt_swap || opt_depth) {
  183. invalid = 1;
  184. }
  185. } else if (opt_pop) {
  186. if (opt_push || opt_copy || opt_swap || opt_depth) {
  187. invalid = 1;
  188. }
  189. if (!!opt_append + !!opt_discard + !!opt_replace > 1) {
  190. invalid = 1;
  191. }
  192. } else if (opt_swap) {
  193. if (opt_push || opt_copy || opt_pop || opt_append ||
  194. opt_discard || opt_replace) {
  195. invalid = 1;
  196. }
  197. } else {
  198. invalid = 1;
  199. }
  200. if (invalid) {
  201. fatal(MYNAME ": invalid combination of options\n");
  202. }
  203. }
  204. void
  205. stackfilt_deinit(void)
  206. {
  207. swapdepth = 0;
  208. }
  209. void
  210. stackfilt_exit(void)
  211. {
  212. struct stack_elt* tmp_elt = NULL;
  213. if (warnings_enabled && stack) {
  214. warning(MYNAME " Warning: leftover stack entries; "
  215. "check command line for mistakes\n");
  216. }
  217. while (stack) {
  218. waypt_flush(&(stack->waypts));
  219. tmp_elt = stack;
  220. stack = stack->next;
  221. xfree(tmp_elt);
  222. }
  223. }
  224. filter_vecs_t stackfilt_vecs = {
  225. stackfilt_init,
  226. stackfilt_process,
  227. stackfilt_deinit,
  228. stackfilt_exit,
  229. stackfilt_args
  230. };
  231. #endif // FILTERS_ENABLED