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)
117 for (opt = &
st->first_option; opt; opt = opt->
next_opt)
118 if ((
const void *) opt == p)
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)
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,
166 G_asprintf(&s,
"<%s>", get_name(rule->opts[start]));
168 for (i = start + 1; i < rule->count - 1; i++) {
170 char *ss = get_name(rule->opts[i]);
177 if (rule->count - start > 1) {
179 char *ss = get_name(rule->opts[i]);
181 G_asprintf(&s, disjunction ?
_(
"%s or <%s>") :
_(
"%s and <%s>"), s0, ss);
189 static void append_error(
const char *msg)
210 static void check_exclusive(
const struct rule *rule)
212 if (count_present(rule, 0) > 1) {
214 G_asprintf(&err,
_(
"Options %s are mutually exclusive"),
215 describe_rule(rule, 0, 0));
234 static void check_required(
const struct rule *rule)
236 if (count_present(rule, 0) < 1) {
238 G_asprintf(&err,
_(
"At least one of the following options is required: %s"),
239 describe_rule(rule, 0, 0));
265 static void check_requires(
const struct rule *rule)
267 if (!is_present(rule->opts[0]))
269 if (count_present(rule, 1) < 1) {
272 G_asprintf(&err,
_(
"Option <%s> requires at least one of %s"),
273 get_name(rule->opts[0]), describe_rule(rule, 1, 1));
276 get_name(rule->opts[0]), describe_rule(rule, 1, 1));
301 static void check_requires_all(
const struct rule *rule)
303 if (!is_present(rule->opts[0]))
305 if (count_present(rule, 1) < rule->count - 1) {
307 G_asprintf(&err,
_(
"Option <%s> requires all of %s"),
308 get_name(rule->opts[0]), describe_rule(rule, 1, 0));
328 static void check_excludes(
const struct rule *rule)
330 if (!is_present(rule->opts[0]))
332 if (count_present(rule, 1) > 0) {
334 G_asprintf(&err,
_(
"Option <%s> is mutually exclusive with all of %s"),
335 get_name(rule->opts[0]), describe_rule(rule, 1, 0));
355 static void check_collective(
const struct rule *rule)
357 int count = count_present(rule, 0);
358 if (count > 0 && count < rule->count) {
360 G_asprintf(&err,
_(
"Either all or none of %s must be given"),
361 describe_rule(rule, 0, 0));
371 for (i = 0; i < rules.count; i++) {
372 const struct rule *rule = &((
const struct rule *) rules.data)[i];
373 switch (rule->type) {
375 check_exclusive(rule);
378 check_required(rule);
381 check_requires(rule);
384 check_requires_all(rule);
387 check_excludes(rule);
390 check_collective(rule);
405 for (i = 0; i < rules.count; i++) {
406 const struct rule *rule = &((
const struct rule *) rules.data)[i];
407 switch (rule->type) {
409 fprintf(stderr,
"Exclusive: %s", describe_rule(rule, 0, 0));
412 fprintf(stderr,
"Required: %s", describe_rule(rule, 0, 1));
415 fprintf(stderr,
"Requires: %s => %s", get_name(rule->opts[0]),
416 describe_rule(rule, 1, 1));
419 fprintf(stderr,
"Requires: %s => %s", get_name(rule->opts[0]),
420 describe_rule(rule, 1, 0));
423 fprintf(stderr,
"Excludes: %s => %s", get_name(rule->opts[0]),
424 describe_rule(rule, 1, 0));
427 fprintf(stderr,
"Collective: %s", describe_rule(rule, 0, 0));
447 for (i = 0; i < rules.count; i++) {
448 const struct rule *rule = &((
const struct rule *) rules.data)[i];
455 static const char *
const rule_types[] = {
475 fprintf(fp,
"\t<rules>\n");
476 for (i = 0; i < rules.count; i++) {
477 const struct rule *rule = &((
const struct rule *) rules.data)[i];
478 fprintf(fp,
"\t\t<rule type=\"%s\">\n", rule_types[rule->type]);
479 for (j = 0; j < rule->count; j++) {
480 void *p = rule->opts[j];
482 const struct Flag *flag = (
const struct Flag *) p;
483 fprintf(fp,
"\t\t\t<rule-flag key=\"%c\"/>\n", flag->
key);
487 fprintf(fp,
"\t\t\t<rule-option key=\"%s\"/>\n", opt->
key);
490 fprintf(fp,
"\t\t</rule>\n");
492 fprintf(fp,
"\t</rules>\n");
int G__has_required_rule(void)
Checks if there is any rule RULE_REQUIRED (internal use only).
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_option_required(void *first,...)
Sets the options to be required.
void G_free(void *)
Free allocated memory.
void G__check_option_rules(void)
Check for option rules (internal use only)
#define G_incr_void_ptr(ptr, size)
void G_option_excludes(void *first,...)
Exclude selected options.
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)
void G_option_rule(int type, int nopts, void **opts)
Set generic option rule.
Structure that stores flag info.
void G_option_requires(void *first,...)
Define a list of options from which at least one option is required if first option is present...
void G_option_exclusive(void *first,...)
Sets the options to be mutually exclusive.
void G__describe_option_rules(void)
Describe option rules (stderr)
void G__describe_option_rules_xml(FILE *fp)
Describe option rules in XML format (internal use only)
void G_option_requires_all(void *first,...)
Define additionally required options for an option.
Structure that stores option information.
char * G_store(const char *)
Copy string to allocated memory.
void G_option_collective(void *first,...)
Sets the options to be collective.
int G_asprintf(char **, const char *,...) __attribute__((format(printf