parser_dependencies.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. /*!
  2. \file lib/gis/parser_dependencies.c
  3. \brief GIS Library - Argument parsing functions (dependencies between options)
  4. (C) 2014 by the GRASS Development Team
  5. This program is free software under the GNU General Public License
  6. (>=v2). Read the file COPYING that comes with GRASS for details.
  7. \author Glynn Clements Jun. 2014
  8. */
  9. #include <stdarg.h>
  10. #include <string.h>
  11. #include <stdio.h>
  12. #include <grass/gis.h>
  13. #include <grass/glocale.h>
  14. #include "parser_local_proto.h"
  15. struct vector {
  16. size_t elsize;
  17. size_t increment;
  18. size_t count;
  19. size_t limit;
  20. void *data;
  21. };
  22. static void vector_new(struct vector *v, size_t elsize, size_t increment)
  23. {
  24. v->elsize = elsize;
  25. v->increment = increment;
  26. v->count = 0;
  27. v->limit = 0;
  28. v->data = NULL;
  29. }
  30. static void vector_append(struct vector *v, const void *data)
  31. {
  32. void *p;
  33. if (v->count >= v->limit) {
  34. v->limit += v->increment;
  35. v->data = G_realloc(v->data, v->limit * v->elsize);
  36. }
  37. p = G_incr_void_ptr(v->data, v->count * v->elsize);
  38. memcpy(p, data, v->elsize);
  39. v->count++;
  40. }
  41. struct rule {
  42. int type;
  43. int count;
  44. void **opts;
  45. };
  46. static struct vector rules = {sizeof(struct rule), 50};
  47. void G__option_rule(int type, int nopts, void **opts)
  48. {
  49. struct rule rule;
  50. rule.type = type;
  51. rule.count = nopts;
  52. rule.opts = opts;
  53. vector_append(&rules, &rule);
  54. }
  55. static void make_rule(int type, void *first, va_list ap)
  56. {
  57. struct vector opts;
  58. void *opt;
  59. vector_new(&opts, sizeof(void *), 10);
  60. opt = first;
  61. vector_append(&opts, &opt);
  62. for (;;) {
  63. opt = va_arg(ap, void*);
  64. if (!opt)
  65. break;
  66. vector_append(&opts, &opt);
  67. }
  68. G__option_rule(type, opts.count, (void**) opts.data);
  69. }
  70. static int is_flag(const void *p)
  71. {
  72. if (st->n_flags) {
  73. const struct Flag *flag;
  74. for (flag = &st->first_flag; flag; flag = flag->next_flag)
  75. if ((const void *) flag == p)
  76. return 1;
  77. }
  78. if (st->n_opts) {
  79. const struct Option *opt;
  80. for (opt = &st->first_option; opt; opt = opt->next_opt)
  81. if ((const void *) opt == p)
  82. return 0;
  83. }
  84. G_fatal_error(_("Internal error: option or flag not found"));
  85. }
  86. static int is_present(const void *p)
  87. {
  88. if (is_flag(p)) {
  89. const struct Flag *flag = p;
  90. return (int) flag->answer;
  91. }
  92. else {
  93. const struct Option *opt = p;
  94. return opt->count > 0;
  95. }
  96. }
  97. static char *get_name(const void *p)
  98. {
  99. if (is_flag(p)) {
  100. char *s;
  101. G_asprintf(&s, "-%c", ((const struct Flag *) p)->key);
  102. return s;
  103. }
  104. else
  105. return G_store(((const struct Option *) p)->key);
  106. }
  107. static int count_present(const struct rule *rule, int start)
  108. {
  109. int i;
  110. int count = 0;
  111. for (i = start; i < rule->count; i++)
  112. if (is_present(rule->opts[i]))
  113. count++;
  114. return count;
  115. }
  116. static const char *describe_rule(const struct rule *rule, int start,
  117. int disjunction)
  118. {
  119. char *s = get_name(rule->opts[start]);
  120. int i;
  121. for (i = start + 1; i < rule->count - 1; i++) {
  122. char *s0 = s;
  123. char *ss = get_name(rule->opts[i]);
  124. s = NULL;
  125. G_asprintf(&s, "%s, %s", s0, ss);
  126. G_free(s0);
  127. G_free(ss);
  128. }
  129. if (rule->count - start > 1) {
  130. char *s0 = s;
  131. char *ss = get_name(rule->opts[i]);
  132. s = NULL;
  133. G_asprintf(&s, disjunction ? _("%s or %s") : _("%s and %s"), s0, ss);
  134. G_free(s0);
  135. G_free(ss);
  136. }
  137. return s;
  138. }
  139. static void append_error(const char *msg)
  140. {
  141. st->error = G_realloc(st->error, sizeof(char *) * (st->n_errors + 1));
  142. st->error[st->n_errors++] = G_store(msg);
  143. }
  144. /* at most one option from a set */
  145. void G_option_exclusive(void *first, ...)
  146. {
  147. va_list ap;
  148. va_start(ap, first);
  149. make_rule(RULE_EXCLUSIVE, first, ap);
  150. va_end(ap);
  151. }
  152. static void check_exclusive(const struct rule *rule)
  153. {
  154. if (count_present(rule, 0) > 1) {
  155. char *err;
  156. G_asprintf(&err, _("Options %s are mutually exclusive"),
  157. describe_rule(rule, 0, 0));
  158. append_error(err);
  159. }
  160. }
  161. /* at least one option from a set */
  162. void G_option_required(void *first, ...)
  163. {
  164. va_list ap;
  165. va_start(ap, first);
  166. make_rule(RULE_REQUIRED, first, ap);
  167. va_end(ap);
  168. }
  169. static void check_required(const struct rule *rule)
  170. {
  171. if (count_present(rule, 0) < 1) {
  172. char *err;
  173. G_asprintf(&err, _("At least one of %s is required"),
  174. describe_rule(rule, 0, 0));
  175. append_error(err);
  176. }
  177. }
  178. /* if the first option is present, at least one of the other
  179. options must also be present */
  180. void G_option_requires(void *first, ...)
  181. {
  182. va_list ap;
  183. va_start(ap, first);
  184. make_rule(RULE_REQUIRES, first, ap);
  185. va_end(ap);
  186. }
  187. static void check_requires(const struct rule *rule)
  188. {
  189. if (!is_present(rule->opts[0]))
  190. return;
  191. if (count_present(rule, 1) < 1) {
  192. char *err;
  193. G_asprintf(&err, _("Option %s requires at least one of %s"),
  194. get_name(rule->opts[0]), describe_rule(rule, 1, 1));
  195. append_error(err);
  196. }
  197. }
  198. /* if the first option is present, all the other options must also
  199. be present. */
  200. void G_option_requires_all(void *first, ...)
  201. {
  202. va_list ap;
  203. va_start(ap, first);
  204. make_rule(RULE_REQUIRES_ALL, first, ap);
  205. va_end(ap);
  206. }
  207. static void check_requires_all(const struct rule *rule)
  208. {
  209. if (!is_present(rule->opts[0]))
  210. return;
  211. if (count_present(rule, 1) < rule->count - 1) {
  212. char *err;
  213. G_asprintf(&err, _("Option %s requires all of %s"),
  214. get_name(rule->opts[0]), describe_rule(rule, 1, 0));
  215. append_error(err);
  216. }
  217. }
  218. /* if the first option is present, none of the other options may also
  219. be present. */
  220. void G_option_excludes(void *first, ...)
  221. {
  222. va_list ap;
  223. va_start(ap, first);
  224. make_rule(RULE_EXCLUDES, first, ap);
  225. va_end(ap);
  226. }
  227. static void check_excludes(const struct rule *rule)
  228. {
  229. if (!is_present(rule->opts[0]))
  230. return;
  231. if (count_present(rule, 1) > 0) {
  232. char *err;
  233. G_asprintf(&err, _("Option %s is mutually exclusive with all of %s"),
  234. get_name(rule->opts[0]), describe_rule(rule, 1, 0));
  235. append_error(err);
  236. }
  237. }
  238. /* if any option is present, all the other options must also be present
  239. all or nothing from a set */
  240. void G_option_collective(void *first, ...)
  241. {
  242. va_list ap;
  243. va_start(ap, first);
  244. make_rule(RULE_COLLECTIVE, first, ap);
  245. va_end(ap);
  246. }
  247. static void check_collective(const struct rule *rule)
  248. {
  249. int count = count_present(rule, 0);
  250. if (count > 0 && count < rule->count) {
  251. char *err;
  252. G_asprintf(&err, _("Either all or none of %s must be given"),
  253. describe_rule(rule, 0, 0));
  254. append_error(err);
  255. }
  256. }
  257. void G__check_option_rules(void)
  258. {
  259. int i;
  260. for (i = 0; i < rules.count; i++) {
  261. const struct rule *rule = &((const struct rule *) rules.data)[i];
  262. switch (rule->type) {
  263. case RULE_EXCLUSIVE:
  264. check_exclusive(rule);
  265. break;
  266. case RULE_REQUIRED:
  267. check_required(rule);
  268. break;
  269. case RULE_REQUIRES:
  270. check_requires(rule);
  271. break;
  272. case RULE_REQUIRES_ALL:
  273. check_requires_all(rule);
  274. break;
  275. case RULE_EXCLUDES:
  276. check_excludes(rule);
  277. break;
  278. case RULE_COLLECTIVE:
  279. check_collective(rule);
  280. break;
  281. default:
  282. G_fatal_error(_("Internal error: invalid rule type: %d"),
  283. rule->type);
  284. break;
  285. }
  286. }
  287. }
  288. void G__describe_option_rules(void)
  289. {
  290. int i;
  291. for (i = 0; i < rules.count; i++) {
  292. const struct rule *rule = &((const struct rule *) rules.data)[i];
  293. switch (rule->type) {
  294. case RULE_EXCLUSIVE:
  295. fprintf(stderr, "Exclusive: %s", describe_rule(rule, 0, 0));
  296. break;
  297. case RULE_REQUIRED:
  298. fprintf(stderr, "Required: %s", describe_rule(rule, 0, 1));
  299. break;
  300. case RULE_REQUIRES:
  301. fprintf(stderr, "Requires: %s => %s", get_name(rule->opts[0]),
  302. describe_rule(rule, 1, 1));
  303. break;
  304. case RULE_REQUIRES_ALL:
  305. fprintf(stderr, "Requires: %s => %s", get_name(rule->opts[0]),
  306. describe_rule(rule, 1, 0));
  307. break;
  308. case RULE_EXCLUDES:
  309. fprintf(stderr, "Excludes: %s => %s", get_name(rule->opts[0]),
  310. describe_rule(rule, 1, 0));
  311. break;
  312. case RULE_COLLECTIVE:
  313. fprintf(stderr, "Collective: %s", describe_rule(rule, 0, 0));
  314. break;
  315. default:
  316. G_fatal_error(_("Internal error: invalid rule type: %d"),
  317. rule->type);
  318. break;
  319. }
  320. }
  321. }
  322. /*!
  323. \brief Checks if there is any rule RULE_REQUIRED.
  324. \return 1 if there is such rule
  325. \return 0 if not
  326. */
  327. int G__has_required_rule(void)
  328. {
  329. size_t i;
  330. for (i = 0; i < rules.count; i++) {
  331. const struct rule *rule = &((const struct rule *) rules.data)[i];
  332. if (rule->type == RULE_REQUIRED)
  333. return TRUE;
  334. }
  335. return FALSE;
  336. }