• Main Page
  • Related Pages
  • Data Structures
  • Files
  • File List
  • Globals

parser.c

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

Generated on Wed Oct 13 2010 12:09:30 for GRASS Programmer's Manual by  doxygen 1.7.1