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