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