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