parser_interface.c 8.8 KB

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