89 #include "parser_local_proto.h"
100 #define MAX_MATCHES 50
107 static void set_flag(
int);
108 static int contains(
const char *,
int);
109 static int valid_option_name(
const char *);
110 static int is_option(
const char *);
111 static int match_option_1(
const char *,
const char *);
112 static int match_option(
const char *,
const char *);
113 static void set_option(
const char *);
114 static void check_opts(
void);
115 static void check_an_opt(
const char *,
int,
const char *,
const char **,
117 static int check_int(
const char *,
const char **);
118 static int check_double(
const char *,
const char **);
119 static int check_string(
const char *,
const char **,
int *);
120 static void check_required(
void);
121 static void split_opts(
void);
122 static void check_multiple_opts(
void);
123 static int check_overwrite(
void);
124 static void define_keywords(
void);
125 static int module_gui_wx(
void);
126 static void append_error(
const char *);
127 static const char *get_renamed_option(
const char *);
142 st->no_interactive = 1;
166 st->current_flag->next_flag = flag;
169 flag = &
st->first_flag;
175 st->current_flag = flag;
179 item =
G_malloc(
sizeof(
struct Item));
180 st->current_item->next_item = item;
183 item = &
st->first_item;
185 G_zero(item,
sizeof(
struct Item));
190 st->current_item = item;
220 st->current_option->next_opt = opt;
223 opt = &
st->first_option;
231 st->current_option = opt;
235 item =
G_malloc(
sizeof(
struct Item));
236 st->current_item->next_item = item;
239 item = &
st->first_item;
241 G_zero(item,
sizeof(
struct Item));
245 st->current_item = item;
261 module = &
st->module_info;
325 const char *gui_envvar;
326 char *ptr, *tmp_name, *
err;
329 char force_gui =
FALSE;
335 st->pgm_path = tmp_name;
339 i = strlen(tmp_name);
347 st->pgm_name = tmp_name;
349 if (!
st->module_info.label && !
st->module_info.description)
350 G_warning(
_(
"Bug in UI description. Missing module description"));
354 opt = &
st->first_option;
355 while (
st->n_opts && opt) {
357 st->has_required = 1;
360 G_warning(
_(
"Bug in UI description. Missing option key"));
361 if (!valid_option_name(opt->
key))
362 G_warning(
_(
"Bug in UI description. Option key <%s> is not valid"),
366 _(
"Bug in UI description. Description for option <%s> missing"),
367 opt->
key ? opt->
key :
"?");
372 char **tokens, delm[2];
411 while (opt->
opts[j]) {
412 if (strcmp(opt->
opts[j], tokens[i]) == 0) {
419 G_warning(
_(
"Bug in UI description. Option '%s' in "
420 "<%s> does not exist"),
421 tokens[i], opt->
key);
437 for (i = 1; opt->
answers[i]; i++) {
453 (gui_envvar &&
G_strcasecmp(gui_envvar,
"text") != 0)) {
454 if (module_gui_wx() == 0)
458 if (argc < 2 && st->has_required &&
isatty(0)) {
462 else if (argc >= 2) {
465 if (strcmp(argv[1],
"help") == 0 || strcmp(argv[1],
"-help") == 0 ||
466 strcmp(argv[1],
"--help") == 0) {
473 if (strcmp(argv[1],
"--help-text") == 0) {
480 if (strcmp(argv[1],
"--interface-description") == 0) {
487 if (strcmp(argv[1],
"--html-description") == 0) {
494 if (strcmp(argv[1],
"--rst-description") == 0) {
501 if (strcmp(argv[1],
"--md-description") == 0) {
508 if (strcmp(argv[1],
"--wps-process-description") == 0) {
515 if (strcmp(argv[1],
"--script") == 0) {
525 if (strcmp(ptr,
"help") == 0 || strcmp(ptr,
"--h") == 0 ||
526 strcmp(ptr,
"-help") == 0 || strcmp(ptr,
"--help") == 0) {
532 if (strcmp(ptr,
"--json") == 0) {
538 if (strcmp(ptr,
"--o") == 0 || strcmp(ptr,
"--overwrite") == 0) {
543 else if (strcmp(ptr,
"--v") == 0 || strcmp(ptr,
"--verbose") == 0) {
548 snprintf(buff,
sizeof(buff),
"GRASS_VERBOSE=%d",
551 if (
st->quiet == 1) {
552 G_warning(
_(
"Use either --quiet or --verbose flag, not "
553 "both. Assuming --verbose."));
559 else if (strcmp(ptr,
"--q") == 0 || strcmp(ptr,
"--quiet") == 0) {
564 snprintf(buff,
sizeof(buff),
"GRASS_VERBOSE=%d",
567 if (
st->quiet == -1) {
568 G_warning(
_(
"Use either --quiet or --verbose flag, not "
569 "both. Assuming --quiet."));
575 else if (strcmp(ptr,
"--qq") == 0) {
580 snprintf(buff,
sizeof(buff),
"GRASS_VERBOSE=%d",
584 if (
st->quiet == -1) {
585 G_warning(
_(
"Use either --qq or --verbose flag, not both. "
592 else if (strcmp(ptr,
"--ui") == 0) {
597 else if (*ptr ==
'-') {
602 else if (is_option(ptr)) {
608 else if (need_first_opt &&
st->n_opts) {
610 st->first_option.count++;
627 if (module_gui_wx() != 0)
628 G_fatal_error(
_(
"Your installation doesn't include GUI, exiting."));
633 check_multiple_opts();
640 if (!
st->suppress_required)
645 if (
st->n_errors > 0) {
649 fprintf(stderr,
"\n");
650 for (i = 0; i <
st->n_errors; i++) {
651 fprintf(stderr,
"%s: %s\n",
_(
"ERROR"),
st->error[i]);
658 if (print_json == 1) {
663 if (!
st->suppress_overwrite) {
664 if (check_overwrite())
692 G_debug(3,
"G_recreate_command()");
696 buff =
G_calloc(1024,
sizeof(
char));
703 if (len >= nalloced) {
704 nalloced += (1024 > len) ? 1024 : len + 1;
712 slen = strlen(
" --overwrite");
713 if (len + slen >= nalloced) {
714 nalloced += (1024 > len) ? 1024 : len + 1;
717 strcpy(cur,
" --overwrite");
731 if (len + slen >= nalloced) {
732 nalloced += (1024 > len) ? 1024 : len + 1;
741 flag = &
st->first_flag;
749 if (len + slen >= nalloced) {
751 (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
763 opt = &
st->first_option;
764 while (
st->n_opts && opt) {
766 slen = strlen(opt->
key) + 4;
767 if (len + slen >= nalloced) {
768 nalloced += (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
775 cur = strchr(cur,
'\0');
785 slen = strlen(opt->
key) + strlen(opt->
answers[0]) +
787 if (len + slen >= nalloced) {
788 nalloced += (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
795 cur = strchr(cur,
'\0');
803 cur = strchr(cur,
'\0');
805 for (n = 1; opt->
answers[n]; n++) {
808 slen = strlen(opt->
answers[n]) + 2;
809 if (len + slen >= nalloced) {
811 (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
818 cur = strchr(cur,
'\0');
871 if (
st->n_keys >=
st->n_keys_alloc) {
872 st->n_keys_alloc += 10;
873 st->module_info.keywords =
G_realloc(
st->module_info.keywords,
874 st->n_keys_alloc *
sizeof(
char *));
877 st->module_info.keywords[
st->n_keys++] =
G_store(keyword);
889 st->module_info.keywords = (
const char **)tokens;
898 char desc[KEYLENGTH];
900 if (
st->module_info.overwrite)
906 opt = &
st->first_option;
910 if (strcmp(age,
"new") == 0)
935 for (i = 0; i <
st->n_keys; i++) {
937 fprintf(fd,
"%s",
st->module_info.keywords[i]);
940 format(fd,
st->module_info.keywords[i]);
942 if (i < st->n_keys - 1) {
962 return st->module_info.overwrite;
965 void define_keywords(
void)
968 st->n_keys_alloc = 0;
981 int module_gui_wx(
void)
991 snprintf(script,
GPATH_MAX,
"%s/gui/wxpython/gui_core/forms.py",
994 G_spawn(getenv(
"GRASS_PYTHON"), getenv(
"GRASS_PYTHON"), script,
1002 void set_flag(
int f)
1006 const char *renamed_key;
1019 flag = &
st->first_flag;
1021 if (flag->
key == f) {
1024 st->suppress_required = 1;
1026 st->suppress_overwrite = 1;
1034 renamed_key = get_renamed_option(
key);
1039 if (*renamed_key ==
'-') {
1041 if (renamed_key[1] ==
'-') {
1042 if (strcmp(renamed_key,
"--overwrite") == 0) {
1044 G_warning(
_(
"Please update the usage of <%s>: "
1045 "flag <%c> has been renamed to <%s>"),
1054 _(
"Please update the usage of <%s>: "
1055 "flag <%c> has been renamed to <%s>"),
1062 for (flag = &
st->first_flag; flag; flag = flag->
next_flag) {
1063 if (renamed_key[1] == flag->
key) {
1064 G_warning(
_(
"Please update the usage of <%s>: "
1065 "flag <%c> has been renamed to <%s>"),
1069 st->suppress_required = 1;
1071 st->suppress_overwrite = 1;
1080 for (opt = &
st->first_option; opt; opt = opt->
next_opt) {
1081 if (strcmp(renamed_key, opt->
key) == 0) {
1083 _(
"Please update the usage of <%s>: "
1084 "flag <%c> has been renamed to option <%s>"),
1101 int contains(
const char *s,
int c)
1111 int valid_option_name(
const char *
string)
1113 int m = strlen(
string);
1114 int n = strspn(
string,
"abcdefghijklmnopqrstuvwxyz0123456789_");
1122 if (
string[m - 1] ==
'_')
1128 int is_option(
const char *
string)
1130 int n = strspn(
string,
"abcdefghijklmnopqrstuvwxyz0123456789_");
1132 return n > 0 &&
string[n] ==
'=' &&
string[0] !=
'_' &&
1133 string[n - 1] !=
'_';
1136 int match_option_1(
const char *
string,
const char *option)
1140 if (*
string ==
'\0')
1143 if (*option ==
'\0')
1146 if (*
string == *option && match_option_1(
string + 1, option + 1))
1149 if (*option ==
'_' && match_option_1(
string, option + 1))
1152 next = strchr(option,
'_');
1157 return match_option_1(
string + 1, next + 1);
1159 return match_option_1(
string, next + 1);
1162 int match_option(
const char *
string,
const char *option)
1164 return (*
string == *option) && match_option_1(
string + 1, option + 1);
1167 void set_option(
const char *
string)
1172 char the_key[KEYLENGTH];
1179 for (ptr = the_key; *
string !=
'='; ptr++,
string++)
1189 key_len = strlen(the_key);
1190 for (at_opt = &
st->first_option; at_opt; at_opt = at_opt->
next_opt) {
1194 if (strcmp(the_key, at_opt->
key) == 0) {
1195 matches[0] = at_opt;
1200 if (strncmp(the_key, at_opt->
key, key_len) == 0 ||
1201 match_option(the_key, at_opt->
key)) {
1204 matches[found++] = at_opt;
1210 int length = strlen(matches[0]->
key);
1214 for (i = 1; i < found; i++) {
1215 int len = strlen(matches[i]->
key);
1222 for (i = 0; prefix && i < found; i++)
1223 if (strncmp(matches[i]->
key, matches[shortest]->
key, length) != 0)
1226 matches[0] = matches[shortest];
1233 for (i = 0; i < found; i++) {
1246 const char *renamed_key = get_renamed_option(the_key);
1251 if (*renamed_key ==
'-') {
1252 if (renamed_key[1] ==
'-')
1254 _(
"Please update the usage of <%s>: "
1255 "option <%s> has been renamed to flag <%s>"),
1259 _(
"Please update the usage of <%s>: "
1260 "option <%s> has been renamed to flag <%c>"),
1267 for (at_opt = &
st->first_option; at_opt;
1269 if (strcmp(renamed_key, at_opt->
key) == 0) {
1270 G_warning(
_(
"Please update the usage of <%s>: "
1271 "option <%s> has been renamed to <%s>"),
1289 if (getenv(
"GRASS_FULL_OPTION_NAMES") && strcmp(the_key, opt->
key) != 0)
1290 G_warning(
_(
"<%s> is an abbreviation for <%s>"), the_key, opt->
key);
1295 G_asprintf(&
err,
_(
"Option <%s> does not accept multiple answers"),
1301 strcat(opt->
answer,
",");
1302 strcat(opt->
answer,
string);
1308 void check_opts(
void)
1316 opt = &
st->first_option;
1340 void check_an_opt(
const char *
key,
int type,
const char *
options,
1341 const char **
opts,
char **answerp)
1343 const char *
answer = *answerp;
1368 _(
"Illegal range syntax for parameter <%s>\n"
1369 "\tPresented as: %s"),
1375 _(
"Value <%s> out of range for parameter <%s>\n"
1376 "\tLegal range: %s"),
1391 _(
"Value <%s> ambiguous for parameter <%s>\n"
1392 "\tValid options: %s"),
1403 int check_int(
const char *ans,
const char **
opts)
1408 if (strcmp(ans,
"-") == 0)
1414 if (sscanf(ans,
"%d", &d) != 1)
1420 for (i = 0;
opts[i]; i++) {
1421 const char *opt =
opts[i];
1424 if (contains(opt,
'-')) {
1425 if (sscanf(opt,
"%d-%d", &lo, &hi) == 2) {
1426 if (d >= lo && d <= hi)
1429 else if (sscanf(opt,
"-%d", &hi) == 1) {
1433 else if (sscanf(opt,
"%d-", &lo) == 1) {
1441 if (sscanf(opt,
"%d", &lo) == 1) {
1453 int check_double(
const char *ans,
const char **
opts)
1459 if (strcmp(ans,
"-") == 0)
1465 if (sscanf(ans,
"%lf", &d) != 1)
1471 for (i = 0;
opts[i]; i++) {
1472 const char *opt =
opts[i];
1475 if (contains(opt,
'-')) {
1476 if (sscanf(opt,
"%lf-%lf", &lo, &hi) == 2) {
1477 if (d >= lo && d <= hi)
1480 else if (sscanf(opt,
"-%lf", &hi) == 1) {
1484 else if (sscanf(opt,
"%lf-", &lo) == 1) {
1492 if (sscanf(opt,
"%lf", &lo) == 1) {
1504 int check_string(
const char *ans,
const char **
opts,
int *result)
1506 int len = strlen(ans);
1514 for (i = 0;
opts[i]; i++) {
1515 if (strcmp(ans,
opts[i]) == 0)
1517 if (strncmp(ans,
opts[i], len) == 0 || match_option(ans,
opts[i])) {
1520 matches[found++] = i;
1526 int length = strlen(
opts[matches[0]]);
1529 for (i = 1; i < found; i++) {
1530 int lengthi = strlen(
opts[matches[i]]);
1532 if (lengthi < length) {
1537 for (i = 0; prefix && i < found; i++)
1538 if (strncmp(
opts[matches[i]],
opts[matches[shortest]], length) != 0)
1541 matches[0] = matches[shortest];
1547 *result = matches[0];
1549 if (found > 0 && getenv(
"GRASS_FULL_OPTION_NAMES") &&
1550 strcmp(ans,
opts[matches[0]]) != 0)
1551 G_warning(
_(
"<%s> is an abbreviation for <%s>"), ans,
opts[matches[0]]);
1563 void check_required(
void)
1573 opt = &
st->first_option;
1577 _(
"Required parameter <%s> not set:\n"
1586 void split_opts(
void)
1598 opt = &
st->first_option;
1610 for (len = 0, ptr2 = ptr1; *ptr2 !=
'\0' && *ptr2 !=
',';
1616 memcpy(opt->
answers[ans_num], ptr1, len);
1617 opt->
answers[ans_num][len] = 0;
1621 if (ans_num >= allocated) {
1643 void check_multiple_opts(
void)
1655 opt = &
st->first_option;
1661 for (ptr = opt->
key_desc; *ptr !=
'\0'; ptr++)
1670 _(
"Option <%s> must be provided in multiples of %d\n"
1671 "\tYou provided %d item(s): %s"),
1681 int check_overwrite(
void)
1684 char age[KEYLENGTH];
1686 char desc[KEYLENGTH];
1688 const char *overstr;
1691 st->module_info.overwrite = 0;
1699 over = atoi(overstr);
1703 if ((overstr = getenv(
"GRASS_OVERWRITE"))) {
1708 if (
st->overwrite || over) {
1709 st->module_info.overwrite = 1;
1711 putenv(
"GRASS_OVERWRITE=1");
1716 opt = &
st->first_option;
1721 if (strcmp(age,
"new") == 0) {
1725 for (i = 0; opt->
answers[i]; i++) {
1727 if (strcmp(
element,
"file") == 0) {
1731 else if (strcmp(
element,
"mapset") != 0) {
1740 if (!
st->overwrite && !over) {
1743 fprintf(stderr,
_(
"ERROR: "));
1745 _(
"option <%s>: <%s> exists. To "
1746 "overwrite, use the --overwrite "
1749 fprintf(stderr,
"\n");
1752 fprintf(stderr,
"GRASS_INFO_ERROR(%d,1): ",
1755 _(
"option <%s>: <%s> exists. To "
1756 "overwrite, use the --overwrite "
1759 fprintf(stderr,
"\n");
1760 fprintf(stderr,
"GRASS_INFO_END(%d,1)\n",
1782 for (ptr1 =
gisprompt, ptr2 = age; *ptr1 !=
'\0'; ptr1++, ptr2++) {
1789 for (ptr1++, ptr2 =
element; *ptr1 !=
'\0'; ptr1++, ptr2++) {
1796 for (ptr1++, ptr2 = desc; *ptr1 !=
'\0'; ptr1++, ptr2++) {
1804 void append_error(
const char *msg)
1806 st->error =
G_realloc(
st->error,
sizeof(
char *) * (
st->n_errors + 1));
1810 const char *get_renamed_option(
const char *
key)
1812 const char *pgm, *key_new;
1815 if (!
st->renamed_options) {
1830 pgm_key = (
char *)
G_malloc(strlen(pgm) + strlen(
key) + 2);
1866 strcmp(option->
gisprompt,
"old,separator,separator") != 0)
1872 if (strcmp(option->
answer,
"pipe") == 0)
1874 else if (strcmp(option->
answer,
"comma") == 0)
1876 else if (strcmp(option->
answer,
"space") == 0)
1878 else if (strcmp(option->
answer,
"tab") == 0 ||
1879 strcmp(option->
answer,
"\\t") == 0)
1881 else if (strcmp(option->
answer,
"newline") == 0 ||
1882 strcmp(option->
answer,
"\\n") == 0)
1887 G_debug(3,
"G_option_to_separator(): key = %s -> sep = '%s'", option->
key,
1929 strcmp(option->
answer,
"-") == 0;
1936 else if (strcmp(option->
gisprompt,
"old,file,file") == 0) {
1939 else if ((fp = fopen(option->
answer,
"r")) ==
NULL)
1941 option->
answer, strerror(errno));
1943 else if (strcmp(option->
gisprompt,
"new,file,file") == 0) {
1946 else if ((fp = fopen(option->
answer,
"w")) ==
NULL)
1948 option->
answer, strerror(errno));
1964 if (fp != stdin && fp != stdout && fp != stderr)
char * G_basename(char *, const char *)
Truncates filename to the base part (before the last '.') if it matches the extension,...
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
void G_free(void *)
Free allocated memory.
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
int G_verbose_max(void)
Get max verbosity level.
const char * G_find_key_value(const char *, const struct Key_Value *)
Find given key (case sensitive)
const char * G_mapset(void)
Get current mapset name.
int G_verbose(void)
Get current verbosity level.
int G_verbose_min(void)
Get min verbosity level.
void G_free_tokens(char **)
Free memory allocated to tokens.
int G_asprintf(char **, const char *,...) __attribute__((format(printf
struct Key_Value * G_read_key_value_file(const char *)
Read key/values pairs from file.
int G_number_of_tokens(char **)
Return number of tokens.
int G_is_dirsep(char)
Checks if a specified character is a valid directory separator character on the host system.
int int G_strcasecmp(const char *, const char *)
String compare ignoring case (upper or lower)
const char * G_original_program_name(void)
Return original path of the executed program.
void G_usage(void)
Command line help/usage message.
int G_info_format(void)
Get current message format.
const char * G_gisbase(void)
Get full path name of the top level module directory.
const char * G_program_name(void)
Return module name.
char * G_chop(char *)
Chop leading and trailing white spaces.
int G_debug(int, const char *,...) __attribute__((format(printf
const char * G_getenv_nofatal(const char *)
Get environment variable.
int G_verbose_std(void)
Get standard verbosity level.
char * G_store(const char *)
Copy string to allocated memory.
char ** G_tokenize(const char *, const char *)
Tokenize string.
void int G_suppress_warnings(int)
Suppress printing a warning message to stderr.
const char * G_find_file(const char *, char *, const char *)
Searches for a file from the mapset search list or in a specified mapset.
int G_spawn(const char *command,...)
Spawn new process based on command.
#define G_INFO_FORMAT_GUI
struct GModule * G_define_module(void)
Initializes a new module.
void G__print_keywords(FILE *fd, void(*format)(FILE *, const char *), int newline)
Print list of keywords (internal use only)
FILE * G_open_option_file(const struct Option *option)
Get an input/output file pointer from the option. If the file name is omitted or '-',...
char * G_recreate_command_original_path(void)
Creates command to run non-interactive.
int G_parser(int argc, char **argv)
Parse command line.
void G_set_keywords(const char *keywords)
Set keywords from the string.
int G__uses_new_gisprompt(void)
char * recreate_command(int original_path)
Creates command to run non-interactive.
struct Option * G_define_option(void)
Initializes an Option struct.
void G_add_keyword(const char *keyword)
Add keyword to the list.
int G_get_overwrite(void)
Get overwrite value.
void G_close_option_file(FILE *fp)
Close an input/output file returned by G_open_option_file(). If the file pointer is stdin,...
char * G_recreate_command(void)
Creates command to run non-interactive.
void G_disable_interactive(void)
Disables the ability of the parser to operate interactively.
struct Flag * G_define_flag(void)
Initializes a Flag struct.
char * G_option_to_separator(const struct Option *option)
Get separator string from the option.
void G__split_gisprompt(const char *gisprompt, char *age, char *element, char *desc)
void G__check_option_rules(void)
Check for option rules (internal use only)
int G__has_required_rule(void)
Checks if there is any rule RULE_REQUIRED (internal use only).
void G__usage_html(void)
Print module usage description in HTML format.
void G__usage_xml(void)
Print module usage description in XML format.
char * G__json(void)
This function generates actinia JSON process chain building blocks from the command line arguments th...
void G__usage_markdown(void)
Print module usage description in Markdown format.
void G__usage_rest(void)
Print module usage description in reStructuredText format.
void G__script(void)
Generate Python script-like output.
void G__wps_print_process_description(void)
Print the WPS 1.0.0 process description XML document to stdout.
Structure that stores flag info.
Structure that stores module info.
Structure that stores option information.
int(* checker)(const char *)
const char * descriptions
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)