GRASS GIS 7 Programmer's Manual  7.0.2(2015)-r00000
parser.c
Go to the documentation of this file.
1 
76 #include <stdio.h>
77 #include <stdlib.h>
78 #include <string.h>
79 #include <unistd.h>
80 
81 #include <grass/gis.h>
82 #include <grass/spawn.h>
83 #include <grass/glocale.h>
84 
85 #include "parser_local_proto.h"
86 
87 enum opt_error {
91  AMBIGUOUS = 4,
93 };
94 
95 #define KEYLENGTH 64
96 
97 #define MAX_MATCHES 50
98 
99 /* initialize the global struct */
100 struct state state;
101 struct state *st = &state;
102 
103 /* local prototypes */
104 static void set_flag(int);
105 static int contains(const char *, int);
106 static int valid_option_name(const char *);
107 static int is_option(const char *);
108 static int match_option_1(const char *, const char *);
109 static int match_option(const char *, const char *);
110 static void set_option(const char *);
111 static void check_opts(void);
112 static void check_an_opt(const char *, int, const char *, const char **, char **);
113 static int check_int(const char *, const char **);
114 static int check_double(const char *, const char **);
115 static int check_string(const char *, const char **, int *);
116 static void check_required(void);
117 static void split_opts(void);
118 static void check_multiple_opts(void);
119 static int check_overwrite(void);
120 static void define_keywords(void);
121 static void split_gisprompt(const char *, char *, char *, char *);
122 static void module_gui_wx(void);
123 static void append_error(const char *);
124 static const char *get_renamed_option(const char *);
125 
138 {
139  st->no_interactive = 1;
140 }
141 
154 struct Flag *G_define_flag(void)
155 {
156  struct Flag *flag;
157  struct Item *item;
158 
159  /* Allocate memory if not the first flag */
160 
161  if (st->n_flags) {
162  flag = G_malloc(sizeof(struct Flag));
163  st->current_flag->next_flag = flag;
164  }
165  else
166  flag = &st->first_flag;
167 
168  /* Zero structure */
169 
170  G_zero(flag, sizeof(struct Flag));
171 
172  st->current_flag = flag;
173  st->n_flags++;
174 
175  if (st->n_items) {
176  item = G_malloc(sizeof(struct Item));
177  st->current_item->next_item = item;
178  }
179  else
180  item = &st->first_item;
181 
182  G_zero(item, sizeof(struct Item));
183 
184  item->flag = flag;
185  item->option = NULL;
186 
187  st->current_item = item;
188  st->n_items++;
189 
190  return (flag);
191 }
192 
208 struct Option *G_define_option(void)
209 {
210  struct Option *opt;
211  struct Item *item;
212 
213  /* Allocate memory if not the first option */
214 
215  if (st->n_opts) {
216  opt = G_malloc(sizeof(struct Option));
217  st->current_option->next_opt = opt;
218  }
219  else
220  opt = &st->first_option;
221 
222  /* Zero structure */
223  G_zero(opt, sizeof(struct Option));
224 
225  opt->required = NO;
226  opt->multiple = NO;
227 
228  st->current_option = opt;
229  st->n_opts++;
230 
231  if (st->n_items) {
232  item = G_malloc(sizeof(struct Item));
233  st->current_item->next_item = item;
234  }
235  else
236  item = &st->first_item;
237 
238  G_zero(item, sizeof(struct Item));
239 
240  item->option = opt;
241 
242  st->current_item = item;
243  st->n_items++;
244 
245  return (opt);
246 }
247 
253 struct GModule *G_define_module(void)
254 {
255  struct GModule *module;
256 
257  /* Allocate memory */
258  module = &st->module_info;
259 
260  /* Zero structure */
261  G_zero(module, sizeof(struct GModule));
262 
263  /* Allocate keywords array */
264  define_keywords();
265 
266  return (module);
267 }
268 
318 int G_parser(int argc, char **argv)
319 {
320  int need_first_opt;
321  int opt_checked = 0;
322  char *ptr, *tmp_name, *err;
323  int i;
324  struct Option *opt;
325  char force_gui = FALSE;
326 
327  err = NULL;
328  need_first_opt = 1;
329  tmp_name = G_store(argv[0]);
330  st->pgm_path = tmp_name;
331  st->n_errors = 0;
332  st->error = NULL;
333  i = strlen(tmp_name);
334  while (--i >= 0) {
335  if (G_is_dirsep(tmp_name[i])) {
336  tmp_name += i + 1;
337  break;
338  }
339  }
340  G_basename(tmp_name, "exe");
341  st->pgm_name = tmp_name;
342 
343  /* Stash default answers */
344 
345  opt = &st->first_option;
346  while (st->n_opts && opt) {
347  if (opt->required)
348  st->has_required = 1;
349 
350  if (!valid_option_name(opt->key))
351  G_warning(_("BUG in option name, '%s' is not valid"), opt->key);
352 
353  /* Parse options */
354  if (opt->options) {
355  int cnt = 0;
356  char **tokens, delm[2];
357 
358  delm[0] = ',';
359  delm[1] = '\0';
360  tokens = G_tokenize(opt->options, delm);
361 
362  i = 0;
363  while (tokens[i]) {
364  G_chop(tokens[i]);
365  cnt++;
366  i++;
367  }
368 
369  opt->opts = G_calloc(cnt + 1, sizeof(const char *));
370 
371  i = 0;
372  while (tokens[i]) {
373  opt->opts[i] = G_store(tokens[i]);
374  i++;
375  }
376  G_free_tokens(tokens);
377 
378  if (opt->descriptions) {
379  delm[0] = ';';
380 
381  opt->descs = G_calloc(cnt + 1, sizeof(const char *));
382  tokens = G_tokenize(opt->descriptions, delm);
383 
384  i = 0;
385  while (tokens[i]) {
386  int j, found;
387 
388  if (!tokens[i + 1])
389  break;
390 
391  G_chop(tokens[i]);
392 
393  j = 0;
394  found = 0;
395  while (opt->opts[j]) {
396  if (strcmp(opt->opts[j], tokens[i]) == 0) {
397  found = 1;
398  break;
399  }
400  j++;
401  }
402  if (!found) {
403  G_warning(_("BUG in descriptions, option '%s' in <%s> does not exist"),
404  tokens[i], opt->key);
405  }
406  else {
407  opt->descs[j] = G_store(tokens[i + 1]);
408  }
409 
410  i += 2;
411  }
412  G_free_tokens(tokens);
413  }
414  }
415 
416  /* Copy answer */
417  if (opt->multiple && opt->answers && opt->answers[0]) {
418  opt->answer = G_malloc(strlen(opt->answers[0]) + 1);
419  strcpy(opt->answer, opt->answers[0]);
420  for (i = 1; opt->answers[i]; i++) {
421  opt->answer = G_realloc(opt->answer,
422  strlen(opt->answer) +
423  strlen(opt->answers[i]) + 2);
424  strcat(opt->answer, ",");
425  strcat(opt->answer, opt->answers[i]);
426  }
427  }
428  opt->def = opt->answer;
429  opt = opt->next_opt;
430  }
431 
432  /* If there are NO arguments, go interactive */
433 
434  if (argc < 2 && (st->has_required || G__has_required_rule())
435  && !st->no_interactive && isatty(0)) {
436  module_gui_wx();
437  return -1;
438  }
439  else if (argc < 2 && st->has_required && isatty(0)) {
440  G_usage();
441  return -1;
442  }
443  else if (argc >= 2) {
444 
445  /* If first arg is "help" give a usage/syntax message */
446  if (strcmp(argv[1], "help") == 0 ||
447  strcmp(argv[1], "-help") == 0 || strcmp(argv[1], "--help") == 0) {
448  G_usage();
449  exit(EXIT_SUCCESS);
450  }
451 
452  /* If first arg is "--help-text" give a usage/syntax message
453  * with machine-readable sentinels */
454  if (strcmp(argv[1], "--help-text") == 0) {
455  G__usage_text();
456  exit(EXIT_SUCCESS);
457  }
458 
459  /* If first arg is "--interface-description" then print out
460  * a xml description of the task */
461  if (strcmp(argv[1], "--interface-description") == 0) {
462  G__usage_xml();
463  exit(EXIT_SUCCESS);
464  }
465 
466  /* If first arg is "--html-description" then print out
467  * a html description of the task */
468  if (strcmp(argv[1], "--html-description") == 0) {
469  G__usage_html();
470  exit(EXIT_SUCCESS);
471  }
472 
473  /* If first arg is "--rst-description" then print out
474  * a reStructuredText description of the task */
475  if (strcmp(argv[1], "--rst-description") == 0) {
476  G__usage_rest();
477  exit(EXIT_SUCCESS);
478  }
479 
480  /* If first arg is "--wps-process-description" then print out
481  * the wps process description of the task */
482  if (strcmp(argv[1], "--wps-process-description") == 0) {
484  exit(EXIT_SUCCESS);
485  }
486 
487  /* If first arg is "--script" then then generate
488  * g.parser boilerplate */
489  if (strcmp(argv[1], "--script") == 0) {
490  G__script();
491  exit(EXIT_SUCCESS);
492  }
493 
494  /* Loop thru all command line arguments */
495 
496  while (--argc) {
497  ptr = *(++argv);
498 
499  if (strcmp(ptr, "help") == 0 || strcmp(ptr, "--h") == 0 ||
500  strcmp(ptr, "-help") == 0 || strcmp(ptr, "--help") == 0) {
501  G_usage();
502  exit(EXIT_SUCCESS);
503  }
504 
505  /* Overwrite option */
506  if (strcmp(ptr, "--o") == 0 || strcmp(ptr, "--overwrite") == 0) {
507  st->overwrite = 1;
508  }
509 
510  /* Verbose option */
511  else if (strcmp(ptr, "--v") == 0 || strcmp(ptr, "--verbose") == 0) {
512  char buff[32];
513 
514  /* print everything: max verbosity level */
515  st->module_info.verbose = G_verbose_max();
516  sprintf(buff, "GRASS_VERBOSE=%d", G_verbose_max());
517  putenv(G_store(buff));
518  if (st->quiet == 1) {
519  G_warning(_("Use either --quiet or --verbose flag, not both. Assuming --verbose."));
520  }
521  st->quiet = -1;
522  }
523 
524  /* Quiet option */
525  else if (strcmp(ptr, "--q") == 0 || strcmp(ptr, "--quiet") == 0) {
526  char buff[32];
527 
528  /* print nothing, but errors and warnings */
529  st->module_info.verbose = G_verbose_min();
530  sprintf(buff, "GRASS_VERBOSE=%d", G_verbose_min());
531  putenv(G_store(buff));
532  if (st->quiet == -1) {
533  G_warning(_("Use either --quiet or --verbose flag, not both. Assuming --quiet."));
534  }
535  st->quiet = 1; /* for passing to gui init */
536  }
537 
538  /* Force gui to come up */
539  else if (strcmp(ptr, "--ui") == 0) {
540  force_gui = TRUE;
541  }
542 
543  /* If we see a flag */
544  else if (*ptr == '-') {
545  while (*(++ptr))
546  set_flag(*ptr);
547 
548  }
549  /* If we see standard option format (option=val) */
550  else if (is_option(ptr)) {
551  set_option(ptr);
552  need_first_opt = 0;
553  }
554 
555  /* If we see the first option with no equal sign */
556  else if (need_first_opt && st->n_opts) {
557  st->first_option.answer = G_store(ptr);
558  st->first_option.count++;
559  need_first_opt = 0;
560  }
561 
562  /* If we see the non valid argument (no "=", just argument) */
563  else {
564  G_asprintf(&err, _("Sorry <%s> is not a valid option"), ptr);
565  append_error(err);
566  }
567 
568  }
569  }
570 
571  /* Split options where multiple answers are OK */
572  split_opts();
573 
574  /* Run the gui if it was specifically requested */
575  if (force_gui) {
576  module_gui_wx();
577  return -1;
578  }
579 
580  /* Check multiple options */
581  check_multiple_opts();
582 
583  /* Check answers against options and check subroutines */
584  if (!opt_checked)
585  check_opts();
586 
587  /* Make sure all required options are set */
588  if (!st->suppress_required)
589  check_required();
590 
592 
593  if (st->n_errors > 0) {
594  if (G_verbose() > -1) {
595  if (G_verbose() > G_verbose_min())
596  G_usage();
597  fprintf(stderr, "\n");
598  for (i = 0; i < st->n_errors; i++) {
599  fprintf(stderr, "%s: %s\n", _("ERROR"), st->error[i]);
600  }
601  }
602  return -1;
603  }
604 
605  if (check_overwrite())
606  return -1;
607 
608  return 0;
609 }
610 
620 {
621  char *buff;
622  char flg[4];
623  char *cur;
624  const char *tmp;
625  struct Flag *flag;
626  struct Option *opt;
627  int n, len, slen;
628  int nalloced = 0;
629 
630  G_debug(3, "G_recreate_command()");
631 
632  /* Flag is not valid if there are no flags to set */
633 
634  buff = G_calloc(1024, sizeof(char));
635  nalloced += 1024;
636  tmp = G_program_name();
637  len = strlen(tmp);
638  if (len >= nalloced) {
639  nalloced += (1024 > len) ? 1024 : len + 1;
640  buff = G_realloc(buff, nalloced);
641  }
642  cur = buff;
643  strcpy(cur, tmp);
644  cur += len;
645 
646  if (st->n_flags) {
647  flag = &st->first_flag;
648  while (flag) {
649  if (flag->answer == 1) {
650  flg[0] = ' ';
651  flg[1] = '-';
652  flg[2] = flag->key;
653  flg[3] = '\0';
654  slen = strlen(flg);
655  if (len + slen >= nalloced) {
656  nalloced +=
657  (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
658  buff = G_realloc(buff, nalloced);
659  cur = buff + len;
660  }
661  strcpy(cur, flg);
662  cur += slen;
663  len += slen;
664  }
665  flag = flag->next_flag;
666  }
667  }
668 
669  opt = &st->first_option;
670  while (st->n_opts && opt) {
671  if (opt->answer && opt->answers && opt->answers[0]) {
672  slen = strlen(opt->key) + strlen(opt->answers[0]) + 4; /* +4 for: ' ' = " " */
673  if (len + slen >= nalloced) {
674  nalloced += (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
675  buff = G_realloc(buff, nalloced);
676  cur = buff + len;
677  }
678  strcpy(cur, " ");
679  cur++;
680  strcpy(cur, opt->key);
681  cur = strchr(cur, '\0');
682  strcpy(cur, "=");
683  cur++;
684  if (opt->type == TYPE_STRING) {
685  strcpy(cur, "\"");
686  cur++;
687  }
688  strcpy(cur, opt->answers[0]);
689  cur = strchr(cur, '\0');
690  len = cur - buff;
691  for (n = 1; opt->answers[n]; n++) {
692  if (!opt->answers[n])
693  break;
694  slen = strlen(opt->answers[n]) + 2; /* +2 for , " */
695  if (len + slen >= nalloced) {
696  nalloced +=
697  (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
698  buff = G_realloc(buff, nalloced);
699  cur = buff + len;
700  }
701  strcpy(cur, ",");
702  cur++;
703  strcpy(cur, opt->answers[n]);
704  cur = strchr(cur, '\0');
705  len = cur - buff;
706  }
707  if (opt->type == TYPE_STRING) {
708  strcpy(cur, "\"");
709  cur++;
710  len = cur - buff;
711  }
712  }
713  opt = opt->next_opt;
714  }
715 
716  return buff;
717 }
718 
724 void G_add_keyword(const char *keyword)
725 {
726  if (st->n_keys >= st->n_keys_alloc) {
727  st->n_keys_alloc += 10;
728  st->module_info.keywords = G_realloc(st->module_info.keywords,
729  st->n_keys_alloc * sizeof(char *));
730  }
731 
732  st->module_info.keywords[st->n_keys++] = G_store(keyword);
733 }
734 
740 void G_set_keywords(const char *keywords)
741 {
742  char **tokens = G_tokenize(keywords, ",");
743  st->module_info.keywords = (const char **)tokens;
744  st->n_keys = st->n_keys_alloc = G_number_of_tokens(tokens);
745 }
746 
747 
749 {
750  struct Option *opt;
751  char age[KEYLENGTH];
752  char element[KEYLENGTH];
753  char desc[KEYLENGTH];
754 
755  if (st->module_info.overwrite)
756  return 1;
757 
758  /* figure out if any of the options use a "new" gisprompt */
759  /* This is to see if we should spit out the --o flag */
760  if (st->n_opts) {
761  opt = &st->first_option;
762  while (opt) {
763  if (opt->gisprompt) {
764  split_gisprompt(opt->gisprompt, age, element, desc);
765  if (strcmp(age, "new") == 0)
766  return 1;
767  }
768  opt = opt->next_opt;
769  }
770  }
771 
772  return 0;
773 }
774 
784 void G__print_keywords(FILE *fd, void (*format)(FILE *, const char *))
785 {
786  int i;
787 
788  for(i = 0; i < st->n_keys; i++) {
789  if (!format) {
790  fprintf(fd, "%s", st->module_info.keywords[i]);
791  }
792  else {
793  format(fd, st->module_info.keywords[i]);
794  }
795  if (i < st->n_keys - 1)
796  fprintf(fd, ", ");
797  }
798 
799  fflush(fd);
800 }
801 
809 {
810  return st->overwrite;
811 }
812 
813 void define_keywords(void)
814 {
815  st->n_keys = 0;
816  st->n_keys_alloc = 0;
817 }
818 
819 /**************************************************************************
820  *
821  * The remaining routines are all local (static) routines used to support
822  * the parsing process.
823  *
824  **************************************************************************/
825 
829 void module_gui_wx(void)
830 {
831  char script[GPATH_MAX];
832 
833  if (!st->pgm_path)
834  st->pgm_path = G_program_name();
835  if (!st->pgm_path)
836  G_fatal_error(_("Unable to determine program name"));
837 
838  sprintf(script, "%s/gui/wxpython/gui_core/forms.py",
839  getenv("GISBASE"));
840  G_spawn(getenv("GRASS_PYTHON"), getenv("GRASS_PYTHON"), script, G_recreate_command(), NULL);
841 }
842 
843 void set_flag(int f)
844 {
845  struct Flag *flag;
846  char *err;
847 
848  err = NULL;
849 
850  /* Flag is not valid if there are no flags to set */
851  if (!st->n_flags) {
852  G_asprintf(&err, _("%s: Sorry, <%c> is not a valid flag"), G_program_name(), f);
853  append_error(err);
854  return;
855  }
856 
857  /* Find flag with corrrect keyword */
858  flag = &st->first_flag;
859  while (flag) {
860  if (flag->key == f) {
861  flag->answer = 1;
862  if (flag->suppress_required)
863  st->suppress_required = 1;
864  return;
865  }
866  flag = flag->next_flag;
867  }
868 
869  G_asprintf(&err, _("%s: Sorry, <%c> is not a valid flag"), G_program_name(), f);
870  append_error(err);
871 }
872 
873 /* contents() is used to find things strings with characters like commas and
874  * dashes.
875  */
876 int contains(const char *s, int c)
877 {
878  while (*s) {
879  if (*s == c)
880  return TRUE;
881  s++;
882  }
883  return FALSE;
884 }
885 
886 int valid_option_name(const char *string)
887 {
888  int m = strlen(string);
889  int n = strspn(string, "abcdefghijklmnopqrstuvwxyz0123456789_");
890 
891  if (!m)
892  return 0;
893 
894  if (m != n)
895  return 0;
896 
897  if (string[m-1] == '_')
898  return 0;
899 
900  return 1;
901 }
902 
903 int is_option(const char *string)
904 {
905  int n = strspn(string, "abcdefghijklmnopqrstuvwxyz0123456789_");
906 
907  return n > 0 && string[n] == '=' && string[0] != '_' && string[n-1] != '_';
908 }
909 
910 int match_option_1(const char *string, const char *option)
911 {
912  const char *next;
913 
914  if (*string == '\0')
915  return 1;
916 
917  if (*option == '\0')
918  return 0;
919 
920  if (*string == *option && match_option_1(string + 1, option + 1))
921  return 1;
922 
923  if (*option == '_' && match_option_1(string, option + 1))
924  return 1;
925 
926  next = strchr(option, '_');
927  if (!next)
928  return 0;
929 
930  if (*string == '_')
931  return match_option_1(string + 1, next + 1);
932 
933  return match_option_1(string, next + 1);
934 }
935 
936 int match_option(const char *string, const char *option)
937 {
938  return (*string == *option)
939  && match_option_1(string + 1, option + 1);
940 }
941 
942 void set_option(const char *string)
943 {
944  struct Option *at_opt = NULL;
945  struct Option *opt = NULL;
946  size_t key_len;
947  char the_key[KEYLENGTH];
948  char *ptr, *err;
949  struct Option *matches[MAX_MATCHES];
950  int found = 0;
951 
952  err = NULL;
953 
954  for (ptr = the_key; *string != '='; ptr++, string++)
955  *ptr = *string;
956  *ptr = '\0';
957  string++;
958 
959  /* Find option with best keyword match */
960  key_len = strlen(the_key);
961  for (at_opt = &st->first_option; at_opt; at_opt = at_opt->next_opt) {
962  if (!at_opt->key)
963  continue;
964 
965  if (strcmp(the_key, at_opt->key) == 0) {
966  matches[0] = at_opt;
967  found = 1;
968  break;
969  }
970 
971  if (strncmp(the_key, at_opt->key, key_len) == 0 ||
972  match_option(the_key, at_opt->key)) {
973  if (found >= MAX_MATCHES)
974  G_fatal_error("Too many matches (limit %d)", MAX_MATCHES);
975  matches[found++] = at_opt;
976  }
977  }
978 
979  if (found > 1) {
980  int shortest = 0;
981  int length = strlen(matches[0]->key);
982  int prefix = 1;
983  int i;
984  for (i = 1; i < found; i++) {
985  int len = strlen(matches[i]->key);
986  if (len < length) {
987  length = len;
988  shortest = i;
989  }
990  }
991  for (i = 0; prefix && i < found; i++)
992  if (strncmp(matches[i]->key, matches[shortest]->key, length) != 0)
993  prefix = 0;
994  if (prefix) {
995  matches[0] = matches[shortest];
996  found = 1;
997  }
998  else {
999  G_asprintf(&err, _("%s: Sorry, <%s=> is ambiguous"), G_program_name(), the_key);
1000  append_error(err);
1001  for (i = 0; i < found; i++) {
1002  G_asprintf(&err, _("Option <%s=> matches"), matches[i]->key);
1003  append_error(err);
1004  }
1005  return;
1006  }
1007  }
1008 
1009  if (found)
1010  opt = matches[0];
1011 
1012  /* First, check if key has been renamed in GRASS 7 */
1013  if (found == 0) {
1014  const char *renamed_key = NULL;
1015 
1016  renamed_key = get_renamed_option(the_key);
1017  if (renamed_key) {
1018  for (at_opt = &st->first_option; at_opt; at_opt = at_opt->next_opt) {
1019  if (strcmp(renamed_key, at_opt->key) == 0) {
1020  G_warning(_("Please update the usage of <%s>: "
1021  "option <%s> has been renamed to <%s>"),
1022  G_program_name(), the_key, renamed_key);
1023  opt = at_opt;
1024  found = 1;
1025  break;
1026  }
1027  }
1028  }
1029  }
1030 
1031  /* If there is no match, complain */
1032  if (found == 0) {
1033  G_asprintf(&err, _("%s: Sorry, <%s> is not a valid parameter"), G_program_name(), the_key);
1034  append_error(err);
1035  return;
1036  }
1037 
1038  if (getenv("GRASS_FULL_OPTION_NAMES") && strcmp(the_key, opt->key) != 0)
1039  G_warning(_("<%s> is an abbreviation for <%s>"), the_key, opt->key);
1040 
1041  /* Allocate memory where answer is stored */
1042  if (opt->count++) {
1043  if (!opt->multiple) {
1044  G_asprintf(&err, _("Option <%s> does not accept multiple answers"), opt->key);
1045  append_error(err);
1046  }
1047  opt->answer = G_realloc(opt->answer,
1048  strlen(opt->answer) + strlen(string) + 2);
1049  strcat(opt->answer, ",");
1050  strcat(opt->answer, string);
1051  }
1052  else
1053  opt->answer = G_store(string);
1054 }
1055 
1056 void check_opts(void)
1057 {
1058  struct Option *opt;
1059  int ans;
1060 
1061  if (!st->n_opts)
1062  return;
1063 
1064  opt = &st->first_option;
1065  while (opt) {
1066  /* Check answer against options if any */
1067 
1068  if (opt->answer) {
1069  if (opt->multiple == 0)
1070  check_an_opt(opt->key, opt->type,
1071  opt->options, opt->opts, &opt->answer);
1072  else {
1073  for (ans = 0; opt->answers[ans] != '\0'; ans++)
1074  check_an_opt(opt->key, opt->type,
1075  opt->options, opt->opts, &opt->answers[ans]);
1076  }
1077  }
1078 
1079  /* Check answer against user's check subroutine if any */
1080 
1081  if (opt->checker)
1082  opt->checker(opt->answer);
1083 
1084  opt = opt->next_opt;
1085  }
1086 }
1087 
1088 void check_an_opt(const char *key, int type, const char *options,
1089  const char **opts, char **answerp)
1090 {
1091  const char *answer = *answerp;
1092  int error;
1093  char *err;
1094  int found;
1095 
1096  error = 0;
1097  err = NULL;
1098 
1099  switch (type) {
1100  case TYPE_INTEGER:
1101  error = check_int(answer, opts);
1102  break;
1103  case TYPE_DOUBLE:
1104  error = check_double(answer, opts);
1105  break;
1106  case TYPE_STRING:
1107  error = check_string(answer, opts, &found);
1108  break;
1109  }
1110  switch (error) {
1111  case 0:
1112  break;
1113  case BAD_SYNTAX:
1114  G_asprintf(&err,
1115  _("Illegal range syntax for parameter <%s>\n"
1116  "\tPresented as: %s"), key, options);
1117  append_error(err);
1118  break;
1119  case OUT_OF_RANGE:
1120  G_asprintf(&err,
1121  _("Value <%s> out of range for parameter <%s>\n"
1122  "\tLegal range: %s"), answer, key, options);
1123  append_error(err);
1124  break;
1125  case MISSING_VALUE:
1126  G_asprintf(&err,
1127  _("Missing value for parameter <%s>"),
1128  key);
1129  append_error(err);
1130  break;
1131  case AMBIGUOUS:
1132  G_asprintf(&err,
1133  _("Value <%s> ambiguous for parameter <%s>\n"
1134  "\tValid options: %s"), answer, key, options);
1135  append_error(err);
1136  break;
1137  case REPLACED:
1138  *answerp = G_store(opts[found]);
1139  error = 0;
1140  break;
1141  }
1142 }
1143 
1144 int check_int(const char *ans, const char **opts)
1145 {
1146  int d, i;
1147 
1148  /* "-" is reserved for standard input */
1149  if (strcmp(ans, "-") == 0)
1150  return 0;
1151 
1152  if (sscanf(ans, "%d", &d) != 1)
1153  return MISSING_VALUE;
1154 
1155  if (!opts)
1156  return 0;
1157 
1158  for (i = 0; opts[i]; i++) {
1159  const char *opt = opts[i];
1160  int lo, hi;
1161 
1162  if (contains(opt, '-')) {
1163  if (sscanf(opt, "%d-%d", &lo, &hi) == 2) {
1164  if (d >= lo && d <= hi)
1165  return 0;
1166  }
1167  else if (sscanf(opt, "-%d", &hi) == 1) {
1168  if (d <= hi)
1169  return 0;
1170  }
1171  else if (sscanf(opt, "%d-", &lo) == 1) {
1172  if (d >= lo)
1173  return 0;
1174  }
1175  else
1176  return BAD_SYNTAX;
1177  }
1178  else {
1179  if (sscanf(opt, "%d", &lo) == 1) {
1180  if (d == lo)
1181  return 0;
1182  }
1183  else
1184  return BAD_SYNTAX;
1185  }
1186  }
1187 
1188  return OUT_OF_RANGE;
1189 }
1190 
1191 int check_double(const char *ans, const char **opts)
1192 {
1193  double d;
1194  int i;
1195 
1196  /* "-" is reserved for standard input */
1197  if (strcmp(ans, "-") == 0)
1198  return 0;
1199 
1200  if (sscanf(ans, "%lf", &d) != 1)
1201  return MISSING_VALUE;
1202 
1203  if (!opts)
1204  return 0;
1205 
1206  for (i = 0; opts[i]; i++) {
1207  const char *opt = opts[i];
1208  double lo, hi;
1209 
1210  if (contains(opt, '-')) {
1211  if (sscanf(opt, "%lf-%lf", &lo, &hi) == 2) {
1212  if (d >= lo && d <= hi)
1213  return 0;
1214  }
1215  else if (sscanf(opt, "-%lf", &hi) == 1) {
1216  if (d <= hi)
1217  return 0;
1218  }
1219  else if (sscanf(opt, "%lf-", &lo) == 1) {
1220  if (d >= lo)
1221  return 0;
1222  }
1223  else
1224  return BAD_SYNTAX;
1225  }
1226  else {
1227  if (sscanf(opt, "%lf", &lo) == 1) {
1228  if (d == lo)
1229  return 0;
1230  }
1231  else
1232  return BAD_SYNTAX;
1233  }
1234  }
1235 
1236  return OUT_OF_RANGE;
1237 }
1238 
1239 int check_string(const char *ans, const char **opts, int *result)
1240 {
1241  int len = strlen(ans);
1242  int found = 0;
1243  int matches[MAX_MATCHES];
1244  int i;
1245 
1246  if (!opts)
1247  return 0;
1248 
1249  for (i = 0; opts[i]; i++) {
1250  if (strcmp(ans, opts[i]) == 0)
1251  return 0;
1252  if (strncmp(ans, opts[i], len) == 0 || match_option(ans, opts[i])) {
1253  if (found >= MAX_MATCHES)
1254  G_fatal_error("too many matches (limit %d)", MAX_MATCHES);
1255  matches[found++] = i;
1256  }
1257  }
1258 
1259  if (found > 1) {
1260  int shortest = 0;
1261  int length = strlen(opts[matches[0]]);
1262  int prefix = 1;
1263  int i;
1264  for (i = 1; i < found; i++) {
1265  int len = strlen(opts[matches[i]]);
1266  if (len < length) {
1267  length = len;
1268  shortest = i;
1269  }
1270  }
1271  for (i = 0; prefix && i < found; i++)
1272  if (strncmp(opts[matches[i]], opts[matches[shortest]], length) != 0)
1273  prefix = 0;
1274  if (prefix) {
1275  matches[0] = matches[shortest];
1276  found = 1;
1277  }
1278  }
1279 
1280  if (found == 1)
1281  *result = matches[0];
1282 
1283  if (found > 0 && getenv("GRASS_FULL_OPTION_NAMES") && strcmp(ans, opts[matches[0]]) != 0)
1284  G_warning(_("<%s> is an abbreviation for <%s>"), ans, opts[matches[0]]);
1285 
1286  switch (found) {
1287  case 0: return OUT_OF_RANGE;
1288  case 1: return REPLACED;
1289  default: return AMBIGUOUS;
1290  }
1291 }
1292 
1293 void check_required(void)
1294 {
1295  struct Option *opt;
1296  char *err;
1297 
1298  err = NULL;
1299 
1300  if (!st->n_opts)
1301  return;
1302 
1303  opt = &st->first_option;
1304  while (opt) {
1305  if (opt->required && !opt->answer) {
1306  G_asprintf(&err, _("Required parameter <%s> not set:\n"
1307  "\t(%s)"),
1308  opt->key, (opt->label ? opt->label : opt->description));
1309  append_error(err);
1310  }
1311  opt = opt->next_opt;
1312  }
1313 }
1314 
1315 void split_opts(void)
1316 {
1317  struct Option *opt;
1318  const char *ptr1;
1319  const char *ptr2;
1320  int allocated;
1321  int ans_num;
1322  int len;
1323 
1324 
1325  if (!st->n_opts)
1326  return;
1327 
1328  opt = &st->first_option;
1329  while (opt) {
1330  if ( /*opt->multiple && */ opt->answer) {
1331  /* Allocate some memory to store array of pointers */
1332  allocated = 10;
1333  opt->answers = G_malloc(allocated * sizeof(char *));
1334 
1335  ans_num = 0;
1336  ptr1 = opt->answer;
1337  opt->answers[ans_num] = NULL;
1338 
1339  for (;;) {
1340  for (len = 0, ptr2 = ptr1; *ptr2 != '\0' && *ptr2 != ',';
1341  ptr2++, len++) ;
1342 
1343  if (len > 0) { /* skip ,, */
1344  opt->answers[ans_num] = G_malloc(len + 1);
1345  memcpy(opt->answers[ans_num], ptr1, len);
1346  opt->answers[ans_num][len] = 0;
1347 
1348  ans_num++;
1349 
1350  if (ans_num >= allocated) {
1351  allocated += 10;
1352  opt->answers = G_realloc(opt->answers,
1353  allocated * sizeof(char *));
1354  }
1355 
1356  opt->answers[ans_num] = NULL;
1357  }
1358 
1359  if (*ptr2 == '\0')
1360  break;
1361 
1362  ptr1 = ptr2 + 1;
1363 
1364  if (*ptr1 == '\0')
1365  break;
1366  }
1367  }
1368  opt = opt->next_opt;
1369  }
1370 }
1371 
1372 void check_multiple_opts(void)
1373 {
1374  struct Option *opt;
1375  const char *ptr;
1376  int n_commas;
1377  int n;
1378  char *err;
1379 
1380  if (!st->n_opts)
1381  return;
1382 
1383  err = NULL;
1384  opt = &st->first_option;
1385  while (opt) {
1386  /* "-" is reserved from standard input/output */
1387  if (opt->answer && strcmp(opt->answer, "-") && opt->key_desc) {
1388  /* count commas */
1389  n_commas = 1;
1390  for (ptr = opt->key_desc; *ptr != '\0'; ptr++)
1391  if (*ptr == ',')
1392  n_commas++;
1393  /* count items */
1394  for (n = 0; opt->answers[n] != '\0'; n++) ;
1395  /* if not correct multiple of items */
1396  if (n % n_commas) {
1397  G_asprintf(&err,
1398  _("Option <%s> must be provided in multiples of %d\n"
1399  "\tYou provided %d item(s): %s"),
1400  opt->key, n_commas, n, opt->answer);
1401  append_error(err);
1402 
1403  }
1404  }
1405  opt = opt->next_opt;
1406  }
1407 }
1408 
1409 /* Check for all 'new' if element already exists */
1410 int check_overwrite(void)
1411 {
1412  struct Option *opt;
1413  char age[KEYLENGTH];
1414  char element[KEYLENGTH];
1415  char desc[KEYLENGTH];
1416  int error = 0;
1417  const char *overstr;
1418  int over;
1419 
1420  st->module_info.overwrite = 0;
1421 
1422  if (!st->n_opts)
1423  return (0);
1424 
1425  over = 0;
1426  /* Check the GRASS OVERWRITE variable */
1427  if ((overstr = G_getenv_nofatal("OVERWRITE"))) {
1428  over = atoi(overstr);
1429  }
1430 
1431  /* Check the GRASS_OVERWRITE environment variable */
1432  if ((overstr = getenv("GRASS_OVERWRITE"))) {
1433  if (atoi(overstr))
1434  over = 1;
1435  }
1436 
1437  if (st->overwrite || over) {
1438  st->module_info.overwrite = 1;
1439  /* Set the environment so that programs run in a script also obey --o */
1440  putenv("GRASS_OVERWRITE=1");
1441  /* No need to check options for existing files if overwrite is true */
1442  return error;
1443  }
1444 
1445  opt = &st->first_option;
1446  while (opt) {
1447  if (opt->answer && opt->gisprompt) {
1448  split_gisprompt(opt->gisprompt, age, element, desc);
1449 
1450  if (strcmp(age, "new") == 0) {
1451  int i;
1452  char found;
1453 
1454  for (i = 0; opt->answers[i]; i++) {
1455  found = FALSE;
1456  if (strcmp(element, "file") == 0) {
1457  if (access(opt->answers[i], F_OK) == 0)
1458  found = TRUE;
1459  }
1460  else if (strcmp(element, "mapset") != 0) {
1461  /* TODO: also other elements should be
1462  probably skipped */
1463  if (G_find_file(element, opt->answers[i], G_mapset())) {
1464  found = TRUE;
1465  }
1466  }
1467 
1468  if (found) { /* found */
1469  if (!st->overwrite && !over) {
1470  if (G_verbose() > -1) {
1471  if (G_info_format() != G_INFO_FORMAT_GUI) {
1472  fprintf(stderr, _("ERROR: "));
1473  fprintf(stderr,
1474  _("option <%s>: <%s> exists. To overwrite, use the --overwrite flag"),
1475  opt->key, opt->answers[i]);
1476  fprintf(stderr, "\n");
1477  }
1478  else {
1479  fprintf(stderr, "GRASS_INFO_ERROR(%d,1): ", getpid());
1480  fprintf(stderr,
1481  _("option <%s>: <%s> exists. To overwrite, use the --overwrite flag"),
1482  opt->key, opt->answers[i]);
1483  fprintf(stderr, "\n");
1484  fprintf(stderr, "GRASS_INFO_END(%d,1)\n",
1485  getpid());
1486  }
1487  }
1488  error = 1;
1489  }
1490  }
1491  }
1492  }
1493  }
1494  opt = opt->next_opt;
1495  }
1496 
1497  return (error);
1498 }
1499 
1500 void split_gisprompt(const char *gisprompt, char *age, char *element,
1501  char *desc)
1502 {
1503  const char *ptr1;
1504  char *ptr2;
1505 
1506  for (ptr1 = gisprompt, ptr2 = age; *ptr1 != '\0'; ptr1++, ptr2++) {
1507  if (*ptr1 == ',')
1508  break;
1509  *ptr2 = *ptr1;
1510  }
1511  *ptr2 = '\0';
1512 
1513  for (ptr1++, ptr2 = element; *ptr1 != '\0'; ptr1++, ptr2++) {
1514  if (*ptr1 == ',')
1515  break;
1516  *ptr2 = *ptr1;
1517  }
1518  *ptr2 = '\0';
1519 
1520  for (ptr1++, ptr2 = desc; *ptr1 != '\0'; ptr1++, ptr2++) {
1521  if (*ptr1 == ',')
1522  break;
1523  *ptr2 = *ptr1;
1524  }
1525  *ptr2 = '\0';
1526 }
1527 
1528 void append_error(const char *msg)
1529 {
1530  st->error = G_realloc(st->error, sizeof(char *) * (st->n_errors + 1));
1531  st->error[st->n_errors++] = G_store(msg);
1532 }
1533 
1534 const char *get_renamed_option(const char *key)
1535 {
1536  const char *pgm, *key_new;
1537  char *pgm_key;
1538 
1539  if (!st->renamed_options) {
1540  /* read renamed options from file (renamed_options) */
1541  char path[GPATH_MAX];
1542 
1543  G_snprintf(path, GPATH_MAX, "%s/etc/renamed_options", G_gisbase());
1544  st->renamed_options = G_read_key_value_file(path);
1545  }
1546 
1547  /* try to check global changes first */
1548  key_new = G_find_key_value(key, st->renamed_options);
1549  if (key_new)
1550  return key_new;
1551 
1552  /* then check module-relevant changes */
1553  pgm = G_program_name();
1554  pgm_key = (char *) G_malloc (strlen(pgm) + strlen(key) + 2);
1555  G_asprintf(&pgm_key, "%s|%s", pgm, key);
1556 
1557  key_new = G_find_key_value(pgm_key, st->renamed_options);
1558  G_free(pgm_key);
1559 
1560  return key_new;
1561 }
1562 
1585 char* G_option_to_separator(const struct Option *option)
1586 {
1587  char* sep;
1588 
1589  if (option->gisprompt == NULL ||
1590  strcmp(option->gisprompt, "old,separator,separator") != 0)
1591  G_fatal_error(_("%s= is not a separator option"), option->key);
1592 
1593  if (option->answer == NULL)
1594  G_fatal_error(_("No separator given for %s="), option->key);
1595 
1596  if (strcmp(option->answer, "pipe") == 0)
1597  sep = G_store("|");
1598  else if (strcmp(option->answer, "comma") == 0)
1599  sep = G_store(",");
1600  else if (strcmp(option->answer, "space") == 0)
1601  sep = G_store(" ");
1602  else if (strcmp(option->answer, "tab") == 0 ||
1603  strcmp(option->answer, "\\t") == 0)
1604  sep = G_store("\t");
1605  else if (strcmp(option->answer, "newline") == 0 ||
1606  strcmp(option->answer, "\\n") == 0)
1607  sep = G_store("\n");
1608  else
1609  sep = G_store(option->answer);
1610 
1611  G_debug(2, "G_option_to_separator(): key = %s -> sep = '%s'",
1612  option->key, sep);
1613 
1614  return sep;
1615 }
1616 
1647 FILE *G_open_option_file(const struct Option *option)
1648 {
1649  int stdinout;
1650  FILE *fp;
1651 
1652  stdinout = !option->answer || !*(option->answer) ||
1653  strcmp(option->answer, "-") == 0;
1654 
1655  if (option->gisprompt == NULL)
1656  G_fatal_error(_("%s= is not a file option"), option->key);
1657  else if (option->multiple)
1658  G_fatal_error(_("Opening multiple files not supported for %s="),
1659  option->key);
1660  else if (strcmp(option->gisprompt, "old,file,file") == 0) {
1661  if (stdinout)
1662  fp = stdin;
1663  else if ((fp = fopen(option->answer, "r")) == NULL)
1664  G_fatal_error(_("Unable to open %s file <%s>"),
1665  option->key, option->answer);
1666  } else if (strcmp(option->gisprompt, "new,file,file") == 0) {
1667  if (stdinout)
1668  fp = stdout;
1669  else if ((fp = fopen(option->answer, "w")) == NULL)
1670  G_fatal_error(_("Unable to create %s file <%s>"),
1671  option->key, option->answer);
1672  } else
1673  G_fatal_error(_("%s= is not a file option"), option->key);
1674 
1675  return fp;
1676 }
1677 
1684 void G_close_option_file(FILE *fp)
1685 {
1686  if (fp != stdin && fp != stdout && fp != stderr)
1687  fclose(fp);
1688 }
int G__uses_new_gisprompt(void)
Definition: parser.c:748
int G_info_format(void)
Get current message format.
Definition: gis/error.c:531
int G__has_required_rule(void)
Checks if there is any rule RULE_REQUIRED (internal use only).
void G__usage_html(void)
Print module usage description in HTML format.
Definition: parser_html.c:29
const char * G_find_key_value(const char *key, const struct Key_Value *kv)
Find given key (case sensitive)
Definition: key_value1.c:84
#define KEYLENGTH
Definition: parser.c:95
const char * G_mapset(void)
Get current mapset name.
Definition: mapset.c:33
#define FALSE
Definition: dbfopen.c:117
void G__usage_xml(void)
Print module usage description in XML format.
struct GModule * G_define_module(void)
Initializes a new module.
Definition: parser.c:253
void G_zero(void *buf, int i)
Zero out a buffer, buf, of length i.
Definition: zero.c:23
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:203
void G__usage_rest(void)
Print module usage description in reStructuredText format.
Definition: parser_rest.c:29
char * G_store(const char *s)
Copy string to allocated memory.
Definition: strings.c:86
void G__check_option_rules(void)
Check for option rules (internal use only)
int G_asprintf(char **out, const char *fmt,...)
Definition: asprintf.c:70
int G_get_overwrite()
Get overwrite value.
Definition: parser.c:808
#define NULL
Definition: ccmath.h:32
char * G_chop(char *line)
Chop leading and trailing white spaces.
Definition: strings.c:286
void G__usage_text(void)
Definition: parser_help.c:53
char * G_option_to_separator(const struct Option *option)
Get separator string from the option.
Definition: parser.c:1585
char * G_recreate_command(void)
Creates command to run non-interactive.
Definition: parser.c:619
struct Flag * G_define_flag(void)
Initializes a Flag struct.
Definition: parser.c:154
int G_number_of_tokens(char **tokens)
Return number of tokens.
Definition: token.c:138
void G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
Definition: gis/error.c:159
int G_snprintf(char *str, size_t size, const char *fmt,...)
snprintf() clone.
Definition: snprintf.c:43
Definition: lidar.h:89
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:1684
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)
Definition: symbol/read.c:220
struct state * st
Definition: parser.c:101
struct Key_Value * G_read_key_value_file(const char *file)
Read key/values pairs from file.
Definition: key_value3.c:53
int G_parser(int argc, char **argv)
Parse command line.
Definition: parser.c:318
struct Option * G_define_option(void)
Initializes an Option struct.
Definition: parser.c:208
int G_verbose_max(void)
Get max verbosity level.
Definition: verbose.c:76
#define TRUE
Definition: dbfopen.c:118
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: debug.c:65
const char * G_getenv_nofatal(const char *name)
Get environment variable.
Definition: env.c:381
void G_set_keywords(const char *keywords)
Set keywords from the string.
Definition: parser.c:740
void G__script(void)
Generate Python script-like output.
Definition: parser_script.c:24
char * G_basename(char *filename, const char *desired_ext)
Truncates filename to the base part (before the last '.') if it matches the extension, otherwise leaves it unchanged.
Definition: basename.c:38
const char * G_program_name(void)
Return module name.
Definition: progrm_nme.c:27
void G_free_tokens(char **tokens)
Free memory allocated to tokens.
Definition: token.c:157
int G_verbose(void)
Get current verbosity level.
Definition: verbose.c:55
void G_usage(void)
Command line help/usage message.
Definition: parser_help.c:48
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 '-', it returns either stdin or stdout based on the gisprompt.
Definition: parser.c:1647
void G_disable_interactive(void)
Disables the ability of the parser to operate interactively.
Definition: parser.c:137
#define MAX_MATCHES
Definition: parser.c:97
Definition: path.h:16
char ** G_tokenize(const char *buf, const char *delim)
Tokenize string.
Definition: token.c:47
int G_verbose_min(void)
Get min verbosity level.
Definition: verbose.c:96
void G__print_keywords(FILE *fd, void(*format)(FILE *, const char *))
Print list of keywords (internal use only)
Definition: parser.c:784
void G_add_keyword(const char *keyword)
Add keyword to the list.
Definition: parser.c:724
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
void G__wps_print_process_description(void)
Print the WPS 1.0.0 process description XML document to stdout.
Definition: parser_wps.c:140
void G_free(void *buf)
Free allocated memory.
Definition: alloc.c:149
struct state state
Definition: parser.c:100
const char * G_gisbase(void)
Get full path name of the top level module directory.
Definition: gisbase.c:41
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition: gis/error.c:203
opt_error
Definition: parser.c:87
int G_spawn(const char *command,...)
Spawn new process based on command.
Definition: spawn.c:924