20#include "parser_local_proto.h"
30static void vector_new(
struct vector *v,
size_t elsize,
size_t increment)
33 v->increment = increment;
39static void vector_append(
struct vector *v,
const void *data)
43 if (v->count >= v->limit) {
44 v->limit += v->increment;
45 v->data =
G_realloc(v->data, v->limit * v->elsize);
49 memcpy(p, data, v->elsize);
59static struct vector rules = {.elsize =
sizeof(
struct rule), .increment = 50};
83 vector_append(&rules, &rule);
86static void make_rule(
int type,
void *first,
va_list ap)
91 vector_new(&opts,
sizeof(
void *), 10);
94 vector_append(&opts, &
opt);
100 vector_append(&opts, &
opt);
106static int is_flag(
const void *p)
112 if ((
const void *)
flag == p)
120 if ((
const void *)
opt == p)
127static int is_present(
const void *p)
132 return (
int)
flag->answer;
137 return opt->count > 0;
141static char *get_name(
const void *p)
153static int count_present(
const struct rule *rule,
int start)
158 for (i = start; i < rule->count; i++)
159 if (is_present(rule->opts[i]))
165static const char *describe_rule(
const struct rule *rule,
int start,
171 G_asprintf(&s,
"<%s>", get_name(rule->opts[start]));
173 for (i = start + 1; i < rule->count - 1; i++) {
175 char *
ss = get_name(rule->opts[i]);
183 if (rule->count - start > 1) {
185 char *
ss = get_name(rule->opts[i]);
197static void append_error(
const char *
msg)
221static void check_exclusive(
const struct rule *rule)
223 if (count_present(rule, 0) > 1) {
227 describe_rule(rule, 0, 0));
249static void check_required(
const struct rule *rule)
251 if (count_present(rule, 0) < 1) {
255 _(
"At least one of the following options is required: %s"),
256 describe_rule(rule, 0, 0));
285static void check_requires(
const struct rule *rule)
287 if (!is_present(rule->opts[0]))
289 if (count_present(rule, 1) < 1) {
294 get_name(rule->opts[0]), describe_rule(rule, 1, 1));
297 get_name(rule->opts[0]), describe_rule(rule, 1, 1));
325static void check_requires_all(
const struct rule *rule)
327 if (!is_present(rule->opts[0]))
329 if (count_present(rule, 1) < rule->count - 1) {
333 get_name(rule->opts[0]), describe_rule(rule, 1, 0));
356static void check_excludes(
const struct rule *rule)
358 if (!is_present(rule->opts[0]))
360 if (count_present(rule, 1) > 0) {
363 G_asprintf(&
err,
_(
"Option <%s> is mutually exclusive with all of %s"),
364 get_name(rule->opts[0]), describe_rule(rule, 1, 0));
387static void check_collective(
const struct rule *rule)
389 int count = count_present(rule, 0);
395 describe_rule(rule, 0, 0));
405 for (i = 0; i < rules.count; i++) {
406 const struct rule *rule = &((
const struct rule *)rules.data)[i];
408 switch (rule->type) {
410 check_exclusive(rule);
413 check_required(rule);
416 check_requires(rule);
419 check_requires_all(rule);
422 check_excludes(rule);
425 check_collective(rule);
440 for (i = 0; i < rules.count; i++) {
441 const struct rule *rule = &((
const struct rule *)rules.data)[i];
443 switch (rule->type) {
451 fprintf(
stderr,
"Requires: %s => %s", get_name(rule->opts[0]),
452 describe_rule(rule, 1, 1));
455 fprintf(
stderr,
"Requires: %s => %s", get_name(rule->opts[0]),
456 describe_rule(rule, 1, 0));
459 fprintf(
stderr,
"Excludes: %s => %s", get_name(rule->opts[0]),
460 describe_rule(rule, 1, 0));
463 fprintf(
stderr,
"Collective: %s", describe_rule(rule, 0, 0));
483 for (i = 0; i < rules.count; i++) {
484 const struct rule *rule = &((
const struct rule *)rules.data)[i];
496 for (i = 0; i < rules.count; i++) {
497 const struct rule *rule = &((
const struct rule *)rules.data)[i];
502 _(
"Internal error: the number of options is < 0"));
504 for (
j = 0;
j < (
unsigned int)rule->count;
j++) {
505 void *p = rule->opts[
j];
509 return (
const struct Option *)p;
516static const char *
const rule_types[] = {
"exclusive",
"required",
517 "requires",
"requires-all",
518 "excludes",
"collective"};
532 for (i = 0; i < rules.count; i++) {
533 const struct rule *rule = &((
const struct rule *)rules.data)[i];
538 fprintf(fp,
"\t\t<rule type=\"%s\">\n", rule_types[rule->type]);
539 for (
j = 0;
j < (
unsigned int)rule->count;
j++) {
540 void *p = rule->opts[
j];
545 fprintf(fp,
"\t\t\t<rule-flag key=\"%c\"/>\n",
flag->key);
550 fprintf(fp,
"\t\t\t<rule-option key=\"%s\"/>\n",
opt->key);
void G_free(void *)
Free allocated memory.
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
int G_asprintf(char **, const char *,...) __attribute__((format(printf
#define G_incr_void_ptr(ptr, size)
char * G_store(const char *)
Copy string to allocated memory.
void G__check_option_rules(void)
Check for option rules (internal use only)
void G_option_rule(int type, int nopts, void **opts)
Set generic option rule.
void G_option_collective(void *first,...)
Sets the options to be collective.
int G__has_required_rule(void)
Checks if there is any rule RULE_REQUIRED (internal use only).
void G__describe_option_rules(void)
Describe option rules (stderr)
void G_option_requires_all(void *first,...)
Define additionally required options for an option.
void G_option_excludes(void *first,...)
Exclude selected options.
void G_option_exclusive(void *first,...)
Sets the options to be mutually exclusive.
void G__describe_option_rules_xml(FILE *fp)
Describe option rules in XML format (internal use only)
const struct Option * G__first_required_option_from_rules(void)
void G_option_required(void *first,...)
Sets the options to be required.
void G_option_requires(void *first,...)
Define a list of options from which at least one option is required if first option is present.
Structure that stores flag info.
Structure that stores option information.
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)