21#include "parser_local_proto.h"
31static void vector_new(
struct vector *v,
size_t elsize,
size_t increment)
34 v->increment = increment;
40static 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);
60static struct vector rules = {.elsize =
sizeof(
struct rule), .increment = 50};
84 vector_append(&rules, &rule);
87static void make_rule(
int type,
void *first,
va_list ap)
92 vector_new(&opts,
sizeof(
void *), 10);
95 vector_append(&opts, &
opt);
101 vector_append(&opts, &
opt);
110static int is_flag(
const void *p)
116 if ((
const void *)
flag == p)
124 if ((
const void *)
opt == p)
131static int is_present(
const void *p)
136 return (
int)
flag->answer;
141 return opt->count > 0;
145static char *get_name(
const void *p)
157static int count_present(
const struct rule *rule,
int start)
162 for (i = start; i < rule->count; i++)
163 if (is_present(rule->opts[i]))
169static const char *describe_rule(
const struct rule *rule,
int start,
175 G_asprintf(&s,
"<%s>", get_name(rule->opts[start]));
177 for (i = start + 1; i < rule->count - 1; i++) {
179 char *
ss = get_name(rule->opts[i]);
187 if (rule->count - start > 1) {
189 char *
ss = get_name(rule->opts[i]);
201static void append_error(
const char *
msg)
225static void check_exclusive(
const struct rule *rule)
227 if (count_present(rule, 0) > 1) {
231 describe_rule(rule, 0, 0));
253static void check_required(
const struct rule *rule)
255 if (count_present(rule, 0) < 1) {
259 _(
"At least one of the following options is required: %s"),
260 describe_rule(rule, 0, 0));
289static void check_requires(
const struct rule *rule)
291 if (!is_present(rule->opts[0]))
293 if (count_present(rule, 1) < 1) {
298 get_name(rule->opts[0]), describe_rule(rule, 1, 1));
301 get_name(rule->opts[0]), describe_rule(rule, 1, 1));
329static void check_requires_all(
const struct rule *rule)
331 if (!is_present(rule->opts[0]))
333 if (count_present(rule, 1) < rule->count - 1) {
337 get_name(rule->opts[0]), describe_rule(rule, 1, 0));
360static void check_excludes(
const struct rule *rule)
362 if (!is_present(rule->opts[0]))
364 if (count_present(rule, 1) > 0) {
367 G_asprintf(&
err,
_(
"Option <%s> is mutually exclusive with all of %s"),
368 get_name(rule->opts[0]), describe_rule(rule, 1, 0));
391static void check_collective(
const struct rule *rule)
393 int count = count_present(rule, 0);
399 describe_rule(rule, 0, 0));
409 for (i = 0; i < rules.count; i++) {
410 const struct rule *rule = &((
const struct rule *)rules.data)[i];
412 switch (rule->type) {
414 check_exclusive(rule);
417 check_required(rule);
420 check_requires(rule);
423 check_requires_all(rule);
426 check_excludes(rule);
429 check_collective(rule);
444 for (i = 0; i < rules.count; i++) {
445 const struct rule *rule = &((
const struct rule *)rules.data)[i];
447 switch (rule->type) {
455 fprintf(
stderr,
"Requires: %s => %s", get_name(rule->opts[0]),
456 describe_rule(rule, 1, 1));
459 fprintf(
stderr,
"Requires: %s => %s", get_name(rule->opts[0]),
460 describe_rule(rule, 1, 0));
463 fprintf(
stderr,
"Excludes: %s => %s", get_name(rule->opts[0]),
464 describe_rule(rule, 1, 0));
467 fprintf(
stderr,
"Collective: %s", describe_rule(rule, 0, 0));
487 for (i = 0; i < rules.count; i++) {
488 const struct rule *rule = &((
const struct rule *)rules.data)[i];
500 for (i = 0; i < rules.count; i++) {
501 const struct rule *rule = &((
const struct rule *)rules.data)[i];
506 _(
"Internal error: the number of options is < 0"));
508 for (
j = 0;
j < (
unsigned int)rule->count;
j++) {
509 void *p = rule->opts[
j];
513 return (
const struct Option *)p;
520static const char *
const rule_types[] = {
"exclusive",
"required",
521 "requires",
"requires-all",
522 "excludes",
"collective"};
536 for (i = 0; i < rules.count; i++) {
537 const struct rule *rule = &((
const struct rule *)rules.data)[i];
542 fprintf(fp,
"\t\t<rule type=\"%s\">\n", rule_types[rule->type]);
543 for (
j = 0;
j < (
unsigned int)rule->count;
j++) {
544 void *p = rule->opts[
j];
549 fprintf(fp,
"\t\t\t<rule-flag key=\"%c\"/>\n",
flag->key);
554 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)