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