|
GRASS Programmer's Manual
6.5.svn(2012)-r51648
|
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 of 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 first_option.count++; 00965 need_first_opt = 0; 00966 } 00967 00968 /* If we see the non valid argument (no "=", just argument) */ 00969 else { 00970 fprintf(stderr, _("Sorry <%s> is not a valid option\n"), ptr); 00971 error = 1; 00972 } 00973 00974 } 00975 } 00976 00977 /* Split options where multiple answers are OK */ 00978 split_opts(); 00979 00980 /* Run the gui if it was specifically requested */ 00981 if (force_gui) { 00982 G_gui(); 00983 return -1; 00984 } 00985 00986 /* Check multiple options */ 00987 error += check_multiple_opts(); 00988 00989 /* Check answers against options and check subroutines */ 00990 if (!opt_checked) 00991 error += check_opts(); 00992 00993 /* Make sure all required options are set */ 00994 error += check_required(); 00995 00996 if (error) { 00997 G_important_message(_("Error in usage. Call `%s --help` for assistance."), 00998 pgm_name); 00999 return -1; 01000 } 01001 01002 if (check_overwrite()) 01003 return -1; 01004 01005 return 0; 01006 } 01007 01008 01009 static int uses_new_gisprompt(void) 01010 { 01011 struct Option *opt; 01012 char age[KEYLENGTH]; 01013 char element[KEYLENGTH]; 01014 char desc[KEYLENGTH]; 01015 01016 if (module_info.overwrite) 01017 return 1; 01018 01019 /* figure out if any of the options use a "new" gisprompt */ 01020 /* This is to see if we should spit out the --o flag */ 01021 if (n_opts) { 01022 opt = &first_option; 01023 while (opt != NULL) { 01024 if (opt->gisprompt) { 01025 split_gisprompt(opt->gisprompt, age, element, desc); 01026 if (strcmp(age, "new") == 0) 01027 return 1; 01028 } 01029 opt = opt->next_opt; 01030 } 01031 } 01032 01033 return 0; 01034 } 01035 01036 01059 int G_usage(void) 01060 { 01061 struct Option *opt; 01062 struct Flag *flag; 01063 char item[256]; 01064 const char *key_desc; 01065 int maxlen; 01066 int len, n; 01067 int new_prompt = 0; 01068 01069 new_prompt = uses_new_gisprompt(); 01070 01071 if (!pgm_name) /* v.dave && r.michael */ 01072 pgm_name = G_program_name(); 01073 if (!pgm_name) 01074 pgm_name = "??"; 01075 01076 if (module_info.label || module_info.description) { 01077 fprintf(stderr, _("\nDescription:\n")); 01078 if (module_info.label) 01079 fprintf(stderr, " %s\n", module_info.label); 01080 if (module_info.description) 01081 fprintf(stderr, " %s\n", module_info.description); 01082 } 01083 if (module_info.keywords) { 01084 fprintf(stderr, _("\nKeywords:\n")); 01085 fprintf(stderr, " %s\n", module_info.keywords); 01086 } 01087 01088 fprintf(stderr, _("\nUsage:\n ")); 01089 01090 len = show(pgm_name, 1); 01091 01092 /* Print flags */ 01093 01094 if (n_flags) { 01095 item[0] = ' '; 01096 item[1] = '['; 01097 item[2] = '-'; 01098 flag = &first_flag; 01099 for (n = 3; flag != NULL; n++, flag = flag->next_flag) 01100 item[n] = flag->key; 01101 item[n++] = ']'; 01102 item[n] = 0; 01103 len = show(item, len); 01104 } 01105 01106 maxlen = 0; 01107 if (n_opts) { 01108 opt = &first_option; 01109 while (opt != NULL) { 01110 if (opt->key_desc != NULL) 01111 key_desc = opt->key_desc; 01112 else if (opt->type == TYPE_STRING) 01113 key_desc = "string"; 01114 else 01115 key_desc = "value"; 01116 01117 n = strlen(opt->key); 01118 if (n > maxlen) 01119 maxlen = n; 01120 01121 strcpy(item, " "); 01122 if (!opt->required) 01123 strcat(item, "["); 01124 strcat(item, opt->key); 01125 strcat(item, "="); 01126 strcat(item, key_desc); 01127 if (opt->multiple) { 01128 strcat(item, "[,"); 01129 strcat(item, key_desc); 01130 strcat(item, ",...]"); 01131 } 01132 if (!opt->required) 01133 strcat(item, "]"); 01134 01135 len = show(item, len); 01136 01137 opt = opt->next_opt; 01138 } 01139 } 01140 if (new_prompt) { 01141 strcpy(item, " [--overwrite]"); 01142 len = show(item, len); 01143 } 01144 01145 strcpy(item, " [--verbose]"); 01146 len = show(item, len); 01147 01148 strcpy(item, " [--quiet]"); 01149 len = show(item, len); 01150 01151 01152 fprintf(stderr, "\n"); 01153 01154 /* Print help info for flags */ 01155 01156 fprintf(stderr, _("\nFlags:\n")); 01157 01158 if (n_flags) { 01159 flag = &first_flag; 01160 while (flag != NULL) { 01161 fprintf(stderr, " -%c ", flag->key); 01162 01163 if (flag->label) { 01164 fprintf(stderr, "%s\n", flag->label); 01165 if (flag->description) 01166 fprintf(stderr, " %s\n", flag->description); 01167 01168 } 01169 else if (flag->description) { 01170 fprintf(stderr, "%s\n", flag->description); 01171 } 01172 01173 flag = flag->next_flag; 01174 } 01175 } 01176 01177 if (new_prompt) 01178 fprintf(stderr, " --o %s\n", 01179 _("Allow output files to overwrite existing files")); 01180 01181 fprintf(stderr, " --v %s\n", _("Verbose module output")); 01182 fprintf(stderr, " --q %s\n", _("Quiet module output")); 01183 01184 /* Print help info for options */ 01185 01186 if (n_opts) { 01187 fprintf(stderr, _("\nParameters:\n")); 01188 opt = &first_option; 01189 while (opt != NULL) { 01190 fprintf(stderr, " %*s ", maxlen, opt->key); 01191 01192 if (opt->label) { 01193 fprintf(stderr, "%s\n", opt->label); 01194 if (opt->description) { 01195 fprintf(stderr, " %*s %s\n", 01196 maxlen, " ", opt->description); 01197 } 01198 } 01199 else if (opt->description) { 01200 fprintf(stderr, "%s\n", opt->description); 01201 } 01202 01203 if (opt->options) 01204 show_options(maxlen, opt->options); 01205 /* 01206 fprintf (stderr, " %*s options: %s\n", maxlen, " ", 01207 _(opt->options)) ; 01208 */ 01209 if (opt->def) 01210 fprintf(stderr, _(" %*s default: %s\n"), maxlen, " ", 01211 opt->def); 01212 01213 if (opt->descs) { 01214 int i = 0; 01215 01216 while (opt->opts[i]) { 01217 if (opt->descs[i]) 01218 fprintf(stderr, " %*s %s: %s\n", 01219 maxlen, " ", opt->opts[i], opt->descs[i]); 01220 01221 i++; 01222 } 01223 } 01224 01225 opt = opt->next_opt; 01226 } 01227 } 01228 01229 return 0; 01230 } 01231 01232 01240 static void print_escaped_for_xml(FILE * fp, const char *str) 01241 { 01242 for (; *str; str++) { 01243 switch (*str) { 01244 case '&': 01245 fputs("&", fp); 01246 break; 01247 case '<': 01248 fputs("<", fp); 01249 break; 01250 case '>': 01251 fputs(">", fp); 01252 break; 01253 default: 01254 fputc(*str, fp); 01255 } 01256 } 01257 } 01258 01259 01263 #define do_escape(c,escaped) case c: fputs(escaped,f);break 01264 static void print_escaped_for_html(FILE * f, const char *str) 01265 { 01266 const char *s; 01267 01268 for (s = str; *s; s++) { 01269 switch (*s) { 01270 do_escape('&', "&"); 01271 do_escape('<', "<"); 01272 do_escape('>', ">"); 01273 do_escape('\n', "<br>"); 01274 default: 01275 fputc(*s, f); 01276 } 01277 } 01278 } 01279 01280 #undef do_escape 01281 01285 static void G_usage_xml(void) 01286 { 01287 struct Option *opt; 01288 struct Flag *flag; 01289 char *type; 01290 char *s, *top; 01291 int i; 01292 char *encoding; 01293 int new_prompt = 0; 01294 01295 new_prompt = uses_new_gisprompt(); 01296 01297 /* gettext converts strings to encoding returned by nl_langinfo(CODESET) */ 01298 01299 #if defined(HAVE_LANGINFO_H) 01300 encoding = nl_langinfo(CODESET); 01301 if (!encoding || strlen(encoding) == 0) { 01302 encoding = "UTF-8"; 01303 } 01304 #elif defined(__MINGW32__) && defined(USE_NLS) 01305 encoding = locale_charset(); 01306 if (!encoding || strlen(encoding) == 0) { 01307 encoding = "UTF-8"; 01308 } 01309 #else 01310 encoding = "UTF-8"; 01311 #endif 01312 01313 if (!pgm_name) /* v.dave && r.michael */ 01314 pgm_name = G_program_name(); 01315 if (!pgm_name) 01316 pgm_name = "??"; 01317 01318 fprintf(stdout, "<?xml version=\"1.0\" encoding=\"%s\"?>\n", encoding); 01319 fprintf(stdout, "<!DOCTYPE task SYSTEM \"grass-interface.dtd\">\n"); 01320 01321 fprintf(stdout, "<task name=\"%s\">\n", pgm_name); 01322 01323 if (module_info.label) { 01324 fprintf(stdout, "\t<label>\n\t\t"); 01325 print_escaped_for_xml(stdout, module_info.label); 01326 fprintf(stdout, "\n\t</label>\n"); 01327 } 01328 01329 if (module_info.description) { 01330 fprintf(stdout, "\t<description>\n\t\t"); 01331 print_escaped_for_xml(stdout, module_info.description); 01332 fprintf(stdout, "\n\t</description>\n"); 01333 } 01334 01335 if (module_info.keywords) { 01336 fprintf(stdout, "\t<keywords>\n\t\t"); 01337 print_escaped_for_xml(stdout, module_info.keywords); 01338 fprintf(stdout, "\n\t</keywords>\n"); 01339 } 01340 01341 /***** Don't use parameter-groups for now. We'll reimplement this later 01342 ***** when we have a concept of several mutually exclusive option 01343 ***** groups 01344 if (n_opts || n_flags) 01345 fprintf(stdout, "\t<parameter-group>\n"); 01346 ***** 01347 ***** 01348 *****/ 01349 01350 if (n_opts) { 01351 opt = &first_option; 01352 while (opt != NULL) { 01353 /* TODO: make this a enumeration type? */ 01354 switch (opt->type) { 01355 case TYPE_INTEGER: 01356 type = "integer"; 01357 break; 01358 case TYPE_DOUBLE: 01359 type = "float"; 01360 break; 01361 case TYPE_STRING: 01362 type = "string"; 01363 break; 01364 default: 01365 type = "string"; 01366 break; 01367 } 01368 fprintf(stdout, "\t<parameter " 01369 "name=\"%s\" " 01370 "type=\"%s\" " 01371 "required=\"%s\" " 01372 "multiple=\"%s\">\n", 01373 opt->key, 01374 type, 01375 opt->required == YES ? "yes" : "no", 01376 opt->multiple == YES ? "yes" : "no"); 01377 01378 if (opt->label) { 01379 fprintf(stdout, "\t\t<label>\n\t\t\t"); 01380 print_escaped_for_xml(stdout, opt->label); 01381 fprintf(stdout, "\n\t\t</label>\n"); 01382 } 01383 01384 if (opt->description) { 01385 fprintf(stdout, "\t\t<description>\n\t\t\t"); 01386 print_escaped_for_xml(stdout, opt->description); 01387 fprintf(stdout, "\n\t\t</description>\n"); 01388 } 01389 01390 if (opt->key_desc) { 01391 fprintf(stdout, "\t\t<keydesc>\n"); 01392 top = G_calloc(strlen(opt->key_desc) + 1, 1); 01393 strcpy(top, opt->key_desc); 01394 s = strtok(top, ","); 01395 for (i = 1; s != NULL; i++) { 01396 fprintf(stdout, "\t\t\t<item order=\"%d\">", i); 01397 print_escaped_for_xml(stdout, s); 01398 fprintf(stdout, "</item>\n"); 01399 s = strtok(NULL, ","); 01400 } 01401 fprintf(stdout, "\t\t</keydesc>\n"); 01402 G_free(top); 01403 } 01404 01405 if (opt->gisprompt) { 01406 const char *atts[] = { "age", "element", "prompt", NULL }; 01407 top = G_calloc(strlen(opt->gisprompt) + 1, 1); 01408 strcpy(top, opt->gisprompt); 01409 s = strtok(top, ","); 01410 fprintf(stdout, "\t\t<gisprompt "); 01411 for (i = 0; s != NULL && atts[i] != NULL; i++) { 01412 fprintf(stdout, "%s=\"%s\" ", atts[i], s); 01413 s = strtok(NULL, ","); 01414 } 01415 fprintf(stdout, "/>\n"); 01416 G_free(top); 01417 } 01418 01419 if (opt->def) { 01420 fprintf(stdout, "\t\t<default>\n\t\t\t"); 01421 print_escaped_for_xml(stdout, opt->def); 01422 fprintf(stdout, "\n\t\t</default>\n"); 01423 } 01424 01425 if (opt->options) { 01426 /* TODO: 01427 * add something like 01428 * <range min="xxx" max="xxx"/> 01429 * to <values> */ 01430 i = 0; 01431 fprintf(stdout, "\t\t<values>\n"); 01432 while (opt->opts[i]) { 01433 fprintf(stdout, "\t\t\t<value>\n"); 01434 fprintf(stdout, "\t\t\t\t<name>"); 01435 print_escaped_for_xml(stdout, opt->opts[i]); 01436 fprintf(stdout, "</name>\n"); 01437 if (opt->descs && opt->opts[i] && opt->descs[i]) { 01438 fprintf(stdout, "\t\t\t\t<description>"); 01439 print_escaped_for_xml(stdout, opt->descs[i]); 01440 fprintf(stdout, "</description>\n"); 01441 } 01442 fprintf(stdout, "\t\t\t</value>\n"); 01443 i++; 01444 } 01445 fprintf(stdout, "\t\t</values>\n"); 01446 } 01447 if (opt->guisection) { 01448 fprintf(stdout, "\t\t<guisection>\n\t\t\t"); 01449 print_escaped_for_xml(stdout, opt->guisection); 01450 fprintf(stdout, "\n\t\t</guisection>\n"); 01451 } 01452 /* TODO: 01453 * - key_desc? 01454 * - there surely are some more. which ones? 01455 */ 01456 01457 opt = opt->next_opt; 01458 fprintf(stdout, "\t</parameter>\n"); 01459 } 01460 } 01461 01462 01463 if (n_flags) { 01464 flag = &first_flag; 01465 while (flag != NULL) { 01466 fprintf(stdout, "\t<flag name=\"%c\">\n", flag->key); 01467 01468 if (flag->label) { 01469 fprintf(stdout, "\t\t<label>\n\t\t\t"); 01470 print_escaped_for_xml(stdout, flag->label); 01471 fprintf(stdout, "\n\t\t</label>\n"); 01472 } 01473 01474 if (flag->description) { 01475 fprintf(stdout, "\t\t<description>\n\t\t\t"); 01476 print_escaped_for_xml(stdout, flag->description); 01477 fprintf(stdout, "\n\t\t</description>\n"); 01478 } 01479 if (flag->guisection) { 01480 fprintf(stdout, " \t\t<guisection>\n\t\t\t"); 01481 print_escaped_for_xml(stdout, flag->guisection); 01482 fprintf(stdout, "\n\t\t</guisection>\n"); 01483 } 01484 flag = flag->next_flag; 01485 fprintf(stdout, "\t</flag>\n"); 01486 } 01487 } 01488 01489 /***** Don't use parameter-groups for now. We'll reimplement this later 01490 ***** when we have a concept of several mutually exclusive option 01491 ***** groups 01492 if (n_opts || n_flags) 01493 fprintf(stdout, "\t</parameter-group>\n"); 01494 ***** 01495 ***** 01496 *****/ 01497 01498 if (new_prompt) { 01499 /* overwrite */ 01500 fprintf(stdout, "\t<flag name=\"%s\">\n", "overwrite"); 01501 fprintf(stdout, "\t\t<description>\n\t\t\t"); 01502 print_escaped_for_xml(stdout, 01503 _("Allow output files to overwrite existing files")); 01504 fprintf(stdout, "\n\t\t</description>\n"); 01505 fprintf(stdout, "\t</flag>\n"); 01506 } 01507 01508 /* verbose */ 01509 fprintf(stdout, "\t<flag name=\"%s\">\n", "verbose"); 01510 fprintf(stdout, "\t\t<description>\n\t\t\t"); 01511 print_escaped_for_xml(stdout, _("Verbose module output")); 01512 fprintf(stdout, "\n\t\t</description>\n"); 01513 fprintf(stdout, "\t</flag>\n"); 01514 01515 /* quiet */ 01516 fprintf(stdout, "\t<flag name=\"%s\">\n", "quiet"); 01517 fprintf(stdout, "\t\t<description>\n\t\t\t"); 01518 print_escaped_for_xml(stdout, _("Quiet module output")); 01519 fprintf(stdout, "\n\t\t</description>\n"); 01520 fprintf(stdout, "\t</flag>\n"); 01521 01522 fprintf(stdout, "</task>\n"); 01523 } 01524 01528 static void G_usage_html(void) 01529 { 01530 struct Option *opt; 01531 struct Flag *flag; 01532 const char *type; 01533 int new_prompt = 0; 01534 01535 new_prompt = uses_new_gisprompt(); 01536 01537 if (!pgm_name) /* v.dave && r.michael */ 01538 pgm_name = G_program_name(); 01539 if (!pgm_name) 01540 pgm_name = "??"; 01541 01542 fprintf(stdout, 01543 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"); 01544 fprintf(stdout, "<html>\n<head>\n"); 01545 fprintf(stdout, "<title>GRASS GIS manual: %s</title>\n", pgm_name); 01546 fprintf(stdout, 01547 "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n"); 01548 fprintf(stdout, 01549 "<link rel=\"stylesheet\" href=\"grassdocs.css\" type=\"text/css\">\n"); 01550 fprintf(stdout, "</head>\n"); 01551 fprintf(stdout, "<body bgcolor=\"white\">\n\n"); 01552 fprintf(stdout, 01553 "<img src=\"grass_logo.png\" alt=\"GRASS logo\"><hr align=center size=6 noshade>\n\n"); 01554 fprintf(stdout, "<h2>%s</h2>\n", _("NAME")); 01555 fprintf(stdout, "<em><b>%s</b></em> ", pgm_name); 01556 01557 if (module_info.label || module_info.description) 01558 fprintf(stdout, " - "); 01559 01560 if (module_info.label) 01561 fprintf(stdout, "%s<BR>\n", module_info.label); 01562 01563 if (module_info.description) 01564 fprintf(stdout, "%s\n", module_info.description); 01565 01566 01567 fprintf(stdout, "<h2>%s</h2>\n", _("KEYWORDS")); 01568 if (module_info.keywords) { 01569 fprintf(stdout, "%s", module_info.keywords); 01570 fprintf(stdout, "\n"); 01571 } 01572 fprintf(stdout, "<h2>%s</h2>\n", _("SYNOPSIS")); 01573 fprintf(stdout, "<b>%s</b><br>\n", pgm_name); 01574 fprintf(stdout, "<b>%s help</b><br>\n", pgm_name); 01575 01576 fprintf(stdout, "<b>%s</b>", pgm_name); 01577 01578 01579 01580 /* print short version first */ 01581 if (n_flags) { 01582 flag = &first_flag; 01583 fprintf(stdout, " [-<b>"); 01584 while (flag != NULL) { 01585 fprintf(stdout, "%c", flag->key); 01586 flag = flag->next_flag; 01587 } 01588 fprintf(stdout, "</b>] "); 01589 } 01590 else 01591 fprintf(stdout, " "); 01592 01593 if (n_opts) { 01594 opt = &first_option; 01595 01596 while (opt != NULL) { 01597 if (opt->key_desc != NULL) 01598 type = opt->key_desc; 01599 else 01600 switch (opt->type) { 01601 case TYPE_INTEGER: 01602 type = "integer"; 01603 break; 01604 case TYPE_DOUBLE: 01605 type = "float"; 01606 break; 01607 case TYPE_STRING: 01608 type = "string"; 01609 break; 01610 default: 01611 type = "string"; 01612 break; 01613 } 01614 if (!opt->required) 01615 fprintf(stdout, " ["); 01616 fprintf(stdout, "<b>%s</b>=<em>%s</em>", opt->key, type); 01617 if (opt->multiple) { 01618 fprintf(stdout, "[,<i>%s</i>,...]", type); 01619 } 01620 if (!opt->required) 01621 fprintf(stdout, "] "); 01622 01623 opt = opt->next_opt; 01624 fprintf(stdout, " "); 01625 } 01626 } 01627 if (new_prompt) 01628 fprintf(stdout, " [--<b>overwrite</b>] "); 01629 01630 fprintf(stdout, " [--<b>verbose</b>] "); 01631 fprintf(stdout, " [--<b>quiet</b>] "); 01632 01633 fprintf(stdout, "\n"); 01634 01635 01636 /* now long version */ 01637 fprintf(stdout, "\n"); 01638 if (n_flags || new_prompt) { 01639 flag = &first_flag; 01640 fprintf(stdout, "<h3>%s:</h3>\n", _("Flags")); 01641 fprintf(stdout, "<DL>\n"); 01642 while (n_flags && flag != NULL) { 01643 fprintf(stdout, "<DT><b>-%c</b></DT>\n", flag->key); 01644 01645 if (flag->label) { 01646 fprintf(stdout, "<DD>"); 01647 fprintf(stdout, "%s", flag->label); 01648 fprintf(stdout, "</DD>\n"); 01649 } 01650 01651 if (flag->description) { 01652 fprintf(stdout, "<DD>"); 01653 fprintf(stdout, "%s", flag->description); 01654 fprintf(stdout, "</DD>\n"); 01655 } 01656 01657 flag = flag->next_flag; 01658 fprintf(stdout, "\n"); 01659 } 01660 if (new_prompt) { 01661 fprintf(stdout, "<DT><b>--overwrite</b></DT>\n"); 01662 fprintf(stdout, "<DD>%s</DD>\n", 01663 _("Allow output files to overwrite existing files")); 01664 } 01665 01666 fprintf(stdout, "<DT><b>--verbose</b></DT>\n"); 01667 fprintf(stdout, "<DD>%s</DD>\n", _("Verbose module output")); 01668 01669 fprintf(stdout, "<DT><b>--quiet</b></DT>\n"); 01670 fprintf(stdout, "<DD>%s</DD>\n", _("Quiet module output")); 01671 01672 fprintf(stdout, "</DL>\n"); 01673 } 01674 01675 fprintf(stdout, "\n"); 01676 if (n_opts) { 01677 opt = &first_option; 01678 fprintf(stdout, "<h3>%s:</h3>\n", _("Parameters")); 01679 fprintf(stdout, "<DL>\n"); 01680 01681 while (opt != NULL) { 01682 /* TODO: make this a enumeration type? */ 01683 if (opt->key_desc != NULL) 01684 type = opt->key_desc; 01685 else 01686 switch (opt->type) { 01687 case TYPE_INTEGER: 01688 type = "integer"; 01689 break; 01690 case TYPE_DOUBLE: 01691 type = "float"; 01692 break; 01693 case TYPE_STRING: 01694 type = "string"; 01695 break; 01696 default: 01697 type = "string"; 01698 break; 01699 } 01700 fprintf(stdout, "<DT><b>%s</b>=<em>%s", opt->key, type); 01701 if (opt->multiple) { 01702 fprintf(stdout, "[,<i>%s</i>,...]", type); 01703 } 01704 fprintf(stdout, "</em></DT>\n"); 01705 01706 if (opt->label) { 01707 fprintf(stdout, "<DD>"); 01708 fprintf(stdout, "%s", opt->label); 01709 fprintf(stdout, "</DD>\n"); 01710 } 01711 if (opt->description) { 01712 fprintf(stdout, "<DD>"); 01713 print_escaped_for_html(stdout, opt->description); 01714 fprintf(stdout, "</DD>\n"); 01715 } 01716 01717 if (opt->options) { 01718 fprintf(stdout, "<DD>%s: <em>", _("Options")); 01719 fprintf(stdout, "%s", opt->options); 01720 fprintf(stdout, "</em></DD>\n"); 01721 } 01722 01723 if (opt->def) { 01724 fprintf(stdout, "<DD>%s: <em>", _("Default")); 01725 fprintf(stdout, "%s", opt->def); 01726 fprintf(stdout, "</em></DD>\n"); 01727 } 01728 01729 if (opt->descs) { 01730 int i = 0; 01731 01732 while (opt->opts[i]) { 01733 if (opt->descs[i]) 01734 fprintf(stdout, "<DD><b>%s</b>: %s</DD>\n", 01735 opt->opts[i], opt->descs[i]); 01736 i++; 01737 } 01738 } 01739 01740 opt = opt->next_opt; 01741 fprintf(stdout, "\n"); 01742 } 01743 fprintf(stdout, "</DL>\n"); 01744 } 01745 01746 fprintf(stdout, "</body>\n</html>\n"); 01747 } 01748 01752 static void G_script(void) 01753 { 01754 FILE *fp = stdout; 01755 char *type; 01756 01757 fprintf(fp, "#!/bin/sh\n\n"); 01758 fprintf(fp, 01759 "############################################################################\n"); 01760 fprintf(fp, "#\n"); 01761 fprintf(fp, "# MODULE: %s_wrapper\n", G_program_name()); 01762 fprintf(fp, "# AUTHOR(S): %s\n", G_whoami()); 01763 fprintf(fp, "# PURPOSE: \n"); 01764 fprintf(fp, "# COPYRIGHT: (C) 2009 GRASS Development Team/%s\n", 01765 G_whoami()); 01766 fprintf(fp, "#\n"); 01767 fprintf(fp, 01768 "# This program is free software; you can redistribute it and/or modify\n"); 01769 fprintf(fp, 01770 "# it under the terms of the GNU General Public License as published by\n"); 01771 fprintf(fp, 01772 "# the Free Software Foundation; either version 2 of the License, or\n"); 01773 fprintf(fp, "# (at your option) any later version.\n"); 01774 fprintf(fp, "#\n"); 01775 fprintf(fp, 01776 "# This program is distributed in the hope that it will be useful,\n"); 01777 fprintf(fp, 01778 "# but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); 01779 fprintf(fp, 01780 "# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); 01781 fprintf(fp, "# GNU General Public License for more details.\n"); 01782 fprintf(fp, "#\n"); 01783 fprintf(fp, 01784 "############################################################################\n"); 01785 01786 fprintf(fp, "#%%Module\n"); 01787 if (module_info.label) 01788 fprintf(fp, "#%% label: %s\n", module_info.label); 01789 if (module_info.description) 01790 fprintf(fp, "#%% description: %s\n", module_info.description); 01791 if (module_info.keywords) 01792 fprintf(fp, "#%% keywords: %s\n", module_info.keywords); 01793 fprintf(fp, "#%%End\n"); 01794 01795 if (n_flags) { 01796 struct Flag *flag; 01797 01798 for (flag = &first_flag; flag; flag = flag->next_flag) { 01799 fprintf(fp, "#%%Flag\n"); 01800 fprintf(fp, "#%% key: %c\n", flag->key); 01801 if (flag->label) 01802 fprintf(fp, "#%% label: %s\n", flag->label); 01803 if (flag->description) 01804 fprintf(fp, "#%% description: %s\n", flag->description); 01805 if (flag->guisection) 01806 fprintf(fp, "#%% guisection: %s\n", flag->guisection); 01807 fprintf(fp, "#%%End\n"); 01808 } 01809 } 01810 01811 if (n_opts) { 01812 struct Option *opt; 01813 01814 for (opt = &first_option; opt; opt = opt->next_opt) { 01815 switch (opt->type) { 01816 case TYPE_INTEGER: 01817 type = "integer"; 01818 break; 01819 case TYPE_DOUBLE: 01820 type = "double"; 01821 break; 01822 case TYPE_STRING: 01823 type = "string"; 01824 break; 01825 default: 01826 type = "string"; 01827 break; 01828 } 01829 01830 fprintf(fp, "#%%Option\n"); 01831 fprintf(fp, "#%% key: %s\n", opt->key); 01832 fprintf(fp, "#%% type: %s\n", type); 01833 fprintf(fp, "#%% required: %s\n", opt->required ? "yes" : "no"); 01834 fprintf(fp, "#%% multiple: %s\n", opt->multiple ? "yes" : "no"); 01835 if (opt->options) 01836 fprintf(fp, "#%% options: %s\n", opt->options); 01837 if (opt->key_desc) 01838 fprintf(fp, "#%% key_desc: %s\n", opt->key_desc); 01839 if (opt->label) 01840 fprintf(fp, "#%% label: %s\n", opt->label); 01841 if (opt->description) 01842 fprintf(fp, "#%% description: %s\n", opt->description); 01843 if (opt->descriptions) 01844 fprintf(fp, "#%% descriptions: %s\n", opt->descriptions); 01845 if (opt->answer) 01846 fprintf(fp, "#%% answer: %s\n", opt->answer); 01847 if (opt->gisprompt) 01848 fprintf(fp, "#%% gisprompt: %s\n", opt->gisprompt); 01849 if (opt->guisection) 01850 fprintf(fp, "#%% guisection: %s\n", opt->guisection); 01851 fprintf(fp, "#%%End\n"); 01852 } 01853 } 01854 01855 fprintf(fp, 01856 "\nif [ -z \"$GISBASE\" ] ; then\n" 01857 " echo \"You must be in GRASS GIS to run this program.\" 1>&2\n" 01858 " exit 1\n" 01859 "fi\n" 01860 "\n" 01861 "if [ \"$1\" != \"@ARGS_PARSED@\" ] ; then\n" 01862 " exec g.parser \"$0\" \"$@\"\n" 01863 "fi\n" "\n" "# CODE GOES HERE\n" "\n"); 01864 } 01865 01871 static void generate_tcl(FILE * fp) 01872 { 01873 int new_prompt = uses_new_gisprompt(); 01874 const char *type; 01875 int optn; 01876 01877 fprintf(fp, "begin_dialog {%s} {\n", pgm_name); 01878 fprintf(fp, " label {%s}\n", module_info.label ? module_info.label : ""); 01879 fprintf(fp, " desc {%s}\n", 01880 module_info.description ? module_info.description : ""); 01881 fprintf(fp, " key {%s}\n", 01882 module_info.keywords ? module_info.keywords : ""); 01883 fprintf(fp, "}\n"); 01884 01885 optn = 1; 01886 01887 if (n_flags) { 01888 struct Flag *flag; 01889 01890 for (flag = &first_flag; flag; flag = flag->next_flag, optn++) { 01891 fprintf(fp, "add_flag %d {\n", optn); 01892 fprintf(fp, " name {%c}\n", flag->key); 01893 fprintf(fp, " desc {%s}\n", flag->description); 01894 fprintf(fp, " answer %d\n", flag->answer); 01895 /* It should be up to the gui as to what 01896 to do with the label and description */ 01897 fprintf(fp, " label {%s}\n", flag->label ? flag->label : ""); 01898 fprintf(fp, " guisection {%s}\n", 01899 flag->guisection ? flag->guisection : ""); 01900 fprintf(fp, "}\n"); 01901 } 01902 } 01903 01904 if (n_opts) { 01905 struct Option *opt; 01906 01907 for (opt = &first_option; opt; opt = opt->next_opt, optn++) { 01908 if (opt->key_desc != NULL) 01909 type = opt->key_desc; 01910 else 01911 switch (opt->type) { 01912 case TYPE_INTEGER: 01913 type = "integer"; 01914 break; 01915 case TYPE_DOUBLE: 01916 type = "float"; 01917 break; 01918 case TYPE_STRING: 01919 type = "string"; 01920 break; 01921 default: 01922 type = "string"; 01923 break; 01924 } 01925 01926 fprintf(fp, "add_option %d {\n", optn); 01927 fprintf(fp, " name {%s}\n", opt->key); 01928 fprintf(fp, " type {%s}\n", type); 01929 fprintf(fp, " multi %d\n", opt->multiple); 01930 fprintf(fp, " desc {%s}\n", opt->description); 01931 fprintf(fp, " required %d\n", opt->required); 01932 fprintf(fp, " options {%s}\n", opt->options ? opt->options : ""); 01933 fprintf(fp, " descs {%s}\n", 01934 opt->descriptions ? opt->descriptions : ""); 01935 fprintf(fp, " answer {%s}\n", opt->answer ? opt->answer : ""); 01936 fprintf(fp, " prompt {%s}\n", 01937 opt->gisprompt ? opt->gisprompt : ""); 01938 /* It should be up to the gui as to what 01939 to do with the label and description */ 01940 fprintf(fp, " label {%s}\n", opt->label ? opt->label : ""); 01941 fprintf(fp, " guisection {%s}\n", 01942 opt->guisection ? opt->guisection : ""); 01943 fprintf(fp, "}\n"); 01944 } 01945 } 01946 01947 if (new_prompt) { 01948 fprintf(fp, "add_xflag %d {\n", optn); 01949 fprintf(fp, " name {overwrite}\n"); 01950 fprintf(fp, " desc {%s}\n", 01951 _("Allow output files to overwrite existing files")); 01952 fprintf(fp, " answer %d\n", overwrite); 01953 fprintf(fp, " label {%s}\n", _("Allow overwrite")); 01954 fprintf(fp, " guisection {}\n"); 01955 fprintf(fp, "}\n"); 01956 optn++; 01957 } 01958 01959 fprintf(fp, "add_xflag %d {\n", optn); 01960 fprintf(fp, " name {quiet}\n"); 01961 fprintf(fp, " desc {%s}\n", _("Run with minimal output messages")); 01962 fprintf(fp, " answer %d\n", quiet); 01963 fprintf(fp, " label {%s}\n", _("Run quietly")); 01964 fprintf(fp, " guisection {}\n"); 01965 fprintf(fp, "}\n"); 01966 optn++; 01967 01968 fprintf(fp, "end_dialog %d\n", optn - 1); 01969 } 01970 01974 static void G_gui_tcltk(void) 01975 { 01976 FILE *fp; 01977 01978 if (!pgm_name) 01979 pgm_name = G_program_name(); 01980 if (!pgm_name) 01981 pgm_name = "??"; 01982 01983 #ifdef __MINGW32__ 01984 if (getenv("GRASS_DEBUG_GUI")) 01985 fp = popen("tee gui_dump.tcl | \"%GRASS_WISH%\"", "w"); 01986 else 01987 fp = popen("\"%GRASS_WISH%\"", "w"); 01988 #else 01989 if (getenv("GRASS_DEBUG_GUI")) 01990 fp = popen("tee gui_dump.tcl | \"$GRASS_WISH\"", "w"); 01991 else 01992 fp = popen("\"$GRASS_WISH\"", "w"); 01993 #endif 01994 01995 if (!fp) 01996 G_fatal_error(_("Unable to spawn the 'wish' program")); 01997 01998 fprintf(fp, "source $env(GISBASE)/etc/gui.tcl\n"); 01999 02000 generate_tcl(fp); 02001 02002 pclose(fp); 02003 } 02004 02008 static void G_gui_wx(void) 02009 { 02010 char script[GPATH_MAX]; 02011 02012 if (!pgm_name) 02013 pgm_name = G_program_name(); 02014 if (!pgm_name) 02015 G_fatal_error(_("Unable to determine program name")); 02016 02017 sprintf(script, "%s/etc/wxpython/gui_core/forms.py", 02018 getenv("GISBASE")); 02019 G_spawn(getenv("GRASS_PYTHON"), getenv("GRASS_PYTHON"), script, G_recreate_command(), NULL); 02020 } 02021 02029 static void G_gui(void) 02030 { 02031 /* read environment variables first then internal GRASS variable */ 02032 char *gui = getenv("GRASS_GUI"); 02033 02034 if (!gui) { 02035 gui = G_getenv("GRASS_GUI"); 02036 } 02037 02038 if (gui && (strcmp(gui, "tcltk") == 0 || strcmp(gui, "oldtcltk") == 0)) 02039 G_gui_tcltk(); 02040 else 02041 G_gui_wx(); 02042 02043 return; 02044 } 02045 02049 static void G_tcltk(void) 02050 { 02051 if (!pgm_name) 02052 pgm_name = G_program_name(); 02053 if (!pgm_name) 02054 pgm_name = "??"; 02055 02056 generate_tcl(stdout); 02057 } 02058 02059 /************************************************************************** 02060 * 02061 * The remaining routines are all local (static) routines used to support 02062 * the parsing process. 02063 * 02064 **************************************************************************/ 02065 02066 static int show_options(int maxlen, const char *str) 02067 { 02068 char *buff = G_store(str); 02069 char *p1, *p2; 02070 int totlen, len; 02071 02072 fprintf(stderr, _(" %*s options: "), maxlen, " "); 02073 totlen = maxlen + 13; 02074 p1 = buff; 02075 while ((p2 = G_index(p1, ','))) { 02076 *p2 = '\0'; 02077 len = strlen(p1) + 1; 02078 if ((len + totlen) > 76) { 02079 totlen = maxlen + 13; 02080 fprintf(stderr, "\n %*s", maxlen + 13, " "); 02081 } 02082 fprintf(stderr, "%s,", p1); 02083 totlen += len; 02084 p1 = p2 + 1; 02085 } 02086 len = strlen(p1); 02087 if ((len + totlen) > 76) 02088 fprintf(stderr, "\n %*s", maxlen + 13, " "); 02089 fprintf(stderr, "%s\n", p1); 02090 02091 G_free(buff); 02092 02093 return 0; 02094 } 02095 02096 static int show(const char *item, int len) 02097 { 02098 int n; 02099 02100 n = strlen(item) + (len > 0); 02101 if (n + len > 76) { 02102 if (len) 02103 fprintf(stderr, "\n "); 02104 len = 0; 02105 } 02106 fprintf(stderr, "%s", item); 02107 return n + len; 02108 } 02109 02110 static int set_flag(int f) 02111 { 02112 struct Flag *flag; 02113 02114 /* Flag is not valid if there are no flags to set */ 02115 02116 if (!n_flags) { 02117 fprintf(stderr, _("Sorry, <%c> is not a valid flag\n"), f); 02118 return (1); 02119 } 02120 02121 /* Find flag with corrrect keyword */ 02122 02123 flag = &first_flag; 02124 while (flag != NULL) { 02125 if (flag->key == f) { 02126 flag->answer = 1; 02127 return (0); 02128 } 02129 flag = flag->next_flag; 02130 } 02131 02132 fprintf(stderr, _("Sorry, <%c> is not a valid flag\n"), f); 02133 return (1); 02134 } 02135 02136 /* contents() is used to find things strings with characters like commas and 02137 * dashes. 02138 */ 02139 static int contains(const char *s, int c) 02140 { 02141 while (*s) { 02142 if (*s == c) 02143 return (1); 02144 s++; 02145 } 02146 return (0); 02147 } 02148 02149 static int is_option(const char *string) 02150 { 02151 const char *p = strchr(string, '='); 02152 02153 if (!p) 02154 return 0; 02155 if (p == string) 02156 return 0; 02157 p--; 02158 if (!strchr("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", *p)) 02159 return 0; 02160 02161 return 1; 02162 } 02163 02164 static int set_option(char *string) 02165 { 02166 struct Option *at_opt = NULL; 02167 struct Option *opt = NULL; 02168 int got_one; 02169 size_t key_len; 02170 char the_key[KEYLENGTH]; 02171 char *ptr; 02172 02173 for (ptr = the_key; *string != '='; ptr++, string++) 02174 *ptr = *string; 02175 *ptr = '\0'; 02176 string++; 02177 02178 /* Find option with best keyword match */ 02179 got_one = 0; 02180 key_len = strlen(the_key); 02181 for (at_opt = &first_option; at_opt != NULL; at_opt = at_opt->next_opt) { 02182 if (at_opt->key == NULL || strncmp(the_key, at_opt->key, key_len)) 02183 continue; 02184 02185 got_one++; 02186 opt = at_opt; 02187 02188 /* changed 1/15/91 -dpg old code is in parser.old */ 02189 /* overide ambiguous check, if we get an exact match */ 02190 if (strlen(at_opt->key) == key_len) { 02191 opt = at_opt; 02192 got_one = 1; 02193 break; 02194 } 02195 } 02196 02197 if (got_one > 1) { 02198 fprintf(stderr, _("Sorry, <%s=> is ambiguous\n"), the_key); 02199 return (1); 02200 } 02201 02202 /* If there is no match, complain */ 02203 if (got_one == 0) { 02204 fprintf(stderr, _("Sorry, <%s> is not a valid parameter\n"), the_key); 02205 return (1); 02206 } 02207 02208 /* Allocate memory where answer is stored */ 02209 if (opt->count++) { 02210 if (!opt->multiple) { 02211 fprintf(stderr, _("Option <%s> does not accept multiple answers\n"), the_key); 02212 return (1); 02213 } 02214 opt->answer = (char *)G_realloc(opt->answer, 02215 strlen(opt->answer) + strlen(string) + 02216 2); 02217 strcat(opt->answer, ","); 02218 strcat(opt->answer, string); 02219 } 02220 else 02221 opt->answer = G_store(string); 02222 return (0); 02223 } 02224 02225 static int check_opts(void) 02226 { 02227 struct Option *opt; 02228 int error; 02229 int ans; 02230 02231 error = 0; 02232 02233 if (!n_opts) 02234 return (0); 02235 02236 opt = &first_option; 02237 while (opt != NULL) { 02238 /* Check answer against options if any */ 02239 02240 if (opt->options && opt->answer) { 02241 if (opt->multiple == 0) 02242 error += check_an_opt(opt->key, opt->type, 02243 opt->options, opt->answer); 02244 else { 02245 for (ans = 0; opt->answers[ans] != '\0'; ans++) 02246 error += check_an_opt(opt->key, opt->type, 02247 opt->options, opt->answers[ans]); 02248 } 02249 } 02250 02251 /* Check answer against user's check subroutine if any */ 02252 02253 if (opt->checker) 02254 error += opt->checker(opt->answer); 02255 02256 opt = opt->next_opt; 02257 } 02258 return (error); 02259 } 02260 02261 static int check_an_opt(const char *key, int type, const char *options, 02262 const char *answer) 02263 { 02264 int error; 02265 02266 error = 0; 02267 02268 switch (type) { 02269 case TYPE_INTEGER: 02270 error = check_int(answer, options); 02271 break; 02272 case TYPE_DOUBLE: 02273 error = check_double(answer, options); 02274 break; 02275 case TYPE_STRING: 02276 error = check_string(answer, options); 02277 break; 02278 /* 02279 case TYPE_COORDINATE: 02280 error = check_coor(answer,options) ; 02281 break ; 02282 */ 02283 } 02284 switch (error) { 02285 case 0: 02286 break; 02287 case BAD_SYNTAX: 02288 fprintf(stderr, 02289 _("\nERROR: illegal range syntax for parameter <%s>\n"), key); 02290 fprintf(stderr, _(" Presented as: %s\n"), options); 02291 break; 02292 case OUT_OF_RANGE: 02293 fprintf(stderr, 02294 _("\nERROR: value <%s> out of range for parameter <%s>\n"), 02295 answer, key); 02296 fprintf(stderr, _(" Legal range: %s\n"), options); 02297 break; 02298 case MISSING_VALUE: 02299 fprintf(stderr, _("\nERROR: Missing value for parameter <%s>\n"), 02300 key); 02301 } 02302 return (error); 02303 } 02304 02305 static int check_int(const char *ans, const char *opts) 02306 { 02307 int d, lo, hi; 02308 02309 if (1 != sscanf(ans, "%d", &d)) 02310 return (MISSING_VALUE); 02311 02312 if (contains(opts, '-')) { 02313 if (2 != sscanf(opts, "%d-%d", &lo, &hi)) 02314 return (BAD_SYNTAX); 02315 if (d < lo || d > hi) 02316 return (OUT_OF_RANGE); 02317 else 02318 return (0); 02319 } 02320 else if (contains(opts, ',')) { 02321 for (;;) { 02322 if (1 != sscanf(opts, "%d", &lo)) 02323 return (BAD_SYNTAX); 02324 if (d == lo) 02325 return (0); 02326 while (*opts != '\0' && *opts != ',') 02327 opts++; 02328 if (*opts == '\0') 02329 return (OUT_OF_RANGE); 02330 if (*(++opts) == '\0') 02331 return (OUT_OF_RANGE); 02332 } 02333 } 02334 else { 02335 if (1 != sscanf(opts, "%d", &lo)) 02336 return (BAD_SYNTAX); 02337 if (d == lo) 02338 return (0); 02339 return (OUT_OF_RANGE); 02340 } 02341 } 02342 02343 /* 02344 static int 02345 check_coor(ans, opts) 02346 char *ans ; 02347 char *opts ; 02348 { 02349 double xd, xlo, xhi; 02350 double yd, ylo, yhi; 02351 02352 if (1 != sscanf(ans,"%lf,%lf", &xd, &yd)) 02353 return(MISSING_VALUE) ; 02354 02355 if (contains(opts, '-')) 02356 { 02357 if (2 != sscanf(opts,"%lf-%lf,%lf-%lf",&xlo, &xhi, &ylo, &yhi)) 02358 return(BAD_SYNTAX) ; 02359 if (xd < xlo || xd > xhi) 02360 return(OUT_OF_RANGE) ; 02361 if (yd < ylo || yd > yhi) 02362 return(OUT_OF_RANGE) ; 02363 return(0) ; 02364 } 02365 return(BAD_SYNTAX) ; 02366 } 02367 */ 02368 02369 static int check_double(const char *ans, const char *opts) 02370 { 02371 double d, lo, hi; 02372 02373 if (1 != sscanf(ans, "%lf", &d)) 02374 return (MISSING_VALUE); 02375 02376 if (contains(opts, '-')) { 02377 if (2 != sscanf(opts, "%lf-%lf", &lo, &hi)) 02378 return (BAD_SYNTAX); 02379 if (d < lo || d > hi) 02380 return (OUT_OF_RANGE); 02381 else 02382 return (0); 02383 } 02384 else if (contains(opts, ',')) { 02385 for (;;) { 02386 if (1 != sscanf(opts, "%lf", &lo)) 02387 return (BAD_SYNTAX); 02388 if (d == lo) 02389 return (0); 02390 while (*opts != '\0' && *opts != ',') 02391 opts++; 02392 if (*opts == '\0') 02393 return (OUT_OF_RANGE); 02394 if (*(++opts) == '\0') 02395 return (OUT_OF_RANGE); 02396 } 02397 } 02398 else { 02399 if (1 != sscanf(opts, "%lf", &lo)) 02400 return (BAD_SYNTAX); 02401 if (d == lo) 02402 return (0); 02403 return (OUT_OF_RANGE); 02404 } 02405 } 02406 02407 static int check_string(const char *ans, const char *opts) 02408 { 02409 if (*opts == '\0') 02410 return (0); 02411 02412 if (contains(opts, ',')) { 02413 for (;;) { 02414 if ((!strncmp(ans, opts, strlen(ans))) 02415 && (*(opts + strlen(ans)) == ',' 02416 || *(opts + strlen(ans)) == '\0')) 02417 return (0); 02418 while (*opts != '\0' && *opts != ',') 02419 opts++; 02420 if (*opts == '\0') 02421 return (OUT_OF_RANGE); 02422 if (*(++opts) == '\0') 02423 return (OUT_OF_RANGE); 02424 } 02425 } 02426 else { 02427 if (!strcmp(ans, opts)) 02428 return (0); 02429 return (OUT_OF_RANGE); 02430 } 02431 } 02432 02433 static int check_required(void) 02434 { 02435 struct Option *opt; 02436 int err; 02437 02438 err = 0; 02439 02440 if (!n_opts) 02441 return (0); 02442 02443 opt = &first_option; 02444 while (opt != NULL) { 02445 if (opt->required && opt->answer == NULL) { 02446 fprintf(stderr, 02447 _("ERROR: Required parameter <%s> not set:\n\t(%s)\n"), 02448 opt->key, (opt->label ? opt->label : opt->description) ); 02449 err++; 02450 } 02451 opt = opt->next_opt; 02452 } 02453 02454 return (err); 02455 } 02456 02457 static int split_opts(void) 02458 { 02459 struct Option *opt; 02460 char *ptr1; 02461 char *ptr2; 02462 int allocated; 02463 int ans_num; 02464 int len; 02465 02466 02467 if (!n_opts) 02468 return 0; 02469 02470 opt = &first_option; 02471 while (opt != NULL) { 02472 if ( /*opt->multiple && */ (opt->answer != NULL)) { 02473 /* Allocate some memory to store array of pointers */ 02474 allocated = 10; 02475 opt->answers = (char **)G_malloc(allocated * sizeof(char *)); 02476 02477 ans_num = 0; 02478 ptr1 = opt->answer; 02479 opt->answers[ans_num] = NULL; 02480 02481 for (;;) { 02482 for (len = 0, ptr2 = ptr1; *ptr2 != '\0' && *ptr2 != ','; 02483 ptr2++, len++) ; 02484 02485 if (len > 0) { /* skip ,, */ 02486 opt->answers[ans_num] = (char *)G_malloc(len + 1); 02487 G_copy(opt->answers[ans_num], ptr1, len); 02488 opt->answers[ans_num][len] = 0; 02489 02490 ans_num++; 02491 02492 if (ans_num >= allocated) { 02493 allocated += 10; 02494 opt->answers = 02495 (char **)G_realloc((char *)opt->answers, 02496 allocated * sizeof(char *)); 02497 } 02498 02499 opt->answers[ans_num] = NULL; 02500 } 02501 02502 if (*ptr2 == '\0') 02503 break; 02504 02505 ptr1 = ptr2 + 1; 02506 02507 if (*ptr1 == '\0') 02508 break; 02509 } 02510 } 02511 opt = opt->next_opt; 02512 } 02513 02514 return 0; 02515 } 02516 02517 static int check_multiple_opts(void) 02518 { 02519 struct Option *opt; 02520 const char *ptr; 02521 int n_commas; 02522 int n; 02523 int error; 02524 02525 if (!n_opts) 02526 return (0); 02527 02528 error = 0; 02529 opt = &first_option; 02530 while (opt != NULL) { 02531 if ((opt->answer != NULL) && (opt->key_desc != NULL)) { 02532 /* count commas */ 02533 n_commas = 1; 02534 for (ptr = opt->key_desc; *ptr != '\0'; ptr++) 02535 if (*ptr == ',') 02536 n_commas++; 02537 /* count items */ 02538 for (n = 0; opt->answers[n] != '\0'; n++) ; 02539 /* if not correct multiple of items */ 02540 if (n % n_commas) { 02541 fprintf(stderr, 02542 _("\nERROR: option <%s> must be provided in multiples of %d\n"), 02543 opt->key, n_commas); 02544 fprintf(stderr, _(" You provided %d items:\n"), n); 02545 fprintf(stderr, " %s\n", opt->answer); 02546 error++; 02547 } 02548 } 02549 opt = opt->next_opt; 02550 } 02551 return (error); 02552 } 02553 02554 /* Check for all 'new' if element already exists */ 02555 static int check_overwrite(void) 02556 { 02557 struct Option *opt; 02558 char age[KEYLENGTH]; 02559 char element[KEYLENGTH]; 02560 char desc[KEYLENGTH]; 02561 int error = 0; 02562 char *overstr; 02563 int over; 02564 02565 if (!n_opts) 02566 return (0); 02567 02568 over = 0; 02569 /* Check the GRASS OVERWRITE variable */ 02570 if ((overstr = G__getenv("OVERWRITE"))) { 02571 over = atoi(overstr); 02572 } 02573 02574 /* Check the GRASS_OVERWRITE environment variable */ 02575 if ((overstr = getenv("GRASS_OVERWRITE"))) { 02576 if (atoi(overstr)) 02577 over = 1; 02578 } 02579 02580 if (overwrite || over) { 02581 module_info.overwrite = 1; 02582 /* Set the environment so that programs run in a script also obey --o */ 02583 putenv("GRASS_OVERWRITE=1"); 02584 /* No need to check options for existing files if overwrite is true */ 02585 return error; 02586 } 02587 02588 opt = &first_option; 02589 while (opt != NULL) { 02590 if ((opt->answer != NULL) && (opt->gisprompt != NULL)) { 02591 split_gisprompt(opt->gisprompt, age, element, desc); 02592 02593 if (strcmp(age, "new") == 0) { 02594 int i; 02595 for (i = 0; opt->answers[i]; i++) { 02596 if (G_find_file(element, opt->answers[i], G_mapset())) { /* found */ 02597 if (!overwrite && !over) { 02598 if (G_info_format() != G_INFO_FORMAT_GUI) { 02599 fprintf(stderr, 02600 _("ERROR: option <%s>: <%s> exists.\n"), 02601 opt->key, opt->answers[i]); 02602 } 02603 else { 02604 fprintf(stderr, 02605 "GRASS_INFO_ERROR(%d,1): option <%s>: <%s> exists.\n", 02606 getpid(), opt->key, opt->answers[i]); 02607 fprintf(stderr, "GRASS_INFO_END(%d,1)\n", 02608 getpid()); 02609 } 02610 02611 error = 1; 02612 } 02613 } 02614 } 02615 } 02616 } 02617 opt = opt->next_opt; 02618 } 02619 02620 return (error); 02621 } 02622 02623 static int interactive(const char *command) 02624 { 02625 struct Item *item; 02626 02627 /* Query for flags */ 02628 02629 if (!n_items) { 02630 fprintf(stderr, "PROGRAMMER ERROR: no flags or options\n"); 02631 exit(EXIT_FAILURE); 02632 } 02633 02634 for (item = &first_item;;) { 02635 if (item->flag) 02636 interactive_flag(item->flag); 02637 else if (item->option) 02638 interactive_option(item->option); 02639 else 02640 break; 02641 02642 item = item->next_item; 02643 02644 if (item == NULL) 02645 break; 02646 } 02647 02648 return 0; 02649 } 02650 02651 static int interactive_flag(struct Flag *flag) 02652 { 02653 char buff[1024]; 02654 02655 fprintf(stderr, _("\nFLAG: Set the following flag?\n")); 02656 sprintf(buff, " %s?", flag->description); 02657 flag->answer = G_yes(buff, 0); 02658 02659 return 0; 02660 } 02661 02662 static int interactive_option(struct Option *opt) 02663 { 02664 char buff[1024], *bptr; 02665 char buff2[1024]; 02666 int set_one; 02667 int no_prompt; 02668 02669 fprintf(stderr, _("\nOPTION: %s\n"), opt->description); 02670 fprintf(stderr, _(" key: %s\n"), opt->key); 02671 if (opt->key_desc) 02672 fprintf(stderr, _(" format: %s\n"), opt->key_desc); 02673 if (opt->def) 02674 fprintf(stderr, _(" default: %s\n"), opt->def); 02675 fprintf(stderr, _("required: %s\n"), opt->required ? "YES" : "NO"); 02676 if (opt->multiple) 02677 fprintf(stderr, _("multiple: %s\n"), opt->multiple ? "YES" : "NO"); 02678 if (opt->options) 02679 fprintf(stderr, _(" options: %s\n"), opt->options); 02680 /* 02681 show_options(0, opt->options) ; 02682 */ 02683 02684 set_one = 0; 02685 for (;;) { 02686 *buff = '\0'; 02687 if (opt->gisprompt) 02688 no_prompt = gis_prompt(opt, buff); 02689 else 02690 no_prompt = -1; 02691 if (no_prompt) { 02692 fprintf(stderr, _("enter option > ")); 02693 if (fgets(buff, 1024, stdin) == 0) 02694 exit(EXIT_SUCCESS);; 02695 bptr = buff; /* strip newline */ 02696 while (*bptr) { 02697 if (*bptr == '\n') 02698 *bptr = '\0'; 02699 bptr++; 02700 } 02701 02702 } 02703 02704 if (strlen(buff) != 0) { 02705 if (opt->options) 02706 /* then check option */ 02707 { 02708 if (check_an_opt(opt->key, opt->type, opt->options, buff)) { 02709 if (G_yes(_(" Try again? "), 1)) 02710 continue; 02711 else 02712 exit(EXIT_FAILURE); 02713 } 02714 } 02715 if (opt->checker) 02716 if (opt->checker(buff)) { 02717 fprintf(stderr, _("Sorry, %s is not accepted.\n"), buff); 02718 *buff = '\0'; 02719 if (G_yes(_(" Try again? "), 1)) 02720 continue; 02721 else 02722 exit(EXIT_FAILURE); 02723 } 02724 02725 sprintf(buff2, "%s=%s", opt->key, buff); 02726 if (!opt->gisprompt) { 02727 fprintf(stderr, _("\nYou have chosen:\n %s\n"), buff2); 02728 if (G_yes(_("Is this correct? "), 1)) { 02729 set_option(buff2); 02730 set_one++; 02731 } 02732 } 02733 else { 02734 set_option(buff2); 02735 set_one++; 02736 } 02737 } /* if strlen(buf ) !=0 */ 02738 02739 if ((strlen(buff) == 0) && opt->required && (set_one == 0)) 02740 exit(EXIT_FAILURE); 02741 if ((strlen(buff) == 0) && (set_one > 0) && opt->multiple) 02742 break; 02743 if ((strlen(buff) == 0) && !opt->required) 02744 break; 02745 if ((set_one == 1) && !opt->multiple) 02746 break; 02747 } 02748 return (0); 02749 } 02750 02751 static int split_gisprompt(const char *gisprompt, char *age, char *element, 02752 char *desc) 02753 { 02754 const char *ptr1; 02755 char *ptr2; 02756 02757 for (ptr1 = gisprompt, ptr2 = age; *ptr1 != '\0'; ptr1++, ptr2++) { 02758 if (*ptr1 == ',') 02759 break; 02760 *ptr2 = *ptr1; 02761 } 02762 *ptr2 = '\0'; 02763 02764 for (ptr1++, ptr2 = element; *ptr1 != '\0'; ptr1++, ptr2++) { 02765 if (*ptr1 == ',') 02766 break; 02767 *ptr2 = *ptr1; 02768 } 02769 *ptr2 = '\0'; 02770 02771 for (ptr1++, ptr2 = desc; *ptr1 != '\0'; ptr1++, ptr2++) { 02772 if (*ptr1 == ',') 02773 break; 02774 *ptr2 = *ptr1; 02775 } 02776 *ptr2 = '\0'; 02777 02778 return 0; 02779 } 02780 02781 static int gis_prompt(struct Option *opt, char *buff) 02782 { 02783 char age[KEYLENGTH]; 02784 char element[KEYLENGTH]; 02785 char desc[KEYLENGTH]; 02786 char *ptr1; 02787 02788 split_gisprompt(opt->gisprompt, age, element, desc); 02789 02790 /*********ptr1 points to current mapset description***********/ 02791 02792 if (opt->answer) 02793 G_set_ask_return_msg(_("to accept the default")); 02794 if (!strcmp("old", age)) { 02795 ptr1 = G_ask_old("", buff, element, desc); 02796 if (ptr1) { 02797 strcpy(buff, G_fully_qualified_name(buff, ptr1)); 02798 } 02799 } 02800 else if (!strcmp("new", age)) 02801 ptr1 = G_ask_new("", buff, element, desc); 02802 else if (!strcmp("mapset", age)) 02803 ptr1 = G_ask_in_mapset("", buff, element, desc); 02804 else if (!strcmp("any", age)) 02805 ptr1 = G_ask_any("", buff, element, desc, 1); 02806 else if (!strcmp("old_file", age)) /* file must exist */ 02807 ptr1 = G_ask_old_file("", buff, element, desc); 02808 else if (!strcmp("new_file", age)) /* file shouldn't exist unless overwrite is enabled */ 02809 ptr1 = G_ask_new_file("", buff, element, desc); 02810 else { 02811 return -1; 02812 } 02813 02814 if (ptr1 == '\0') 02815 *buff = '\0'; 02816 02817 return 0; 02818 } 02819 02828 char *G_recreate_command(void) 02829 { 02830 static char *buff; 02831 char flg[4]; 02832 char *cur; 02833 const char *tmp; 02834 struct Flag *flag; 02835 struct Option *opt; 02836 int n, len, slen; 02837 int nalloced = 0; 02838 02839 G_debug(3, "G_recreate_command()"); 02840 02841 /* Flag is not valid if there are no flags to set */ 02842 02843 buff = G_calloc(1024, sizeof(char)); 02844 nalloced += 1024; 02845 tmp = G_program_name(); 02846 len = strlen(tmp); 02847 if (len >= nalloced) { 02848 nalloced += (1024 > len) ? 1024 : len + 1; 02849 buff = G_realloc(buff, nalloced); 02850 } 02851 cur = buff; 02852 strcpy(cur, tmp); 02853 cur += len; 02854 02855 if (n_flags) { 02856 flag = &first_flag; 02857 while (flag != '\0') { 02858 if (flag->answer == 1) { 02859 flg[0] = ' '; 02860 flg[1] = '-'; 02861 flg[2] = flag->key; 02862 flg[3] = '\0'; 02863 slen = strlen(flg); 02864 if (len + slen >= nalloced) { 02865 nalloced += 02866 (nalloced + 1024 > len + slen) ? 1024 : slen + 1; 02867 buff = G_realloc(buff, nalloced); 02868 cur = buff + len; 02869 } 02870 strcpy(cur, flg); 02871 cur += slen; 02872 len += slen; 02873 } 02874 flag = flag->next_flag; 02875 } 02876 } 02877 02878 opt = &first_option; 02879 while (opt != '\0') { 02880 if (opt->answer != '\0' && opt->answers && opt->answers[0] != NULL) { 02881 slen = strlen(opt->key) + strlen(opt->answers[0]) + 4; /* +4 for: ' ' = " " */ 02882 if (len + slen >= nalloced) { 02883 nalloced += (nalloced + 1024 > len + slen) ? 1024 : slen + 1; 02884 buff = G_realloc(buff, nalloced); 02885 cur = buff + len; 02886 } 02887 strcpy(cur, " "); 02888 cur++; 02889 strcpy(cur, opt->key); 02890 cur = strchr(cur, '\0'); 02891 strcpy(cur, "="); 02892 cur++; 02893 if (opt->type == TYPE_STRING) { 02894 strcpy(cur, "\""); 02895 cur++; 02896 } 02897 strcpy(cur, opt->answers[0]); 02898 cur = strchr(cur, '\0'); 02899 len = cur - buff; 02900 for (n = 1; opt->answers[n] != NULL && opt->answers[n] != '\0'; 02901 n++) { 02902 if (opt->answers[n] == NULL) 02903 break; 02904 slen = strlen(opt->answers[n]) + 2; /* +2 for , " */ 02905 if (len + slen >= nalloced) { 02906 nalloced += 02907 (nalloced + 1024 > len + slen) ? 1024 : slen + 1; 02908 buff = G_realloc(buff, nalloced); 02909 cur = buff + len; 02910 } 02911 strcpy(cur, ","); 02912 cur++; 02913 strcpy(cur, opt->answers[n]); 02914 cur = strchr(cur, '\0'); 02915 len = cur - buff; 02916 } 02917 if (opt->type == TYPE_STRING) { 02918 strcpy(cur, "\""); 02919 cur++; 02920 len = cur - buff; 02921 } 02922 } 02923 opt = opt->next_opt; 02924 } 02925 02926 return (buff); 02927 }