1 /*!
2 * \file lib/gis/parser.c
3 *
4 * \brief GIS Library - Argument parsing functions.
5 *
6 * Parses the command line provided through argc and argv. Example:
7 * Assume the previous calls:
8 *
9 \code
10 opt1 = G_define_option() ;
11 opt1->key = "map",
12 opt1->type = TYPE_STRING,
13 opt1->required = YES,
14 opt1->checker = sub,
15 opt1->description= "Name of an existing raster map" ;
16
17 opt2 = G_define_option() ;
18 opt2->key = "color",
19 opt2->type = TYPE_STRING,
20 opt2->required = NO,
21 opt2->answer = "white",
22 opt2->options = "red,orange,blue,white,black",
23 opt2->description= "Color used to display the map" ;
24
25 opt3 = G_define_option() ;
26 opt3->key = "number",
27 opt3->type = TYPE_DOUBLE,
28 opt3->required = NO,
29 opt3->answer = "12345.67",
30 opt3->options = "0-99999",
31 opt3->description= "Number to test parser" ;
32 \endcode
33 *
34 * G_parser() will respond to the following command lines as described:
35 *
36 \verbatim
37 command (No command line arguments)
38 \endverbatim
39 * Parser enters interactive mode.
40 *
41 \verbatim
42 command map=map.name
43 \endverbatim
44 * Parser will accept this line. Map will be set to "map.name", the
45 * 'a' and 'b' flags will remain off and the num option will be set
46 * to the default of 5.
47 *
48 \verbatim
49 command -ab map=map.name num=9
50 command -a -b map=map.name num=9
51 command -ab map.name num=9
52 command map.name num=9 -ab
53 command num=9 -a map=map.name -b
54 \endverbatim
55 * These are all treated as acceptable and identical. Both flags are
56 * set to on, the map option is "map.name" and the num option is "9".
57 * Note that the "map=" may be omitted from the command line if it
58 * is part of the first option (flags do not count).
59 *
60 \verbatim
61 command num=12
62 \endverbatim
63 * This command line is in error in two ways. The user will be told
64 * that the "map" option is required and also that the number 12 is
65 * out of range. The acceptable range (or list) will be printed.
66 *
67 * Overview table: <a href="parser_standard_options.html">Parser standard options</a>
68 *
69 * (C) 2001-2015 by the GRASS Development Team
70 *
71 * This program is free software under the GNU General Public License
72 * (>=v2). Read the file COPYING that comes with GRASS for details.
73 *
74 * \author Original author CERL
75 * \author Soeren Gebbert added Dec. 2009 WPS process_description document
76 */
77
78 #include <stdio.h>
79 #include <stdlib.h>
80 #include <string.h>
81 #include <unistd.h>
82
83 #include <grass/gis.h>
84 #include <grass/spawn.h>
85 #include <grass/glocale.h>
86
87 #include "parser_local_proto.h"
88
89 enum opt_error {
90 BAD_SYNTAX = 1,
91 OUT_OF_RANGE = 2,
92 MISSING_VALUE = 3,
93 INVALID_VALUE = 4,
94 AMBIGUOUS = 5,
95 REPLACED = 6
96 };
97
98
99 #define MAX_MATCHES 50
100
101 /* initialize the global struct */
102 struct state state;
103 struct state *st = &state;
104
105 /* local prototypes */
106 static void set_flag(int);
107 static int contains(const char *, int);
108 static int valid_option_name(const char *);
109 static int is_option(const char *);
110 static int match_option_1(const char *, const char *);
111 static int match_option(const char *, const char *);
112 static void set_option(const char *);
113 static void check_opts(void);
114 static void check_an_opt(const char *, int, const char *, const char **, char **);
115 static int check_int(const char *, const char **);
116 static int check_double(const char *, const char **);
117 static int check_string(const char *, const char **, int *);
118 static void check_required(void);
119 static void split_opts(void);
120 static void check_multiple_opts(void);
121 static int check_overwrite(void);
122 static void define_keywords(void);
123 static int module_gui_wx(void);
124 static void append_error(const char *);
125 static const char *get_renamed_option(const char *);
126
127 /*!
128 * \brief Disables the ability of the parser to operate interactively.
129 *
130 * When a user calls a command with no arguments on the command line,
131 * the parser will enter its own standardized interactive session in
132 * which all flags and options are presented to the user for input. A
133 * call to G_disable_interactive() disables the parser's interactive
134 * prompting.
135 *
136 */
137
G_disable_interactive(void)138 void G_disable_interactive(void)
139 {
140 st->no_interactive = 1;
141 }
142
143 /*!
144 * \brief Initializes a Flag struct.
145 *
146 * Allocates memory for the Flag structure and returns a pointer to
147 * this memory.
148 *
149 * Flags are always represented by single letters. A user "turns them
150 * on" at the command line using a minus sign followed by the
151 * character representing the flag.
152 *
153 * \return Pointer to a Flag struct
154 */
G_define_flag(void)155 struct Flag *G_define_flag(void)
156 {
157 struct Flag *flag;
158 struct Item *item;
159
160 /* Allocate memory if not the first flag */
161
162 if (st->n_flags) {
163 flag = G_malloc(sizeof(struct Flag));
164 st->current_flag->next_flag = flag;
165 }
166 else
167 flag = &st->first_flag;
168
169 /* Zero structure */
170
171 G_zero(flag, sizeof(struct Flag));
172
173 st->current_flag = flag;
174 st->n_flags++;
175
176 if (st->n_items) {
177 item = G_malloc(sizeof(struct Item));
178 st->current_item->next_item = item;
179 }
180 else
181 item = &st->first_item;
182
183 G_zero(item, sizeof(struct Item));
184
185 item->flag = flag;
186 item->option = NULL;
187
188 st->current_item = item;
189 st->n_items++;
190
191 return (flag);
192 }
193
194 /*!
195 * \brief Initializes an Option struct.
196 *
197 * Allocates memory for the Option structure and returns a pointer to
198 * this memory.
199 *
200 * Options are provided by user on command line using the standard
201 * format: <i>key=value</i>. Options identified as REQUIRED must be
202 * specified by user on command line. The option string can either
203 * specify a range of values (e.g. "10-100") or a list of acceptable
204 * values (e.g. "red,orange,yellow"). Unless the option string is
205 * NULL, user provided input will be evaluated against this string.
206 *
207 * \return pointer to an Option struct
208 */
G_define_option(void)209 struct Option *G_define_option(void)
210 {
211 struct Option *opt;
212 struct Item *item;
213
214 /* Allocate memory if not the first option */
215
216 if (st->n_opts) {
217 opt = G_malloc(sizeof(struct Option));
218 st->current_option->next_opt = opt;
219 }
220 else
221 opt = &st->first_option;
222
223 /* Zero structure */
224 G_zero(opt, sizeof(struct Option));
225
226 opt->required = NO;
227 opt->multiple = NO;
228
229 st->current_option = opt;
230 st->n_opts++;
231
232 if (st->n_items) {
233 item = G_malloc(sizeof(struct Item));
234 st->current_item->next_item = item;
235 }
236 else
237 item = &st->first_item;
238
239 G_zero(item, sizeof(struct Item));
240
241 item->option = opt;
242
243 st->current_item = item;
244 st->n_items++;
245
246 return (opt);
247 }
248
249 /*!
250 * \brief Initializes a new module.
251 *
252 * \return pointer to a GModule struct
253 */
G_define_module(void)254 struct GModule *G_define_module(void)
255 {
256 struct GModule *module;
257
258 /* Allocate memory */
259 module = &st->module_info;
260
261 /* Zero structure */
262 G_zero(module, sizeof(struct GModule));
263
264 /* Allocate keywords array */
265 define_keywords();
266
267 return (module);
268 }
269
270 /*!
271 * \brief Parse command line.
272 *
273 * The command line parameters <i>argv</i> and the number of
274 * parameters <i>argc</i> from the main() routine are passed directly
275 * to G_parser(). G_parser() accepts the command line input entered by
276 * the user, and parses this input according to the input options
277 * and/or flags that were defined by the programmer.
278 *
279 * <b>Note:</b> The only functions which can legitimately be called
280 * before G_parser() are:
281 *
282 * - G_gisinit()
283 * - G_no_gisinit()
284 * - G_define_module()
285 * - G_define_flag()
286 * - G_define_option()
287 * - G_define_standard_flag()
288 * - G_define_standard_option()
289 * - G_disable_interactive()
290 * - G_option_exclusive()
291 * - G_option_required()
292 * - G_option_requires()
293 * - G_option_requires_all()
294 * - G_option_excludes()
295 * - G_option_collective()
296 *
297 * The usual order a module calls functions is:
298 *
299 * 1. G_gisinit()
300 * 2. G_define_module()
301 * 3. G_define_standard_flag()
302 * 4. G_define_standard_option()
303 * 5. G_define_flag()
304 * 6. G_define_option()
305 * 7. G_option_exclusive()
306 * 8. G_option_required()
307 * 9. G_option_requires()
308 * 10. G_option_requires_all()
309 * 11. G_option_excludes()
310 * 12. G_option_collective()
311 * 13. G_parser()
312 *
313 * \param argc number of arguments
314 * \param argv argument list
315 *
316 * \return 0 on success
317 * \return -1 on error and calls G_usage()
318 */
G_parser(int argc,char ** argv)319 int G_parser(int argc, char **argv)
320 {
321 int need_first_opt;
322 int opt_checked = 0;
323 const char *gui_envvar;
324 char *ptr, *tmp_name, *err;
325 int i;
326 struct Option *opt;
327 char force_gui = FALSE;
328 int print_json = 0;
329
330 err = NULL;
331 need_first_opt = 1;
332 tmp_name = G_store(argv[0]);
333 st->pgm_path = tmp_name;
334 st->n_errors = 0;
335 st->error = NULL;
336 st->module_info.verbose = G_verbose_std();
337 i = strlen(tmp_name);
338 while (--i >= 0) {
339 if (G_is_dirsep(tmp_name[i])) {
340 tmp_name += i + 1;
341 break;
342 }
343 }
344 G_basename(tmp_name, "exe");
345 st->pgm_name = tmp_name;
346
347 if (!st->module_info.label && !st->module_info.description)
348 G_warning(_("Bug in UI description. Missing module description"));
349
350 /* Stash default answers */
351
352 opt = &st->first_option;
353 while (st->n_opts && opt) {
354 if (opt->required)
355 st->has_required = 1;
356
357 if (!opt->key)
358 G_warning(_("Bug in UI description. Missing option key"));
359 if (!valid_option_name(opt->key))
360 G_warning(_("Bug in UI description. Option key <%s> is not valid"), opt->key);
361 if (!opt->label && !opt->description)
362 G_warning(_("Bug in UI description. Description for option <%s> missing"), opt->key ? opt->key : "?");
363
364 /* Parse options */
365 if (opt->options) {
366 int cnt = 0;
367 char **tokens, delm[2];
368
369 delm[0] = ',';
370 delm[1] = '\0';
371 tokens = G_tokenize(opt->options, delm);
372
373 i = 0;
374 while (tokens[i]) {
375 G_chop(tokens[i]);
376 cnt++;
377 i++;
378 }
379
380 opt->opts = G_calloc(cnt + 1, sizeof(const char *));
381
382 i = 0;
383 while (tokens[i]) {
384 opt->opts[i] = G_store(tokens[i]);
385 i++;
386 }
387 G_free_tokens(tokens);
388
389 if (opt->descriptions) {
390 delm[0] = ';';
391
392 opt->descs = G_calloc(cnt + 1, sizeof(const char *));
393 tokens = G_tokenize(opt->descriptions, delm);
394
395 i = 0;
396 while (tokens[i]) {
397 int j, found;
398
399 if (!tokens[i + 1])
400 break;
401
402 G_chop(tokens[i]);
403
404 j = 0;
405 found = 0;
406 while (opt->opts[j]) {
407 if (strcmp(opt->opts[j], tokens[i]) == 0) {
408 found = 1;
409 break;
410 }
411 j++;
412 }
413 if (!found) {
414 G_warning(_("Bug in UI description. Option '%s' in <%s> does not exist"),
415 tokens[i], opt->key);
416 }
417 else {
418 opt->descs[j] = G_store(tokens[i + 1]);
419 }
420
421 i += 2;
422 }
423 G_free_tokens(tokens);
424 }
425 }
426
427 /* Copy answer */
428 if (opt->multiple && opt->answers && opt->answers[0]) {
429 opt->answer = G_malloc(strlen(opt->answers[0]) + 1);
430 strcpy(opt->answer, opt->answers[0]);
431 for (i = 1; opt->answers[i]; i++) {
432 opt->answer = G_realloc(opt->answer,
433 strlen(opt->answer) +
434 strlen(opt->answers[i]) + 2);
435 strcat(opt->answer, ",");
436 strcat(opt->answer, opt->answers[i]);
437 }
438 }
439 opt->def = opt->answer;
440 opt = opt->next_opt;
441 }
442
443 /* If there are NO arguments, go interactive */
444 gui_envvar = G_getenv_nofatal("GUI");
445 if (argc < 2 && (st->has_required || G__has_required_rule())
446 && !st->no_interactive && isatty(0) &&
447 (gui_envvar && G_strcasecmp(gui_envvar, "text") != 0)) {
448 if (module_gui_wx() == 0)
449 return -1;
450 }
451
452 if (argc < 2 && st->has_required && isatty(0)) {
453 G_usage();
454 return -1;
455 }
456 else if (argc >= 2) {
457
458 /* If first arg is "help" give a usage/syntax message */
459 if (strcmp(argv[1], "help") == 0 ||
460 strcmp(argv[1], "-help") == 0 || strcmp(argv[1], "--help") == 0) {
461 G_usage();
462 exit(EXIT_SUCCESS);
463 }
464
465 /* If first arg is "--help-text" give a usage/syntax message
466 * with machine-readable sentinels */
467 if (strcmp(argv[1], "--help-text") == 0) {
468 G__usage_text();
469 exit(EXIT_SUCCESS);
470 }
471
472 /* If first arg is "--interface-description" then print out
473 * a xml description of the task */
474 if (strcmp(argv[1], "--interface-description") == 0) {
475 G__usage_xml();
476 exit(EXIT_SUCCESS);
477 }
478
479 /* If first arg is "--html-description" then print out
480 * a html description of the task */
481 if (strcmp(argv[1], "--html-description") == 0) {
482 G__usage_html();
483 exit(EXIT_SUCCESS);
484 }
485
486 /* If first arg is "--rst-description" then print out
487 * a reStructuredText description of the task */
488 if (strcmp(argv[1], "--rst-description") == 0) {
489 G__usage_rest();
490 exit(EXIT_SUCCESS);
491 }
492
493 /* If first arg is "--wps-process-description" then print out
494 * the wps process description of the task */
495 if (strcmp(argv[1], "--wps-process-description") == 0) {
496 G__wps_print_process_description();
497 exit(EXIT_SUCCESS);
498 }
499
500 /* If first arg is "--script" then then generate
501 * g.parser boilerplate */
502 if (strcmp(argv[1], "--script") == 0) {
503 G__script();
504 exit(EXIT_SUCCESS);
505 }
506
507 /* Loop through all command line arguments */
508
509 while (--argc) {
510 ptr = *(++argv);
511
512 if (strcmp(ptr, "help") == 0 || strcmp(ptr, "--h") == 0 ||
513 strcmp(ptr, "-help") == 0 || strcmp(ptr, "--help") == 0) {
514 G_usage();
515 exit(EXIT_SUCCESS);
516 }
517
518 /* JSON print option */
519 if (strcmp(ptr, "--json") == 0) {
520 print_json = 1;
521 continue;
522 }
523
524 /* Overwrite option */
525 if (strcmp(ptr, "--o") == 0 || strcmp(ptr, "--overwrite") == 0) {
526 st->overwrite = 1;
527 }
528
529 /* Verbose option */
530 else if (strcmp(ptr, "--v") == 0 || strcmp(ptr, "--verbose") == 0) {
531 char buff[32];
532
533 /* print everything: max verbosity level */
534 st->module_info.verbose = G_verbose_max();
535 sprintf(buff, "GRASS_VERBOSE=%d", G_verbose_max());
536 putenv(G_store(buff));
537 if (st->quiet == 1) {
538 G_warning(_("Use either --quiet or --verbose flag, not both. Assuming --verbose."));
539 }
540 st->quiet = -1;
541 }
542
543 /* Quiet option */
544 else if (strcmp(ptr, "--q") == 0 || strcmp(ptr, "--quiet") == 0) {
545 char buff[32];
546
547 /* print nothing, but errors and warnings */
548 st->module_info.verbose = G_verbose_min();
549 sprintf(buff, "GRASS_VERBOSE=%d", G_verbose_min());
550 putenv(G_store(buff));
551 if (st->quiet == -1) {
552 G_warning(_("Use either --quiet or --verbose flag, not both. Assuming --quiet."));
553 }
554 st->quiet = 1; /* for passing to gui init */
555 }
556
557 /* Super quiet option */
558 else if (strcmp(ptr, "--qq") == 0 ) {
559 char buff[32];
560
561 /* print nothing, but errors */
562 st->module_info.verbose = G_verbose_min();
563 sprintf(buff, "GRASS_VERBOSE=%d", G_verbose_min());
564 putenv(G_store(buff));
565 G_suppress_warnings(TRUE);
566 if (st->quiet == -1) {
567 G_warning(_("Use either --qq or --verbose flag, not both. Assuming --qq."));
568 }
569 st->quiet = 1; /* for passing to gui init */
570 }
571
572 /* Force gui to come up */
573 else if (strcmp(ptr, "--ui") == 0) {
574 force_gui = TRUE;
575 }
576
577 /* If we see a flag */
578 else if (*ptr == '-') {
579 while (*(++ptr))
580 set_flag(*ptr);
581
582 }
583 /* If we see standard option format (option=val) */
584 else if (is_option(ptr)) {
585 set_option(ptr);
586 need_first_opt = 0;
587 }
588
589 /* If we see the first option with no equal sign */
590 else if (need_first_opt && st->n_opts) {
591 st->first_option.answer = G_store(ptr);
592 st->first_option.count++;
593 need_first_opt = 0;
594 }
595
596 /* If we see the non valid argument (no "=", just argument) */
597 else {
598 G_asprintf(&err, _("Sorry <%s> is not a valid option"), ptr);
599 append_error(err);
600 }
601
602 }
603 }
604
605 /* Split options where multiple answers are OK */
606 split_opts();
607
608 /* Run the gui if it was specifically requested */
609 if (force_gui) {
610 if (module_gui_wx() != 0)
611 G_fatal_error(_("Your installation doesn't include GUI, exiting."));
612 return -1;
613 }
614
615 /* Check multiple options */
616 check_multiple_opts();
617
618 /* Check answers against options and check subroutines */
619 if (!opt_checked)
620 check_opts();
621
622 /* Make sure all required options are set */
623 if (!st->suppress_required)
624 check_required();
625
626 G__check_option_rules();
627
628 if (st->n_errors > 0) {
629 if (G_verbose() > -1) {
630 if (G_verbose() > G_verbose_min())
631 G_usage();
632 fprintf(stderr, "\n");
633 for (i = 0; i < st->n_errors; i++) {
634 fprintf(stderr, "%s: %s\n", _("ERROR"), st->error[i]);
635 }
636 }
637 return -1;
638 }
639
640 /* Print the JSON definition of the command and exit */
641 if(print_json == 1) {
642 G__json();
643 exit(EXIT_SUCCESS);
644 }
645
646 if (!st->suppress_overwrite) {
647 if (check_overwrite())
648 return -1;
649 }
650
651 return 0;
652 }
653
654 /*!
655 * \brief Creates command to run non-interactive.
656 *
657 * Creates a command-line that runs the current command completely
658 * non-interactive.
659 *
660 * \param original_path TRUE if original path should be used, FALSE for
661 * stripped and clean name of the module
662 * \return pointer to a char string
663 */
recreate_command(int original_path)664 char *recreate_command(int original_path)
665 {
666 char *buff;
667 char flg[4];
668 char *cur;
669 const char *tmp;
670 struct Flag *flag;
671 struct Option *opt;
672 int n, len, slen;
673 int nalloced = 0;
674
675 G_debug(3, "G_recreate_command()");
676
677 /* Flag is not valid if there are no flags to set */
678
679 buff = G_calloc(1024, sizeof(char));
680 nalloced += 1024;
681 if (original_path)
682 tmp = G_original_program_name();
683 else
684 tmp = G_program_name();
685 len = strlen(tmp);
686 if (len >= nalloced) {
687 nalloced += (1024 > len) ? 1024 : len + 1;
688 buff = G_realloc(buff, nalloced);
689 }
690 cur = buff;
691 strcpy(cur, tmp);
692 cur += len;
693
694 if (st->overwrite) {
695 slen = strlen(" --overwrite");
696 if (len + slen >= nalloced) {
697 nalloced += (1024 > len) ? 1024 : len + 1;
698 buff = G_realloc(buff, nalloced);
699 }
700 strcpy(cur, " --overwrite");
701 cur += slen;
702 len += slen;
703 }
704
705 if (st->module_info.verbose != G_verbose_std()) {
706 char *sflg;
707 if (st->module_info.verbose == G_verbose_max())
708 sflg = " --verbose";
709 else
710 sflg = " --quiet";
711
712 slen = strlen(sflg);
713 if (len + slen >= nalloced) {
714 nalloced += (1024 > len) ? 1024 : len + 1;
715 buff = G_realloc(buff, nalloced);
716 }
717 strcpy(cur, sflg);
718 cur += slen;
719 len += slen;
720 }
721
722 if (st->n_flags) {
723 flag = &st->first_flag;
724 while (flag) {
725 if (flag->answer == 1) {
726 flg[0] = ' ';
727 flg[1] = '-';
728 flg[2] = flag->key;
729 flg[3] = '\0';
730 slen = strlen(flg);
731 if (len + slen >= nalloced) {
732 nalloced +=
733 (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
734 buff = G_realloc(buff, nalloced);
735 cur = buff + len;
736 }
737 strcpy(cur, flg);
738 cur += slen;
739 len += slen;
740 }
741 flag = flag->next_flag;
742 }
743 }
744
745 opt = &st->first_option;
746 while (st->n_opts && opt) {
747 if (opt->answer && opt->answer[0] == '\0') { /* answer = "" */
748 slen = strlen(opt->key) + 4; /* +4 for: ' ' = " " */
749 if (len + slen >= nalloced) {
750 nalloced += (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
751 buff = G_realloc(buff, nalloced);
752 cur = buff + len;
753 }
754 strcpy(cur, " ");
755 cur++;
756 strcpy(cur, opt->key);
757 cur = strchr(cur, '\0');
758 strcpy(cur, "=");
759 cur++;
760 if (opt->type == TYPE_STRING) {
761 strcpy(cur, "\"\"");
762 cur += 2;
763 }
764 len = cur - buff;
765 } else if (opt->answer && opt->answers && opt->answers[0]) {
766 slen = strlen(opt->key) + strlen(opt->answers[0]) + 4; /* +4 for: ' ' = " " */
767 if (len + slen >= nalloced) {
768 nalloced += (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
769 buff = G_realloc(buff, nalloced);
770 cur = buff + len;
771 }
772 strcpy(cur, " ");
773 cur++;
774 strcpy(cur, opt->key);
775 cur = strchr(cur, '\0');
776 strcpy(cur, "=");
777 cur++;
778 if (opt->type == TYPE_STRING) {
779 strcpy(cur, "\"");
780 cur++;
781 }
782 strcpy(cur, opt->answers[0]);
783 cur = strchr(cur, '\0');
784 len = cur - buff;
785 for (n = 1; opt->answers[n]; n++) {
786 if (!opt->answers[n])
787 break;
788 slen = strlen(opt->answers[n]) + 2; /* +2 for , " */
789 if (len + slen >= nalloced) {
790 nalloced +=
791 (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
792 buff = G_realloc(buff, nalloced);
793 cur = buff + len;
794 }
795 strcpy(cur, ",");
796 cur++;
797 strcpy(cur, opt->answers[n]);
798 cur = strchr(cur, '\0');
799 len = cur - buff;
800 }
801 if (opt->type == TYPE_STRING) {
802 strcpy(cur, "\"");
803 cur++;
804 len = cur - buff;
805 }
806 }
807 opt = opt->next_opt;
808 }
809
810 return buff;
811 }
812
813 /*!
814 * \brief Creates command to run non-interactive.
815 *
816 * Creates a command-line that runs the current command completely
817 * non-interactive.
818 *
819 * \return pointer to a char string
820 */
G_recreate_command(void)821 char *G_recreate_command(void)
822 {
823 return recreate_command(FALSE);
824 }
825
826 /* TODO: update to docs of these 3 functions to whatever general purpose
827 * they have now. */
828 /*!
829 * \brief Creates command to run non-interactive.
830 *
831 * Creates a command-line that runs the current command completely
832 * non-interactive.
833 *
834 * This gives the same as G_recreate_command() but the original path
835 * from the command line is used instead of the module name only.
836 *
837 * \return pointer to a char string
838 */
G_recreate_command_original_path(void)839 char *G_recreate_command_original_path(void)
840 {
841 return recreate_command(TRUE);
842 }
843
844 /*!
845 \brief Add keyword to the list
846
847 \param keyword keyword string
848 */
G_add_keyword(const char * keyword)849 void G_add_keyword(const char *keyword)
850 {
851 if (st->n_keys >= st->n_keys_alloc) {
852 st->n_keys_alloc += 10;
853 st->module_info.keywords = G_realloc(st->module_info.keywords,
854 st->n_keys_alloc * sizeof(char *));
855 }
856
857 st->module_info.keywords[st->n_keys++] = G_store(keyword);
858 }
859
860 /*!
861 \brief Set keywords from the string
862
863 \param keywords keywords separated by commas
864 */
G_set_keywords(const char * keywords)865 void G_set_keywords(const char *keywords)
866 {
867 char **tokens = G_tokenize(keywords, ",");
868 st->module_info.keywords = (const char **)tokens;
869 st->n_keys = st->n_keys_alloc = G_number_of_tokens(tokens);
870 }
871
872
G__uses_new_gisprompt(void)873 int G__uses_new_gisprompt(void)
874 {
875 struct Option *opt;
876 char age[KEYLENGTH];
877 char element[KEYLENGTH];
878 char desc[KEYLENGTH];
879
880 if (st->module_info.overwrite)
881 return 1;
882
883 /* figure out if any of the options use a "new" gisprompt */
884 /* This is to see if we should spit out the --o flag */
885 if (st->n_opts) {
886 opt = &st->first_option;
887 while (opt) {
888 if (opt->gisprompt) {
889 G__split_gisprompt(opt->gisprompt, age, element, desc);
890 if (strcmp(age, "new") == 0)
891 return 1;
892 }
893 opt = opt->next_opt;
894 }
895 }
896
897 return 0;
898 }
899
900 /*!
901 \brief Print list of keywords (internal use only)
902
903 If <em>format</em> function is NULL than list of keywords is printed
904 comma-separated.
905
906 \param[out] fd file where to print
907 \param format pointer to print function
908 */
G__print_keywords(FILE * fd,void (* format)(FILE *,const char *))909 void G__print_keywords(FILE *fd, void (*format)(FILE *, const char *))
910 {
911 int i;
912
913 for(i = 0; i < st->n_keys; i++) {
914 if (!format) {
915 fprintf(fd, "%s", st->module_info.keywords[i]);
916 }
917 else {
918 format(fd, st->module_info.keywords[i]);
919 }
920 if (i < st->n_keys - 1)
921 fprintf(fd, ", ");
922 }
923
924 fflush(fd);
925 }
926
927 /*!
928 \brief Get overwrite value
929
930 \return 1 overwrite enabled
931 \return 0 overwrite disabled
932 */
G_get_overwrite()933 int G_get_overwrite()
934 {
935 return st->module_info.overwrite;
936 }
937
define_keywords(void)938 void define_keywords(void)
939 {
940 st->n_keys = 0;
941 st->n_keys_alloc = 0;
942 }
943
944 /**************************************************************************
945 *
946 * The remaining routines are all local (static) routines used to support
947 * the parsing process.
948 *
949 **************************************************************************/
950
951 /*!
952 \brief Invoke GUI dialog
953 */
module_gui_wx(void)954 int module_gui_wx(void)
955 {
956 char script[GPATH_MAX];
957
958 /* TODO: the 4 following lines seems useless */
959 if (!st->pgm_path)
960 st->pgm_path = G_program_name();
961 if (!st->pgm_path)
962 G_fatal_error(_("Unable to determine program name"));
963
964 sprintf(script, "%s/gui/wxpython/gui_core/forms.py",
965 getenv("GISBASE"));
966 if (access(script, F_OK) != -1)
967 G_spawn(getenv("GRASS_PYTHON"), getenv("GRASS_PYTHON"),
968 script, G_recreate_command_original_path(), NULL);
969 else
970 return -1;
971
972 return 0;
973 }
974
set_flag(int f)975 void set_flag(int f)
976 {
977 struct Flag *flag;
978 char *err;
979
980 err = NULL;
981
982 /* Flag is not valid if there are no flags to set */
983 if (!st->n_flags) {
984 G_asprintf(&err, _("%s: Sorry, <%c> is not a valid flag"), G_program_name(), f);
985 append_error(err);
986 return;
987 }
988
989 /* Find flag with corrrect keyword */
990 flag = &st->first_flag;
991 while (flag) {
992 if (flag->key == f) {
993 flag->answer = 1;
994 if (flag->suppress_required)
995 st->suppress_required = 1;
996 if (flag->suppress_overwrite)
997 st->suppress_overwrite = 1;
998 return;
999 }
1000 flag = flag->next_flag;
1001 }
1002
1003 G_asprintf(&err, _("%s: Sorry, <%c> is not a valid flag"), G_program_name(), f);
1004 append_error(err);
1005 }
1006
1007 /* contents() is used to find things strings with characters like commas and
1008 * dashes.
1009 */
contains(const char * s,int c)1010 int contains(const char *s, int c)
1011 {
1012 while (*s) {
1013 if (*s == c)
1014 return TRUE;
1015 s++;
1016 }
1017 return FALSE;
1018 }
1019
valid_option_name(const char * string)1020 int valid_option_name(const char *string)
1021 {
1022 int m = strlen(string);
1023 int n = strspn(string, "abcdefghijklmnopqrstuvwxyz0123456789_");
1024
1025 if (!m)
1026 return 0;
1027
1028 if (m != n)
1029 return 0;
1030
1031 if (string[m-1] == '_')
1032 return 0;
1033
1034 return 1;
1035 }
1036
is_option(const char * string)1037 int is_option(const char *string)
1038 {
1039 int n = strspn(string, "abcdefghijklmnopqrstuvwxyz0123456789_");
1040
1041 return n > 0 && string[n] == '=' && string[0] != '_' && string[n-1] != '_';
1042 }
1043
match_option_1(const char * string,const char * option)1044 int match_option_1(const char *string, const char *option)
1045 {
1046 const char *next;
1047
1048 if (*string == '\0')
1049 return 1;
1050
1051 if (*option == '\0')
1052 return 0;
1053
1054 if (*string == *option && match_option_1(string + 1, option + 1))
1055 return 1;
1056
1057 if (*option == '_' && match_option_1(string, option + 1))
1058 return 1;
1059
1060 next = strchr(option, '_');
1061 if (!next)
1062 return 0;
1063
1064 if (*string == '_')
1065 return match_option_1(string + 1, next + 1);
1066
1067 return match_option_1(string, next + 1);
1068 }
1069
match_option(const char * string,const char * option)1070 int match_option(const char *string, const char *option)
1071 {
1072 return (*string == *option)
1073 && match_option_1(string + 1, option + 1);
1074 }
1075
set_option(const char * string)1076 void set_option(const char *string)
1077 {
1078 struct Option *at_opt = NULL;
1079 struct Option *opt = NULL;
1080 size_t key_len;
1081 char the_key[KEYLENGTH];
1082 char *ptr, *err;
1083 struct Option *matches[MAX_MATCHES];
1084 int found = 0;
1085
1086 err = NULL;
1087
1088 for (ptr = the_key; *string != '='; ptr++, string++)
1089 *ptr = *string;
1090 *ptr = '\0';
1091 string++;
1092
1093 /* an empty string is not a valid answer, skip */
1094 if (! *string)
1095 return;
1096
1097 /* Find option with best keyword match */
1098 key_len = strlen(the_key);
1099 for (at_opt = &st->first_option; at_opt; at_opt = at_opt->next_opt) {
1100 if (!at_opt->key)
1101 continue;
1102
1103 if (strcmp(the_key, at_opt->key) == 0) {
1104 matches[0] = at_opt;
1105 found = 1;
1106 break;
1107 }
1108
1109 if (strncmp(the_key, at_opt->key, key_len) == 0 ||
1110 match_option(the_key, at_opt->key)) {
1111 if (found >= MAX_MATCHES)
1112 G_fatal_error("Too many matches (limit %d)", MAX_MATCHES);
1113 matches[found++] = at_opt;
1114 }
1115 }
1116
1117 if (found > 1) {
1118 int shortest = 0;
1119 int length = strlen(matches[0]->key);
1120 int prefix = 1;
1121 int i;
1122 for (i = 1; i < found; i++) {
1123 int len = strlen(matches[i]->key);
1124 if (len < length) {
1125 length = len;
1126 shortest = i;
1127 }
1128 }
1129 for (i = 0; prefix && i < found; i++)
1130 if (strncmp(matches[i]->key, matches[shortest]->key, length) != 0)
1131 prefix = 0;
1132 if (prefix) {
1133 matches[0] = matches[shortest];
1134 found = 1;
1135 }
1136 else {
1137 G_asprintf(&err, _("%s: Sorry, <%s=> is ambiguous"), G_program_name(), the_key);
1138 append_error(err);
1139 for (i = 0; i < found; i++) {
1140 G_asprintf(&err, _("Option <%s=> matches"), matches[i]->key);
1141 append_error(err);
1142 }
1143 return;
1144 }
1145 }
1146
1147 if (found)
1148 opt = matches[0];
1149
1150 /* First, check if key has been renamed in GRASS 7 */
1151 if (found == 0) {
1152 const char *renamed_key = NULL;
1153
1154 renamed_key = get_renamed_option(the_key);
1155 if (renamed_key) {
1156 for (at_opt = &st->first_option; at_opt; at_opt = at_opt->next_opt) {
1157 if (strcmp(renamed_key, at_opt->key) == 0) {
1158 G_warning(_("Please update the usage of <%s>: "
1159 "option <%s> has been renamed to <%s>"),
1160 G_program_name(), the_key, renamed_key);
1161 opt = at_opt;
1162 found = 1;
1163 break;
1164 }
1165 }
1166 }
1167 }
1168
1169 /* If there is no match, complain */
1170 if (found == 0) {
1171 G_asprintf(&err, _("%s: Sorry, <%s> is not a valid parameter"), G_program_name(), the_key);
1172 append_error(err);
1173 return;
1174 }
1175
1176 if (getenv("GRASS_FULL_OPTION_NAMES") && strcmp(the_key, opt->key) != 0)
1177 G_warning(_("<%s> is an abbreviation for <%s>"), the_key, opt->key);
1178
1179 /* Allocate memory where answer is stored */
1180 if (opt->count++) {
1181 if (!opt->multiple) {
1182 G_asprintf(&err, _("Option <%s> does not accept multiple answers"), opt->key);
1183 append_error(err);
1184 }
1185 opt->answer = G_realloc(opt->answer,
1186 strlen(opt->answer) + strlen(string) + 2);
1187 strcat(opt->answer, ",");
1188 strcat(opt->answer, string);
1189 }
1190 else
1191 opt->answer = G_store(string);
1192 }
1193
check_opts(void)1194 void check_opts(void)
1195 {
1196 struct Option *opt;
1197 int ans;
1198
1199 if (!st->n_opts)
1200 return;
1201
1202 opt = &st->first_option;
1203 while (opt) {
1204 /* Check answer against options if any */
1205
1206 if (opt->answer) {
1207 if (opt->multiple == 0)
1208 check_an_opt(opt->key, opt->type,
1209 opt->options, opt->opts, &opt->answer);
1210 else {
1211 for (ans = 0; opt->answers[ans] != '\0'; ans++)
1212 check_an_opt(opt->key, opt->type,
1213 opt->options, opt->opts, &opt->answers[ans]);
1214 }
1215 }
1216
1217 /* Check answer against user's check subroutine if any */
1218
1219 if (opt->checker)
1220 opt->checker(opt->answer);
1221
1222 opt = opt->next_opt;
1223 }
1224 }
1225
check_an_opt(const char * key,int type,const char * options,const char ** opts,char ** answerp)1226 void check_an_opt(const char *key, int type, const char *options,
1227 const char **opts, char **answerp)
1228 {
1229 const char *answer = *answerp;
1230 int error;
1231 char *err;
1232 int found;
1233
1234 error = 0;
1235 err = NULL;
1236 found = 0;
1237
1238 switch (type) {
1239 case TYPE_INTEGER:
1240 error = check_int(answer, opts);
1241 break;
1242 case TYPE_DOUBLE:
1243 error = check_double(answer, opts);
1244 break;
1245 case TYPE_STRING:
1246 error = check_string(answer, opts, &found);
1247 break;
1248 }
1249 switch (error) {
1250 case 0:
1251 break;
1252 case BAD_SYNTAX:
1253 G_asprintf(&err,
1254 _("Illegal range syntax for parameter <%s>\n"
1255 "\tPresented as: %s"), key, options);
1256 append_error(err);
1257 break;
1258 case OUT_OF_RANGE:
1259 G_asprintf(&err,
1260 _("Value <%s> out of range for parameter <%s>\n"
1261 "\tLegal range: %s"), answer, key, options);
1262 append_error(err);
1263 break;
1264 case MISSING_VALUE:
1265 G_asprintf(&err,
1266 _("Missing value for parameter <%s>"),
1267 key);
1268 append_error(err);
1269 break;
1270 case INVALID_VALUE:
1271 G_asprintf(&err,
1272 _("Invalid value <%s> for parameter <%s>"),
1273 answer, key);
1274 append_error(err);
1275 break;
1276 case AMBIGUOUS:
1277 G_asprintf(&err,
1278 _("Value <%s> ambiguous for parameter <%s>\n"
1279 "\tValid options: %s"), answer, key, options);
1280 append_error(err);
1281 break;
1282 case REPLACED:
1283 *answerp = G_store(opts[found]);
1284 error = 0;
1285 break;
1286 }
1287 }
1288
check_int(const char * ans,const char ** opts)1289 int check_int(const char *ans, const char **opts)
1290 {
1291 int d, i;
1292
1293 /* "-" is reserved for standard input */
1294 if (strcmp(ans, "-") == 0)
1295 return 0;
1296
1297 if (!ans || !*ans)
1298 return MISSING_VALUE;
1299
1300 if (sscanf(ans, "%d", &d) != 1)
1301 return INVALID_VALUE;
1302
1303 if (!opts)
1304 return 0;
1305
1306 for (i = 0; opts[i]; i++) {
1307 const char *opt = opts[i];
1308 int lo, hi;
1309
1310 if (contains(opt, '-')) {
1311 if (sscanf(opt, "%d-%d", &lo, &hi) == 2) {
1312 if (d >= lo && d <= hi)
1313 return 0;
1314 }
1315 else if (sscanf(opt, "-%d", &hi) == 1) {
1316 if (d <= hi)
1317 return 0;
1318 }
1319 else if (sscanf(opt, "%d-", &lo) == 1) {
1320 if (d >= lo)
1321 return 0;
1322 }
1323 else
1324 return BAD_SYNTAX;
1325 }
1326 else {
1327 if (sscanf(opt, "%d", &lo) == 1) {
1328 if (d == lo)
1329 return 0;
1330 }
1331 else
1332 return BAD_SYNTAX;
1333 }
1334 }
1335
1336 return OUT_OF_RANGE;
1337 }
1338
check_double(const char * ans,const char ** opts)1339 int check_double(const char *ans, const char **opts)
1340 {
1341 double d;
1342 int i;
1343
1344 /* "-" is reserved for standard input */
1345 if (strcmp(ans, "-") == 0)
1346 return 0;
1347
1348 if (!ans || !*ans)
1349 return MISSING_VALUE;
1350
1351 if (sscanf(ans, "%lf", &d) != 1)
1352 return INVALID_VALUE;
1353
1354 if (!opts)
1355 return 0;
1356
1357 for (i = 0; opts[i]; i++) {
1358 const char *opt = opts[i];
1359 double lo, hi;
1360
1361 if (contains(opt, '-')) {
1362 if (sscanf(opt, "%lf-%lf", &lo, &hi) == 2) {
1363 if (d >= lo && d <= hi)
1364 return 0;
1365 }
1366 else if (sscanf(opt, "-%lf", &hi) == 1) {
1367 if (d <= hi)
1368 return 0;
1369 }
1370 else if (sscanf(opt, "%lf-", &lo) == 1) {
1371 if (d >= lo)
1372 return 0;
1373 }
1374 else
1375 return BAD_SYNTAX;
1376 }
1377 else {
1378 if (sscanf(opt, "%lf", &lo) == 1) {
1379 if (d == lo)
1380 return 0;
1381 }
1382 else
1383 return BAD_SYNTAX;
1384 }
1385 }
1386
1387 return OUT_OF_RANGE;
1388 }
1389
check_string(const char * ans,const char ** opts,int * result)1390 int check_string(const char *ans, const char **opts, int *result)
1391 {
1392 int len = strlen(ans);
1393 int found = 0;
1394 int matches[MAX_MATCHES];
1395 int i;
1396
1397 if (!opts)
1398 return 0;
1399
1400 for (i = 0; opts[i]; i++) {
1401 if (strcmp(ans, opts[i]) == 0)
1402 return 0;
1403 if (strncmp(ans, opts[i], len) == 0 || match_option(ans, opts[i])) {
1404 if (found >= MAX_MATCHES)
1405 G_fatal_error("too many matches (limit %d)", MAX_MATCHES);
1406 matches[found++] = i;
1407 }
1408 }
1409
1410 if (found > 1) {
1411 int shortest = 0;
1412 int length = strlen(opts[matches[0]]);
1413 int prefix = 1;
1414
1415 for (i = 1; i < found; i++) {
1416 int lengthi = strlen(opts[matches[i]]);
1417
1418 if (lengthi < length) {
1419 length = lengthi;
1420 shortest = i;
1421 }
1422 }
1423 for (i = 0; prefix && i < found; i++)
1424 if (strncmp(opts[matches[i]], opts[matches[shortest]], length) != 0)
1425 prefix = 0;
1426 if (prefix) {
1427 matches[0] = matches[shortest];
1428 found = 1;
1429 }
1430 }
1431
1432 if (found == 1)
1433 *result = matches[0];
1434
1435 if (found > 0 && getenv("GRASS_FULL_OPTION_NAMES") && strcmp(ans, opts[matches[0]]) != 0)
1436 G_warning(_("<%s> is an abbreviation for <%s>"), ans, opts[matches[0]]);
1437
1438 switch (found) {
1439 case 0: return OUT_OF_RANGE;
1440 case 1: return REPLACED;
1441 default: return AMBIGUOUS;
1442 }
1443 }
1444
check_required(void)1445 void check_required(void)
1446 {
1447 struct Option *opt;
1448 char *err;
1449
1450 err = NULL;
1451
1452 if (!st->n_opts)
1453 return;
1454
1455 opt = &st->first_option;
1456 while (opt) {
1457 if (opt->required && !opt->answer) {
1458 G_asprintf(&err, _("Required parameter <%s> not set:\n"
1459 "\t(%s)"),
1460 opt->key, (opt->label ? opt->label : opt->description));
1461 append_error(err);
1462 }
1463 opt = opt->next_opt;
1464 }
1465 }
1466
split_opts(void)1467 void split_opts(void)
1468 {
1469 struct Option *opt;
1470 const char *ptr1;
1471 const char *ptr2;
1472 int allocated;
1473 int ans_num;
1474 int len;
1475
1476
1477 if (!st->n_opts)
1478 return;
1479
1480 opt = &st->first_option;
1481 while (opt) {
1482 if ( /*opt->multiple && */ opt->answer) {
1483 /* Allocate some memory to store array of pointers */
1484 allocated = 10;
1485 opt->answers = G_malloc(allocated * sizeof(char *));
1486
1487 ans_num = 0;
1488 ptr1 = opt->answer;
1489 opt->answers[ans_num] = NULL;
1490
1491 for (;;) {
1492 for (len = 0, ptr2 = ptr1; *ptr2 != '\0' && *ptr2 != ',';
1493 ptr2++, len++) ;
1494
1495 if (len > 0) { /* skip ,, */
1496 opt->answers[ans_num] = G_malloc(len + 1);
1497 memcpy(opt->answers[ans_num], ptr1, len);
1498 opt->answers[ans_num][len] = 0;
1499
1500 ans_num++;
1501
1502 if (ans_num >= allocated) {
1503 allocated += 10;
1504 opt->answers = G_realloc(opt->answers,
1505 allocated * sizeof(char *));
1506 }
1507
1508 opt->answers[ans_num] = NULL;
1509 }
1510
1511 if (*ptr2 == '\0')
1512 break;
1513
1514 ptr1 = ptr2 + 1;
1515
1516 if (*ptr1 == '\0')
1517 break;
1518 }
1519 }
1520 opt = opt->next_opt;
1521 }
1522 }
1523
check_multiple_opts(void)1524 void check_multiple_opts(void)
1525 {
1526 struct Option *opt;
1527 const char *ptr;
1528 int n_commas;
1529 int n;
1530 char *err;
1531
1532 if (!st->n_opts)
1533 return;
1534
1535 err = NULL;
1536 opt = &st->first_option;
1537 while (opt) {
1538 /* "-" is reserved from standard input/output */
1539 if (opt->answer && strcmp(opt->answer, "-") && opt->key_desc) {
1540 /* count commas */
1541 n_commas = 1;
1542 for (ptr = opt->key_desc; *ptr != '\0'; ptr++)
1543 if (*ptr == ',')
1544 n_commas++;
1545 /* count items */
1546 for (n = 0; opt->answers[n] != '\0'; n++) ;
1547 /* if not correct multiple of items */
1548 if (n % n_commas) {
1549 G_asprintf(&err,
1550 _("Option <%s> must be provided in multiples of %d\n"
1551 "\tYou provided %d item(s): %s"),
1552 opt->key, n_commas, n, opt->answer);
1553 append_error(err);
1554
1555 }
1556 }
1557 opt = opt->next_opt;
1558 }
1559 }
1560
1561 /* Check for all 'new' if element already exists */
check_overwrite(void)1562 int check_overwrite(void)
1563 {
1564 struct Option *opt;
1565 char age[KEYLENGTH];
1566 char element[KEYLENGTH];
1567 char desc[KEYLENGTH];
1568 int error = 0;
1569 const char *overstr;
1570 int over;
1571
1572 st->module_info.overwrite = 0;
1573
1574 if (!st->n_opts)
1575 return (0);
1576
1577 over = 0;
1578 /* Check the GRASS OVERWRITE variable */
1579 if ((overstr = G_getenv_nofatal("OVERWRITE"))) {
1580 over = atoi(overstr);
1581 }
1582
1583 /* Check the GRASS_OVERWRITE environment variable */
1584 if ((overstr = getenv("GRASS_OVERWRITE"))) {
1585 if (atoi(overstr))
1586 over = 1;
1587 }
1588
1589 if (st->overwrite || over) {
1590 st->module_info.overwrite = 1;
1591 /* Set the environment so that programs run in a script also obey --o */
1592 putenv("GRASS_OVERWRITE=1");
1593 /* No need to check options for existing files if overwrite is true */
1594 return error;
1595 }
1596
1597 opt = &st->first_option;
1598 while (opt) {
1599 if (opt->answer && opt->gisprompt) {
1600 G__split_gisprompt(opt->gisprompt, age, element, desc);
1601
1602 if (strcmp(age, "new") == 0) {
1603 int i;
1604 char found;
1605
1606 for (i = 0; opt->answers[i]; i++) {
1607 found = FALSE;
1608 if (strcmp(element, "file") == 0) {
1609 if (access(opt->answers[i], F_OK) == 0)
1610 found = TRUE;
1611 }
1612 else if (strcmp(element, "mapset") != 0) {
1613 /* TODO: also other elements should be
1614 probably skipped */
1615 if (G_find_file(element, opt->answers[i], G_mapset())) {
1616 found = TRUE;
1617 }
1618 }
1619
1620 if (found) { /* found */
1621 if (!st->overwrite && !over) {
1622 if (G_verbose() > -1) {
1623 if (G_info_format() != G_INFO_FORMAT_GUI) {
1624 fprintf(stderr, _("ERROR: "));
1625 fprintf(stderr,
1626 _("option <%s>: <%s> exists. To overwrite, use the --overwrite flag"),
1627 opt->key, opt->answers[i]);
1628 fprintf(stderr, "\n");
1629 }
1630 else {
1631 fprintf(stderr, "GRASS_INFO_ERROR(%d,1): ", getpid());
1632 fprintf(stderr,
1633 _("option <%s>: <%s> exists. To overwrite, use the --overwrite flag"),
1634 opt->key, opt->answers[i]);
1635 fprintf(stderr, "\n");
1636 fprintf(stderr, "GRASS_INFO_END(%d,1)\n",
1637 getpid());
1638 }
1639 }
1640 error = 1;
1641 }
1642 }
1643 }
1644 }
1645 }
1646 opt = opt->next_opt;
1647 }
1648
1649 return (error);
1650 }
1651
G__split_gisprompt(const char * gisprompt,char * age,char * element,char * desc)1652 void G__split_gisprompt(const char *gisprompt, char *age, char *element,
1653 char *desc)
1654 {
1655 const char *ptr1;
1656 char *ptr2;
1657
1658 for (ptr1 = gisprompt, ptr2 = age; *ptr1 != '\0'; ptr1++, ptr2++) {
1659 if (*ptr1 == ',')
1660 break;
1661 *ptr2 = *ptr1;
1662 }
1663 *ptr2 = '\0';
1664
1665 for (ptr1++, ptr2 = element; *ptr1 != '\0'; ptr1++, ptr2++) {
1666 if (*ptr1 == ',')
1667 break;
1668 *ptr2 = *ptr1;
1669 }
1670 *ptr2 = '\0';
1671
1672 for (ptr1++, ptr2 = desc; *ptr1 != '\0'; ptr1++, ptr2++) {
1673 if (*ptr1 == ',')
1674 break;
1675 *ptr2 = *ptr1;
1676 }
1677 *ptr2 = '\0';
1678 }
1679
append_error(const char * msg)1680 void append_error(const char *msg)
1681 {
1682 st->error = G_realloc(st->error, sizeof(char *) * (st->n_errors + 1));
1683 st->error[st->n_errors++] = G_store(msg);
1684 }
1685
get_renamed_option(const char * key)1686 const char *get_renamed_option(const char *key)
1687 {
1688 const char *pgm, *key_new;
1689 char *pgm_key;
1690
1691 if (!st->renamed_options) {
1692 /* read renamed options from file (renamed_options) */
1693 char path[GPATH_MAX];
1694
1695 G_snprintf(path, GPATH_MAX, "%s/etc/renamed_options", G_gisbase());
1696 st->renamed_options = G_read_key_value_file(path);
1697 }
1698
1699 /* try to check global changes first */
1700 key_new = G_find_key_value(key, st->renamed_options);
1701 if (key_new)
1702 return key_new;
1703
1704 /* then check module-relevant changes */
1705 pgm = G_program_name();
1706 pgm_key = (char *) G_malloc (strlen(pgm) + strlen(key) + 2);
1707 G_asprintf(&pgm_key, "%s|%s", pgm, key);
1708
1709 key_new = G_find_key_value(pgm_key, st->renamed_options);
1710 G_free(pgm_key);
1711
1712 return key_new;
1713 }
1714
1715 /*!
1716 \brief Get separator string from the option.
1717
1718 Calls G_fatal_error() on error. Allocated string can be later freed
1719 by G_free().
1720
1721 \code
1722 char *fs;
1723 struct Option *opt_fs;
1724
1725 opt_fs = G_define_standard_option(G_OPT_F_SEP);
1726
1727 if (G_parser(argc, argv))
1728 exit(EXIT_FAILURE);
1729
1730 fs = G_option_to_separator(opt_fs);
1731 \endcode
1732
1733 \param option pointer to separator option
1734
1735 \return allocated string with separator
1736 */
G_option_to_separator(const struct Option * option)1737 char* G_option_to_separator(const struct Option *option)
1738 {
1739 char* sep;
1740
1741 if (option->gisprompt == NULL ||
1742 strcmp(option->gisprompt, "old,separator,separator") != 0)
1743 G_fatal_error(_("%s= is not a separator option"), option->key);
1744
1745 if (option->answer == NULL)
1746 G_fatal_error(_("No separator given for %s="), option->key);
1747
1748 if (strcmp(option->answer, "pipe") == 0)
1749 sep = G_store("|");
1750 else if (strcmp(option->answer, "comma") == 0)
1751 sep = G_store(",");
1752 else if (strcmp(option->answer, "space") == 0)
1753 sep = G_store(" ");
1754 else if (strcmp(option->answer, "tab") == 0 ||
1755 strcmp(option->answer, "\\t") == 0)
1756 sep = G_store("\t");
1757 else if (strcmp(option->answer, "newline") == 0 ||
1758 strcmp(option->answer, "\\n") == 0)
1759 sep = G_store("\n");
1760 else
1761 sep = G_store(option->answer);
1762
1763 G_debug(3, "G_option_to_separator(): key = %s -> sep = '%s'",
1764 option->key, sep);
1765
1766 return sep;
1767 }
1768
1769 /*!
1770 \brief Get an input/output file pointer from the option. If the file name is
1771 omitted or '-', it returns either stdin or stdout based on the gisprompt.
1772
1773 Calls G_fatal_error() on error. File pointer can be later closed by
1774 G_close_option_file().
1775
1776 \code
1777 FILE *fp_input;
1778 FILE *fp_output;
1779 struct Option *opt_input;
1780 struct Option *opt_output;
1781
1782 opt_input = G_define_standard_option(G_OPT_F_INPUT);
1783 opt_output = G_define_standard_option(G_OPT_F_OUTPUT);
1784
1785 if (G_parser(argc, argv))
1786 exit(EXIT_FAILURE);
1787
1788 fp_input = G_open_option_file(opt_input);
1789 fp_output = G_open_option_file(opt_output);
1790 ...
1791 G_close_option_file(fp_input);
1792 G_close_option_file(fp_output);
1793 \endcode
1794
1795 \param option pointer to a file option
1796
1797 \return file pointer
1798 */
G_open_option_file(const struct Option * option)1799 FILE *G_open_option_file(const struct Option *option)
1800 {
1801 int stdinout;
1802 FILE *fp;
1803
1804 stdinout = !option->answer || !*(option->answer) ||
1805 strcmp(option->answer, "-") == 0;
1806
1807 if (option->gisprompt == NULL)
1808 G_fatal_error(_("%s= is not a file option"), option->key);
1809 else if (option->multiple)
1810 G_fatal_error(_("Opening multiple files not supported for %s="),
1811 option->key);
1812 else if (strcmp(option->gisprompt, "old,file,file") == 0) {
1813 if (stdinout)
1814 fp = stdin;
1815 else if ((fp = fopen(option->answer, "r")) == NULL)
1816 G_fatal_error(_("Unable to open %s file <%s>"),
1817 option->key, option->answer);
1818 } else if (strcmp(option->gisprompt, "new,file,file") == 0) {
1819 if (stdinout)
1820 fp = stdout;
1821 else if ((fp = fopen(option->answer, "w")) == NULL)
1822 G_fatal_error(_("Unable to create %s file <%s>"),
1823 option->key, option->answer);
1824 } else
1825 G_fatal_error(_("%s= is not a file option"), option->key);
1826
1827 return fp;
1828 }
1829
1830 /*!
1831 \brief Close an input/output file returned by G_open_option_file(). If the
1832 file pointer is stdin, stdout, or stderr, nothing happens.
1833
1834 \param file pointer
1835 */
G_close_option_file(FILE * fp)1836 void G_close_option_file(FILE *fp)
1837 {
1838 if (fp != stdin && fp != stdout && fp != stderr)
1839 fclose(fp);
1840 }
1841