00001
00069 #include <grass/config.h>
00070
00071 #if defined(HAVE_LANGINFO_H)
00072 #include <langinfo.h>
00073 #endif
00074
00075 #include <stdio.h>
00076 #include <stdlib.h>
00077 #include <string.h>
00078 #include <ctype.h>
00079 #include <unistd.h>
00080 #include <stdarg.h>
00081 #include <sys/types.h>
00082 #include <grass/gis.h>
00083 #include <grass/glocale.h>
00084 #include <grass/spawn.h>
00085
00086
00087 #define BAD_SYNTAX 1
00088 #define OUT_OF_RANGE 2
00089 #define MISSING_VALUE 3
00090 #define KEYLENGTH 64
00091
00092 static int interactive_ok = 1;
00093 static int n_opts = 0;
00094 static int n_flags = 0;
00095 static int overwrite = 0;
00096 static int quiet = 0;
00097
00098 static struct Flag first_flag;
00099 static struct Flag *current_flag;
00100
00101 static struct Option first_option;
00102 static struct Option *current_option;
00103
00104 static struct GModule module_info;
00105
00106 static const char *pgm_name = NULL;
00107
00108 struct Item
00109 {
00110 struct Option *option;
00111 struct Flag *flag;
00112 struct Item *next_item;
00113 };
00114
00115 static struct Item first_item;
00116 static struct Item *current_item;
00117 static int n_items = 0;
00118 static int show_options(int, const char *);
00119 static int show(const char *, int);
00120 static int set_flag(int);
00121 static int contains(const char *, int);
00122 static int is_option(const char *);
00123 static int set_option(char *);
00124 static int check_opts();
00125 static int check_an_opt(const char *, int, const char *, const char *);
00126 static int check_int(const char *, const char *);
00127 static int check_double(const char *, const char *);
00128 static int check_string(const char *, const char *);
00129 static int check_required(void);
00130 static int split_opts(void);
00131 static int check_multiple_opts(void);
00132 static int check_overwrite(void);
00133 static int interactive(const char *);
00134 static int interactive_flag(struct Flag *);
00135 static int interactive_option(struct Option *);
00136 static int gis_prompt(struct Option *, char *);
00137 static int split_gisprompt(const char *, char *, char *, char *);
00138
00139 static void G_gui(void);
00140 static void G_tcltk(void);
00141 static void G_usage_xml(void);
00142 static void G_usage_html(void);
00143 static void G_script(void);
00144
00145
00158 int G_disable_interactive(void)
00159 {
00160 interactive_ok = 0;
00161
00162 return 0;
00163 }
00164
00165
00179 struct Flag *G_define_flag(void)
00180 {
00181 struct Flag *flag;
00182 struct Item *item;
00183
00184
00185
00186 if (n_flags) {
00187 flag = (struct Flag *)G_malloc(sizeof(struct Flag));
00188 current_flag->next_flag = flag;
00189 }
00190 else
00191 flag = &first_flag;
00192
00193
00194
00195 G_zero((char *)flag, sizeof(struct Flag));
00196
00197 current_flag = flag;
00198 n_flags++;
00199
00200 if (n_items) {
00201 item = (struct Item *)G_malloc(sizeof(struct Item));
00202 current_item->next_item = item;
00203 }
00204 else
00205 item = &first_item;
00206
00207 G_zero((char *)item, sizeof(struct Item));
00208
00209 item->flag = flag;
00210 item->option = NULL;
00211
00212 current_item = item;
00213 n_items++;
00214
00215 return (flag);
00216 }
00217
00218
00235 struct Option *G_define_option(void)
00236 {
00237 struct Option *opt;
00238 struct Item *item;
00239
00240
00241
00242 if (n_opts) {
00243 opt = (struct Option *)G_malloc(sizeof(struct Option));
00244 current_option->next_opt = opt;
00245 }
00246 else
00247 opt = &first_option;
00248
00249
00250 G_zero((char *)opt, sizeof(struct Option));
00251
00252 opt->required = NO;
00253 opt->multiple = NO;
00254 opt->answer = NULL;
00255 opt->answers = NULL;
00256 opt->def = NULL;
00257 opt->checker = NULL;
00258 opt->options = NULL;
00259 opt->key_desc = NULL;
00260 opt->gisprompt = NULL;
00261 opt->label = NULL;
00262 opt->opts = NULL;
00263 opt->description = NULL;
00264 opt->descriptions = NULL;
00265 opt->guisection = NULL;
00266
00267 current_option = opt;
00268 n_opts++;
00269
00270 if (n_items) {
00271 item = (struct Item *)G_malloc(sizeof(struct Item));
00272 current_item->next_item = item;
00273 }
00274 else
00275 item = &first_item;
00276
00277 G_zero((char *)item, sizeof(struct Item));
00278
00279 item->option = opt;
00280 item->flag = NULL;
00281
00282 current_item = item;
00283 n_items++;
00284
00285 return (opt);
00286 }
00287
00288
00315 struct Option *G_define_standard_option(int opt)
00316 {
00317 struct Option *Opt;
00318
00319 Opt = G_define_option();
00320
00321 switch (opt) {
00322
00323 case G_OPT_WHERE:
00324 Opt->key = "where";
00325 Opt->type = TYPE_STRING;
00326 Opt->key_desc = "sql_query";
00327 Opt->required = NO;
00328 Opt->label = _("WHERE conditions of SQL statement without 'where' keyword");
00329 Opt->description = _("Example: income < 1000 and inhab >= 10000");
00330 break;
00331 case G_OPT_TABLE:
00332 Opt->key = "table";
00333 Opt->type = TYPE_STRING;
00334 Opt->key_desc = "name";
00335 Opt->required = NO;
00336 Opt->multiple = NO;
00337 Opt->description = _("Table name");
00338 Opt->gisprompt = "old_dbtable,dbtable,dbtable";
00339 break;
00340 case G_OPT_DRIVER:
00341 Opt->key = "driver";
00342 Opt->type = TYPE_STRING;
00343 Opt->key_desc = "name";
00344 Opt->required = NO;
00345 Opt->multiple = NO;
00346 Opt->description = _("Driver name");
00347 Opt->gisprompt = "old_dbdriver,dbdriver,dbdriver";
00348 break;
00349 case G_OPT_DATABASE:
00350 Opt->key = "database";
00351 Opt->type = TYPE_STRING;
00352 Opt->key_desc = "name";
00353 Opt->required = NO;
00354 Opt->multiple = NO;
00355 Opt->description = _("Database name");
00356 Opt->gisprompt = "old_dbname,dbname,dbname";
00357 break;
00358 case G_OPT_COLUMN:
00359 Opt->key = "column";
00360 Opt->type = TYPE_STRING;
00361 Opt->key_desc = "name";
00362 Opt->required = NO;
00363 Opt->multiple = NO;
00364 Opt->description = _("Name of attribute column");
00365 Opt->gisprompt = "old_dbcolumn,dbcolumn,dbcolumn";
00366 break;
00367 case G_OPT_COLUMNS:
00368 Opt->key = "columns";
00369 Opt->type = TYPE_STRING;
00370 Opt->key_desc = "name";
00371 Opt->required = NO;
00372 Opt->multiple = YES;
00373 Opt->description = _("Name of attribute column(s)");
00374 Opt->gisprompt = "old_dbcolumn,dbcolumn,dbcolumn";
00375 break;
00376
00377
00378 case G_OPT_I_GROUP:
00379 Opt->key = "group";
00380 Opt->type = TYPE_STRING;
00381 Opt->key_desc = "name";
00382 Opt->required = YES;
00383 Opt->gisprompt = "old,group,group";
00384 Opt->description = _("Name of input imagery group");
00385 break;
00386 case G_OPT_I_SUBGROUP:
00387 Opt->key = "subgroup";
00388 Opt->type = TYPE_STRING;
00389 Opt->key_desc = "name";
00390 Opt->required = YES;
00391 Opt->gisprompt = "old,subgroup,subgroup";
00392 Opt->description = _("Name of input imagery subgroup");
00393 break;
00394
00395
00396 case G_OPT_R_INPUT:
00397 Opt->key = "input";
00398 Opt->type = TYPE_STRING;
00399 Opt->key_desc = "name";
00400 Opt->required = YES;
00401 Opt->gisprompt = "old,cell,raster";
00402 Opt->description = _("Name of input raster map");
00403 break;
00404 case G_OPT_R_INPUTS:
00405 Opt->key = "input";
00406 Opt->type = TYPE_STRING;
00407 Opt->key_desc = "name";
00408 Opt->required = YES;
00409 Opt->multiple = YES;
00410 Opt->gisprompt = "old,cell,raster";
00411 Opt->description = _("Name of input raster map(s)");
00412 break;
00413 case G_OPT_R_OUTPUT:
00414 Opt->key = "output";
00415 Opt->type = TYPE_STRING;
00416 Opt->key_desc = "name";
00417 Opt->required = YES;
00418 Opt->gisprompt = "new,cell,raster";
00419 Opt->description = _("Name for output raster map");
00420 break;
00421 case G_OPT_R_MAP:
00422 Opt->key = "map";
00423 Opt->type = TYPE_STRING;
00424 Opt->key_desc = "name";
00425 Opt->required = YES;
00426 Opt->gisprompt = "old,cell,raster";
00427 Opt->description = _("Name of input raster map");
00428 break;
00429 case G_OPT_R_MAPS:
00430 Opt->key = "map";
00431 Opt->type = TYPE_STRING;
00432 Opt->key_desc = "name";
00433 Opt->required = YES;
00434 Opt->multiple = YES;
00435 Opt->gisprompt = "old,cell,raster";
00436 Opt->description = _("Name of input raster map(s)");
00437 break;
00438 case G_OPT_R_BASE:
00439 Opt->key = "base";
00440 Opt->type = TYPE_STRING;
00441 Opt->key_desc = "name";
00442 Opt->required = YES;
00443 Opt->gisprompt = "old,cell,raster";
00444 Opt->description = _("Name of base raster map");
00445 break;
00446 case G_OPT_R_COVER:
00447 Opt->key = "cover";
00448 Opt->type = TYPE_STRING;
00449 Opt->key_desc = "name";
00450 Opt->required = YES;
00451 Opt->gisprompt = "old,cell,raster";
00452 Opt->description = _("Name of cover raster map");
00453 break;
00454 case G_OPT_R_ELEV:
00455 Opt->key = "elevation";
00456 Opt->type = TYPE_STRING;
00457 Opt->key_desc = "name";
00458 Opt->required = YES;
00459 Opt->gisprompt = "old,cell,raster";
00460 Opt->description = _("Name of elevation raster map");
00461 break;
00462 case G_OPT_R_ELEVS:
00463 Opt->key = "elevation";
00464 Opt->type = TYPE_STRING;
00465 Opt->key_desc = "name";
00466 Opt->required = YES;
00467 Opt->multiple = YES;
00468 Opt->gisprompt = "old,cell,raster";
00469 Opt->description = _("Name of elevation raster map(s)");
00470 break;
00471
00472
00473 case G_OPT_R3_INPUT:
00474 Opt->key = "input";
00475 Opt->type = TYPE_STRING;
00476 Opt->key_desc = "name";
00477 Opt->required = YES;
00478 Opt->gisprompt = "old,grid3,3d-raster";
00479 Opt->description = _("Name of input raster3d map");
00480 break;
00481 case G_OPT_R3_INPUTS:
00482 Opt->key = "input";
00483 Opt->type = TYPE_STRING;
00484 Opt->key_desc = "name";
00485 Opt->required = YES;
00486 Opt->multiple = YES;
00487 Opt->gisprompt = "old,grid3,3d-raster";
00488 Opt->description = _("Name of input raster3d map(s)");
00489 break;
00490 case G_OPT_R3_OUTPUT:
00491 Opt->key = "output";
00492 Opt->type = TYPE_STRING;
00493 Opt->key_desc = "name";
00494 Opt->required = YES;
00495 Opt->gisprompt = "new,grid3,3d-raster";
00496 Opt->description = _("Name for output raster3d map");
00497 break;
00498 case G_OPT_R3_MAP:
00499 Opt->key = "map";
00500 Opt->type = TYPE_STRING;
00501 Opt->key_desc = "name";
00502 Opt->required = YES;
00503 Opt->gisprompt = "old,grid3,3d-raster";
00504 Opt->description = _("Name of input raster3d map");
00505 break;
00506 case G_OPT_R3_MAPS:
00507 Opt->key = "map";
00508 Opt->type = TYPE_STRING;
00509 Opt->key_desc = "name";
00510 Opt->required = YES;
00511 Opt->multiple = YES;
00512 Opt->gisprompt = "old,grid3,3d-raster";
00513 Opt->description = _("Name of input raster3d map(s)");
00514 break;
00515
00516
00517 case G_OPT_V_INPUT:
00518 Opt->key = "input";
00519 Opt->type = TYPE_STRING;
00520 Opt->key_desc = "name";
00521 Opt->required = YES;
00522 Opt->gisprompt = "old,vector,vector";
00523 Opt->description = _("Name of input vector map");
00524 break;
00525 case G_OPT_V_INPUTS:
00526 Opt->key = "input";
00527 Opt->type = TYPE_STRING;
00528 Opt->key_desc = "name";
00529 Opt->required = YES;
00530 Opt->multiple = YES;
00531 Opt->gisprompt = "old,vector,vector";
00532 Opt->description = _("Name of input vector map(s)");
00533 break;
00534 case G_OPT_V_OUTPUT:
00535 Opt->key = "output";
00536 Opt->type = TYPE_STRING;
00537 Opt->key_desc = "name";
00538 Opt->required = YES;
00539 Opt->gisprompt = "new,vector,vector";
00540 Opt->description = _("Name for output vector map");
00541 break;
00542 case G_OPT_V_MAP:
00543 Opt->key = "map";
00544 Opt->type = TYPE_STRING;
00545 Opt->key_desc = "name";
00546 Opt->required = YES;
00547 Opt->gisprompt = "old,vector,vector";
00548 Opt->description = _("Name of input vector map");
00549 break;
00550 case G_OPT_V_MAPS:
00551 Opt->key = "map";
00552 Opt->type = TYPE_STRING;
00553 Opt->key_desc = "name";
00554 Opt->required = YES;
00555 Opt->multiple = YES;
00556 Opt->gisprompt = "old,vector,vector";
00557 Opt->description = _("Name of input vector map(s)");
00558 break;
00559 case G_OPT_V_TYPE:
00560 Opt->key = "type";
00561 Opt->type = TYPE_STRING;
00562 Opt->required = NO;
00563 Opt->multiple = YES;
00564 Opt->answer = "point,line,boundary,centroid,area";
00565 Opt->options = "point,line,boundary,centroid,area";
00566 Opt->description = _("Feature type");
00567 break;
00568 case G_OPT_V_FIELD:
00569 Opt->key = "layer";
00570 Opt->type = TYPE_INTEGER;
00571 Opt->required = NO;
00572 Opt->answer = "1";
00573 Opt->label = _("Layer number");
00574 Opt->description =
00575 _("A single vector map can be connected to multiple database "
00576 "tables. This number determines which table to use.");
00577 Opt->gisprompt = "old_layer,layer,layer";
00578
00579 break;
00580 case G_OPT_V_CAT:
00581 Opt->key = "cat";
00582 Opt->type = TYPE_INTEGER;
00583 Opt->required = NO;
00584 Opt->description = _("Category value");
00585 break;
00586 case G_OPT_V_CATS:
00587 Opt->key = "cats";
00588 Opt->type = TYPE_STRING;
00589 Opt->key_desc = "range";
00590 Opt->required = NO;
00591 Opt->label = _("Category values");
00592 Opt->description = _("Example: 1,3,7-9,13");
00593 break;
00594 case G_OPT_V_ID:
00595 Opt->key = "id";
00596 Opt->type = TYPE_INTEGER;
00597 Opt->required = NO;
00598 Opt->description = _("Feature id");
00599 break;
00600 case G_OPT_V_IDS:
00601 Opt->key = "ids";
00602 Opt->type = TYPE_STRING;
00603 Opt->key_desc = "range";
00604 Opt->required = NO;
00605 Opt->label = _("Feature ids");
00606 Opt->description = _("Example: 1,3,7-9,13");
00607 break;
00608
00609
00610 case G_OPT_F_INPUT:
00611 Opt->key = "input";
00612 Opt->type = TYPE_STRING;
00613 Opt->key_desc = "name";
00614 Opt->required = YES;
00615 Opt->gisprompt = "old_file,file,input";
00616 Opt->description = _("Name of input file");
00617 break;
00618 case G_OPT_F_OUTPUT:
00619 Opt->key = "output";
00620 Opt->type = TYPE_STRING;
00621 Opt->key_desc = "name";
00622 Opt->required = YES;
00623 Opt->gisprompt = "new_file,file,output";
00624 Opt->description = _("Name for output file");
00625 break;
00626 case G_OPT_F_SEP:
00627 Opt->key = "fs";
00628 Opt->type = TYPE_STRING;
00629 Opt->key_desc = "character";
00630 Opt->required = NO;
00631 Opt->answer = "|";
00632 Opt->description = _("Field separator");
00633 break;
00634
00635
00636 case G_OPT_C_FG:
00637 Opt->key = "color";
00638 Opt->type = TYPE_STRING;
00639 Opt->key_desc = "name";
00640 Opt->required = NO;
00641 Opt->answer = DEFAULT_FG_COLOR;
00642 Opt->gisprompt = "old_color,color,color";
00643 Opt->label = _("Color");
00644 Opt->description = _("Either a standard color name or R:G:B triplet");
00645 break;
00646 case G_OPT_C_BG:
00647 Opt->key = "bgcolor";
00648 Opt->type = TYPE_STRING;
00649 Opt->key_desc = "name";
00650 Opt->required = NO;
00651 Opt->answer = DEFAULT_BG_COLOR;
00652 Opt->gisprompt = "old_color,color,color_none";
00653 Opt->label = _("Background color");
00654 Opt->description =
00655 _("Either a standard GRASS color, R:G:B triplet, or \"none\"");
00656 break;
00657 }
00658
00659 return (Opt);
00660 }
00661
00662
00669 struct GModule *G_define_module(void)
00670 {
00671 struct GModule *module;
00672
00673
00674
00675 module = &module_info;
00676
00677
00678
00679 G_zero((char *)module, sizeof(struct GModule));
00680
00681 return (module);
00682 }
00683
00684
00685
00721 int G_parser(int argc, char **argv)
00722 {
00723 int need_first_opt;
00724 int opt_checked = 0;
00725 int error;
00726 char *ptr, *tmp_name;
00727 int i;
00728 struct Option *opt;
00729 char force_gui = FALSE;
00730
00731 error = 0;
00732 need_first_opt = 1;
00733 i = strlen(tmp_name = G_store(argv[0]));
00734 while (--i >= 0) {
00735 if (G_is_dirsep(tmp_name[i])) {
00736 tmp_name += i + 1;
00737 break;
00738 }
00739 }
00740 G_basename(tmp_name, "exe");
00741 pgm_name = tmp_name;
00742
00743
00744
00745 opt = &first_option;
00746 while (opt != NULL) {
00747
00748 if (opt->options) {
00749 int cnt = 0;
00750 char **tokens, delm[2];
00751
00752 delm[0] = ',';
00753 delm[1] = '\0';
00754 tokens = G_tokenize(opt->options, delm);
00755
00756 i = 0;
00757 while (tokens[i]) {
00758 cnt++;
00759 i++;
00760 }
00761
00762 opt->opts =
00763 (const char **)G_calloc(cnt + 1, sizeof(const char *));
00764
00765 i = 0;
00766 while (tokens[i]) {
00767 opt->opts[i] = G_store(tokens[i]);
00768 i++;
00769 }
00770 G_free_tokens(tokens);
00771
00772 if (opt->descriptions) {
00773 delm[0] = ';';
00774
00775 opt->descs =
00776 (const char **)G_calloc(cnt + 1, sizeof(const char *));
00777 tokens = G_tokenize(opt->descriptions, delm);
00778
00779 i = 0;
00780 while (tokens[i]) {
00781 int j, found;
00782
00783 if (!tokens[i + 1])
00784 break;
00785
00786 j = 0;
00787 found = 0;
00788 while (opt->opts[j]) {
00789 if (strcmp(opt->opts[j], tokens[i]) == 0) {
00790 found = 1;
00791 break;
00792 }
00793 j++;
00794 }
00795 if (!found) {
00796 G_warning(_("BUG in descriptions, option '%s' in <%s> does not exist"),
00797 tokens[i], opt->key);
00798 }
00799 else {
00800 opt->descs[j] = G_store(tokens[i + 1]);
00801 }
00802
00803 i += 2;
00804 }
00805 G_free_tokens(tokens);
00806 }
00807 }
00808
00809
00810 if (opt->multiple && opt->answers && opt->answers[0]) {
00811 opt->answer = (char *)G_malloc(strlen(opt->answers[0]) + 1);
00812 strcpy(opt->answer, opt->answers[0]);
00813 for (i = 1; opt->answers[i]; i++) {
00814 opt->answer = (char *)G_realloc(opt->answer,
00815 strlen(opt->answer) +
00816 strlen(opt->answers[i]) + 2);
00817 strcat(opt->answer, ",");
00818 strcat(opt->answer, opt->answers[i]);
00819 }
00820 }
00821 opt->def = opt->answer;
00822 opt = opt->next_opt;
00823 }
00824
00825
00826
00827 if (argc < 2 && interactive_ok && isatty(0)) {
00828 if (getenv("GRASS_UI_TERM")) {
00829 interactive(argv[0]);
00830 opt_checked = 1;
00831
00832 }
00833 else {
00834 G_gui();
00835 return -1;
00836 }
00837 }
00838 else if (argc < 2 && isatty(0)) {
00839 G_usage();
00840 return -1;
00841 }
00842 else if (argc >= 2) {
00843
00844
00845 if (strcmp(argv[1], "help") == 0 ||
00846 strcmp(argv[1], "-help") == 0 || strcmp(argv[1], "--help") == 0) {
00847 G_usage();
00848 exit(EXIT_SUCCESS);
00849 }
00850
00851
00852
00853 if (strcmp(argv[1], "--interface-description") == 0) {
00854 G_usage_xml();
00855 exit(EXIT_SUCCESS);
00856 }
00857
00858
00859
00860 if (strcmp(argv[1], "--html-description") == 0) {
00861 G_usage_html();
00862 exit(EXIT_SUCCESS);
00863 }
00864
00865
00866
00867 if (strcmp(argv[1], "--tcltk") == 0) {
00868 G_tcltk();
00869 exit(EXIT_SUCCESS);
00870 }
00871
00872
00873
00874 if (strcmp(argv[1], "--script") == 0) {
00875 G_script();
00876 exit(EXIT_SUCCESS);
00877 }
00878
00879
00880
00881 while (--argc) {
00882 ptr = *(++argv);
00883
00884
00885 if (strcmp(ptr, "--o") == 0 || strcmp(ptr, "--overwrite") == 0) {
00886 overwrite = 1;
00887 }
00888
00889
00890 else if (strcmp(ptr, "--v") == 0 || strcmp(ptr, "--verbose") == 0) {
00891 char buff[32];
00892
00893
00894 module_info.verbose = G_verbose_max();
00895 sprintf(buff, "GRASS_VERBOSE=%d", G_verbose_max());
00896 putenv(G_store(buff));
00897 if (quiet == 1) {
00898 G_warning(_("Use either --quiet or --verbose flag, not both. Assuming --verbose."));
00899 }
00900 quiet = -1;
00901 }
00902
00903
00904 else if (strcmp(ptr, "--q") == 0 || strcmp(ptr, "--quiet") == 0) {
00905 char buff[32];
00906
00907
00908 module_info.verbose = G_verbose_min();
00909 sprintf(buff, "GRASS_VERBOSE=%d", G_verbose_min());
00910 putenv(G_store(buff));
00911 if (quiet == -1) {
00912 G_warning(_("Use either --quiet or --verbose flag, not both. Assuming --quiet."));
00913 }
00914 quiet = 1;
00915 }
00916
00917
00918 else if (strcmp(ptr, "--ui") == 0) {
00919 force_gui = TRUE;
00920 }
00921
00922
00923 else if (*ptr == '-') {
00924 while (*(++ptr))
00925 error += set_flag(*ptr);
00926
00927 }
00928
00929 else if (is_option(ptr)) {
00930 error += set_option(ptr);
00931 need_first_opt = 0;
00932 }
00933
00934
00935 else if (need_first_opt && n_opts) {
00936 first_option.answer = G_store(ptr);
00937 need_first_opt = 0;
00938 }
00939
00940
00941 else if (contains(ptr, '=') == 0) {
00942 fprintf(stderr, _("Sorry <%s> is not a valid option\n"), ptr);
00943 error = 1;
00944 }
00945
00946 }
00947 }
00948
00949
00950 if (force_gui) {
00951 G_gui();
00952 return -1;
00953 }
00954
00955
00956 split_opts();
00957
00958
00959 error += check_multiple_opts();
00960
00961
00962 if (!opt_checked)
00963 error += check_opts();
00964
00965
00966 error += check_required();
00967
00968
00969 if (error) {
00970 if (G_verbose() > G_verbose_min())
00971 G_usage();
00972 return -1;
00973 }
00974
00975 if (check_overwrite())
00976 return -1;
00977
00978 return (0);
00979 }
00980
00981
00982 static int uses_new_gisprompt(void)
00983 {
00984 struct Option *opt;
00985 char age[KEYLENGTH];
00986 char element[KEYLENGTH];
00987 char desc[KEYLENGTH];
00988
00989
00990
00991 if (n_opts) {
00992 opt = &first_option;
00993 while (opt != NULL) {
00994 if (opt->gisprompt) {
00995 split_gisprompt(opt->gisprompt, age, element, desc);
00996 if (strcmp(age, "new") == 0)
00997 return 1;
00998 }
00999 opt = opt->next_opt;
01000 }
01001 }
01002
01003 return 0;
01004 }
01005
01006
01029 int G_usage(void)
01030 {
01031 struct Option *opt;
01032 struct Flag *flag;
01033 char item[256];
01034 const char *key_desc;
01035 int maxlen;
01036 int len, n;
01037 int new_prompt = 0;
01038
01039 new_prompt = uses_new_gisprompt();
01040
01041 if (!pgm_name)
01042 pgm_name = G_program_name();
01043 if (!pgm_name)
01044 pgm_name = "??";
01045
01046 if (module_info.label || module_info.description) {
01047 fprintf(stderr, _("\nDescription:\n"));
01048 if (module_info.label)
01049 fprintf(stderr, " %s\n", module_info.label);
01050 if (module_info.description)
01051 fprintf(stderr, " %s\n", module_info.description);
01052 }
01053 if (module_info.keywords) {
01054 fprintf(stderr, _("\nKeywords:\n"));
01055 fprintf(stderr, " %s\n", module_info.keywords);
01056 }
01057
01058 fprintf(stderr, _("\nUsage:\n "));
01059
01060 len = show(pgm_name, 1);
01061
01062
01063
01064 if (n_flags) {
01065 item[0] = ' ';
01066 item[1] = '[';
01067 item[2] = '-';
01068 flag = &first_flag;
01069 for (n = 3; flag != NULL; n++, flag = flag->next_flag)
01070 item[n] = flag->key;
01071 item[n++] = ']';
01072 item[n] = 0;
01073 len = show(item, len);
01074 }
01075
01076 maxlen = 0;
01077 if (n_opts) {
01078 opt = &first_option;
01079 while (opt != NULL) {
01080 if (opt->key_desc != NULL)
01081 key_desc = opt->key_desc;
01082 else if (opt->type == TYPE_STRING)
01083 key_desc = "string";
01084 else
01085 key_desc = "value";
01086
01087 n = strlen(opt->key);
01088 if (n > maxlen)
01089 maxlen = n;
01090
01091 strcpy(item, " ");
01092 if (!opt->required)
01093 strcat(item, "[");
01094 strcat(item, opt->key);
01095 strcat(item, "=");
01096 strcat(item, key_desc);
01097 if (opt->multiple) {
01098 strcat(item, "[,");
01099 strcat(item, key_desc);
01100 strcat(item, ",...]");
01101 }
01102 if (!opt->required)
01103 strcat(item, "]");
01104
01105 len = show(item, len);
01106
01107 opt = opt->next_opt;
01108 }
01109 }
01110 if (new_prompt) {
01111 strcpy(item, " [--overwrite]");
01112 len = show(item, len);
01113 }
01114
01115 strcpy(item, " [--verbose]");
01116 len = show(item, len);
01117
01118 strcpy(item, " [--quiet]");
01119 len = show(item, len);
01120
01121
01122 fprintf(stderr, "\n");
01123
01124
01125
01126 fprintf(stderr, _("\nFlags:\n"));
01127
01128 if (n_flags) {
01129 flag = &first_flag;
01130 while (flag != NULL) {
01131 fprintf(stderr, " -%c ", flag->key);
01132
01133 if (flag->label) {
01134 fprintf(stderr, "%s\n", flag->label);
01135 if (flag->description)
01136 fprintf(stderr, " %s\n", flag->description);
01137
01138 }
01139 else if (flag->description) {
01140 fprintf(stderr, "%s\n", flag->description);
01141 }
01142
01143 flag = flag->next_flag;
01144 }
01145 }
01146
01147 if (new_prompt)
01148 fprintf(stderr, " --o %s\n",
01149 _("Allow output files to overwrite existing files"));
01150
01151 fprintf(stderr, " --v %s\n", _("Verbose module output"));
01152 fprintf(stderr, " --q %s\n", _("Quiet module output"));
01153
01154
01155
01156 if (n_opts) {
01157 fprintf(stderr, _("\nParameters:\n"));
01158 opt = &first_option;
01159 while (opt != NULL) {
01160 fprintf(stderr, " %*s ", maxlen, opt->key);
01161
01162 if (opt->label) {
01163 fprintf(stderr, "%s\n", opt->label);
01164 if (opt->description) {
01165 fprintf(stderr, " %*s %s\n",
01166 maxlen, " ", opt->description);
01167 }
01168 }
01169 else if (opt->description) {
01170 fprintf(stderr, "%s\n", opt->description);
01171 }
01172
01173 if (opt->options)
01174 show_options(maxlen, opt->options);
01175
01176
01177
01178
01179 if (opt->def)
01180 fprintf(stderr, _(" %*s default: %s\n"), maxlen, " ",
01181 opt->def);
01182
01183 if (opt->descs) {
01184 int i = 0;
01185
01186 while (opt->opts[i]) {
01187 if (opt->descs[i])
01188 fprintf(stderr, " %*s %s: %s\n",
01189 maxlen, " ", opt->opts[i], opt->descs[i]);
01190
01191 i++;
01192 }
01193 }
01194
01195 opt = opt->next_opt;
01196 }
01197 }
01198
01199 return 0;
01200 }
01201
01202
01210 static void print_escaped_for_xml(FILE * fp, const char *str)
01211 {
01212 for (; *str; str++) {
01213 switch (*str) {
01214 case '&':
01215 fputs("&", fp);
01216 break;
01217 case '<':
01218 fputs("<", fp);
01219 break;
01220 case '>':
01221 fputs(">", fp);
01222 break;
01223 default:
01224 fputc(*str, fp);
01225 }
01226 }
01227 }
01228
01229
01233 #define do_escape(c,escaped) case c: fputs(escaped,f);break
01234 static void print_escaped_for_html(FILE * f, const char *str)
01235 {
01236 const char *s;
01237
01238 for (s = str; *s; s++) {
01239 switch (*s) {
01240 do_escape('&', "&");
01241 do_escape('<', "<");
01242 do_escape('>', ">");
01243 do_escape('\n', "<br>");
01244 default:
01245 fputc(*s, f);
01246 }
01247 }
01248 }
01249
01250 #undef do_escape
01251
01255 static void G_usage_xml(void)
01256 {
01257 struct Option *opt;
01258 struct Flag *flag;
01259 char *type;
01260 char *s, *top;
01261 int i;
01262 char *encoding;
01263 int new_prompt = 0;
01264
01265 new_prompt = uses_new_gisprompt();
01266
01267
01268
01269 #if defined(HAVE_LANGINFO_H)
01270 encoding = nl_langinfo(CODESET);
01271 if (!encoding || strlen(encoding) == 0) {
01272 encoding = "UTF-8";
01273 }
01274 #else
01275 encoding = "UTF-8";
01276 #endif
01277
01278 if (!pgm_name)
01279 pgm_name = G_program_name();
01280 if (!pgm_name)
01281 pgm_name = "??";
01282
01283 fprintf(stdout, "<?xml version=\"1.0\" encoding=\"%s\"?>\n", encoding);
01284 fprintf(stdout, "<!DOCTYPE task SYSTEM \"grass-interface.dtd\">\n");
01285
01286 fprintf(stdout, "<task name=\"%s\">\n", pgm_name);
01287
01288 if (module_info.label) {
01289 fprintf(stdout, "\t<label>\n\t\t");
01290 print_escaped_for_xml(stdout, module_info.label);
01291 fprintf(stdout, "\n\t</label>\n");
01292 }
01293
01294 if (module_info.description) {
01295 fprintf(stdout, "\t<description>\n\t\t");
01296 print_escaped_for_xml(stdout, module_info.description);
01297 fprintf(stdout, "\n\t</description>\n");
01298 }
01299
01300 if (module_info.keywords) {
01301 fprintf(stdout, "\t<keywords>\n\t\t");
01302 print_escaped_for_xml(stdout, module_info.keywords);
01303 fprintf(stdout, "\n\t</keywords>\n");
01304 }
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315 if (n_opts) {
01316 opt = &first_option;
01317 while (opt != NULL) {
01318
01319 switch (opt->type) {
01320 case TYPE_INTEGER:
01321 type = "integer";
01322 break;
01323 case TYPE_DOUBLE:
01324 type = "float";
01325 break;
01326 case TYPE_STRING:
01327 type = "string";
01328 break;
01329 default:
01330 type = "string";
01331 break;
01332 }
01333 fprintf(stdout, "\t<parameter "
01334 "name=\"%s\" "
01335 "type=\"%s\" "
01336 "required=\"%s\" "
01337 "multiple=\"%s\">\n",
01338 opt->key,
01339 type,
01340 opt->required == YES ? "yes" : "no",
01341 opt->multiple == YES ? "yes" : "no");
01342
01343 if (opt->label) {
01344 fprintf(stdout, "\t\t<label>\n\t\t\t");
01345 print_escaped_for_xml(stdout, opt->label);
01346 fprintf(stdout, "\n\t\t</label>\n");
01347 }
01348
01349 if (opt->description) {
01350 fprintf(stdout, "\t\t<description>\n\t\t\t");
01351 print_escaped_for_xml(stdout, opt->description);
01352 fprintf(stdout, "\n\t\t</description>\n");
01353 }
01354
01355 if (opt->key_desc) {
01356 fprintf(stdout, "\t\t<keydesc>\n");
01357 top = G_calloc(strlen(opt->key_desc) + 1, 1);
01358 strcpy(top, opt->key_desc);
01359 s = strtok(top, ",");
01360 for (i = 1; s != NULL; i++) {
01361 fprintf(stdout, "\t\t\t<item order=\"%d\">", i);
01362 print_escaped_for_xml(stdout, s);
01363 fprintf(stdout, "</item>\n");
01364 s = strtok(NULL, ",");
01365 }
01366 fprintf(stdout, "\t\t</keydesc>\n");
01367 G_free(top);
01368 }
01369
01370 if (opt->gisprompt) {
01371 const char *atts[] = { "age", "element", "prompt", NULL };
01372 top = G_calloc(strlen(opt->gisprompt) + 1, 1);
01373 strcpy(top, opt->gisprompt);
01374 s = strtok(top, ",");
01375 fprintf(stdout, "\t\t<gisprompt ");
01376 for (i = 0; s != NULL && atts[i] != NULL; i++) {
01377 fprintf(stdout, "%s=\"%s\" ", atts[i], s);
01378 s = strtok(NULL, ",");
01379 }
01380 fprintf(stdout, "/>\n");
01381 G_free(top);
01382 }
01383
01384 if (opt->def) {
01385 fprintf(stdout, "\t\t<default>\n\t\t\t");
01386 print_escaped_for_xml(stdout, opt->def);
01387 fprintf(stdout, "\n\t\t</default>\n");
01388 }
01389
01390 if (opt->options) {
01391
01392
01393
01394
01395 i = 0;
01396 fprintf(stdout, "\t\t<values>\n");
01397 while (opt->opts[i]) {
01398 fprintf(stdout, "\t\t\t<value>\n");
01399 fprintf(stdout, "\t\t\t\t<name>");
01400 print_escaped_for_xml(stdout, opt->opts[i]);
01401 fprintf(stdout, "</name>\n");
01402 if (opt->descs && opt->opts[i] && opt->descs[i]) {
01403 fprintf(stdout, "\t\t\t\t<description>");
01404 print_escaped_for_xml(stdout, opt->descs[i]);
01405 fprintf(stdout, "</description>\n");
01406 }
01407 fprintf(stdout, "\t\t\t</value>\n");
01408 i++;
01409 }
01410 fprintf(stdout, "\t\t</values>\n");
01411 }
01412 if (opt->guisection) {
01413 fprintf(stdout, "\t\t<guisection>\n\t\t\t");
01414 print_escaped_for_xml(stdout, opt->guisection);
01415 fprintf(stdout, "\n\t\t</guisection>\n");
01416 }
01417
01418
01419
01420
01421
01422 opt = opt->next_opt;
01423 fprintf(stdout, "\t</parameter>\n");
01424 }
01425 }
01426
01427
01428 if (n_flags) {
01429 flag = &first_flag;
01430 while (flag != NULL) {
01431 fprintf(stdout, "\t<flag name=\"%c\">\n", flag->key);
01432
01433 if (flag->label) {
01434 fprintf(stdout, "\t\t<label>\n\t\t\t");
01435 print_escaped_for_xml(stdout, flag->label);
01436 fprintf(stdout, "\n\t\t</label>\n");
01437 }
01438
01439 if (flag->description) {
01440 fprintf(stdout, "\t\t<description>\n\t\t\t");
01441 print_escaped_for_xml(stdout, flag->description);
01442 fprintf(stdout, "\n\t\t</description>\n");
01443 }
01444 if (flag->guisection) {
01445 fprintf(stdout, " \t\t<guisection>\n\t\t\t");
01446 print_escaped_for_xml(stdout, flag->guisection);
01447 fprintf(stdout, "\n\t\t</guisection>\n");
01448 }
01449 flag = flag->next_flag;
01450 fprintf(stdout, "\t</flag>\n");
01451 }
01452 }
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463 if (new_prompt) {
01464
01465 fprintf(stdout, "\t<flag name=\"%s\">\n", "overwrite");
01466 fprintf(stdout, "\t\t<description>\n\t\t\t");
01467 print_escaped_for_xml(stdout,
01468 "Allow output files to overwrite existing files");
01469 fprintf(stdout, "\n\t\t</description>\n");
01470 fprintf(stdout, "\t</flag>\n");
01471 }
01472
01473
01474 fprintf(stdout, "\t<flag name=\"%s\">\n", "verbose");
01475 fprintf(stdout, "\t\t<description>\n\t\t\t");
01476 print_escaped_for_xml(stdout, "Verbose module output");
01477 fprintf(stdout, "\n\t\t</description>\n");
01478 fprintf(stdout, "\t</flag>\n");
01479
01480
01481 fprintf(stdout, "\t<flag name=\"%s\">\n", "quiet");
01482 fprintf(stdout, "\t\t<description>\n\t\t\t");
01483 print_escaped_for_xml(stdout, "Quiet module output");
01484 fprintf(stdout, "\n\t\t</description>\n");
01485 fprintf(stdout, "\t</flag>\n");
01486
01487 fprintf(stdout, "</task>\n");
01488 }
01489
01493 static void G_usage_html(void)
01494 {
01495 struct Option *opt;
01496 struct Flag *flag;
01497 const char *type;
01498 int new_prompt = 0;
01499
01500 new_prompt = uses_new_gisprompt();
01501
01502 if (!pgm_name)
01503 pgm_name = G_program_name();
01504 if (!pgm_name)
01505 pgm_name = "??";
01506
01507 fprintf(stdout,
01508 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n");
01509 fprintf(stdout, "<html>\n<head>\n");
01510 fprintf(stdout, "<title>GRASS GIS manual: %s</title>\n", pgm_name);
01511 fprintf(stdout,
01512 "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n");
01513 fprintf(stdout,
01514 "<link rel=\"stylesheet\" href=\"grassdocs.css\" type=\"text/css\">\n");
01515 fprintf(stdout, "</head>\n");
01516 fprintf(stdout, "<body bgcolor=\"white\">\n\n");
01517 fprintf(stdout,
01518 "<img src=\"grass_logo.png\" alt=\"GRASS logo\"><hr align=center size=6 noshade>\n\n");
01519 fprintf(stdout, "<h2>%s</h2>\n", _("NAME"));
01520 fprintf(stdout, "<em><b>%s</b></em> ", pgm_name);
01521
01522 if (module_info.label || module_info.description)
01523 fprintf(stdout, " - ");
01524
01525 if (module_info.label)
01526 fprintf(stdout, "%s<BR>\n", module_info.label);
01527
01528 if (module_info.description)
01529 fprintf(stdout, "%s\n", module_info.description);
01530
01531
01532 fprintf(stdout, "<h2>%s</h2>\n", _("KEYWORDS"));
01533 if (module_info.keywords) {
01534 fprintf(stdout, "%s", module_info.keywords);
01535 fprintf(stdout, "\n");
01536 }
01537 fprintf(stdout, "<h2>%s</h2>\n", _("SYNOPSIS"));
01538 fprintf(stdout, "<b>%s</b><br>\n", pgm_name);
01539 fprintf(stdout, "<b>%s help</b><br>\n", pgm_name);
01540
01541 fprintf(stdout, "<b>%s</b>", pgm_name);
01542
01543
01544
01545
01546 if (n_flags) {
01547 flag = &first_flag;
01548 fprintf(stdout, " [-<b>");
01549 while (flag != NULL) {
01550 fprintf(stdout, "%c", flag->key);
01551 flag = flag->next_flag;
01552 }
01553 fprintf(stdout, "</b>] ");
01554 }
01555 else
01556 fprintf(stdout, " ");
01557
01558 if (n_opts) {
01559 opt = &first_option;
01560
01561 while (opt != NULL) {
01562 if (opt->key_desc != NULL)
01563 type = opt->key_desc;
01564 else
01565 switch (opt->type) {
01566 case TYPE_INTEGER:
01567 type = "integer";
01568 break;
01569 case TYPE_DOUBLE:
01570 type = "float";
01571 break;
01572 case TYPE_STRING:
01573 type = "string";
01574 break;
01575 default:
01576 type = "string";
01577 break;
01578 }
01579 if (!opt->required)
01580 fprintf(stdout, " [");
01581 fprintf(stdout, "<b>%s</b>=<em>%s</em>", opt->key, type);
01582 if (opt->multiple) {
01583 fprintf(stdout, "[,<i>%s</i>,...]", type);
01584 }
01585 if (!opt->required)
01586 fprintf(stdout, "] ");
01587
01588 opt = opt->next_opt;
01589 fprintf(stdout, " ");
01590 }
01591 }
01592 if (new_prompt)
01593 fprintf(stdout, " [--<b>overwrite</b>] ");
01594
01595 fprintf(stdout, " [--<b>verbose</b>] ");
01596 fprintf(stdout, " [--<b>quiet</b>] ");
01597
01598 fprintf(stdout, "\n");
01599
01600
01601
01602 fprintf(stdout, "\n");
01603 if (n_flags || new_prompt) {
01604 flag = &first_flag;
01605 fprintf(stdout, "<h3>%s:</h3>\n", _("Flags"));
01606 fprintf(stdout, "<DL>\n");
01607 while (n_flags && flag != NULL) {
01608 fprintf(stdout, "<DT><b>-%c</b></DT>\n", flag->key);
01609
01610 if (flag->label) {
01611 fprintf(stdout, "<DD>");
01612 fprintf(stdout, "%s", flag->label);
01613 fprintf(stdout, "</DD>\n");
01614 }
01615
01616 if (flag->description) {
01617 fprintf(stdout, "<DD>");
01618 fprintf(stdout, "%s", flag->description);
01619 fprintf(stdout, "</DD>\n");
01620 }
01621
01622 flag = flag->next_flag;
01623 fprintf(stdout, "\n");
01624 }
01625 if (new_prompt) {
01626 fprintf(stdout, "<DT><b>--overwrite</b></DT>\n");
01627 fprintf(stdout, "<DD>%s</DD>\n",
01628 _("Allow output files to overwrite existing files"));
01629 }
01630
01631 fprintf(stdout, "<DT><b>--verbose</b></DT>\n");
01632 fprintf(stdout, "<DD>%s</DD>\n", _("Verbose module output"));
01633
01634 fprintf(stdout, "<DT><b>--quiet</b></DT>\n");
01635 fprintf(stdout, "<DD>%s</DD>\n", _("Quiet module output"));
01636
01637 fprintf(stdout, "</DL>\n");
01638 }
01639
01640 fprintf(stdout, "\n");
01641 if (n_opts) {
01642 opt = &first_option;
01643 fprintf(stdout, "<h3>%s:</h3>\n", _("Parameters"));
01644 fprintf(stdout, "<DL>\n");
01645
01646 while (opt != NULL) {
01647
01648 if (opt->key_desc != NULL)
01649 type = opt->key_desc;
01650 else
01651 switch (opt->type) {
01652 case TYPE_INTEGER:
01653 type = "integer";
01654 break;
01655 case TYPE_DOUBLE:
01656 type = "float";
01657 break;
01658 case TYPE_STRING:
01659 type = "string";
01660 break;
01661 default:
01662 type = "string";
01663 break;
01664 }
01665 fprintf(stdout, "<DT><b>%s</b>=<em>%s", opt->key, type);
01666 if (opt->multiple) {
01667 fprintf(stdout, "[,<i>%s</i>,...]", type);
01668 }
01669 fprintf(stdout, "</em></DT>\n");
01670
01671 if (opt->label) {
01672 fprintf(stdout, "<DD>");
01673 fprintf(stdout, "%s", opt->label);
01674 fprintf(stdout, "</DD>\n");
01675 }
01676 if (opt->description) {
01677 fprintf(stdout, "<DD>");
01678 print_escaped_for_html(stdout, opt->description);
01679 fprintf(stdout, "</DD>\n");
01680 }
01681
01682 if (opt->options) {
01683 fprintf(stdout, "<DD>%s: <em>", _("Options"));
01684 fprintf(stdout, "%s", opt->options);
01685 fprintf(stdout, "</em></DD>\n");
01686 }
01687
01688 if (opt->def) {
01689 fprintf(stdout, "<DD>%s: <em>", _("Default"));
01690 fprintf(stdout, "%s", opt->def);
01691 fprintf(stdout, "</em></DD>\n");
01692 }
01693
01694 if (opt->descs) {
01695 int i = 0;
01696
01697 while (opt->opts[i]) {
01698 if (opt->descs[i])
01699 fprintf(stdout, "<DD><b>%s</b>: %s</DD>\n",
01700 opt->opts[i], opt->descs[i]);
01701 i++;
01702 }
01703 }
01704
01705 opt = opt->next_opt;
01706 fprintf(stdout, "\n");
01707 }
01708 fprintf(stdout, "</DL>\n");
01709 }
01710
01711 fprintf(stdout, "</body>\n</html>\n");
01712 }
01713
01717 static void G_script(void)
01718 {
01719 FILE *fp = stdout;
01720 char *type;
01721
01722 fprintf(fp, "#!/bin/sh\n\n");
01723 fprintf(fp,
01724 "############################################################################\n");
01725 fprintf(fp, "#\n");
01726 fprintf(fp, "# MODULE: %s_wrapper\n", G_program_name());
01727 fprintf(fp, "# AUTHOR(S): %s\n", G_whoami());
01728 fprintf(fp, "# PURPOSE: \n");
01729 fprintf(fp, "# COPYRIGHT: (C) 2009 GRASS Development Team/%s\n",
01730 G_whoami());
01731 fprintf(fp, "#\n");
01732 fprintf(fp,
01733 "# This program is free software; you can redistribute it and/or modify\n");
01734 fprintf(fp,
01735 "# it under the terms of the GNU General Public License as published by\n");
01736 fprintf(fp,
01737 "# the Free Software Foundation; either version 2 of the License, or\n");
01738 fprintf(fp, "# (at your option) any later version.\n");
01739 fprintf(fp, "#\n");
01740 fprintf(fp,
01741 "# This program is distributed in the hope that it will be useful,\n");
01742 fprintf(fp,
01743 "# but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
01744 fprintf(fp,
01745 "# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
01746 fprintf(fp, "# GNU General Public License for more details.\n");
01747 fprintf(fp, "#\n");
01748 fprintf(fp,
01749 "#############################################################################/\n");
01750
01751 fprintf(fp, "#%%Module\n");
01752 if (module_info.label)
01753 fprintf(fp, "#%% label: %s\n", module_info.label);
01754 if (module_info.description)
01755 fprintf(fp, "#%% description: %s\n", module_info.description);
01756 if (module_info.keywords)
01757 fprintf(fp, "#%% keywords: %s\n", module_info.keywords);
01758 fprintf(fp, "#%%End\n");
01759
01760 if (n_flags) {
01761 struct Flag *flag;
01762
01763 for (flag = &first_flag; flag; flag = flag->next_flag) {
01764 fprintf(fp, "#%%Flag\n");
01765 fprintf(fp, "#%% key: %c\n", flag->key);
01766 if (flag->label)
01767 fprintf(fp, "#%% label: %s\n", flag->label);
01768 if (flag->description)
01769 fprintf(fp, "#%% description: %s\n", flag->description);
01770 if (flag->guisection)
01771 fprintf(fp, "#%% guisection: %s\n", flag->guisection);
01772 fprintf(fp, "#%%End\n");
01773 }
01774 }
01775
01776 if (n_opts) {
01777 struct Option *opt;
01778
01779 for (opt = &first_option; opt; opt = opt->next_opt) {
01780 switch (opt->type) {
01781 case TYPE_INTEGER:
01782 type = "integer";
01783 break;
01784 case TYPE_DOUBLE:
01785 type = "double";
01786 break;
01787 case TYPE_STRING:
01788 type = "string";
01789 break;
01790 default:
01791 type = "string";
01792 break;
01793 }
01794
01795 fprintf(fp, "#%%Option\n");
01796 fprintf(fp, "#%% key: %s\n", opt->key);
01797 fprintf(fp, "#%% type: %s\n", type);
01798 fprintf(fp, "#%% required: %s\n", opt->required ? "yes" : "no");
01799 fprintf(fp, "#%% multiple: %s\n", opt->multiple ? "yes" : "no");
01800 if (opt->options)
01801 fprintf(fp, "#%% options: %s\n", opt->options);
01802 if (opt->key_desc)
01803 fprintf(fp, "#%% key_desc: %s\n", opt->key_desc);
01804 if (opt->label)
01805 fprintf(fp, "#%% label: %s\n", opt->label);
01806 if (opt->description)
01807 fprintf(fp, "#%% description: %s\n", opt->description);
01808 if (opt->descriptions)
01809 fprintf(fp, "#%% descriptions: %s\n", opt->descriptions);
01810 if (opt->answer)
01811 fprintf(fp, "#%% answer: %s\n", opt->answer);
01812 if (opt->gisprompt)
01813 fprintf(fp, "#%% gisprompt: %s\n", opt->gisprompt);
01814 if (opt->guisection)
01815 fprintf(fp, "#%% guisection: %s\n", opt->guisection);
01816 fprintf(fp, "#%%End\n");
01817 }
01818 }
01819
01820 fprintf(fp,
01821 "\nif [ -z \"$GISBASE\" ] ; then\n"
01822 " echo \"You must be in GRASS GIS to run this program.\" 1>&2\n"
01823 " exit 1\n"
01824 "fi\n"
01825 "\n"
01826 "if [ \"$1\" != \"@ARGS_PARSED@\" ] ; then\n"
01827 " exec g.parser \"$0\" \"$@\"\n"
01828 "fi\n" "\n" "# CODE GOES HERE\n" "\n");
01829 }
01830
01836 static void generate_tcl(FILE * fp)
01837 {
01838 int new_prompt = uses_new_gisprompt();
01839 const char *type;
01840 int optn;
01841
01842 fprintf(fp, "begin_dialog {%s} {\n", pgm_name);
01843 fprintf(fp, " label {%s}\n", module_info.label ? module_info.label : "");
01844 fprintf(fp, " desc {%s}\n",
01845 module_info.description ? module_info.description : "");
01846 fprintf(fp, " key {%s}\n",
01847 module_info.keywords ? module_info.keywords : "");
01848 fprintf(fp, "}\n");
01849
01850 optn = 1;
01851
01852 if (n_flags) {
01853 struct Flag *flag;
01854
01855 for (flag = &first_flag; flag; flag = flag->next_flag, optn++) {
01856 fprintf(fp, "add_flag %d {\n", optn);
01857 fprintf(fp, " name {%c}\n", flag->key);
01858 fprintf(fp, " desc {%s}\n", flag->description);
01859 fprintf(fp, " answer %d\n", flag->answer);
01860
01861
01862 fprintf(fp, " label {%s}\n", flag->label ? flag->label : "");
01863 fprintf(fp, " guisection {%s}\n",
01864 flag->guisection ? flag->guisection : "");
01865 fprintf(fp, "}\n");
01866 }
01867 }
01868
01869 if (n_opts) {
01870 struct Option *opt;
01871
01872 for (opt = &first_option; opt; opt = opt->next_opt, optn++) {
01873 if (opt->key_desc != NULL)
01874 type = opt->key_desc;
01875 else
01876 switch (opt->type) {
01877 case TYPE_INTEGER:
01878 type = "integer";
01879 break;
01880 case TYPE_DOUBLE:
01881 type = "float";
01882 break;
01883 case TYPE_STRING:
01884 type = "string";
01885 break;
01886 default:
01887 type = "string";
01888 break;
01889 }
01890
01891 fprintf(fp, "add_option %d {\n", optn);
01892 fprintf(fp, " name {%s}\n", opt->key);
01893 fprintf(fp, " type {%s}\n", type);
01894 fprintf(fp, " multi %d\n", opt->multiple);
01895 fprintf(fp, " desc {%s}\n", opt->description);
01896 fprintf(fp, " required %d\n", opt->required);
01897 fprintf(fp, " options {%s}\n", opt->options ? opt->options : "");
01898 fprintf(fp, " descs {%s}\n",
01899 opt->descriptions ? opt->descriptions : "");
01900 fprintf(fp, " answer {%s}\n", opt->answer ? opt->answer : "");
01901 fprintf(fp, " prompt {%s}\n",
01902 opt->gisprompt ? opt->gisprompt : "");
01903
01904
01905 fprintf(fp, " label {%s}\n", opt->label ? opt->label : "");
01906 fprintf(fp, " guisection {%s}\n",
01907 opt->guisection ? opt->guisection : "");
01908 fprintf(fp, "}\n");
01909 }
01910 }
01911
01912 if (new_prompt) {
01913 fprintf(fp, "add_xflag %d {\n", optn);
01914 fprintf(fp, " name {overwrite}\n");
01915 fprintf(fp, " desc {%s}\n",
01916 _("Allow output files to overwrite existing files"));
01917 fprintf(fp, " answer %d\n", overwrite);
01918 fprintf(fp, " label {%s}\n", _("Allow overwrite"));
01919 fprintf(fp, " guisection {}\n");
01920 fprintf(fp, "}\n");
01921 optn++;
01922 }
01923
01924 fprintf(fp, "add_xflag %d {\n", optn);
01925 fprintf(fp, " name {quiet}\n");
01926 fprintf(fp, " desc {%s}\n", _("Run with minimal output messages"));
01927 fprintf(fp, " answer %d\n", quiet);
01928 fprintf(fp, " label {%s}\n", _("Run quietly"));
01929 fprintf(fp, " guisection {}\n");
01930 fprintf(fp, "}\n");
01931 optn++;
01932
01933 fprintf(fp, "end_dialog %d\n", optn - 1);
01934 }
01935
01939 static void G_gui_tcltk(void)
01940 {
01941 FILE *fp;
01942
01943 if (!pgm_name)
01944 pgm_name = G_program_name();
01945 if (!pgm_name)
01946 pgm_name = "??";
01947
01948 #ifdef __MINGW32__
01949 if (getenv("GRASS_DEBUG_GUI"))
01950 fp = G_popen("tee gui_dump.tcl | %GRASS_WISH%", "w");
01951 else
01952 fp = G_popen("%GRASS_WISH%", "w");
01953 #else
01954 if (getenv("GRASS_DEBUG_GUI"))
01955 fp = G_popen("tee gui_dump.tcl | $GRASS_WISH", "w");
01956 else
01957 fp = G_popen("$GRASS_WISH", "w");
01958 #endif
01959
01960 if (!fp)
01961 G_fatal_error(_("Unable to spawn the 'wish' program"));
01962
01963 fprintf(fp, "source $env(GISBASE)/etc/gui.tcl\n");
01964
01965 generate_tcl(fp);
01966
01967 G_pclose(fp);
01968 }
01969
01973 static void G_gui_wx(void)
01974 {
01975 char script[GPATH_MAX];
01976
01977 if (!pgm_name)
01978 pgm_name = G_program_name();
01979 if (!pgm_name)
01980 G_fatal_error(_("Unable to determine program name"));
01981
01982 sprintf(script, "%s/etc/wxpython/gui_modules/menuform.py",
01983 getenv("GISBASE"));
01984 G_spawn(getenv("GRASS_PYTHON"), "menuform.py", script, pgm_name, NULL);
01985 }
01986
01994 static void G_gui(void)
01995 {
01996
01997 char *gui = getenv("GRASS_GUI");
01998
01999 if (!gui) {
02000 gui = G_getenv("GRASS_GUI");
02001 }
02002
02003 if (gui && strcmp(gui, "wxpython") == 0)
02004 G_gui_wx();
02005 else
02006 G_gui_tcltk();
02007
02008 return;
02009 }
02010
02014 static void G_tcltk(void)
02015 {
02016 if (!pgm_name)
02017 pgm_name = G_program_name();
02018 if (!pgm_name)
02019 pgm_name = "??";
02020
02021 generate_tcl(stdout);
02022 }
02023
02024
02025
02026
02027
02028
02029
02030
02031 static int show_options(int maxlen, const char *str)
02032 {
02033 char *buff = G_store(str);
02034 char *p1, *p2;
02035 int totlen, len;
02036
02037 fprintf(stderr, _(" %*s options: "), maxlen, " ");
02038 totlen = maxlen + 13;
02039 p1 = buff;
02040 while ((p2 = G_index(p1, ','))) {
02041 *p2 = '\0';
02042 len = strlen(p1) + 1;
02043 if ((len + totlen) > 76) {
02044 totlen = maxlen + 13;
02045 fprintf(stderr, "\n %*s", maxlen + 13, " ");
02046 }
02047 fprintf(stderr, "%s,", p1);
02048 totlen += len;
02049 p1 = p2 + 1;
02050 }
02051 len = strlen(p1);
02052 if ((len + totlen) > 76)
02053 fprintf(stderr, "\n %*s", maxlen + 13, " ");
02054 fprintf(stderr, "%s\n", p1);
02055
02056 G_free(buff);
02057
02058 return 0;
02059 }
02060
02061 static int show(const char *item, int len)
02062 {
02063 int n;
02064
02065 n = strlen(item) + (len > 0);
02066 if (n + len > 76) {
02067 if (len)
02068 fprintf(stderr, "\n ");
02069 len = 0;
02070 }
02071 fprintf(stderr, "%s", item);
02072 return n + len;
02073 }
02074
02075 static int set_flag(int f)
02076 {
02077 struct Flag *flag;
02078
02079
02080
02081 if (!n_flags) {
02082 fprintf(stderr, _("Sorry, <%c> is not a valid flag\n"), f);
02083 return (1);
02084 }
02085
02086
02087
02088 flag = &first_flag;
02089 while (flag != NULL) {
02090 if (flag->key == f) {
02091 flag->answer = 1;
02092 return (0);
02093 }
02094 flag = flag->next_flag;
02095 }
02096
02097 fprintf(stderr, _("Sorry, <%c> is not a valid flag\n"), f);
02098 return (1);
02099 }
02100
02101
02102
02103
02104 static int contains(const char *s, int c)
02105 {
02106 while (*s) {
02107 if (*s == c)
02108 return (1);
02109 s++;
02110 }
02111 return (0);
02112 }
02113
02114 static int is_option(const char *string)
02115 {
02116 const char *p = strchr(string, '=');
02117
02118 if (!p)
02119 return 0;
02120 if (p == string)
02121 return 0;
02122 p--;
02123 if (!strchr("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", *p))
02124 return 0;
02125
02126 return 1;
02127 }
02128
02129 static int set_option(char *string)
02130 {
02131 struct Option *at_opt = NULL;
02132 struct Option *opt = NULL;
02133 int got_one;
02134 size_t key_len;
02135 char the_key[KEYLENGTH];
02136 char *ptr;
02137
02138 for (ptr = the_key; *string != '='; ptr++, string++)
02139 *ptr = *string;
02140 *ptr = '\0';
02141 string++;
02142
02143
02144 got_one = 0;
02145 key_len = strlen(the_key);
02146 for (at_opt = &first_option; at_opt != NULL; at_opt = at_opt->next_opt) {
02147 if (at_opt->key == NULL || strncmp(the_key, at_opt->key, key_len))
02148 continue;
02149
02150 got_one++;
02151 opt = at_opt;
02152
02153
02154
02155 if (strlen(at_opt->key) == key_len) {
02156 opt = at_opt;
02157 got_one = 1;
02158 break;
02159 }
02160 }
02161
02162 if (got_one > 1) {
02163 fprintf(stderr, _("Sorry, <%s=> is ambiguous\n"), the_key);
02164 return (1);
02165 }
02166
02167
02168 if (got_one == 0) {
02169 fprintf(stderr, _("Sorry, <%s> is not a valid parameter\n"), the_key);
02170 return (1);
02171 }
02172
02173
02174 if (opt->count++) {
02175 opt->answer = (char *)G_realloc(opt->answer,
02176 strlen(opt->answer) + strlen(string) +
02177 2);
02178 strcat(opt->answer, ",");
02179 strcat(opt->answer, string);
02180 }
02181 else
02182 opt->answer = G_store(string);
02183 return (0);
02184 }
02185
02186 static int check_opts(void)
02187 {
02188 struct Option *opt;
02189 int error;
02190 int ans;
02191
02192 error = 0;
02193
02194 if (!n_opts)
02195 return (0);
02196
02197 opt = &first_option;
02198 while (opt != NULL) {
02199
02200
02201 if (opt->options && opt->answer) {
02202 if (opt->multiple == 0)
02203 error += check_an_opt(opt->key, opt->type,
02204 opt->options, opt->answer);
02205 else {
02206 for (ans = 0; opt->answers[ans] != '\0'; ans++)
02207 error += check_an_opt(opt->key, opt->type,
02208 opt->options, opt->answers[ans]);
02209 }
02210 }
02211
02212
02213
02214 if (opt->checker)
02215 error += opt->checker(opt->answer);
02216
02217 opt = opt->next_opt;
02218 }
02219 return (error);
02220 }
02221
02222 static int check_an_opt(const char *key, int type, const char *options,
02223 const char *answer)
02224 {
02225 int error;
02226
02227 error = 0;
02228
02229 switch (type) {
02230 case TYPE_INTEGER:
02231 error = check_int(answer, options);
02232 break;
02233 case TYPE_DOUBLE:
02234 error = check_double(answer, options);
02235 break;
02236 case TYPE_STRING:
02237 error = check_string(answer, options);
02238 break;
02239
02240
02241
02242
02243
02244 }
02245 switch (error) {
02246 case 0:
02247 break;
02248 case BAD_SYNTAX:
02249 fprintf(stderr,
02250 _("\nERROR: illegal range syntax for parameter <%s>\n"), key);
02251 fprintf(stderr, _(" Presented as: %s\n"), options);
02252 break;
02253 case OUT_OF_RANGE:
02254 fprintf(stderr,
02255 _("\nERROR: value <%s> out of range for parameter <%s>\n"),
02256 answer, key);
02257 fprintf(stderr, _(" Legal range: %s\n"), options);
02258 break;
02259 case MISSING_VALUE:
02260 fprintf(stderr, _("\nERROR: Missing value for parameter <%s>\n"),
02261 key);
02262 }
02263 return (error);
02264 }
02265
02266 static int check_int(const char *ans, const char *opts)
02267 {
02268 int d, lo, hi;
02269
02270 if (1 != sscanf(ans, "%d", &d))
02271 return (MISSING_VALUE);
02272
02273 if (contains(opts, '-')) {
02274 if (2 != sscanf(opts, "%d-%d", &lo, &hi))
02275 return (BAD_SYNTAX);
02276 if (d < lo || d > hi)
02277 return (OUT_OF_RANGE);
02278 else
02279 return (0);
02280 }
02281 else if (contains(opts, ',')) {
02282 for (;;) {
02283 if (1 != sscanf(opts, "%d", &lo))
02284 return (BAD_SYNTAX);
02285 if (d == lo)
02286 return (0);
02287 while (*opts != '\0' && *opts != ',')
02288 opts++;
02289 if (*opts == '\0')
02290 return (OUT_OF_RANGE);
02291 if (*(++opts) == '\0')
02292 return (OUT_OF_RANGE);
02293 }
02294 }
02295 else {
02296 if (1 != sscanf(opts, "%d", &lo))
02297 return (BAD_SYNTAX);
02298 if (d == lo)
02299 return (0);
02300 return (OUT_OF_RANGE);
02301 }
02302 }
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330 static int check_double(const char *ans, const char *opts)
02331 {
02332 double d, lo, hi;
02333
02334 if (1 != sscanf(ans, "%lf", &d))
02335 return (MISSING_VALUE);
02336
02337 if (contains(opts, '-')) {
02338 if (2 != sscanf(opts, "%lf-%lf", &lo, &hi))
02339 return (BAD_SYNTAX);
02340 if (d < lo || d > hi)
02341 return (OUT_OF_RANGE);
02342 else
02343 return (0);
02344 }
02345 else if (contains(opts, ',')) {
02346 for (;;) {
02347 if (1 != sscanf(opts, "%lf", &lo))
02348 return (BAD_SYNTAX);
02349 if (d == lo)
02350 return (0);
02351 while (*opts != '\0' && *opts != ',')
02352 opts++;
02353 if (*opts == '\0')
02354 return (OUT_OF_RANGE);
02355 if (*(++opts) == '\0')
02356 return (OUT_OF_RANGE);
02357 }
02358 }
02359 else {
02360 if (1 != sscanf(opts, "%lf", &lo))
02361 return (BAD_SYNTAX);
02362 if (d == lo)
02363 return (0);
02364 return (OUT_OF_RANGE);
02365 }
02366 }
02367
02368 static int check_string(const char *ans, const char *opts)
02369 {
02370 if (*opts == '\0')
02371 return (0);
02372
02373 if (contains(opts, ',')) {
02374 for (;;) {
02375 if ((!strncmp(ans, opts, strlen(ans)))
02376 && (*(opts + strlen(ans)) == ','
02377 || *(opts + strlen(ans)) == '\0'))
02378 return (0);
02379 while (*opts != '\0' && *opts != ',')
02380 opts++;
02381 if (*opts == '\0')
02382 return (OUT_OF_RANGE);
02383 if (*(++opts) == '\0')
02384 return (OUT_OF_RANGE);
02385 }
02386 }
02387 else {
02388 if (!strcmp(ans, opts))
02389 return (0);
02390 return (OUT_OF_RANGE);
02391 }
02392 }
02393
02394 static int check_required(void)
02395 {
02396 struct Option *opt;
02397 int err;
02398
02399 err = 0;
02400
02401 if (!n_opts)
02402 return (0);
02403
02404 opt = &first_option;
02405 while (opt != NULL) {
02406 if (opt->required && opt->answer == NULL) {
02407 fprintf(stderr,
02408 _("\nERROR: Required parameter <%s> not set:\n (%s).\n"),
02409 opt->key, (opt->label ? opt->label : opt->description) );
02410 err++;
02411 }
02412 opt = opt->next_opt;
02413 }
02414
02415 return (err);
02416 }
02417
02418 static int split_opts(void)
02419 {
02420 struct Option *opt;
02421 char *ptr1;
02422 char *ptr2;
02423 int allocated;
02424 int ans_num;
02425 int len;
02426
02427
02428 if (!n_opts)
02429 return 0;
02430
02431 opt = &first_option;
02432 while (opt != NULL) {
02433 if ( (opt->answer != NULL)) {
02434
02435 allocated = 10;
02436 opt->answers = (char **)G_malloc(allocated * sizeof(char *));
02437
02438 ans_num = 0;
02439 ptr1 = opt->answer;
02440 opt->answers[ans_num] = NULL;
02441
02442 for (;;) {
02443 for (len = 0, ptr2 = ptr1; *ptr2 != '\0' && *ptr2 != ',';
02444 ptr2++, len++) ;
02445
02446 if (len > 0) {
02447 opt->answers[ans_num] = (char *)G_malloc(len + 1);
02448 G_copy(opt->answers[ans_num], ptr1, len);
02449 opt->answers[ans_num][len] = 0;
02450
02451 ans_num++;
02452
02453 if (ans_num >= allocated) {
02454 allocated += 10;
02455 opt->answers =
02456 (char **)G_realloc((char *)opt->answers,
02457 allocated * sizeof(char *));
02458 }
02459
02460 opt->answers[ans_num] = NULL;
02461 }
02462
02463 if (*ptr2 == '\0')
02464 break;
02465
02466 ptr1 = ptr2 + 1;
02467
02468 if (*ptr1 == '\0')
02469 break;
02470 }
02471 }
02472 opt = opt->next_opt;
02473 }
02474
02475 return 0;
02476 }
02477
02478 static int check_multiple_opts(void)
02479 {
02480 struct Option *opt;
02481 const char *ptr;
02482 int n_commas;
02483 int n;
02484 int error;
02485
02486 if (!n_opts)
02487 return (0);
02488
02489 error = 0;
02490 opt = &first_option;
02491 while (opt != NULL) {
02492 if ((opt->answer != NULL) && (opt->key_desc != NULL)) {
02493
02494 n_commas = 1;
02495 for (ptr = opt->key_desc; *ptr != '\0'; ptr++)
02496 if (*ptr == ',')
02497 n_commas++;
02498
02499 for (n = 0; opt->answers[n] != '\0'; n++) ;
02500
02501 if (n % n_commas) {
02502 fprintf(stderr,
02503 _("\nERROR: option <%s> must be provided in multiples of %d\n"),
02504 opt->key, n_commas);
02505 fprintf(stderr, _(" You provided %d items:\n"), n);
02506 fprintf(stderr, " %s\n", opt->answer);
02507 error++;
02508 }
02509 }
02510 opt = opt->next_opt;
02511 }
02512 return (error);
02513 }
02514
02515
02516 static int check_overwrite(void)
02517 {
02518 struct Option *opt;
02519 char age[KEYLENGTH];
02520 char element[KEYLENGTH];
02521 char desc[KEYLENGTH];
02522 int error = 0;
02523 char *overstr;
02524 int over;
02525
02526 if (!n_opts)
02527 return (0);
02528
02529 over = 0;
02530
02531 if ((overstr = G__getenv("OVERWRITE"))) {
02532 over = atoi(overstr);
02533 }
02534
02535
02536 if ((overstr = getenv("GRASS_OVERWRITE"))) {
02537 if (atoi(overstr))
02538 over = 1;
02539 }
02540
02541 if (overwrite || over) {
02542 module_info.overwrite = 1;
02543
02544 putenv("GRASS_OVERWRITE=1");
02545
02546 return error;
02547 }
02548
02549 opt = &first_option;
02550 while (opt != NULL) {
02551 if ((opt->answer != NULL) && (opt->gisprompt != NULL)) {
02552 split_gisprompt(opt->gisprompt, age, element, desc);
02553
02554 if (strcmp(age, "new") == 0) {
02555 int i;
02556 for (i = 0; opt->answers[i]; i++) {
02557 if (G_find_file(element, opt->answers[i], G_mapset())) {
02558 if (!overwrite && !over) {
02559 if (G_info_format() != G_INFO_FORMAT_GUI) {
02560 fprintf(stderr,
02561 _("ERROR: option <%s>: <%s> exists.\n"),
02562 opt->key, opt->answers[i]);
02563 }
02564 else {
02565 fprintf(stderr,
02566 "GRASS_INFO_ERROR(%d,1): option <%s>: <%s> exists.\n",
02567 getpid(), opt->key, opt->answers[i]);
02568 fprintf(stderr, "GRASS_INFO_END(%d,1)\n",
02569 getpid());
02570 }
02571
02572 error = 1;
02573 }
02574 }
02575 }
02576 }
02577 }
02578 opt = opt->next_opt;
02579 }
02580
02581 return (error);
02582 }
02583
02584 static int interactive(const char *command)
02585 {
02586 struct Item *item;
02587
02588
02589
02590 if (!n_items) {
02591 fprintf(stderr, "PROGRAMMER ERROR: no flags or options\n");
02592 exit(EXIT_FAILURE);
02593 }
02594
02595 for (item = &first_item;;) {
02596 if (item->flag)
02597 interactive_flag(item->flag);
02598 else if (item->option)
02599 interactive_option(item->option);
02600 else
02601 break;
02602
02603 item = item->next_item;
02604
02605 if (item == NULL)
02606 break;
02607 }
02608
02609 return 0;
02610 }
02611
02612 static int interactive_flag(struct Flag *flag)
02613 {
02614 char buff[1024];
02615
02616 fprintf(stderr, _("\nFLAG: Set the following flag?\n"));
02617 sprintf(buff, " %s?", flag->description);
02618 flag->answer = G_yes(buff, 0);
02619
02620 return 0;
02621 }
02622
02623 static int interactive_option(struct Option *opt)
02624 {
02625 char buff[1024], *bptr;
02626 char buff2[1024];
02627 int set_one;
02628 int no_prompt;
02629
02630 fprintf(stderr, _("\nOPTION: %s\n"), opt->description);
02631 fprintf(stderr, _(" key: %s\n"), opt->key);
02632 if (opt->key_desc)
02633 fprintf(stderr, _(" format: %s\n"), opt->key_desc);
02634 if (opt->def)
02635 fprintf(stderr, _(" default: %s\n"), opt->def);
02636 fprintf(stderr, _("required: %s\n"), opt->required ? "YES" : "NO");
02637 if (opt->multiple)
02638 fprintf(stderr, _("multiple: %s\n"), opt->multiple ? "YES" : "NO");
02639 if (opt->options)
02640 fprintf(stderr, _(" options: %s\n"), opt->options);
02641
02642
02643
02644
02645 set_one = 0;
02646 for (;;) {
02647 *buff = '\0';
02648 if (opt->gisprompt)
02649 no_prompt = gis_prompt(opt, buff);
02650 else
02651 no_prompt = -1;
02652 if (no_prompt) {
02653 fprintf(stderr, _("enter option > "));
02654 if (fgets(buff, 1024, stdin) == 0)
02655 exit(EXIT_SUCCESS);;
02656 bptr = buff;
02657 while (*bptr) {
02658 if (*bptr == '\n')
02659 *bptr = '\0';
02660 bptr++;
02661 }
02662
02663 }
02664
02665 if (strlen(buff) != 0) {
02666 if (opt->options)
02667
02668 {
02669 if (check_an_opt(opt->key, opt->type, opt->options, buff)) {
02670 if (G_yes(_(" Try again? "), 1))
02671 continue;
02672 else
02673 exit(EXIT_FAILURE);
02674 }
02675 }
02676 if (opt->checker)
02677 if (opt->checker(buff)) {
02678 fprintf(stderr, _("Sorry, %s is not accepted.\n"), buff);
02679 *buff = '\0';
02680 if (G_yes(_(" Try again? "), 1))
02681 continue;
02682 else
02683 exit(EXIT_FAILURE);
02684 }
02685
02686 sprintf(buff2, "%s=%s", opt->key, buff);
02687 if (!opt->gisprompt) {
02688 fprintf(stderr, _("\nYou have chosen:\n %s\n"), buff2);
02689 if (G_yes(_("Is this correct? "), 1)) {
02690 set_option(buff2);
02691 set_one++;
02692 }
02693 }
02694 else {
02695 set_option(buff2);
02696 set_one++;
02697 }
02698 }
02699
02700 if ((strlen(buff) == 0) && opt->required && (set_one == 0))
02701 exit(EXIT_FAILURE);
02702 if ((strlen(buff) == 0) && (set_one > 0) && opt->multiple)
02703 break;
02704 if ((strlen(buff) == 0) && !opt->required)
02705 break;
02706 if ((set_one == 1) && !opt->multiple)
02707 break;
02708 }
02709 return (0);
02710 }
02711
02712 static int split_gisprompt(const char *gisprompt, char *age, char *element,
02713 char *desc)
02714 {
02715 const char *ptr1;
02716 char *ptr2;
02717
02718 for (ptr1 = gisprompt, ptr2 = age; *ptr1 != '\0'; ptr1++, ptr2++) {
02719 if (*ptr1 == ',')
02720 break;
02721 *ptr2 = *ptr1;
02722 }
02723 *ptr2 = '\0';
02724
02725 for (ptr1++, ptr2 = element; *ptr1 != '\0'; ptr1++, ptr2++) {
02726 if (*ptr1 == ',')
02727 break;
02728 *ptr2 = *ptr1;
02729 }
02730 *ptr2 = '\0';
02731
02732 for (ptr1++, ptr2 = desc; *ptr1 != '\0'; ptr1++, ptr2++) {
02733 if (*ptr1 == ',')
02734 break;
02735 *ptr2 = *ptr1;
02736 }
02737 *ptr2 = '\0';
02738
02739 return 0;
02740 }
02741
02742 static int gis_prompt(struct Option *opt, char *buff)
02743 {
02744 char age[KEYLENGTH];
02745 char element[KEYLENGTH];
02746 char desc[KEYLENGTH];
02747 char *ptr1;
02748
02749 split_gisprompt(opt->gisprompt, age, element, desc);
02750
02751
02752
02753 if (opt->answer)
02754 G_set_ask_return_msg(_("to accept the default"));
02755 if (!strcmp("old", age)) {
02756 ptr1 = G_ask_old("", buff, element, desc);
02757 if (ptr1) {
02758 strcpy(buff, G_fully_qualified_name(buff, ptr1));
02759 }
02760 }
02761 else if (!strcmp("new", age))
02762 ptr1 = G_ask_new("", buff, element, desc);
02763 else if (!strcmp("mapset", age))
02764 ptr1 = G_ask_in_mapset("", buff, element, desc);
02765 else if (!strcmp("any", age))
02766 ptr1 = G_ask_any("", buff, element, desc, 1);
02767 else if (!strcmp("old_file", age))
02768 ptr1 = G_ask_old_file("", buff, element, desc);
02769 else if (!strcmp("new_file", age))
02770 ptr1 = G_ask_new_file("", buff, element, desc);
02771 else {
02772 return -1;
02773 }
02774
02775 if (ptr1 == '\0')
02776 *buff = '\0';
02777
02778 return 0;
02779 }
02780
02789 char *G_recreate_command(void)
02790 {
02791 static char *buff;
02792 char flg[4];
02793 char *cur;
02794 const char *tmp;
02795 struct Flag *flag;
02796 struct Option *opt;
02797 int n, len, slen;
02798 int nalloced = 0;
02799
02800 G_debug(3, "G_recreate_command()");
02801
02802
02803
02804 buff = G_calloc(1024, sizeof(char));
02805 nalloced += 1024;
02806 tmp = G_program_name();
02807 len = strlen(tmp);
02808 if (len >= nalloced) {
02809 nalloced += (1024 > len) ? 1024 : len + 1;
02810 buff = G_realloc(buff, nalloced);
02811 }
02812 cur = buff;
02813 strcpy(cur, tmp);
02814 cur += len;
02815
02816 if (n_flags) {
02817 flag = &first_flag;
02818 while (flag != '\0') {
02819 if (flag->answer == 1) {
02820 flg[0] = ' ';
02821 flg[1] = '-';
02822 flg[2] = flag->key;
02823 flg[3] = '\0';
02824 slen = strlen(flg);
02825 if (len + slen >= nalloced) {
02826 nalloced +=
02827 (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
02828 buff = G_realloc(buff, nalloced);
02829 cur = buff + len;
02830 }
02831 strcpy(cur, flg);
02832 cur += slen;
02833 len += slen;
02834 }
02835 flag = flag->next_flag;
02836 }
02837 }
02838
02839 opt = &first_option;
02840 while (opt != '\0') {
02841 if (opt->answer != '\0' && opt->answers[0] != NULL) {
02842 slen = strlen(opt->key) + strlen(opt->answers[0]) + 4;
02843 if (len + slen >= nalloced) {
02844 nalloced += (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
02845 buff = G_realloc(buff, nalloced);
02846 cur = buff + len;
02847 }
02848 strcpy(cur, " ");
02849 cur++;
02850 strcpy(cur, opt->key);
02851 cur = strchr(cur, '\0');
02852 strcpy(cur, "=");
02853 cur++;
02854 if (opt->type == TYPE_STRING) {
02855 strcpy(cur, "\"");
02856 cur++;
02857 }
02858 strcpy(cur, opt->answers[0]);
02859 cur = strchr(cur, '\0');
02860 len = cur - buff;
02861 for (n = 1; opt->answers[n] != NULL && opt->answers[n] != '\0';
02862 n++) {
02863 if (opt->answers[n] == NULL)
02864 break;
02865 slen = strlen(opt->answers[n]) + 2;
02866 if (len + slen >= nalloced) {
02867 nalloced +=
02868 (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
02869 buff = G_realloc(buff, nalloced);
02870 cur = buff + len;
02871 }
02872 strcpy(cur, ",");
02873 cur++;
02874 strcpy(cur, opt->answers[n]);
02875 cur = strchr(cur, '\0');
02876 len = cur - buff;
02877 }
02878 if (opt->type == TYPE_STRING) {
02879 strcpy(cur, "\"");
02880 cur++;
02881 len = cur - buff;
02882 }
02883 }
02884 opt = opt->next_opt;
02885 }
02886
02887 return (buff);
02888 }