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