GRASS GIS 8 Programmer's Manual 8.3.2(2024)-exported
Loading...
Searching...
No Matches
parser_interface.c
Go to the documentation of this file.
1/*!
2 * \file lib/gis/parser_interface.c
3 *
4 * \brief GIS Library - Argument parsing functions (interface)
5 *
6 * (C) 2001-2009 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 <grass/config.h>
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <ctype.h>
21#include <unistd.h>
22#include <stdarg.h>
23#include <sys/types.h>
24
25#if defined(HAVE_LANGINFO_H)
26#include <langinfo.h>
27#endif
28#if defined(__MINGW32__) && defined(USE_NLS)
29#include <localcharset.h>
30#endif
31#ifdef HAVE_ICONV_H
32#include <iconv.h>
33#endif
34
35#include <grass/gis.h>
36#include <grass/glocale.h>
37#include <grass/spawn.h>
38
39#include "parser_local_proto.h"
40
41#ifdef HAVE_ICONV_H
42static const char *src_enc;
43#endif
44
45/*!
46 * \brief Formats text for XML.
47 *
48 * \param[in,out] fp file to write to
49 * \param str string to write
50 */
51static void print_escaped_for_xml(FILE *fp, const char *str)
52{
53#ifdef HAVE_ICONV_H
54 iconv_t conv = iconv_open("UTF-8", src_enc);
55 char *enc = NULL;
56
57 if (conv != (iconv_t)-1) {
58 char *src = (char *)str;
59 size_t srclen = strlen(src);
60 size_t dstlen = srclen * 4 + 1;
61 char *dst = G_alloca(dstlen);
62 size_t ret;
63
64 enc = dst;
65
66 ret = iconv(conv, (char **)&src, &srclen, &dst, &dstlen);
67 if (ret != (size_t)-1 && srclen == 0) {
68 str = enc;
69 *dst = '\0';
70 }
71 }
72#endif
73
74 for (; *str; str++) {
75 switch (*str) {
76 case '&':
77 fputs("&amp;", fp);
78 break;
79 case '<':
80 fputs("&lt;", fp);
81 break;
82 case '>':
83 fputs("&gt;", fp);
84 break;
85 default:
86 fputc(*str, fp);
87 }
88 }
89
90#ifdef HAVE_ICONV_H
91 if (enc) {
92 G_freea(enc);
93 }
94
95 if (conv != (iconv_t)-1)
96 iconv_close(conv);
97#endif
98}
99
100/*!
101 \brief Print module usage description in XML format.
102 */
103void G__usage_xml(void)
104{
105 struct Option *opt;
106 struct Flag *flag;
107 char *type;
108 char *s, *top;
109 int i;
110 const char *encoding;
111 int new_prompt = 0;
112
113 new_prompt = G__uses_new_gisprompt();
114
115 /* gettext converts strings to encoding returned by nl_langinfo(CODESET) */
116
117#if defined(HAVE_LANGINFO_H)
118 encoding = nl_langinfo(CODESET);
119#elif defined(__MINGW32__) && defined(USE_NLS)
120 encoding = locale_charset();
121#endif
122
123 if (!encoding || strlen(encoding) == 0)
124 encoding = "UTF-8";
125
126#ifdef HAVE_ICONV_H
127 src_enc = encoding;
128 encoding = "UTF-8";
129#endif
130
131 if (!st->pgm_name) /* v.dave && r.michael */
132 st->pgm_name = G_program_name();
133 if (!st->pgm_name)
134 st->pgm_name = "??";
135
136 fprintf(stdout, "<?xml version=\"1.0\" encoding=\"%s\"?>\n", encoding);
137 fprintf(stdout, "<!DOCTYPE task SYSTEM \"grass-interface.dtd\">\n");
138
139 fprintf(stdout, "<task name=\"%s\">\n", st->pgm_name);
140
141 if (st->module_info.label) {
142 fprintf(stdout, "\t<label>\n\t\t");
143 print_escaped_for_xml(stdout, st->module_info.label);
144 fprintf(stdout, "\n\t</label>\n");
145 }
146
147 if (st->module_info.description) {
148 fprintf(stdout, "\t<description>\n\t\t");
149 print_escaped_for_xml(stdout, st->module_info.description);
150 fprintf(stdout, "\n\t</description>\n");
151 }
152
153 if (st->module_info.keywords) {
154 fprintf(stdout, "\t<keywords>\n\t\t");
155 G__print_keywords(stdout, print_escaped_for_xml);
156 fprintf(stdout, "\n\t</keywords>\n");
157 }
158
159 /***** Don't use parameter-groups for now. We'll reimplement this later
160 ***** when we have a concept of several mutually exclusive option
161 ***** groups
162 if (st->n_opts || st->n_flags)
163 fprintf(stdout, "\t<parameter-group>\n");
164 *****
165 *****
166 *****/
167
168 if (st->n_opts) {
169 opt = &st->first_option;
170 while (opt != NULL) {
171 /* TODO: make this a enumeration type? */
172 switch (opt->type) {
173 case TYPE_INTEGER:
174 type = "integer";
175 break;
176 case TYPE_DOUBLE:
177 type = "float";
178 break;
179 case TYPE_STRING:
180 type = "string";
181 break;
182 default:
183 type = "string";
184 break;
185 }
186 fprintf(stdout,
187 "\t<parameter "
188 "name=\"%s\" "
189 "type=\"%s\" "
190 "required=\"%s\" "
191 "multiple=\"%s\">\n",
192 opt->key, type, opt->required == YES ? "yes" : "no",
193 opt->multiple == YES ? "yes" : "no");
194
195 if (opt->label) {
196 fprintf(stdout, "\t\t<label>\n\t\t\t");
197 print_escaped_for_xml(stdout, opt->label);
198 fprintf(stdout, "\n\t\t</label>\n");
199 }
200
201 if (opt->description) {
202 fprintf(stdout, "\t\t<description>\n\t\t\t");
203 print_escaped_for_xml(stdout, opt->description);
204 fprintf(stdout, "\n\t\t</description>\n");
205 }
206
207 if (opt->key_desc) {
208 fprintf(stdout, "\t\t<keydesc>\n");
209 top = G_calloc(strlen(opt->key_desc) + 1, 1);
210 strcpy(top, opt->key_desc);
211 s = strtok(top, ",");
212 for (i = 1; s != NULL; i++) {
213 fprintf(stdout, "\t\t\t<item order=\"%d\">", i);
214 print_escaped_for_xml(stdout, s);
215 fprintf(stdout, "</item>\n");
216 s = strtok(NULL, ",");
217 }
218 fprintf(stdout, "\t\t</keydesc>\n");
219 G_free(top);
220 }
221
222 if (opt->gisprompt) {
223 const char *atts[] = {"age", "element", "prompt", NULL};
224 top = G_calloc(strlen(opt->gisprompt) + 1, 1);
225 strcpy(top, opt->gisprompt);
226 s = strtok(top, ",");
227 fprintf(stdout, "\t\t<gisprompt ");
228 for (i = 0; s != NULL && atts[i] != NULL; i++) {
229 fprintf(stdout, "%s=\"%s\" ", atts[i], s);
230 s = strtok(NULL, ",");
231 }
232 fprintf(stdout, "/>\n");
233 G_free(top);
234 }
235
236 if (opt->def) {
237 fprintf(stdout, "\t\t<default>\n\t\t\t");
238 print_escaped_for_xml(stdout, opt->def);
239 fprintf(stdout, "\n\t\t</default>\n");
240 }
241
242 if (opt->options) {
243 /* TODO:
244 * add something like
245 * <range min="xxx" max="xxx"/>
246 * to <values> */
247 i = 0;
248 fprintf(stdout, "\t\t<values>\n");
249 while (opt->opts[i]) {
250 fprintf(stdout, "\t\t\t<value>\n");
251 fprintf(stdout, "\t\t\t\t<name>");
252 print_escaped_for_xml(stdout, opt->opts[i]);
253 fprintf(stdout, "</name>\n");
254 if (opt->descs && opt->opts[i] && opt->descs[i]) {
255 fprintf(stdout, "\t\t\t\t<description>");
256 print_escaped_for_xml(stdout, opt->descs[i]);
257 fprintf(stdout, "</description>\n");
258 }
259 fprintf(stdout, "\t\t\t</value>\n");
260 i++;
261 }
262 fprintf(stdout, "\t\t</values>\n");
263 }
264 if (opt->guisection) {
265 fprintf(stdout, "\t\t<guisection>\n\t\t\t");
266 print_escaped_for_xml(stdout, opt->guisection);
267 fprintf(stdout, "\n\t\t</guisection>\n");
268 }
269 if (opt->guidependency) {
270 fprintf(stdout, "\t\t<guidependency>\n\t\t\t");
271 print_escaped_for_xml(stdout, opt->guidependency);
272 fprintf(stdout, "\n\t\t</guidependency>\n");
273 }
274 /* TODO:
275 * - key_desc?
276 * - there surely are some more. which ones?
277 */
278
279 opt = opt->next_opt;
280 fprintf(stdout, "\t</parameter>\n");
281 }
282 }
283
284 if (st->n_flags) {
285 flag = &st->first_flag;
286 while (flag != NULL) {
287 fprintf(stdout, "\t<flag name=\"%c\">\n", flag->key);
288
289 if (flag->label) {
290 fprintf(stdout, "\t\t<label>\n\t\t\t");
291 print_escaped_for_xml(stdout, flag->label);
292 fprintf(stdout, "\n\t\t</label>\n");
293 }
294
295 if (flag->suppress_required)
296 fprintf(stdout, "\t\t<suppress_required/>\n");
297
298 if (flag->description) {
299 fprintf(stdout, "\t\t<description>\n\t\t\t");
300 print_escaped_for_xml(stdout, flag->description);
301 fprintf(stdout, "\n\t\t</description>\n");
302 }
303 if (flag->guisection) {
304 fprintf(stdout, " \t\t<guisection>\n\t\t\t");
305 print_escaped_for_xml(stdout, flag->guisection);
306 fprintf(stdout, "\n\t\t</guisection>\n");
307 }
308 flag = flag->next_flag;
309 fprintf(stdout, "\t</flag>\n");
310 }
311 }
312
313 /***** Don't use parameter-groups for now. We'll reimplement this later
314 ***** when we have a concept of several mutually exclusive option
315 ***** groups
316 if (st->n_opts || st->n_flags)
317 fprintf(stdout, "\t</parameter-group>\n");
318 *****
319 *****
320 *****/
321
322 if (new_prompt) {
323 /* overwrite */
324 fprintf(stdout, "\t<flag name=\"%s\">\n", "overwrite");
325 fprintf(stdout, "\t\t<description>\n\t\t\t");
326 print_escaped_for_xml(
327 stdout, _("Allow output files to overwrite existing files"));
328 fprintf(stdout, "\n\t\t</description>\n");
329 fprintf(stdout, "\t</flag>\n");
330 }
331
332 /* help */
333 fprintf(stdout, "\t<flag name=\"%s\">\n", "help");
334 fprintf(stdout, "\t\t<description>\n\t\t\t");
335 print_escaped_for_xml(stdout, _("Print usage summary"));
336 fprintf(stdout, "\n\t\t</description>\n");
337 fprintf(stdout, "\t</flag>\n");
338
339 /* verbose */
340 fprintf(stdout, "\t<flag name=\"%s\">\n", "verbose");
341 fprintf(stdout, "\t\t<description>\n\t\t\t");
342 print_escaped_for_xml(stdout, _("Verbose module output"));
343 fprintf(stdout, "\n\t\t</description>\n");
344 fprintf(stdout, "\t</flag>\n");
345
346 /* quiet */
347 fprintf(stdout, "\t<flag name=\"%s\">\n", "quiet");
348 fprintf(stdout, "\t\t<description>\n\t\t\t");
349 print_escaped_for_xml(stdout, _("Quiet module output"));
350 fprintf(stdout, "\n\t\t</description>\n");
351 fprintf(stdout, "\t</flag>\n");
352
354
355 fprintf(stdout, "</task>\n");
356}
void G_free(void *buf)
Free allocated memory.
Definition alloc.c:150
#define NULL
Definition ccmath.h:32
int G__uses_new_gisprompt(void)
Definition parser.c:883
struct state * st
Definition parser.c:104
void G__print_keywords(FILE *fd, void(*format)(FILE *, const char *))
Print list of keywords (internal use only)
Definition parser.c:919
void G__describe_option_rules_xml(FILE *fp)
Describe option rules in XML format (internal use only)
void G__usage_xml(void)
Print module usage description in XML format.
const char * G_program_name(void)
Return module name.
Definition progrm_nme.c:28