GRASS GIS 8 Programmer's Manual  8.2.2dev(2023)-3d2c704037
parser_help.c
Go to the documentation of this file.
1 /*!
2  \file lib/gis/parser_help.c
3 
4  \brief GIS Library - Argument parsing functions (help)
5 
6  (C) 2001-2009, 2011 by the GRASS Development Team
7 
8  This program is free software under the GNU General Public License
9  (>=v2). Read the file COPYING that comes with GRASS for details.
10 
11  \author Original author CERL
12  \author Soeren Gebbert added Dec. 2009 WPS process_description document
13 */
14 
15 #include <stdio.h>
16 #include <string.h>
17 #include <stdlib.h>
18 
19 #include <grass/gis.h>
20 #include <grass/glocale.h>
21 
22 #include "parser_local_proto.h"
23 
24 static void usage(FILE *fp, int markers);
25 static void show_options(FILE *fp, int maxlen, const char *str);
26 static int show(FILE *fp, const char *item, int len);
27 
28 /*!
29  \brief Command line help/usage message.
30 
31  Calls to G_usage() allow the programmer to print the usage
32  message at any time. This will explain the allowed and required
33  command line input to the user. This description is given according
34  to the programmer's definitions for options and flags. This function
35  becomes useful when the user enters options and/or flags on the
36  command line that are syntactically valid to the parser, but
37  functionally invalid for the command (e.g. an invalid file name.)
38 
39  For example, the parser logic doesn't directly support grouping
40  options. If two options be specified together or not at all, the
41  parser must be told that these options are not required and the
42  programmer must check that if one is specified the other must be as
43  well. If this additional check fails, then G_parser() will succeed,
44  but the programmer can then call G_usage() to print the standard
45  usage message and print additional information about how the two
46  options work together.
47 */
48 void G_usage(void)
49 {
50  usage(stderr, 0);
51 }
52 
53 void G__usage_text(void)
54 {
55  usage(stdout, 1);
56 }
57 
58 static void usage(FILE *fp, int markers)
59 {
60  struct Option *opt;
61  struct Flag *flag;
62  char item[256];
63  const char *key_desc;
64  int maxlen;
65  int len, n;
66  int new_prompt = 0;
67  int extensive = 0; /* include also less important parts */
68  int standard = 0; /* include also standard flags */
69  int detailed = 0; /* details for each flag and option */
70 
71  new_prompt = G__uses_new_gisprompt();
72 
73  if (!st->pgm_name) /* v.dave && r.michael */
74  st->pgm_name = G_program_name();
75  if (!st->pgm_name)
76  st->pgm_name = "??";
77 
78  if (st->module_info.label || st->module_info.description) {
79  if (extensive)
80  fprintf(fp, "\n");
81  if (markers)
82  fprintf(fp, "{{{DESCRIPTION}}}\n");
83  if (extensive) {
84  fprintf(fp, "%s\n", _("Description:"));
85  if (st->module_info.label)
86  fprintf(fp, " %s\n", st->module_info.label);
87  if (st->module_info.description)
88  fprintf(fp, " %s\n", st->module_info.description);
89  }
90  else {
91  /* print label, if no label, try description */
92  /* no leading space without heading */
93  if (st->module_info.label)
94  fprintf(fp, "%s\n", st->module_info.label);
95  else if (st->module_info.description)
96  fprintf(fp, "%s\n", st->module_info.description);
97  }
98  }
99  if (extensive && st->module_info.keywords) {
100  fprintf(fp, "\n");
101  if (markers)
102  fprintf(fp, "{{{KEYWORDS}}}\n");
103  fprintf(fp, "%s\n ", _("Keywords:"));
104  G__print_keywords(fp, NULL);
105  fprintf(fp, "\n");
106  }
107 
108  fprintf(fp, "\n");
109  if (markers)
110  fprintf(fp, "{{{USAGE}}}\n");
111  fprintf(fp, "%s\n ", _("Usage:"));
112 
113  len = show(fp, st->pgm_name, 1);
114 
115  /* Print flags */
116 
117  if (st->n_flags) {
118  item[0] = ' ';
119  item[1] = '[';
120  item[2] = '-';
121  flag = &st->first_flag;
122  for (n = 3; flag != NULL; n++, flag = flag->next_flag)
123  item[n] = flag->key;
124  item[n++] = ']';
125  item[n] = 0;
126  len = show(fp, item, len);
127  }
128 
129  maxlen = 0;
130  if (st->n_opts) {
131  opt = &st->first_option;
132  while (opt != NULL) {
133  if (opt->key_desc != NULL)
134  key_desc = opt->key_desc;
135  else if (opt->type == TYPE_STRING)
136  key_desc = "string";
137  else
138  key_desc = "value";
139 
140  if (!opt->key) {
141  fprintf(stderr, "\n%s\n", _("ERROR: Option key not defined"));
142  exit(EXIT_FAILURE);
143  }
144  n = strlen(opt->key);
145  if (n > maxlen)
146  maxlen = n;
147 
148  strcpy(item, " ");
149  if (!opt->required)
150  strcat(item, "[");
151  strcat(item, opt->key);
152  strcat(item, "=");
153  strcat(item, key_desc);
154  if (opt->multiple) {
155  strcat(item, "[,");
156  strcat(item, key_desc);
157  strcat(item, ",...]");
158  }
159  if (!opt->required)
160  strcat(item, "]");
161 
162  len = show(fp, item, len);
163 
164  opt = opt->next_opt;
165  }
166  }
167  if (new_prompt) {
168  strcpy(item, " [--overwrite]");
169  len = show(fp, item, len);
170  }
171 
172  strcpy(item, " [--help]");
173  len = show(fp, item, len);
174 
175  strcpy(item, " [--verbose]");
176  len = show(fp, item, len);
177 
178  strcpy(item, " [--quiet]");
179  len = show(fp, item, len);
180 
181  strcpy(item, " [--ui]");
182  len = show(fp, item, len);
183 
184  fprintf(fp, "\n");
185 
186  /* Print help info for flags */
187 
188  /* Show section only when there are flags.
189  * There are always the standard flags if we are printing those.
190  * There is no use case for the markers, so no way to decide if
191  * the marker for flags is mandatory and should be empty if it is
192  * okay for it to be missing like in the current implementation.
193  */
194  if (st->n_flags || standard) {
195  fprintf(fp, "\n");
196  if (markers)
197  fprintf(fp, "{{{FLAGS}}}\n");
198  fprintf(fp, "%s\n", _("Flags:"));
199  }
200 
201  if (st->n_flags) {
202  flag = &st->first_flag;
203  while (flag != NULL) {
204  fprintf(fp, " -%c ", flag->key);
205 
206  if (flag->label) {
207  fprintf(fp, "%s\n", flag->label);
208  if (detailed && flag->description)
209  fprintf(fp, " %s\n", flag->description);
210 
211  }
212  else if (flag->description) {
213  fprintf(fp, "%s\n", flag->description);
214  }
215 
216  flag = flag->next_flag;
217  }
218  }
219 
220  if (standard) {
221  if (new_prompt)
222  fprintf(fp, " --o %s\n",
223  _("Allow output files to overwrite existing files"));
224 
225  fprintf(fp, " --h %s\n", _("Print usage summary"));
226  fprintf(fp, " --v %s\n", _("Verbose module output"));
227  fprintf(fp, " --q %s\n", _("Quiet module output"));
228  fprintf(fp, " --qq %s\n", _("Super quiet module output"));
229  fprintf(fp, " --ui %s\n", _("Force launching GUI dialog"));
230  }
231 
232  /* Print help info for options */
233 
234  if (st->n_opts) {
235  fprintf(fp, "\n");
236  if (markers)
237  fprintf(fp, "{{{PARAMETERS}}}\n");
238  fprintf(fp, "%s\n", _("Parameters:"));
239  opt = &st->first_option;
240  while (opt != NULL) {
241  fprintf(fp, " %*s ", maxlen, opt->key);
242 
243  if (opt->label) {
244  fprintf(fp, "%s\n", opt->label);
245  if (detailed && opt->description) {
246  fprintf(fp, " %*s %s\n",
247  maxlen, " ", opt->description);
248  }
249  }
250  else if (opt->description) {
251  fprintf(fp, "%s\n", opt->description);
252  }
253 
254  if (opt->options)
255  show_options(fp, maxlen, opt->options);
256  /*
257  fprintf (fp, " %*s options: %s\n", maxlen, " ",
258  _(opt->options)) ;
259  */
260  if (opt->def)
261  fprintf(fp, _(" %*s default: %s\n"), maxlen, " ",
262  opt->def);
263 
264  if (detailed && opt->descs) {
265  int i = 0;
266 
267  while (opt->opts[i]) {
268  if (opt->descs[i])
269  fprintf(fp, " %*s %s: %s\n",
270  maxlen, " ", opt->opts[i], opt->descs[i]);
271 
272  i++;
273  }
274  }
275 
276  opt = opt->next_opt;
277  }
278  }
279 }
280 
281 static void show_options(FILE *fp, int maxlen, const char *str)
282 {
283  char *buff = G_store(str);
284  char *p1, *p2;
285  int totlen, len;
286 
287  fprintf(fp, _(" %*s options: "), maxlen, " ");
288  totlen = maxlen + 13;
289  p1 = buff;
290  while ((p2 = strchr(p1, ','))) {
291  *p2 = '\0';
292  len = strlen(p1) + 1;
293  if ((len + totlen) > 76) {
294  totlen = maxlen + 13;
295  fprintf(fp, "\n %*s", maxlen + 13, " ");
296  }
297  fprintf(fp, "%s,", p1);
298  totlen += len;
299  p1 = p2 + 1;
300  }
301  len = strlen(p1);
302  if ((len + totlen) > 76)
303  fprintf(fp, "\n %*s", maxlen + 13, " ");
304  fprintf(fp, "%s\n", p1);
305 
306  G_free(buff);
307 }
308 
309 static int show(FILE *fp, const char *item, int len)
310 {
311  int n;
312 
313  n = strlen(item) + (len > 0);
314  if (n + len > 76) {
315  if (len)
316  fprintf(fp, "\n ");
317  len = 0;
318  }
319  fprintf(fp, "%s", item);
320  return n + len;
321 }
int G__uses_new_gisprompt(void)
Definition: parser.c:874
const char ** opts
Definition: gis.h:549
const char * G_program_name(void)
Return module name.
Definition: progrm_nme.c:28
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:149
#define TYPE_STRING
Definition: gis.h:172
#define NULL
Definition: ccmath.h:32
void G__usage_text(void)
Definition: parser_help.c:53
const char * def
Definition: gis.h:556
const char * description
Definition: gis.h:552
int type
Definition: gis.h:545
struct state * st
Definition: parser.c:104
int multiple
Definition: gis.h:547
Structure that stores flag info.
Definition: gis.h:571
char key
Definition: gis.h:573
int required
Definition: gis.h:546
struct Flag * next_flag
Definition: gis.h:580
const char * label
Definition: gis.h:577
const char * label
Definition: gis.h:551
const char ** descs
Definition: gis.h:554
void G_usage(void)
Command line help/usage message.
Definition: parser_help.c:48
Structure that stores option information.
Definition: gis.h:542
#define _(str)
Definition: glocale.h:10
const char * description
Definition: gis.h:578
char * G_store(const char *)
Copy string to allocated memory.
Definition: strings.c:87
const char * key
Definition: gis.h:544
void G__print_keywords(FILE *fd, void(*format)(FILE *, const char *))
Print list of keywords (internal use only)
Definition: parser.c:910
const char * options
Definition: gis.h:548
const char * key_desc
Definition: gis.h:550
struct Option * next_opt
Definition: gis.h:558