18 #include <grass/gis.h>
19 #include <grass/glocale.h>
21 #include "parser_local_proto.h"
31 static void vector_new(
struct vector *v,
size_t elsize,
size_t increment)
34 v->increment = increment;
40 static void vector_append(
struct vector *v,
const void *data)
44 if (v->count >= v->limit) {
45 v->limit += v->increment;
46 v->data = G_realloc(v->data, v->limit * v->elsize);
50 memcpy(p, data, v->elsize);
60 static struct vector rules = {
sizeof(
struct rule), 50};
84 vector_append(&rules, &rule);
87 static void make_rule(
int type,
void *first, va_list ap)
92 vector_new(&opts,
sizeof(
void *), 10);
95 vector_append(&opts, &opt);
97 opt = va_arg(ap,
void*);
100 vector_append(&opts, &opt);
106 static int is_flag(
const void *p)
109 const struct Flag *flag;
110 for (flag = &
st->first_flag; flag; flag = flag->next_flag)
111 if ((
const void *) flag == p)
116 const struct Option *opt;
117 for (opt = &
st->first_option; opt; opt = opt->next_opt)
118 if ((
const void *) opt == p)
122 G_fatal_error(_(
"Internal error: option or flag not found"));
125 static int is_present(
const void *p)
128 const struct Flag *flag = p;
129 return (
int) flag->answer;
132 const struct Option *opt = p;
133 return opt->count > 0;
137 static char *get_name(
const void *p)
141 G_asprintf(&s,
"-%c", ((
const struct Flag *) p)->key);
145 return G_store(((
const struct Option *) p)->key);
148 static int count_present(
const struct rule *rule,
int start)
153 for (i = start; i < rule->count; i++)
154 if (is_present(rule->opts[i]))
160 static const char *describe_rule(
const struct rule *rule,
int start,
163 char *s = get_name(rule->opts[start]);
166 for (i = start + 1; i < rule->count - 1; i++) {
168 char *ss = get_name(rule->opts[i]);
175 if (rule->count - start > 1) {
177 char *ss = get_name(rule->opts[i]);
179 G_asprintf(&s, disjunction ? _(
"<%s> or <%s>") : _(
"<%s> and <%s>"), s0, ss);
187 static void append_error(
const char *msg)
189 st->error = G_realloc(
st->error,
sizeof(
char *) * (
st->n_errors + 1));
204 make_rule(RULE_EXCLUSIVE, first, ap);
208 static void check_exclusive(
const struct rule *rule)
210 if (count_present(rule, 0) > 1) {
213 describe_rule(rule, 0, 0));
228 make_rule(RULE_REQUIRED, first, ap);
232 static void check_required(
const struct rule *rule)
234 if (count_present(rule, 0) < 1) {
236 G_asprintf(&
err, _(
"At least one of the following options is required: %s"),
237 describe_rule(rule, 0, 0));
259 make_rule(RULE_REQUIRES, first, ap);
263 static void check_requires(
const struct rule *rule)
265 if (!is_present(rule->opts[0]))
267 if (count_present(rule, 1) < 1) {
270 G_asprintf(&
err, _(
"Option <%s> requires at least one of %s"),
271 get_name(rule->opts[0]), describe_rule(rule, 1, 1));
274 get_name(rule->opts[0]), describe_rule(rule, 1, 1));
295 make_rule(RULE_REQUIRES_ALL, first, ap);
299 static void check_requires_all(
const struct rule *rule)
301 if (!is_present(rule->opts[0]))
303 if (count_present(rule, 1) < rule->count - 1) {
306 get_name(rule->opts[0]), describe_rule(rule, 1, 0));
322 make_rule(RULE_EXCLUDES, first, ap);
326 static void check_excludes(
const struct rule *rule)
328 if (!is_present(rule->opts[0]))
330 if (count_present(rule, 1) > 0) {
332 G_asprintf(&
err, _(
"Option <%s> is mutually exclusive with all of %s"),
333 get_name(rule->opts[0]), describe_rule(rule, 1, 0));
349 make_rule(RULE_COLLECTIVE, first, ap);
353 static void check_collective(
const struct rule *rule)
355 int count = count_present(rule, 0);
358 G_asprintf(&
err, _(
"Either all or none of %s must be given"),
359 describe_rule(rule, 0, 0));
369 for (i = 0; i < rules.count; i++) {
370 const struct rule *rule = &((
const struct rule *) rules.data)[i];
371 switch (rule->type) {
373 check_exclusive(rule);
376 check_required(rule);
379 check_requires(rule);
381 case RULE_REQUIRES_ALL:
382 check_requires_all(rule);
385 check_excludes(rule);
387 case RULE_COLLECTIVE:
388 check_collective(rule);
403 for (i = 0; i < rules.count; i++) {
404 const struct rule *rule = &((
const struct rule *) rules.data)[i];
405 switch (rule->type) {
407 fprintf(stderr,
"Exclusive: %s", describe_rule(rule, 0, 0));
410 fprintf(stderr,
"Required: %s", describe_rule(rule, 0, 1));
413 fprintf(stderr,
"Requires: %s => %s", get_name(rule->opts[0]),
414 describe_rule(rule, 1, 1));
416 case RULE_REQUIRES_ALL:
417 fprintf(stderr,
"Requires: %s => %s", get_name(rule->opts[0]),
418 describe_rule(rule, 1, 0));
421 fprintf(stderr,
"Excludes: %s => %s", get_name(rule->opts[0]),
422 describe_rule(rule, 1, 0));
424 case RULE_COLLECTIVE:
425 fprintf(stderr,
"Collective: %s", describe_rule(rule, 0, 0));
445 for (i = 0; i < rules.count; i++) {
446 const struct rule *rule = &((
const struct rule *) rules.data)[i];
447 if (rule->type == RULE_REQUIRED)
453 static const char *
const rule_types[] = {
473 fprintf(fp,
"\t<rules>\n");
474 for (i = 0; i < rules.count; i++) {
475 const struct rule *rule = &((
const struct rule *) rules.data)[i];
476 fprintf(fp,
"\t\t<rule type=\"%s\">\n", rule_types[rule->type]);
477 for (j = 0; j < rule->count; j++) {
478 void *p = rule->opts[j];
480 const struct Flag *flag = (
const struct Flag *) p;
481 fprintf(fp,
"\t\t\t<rule-flag key=\"%c\"/>\n", flag->key);
484 const struct Option *opt = (
const struct Option *) p;
485 fprintf(fp,
"\t\t\t<rule-option key=\"%s\"/>\n", opt->key);
488 fprintf(fp,
"\t\t</rule>\n");
490 fprintf(fp,
"\t</rules>\n");