Loading...
Searching...
No Matches
parser.c
Go to the documentation of this file.
/*!
* \file lib/gis/parser.c
*
* \brief GIS Library - Argument parsing functions.
*
* Parses the command line provided through argc and argv. Example:
* Assume the previous calls:
*
\code
opt1 = G_define_option() ;
opt1->key = "map",
opt1->type = TYPE_STRING,
opt1->required = YES,
opt1->checker = sub,
opt1->description= "Name of an existing raster map" ;
opt2 = G_define_option() ;
opt2->key = "color",
opt2->type = TYPE_STRING,
opt2->required = NO,
opt2->answer = "white",
opt2->options = "red,orange,blue,white,black",
opt2->description= "Color used to display the map" ;
opt3 = G_define_option() ;
opt3->key = "number",
opt3->type = TYPE_DOUBLE,
opt3->required = NO,
opt3->answer = "12345.67",
opt3->options = "0-99999",
opt3->description= "Number to test parser" ;
\endcode
*
* G_parser() will respond to the following command lines as described:
*
\verbatim
command (No command line arguments)
\endverbatim
* Parser enters interactive mode.
*
\verbatim
command map=map.name
\endverbatim
* Parser will accept this line. Map will be set to "map.name", the
* 'a' and 'b' flags will remain off and the num option will be set
* to the default of 5.
*
\verbatim
command -ab map=map.name num=9
command -a -b map=map.name num=9
command -ab map.name num=9
command map.name num=9 -ab
command num=9 -a map=map.name -b
\endverbatim
* These are all treated as acceptable and identical. Both flags are
* set to on, the map option is "map.name" and the num option is "9".
* Note that the "map=" may be omitted from the command line if it
* is part of the first option (flags do not count).
*
\verbatim
command num=12
\endverbatim
* This command line is in error in two ways. The user will be told
* that the "map" option is required and also that the number 12 is
* out of range. The acceptable range (or list) will be printed.
*
* Overview table: <a href="parser_standard_options.html">Parser standard
options</a>
*
* (C) 2001-2015 by the GRASS Development Team
*
* This program is free software under the GNU General Public License
* (>=v2). Read the file COPYING that comes with GRASS for details.
*
* \author Original author CERL
* \author Soeren Gebbert added Dec. 2009 WPS process_description document
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <grass/gis.h>
#include <grass/spawn.h>
#include <grass/glocale.h>
#include "parser_local_proto.h"
enum opt_error {
BAD_SYNTAX = 1,
OUT_OF_RANGE = 2,
MISSING_VALUE = 3,
INVALID_VALUE = 4,
AMBIGUOUS = 5,
REPLACED = 6
};
#define MAX_MATCHES 50
/* initialize the global struct */
struct state state;
struct state *st = &state;
/* local prototypes */
static void set_flag(int);
static int contains(const char *, int);
static int valid_option_name(const char *);
static int is_option(const char *);
static int match_option_1(const char *, const char *);
static int match_option(const char *, const char *);
static void set_option(const char *);
static void check_opts(void);
static void check_an_opt(const char *, int, const char *, const char **,
char **);
static int check_int(const char *, const char **);
static int check_double(const char *, const char **);
static int check_string(const char *, const char **, int *);
static void check_required(void);
static void split_opts(void);
static void check_multiple_opts(void);
static int check_overwrite(void);
static void define_keywords(void);
static int module_gui_wx(void);
static void append_error(const char *);
static const char *get_renamed_option(const char *);
/*!
* \brief Disables the ability of the parser to operate interactively.
*
* When a user calls a command with no arguments on the command line,
* the parser will enter its own standardized interactive session in
* which all flags and options are presented to the user for input. A
* call to G_disable_interactive() disables the parser's interactive
* prompting.
*
*/
void G_disable_interactive(void)
{
st->no_interactive = 1;
}
/*!
* \brief Initializes a Flag struct.
*
* Allocates memory for the Flag structure and returns a pointer to
* this memory.
*
* Flags are always represented by single letters. A user "turns them
* on" at the command line using a minus sign followed by the
* character representing the flag.
*
* \return Pointer to a Flag struct
*/
struct Flag *G_define_flag(void)
{
struct Flag *flag;
struct Item *item;
/* Allocate memory if not the first flag */
if (st->n_flags) {
flag = G_malloc(sizeof(struct Flag));
st->current_flag->next_flag = flag;
}
else
flag = &st->first_flag;
/* Zero structure */
G_zero(flag, sizeof(struct Flag));
st->current_flag = flag;
st->n_flags++;
if (st->n_items) {
item = G_malloc(sizeof(struct Item));
st->current_item->next_item = item;
}
else
item = &st->first_item;
G_zero(item, sizeof(struct Item));
item->flag = flag;
item->option = NULL;
st->current_item = item;
st->n_items++;
return (flag);
}
/*!
* \brief Initializes an Option struct.
*
* Allocates memory for the Option structure and returns a pointer to
* this memory.
*
* Options are provided by user on command line using the standard
* format: <i>key=value</i>. Options identified as REQUIRED must be
* specified by user on command line. The option string can either
* specify a range of values (e.g. "10-100") or a list of acceptable
* values (e.g. "red,orange,yellow"). Unless the option string is
* NULL, user provided input will be evaluated against this string.
*
* \return pointer to an Option struct
*/
struct Option *G_define_option(void)
{
struct Option *opt;
struct Item *item;
/* Allocate memory if not the first option */
if (st->n_opts) {
opt = G_malloc(sizeof(struct Option));
st->current_option->next_opt = opt;
}
else
opt = &st->first_option;
/* Zero structure */
G_zero(opt, sizeof(struct Option));
opt->required = NO;
opt->multiple = NO;
st->current_option = opt;
st->n_opts++;
if (st->n_items) {
item = G_malloc(sizeof(struct Item));
st->current_item->next_item = item;
}
else
item = &st->first_item;
G_zero(item, sizeof(struct Item));
item->option = opt;
st->current_item = item;
st->n_items++;
return (opt);
}
/*!
* \brief Initializes a new module.
*
* \return pointer to a GModule struct
*/
struct GModule *G_define_module(void)
{
struct GModule *module;
/* Allocate memory */
module = &st->module_info;
/* Zero structure */
G_zero(module, sizeof(struct GModule));
/* Allocate keywords array */
define_keywords();
return (module);
}
/*!
* \brief Parse command line.
*
* The command line parameters <i>argv</i> and the number of
* parameters <i>argc</i> from the main() routine are passed directly
* to G_parser(). G_parser() accepts the command line input entered by
* the user, and parses this input according to the input options
* and/or flags that were defined by the programmer.
*
* <b>Note:</b> The only functions which can legitimately be called
* before G_parser() are:
*
* - G_gisinit()
* - G_no_gisinit()
* - G_define_module()
* - G_define_flag()
* - G_define_option()
* - G_define_standard_flag()
* - G_define_standard_option()
* - G_disable_interactive()
* - G_option_exclusive()
* - G_option_required()
* - G_option_requires()
* - G_option_requires_all()
* - G_option_excludes()
* - G_option_collective()
*
* The usual order a module calls functions is:
*
* 1. G_gisinit()
* 2. G_define_module()
* 3. G_define_standard_flag()
* 4. G_define_standard_option()
* 5. G_define_flag()
* 6. G_define_option()
* 7. G_option_exclusive()
* 8. G_option_required()
* 9. G_option_requires()
* 10. G_option_requires_all()
* 11. G_option_excludes()
* 12. G_option_collective()
* 13. G_parser()
*
* \param argc number of arguments
* \param argv argument list
*
* \return 0 on success
* \return -1 on error and calls G_usage()
*/
int G_parser(int argc, char **argv)
{
int need_first_opt;
int opt_checked = 0;
const char *gui_envvar;
char *ptr, *tmp_name, *err;
int i;
struct Option *opt;
char force_gui = FALSE;
int print_json = 0;
err = NULL;
need_first_opt = 1;
tmp_name = G_store(argv[0]);
st->pgm_path = tmp_name;
st->n_errors = 0;
st->error = NULL;
st->module_info.verbose = G_verbose_std();
i = strlen(tmp_name);
while (--i >= 0) {
if (G_is_dirsep(tmp_name[i])) {
tmp_name += i + 1;
break;
}
}
G_basename(tmp_name, "exe");
st->pgm_name = tmp_name;
if (!st->module_info.label && !st->module_info.description)
G_warning(_("Bug in UI description. Missing module description"));
/* Stash default answers */
opt = &st->first_option;
while (st->n_opts && opt) {
if (opt->required)
st->has_required = 1;
if (!opt->key)
G_warning(_("Bug in UI description. Missing option key"));
if (opt->key && !valid_option_name(opt->key))
G_warning(_("Bug in UI description. Option key <%s> is not valid"),
opt->key);
if (!opt->label && !opt->description)
G_warning(
_("Bug in UI description. Description for option <%s> missing"),
opt->key ? opt->key : "?");
/* Parse options */
if (opt->options) {
int cnt = 0;
char **tokens, delm[2];
delm[0] = ',';
delm[1] = '\0';
tokens = G_tokenize(opt->options, delm);
i = 0;
while (tokens[i]) {
G_chop(tokens[i]);
cnt++;
i++;
}
opt->opts = G_calloc(cnt + 1, sizeof(const char *));
i = 0;
while (tokens[i]) {
opt->opts[i] = G_store(tokens[i]);
i++;
}
G_free_tokens(tokens);
if (opt->descriptions) {
delm[0] = ';';
opt->descs = G_calloc(cnt + 1, sizeof(const char *));
tokens = G_tokenize(opt->descriptions, delm);
i = 0;
while (tokens[i]) {
int j, found;
if (!tokens[i + 1])
break;
G_chop(tokens[i]);
j = 0;
found = 0;
while (opt->opts[j]) {
if (strcmp(opt->opts[j], tokens[i]) == 0) {
found = 1;
break;
}
j++;
}
if (!found) {
G_warning(_("Bug in UI description. Option '%s' in "
"<%s> does not exist"),
tokens[i], opt->key);
}
else {
opt->descs[j] = G_store(tokens[i + 1]);
}
i += 2;
}
G_free_tokens(tokens);
}
}
/* Copy answer */
if (opt->multiple && opt->answers && opt->answers[0]) {
opt->answer = G_malloc(strlen(opt->answers[0]) + 1);
strcpy(opt->answer, opt->answers[0]);
for (i = 1; opt->answers[i]; i++) {
opt->answer =
G_realloc(opt->answer, strlen(opt->answer) +
strlen(opt->answers[i]) + 2);
strcat(opt->answer, ",");
strcat(opt->answer, opt->answers[i]);
}
}
opt->def = opt->answer;
opt = opt->next_opt;
}
/* If there are NO arguments, go interactive */
gui_envvar = G_getenv_nofatal("GUI");
if (argc < 2 && (st->has_required || G__has_required_rule()) &&
!st->no_interactive && isatty(0) &&
(gui_envvar && G_strcasecmp(gui_envvar, "text") != 0)) {
if (module_gui_wx() == 0)
return -1;
}
if (argc < 2 && st->has_required && isatty(0)) {
G_usage();
return -1;
}
else if (argc >= 2) {
/* If first arg is "help" give a usage/syntax message */
if (strcmp(argv[1], "help") == 0 || strcmp(argv[1], "-help") == 0 ||
strcmp(argv[1], "--help") == 0) {
G_usage();
exit(EXIT_SUCCESS);
}
/* If first arg is "--help-text" give a usage/syntax message
* with machine-readable sentinels */
if (strcmp(argv[1], "--help-text") == 0) {
G__usage_text();
exit(EXIT_SUCCESS);
}
/* If first arg is "--interface-description" then print out
* an xml description of the task */
if (strcmp(argv[1], "--interface-description") == 0) {
G__usage_xml();
exit(EXIT_SUCCESS);
}
/* If first arg is "--html-description" then print out
* a html description of the task */
if (strcmp(argv[1], "--html-description") == 0) {
G__usage_html();
exit(EXIT_SUCCESS);
}
/* If first arg is "--rst-description" then print out
* a reStructuredText description of the task */
if (strcmp(argv[1], "--rst-description") == 0) {
G__usage_rest();
exit(EXIT_SUCCESS);
}
/* If first arg is "--md-description" then print out
* a Markdown description of the task */
if (strcmp(argv[1], "--md-description") == 0) {
G__usage_markdown();
exit(EXIT_SUCCESS);
}
/* If first arg is "--wps-process-description" then print out
* the wps process description of the task */
if (strcmp(argv[1], "--wps-process-description") == 0) {
G__wps_print_process_description();
exit(EXIT_SUCCESS);
}
/* If first arg is "--script" then then generate
* g.parser boilerplate */
if (strcmp(argv[1], "--script") == 0) {
G__script();
exit(EXIT_SUCCESS);
}
/* Loop through all command line arguments */
while (--argc) {
ptr = *(++argv);
if (strcmp(ptr, "help") == 0 || strcmp(ptr, "--h") == 0 ||
strcmp(ptr, "-help") == 0 || strcmp(ptr, "--help") == 0) {
G_usage();
exit(EXIT_SUCCESS);
}
/* JSON print option */
if (strcmp(ptr, "--json") == 0) {
print_json = 1;
continue;
}
/* Overwrite option */
if (strcmp(ptr, "--o") == 0 || strcmp(ptr, "--overwrite") == 0) {
st->overwrite = 1;
}
/* Verbose option */
else if (strcmp(ptr, "--v") == 0 || strcmp(ptr, "--verbose") == 0) {
char buff[32];
/* print everything: max verbosity level */
st->module_info.verbose = G_verbose_max();
snprintf(buff, sizeof(buff), "GRASS_VERBOSE=%d",
G_verbose_max());
putenv(G_store(buff));
if (st->quiet == 1) {
G_warning(_("Use either --quiet or --verbose flag, not "
"both. Assuming --verbose."));
}
st->quiet = -1;
}
/* Quiet option */
else if (strcmp(ptr, "--q") == 0 || strcmp(ptr, "--quiet") == 0) {
char buff[32];
/* print nothing, but errors and warnings */
st->module_info.verbose = G_verbose_min();
snprintf(buff, sizeof(buff), "GRASS_VERBOSE=%d",
G_verbose_min());
putenv(G_store(buff));
if (st->quiet == -1) {
G_warning(_("Use either --quiet or --verbose flag, not "
"both. Assuming --quiet."));
}
st->quiet = 1; /* for passing to gui init */
}
/* Super quiet option */
else if (strcmp(ptr, "--qq") == 0) {
char buff[32];
/* print nothing, but errors */
st->module_info.verbose = G_verbose_min();
snprintf(buff, sizeof(buff), "GRASS_VERBOSE=%d",
G_verbose_min());
putenv(G_store(buff));
G_suppress_warnings(TRUE);
if (st->quiet == -1) {
G_warning(_("Use either --qq or --verbose flag, not both. "
"Assuming --qq."));
}
st->quiet = 1; /* for passing to gui init */
}
/* Force gui to come up */
else if (strcmp(ptr, "--ui") == 0) {
force_gui = TRUE;
}
/* If we see a flag */
else if (*ptr == '-') {
while (*(++ptr))
set_flag(*ptr);
}
/* If we see standard option format (option=val) */
else if (is_option(ptr)) {
set_option(ptr);
need_first_opt = 0;
}
/* If we see the first option with no equal sign */
else if (need_first_opt && st->n_opts) {
st->first_option.answer = G_store(ptr);
st->first_option.count++;
need_first_opt = 0;
}
/* If we see the non valid argument (no "=", just argument) */
else {
G_asprintf(&err, _("Sorry <%s> is not a valid option"), ptr);
append_error(err);
}
}
}
/* Split options where multiple answers are OK */
split_opts();
/* Run the gui if it was specifically requested */
if (force_gui) {
if (module_gui_wx() != 0)
G_fatal_error(_("Your installation doesn't include GUI, exiting."));
return -1;
}
/* Check multiple options */
check_multiple_opts();
/* Check answers against options and check subroutines */
if (!opt_checked)
check_opts();
/* Make sure all required options are set */
if (!st->suppress_required)
check_required();
G__check_option_rules();
if (st->n_errors > 0) {
if (G_verbose() > -1) {
if (G_verbose() > G_verbose_min())
G_usage();
fprintf(stderr, "\n");
for (i = 0; i < st->n_errors; i++) {
fprintf(stderr, "%s: %s\n", _("ERROR"), st->error[i]);
}
}
return -1;
}
/* Print the JSON definition of the command and exit */
if (print_json == 1) {
G__json();
exit(EXIT_SUCCESS);
}
if (!st->suppress_overwrite) {
if (check_overwrite())
return -1;
}
return 0;
}
/*!
* \brief Creates command to run non-interactive.
*
* Creates a command-line that runs the current command completely
* non-interactive.
*
* \param original_path TRUE if original path should be used, FALSE for
* stripped and clean name of the module
* \return pointer to a char string
*/
char *recreate_command(int original_path)
{
char *buff;
char flg[4];
char *cur;
const char *tmp;
struct Flag *flag;
struct Option *opt;
int n, len, slen;
int nalloced = 0;
G_debug(3, "G_recreate_command()");
/* Flag is not valid if there are no flags to set */
buff = G_calloc(1024, sizeof(char));
nalloced += 1024;
if (original_path)
tmp = G_original_program_name();
else
tmp = G_program_name();
len = strlen(tmp);
if (len >= nalloced) {
nalloced += (1024 > len) ? 1024 : len + 1;
buff = G_realloc(buff, nalloced);
}
cur = buff;
strcpy(cur, tmp);
cur += len;
if (st->overwrite) {
slen = strlen(" --overwrite");
if (len + slen >= nalloced) {
nalloced += (1024 > len) ? 1024 : len + 1;
buff = G_realloc(buff, nalloced);
}
strcpy(cur, " --overwrite");
cur += slen;
len += slen;
}
if (st->module_info.verbose != G_verbose_std()) {
char *sflg;
if (st->module_info.verbose == G_verbose_max())
sflg = " --verbose";
else
sflg = " --quiet";
slen = strlen(sflg);
if (len + slen >= nalloced) {
nalloced += (1024 > len) ? 1024 : len + 1;
buff = G_realloc(buff, nalloced);
}
strcpy(cur, sflg);
cur += slen;
len += slen;
}
if (st->n_flags) {
flag = &st->first_flag;
while (flag) {
if (flag->answer == 1) {
flg[0] = ' ';
flg[1] = '-';
flg[2] = flag->key;
flg[3] = '\0';
slen = strlen(flg);
if (len + slen >= nalloced) {
nalloced +=
(nalloced + 1024 > len + slen) ? 1024 : slen + 1;
buff = G_realloc(buff, nalloced);
cur = buff + len;
}
strcpy(cur, flg);
cur += slen;
len += slen;
}
flag = flag->next_flag;
}
}
opt = &st->first_option;
while (st->n_opts && opt) {
if (opt->answer && opt->answer[0] == '\0') { /* answer = "" */
slen = strlen(opt->key) + 4; /* +4 for: ' ' = " " */
if (len + slen >= nalloced) {
nalloced += (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
buff = G_realloc(buff, nalloced);
cur = buff + len;
}
strcpy(cur, " ");
cur++;
strcpy(cur, opt->key);
cur = strchr(cur, '\0');
strcpy(cur, "=");
cur++;
if (opt->type == TYPE_STRING) {
strcpy(cur, "\"\"");
cur += 2;
}
len = cur - buff;
}
else if (opt->answer && opt->answers && opt->answers[0]) {
slen = strlen(opt->key) + strlen(opt->answers[0]) +
4; /* +4 for: ' ' = " " */
if (len + slen >= nalloced) {
nalloced += (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
buff = G_realloc(buff, nalloced);
cur = buff + len;
}
strcpy(cur, " ");
cur++;
strcpy(cur, opt->key);
cur = strchr(cur, '\0');
strcpy(cur, "=");
cur++;
if (opt->type == TYPE_STRING) {
strcpy(cur, "\"");
cur++;
}
strcpy(cur, opt->answers[0]);
cur = strchr(cur, '\0');
len = cur - buff;
for (n = 1; opt->answers[n]; n++) {
if (!opt->answers[n])
break;
slen = strlen(opt->answers[n]) + 2; /* +2 for , " */
if (len + slen >= nalloced) {
nalloced +=
(nalloced + 1024 > len + slen) ? 1024 : slen + 1;
buff = G_realloc(buff, nalloced);
cur = buff + len;
}
strcpy(cur, ",");
cur++;
strcpy(cur, opt->answers[n]);
cur = strchr(cur, '\0');
len = cur - buff;
}
if (opt->type == TYPE_STRING) {
strcpy(cur, "\"");
cur++;
len = cur - buff;
}
}
opt = opt->next_opt;
}
return buff;
}
/*!
* \brief Creates command to run non-interactive.
*
* Creates a command-line that runs the current command completely
* non-interactive.
*
* \return pointer to a char string
*/
char *G_recreate_command(void)
{
return recreate_command(FALSE);
}
/* TODO: update to docs of these 3 functions to whatever general purpose
* they have now. */
/*!
* \brief Creates command to run non-interactive.
*
* Creates a command-line that runs the current command completely
* non-interactive.
*
* This gives the same as G_recreate_command() but the original path
* from the command line is used instead of the module name only.
*
* \return pointer to a char string
*/
char *G_recreate_command_original_path(void)
{
return recreate_command(TRUE);
}
/*!
\brief Add keyword to the list
\param keyword keyword string
*/
void G_add_keyword(const char *keyword)
{
if (st->n_keys >= st->n_keys_alloc) {
st->n_keys_alloc += 10;
st->module_info.keywords = G_realloc(st->module_info.keywords,
st->n_keys_alloc * sizeof(char *));
}
st->module_info.keywords[st->n_keys++] = G_store(keyword);
}
/*!
\brief Set keywords from the string
\param keywords keywords separated by commas
*/
void G_set_keywords(const char *keywords)
{
char **tokens = G_tokenize(keywords, ",");
st->module_info.keywords = (const char **)tokens;
st->n_keys = st->n_keys_alloc = G_number_of_tokens(tokens);
}
int G__uses_new_gisprompt(void)
{
struct Option *opt;
char age[KEYLENGTH];
char element[KEYLENGTH];
char desc[KEYLENGTH];
if (st->module_info.overwrite)
return 1;
/* figure out if any of the options use a "new" gisprompt */
/* This is to see if we should spit out the --o flag */
if (st->n_opts) {
opt = &st->first_option;
while (opt) {
if (opt->gisprompt) {
G__split_gisprompt(opt->gisprompt, age, element, desc);
if (strcmp(age, "new") == 0)
return 1;
}
opt = opt->next_opt;
}
}
return 0;
}
/*!
\brief Print list of keywords (internal use only)
If <em>format</em> function is NULL then list of keywords is printed
comma-separated.
\param[out] fd file where to print
\param format pointer to print function
\param newline TRUE to include newline
*/
void G__print_keywords(FILE *fd, void (*format)(FILE *, const char *),
int newline)
{
int i;
for (i = 0; i < st->n_keys; i++) {
if (!format) {
fprintf(fd, "%s", st->module_info.keywords[i]);
}
else {
format(fd, st->module_info.keywords[i]);
}
if (i < st->n_keys - 1) {
fprintf(fd, ",");
if (!newline)
fprintf(fd, " ");
}
if (newline)
fprintf(fd, "\n");
}
fflush(fd);
}
/*!
\brief Get overwrite value
\return 1 overwrite enabled
\return 0 overwrite disabled
*/
int G_get_overwrite(void)
{
return st->module_info.overwrite;
}
void define_keywords(void)
{
st->n_keys = 0;
st->n_keys_alloc = 0;
}
/**************************************************************************
*
* The remaining routines are all local (static) routines used to support
* the parsing process.
*
**************************************************************************/
/*!
\brief Invoke GUI dialog
*/
int module_gui_wx(void)
{
char script[GPATH_MAX];
/* TODO: the 4 following lines seems useless */
if (!st->pgm_path)
st->pgm_path = G_program_name();
if (!st->pgm_path)
G_fatal_error(_("Unable to determine program name"));
snprintf(script, GPATH_MAX, "%s/gui/wxpython/gui_core/forms.py",
getenv("GISBASE"));
if (access(script, F_OK) != -1)
G_spawn(getenv("GRASS_PYTHON"), getenv("GRASS_PYTHON"), script,
G_recreate_command_original_path(), NULL);
else
return -1;
return 0;
}
void set_flag(int f)
{
struct Flag *flag;
char *key, *err;
const char *renamed_key;
err = NULL;
/* Flag is not valid if there are no flags to set */
if (!st->n_flags) {
G_asprintf(&err, _("%s: Sorry, <%c> is not a valid flag"),
G_program_name(), f);
append_error(err);
return;
}
/* Find flag with correct keyword */
flag = &st->first_flag;
while (flag) {
if (flag->key == f) {
flag->answer = 1;
if (flag->suppress_required)
st->suppress_required = 1;
if (flag->suppress_overwrite)
st->suppress_overwrite = 1;
return;
}
flag = flag->next_flag;
}
/* First, check if key has been renamed */
G_asprintf(&key, "-%c", f);
renamed_key = get_renamed_option(key);
G_free(key);
if (renamed_key) {
/* if renamed to a new flag */
if (*renamed_key == '-') {
/* if renamed to a long flag */
if (renamed_key[1] == '-') {
if (strcmp(renamed_key, "--overwrite") == 0) {
/* this is a special case for -? to --overwrite */
G_warning(_("Please update the usage of <%s>: "
"flag <%c> has been renamed to <%s>"),
G_program_name(), f, renamed_key);
st->overwrite = 1;
}
else {
/* long flags other than --overwrite are usually specific to
* GRASS internals, just print an error and let's not
* support them */
G_asprintf(&err,
_("Please update the usage of <%s>: "
"flag <%c> has been renamed to <%s>"),
G_program_name(), f, renamed_key);
append_error(err);
}
return;
}
/* if renamed to a short flag */
for (flag = &st->first_flag; flag; flag = flag->next_flag) {
if (renamed_key[1] == flag->key) {
G_warning(_("Please update the usage of <%s>: "
"flag <%c> has been renamed to <%s>"),
G_program_name(), f, renamed_key);
flag->answer = 1;
if (flag->suppress_required)
st->suppress_required = 1;
if (flag->suppress_overwrite)
st->suppress_overwrite = 1;
return;
}
}
}
else {
/* if renamed to a new option (no option value given but will be
* required), fatal error */
struct Option *opt = NULL;
for (opt = &st->first_option; opt; opt = opt->next_opt) {
if (strcmp(renamed_key, opt->key) == 0) {
G_asprintf(&err,
_("Please update the usage of <%s>: "
"flag <%c> has been renamed to option <%s>"),
G_program_name(), f, renamed_key);
append_error(err);
return;
}
}
}
}
G_asprintf(&err, _("%s: Sorry, <%c> is not a valid flag"), G_program_name(),
f);
append_error(err);
}
/* contents() is used to find things strings with characters like commas and
* dashes.
*/
int contains(const char *s, int c)
{
while (*s) {
if (*s == c)
return TRUE;
s++;
}
return FALSE;
}
int valid_option_name(const char *string)
{
int m = strlen(string);
int n = strspn(string, "abcdefghijklmnopqrstuvwxyz0123456789_");
if (!m)
return 0;
if (m != n)
return 0;
if (string[m - 1] == '_')
return 0;
return 1;
}
int is_option(const char *string)
{
int n = strspn(string, "abcdefghijklmnopqrstuvwxyz0123456789_");
return n > 0 && string[n] == '=' && string[0] != '_' &&
string[n - 1] != '_';
}
int match_option_1(const char *string, const char *option)
{
const char *next;
if (*string == '\0')
return 1;
if (*option == '\0')
return 0;
if (*string == *option && match_option_1(string + 1, option + 1))
return 1;
if (*option == '_' && match_option_1(string, option + 1))
return 1;
next = strchr(option, '_');
if (!next)
return 0;
if (*string == '_')
return match_option_1(string + 1, next + 1);
return match_option_1(string, next + 1);
}
int match_option(const char *string, const char *option)
{
return (*string == *option) && match_option_1(string + 1, option + 1);
}
void set_option(const char *string)
{
struct Option *at_opt = NULL;
struct Option *opt = NULL;
size_t key_len;
char the_key[KEYLENGTH];
char *ptr, *err;
struct Option *matches[MAX_MATCHES];
int found = 0;
err = NULL;
for (ptr = the_key; *string != '='; ptr++, string++)
*ptr = *string;
*ptr = '\0';
string++;
/* an empty string is not a valid answer, skip */
if (!*string)
return;
/* Find option with best keyword match */
key_len = strlen(the_key);
for (at_opt = &st->first_option; at_opt; at_opt = at_opt->next_opt) {
if (!at_opt->key)
continue;
if (strcmp(the_key, at_opt->key) == 0) {
matches[0] = at_opt;
found = 1;
break;
}
if (strncmp(the_key, at_opt->key, key_len) == 0 ||
match_option(the_key, at_opt->key)) {
if (found >= MAX_MATCHES)
G_fatal_error("Too many matches (limit %d)", MAX_MATCHES);
matches[found++] = at_opt;
}
}
if (found > 1) {
int shortest = 0;
int length = strlen(matches[0]->key);
int prefix = 1;
int i;
for (i = 1; i < found; i++) {
int len = strlen(matches[i]->key);
if (len < length) {
length = len;
shortest = i;
}
}
for (i = 0; prefix && i < found; i++)
if (strncmp(matches[i]->key, matches[shortest]->key, length) != 0)
prefix = 0;
if (prefix) {
matches[0] = matches[shortest];
found = 1;
}
else {
G_asprintf(&err, _("%s: Sorry, <%s=> is ambiguous"),
G_program_name(), the_key);
append_error(err);
for (i = 0; i < found; i++) {
G_asprintf(&err, _("Option <%s=> matches"), matches[i]->key);
append_error(err);
}
return;
}
}
if (found)
opt = matches[0];
/* First, check if key has been renamed */
if (found == 0) {
const char *renamed_key = get_renamed_option(the_key);
if (renamed_key) {
/* if renamed to a new flag (option value given but will be lost),
* fatal error */
if (*renamed_key == '-') {
if (renamed_key[1] == '-')
G_asprintf(&err,
_("Please update the usage of <%s>: "
"option <%s> has been renamed to flag <%s>"),
G_program_name(), the_key, renamed_key);
else
G_asprintf(&err,
_("Please update the usage of <%s>: "
"option <%s> has been renamed to flag <%c>"),
G_program_name(), the_key, renamed_key[1]);
append_error(err);
return;
}
/* if renamed to a new option */
for (at_opt = &st->first_option; at_opt;
at_opt = at_opt->next_opt) {
if (strcmp(renamed_key, at_opt->key) == 0) {
G_warning(_("Please update the usage of <%s>: "
"option <%s> has been renamed to <%s>"),
G_program_name(), the_key, renamed_key);
opt = at_opt;
found = 1;
break;
}
}
}
}
/* If there is no match, complain */
if (found == 0) {
G_asprintf(&err, _("%s: Sorry, <%s> is not a valid parameter"),
G_program_name(), the_key);
append_error(err);
return;
}
if (getenv("GRASS_FULL_OPTION_NAMES") && strcmp(the_key, opt->key) != 0)
G_warning(_("<%s> is an abbreviation for <%s>"), the_key, opt->key);
/* Allocate memory where answer is stored */
if (opt->count++) {
if (!opt->multiple) {
G_asprintf(&err, _("Option <%s> does not accept multiple answers"),
opt->key);
append_error(err);
}
opt->answer =
G_realloc(opt->answer, strlen(opt->answer) + strlen(string) + 2);
strcat(opt->answer, ",");
strcat(opt->answer, string);
}
else
opt->answer = G_store(string);
}
void check_opts(void)
{
struct Option *opt;
int ans;
if (!st->n_opts)
return;
opt = &st->first_option;
while (opt) {
/* Check answer against options if any */
if (opt->answer) {
if (opt->multiple == 0)
check_an_opt(opt->key, opt->type, opt->options, opt->opts,
&opt->answer);
else {
for (ans = 0; opt->answers[ans] != NULL; ans++)
check_an_opt(opt->key, opt->type, opt->options, opt->opts,
&opt->answers[ans]);
}
}
/* Check answer against user's check subroutine if any */
if (opt->checker)
opt->checker(opt->answer);
opt = opt->next_opt;
}
}
void check_an_opt(const char *key, int type, const char *options,
const char **opts, char **answerp)
{
const char *answer = *answerp;
int error;
char *err;
int found;
error = 0;
err = NULL;
found = 0;
switch (type) {
case TYPE_INTEGER:
error = check_int(answer, opts);
break;
case TYPE_DOUBLE:
error = check_double(answer, opts);
break;
case TYPE_STRING:
error = check_string(answer, opts, &found);
break;
}
switch (error) {
case 0:
break;
case BAD_SYNTAX:
G_asprintf(&err,
_("Illegal range syntax for parameter <%s>\n"
"\tPresented as: %s"),
key, options);
append_error(err);
break;
case OUT_OF_RANGE:
G_asprintf(&err,
_("Value <%s> out of range for parameter <%s>\n"
"\tLegal range: %s"),
answer, key, options);
append_error(err);
break;
case MISSING_VALUE:
G_asprintf(&err, _("Missing value for parameter <%s>"), key);
append_error(err);
break;
case INVALID_VALUE:
G_asprintf(&err, _("Invalid value <%s> for parameter <%s>"), answer,
key);
append_error(err);
break;
case AMBIGUOUS:
G_asprintf(&err,
_("Value <%s> ambiguous for parameter <%s>\n"
"\tValid options: %s"),
answer, key, options);
append_error(err);
break;
case REPLACED:
*answerp = G_store(opts[found]);
error = 0;
break;
}
}
int check_int(const char *ans, const char **opts)
{
int d, i;
/* "-" is reserved for standard input */
if (strcmp(ans, "-") == 0)
return 0;
if (!ans || !*ans)
return MISSING_VALUE;
if (sscanf(ans, "%d", &d) != 1)
return INVALID_VALUE;
if (!opts)
return 0;
for (i = 0; opts[i]; i++) {
const char *opt = opts[i];
int lo, hi;
if (contains(opt, '-')) {
if (sscanf(opt, "%d-%d", &lo, &hi) == 2) {
if (d >= lo && d <= hi)
return 0;
}
else if (sscanf(opt, "-%d", &hi) == 1) {
if (d <= hi)
return 0;
}
else if (sscanf(opt, "%d-", &lo) == 1) {
if (d >= lo)
return 0;
}
else
return BAD_SYNTAX;
}
else {
if (sscanf(opt, "%d", &lo) == 1) {
if (d == lo)
return 0;
}
else
return BAD_SYNTAX;
}
}
return OUT_OF_RANGE;
}
int check_double(const char *ans, const char **opts)
{
double d;
int i;
/* "-" is reserved for standard input */
if (strcmp(ans, "-") == 0)
return 0;
if (!ans || !*ans)
return MISSING_VALUE;
if (sscanf(ans, "%lf", &d) != 1)
return INVALID_VALUE;
if (!opts)
return 0;
for (i = 0; opts[i]; i++) {
const char *opt = opts[i];
double lo, hi;
if (contains(opt, '-')) {
if (sscanf(opt, "%lf-%lf", &lo, &hi) == 2) {
if (d >= lo && d <= hi)
return 0;
}
else if (sscanf(opt, "-%lf", &hi) == 1) {
if (d <= hi)
return 0;
}
else if (sscanf(opt, "%lf-", &lo) == 1) {
if (d >= lo)
return 0;
}
else
return BAD_SYNTAX;
}
else {
if (sscanf(opt, "%lf", &lo) == 1) {
if (d == lo)
return 0;
}
else
return BAD_SYNTAX;
}
}
return OUT_OF_RANGE;
}
int check_string(const char *ans, const char **opts, int *result)
{
int len = strlen(ans);
int found = 0;
int matches[MAX_MATCHES];
int i;
if (!opts)
return 0;
for (i = 0; opts[i]; i++) {
if (strcmp(ans, opts[i]) == 0)
return 0;
if (strncmp(ans, opts[i], len) == 0 || match_option(ans, opts[i])) {
if (found >= MAX_MATCHES)
G_fatal_error("too many matches (limit %d)", MAX_MATCHES);
matches[found++] = i;
}
}
if (found > 1) {
int shortest = 0;
int length = strlen(opts[matches[0]]);
int prefix = 1;
for (i = 1; i < found; i++) {
int lengthi = strlen(opts[matches[i]]);
if (lengthi < length) {
length = lengthi;
shortest = i;
}
}
for (i = 0; prefix && i < found; i++)
if (strncmp(opts[matches[i]], opts[matches[shortest]], length) != 0)
prefix = 0;
if (prefix) {
matches[0] = matches[shortest];
found = 1;
}
}
if (found == 1)
*result = matches[0];
if (found > 0 && getenv("GRASS_FULL_OPTION_NAMES") &&
strcmp(ans, opts[matches[0]]) != 0)
G_warning(_("<%s> is an abbreviation for <%s>"), ans, opts[matches[0]]);
switch (found) {
case 0:
return OUT_OF_RANGE;
case 1:
return REPLACED;
default:
return AMBIGUOUS;
}
}
void check_required(void)
{
struct Option *opt;
char *err;
err = NULL;
if (!st->n_opts)
return;
opt = &st->first_option;
while (opt) {
if (opt->required && !opt->answer) {
G_asprintf(&err,
_("Required parameter <%s> not set:\n"
"\t(%s)"),
opt->key, (opt->label ? opt->label : opt->description));
append_error(err);
}
opt = opt->next_opt;
}
}
void split_opts(void)
{
struct Option *opt;
const char *ptr1;
const char *ptr2;
int allocated;
int ans_num;
int len;
if (!st->n_opts)
return;
opt = &st->first_option;
while (opt) {
if (/*opt->multiple && */ opt->answer) {
/* Allocate some memory to store array of pointers */
allocated = 10;
opt->answers = G_malloc(allocated * sizeof(char *));
ans_num = 0;
ptr1 = opt->answer;
opt->answers[ans_num] = NULL;
for (;;) {
for (len = 0, ptr2 = ptr1; *ptr2 != '\0' && *ptr2 != ',';
ptr2++, len++)
;
if (len > 0) { /* skip ,, */
opt->answers[ans_num] = G_malloc(len + 1);
memcpy(opt->answers[ans_num], ptr1, len);
opt->answers[ans_num][len] = 0;
ans_num++;
if (ans_num >= allocated) {
allocated += 10;
opt->answers =
G_realloc(opt->answers, allocated * sizeof(char *));
}
opt->answers[ans_num] = NULL;
}
if (*ptr2 == '\0')
break;
ptr1 = ptr2 + 1;
if (*ptr1 == '\0')
break;
}
}
opt = opt->next_opt;
}
}
void check_multiple_opts(void)
{
struct Option *opt;
const char *ptr;
int n_commas;
int n;
char *err;
if (!st->n_opts)
return;
err = NULL;
opt = &st->first_option;
while (opt) {
/* "-" is reserved from standard input/output */
if (opt->answer && strcmp(opt->answer, "-") && opt->key_desc) {
/* count commas */
n_commas = 1;
for (ptr = opt->key_desc; *ptr != '\0'; ptr++)
if (*ptr == ',')
n_commas++;
/* count items */
for (n = 0; opt->answers[n] != NULL; n++)
;
/* if not correct multiple of items */
if (n % n_commas) {
G_asprintf(&err,
_("Option <%s> must be provided in multiples of %d\n"
"\tYou provided %d item(s): %s"),
opt->key, n_commas, n, opt->answer);
append_error(err);
}
}
opt = opt->next_opt;
}
}
/* Check for all 'new' if element already exists */
int check_overwrite(void)
{
struct Option *opt;
char age[KEYLENGTH];
char element[KEYLENGTH];
char desc[KEYLENGTH];
int error = 0;
const char *overstr;
int over;
st->module_info.overwrite = 0;
if (!st->n_opts)
return (0);
over = 0;
/* Check the GRASS OVERWRITE variable */
if ((overstr = G_getenv_nofatal("OVERWRITE"))) {
over = atoi(overstr);
}
/* Check the GRASS_OVERWRITE environment variable */
if ((overstr = getenv("GRASS_OVERWRITE"))) {
if (atoi(overstr))
over = 1;
}
if (st->overwrite || over) {
st->module_info.overwrite = 1;
/* Set the environment so that programs run in a script also obey --o */
putenv("GRASS_OVERWRITE=1");
/* No need to check options for existing files if overwrite is true */
return error;
}
opt = &st->first_option;
while (opt) {
if (opt->answer && opt->gisprompt) {
G__split_gisprompt(opt->gisprompt, age, element, desc);
if (strcmp(age, "new") == 0) {
int i;
char found;
for (i = 0; opt->answers[i]; i++) {
found = FALSE;
if (strcmp(element, "file") == 0) {
if (access(opt->answers[i], F_OK) == 0)
found = TRUE;
}
else if (strcmp(element, "mapset") != 0) {
/* TODO: also other elements should be
probably skipped */
if (G_find_file(element, opt->answers[i], G_mapset())) {
found = TRUE;
}
}
if (found) { /* found */
if (!st->overwrite && !over) {
if (G_verbose() > -1) {
if (G_info_format() != G_INFO_FORMAT_GUI) {
fprintf(stderr, _("ERROR: "));
fprintf(stderr,
_("option <%s>: <%s> exists. To "
"overwrite, use the --overwrite "
"flag"),
opt->key, opt->answers[i]);
fprintf(stderr, "\n");
}
else {
fprintf(stderr, "GRASS_INFO_ERROR(%d,1): ",
getpid());
fprintf(stderr,
_("option <%s>: <%s> exists. To "
"overwrite, use the --overwrite "
"flag"),
opt->key, opt->answers[i]);
fprintf(stderr, "\n");
fprintf(stderr, "GRASS_INFO_END(%d,1)\n",
getpid());
}
}
error = 1;
}
}
}
}
}
opt = opt->next_opt;
}
return (error);
}
void G__split_gisprompt(const char *gisprompt, char *age, char *element,
char *desc)
{
const char *ptr1;
char *ptr2;
for (ptr1 = gisprompt, ptr2 = age; *ptr1 != '\0'; ptr1++, ptr2++) {
if (*ptr1 == ',')
break;
*ptr2 = *ptr1;
}
*ptr2 = '\0';
for (ptr1++, ptr2 = element; *ptr1 != '\0'; ptr1++, ptr2++) {
if (*ptr1 == ',')
break;
*ptr2 = *ptr1;
}
*ptr2 = '\0';
for (ptr1++, ptr2 = desc; *ptr1 != '\0'; ptr1++, ptr2++) {
if (*ptr1 == ',')
break;
*ptr2 = *ptr1;
}
*ptr2 = '\0';
}
void append_error(const char *msg)
{
st->error = G_realloc(st->error, sizeof(char *) * (st->n_errors + 1));
st->error[st->n_errors++] = G_store(msg);
}
const char *get_renamed_option(const char *key)
{
const char *pgm, *key_new;
char *pgm_key;
if (!st->renamed_options) {
/* read renamed options from file (renamed_options) */
char path[GPATH_MAX];
snprintf(path, GPATH_MAX, "%s/etc/renamed_options", G_gisbase());
st->renamed_options = G_read_key_value_file(path);
}
/* try to check global changes first */
key_new = G_find_key_value(key, st->renamed_options);
if (key_new)
return key_new;
/* then check module-relevant changes */
pgm = G_program_name();
pgm_key = (char *)G_malloc(strlen(pgm) + strlen(key) + 2);
G_asprintf(&pgm_key, "%s|%s", pgm, key);
key_new = G_find_key_value(pgm_key, st->renamed_options);
G_free(pgm_key);
return key_new;
}
/*!
\brief Get separator string from the option.
Calls G_fatal_error() on error. Allocated string can be later freed
by G_free().
\code
char *fs;
struct Option *opt_fs;
opt_fs = G_define_standard_option(G_OPT_F_SEP);
if (G_parser(argc, argv))
exit(EXIT_FAILURE);
fs = G_option_to_separator(opt_fs);
\endcode
\param option pointer to separator option
\return allocated string with separator
*/
char *G_option_to_separator(const struct Option *option)
{
char *sep;
if (option->gisprompt == NULL ||
strcmp(option->gisprompt, "old,separator,separator") != 0)
G_fatal_error(_("%s= is not a separator option"), option->key);
if (option->answer == NULL)
G_fatal_error(_("No separator given for %s="), option->key);
if (strcmp(option->answer, "pipe") == 0)
sep = G_store("|");
else if (strcmp(option->answer, "comma") == 0)
sep = G_store(",");
else if (strcmp(option->answer, "space") == 0)
sep = G_store(" ");
else if (strcmp(option->answer, "tab") == 0 ||
strcmp(option->answer, "\\t") == 0)
sep = G_store("\t");
else if (strcmp(option->answer, "newline") == 0 ||
strcmp(option->answer, "\\n") == 0)
sep = G_store("\n");
else
sep = G_store(option->answer);
G_debug(3, "G_option_to_separator(): key = %s -> sep = '%s'", option->key,
sep);
return sep;
}
/*!
\brief Get an input/output file pointer from the option. If the file name is
omitted or '-', it returns either stdin or stdout based on the gisprompt.
Calls G_fatal_error() on error. File pointer can be later closed by
G_close_option_file().
\code
FILE *fp_input;
FILE *fp_output;
struct Option *opt_input;
struct Option *opt_output;
opt_input = G_define_standard_option(G_OPT_F_INPUT);
opt_output = G_define_standard_option(G_OPT_F_OUTPUT);
if (G_parser(argc, argv))
exit(EXIT_FAILURE);
fp_input = G_open_option_file(opt_input);
fp_output = G_open_option_file(opt_output);
...
G_close_option_file(fp_input);
G_close_option_file(fp_output);
\endcode
\param option pointer to a file option
\return file pointer
*/
FILE *G_open_option_file(const struct Option *option)
{
int stdinout;
FILE *fp;
stdinout = !option->answer || !*(option->answer) ||
strcmp(option->answer, "-") == 0;
if (option->gisprompt == NULL)
G_fatal_error(_("%s= is not a file option"), option->key);
else if (option->multiple)
G_fatal_error(_("Opening multiple files not supported for %s="),
option->key);
else if (strcmp(option->gisprompt, "old,file,file") == 0) {
if (stdinout)
fp = stdin;
else if ((fp = fopen(option->answer, "r")) == NULL)
G_fatal_error(_("Unable to open %s file <%s>: %s"), option->key,
option->answer, strerror(errno));
}
else if (strcmp(option->gisprompt, "new,file,file") == 0) {
if (stdinout)
fp = stdout;
else if ((fp = fopen(option->answer, "w")) == NULL)
G_fatal_error(_("Unable to create %s file <%s>: %s"), option->key,
option->answer, strerror(errno));
}
else
G_fatal_error(_("%s= is not a file option"), option->key);
return fp;
}
/*!
\brief Close an input/output file returned by G_open_option_file(). If the
file pointer is stdin, stdout, or stderr, nothing happens.
\param fp file pointer
*/
void G_close_option_file(FILE *fp)
{
if (fp != stdin && fp != stdout && fp != stderr)
fclose(fp);
}
G_free
void G_free(void *buf)
Free allocated memory.
Definition alloc.c:147
G_asprintf
int G_asprintf(char **out, const char *fmt,...)
Definition asprintf.c:68
G_basename
char * G_basename(char *filename, const char *desired_ext)
Truncates filename to the base part (before the last '.') if it matches the extension,...
Definition basename.c:36
NULL
#define NULL
Definition ccmath.h:32
TRUE
#define TRUE
Definition dbfopen.c:56
FALSE
#define FALSE
Definition dbfopen.c:55
G_debug
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition debug.c:66
G_getenv_nofatal
const char * G_getenv_nofatal(const char *name)
Get environment variable.
Definition env.c:405
G_find_file
const char * G_find_file(const char *element, char *name, const char *mapset)
Searches for a file from the mapset search list or in a specified mapset.
Definition find_file.c:186
G_fatal_error
void G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
Definition gis/error.c:159
G_suppress_warnings
int G_suppress_warnings(int flag)
Suppress printing a warning message to stderr.
Definition gis/error.c:222
G_warning
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition gis/error.c:203
G_info_format
int G_info_format(void)
Get current message format.
Definition gis/error.c:540
G_gisbase
const char * G_gisbase(void)
Get full path name of the top level module directory.
Definition gisbase.c:39
G_find_key_value
const char * G_find_key_value(const char *key, const struct Key_Value *kv)
Find given key (case sensitive).
Definition key_value1.c:85
G_read_key_value_file
struct Key_Value * G_read_key_value_file(const char *file)
Read key/values pairs from file.
Definition key_value3.c:55
G_mapset
const char * G_mapset(void)
Get current mapset name.
Definition mapset.c:33
G_define_module
struct GModule * G_define_module(void)
Initializes a new module.
Definition parser.c:255
G__print_keywords
void G__print_keywords(FILE *fd, void(*format)(FILE *, const char *), int newline)
Print list of keywords (internal use only).
Definition parser.c:929
G_define_flag
struct Flag * G_define_flag(void)
Initializes a Flag struct.
Definition parser.c:156
G_parser
int G_parser(int argc, char **argv)
Parse command line.
Definition parser.c:320
G_set_keywords
void G_set_keywords(const char *keywords)
Set keywords from the string.
Definition parser.c:884
G_open_option_file
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 '-',...
Definition parser.c:1922
G__uses_new_gisprompt
int G__uses_new_gisprompt(void)
Definition parser.c:892
opt_error
opt_error
Definition parser.c:91
OUT_OF_RANGE
@ OUT_OF_RANGE
Definition parser.c:93
BAD_SYNTAX
@ BAD_SYNTAX
Definition parser.c:92
REPLACED
@ REPLACED
Definition parser.c:97
AMBIGUOUS
@ AMBIGUOUS
Definition parser.c:96
INVALID_VALUE
@ INVALID_VALUE
Definition parser.c:95
MISSING_VALUE
@ MISSING_VALUE
Definition parser.c:94
G_add_keyword
void G_add_keyword(const char *keyword)
Add keyword to the list.
Definition parser.c:868
G_get_overwrite
int G_get_overwrite(void)
Get overwrite value.
Definition parser.c:959
G_option_to_separator
char * G_option_to_separator(const struct Option *option)
Get separator string from the option.
Definition parser.c:1860
recreate_command
char * recreate_command(int original_path)
Creates command to run non-interactive.
Definition parser.c:680
G_close_option_file
void G_close_option_file(FILE *fp)
Close an input/output file returned by G_open_option_file(). If the file pointer is stdin,...
Definition parser.c:1961
G_recreate_command
char * G_recreate_command(void)
Creates command to run non-interactive.
Definition parser.c:840
G_define_option
struct Option * G_define_option(void)
Initializes an Option struct.
Definition parser.c:210
G_disable_interactive
void G_disable_interactive(void)
Disables the ability of the parser to operate interactively.
Definition parser.c:139
G_recreate_command_original_path
char * G_recreate_command_original_path(void)
Creates command to run non-interactive.
Definition parser.c:858
G__split_gisprompt
void G__split_gisprompt(const char *gisprompt, char *age, char *element, char *desc)
Definition parser.c:1775
MAX_MATCHES
#define MAX_MATCHES
Definition parser.c:100
G__check_option_rules
void G__check_option_rules(void)
Check for option rules (internal use only).
Definition parser_dependencies.c:403
G__has_required_rule
int G__has_required_rule(void)
Checks if there is any rule RULE_REQUIRED (internal use only).
Definition parser_dependencies.c:481
G_usage
void G_usage(void)
Command line help/usage message.
Definition parser_help.c:48
G__usage_text
void G__usage_text(void)
Definition parser_help.c:53
G__usage_html
void G__usage_html(void)
Print module usage description in HTML format.
Definition parser_html.c:29
G__usage_xml
void G__usage_xml(void)
Print module usage description in XML format.
Definition parser_interface.c:103
G__json
char * G__json(void)
This function generates actinia JSON process chain building blocks from the command line arguments th...
Definition parser_json.c:193
G__usage_markdown
void G__usage_markdown(void)
Print module usage description in Markdown format.
Definition parser_md.c:25
G__usage_rest
void G__usage_rest(void)
Print module usage description in reStructuredText format.
Definition parser_rest.c:27
G__script
void G__script(void)
Generate Python script-like output.
Definition parser_script.c:24
G__wps_print_process_description
void G__wps_print_process_description(void)
Print the WPS 1.0.0 process description XML document to stdout.
Definition parser_wps.c:156
strcpy
#define strcpy
Definition parson.c:66
G_is_dirsep
int G_is_dirsep(char c)
Checks if a specified character is a valid directory separator character on the host system.
Definition paths.c:45
G_program_name
const char * G_program_name(void)
Return module name.
Definition progrm_nme.c:28
G_original_program_name
const char * G_original_program_name(void)
Return original path of the executed program.
Definition progrm_nme.c:46
G_spawn
int G_spawn(const char *command,...)
Spawn new process based on command.
Definition spawn.c:920
G_chop
char * G_chop(char *line)
Chop leading and trailing white spaces.
Definition strings.c:332
G_strcasecmp
int G_strcasecmp(const char *x, const char *y)
String compare ignoring case (upper or lower).
Definition strings.c:47
G_store
char * G_store(const char *s)
Copy string to allocated memory.
Definition strings.c:87
element
Definition lidar.h:85
path
Definition path.h:15
err
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)
Definition symbol/read.c:216
G_free_tokens
void G_free_tokens(char **tokens)
Free memory allocated to tokens.
Definition token.c:197
G_tokenize
char ** G_tokenize(const char *buf, const char *delim)
Tokenize string.
Definition token.c:47
G_number_of_tokens
int G_number_of_tokens(char **tokens)
Return number of tokens.
Definition token.c:178
G_verbose_max
int G_verbose_max(void)
Get max verbosity level.
Definition verbose.c:81
G_verbose
int G_verbose(void)
Get current verbosity level.
Definition verbose.c:60
G_verbose_min
int G_verbose_min(void)
Get min verbosity level.
Definition verbose.c:101
G_verbose_std
int G_verbose_std(void)
Get standard verbosity level.
Definition verbose.c:91
G_zero
void G_zero(void *buf, int i)
Zero out a buffer, buf, of length i.
Definition zero.c:23