GRASS GIS 7 Programmer's Manual  7.0.3(2016)-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 int 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  st->module_info.verbose = G_verbose_std();
334  i = strlen(tmp_name);
335  while (--i >= 0) {
336  if (G_is_dirsep(tmp_name[i])) {
337  tmp_name += i + 1;
338  break;
339  }
340  }
341  G_basename(tmp_name, "exe");
342  st->pgm_name = tmp_name;
343 
344  /* Stash default answers */
345 
346  opt = &st->first_option;
347  while (st->n_opts && opt) {
348  if (opt->required)
349  st->has_required = 1;
350 
351  if (!valid_option_name(opt->key))
352  G_warning(_("BUG in option name, '%s' is not valid"), opt->key);
353 
354  /* Parse options */
355  if (opt->options) {
356  int cnt = 0;
357  char **tokens, delm[2];
358 
359  delm[0] = ',';
360  delm[1] = '\0';
361  tokens = G_tokenize(opt->options, delm);
362 
363  i = 0;
364  while (tokens[i]) {
365  G_chop(tokens[i]);
366  cnt++;
367  i++;
368  }
369 
370  opt->opts = G_calloc(cnt + 1, sizeof(const char *));
371 
372  i = 0;
373  while (tokens[i]) {
374  opt->opts[i] = G_store(tokens[i]);
375  i++;
376  }
377  G_free_tokens(tokens);
378 
379  if (opt->descriptions) {
380  delm[0] = ';';
381 
382  opt->descs = G_calloc(cnt + 1, sizeof(const char *));
383  tokens = G_tokenize(opt->descriptions, delm);
384 
385  i = 0;
386  while (tokens[i]) {
387  int j, found;
388 
389  if (!tokens[i + 1])
390  break;
391 
392  G_chop(tokens[i]);
393 
394  j = 0;
395  found = 0;
396  while (opt->opts[j]) {
397  if (strcmp(opt->opts[j], tokens[i]) == 0) {
398  found = 1;
399  break;
400  }
401  j++;
402  }
403  if (!found) {
404  G_warning(_("BUG in descriptions, option '%s' in <%s> does not exist"),
405  tokens[i], opt->key);
406  }
407  else {
408  opt->descs[j] = G_store(tokens[i + 1]);
409  }
410 
411  i += 2;
412  }
413  G_free_tokens(tokens);
414  }
415  }
416 
417  /* Copy answer */
418  if (opt->multiple && opt->answers && opt->answers[0]) {
419  opt->answer = G_malloc(strlen(opt->answers[0]) + 1);
420  strcpy(opt->answer, opt->answers[0]);
421  for (i = 1; opt->answers[i]; i++) {
422  opt->answer = G_realloc(opt->answer,
423  strlen(opt->answer) +
424  strlen(opt->answers[i]) + 2);
425  strcat(opt->answer, ",");
426  strcat(opt->answer, opt->answers[i]);
427  }
428  }
429  opt->def = opt->answer;
430  opt = opt->next_opt;
431  }
432 
433  /* If there are NO arguments, go interactive */
434 
435  if (argc < 2 && (st->has_required || G__has_required_rule())
436  && !st->no_interactive && isatty(0)) {
437  if (module_gui_wx() == 0)
438  return -1;
439  }
440 
441  if (argc < 2 && st->has_required && isatty(0)) {
442  G_usage();
443  return -1;
444  }
445  else if (argc >= 2) {
446 
447  /* If first arg is "help" give a usage/syntax message */
448  if (strcmp(argv[1], "help") == 0 ||
449  strcmp(argv[1], "-help") == 0 || strcmp(argv[1], "--help") == 0) {
450  G_usage();
451  exit(EXIT_SUCCESS);
452  }
453 
454  /* If first arg is "--help-text" give a usage/syntax message
455  * with machine-readable sentinels */
456  if (strcmp(argv[1], "--help-text") == 0) {
457  G__usage_text();
458  exit(EXIT_SUCCESS);
459  }
460 
461  /* If first arg is "--interface-description" then print out
462  * a xml description of the task */
463  if (strcmp(argv[1], "--interface-description") == 0) {
464  G__usage_xml();
465  exit(EXIT_SUCCESS);
466  }
467 
468  /* If first arg is "--html-description" then print out
469  * a html description of the task */
470  if (strcmp(argv[1], "--html-description") == 0) {
471  G__usage_html();
472  exit(EXIT_SUCCESS);
473  }
474 
475  /* If first arg is "--rst-description" then print out
476  * a reStructuredText description of the task */
477  if (strcmp(argv[1], "--rst-description") == 0) {
478  G__usage_rest();
479  exit(EXIT_SUCCESS);
480  }
481 
482  /* If first arg is "--wps-process-description" then print out
483  * the wps process description of the task */
484  if (strcmp(argv[1], "--wps-process-description") == 0) {
486  exit(EXIT_SUCCESS);
487  }
488 
489  /* If first arg is "--script" then then generate
490  * g.parser boilerplate */
491  if (strcmp(argv[1], "--script") == 0) {
492  G__script();
493  exit(EXIT_SUCCESS);
494  }
495 
496  /* Loop thru all command line arguments */
497 
498  while (--argc) {
499  ptr = *(++argv);
500 
501  if (strcmp(ptr, "help") == 0 || strcmp(ptr, "--h") == 0 ||
502  strcmp(ptr, "-help") == 0 || strcmp(ptr, "--help") == 0) {
503  G_usage();
504  exit(EXIT_SUCCESS);
505  }
506 
507  /* Overwrite option */
508  if (strcmp(ptr, "--o") == 0 || strcmp(ptr, "--overwrite") == 0) {
509  st->overwrite = 1;
510  }
511 
512  /* Verbose option */
513  else if (strcmp(ptr, "--v") == 0 || strcmp(ptr, "--verbose") == 0) {
514  char buff[32];
515 
516  /* print everything: max verbosity level */
517  st->module_info.verbose = G_verbose_max();
518  sprintf(buff, "GRASS_VERBOSE=%d", G_verbose_max());
519  putenv(G_store(buff));
520  if (st->quiet == 1) {
521  G_warning(_("Use either --quiet or --verbose flag, not both. Assuming --verbose."));
522  }
523  st->quiet = -1;
524  }
525 
526  /* Quiet option */
527  else if (strcmp(ptr, "--q") == 0 || strcmp(ptr, "--quiet") == 0) {
528  char buff[32];
529 
530  /* print nothing, but errors and warnings */
531  st->module_info.verbose = G_verbose_min();
532  sprintf(buff, "GRASS_VERBOSE=%d", G_verbose_min());
533  putenv(G_store(buff));
534  if (st->quiet == -1) {
535  G_warning(_("Use either --quiet or --verbose flag, not both. Assuming --quiet."));
536  }
537  st->quiet = 1; /* for passing to gui init */
538  }
539 
540  /* Force gui to come up */
541  else if (strcmp(ptr, "--ui") == 0) {
542  force_gui = TRUE;
543  }
544 
545  /* If we see a flag */
546  else if (*ptr == '-') {
547  while (*(++ptr))
548  set_flag(*ptr);
549 
550  }
551  /* If we see standard option format (option=val) */
552  else if (is_option(ptr)) {
553  set_option(ptr);
554  need_first_opt = 0;
555  }
556 
557  /* If we see the first option with no equal sign */
558  else if (need_first_opt && st->n_opts) {
559  st->first_option.answer = G_store(ptr);
560  st->first_option.count++;
561  need_first_opt = 0;
562  }
563 
564  /* If we see the non valid argument (no "=", just argument) */
565  else {
566  G_asprintf(&err, _("Sorry <%s> is not a valid option"), ptr);
567  append_error(err);
568  }
569 
570  }
571  }
572 
573  /* Split options where multiple answers are OK */
574  split_opts();
575 
576  /* Run the gui if it was specifically requested */
577  if (force_gui) {
578  if (module_gui_wx() != 0)
579  G_fatal_error(_("Your installation doesn't include GUI, exiting."));
580  return -1;
581  }
582 
583  /* Check multiple options */
584  check_multiple_opts();
585 
586  /* Check answers against options and check subroutines */
587  if (!opt_checked)
588  check_opts();
589 
590  /* Make sure all required options are set */
591  if (!st->suppress_required)
592  check_required();
593 
595 
596  if (st->n_errors > 0) {
597  if (G_verbose() > -1) {
598  if (G_verbose() > G_verbose_min())
599  G_usage();
600  fprintf(stderr, "\n");
601  for (i = 0; i < st->n_errors; i++) {
602  fprintf(stderr, "%s: %s\n", _("ERROR"), st->error[i]);
603  }
604  }
605  return -1;
606  }
607 
608  if (check_overwrite())
609  return -1;
610 
611  return 0;
612 }
613 
623 {
624  char *buff;
625  char flg[4];
626  char *cur;
627  const char *tmp;
628  struct Flag *flag;
629  struct Option *opt;
630  int n, len, slen;
631  int nalloced = 0;
632 
633  G_debug(3, "G_recreate_command()");
634 
635  /* Flag is not valid if there are no flags to set */
636 
637  buff = G_calloc(1024, sizeof(char));
638  nalloced += 1024;
639  tmp = G_program_name();
640  len = strlen(tmp);
641  if (len >= nalloced) {
642  nalloced += (1024 > len) ? 1024 : len + 1;
643  buff = G_realloc(buff, nalloced);
644  }
645  cur = buff;
646  strcpy(cur, tmp);
647  cur += len;
648 
649  if (st->overwrite) {
650  slen = strlen(" --overwrite");
651  if (len + slen >= nalloced) {
652  nalloced += (1024 > len) ? 1024 : len + 1;
653  buff = G_realloc(buff, nalloced);
654  }
655  strcpy(cur, " --overwrite");
656  cur += slen;
657  len += slen;
658  }
659 
660  if (st->module_info.verbose != G_verbose_std()) {
661  char *sflg;
662  if (st->module_info.verbose == G_verbose_max())
663  sflg = " --verbose";
664  else
665  sflg = " --quiet";
666 
667  slen = strlen(sflg);
668  if (len + slen >= nalloced) {
669  nalloced += (1024 > len) ? 1024 : len + 1;
670  buff = G_realloc(buff, nalloced);
671  }
672  strcpy(cur, sflg);
673  cur += slen;
674  len += slen;
675  }
676 
677  if (st->n_flags) {
678  flag = &st->first_flag;
679  while (flag) {
680  if (flag->answer == 1) {
681  flg[0] = ' ';
682  flg[1] = '-';
683  flg[2] = flag->key;
684  flg[3] = '\0';
685  slen = strlen(flg);
686  if (len + slen >= nalloced) {
687  nalloced +=
688  (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
689  buff = G_realloc(buff, nalloced);
690  cur = buff + len;
691  }
692  strcpy(cur, flg);
693  cur += slen;
694  len += slen;
695  }
696  flag = flag->next_flag;
697  }
698  }
699 
700  opt = &st->first_option;
701  while (st->n_opts && opt) {
702  if (opt->answer && opt->answers && opt->answers[0]) {
703  slen = strlen(opt->key) + strlen(opt->answers[0]) + 4; /* +4 for: ' ' = " " */
704  if (len + slen >= nalloced) {
705  nalloced += (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
706  buff = G_realloc(buff, nalloced);
707  cur = buff + len;
708  }
709  strcpy(cur, " ");
710  cur++;
711  strcpy(cur, opt->key);
712  cur = strchr(cur, '\0');
713  strcpy(cur, "=");
714  cur++;
715  if (opt->type == TYPE_STRING) {
716  strcpy(cur, "\"");
717  cur++;
718  }
719  strcpy(cur, opt->answers[0]);
720  cur = strchr(cur, '\0');
721  len = cur - buff;
722  for (n = 1; opt->answers[n]; n++) {
723  if (!opt->answers[n])
724  break;
725  slen = strlen(opt->answers[n]) + 2; /* +2 for , " */
726  if (len + slen >= nalloced) {
727  nalloced +=
728  (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
729  buff = G_realloc(buff, nalloced);
730  cur = buff + len;
731  }
732  strcpy(cur, ",");
733  cur++;
734  strcpy(cur, opt->answers[n]);
735  cur = strchr(cur, '\0');
736  len = cur - buff;
737  }
738  if (opt->type == TYPE_STRING) {
739  strcpy(cur, "\"");
740  cur++;
741  len = cur - buff;
742  }
743  }
744  opt = opt->next_opt;
745  }
746 
747  return buff;
748 }
749 
755 void G_add_keyword(const char *keyword)
756 {
757  if (st->n_keys >= st->n_keys_alloc) {
758  st->n_keys_alloc += 10;
759  st->module_info.keywords = G_realloc(st->module_info.keywords,
760  st->n_keys_alloc * sizeof(char *));
761  }
762 
763  st->module_info.keywords[st->n_keys++] = G_store(keyword);
764 }
765 
771 void G_set_keywords(const char *keywords)
772 {
773  char **tokens = G_tokenize(keywords, ",");
774  st->module_info.keywords = (const char **)tokens;
775  st->n_keys = st->n_keys_alloc = G_number_of_tokens(tokens);
776 }
777 
778 
780 {
781  struct Option *opt;
782  char age[KEYLENGTH];
783  char element[KEYLENGTH];
784  char desc[KEYLENGTH];
785 
786  if (st->module_info.overwrite)
787  return 1;
788 
789  /* figure out if any of the options use a "new" gisprompt */
790  /* This is to see if we should spit out the --o flag */
791  if (st->n_opts) {
792  opt = &st->first_option;
793  while (opt) {
794  if (opt->gisprompt) {
795  split_gisprompt(opt->gisprompt, age, element, desc);
796  if (strcmp(age, "new") == 0)
797  return 1;
798  }
799  opt = opt->next_opt;
800  }
801  }
802 
803  return 0;
804 }
805 
815 void G__print_keywords(FILE *fd, void (*format)(FILE *, const char *))
816 {
817  int i;
818 
819  for(i = 0; i < st->n_keys; i++) {
820  if (!format) {
821  fprintf(fd, "%s", st->module_info.keywords[i]);
822  }
823  else {
824  format(fd, st->module_info.keywords[i]);
825  }
826  if (i < st->n_keys - 1)
827  fprintf(fd, ", ");
828  }
829 
830  fflush(fd);
831 }
832 
840 {
841  return st->overwrite;
842 }
843 
844 void define_keywords(void)
845 {
846  st->n_keys = 0;
847  st->n_keys_alloc = 0;
848 }
849 
850 /**************************************************************************
851  *
852  * The remaining routines are all local (static) routines used to support
853  * the parsing process.
854  *
855  **************************************************************************/
856 
860 int module_gui_wx(void)
861 {
862  char script[GPATH_MAX];
863 
864  if (!st->pgm_path)
865  st->pgm_path = G_program_name();
866  if (!st->pgm_path)
867  G_fatal_error(_("Unable to determine program name"));
868 
869  sprintf(script, "%s/gui/wxpython/gui_core/forms.py",
870  getenv("GISBASE"));
871  if (access(script, F_OK) != -1)
872  G_spawn(getenv("GRASS_PYTHON"), getenv("GRASS_PYTHON"),
873  script, G_recreate_command(), NULL);
874  else
875  return -1;
876 
877  return 0;
878 }
879 
880 void set_flag(int f)
881 {
882  struct Flag *flag;
883  char *err;
884 
885  err = NULL;
886 
887  /* Flag is not valid if there are no flags to set */
888  if (!st->n_flags) {
889  G_asprintf(&err, _("%s: Sorry, <%c> is not a valid flag"), G_program_name(), f);
890  append_error(err);
891  return;
892  }
893 
894  /* Find flag with corrrect keyword */
895  flag = &st->first_flag;
896  while (flag) {
897  if (flag->key == f) {
898  flag->answer = 1;
899  if (flag->suppress_required)
900  st->suppress_required = 1;
901  return;
902  }
903  flag = flag->next_flag;
904  }
905 
906  G_asprintf(&err, _("%s: Sorry, <%c> is not a valid flag"), G_program_name(), f);
907  append_error(err);
908 }
909 
910 /* contents() is used to find things strings with characters like commas and
911  * dashes.
912  */
913 int contains(const char *s, int c)
914 {
915  while (*s) {
916  if (*s == c)
917  return TRUE;
918  s++;
919  }
920  return FALSE;
921 }
922 
923 int valid_option_name(const char *string)
924 {
925  int m = strlen(string);
926  int n = strspn(string, "abcdefghijklmnopqrstuvwxyz0123456789_");
927 
928  if (!m)
929  return 0;
930 
931  if (m != n)
932  return 0;
933 
934  if (string[m-1] == '_')
935  return 0;
936 
937  return 1;
938 }
939 
940 int is_option(const char *string)
941 {
942  int n = strspn(string, "abcdefghijklmnopqrstuvwxyz0123456789_");
943 
944  return n > 0 && string[n] == '=' && string[0] != '_' && string[n-1] != '_';
945 }
946 
947 int match_option_1(const char *string, const char *option)
948 {
949  const char *next;
950 
951  if (*string == '\0')
952  return 1;
953 
954  if (*option == '\0')
955  return 0;
956 
957  if (*string == *option && match_option_1(string + 1, option + 1))
958  return 1;
959 
960  if (*option == '_' && match_option_1(string, option + 1))
961  return 1;
962 
963  next = strchr(option, '_');
964  if (!next)
965  return 0;
966 
967  if (*string == '_')
968  return match_option_1(string + 1, next + 1);
969 
970  return match_option_1(string, next + 1);
971 }
972 
973 int match_option(const char *string, const char *option)
974 {
975  return (*string == *option)
976  && match_option_1(string + 1, option + 1);
977 }
978 
979 void set_option(const char *string)
980 {
981  struct Option *at_opt = NULL;
982  struct Option *opt = NULL;
983  size_t key_len;
984  char the_key[KEYLENGTH];
985  char *ptr, *err;
986  struct Option *matches[MAX_MATCHES];
987  int found = 0;
988 
989  err = NULL;
990 
991  for (ptr = the_key; *string != '='; ptr++, string++)
992  *ptr = *string;
993  *ptr = '\0';
994  string++;
995 
996  /* Find option with best keyword match */
997  key_len = strlen(the_key);
998  for (at_opt = &st->first_option; at_opt; at_opt = at_opt->next_opt) {
999  if (!at_opt->key)
1000  continue;
1001 
1002  if (strcmp(the_key, at_opt->key) == 0) {
1003  matches[0] = at_opt;
1004  found = 1;
1005  break;
1006  }
1007 
1008  if (strncmp(the_key, at_opt->key, key_len) == 0 ||
1009  match_option(the_key, at_opt->key)) {
1010  if (found >= MAX_MATCHES)
1011  G_fatal_error("Too many matches (limit %d)", MAX_MATCHES);
1012  matches[found++] = at_opt;
1013  }
1014  }
1015 
1016  if (found > 1) {
1017  int shortest = 0;
1018  int length = strlen(matches[0]->key);
1019  int prefix = 1;
1020  int i;
1021  for (i = 1; i < found; i++) {
1022  int len = strlen(matches[i]->key);
1023  if (len < length) {
1024  length = len;
1025  shortest = i;
1026  }
1027  }
1028  for (i = 0; prefix && i < found; i++)
1029  if (strncmp(matches[i]->key, matches[shortest]->key, length) != 0)
1030  prefix = 0;
1031  if (prefix) {
1032  matches[0] = matches[shortest];
1033  found = 1;
1034  }
1035  else {
1036  G_asprintf(&err, _("%s: Sorry, <%s=> is ambiguous"), G_program_name(), the_key);
1037  append_error(err);
1038  for (i = 0; i < found; i++) {
1039  G_asprintf(&err, _("Option <%s=> matches"), matches[i]->key);
1040  append_error(err);
1041  }
1042  return;
1043  }
1044  }
1045 
1046  if (found)
1047  opt = matches[0];
1048 
1049  /* First, check if key has been renamed in GRASS 7 */
1050  if (found == 0) {
1051  const char *renamed_key = NULL;
1052 
1053  renamed_key = get_renamed_option(the_key);
1054  if (renamed_key) {
1055  for (at_opt = &st->first_option; at_opt; at_opt = at_opt->next_opt) {
1056  if (strcmp(renamed_key, at_opt->key) == 0) {
1057  G_warning(_("Please update the usage of <%s>: "
1058  "option <%s> has been renamed to <%s>"),
1059  G_program_name(), the_key, renamed_key);
1060  opt = at_opt;
1061  found = 1;
1062  break;
1063  }
1064  }
1065  }
1066  }
1067 
1068  /* If there is no match, complain */
1069  if (found == 0) {
1070  G_asprintf(&err, _("%s: Sorry, <%s> is not a valid parameter"), G_program_name(), the_key);
1071  append_error(err);
1072  return;
1073  }
1074 
1075  if (getenv("GRASS_FULL_OPTION_NAMES") && strcmp(the_key, opt->key) != 0)
1076  G_warning(_("<%s> is an abbreviation for <%s>"), the_key, opt->key);
1077 
1078  /* Allocate memory where answer is stored */
1079  if (opt->count++) {
1080  if (!opt->multiple) {
1081  G_asprintf(&err, _("Option <%s> does not accept multiple answers"), opt->key);
1082  append_error(err);
1083  }
1084  opt->answer = G_realloc(opt->answer,
1085  strlen(opt->answer) + strlen(string) + 2);
1086  strcat(opt->answer, ",");
1087  strcat(opt->answer, string);
1088  }
1089  else
1090  opt->answer = G_store(string);
1091 }
1092 
1093 void check_opts(void)
1094 {
1095  struct Option *opt;
1096  int ans;
1097 
1098  if (!st->n_opts)
1099  return;
1100 
1101  opt = &st->first_option;
1102  while (opt) {
1103  /* Check answer against options if any */
1104 
1105  if (opt->answer) {
1106  if (opt->multiple == 0)
1107  check_an_opt(opt->key, opt->type,
1108  opt->options, opt->opts, &opt->answer);
1109  else {
1110  for (ans = 0; opt->answers[ans] != '\0'; ans++)
1111  check_an_opt(opt->key, opt->type,
1112  opt->options, opt->opts, &opt->answers[ans]);
1113  }
1114  }
1115 
1116  /* Check answer against user's check subroutine if any */
1117 
1118  if (opt->checker)
1119  opt->checker(opt->answer);
1120 
1121  opt = opt->next_opt;
1122  }
1123 }
1124 
1125 void check_an_opt(const char *key, int type, const char *options,
1126  const char **opts, char **answerp)
1127 {
1128  const char *answer = *answerp;
1129  int error;
1130  char *err;
1131  int found;
1132 
1133  error = 0;
1134  err = NULL;
1135 
1136  switch (type) {
1137  case TYPE_INTEGER:
1138  error = check_int(answer, opts);
1139  break;
1140  case TYPE_DOUBLE:
1141  error = check_double(answer, opts);
1142  break;
1143  case TYPE_STRING:
1144  error = check_string(answer, opts, &found);
1145  break;
1146  }
1147  switch (error) {
1148  case 0:
1149  break;
1150  case BAD_SYNTAX:
1151  G_asprintf(&err,
1152  _("Illegal range syntax for parameter <%s>\n"
1153  "\tPresented as: %s"), key, options);
1154  append_error(err);
1155  break;
1156  case OUT_OF_RANGE:
1157  G_asprintf(&err,
1158  _("Value <%s> out of range for parameter <%s>\n"
1159  "\tLegal range: %s"), answer, key, options);
1160  append_error(err);
1161  break;
1162  case MISSING_VALUE:
1163  G_asprintf(&err,
1164  _("Missing value for parameter <%s>"),
1165  key);
1166  append_error(err);
1167  break;
1168  case AMBIGUOUS:
1169  G_asprintf(&err,
1170  _("Value <%s> ambiguous for parameter <%s>\n"
1171  "\tValid options: %s"), answer, key, options);
1172  append_error(err);
1173  break;
1174  case REPLACED:
1175  *answerp = G_store(opts[found]);
1176  error = 0;
1177  break;
1178  }
1179 }
1180 
1181 int check_int(const char *ans, const char **opts)
1182 {
1183  int d, i;
1184 
1185  /* "-" is reserved for standard input */
1186  if (strcmp(ans, "-") == 0)
1187  return 0;
1188 
1189  if (sscanf(ans, "%d", &d) != 1)
1190  return MISSING_VALUE;
1191 
1192  if (!opts)
1193  return 0;
1194 
1195  for (i = 0; opts[i]; i++) {
1196  const char *opt = opts[i];
1197  int lo, hi;
1198 
1199  if (contains(opt, '-')) {
1200  if (sscanf(opt, "%d-%d", &lo, &hi) == 2) {
1201  if (d >= lo && d <= hi)
1202  return 0;
1203  }
1204  else if (sscanf(opt, "-%d", &hi) == 1) {
1205  if (d <= hi)
1206  return 0;
1207  }
1208  else if (sscanf(opt, "%d-", &lo) == 1) {
1209  if (d >= lo)
1210  return 0;
1211  }
1212  else
1213  return BAD_SYNTAX;
1214  }
1215  else {
1216  if (sscanf(opt, "%d", &lo) == 1) {
1217  if (d == lo)
1218  return 0;
1219  }
1220  else
1221  return BAD_SYNTAX;
1222  }
1223  }
1224 
1225  return OUT_OF_RANGE;
1226 }
1227 
1228 int check_double(const char *ans, const char **opts)
1229 {
1230  double d;
1231  int i;
1232 
1233  /* "-" is reserved for standard input */
1234  if (strcmp(ans, "-") == 0)
1235  return 0;
1236 
1237  if (sscanf(ans, "%lf", &d) != 1)
1238  return MISSING_VALUE;
1239 
1240  if (!opts)
1241  return 0;
1242 
1243  for (i = 0; opts[i]; i++) {
1244  const char *opt = opts[i];
1245  double lo, hi;
1246 
1247  if (contains(opt, '-')) {
1248  if (sscanf(opt, "%lf-%lf", &lo, &hi) == 2) {
1249  if (d >= lo && d <= hi)
1250  return 0;
1251  }
1252  else if (sscanf(opt, "-%lf", &hi) == 1) {
1253  if (d <= hi)
1254  return 0;
1255  }
1256  else if (sscanf(opt, "%lf-", &lo) == 1) {
1257  if (d >= lo)
1258  return 0;
1259  }
1260  else
1261  return BAD_SYNTAX;
1262  }
1263  else {
1264  if (sscanf(opt, "%lf", &lo) == 1) {
1265  if (d == lo)
1266  return 0;
1267  }
1268  else
1269  return BAD_SYNTAX;
1270  }
1271  }
1272 
1273  return OUT_OF_RANGE;
1274 }
1275 
1276 int check_string(const char *ans, const char **opts, int *result)
1277 {
1278  int len = strlen(ans);
1279  int found = 0;
1280  int matches[MAX_MATCHES];
1281  int i;
1282 
1283  if (!opts)
1284  return 0;
1285 
1286  for (i = 0; opts[i]; i++) {
1287  if (strcmp(ans, opts[i]) == 0)
1288  return 0;
1289  if (strncmp(ans, opts[i], len) == 0 || match_option(ans, opts[i])) {
1290  if (found >= MAX_MATCHES)
1291  G_fatal_error("too many matches (limit %d)", MAX_MATCHES);
1292  matches[found++] = i;
1293  }
1294  }
1295 
1296  if (found > 1) {
1297  int shortest = 0;
1298  int length = strlen(opts[matches[0]]);
1299  int prefix = 1;
1300  int i;
1301  for (i = 1; i < found; i++) {
1302  int len = strlen(opts[matches[i]]);
1303  if (len < length) {
1304  length = len;
1305  shortest = i;
1306  }
1307  }
1308  for (i = 0; prefix && i < found; i++)
1309  if (strncmp(opts[matches[i]], opts[matches[shortest]], length) != 0)
1310  prefix = 0;
1311  if (prefix) {
1312  matches[0] = matches[shortest];
1313  found = 1;
1314  }
1315  }
1316 
1317  if (found == 1)
1318  *result = matches[0];
1319 
1320  if (found > 0 && getenv("GRASS_FULL_OPTION_NAMES") && strcmp(ans, opts[matches[0]]) != 0)
1321  G_warning(_("<%s> is an abbreviation for <%s>"), ans, opts[matches[0]]);
1322 
1323  switch (found) {
1324  case 0: return OUT_OF_RANGE;
1325  case 1: return REPLACED;
1326  default: return AMBIGUOUS;
1327  }
1328 }
1329 
1330 void check_required(void)
1331 {
1332  struct Option *opt;
1333  char *err;
1334 
1335  err = NULL;
1336 
1337  if (!st->n_opts)
1338  return;
1339 
1340  opt = &st->first_option;
1341  while (opt) {
1342  if (opt->required && !opt->answer) {
1343  G_asprintf(&err, _("Required parameter <%s> not set:\n"
1344  "\t(%s)"),
1345  opt->key, (opt->label ? opt->label : opt->description));
1346  append_error(err);
1347  }
1348  opt = opt->next_opt;
1349  }
1350 }
1351 
1352 void split_opts(void)
1353 {
1354  struct Option *opt;
1355  const char *ptr1;
1356  const char *ptr2;
1357  int allocated;
1358  int ans_num;
1359  int len;
1360 
1361 
1362  if (!st->n_opts)
1363  return;
1364 
1365  opt = &st->first_option;
1366  while (opt) {
1367  if ( /*opt->multiple && */ opt->answer) {
1368  /* Allocate some memory to store array of pointers */
1369  allocated = 10;
1370  opt->answers = G_malloc(allocated * sizeof(char *));
1371 
1372  ans_num = 0;
1373  ptr1 = opt->answer;
1374  opt->answers[ans_num] = NULL;
1375 
1376  for (;;) {
1377  for (len = 0, ptr2 = ptr1; *ptr2 != '\0' && *ptr2 != ',';
1378  ptr2++, len++) ;
1379 
1380  if (len > 0) { /* skip ,, */
1381  opt->answers[ans_num] = G_malloc(len + 1);
1382  memcpy(opt->answers[ans_num], ptr1, len);
1383  opt->answers[ans_num][len] = 0;
1384 
1385  ans_num++;
1386 
1387  if (ans_num >= allocated) {
1388  allocated += 10;
1389  opt->answers = G_realloc(opt->answers,
1390  allocated * sizeof(char *));
1391  }
1392 
1393  opt->answers[ans_num] = NULL;
1394  }
1395 
1396  if (*ptr2 == '\0')
1397  break;
1398 
1399  ptr1 = ptr2 + 1;
1400 
1401  if (*ptr1 == '\0')
1402  break;
1403  }
1404  }
1405  opt = opt->next_opt;
1406  }
1407 }
1408 
1409 void check_multiple_opts(void)
1410 {
1411  struct Option *opt;
1412  const char *ptr;
1413  int n_commas;
1414  int n;
1415  char *err;
1416 
1417  if (!st->n_opts)
1418  return;
1419 
1420  err = NULL;
1421  opt = &st->first_option;
1422  while (opt) {
1423  /* "-" is reserved from standard input/output */
1424  if (opt->answer && strcmp(opt->answer, "-") && opt->key_desc) {
1425  /* count commas */
1426  n_commas = 1;
1427  for (ptr = opt->key_desc; *ptr != '\0'; ptr++)
1428  if (*ptr == ',')
1429  n_commas++;
1430  /* count items */
1431  for (n = 0; opt->answers[n] != '\0'; n++) ;
1432  /* if not correct multiple of items */
1433  if (n % n_commas) {
1434  G_asprintf(&err,
1435  _("Option <%s> must be provided in multiples of %d\n"
1436  "\tYou provided %d item(s): %s"),
1437  opt->key, n_commas, n, opt->answer);
1438  append_error(err);
1439 
1440  }
1441  }
1442  opt = opt->next_opt;
1443  }
1444 }
1445 
1446 /* Check for all 'new' if element already exists */
1447 int check_overwrite(void)
1448 {
1449  struct Option *opt;
1450  char age[KEYLENGTH];
1451  char element[KEYLENGTH];
1452  char desc[KEYLENGTH];
1453  int error = 0;
1454  const char *overstr;
1455  int over;
1456 
1457  st->module_info.overwrite = 0;
1458 
1459  if (!st->n_opts)
1460  return (0);
1461 
1462  over = 0;
1463  /* Check the GRASS OVERWRITE variable */
1464  if ((overstr = G_getenv_nofatal("OVERWRITE"))) {
1465  over = atoi(overstr);
1466  }
1467 
1468  /* Check the GRASS_OVERWRITE environment variable */
1469  if ((overstr = getenv("GRASS_OVERWRITE"))) {
1470  if (atoi(overstr))
1471  over = 1;
1472  }
1473 
1474  if (st->overwrite || over) {
1475  st->module_info.overwrite = 1;
1476  /* Set the environment so that programs run in a script also obey --o */
1477  putenv("GRASS_OVERWRITE=1");
1478  /* No need to check options for existing files if overwrite is true */
1479  return error;
1480  }
1481 
1482  opt = &st->first_option;
1483  while (opt) {
1484  if (opt->answer && opt->gisprompt) {
1485  split_gisprompt(opt->gisprompt, age, element, desc);
1486 
1487  if (strcmp(age, "new") == 0) {
1488  int i;
1489  char found;
1490 
1491  for (i = 0; opt->answers[i]; i++) {
1492  found = FALSE;
1493  if (strcmp(element, "file") == 0) {
1494  if (access(opt->answers[i], F_OK) == 0)
1495  found = TRUE;
1496  }
1497  else if (strcmp(element, "mapset") != 0) {
1498  /* TODO: also other elements should be
1499  probably skipped */
1500  if (G_find_file(element, opt->answers[i], G_mapset())) {
1501  found = TRUE;
1502  }
1503  }
1504 
1505  if (found) { /* found */
1506  if (!st->overwrite && !over) {
1507  if (G_verbose() > -1) {
1508  if (G_info_format() != G_INFO_FORMAT_GUI) {
1509  fprintf(stderr, _("ERROR: "));
1510  fprintf(stderr,
1511  _("option <%s>: <%s> exists. To overwrite, use the --overwrite flag"),
1512  opt->key, opt->answers[i]);
1513  fprintf(stderr, "\n");
1514  }
1515  else {
1516  fprintf(stderr, "GRASS_INFO_ERROR(%d,1): ", getpid());
1517  fprintf(stderr,
1518  _("option <%s>: <%s> exists. To overwrite, use the --overwrite flag"),
1519  opt->key, opt->answers[i]);
1520  fprintf(stderr, "\n");
1521  fprintf(stderr, "GRASS_INFO_END(%d,1)\n",
1522  getpid());
1523  }
1524  }
1525  error = 1;
1526  }
1527  }
1528  }
1529  }
1530  }
1531  opt = opt->next_opt;
1532  }
1533 
1534  return (error);
1535 }
1536 
1537 void split_gisprompt(const char *gisprompt, char *age, char *element,
1538  char *desc)
1539 {
1540  const char *ptr1;
1541  char *ptr2;
1542 
1543  for (ptr1 = gisprompt, ptr2 = age; *ptr1 != '\0'; ptr1++, ptr2++) {
1544  if (*ptr1 == ',')
1545  break;
1546  *ptr2 = *ptr1;
1547  }
1548  *ptr2 = '\0';
1549 
1550  for (ptr1++, ptr2 = element; *ptr1 != '\0'; ptr1++, ptr2++) {
1551  if (*ptr1 == ',')
1552  break;
1553  *ptr2 = *ptr1;
1554  }
1555  *ptr2 = '\0';
1556 
1557  for (ptr1++, ptr2 = desc; *ptr1 != '\0'; ptr1++, ptr2++) {
1558  if (*ptr1 == ',')
1559  break;
1560  *ptr2 = *ptr1;
1561  }
1562  *ptr2 = '\0';
1563 }
1564 
1565 void append_error(const char *msg)
1566 {
1567  st->error = G_realloc(st->error, sizeof(char *) * (st->n_errors + 1));
1568  st->error[st->n_errors++] = G_store(msg);
1569 }
1570 
1571 const char *get_renamed_option(const char *key)
1572 {
1573  const char *pgm, *key_new;
1574  char *pgm_key;
1575 
1576  if (!st->renamed_options) {
1577  /* read renamed options from file (renamed_options) */
1578  char path[GPATH_MAX];
1579 
1580  G_snprintf(path, GPATH_MAX, "%s/etc/renamed_options", G_gisbase());
1581  st->renamed_options = G_read_key_value_file(path);
1582  }
1583 
1584  /* try to check global changes first */
1585  key_new = G_find_key_value(key, st->renamed_options);
1586  if (key_new)
1587  return key_new;
1588 
1589  /* then check module-relevant changes */
1590  pgm = G_program_name();
1591  pgm_key = (char *) G_malloc (strlen(pgm) + strlen(key) + 2);
1592  G_asprintf(&pgm_key, "%s|%s", pgm, key);
1593 
1594  key_new = G_find_key_value(pgm_key, st->renamed_options);
1595  G_free(pgm_key);
1596 
1597  return key_new;
1598 }
1599 
1622 char* G_option_to_separator(const struct Option *option)
1623 {
1624  char* sep;
1625 
1626  if (option->gisprompt == NULL ||
1627  strcmp(option->gisprompt, "old,separator,separator") != 0)
1628  G_fatal_error(_("%s= is not a separator option"), option->key);
1629 
1630  if (option->answer == NULL)
1631  G_fatal_error(_("No separator given for %s="), option->key);
1632 
1633  if (strcmp(option->answer, "pipe") == 0)
1634  sep = G_store("|");
1635  else if (strcmp(option->answer, "comma") == 0)
1636  sep = G_store(",");
1637  else if (strcmp(option->answer, "space") == 0)
1638  sep = G_store(" ");
1639  else if (strcmp(option->answer, "tab") == 0 ||
1640  strcmp(option->answer, "\\t") == 0)
1641  sep = G_store("\t");
1642  else if (strcmp(option->answer, "newline") == 0 ||
1643  strcmp(option->answer, "\\n") == 0)
1644  sep = G_store("\n");
1645  else
1646  sep = G_store(option->answer);
1647 
1648  G_debug(2, "G_option_to_separator(): key = %s -> sep = '%s'",
1649  option->key, sep);
1650 
1651  return sep;
1652 }
1653 
1684 FILE *G_open_option_file(const struct Option *option)
1685 {
1686  int stdinout;
1687  FILE *fp;
1688 
1689  stdinout = !option->answer || !*(option->answer) ||
1690  strcmp(option->answer, "-") == 0;
1691 
1692  if (option->gisprompt == NULL)
1693  G_fatal_error(_("%s= is not a file option"), option->key);
1694  else if (option->multiple)
1695  G_fatal_error(_("Opening multiple files not supported for %s="),
1696  option->key);
1697  else if (strcmp(option->gisprompt, "old,file,file") == 0) {
1698  if (stdinout)
1699  fp = stdin;
1700  else if ((fp = fopen(option->answer, "r")) == NULL)
1701  G_fatal_error(_("Unable to open %s file <%s>"),
1702  option->key, option->answer);
1703  } else if (strcmp(option->gisprompt, "new,file,file") == 0) {
1704  if (stdinout)
1705  fp = stdout;
1706  else if ((fp = fopen(option->answer, "w")) == NULL)
1707  G_fatal_error(_("Unable to create %s file <%s>"),
1708  option->key, option->answer);
1709  } else
1710  G_fatal_error(_("%s= is not a file option"), option->key);
1711 
1712  return fp;
1713 }
1714 
1721 void G_close_option_file(FILE *fp)
1722 {
1723  if (fp != stdin && fp != stdout && fp != stderr)
1724  fclose(fp);
1725 }
int G__uses_new_gisprompt(void)
Definition: parser.c:779
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:839
#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:1622
char * G_recreate_command(void)
Creates command to run non-interactive.
Definition: parser.c:622
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:185
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:1721
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:771
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 &#39;.&#39;) 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
int G_verbose_std(void)
Get standard verbosity level.
Definition: verbose.c:86
void G_free_tokens(char **tokens)
Free memory allocated to tokens.
Definition: token.c:204
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 &#39;-&#39;, it returns either stdin or stdout based on the gisprompt.
Definition: parser.c:1684
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:48
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:815
void G_add_keyword(const char *keyword)
Add keyword to the list.
Definition: parser.c:755
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