parser_dependencies.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /*!
  2. \file lib/gis/parser_dependencies.c
  3. \brief GIS Library - Argument parsing functions (dependencies between options)
  4. (C) 2014-2015 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. /*! \brief Set generic option rule
  48. Supported rule types:
  49. - RULE_EXCLUSIVE
  50. - RULE_REQUIRED
  51. - RULE_REQUIRES
  52. - RULE_REQUIRES_ALL
  53. - RULE_EXCLUDES
  54. - RULE_COLLECTIVE
  55. \param type rule type
  56. \param nopts number of options in the array
  57. \param opts array of options
  58. */
  59. void G_option_rule(int type, int nopts, void **opts)
  60. {
  61. struct rule rule;
  62. rule.type = type;
  63. rule.count = nopts;
  64. rule.opts = opts;
  65. vector_append(&rules, &rule);
  66. }
  67. static void make_rule(int type, void *first, va_list ap)
  68. {
  69. struct vector opts;
  70. void *opt;
  71. vector_new(&opts, sizeof(void *), 10);
  72. opt = first;
  73. vector_append(&opts, &opt);
  74. for (;;) {
  75. opt = va_arg(ap, void*);
  76. if (!opt)
  77. break;
  78. vector_append(&opts, &opt);
  79. }
  80. G_option_rule(type, opts.count, (void**) opts.data);
  81. }
  82. static int is_flag(const void *p)
  83. {
  84. if (st->n_flags) {
  85. const struct Flag *flag;
  86. for (flag = &st->first_flag; flag; flag = flag->next_flag)
  87. if ((const void *) flag == p)
  88. return 1;
  89. }
  90. if (st->n_opts) {
  91. const struct Option *opt;
  92. for (opt = &st->first_option; opt; opt = opt->next_opt)
  93. if ((const void *) opt == p)
  94. return 0;
  95. }
  96. G_fatal_error(_("Internal error: option or flag not found"));
  97. }
  98. static int is_present(const void *p)
  99. {
  100. if (is_flag(p)) {
  101. const struct Flag *flag = p;
  102. return (int) flag->answer;
  103. }
  104. else {
  105. const struct Option *opt = p;
  106. return opt->count > 0;
  107. }
  108. }
  109. static char *get_name(const void *p)
  110. {
  111. if (is_flag(p)) {
  112. char *s;
  113. G_asprintf(&s, "-%c", ((const struct Flag *) p)->key);
  114. return s;
  115. }
  116. else
  117. return G_store(((const struct Option *) p)->key);
  118. }
  119. static int count_present(const struct rule *rule, int start)
  120. {
  121. int i;
  122. int count = 0;
  123. for (i = start; i < rule->count; i++)
  124. if (is_present(rule->opts[i]))
  125. count++;
  126. return count;
  127. }
  128. static const char *describe_rule(const struct rule *rule, int start,
  129. int disjunction)
  130. {
  131. char *s = get_name(rule->opts[start]);
  132. int i;
  133. for (i = start + 1; i < rule->count - 1; i++) {
  134. char *s0 = s;
  135. char *ss = get_name(rule->opts[i]);
  136. s = NULL;
  137. G_asprintf(&s, "%s>, <%s", s0, ss);
  138. G_free(s0);
  139. G_free(ss);
  140. }
  141. if (rule->count - start > 1) {
  142. char *s0 = s;
  143. char *ss = get_name(rule->opts[i]);
  144. s = NULL;
  145. G_asprintf(&s, disjunction ? _("<%s> or <%s>") : _("<%s> and <%s>"), s0, ss);
  146. G_free(s0);
  147. G_free(ss);
  148. }
  149. return s;
  150. }
  151. static void append_error(const char *msg)
  152. {
  153. st->error = G_realloc(st->error, sizeof(char *) * (st->n_errors + 1));
  154. st->error[st->n_errors++] = G_store(msg);
  155. }
  156. /*! \brief Sets the options to be mutually exclusive.
  157. When running the module, at most one option from a set can be
  158. provided.
  159. \param first first given option
  160. */
  161. void G_option_exclusive(void *first, ...)
  162. {
  163. va_list ap;
  164. va_start(ap, first);
  165. make_rule(RULE_EXCLUSIVE, first, ap);
  166. va_end(ap);
  167. }
  168. static void check_exclusive(const struct rule *rule)
  169. {
  170. if (count_present(rule, 0) > 1) {
  171. char *err;
  172. G_asprintf(&err, _("Options %s are mutually exclusive"),
  173. describe_rule(rule, 0, 0));
  174. append_error(err);
  175. }
  176. }
  177. /*! \brief Sets the options to be required.
  178. At least one option from a set must be given.
  179. \param first first given option
  180. */
  181. void G_option_required(void *first, ...)
  182. {
  183. va_list ap;
  184. va_start(ap, first);
  185. make_rule(RULE_REQUIRED, first, ap);
  186. va_end(ap);
  187. }
  188. static void check_required(const struct rule *rule)
  189. {
  190. if (count_present(rule, 0) < 1) {
  191. char *err;
  192. G_asprintf(&err, _("At least one of the following options is required: %s"),
  193. describe_rule(rule, 0, 0));
  194. append_error(err);
  195. }
  196. }
  197. /*! \brief Define a list of options from which at least one option
  198. is required if first option is present.
  199. If the first option is present, at least one of the other
  200. options must also be present.
  201. If you want all options to be provided use G_option_requires_all()
  202. function.
  203. If you want more than one option to be present but not all,
  204. call this function multiple times.
  205. \param first first given option
  206. */
  207. void G_option_requires(void *first, ...)
  208. {
  209. va_list ap;
  210. va_start(ap, first);
  211. make_rule(RULE_REQUIRES, first, ap);
  212. va_end(ap);
  213. }
  214. static void check_requires(const struct rule *rule)
  215. {
  216. if (!is_present(rule->opts[0]))
  217. return;
  218. if (count_present(rule, 1) < 1) {
  219. char *err;
  220. if (rule->count > 2)
  221. G_asprintf(&err, _("Option <%s> requires at least one of %s"),
  222. get_name(rule->opts[0]), describe_rule(rule, 1, 1));
  223. else
  224. G_asprintf(&err, _("Option <%s> requires <%s>"),
  225. get_name(rule->opts[0]), describe_rule(rule, 1, 1));
  226. append_error(err);
  227. }
  228. }
  229. /*! \brief Define additionally required options for an option.
  230. If the first option is present, all the other options must also
  231. be present.
  232. If it is enough if only one option from a set is present,
  233. use G_option_requires() function.
  234. \see G_option_collective()
  235. \param first first given option
  236. */
  237. void G_option_requires_all(void *first, ...)
  238. {
  239. va_list ap;
  240. va_start(ap, first);
  241. make_rule(RULE_REQUIRES_ALL, first, ap);
  242. va_end(ap);
  243. }
  244. static void check_requires_all(const struct rule *rule)
  245. {
  246. if (!is_present(rule->opts[0]))
  247. return;
  248. if (count_present(rule, 1) < rule->count - 1) {
  249. char *err;
  250. G_asprintf(&err, _("Option %s requires all of %s"),
  251. get_name(rule->opts[0]), describe_rule(rule, 1, 0));
  252. append_error(err);
  253. }
  254. }
  255. /*! \brief Exclude selected options.
  256. If the first option is present, none of the other options may also (should?)
  257. be present.
  258. \param first first given option
  259. */
  260. void G_option_excludes(void *first, ...)
  261. {
  262. va_list ap;
  263. va_start(ap, first);
  264. make_rule(RULE_EXCLUDES, first, ap);
  265. va_end(ap);
  266. }
  267. static void check_excludes(const struct rule *rule)
  268. {
  269. if (!is_present(rule->opts[0]))
  270. return;
  271. if (count_present(rule, 1) > 0) {
  272. char *err;
  273. G_asprintf(&err, _("Option %s is mutually exclusive with all of %s"),
  274. get_name(rule->opts[0]), describe_rule(rule, 1, 0));
  275. append_error(err);
  276. }
  277. }
  278. /*! \brief Sets the options to be collective.
  279. If any option is present, all the other options must also be present
  280. all or nothing from a set.
  281. \param first first given option
  282. */
  283. void G_option_collective(void *first, ...)
  284. {
  285. va_list ap;
  286. va_start(ap, first);
  287. make_rule(RULE_COLLECTIVE, first, ap);
  288. va_end(ap);
  289. }
  290. static void check_collective(const struct rule *rule)
  291. {
  292. int count = count_present(rule, 0);
  293. if (count > 0 && count < rule->count) {
  294. char *err;
  295. G_asprintf(&err, _("Either all or none of %s must be given"),
  296. describe_rule(rule, 0, 0));
  297. append_error(err);
  298. }
  299. }
  300. /*! \brief Check for option rules (internal use only) */
  301. void G__check_option_rules(void)
  302. {
  303. unsigned int i;
  304. for (i = 0; i < rules.count; i++) {
  305. const struct rule *rule = &((const struct rule *) rules.data)[i];
  306. switch (rule->type) {
  307. case RULE_EXCLUSIVE:
  308. check_exclusive(rule);
  309. break;
  310. case RULE_REQUIRED:
  311. check_required(rule);
  312. break;
  313. case RULE_REQUIRES:
  314. check_requires(rule);
  315. break;
  316. case RULE_REQUIRES_ALL:
  317. check_requires_all(rule);
  318. break;
  319. case RULE_EXCLUDES:
  320. check_excludes(rule);
  321. break;
  322. case RULE_COLLECTIVE:
  323. check_collective(rule);
  324. break;
  325. default:
  326. G_fatal_error(_("Internal error: invalid rule type: %d"),
  327. rule->type);
  328. break;
  329. }
  330. }
  331. }
  332. /*! \brief Describe option rules (stderr) */
  333. void G__describe_option_rules(void)
  334. {
  335. unsigned int i;
  336. for (i = 0; i < rules.count; i++) {
  337. const struct rule *rule = &((const struct rule *) rules.data)[i];
  338. switch (rule->type) {
  339. case RULE_EXCLUSIVE:
  340. fprintf(stderr, "Exclusive: %s", describe_rule(rule, 0, 0));
  341. break;
  342. case RULE_REQUIRED:
  343. fprintf(stderr, "Required: %s", describe_rule(rule, 0, 1));
  344. break;
  345. case RULE_REQUIRES:
  346. fprintf(stderr, "Requires: %s => %s", get_name(rule->opts[0]),
  347. describe_rule(rule, 1, 1));
  348. break;
  349. case RULE_REQUIRES_ALL:
  350. fprintf(stderr, "Requires: %s => %s", get_name(rule->opts[0]),
  351. describe_rule(rule, 1, 0));
  352. break;
  353. case RULE_EXCLUDES:
  354. fprintf(stderr, "Excludes: %s => %s", get_name(rule->opts[0]),
  355. describe_rule(rule, 1, 0));
  356. break;
  357. case RULE_COLLECTIVE:
  358. fprintf(stderr, "Collective: %s", describe_rule(rule, 0, 0));
  359. break;
  360. default:
  361. G_fatal_error(_("Internal error: invalid rule type: %d"),
  362. rule->type);
  363. break;
  364. }
  365. }
  366. }
  367. /*!
  368. \brief Checks if there is any rule RULE_REQUIRED (internal use only).
  369. \return 1 if there is such rule
  370. \return 0 if not
  371. */
  372. int G__has_required_rule(void)
  373. {
  374. size_t i;
  375. for (i = 0; i < rules.count; i++) {
  376. const struct rule *rule = &((const struct rule *) rules.data)[i];
  377. if (rule->type == RULE_REQUIRED)
  378. return TRUE;
  379. }
  380. return FALSE;
  381. }
  382. static const char * const rule_types[] = {
  383. "exclusive",
  384. "required",
  385. "requires",
  386. "requires-all",
  387. "excludes",
  388. "collective"
  389. };
  390. /*! \brief Describe option rules in XML format (internal use only)
  391. \param fp file where to print XML info
  392. */
  393. void G__describe_option_rules_xml(FILE *fp)
  394. {
  395. unsigned int i, j;
  396. if (!rules.count)
  397. return;
  398. fprintf(fp, "\t<rules>\n");
  399. for (i = 0; i < rules.count; i++) {
  400. const struct rule *rule = &((const struct rule *) rules.data)[i];
  401. fprintf(fp, "\t\t<rule type=\"%s\">\n", rule_types[rule->type]);
  402. for (j = 0; j < rule->count; j++) {
  403. void *p = rule->opts[j];
  404. if (is_flag(p)) {
  405. const struct Flag *flag = (const struct Flag *) p;
  406. fprintf(fp, "\t\t\t<rule-flag key=\"%c\"/>\n", flag->key);
  407. }
  408. else {
  409. const struct Option *opt = (const struct Option *) p;
  410. fprintf(fp, "\t\t\t<rule-option key=\"%s\"/>\n", opt->key);
  411. }
  412. }
  413. fprintf(fp, "\t\t</rule>\n");
  414. }
  415. fprintf(fp, "\t</rules>\n");
  416. }