parser.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  * Routines used to assist in command line parsing.  
00003  ***************************************************************************
00004  * G_define_flag()
00005  *
00006  * Returns a pointer to a flag structure.
00007  * Flags are always represented by single letters.  A user "turns them on"
00008  * at the command line using a minus sign followed by the character
00009  * representing the flag.
00010  *
00011  ***************************************************************************
00012  * G_define_option()
00013  *
00014  * Returns a pointer to a flag structure.
00015  * Options are provided by user on command line using the standard
00016  * format:  key=value
00017  * Options identified as REQUIRED must be specified by user on command line.
00018  * The option string can either specify a range of values (e.g. "10-100") or
00019  * a list of acceptable values (e.g. "red,orange,yellow").  Unless the option
00020  * string is NULL, user provided input will be evaluated agaist this string.
00021  *
00022  ***************************************************************************
00023  *
00024  * G_disable_interactive()
00025  *
00026  * Disables the ability of the parser to operate interactively.
00027  *
00028  ***************************************************************************
00029  *
00030  * G_parser(argc, argv)
00031  *    int argc ;
00032  *    char **argv ;
00033  *
00034  * Parses the command line provided through argc and argv.  Example:
00035  * Assume the previous calls:
00036  *
00037  *  opt1 = G_define_option() ;
00038  *  opt1->key        = "map",
00039  *  opt1->type       = TYPE_STRING,
00040  *  opt1->required   = YES,
00041  *  opt1->checker    = sub,
00042  *  opt1->description= "Name of an existing raster map" ;
00043  *
00044  *  opt2 = G_define_option() ;
00045  *  opt2->key        = "color",
00046  *  opt2->type       = TYPE_STRING,
00047  *  opt2->required   = NO,
00048  *  opt2->answer     = "white",
00049  *  opt2->options    = "red,orange,blue,white,black",
00050  *  opt2->description= "Color used to display the map" ;
00051  *
00052  *  opt3 = G_define_option() ;
00053  *  opt3->key        = "number",
00054  *  opt3->type       = TYPE_DOUBLE,
00055  *  opt3->required   = NO,
00056  *  opt3->answer     = "12345.67",
00057  *  opt3->options    = "0-99999",
00058  *  opt3->description= "Number to test parser" ;
00059  *
00060  *
00061  * The only functions which can legitimately be called before G_parser() are:
00062  *   G_gisinit()
00063  *   G_no_gisinit()
00064  *   G_define_module()
00065  *   G_define_flag()
00066  *   G_define_option()
00067  *   G_define_standard_option()
00068  *   G_disable_interactive()
00069  *
00070  * The usual order is:
00071  *   G_gisinit()
00072  *   G_define_module()
00073  *   G_define_{flag,option}()
00074  *   G_parser()
00075  *
00076  *
00077  * G_parser() will respond to the following command lines as described:
00078  *
00079  * command      (No command line arguments)
00080  *    Parser enters interactive mode.
00081  *
00082  * command map=map.name
00083  *    Parser will accept this line.  Map will be set to "map.name", the
00084  *    'a' and 'b' flags will remain off and the num option will be set
00085  *    to the default of 5.
00086  *
00087  * command -ab map=map.name num=9
00088  * command -a -b map=map.name num=9
00089  * command -ab map.name num=9
00090  * command map.name num=9 -ab
00091  * command num=9 -a map=map.name -b
00092  *    These are all treated as acceptable and identical. Both flags are
00093  *    set to on, the map option is "map.name" and the num option is "9".
00094  *    Note that the "map=" may be omitted from the command line if it
00095  *    is part of the first option (flags do not count).
00096  *
00097  * command num=12
00098  *    This command line is in error in two ways.  The user will be told 
00099  *    that the "map" option is required and also that the number 12 is
00100  *    out of range.  The acceptable range (or list) will be printed.
00101  *
00102  * On error, G_parser() prints call G_usage() and returns -1.
00103  * Otherwise returns 0
00104  *
00105  ***************************************************************************
00106  *
00107  * G_recreate_command()
00108  *
00109  * Creates a command-line that runs the current command completely
00110  * non-interactive
00111  *
00112  ***************************************************************************
00113 */
00114 
00115 #include <grass/config.h>
00116 
00117 #if defined(HAVE_LANGINFO_H)
00118 #include <langinfo.h>
00119 #endif
00120 
00121 #include <stdio.h>
00122 #include <stdlib.h>
00123 #include <string.h>
00124 #include <ctype.h>
00125 #include <unistd.h>
00126 #include <stdarg.h>
00127 #include <grass/gis.h>
00128 #include <grass/glocale.h>
00129 
00130 #define BAD_SYNTAX  1
00131 #define OUT_OF_RANGE    2
00132 #define MISSING_VALUE   3
00133 #define KEYLENGTH 64
00134 
00135 static int interactive_ok = 1 ;
00136 static int n_opts = 0 ;
00137 static int n_flags = 0 ;
00138 static int overwrite = 0 ;
00139 
00140 static struct Flag first_flag;    /* First flag in a linked list      */
00141 static struct Flag *current_flag; /* Pointer for traversing list      */
00142 
00143 static struct Option first_option ;
00144 static struct Option *current_option ;
00145 
00146 static struct GModule module_info; /* general information on the corresponding module */
00147 
00148 static const char *pgm_name = NULL;
00149 
00150 struct Item
00151 {
00152         struct Option *option ;
00153         struct Flag *flag ;
00154         struct Item *next_item ;
00155 } ;
00156 
00157 static struct Item first_item ;
00158 static struct Item *current_item ;
00159 static int n_items = 0 ;
00160 static int show_options(int ,char *);
00161 static int show(const char *,int);
00162 static int set_flag (int);
00163 static int contains (char *,int);
00164 static int set_option( char *);
00165 static int check_opts();
00166 static int check_an_opt( char *, int , char *,char *);
00167 static int check_int(char *, char *);
00168 static int check_double( char *, char *);
00169 static int check_string( char *, char *);
00170 static int check_required();
00171 static int split_opts();
00172 static int check_multiple_opts();
00173 static int check_overwrite();
00174 static int interactive( char *);
00175 static int interactive_flag( struct Flag *);
00176 static int interactive_option( struct Option *);
00177 static int gis_prompt( struct Option *, char *);
00178 static int split_gisprompt (const char *, char *, char *, char *);
00179 
00180 static void G_gui (void);
00181 static void G_tcltk (void);
00182 static void G_usage_xml (void);
00183 static void G_usage_html (void);
00184 
00185 
00199 int 
00200 G_disable_interactive (void)
00201 {
00202         interactive_ok = 0 ;
00203 
00204         return 0;
00205 }
00206 
00207  
00218 struct Flag *
00219 G_define_flag (void)
00220 {
00221         struct Flag *flag ;
00222         struct Item *item ;
00223 
00224         /* Allocate memory if not the first flag */
00225 
00226         if (n_flags)
00227         {
00228                 flag = (struct Flag *)G_malloc(sizeof(struct Flag)) ;
00229                 current_flag->next_flag = flag ;
00230         }
00231         else
00232                 flag = &first_flag ;
00233 
00234         /* Zero structure */
00235 
00236         G_zero ((char *) flag, sizeof(struct Flag));
00237 
00238         current_flag = flag ;
00239         n_flags++ ;
00240 
00241         if (n_items)
00242         {
00243                 item = (struct Item *)G_malloc(sizeof(struct Item)) ;
00244                 current_item->next_item = item ;
00245         }
00246         else
00247                 item = &first_item ;
00248 
00249         G_zero ((char *) item, sizeof(struct Item));
00250         
00251         item->flag = flag ;
00252         item->option = NULL ;
00253 
00254         current_item = item ;
00255         n_items++ ;
00256 
00257         return(flag) ;
00258 }
00259 
00269 struct Option *
00270 G_define_option (void)
00271 {
00272         struct Option *opt ;
00273         struct Item *item ;
00274 
00275         /* Allocate memory if not the first option */
00276 
00277         if (n_opts)
00278         {
00279                 opt = (struct Option *)G_malloc(sizeof(struct Option)) ;
00280                 current_option->next_opt = opt ;
00281         }
00282         else
00283                 opt = &first_option ;
00284 
00285         /* Zero structure */
00286         G_zero ((char *) opt, sizeof(struct Option));
00287 
00288         opt->required  = NO ;
00289         opt->multiple  = NO ;
00290         opt->answer    = NULL ;
00291         opt->answers   = NULL ;
00292         opt->def       = NULL ;
00293         opt->checker   = NULL ;
00294         opt->options   = NULL ;
00295         opt->key_desc  = NULL ;
00296         opt->gisprompt = NULL ;
00297         opt->label     = NULL ;
00298         opt->opts      = NULL ;
00299         opt->description  = NULL ;
00300         opt->descriptions = NULL ;
00301         opt->guisection   = NULL ;
00302 
00303         current_option = opt ;
00304         n_opts++ ;
00305 
00306         if (n_items)
00307         {
00308                 item = (struct Item *)G_malloc(sizeof(struct Item)) ;
00309                 current_item->next_item = item ;
00310         }
00311         else
00312                 item = &first_item ;
00313 
00314         G_zero ((char *) item, sizeof(struct Item));
00315         
00316         item->option = opt ;
00317         item->flag = NULL ;
00318 
00319         current_item = item ;
00320         n_items++ ;
00321 
00322         return(opt) ;
00323 }
00324 
00325 
00342 struct Option *
00343 G_define_standard_option (int opt)
00344 {
00345     struct Option *Opt;
00346     
00347     Opt = G_define_option();
00348 
00349     switch ( opt ) {
00350         case G_OPT_WHERE:
00351             Opt->key          = "where";
00352             Opt->type         = TYPE_STRING;
00353             Opt->key_desc     = "sql_query";
00354             Opt->required     = NO;
00355             Opt->description  = _("WHERE conditions of SQL statement without 'where' keyword. (example: income < 1000 and inhab >= 10000)");
00356             break;
00357             
00358         /*raster maps*/    
00359         case G_OPT_R_INPUT:
00360             Opt->key          = "input";
00361             Opt->type         = TYPE_STRING;
00362             Opt->key_desc     = "name";
00363             Opt->required     = YES;
00364             Opt->gisprompt    = "old,cell,raster";
00365             Opt->description  = _("Name of input raster map");
00366             break;
00367         case G_OPT_R_INPUTS:
00368             Opt->key          = "input";
00369             Opt->type         = TYPE_STRING;
00370             Opt->key_desc     = "name";
00371             Opt->required     = YES;
00372             Opt->multiple     = YES;
00373             Opt->gisprompt    = "old,cell,raster";
00374             Opt->description  = _("Name of input raster map(s)");
00375             break;
00376         case G_OPT_R_OUTPUT:
00377             Opt->key          = "output";
00378             Opt->type         = TYPE_STRING;
00379             Opt->key_desc     = "name";
00380             Opt->required     = YES;
00381             Opt->gisprompt    = "new,cell,raster";
00382             Opt->description  = _("Name for output raster map");
00383             break;
00384         case G_OPT_R_MAP:
00385             Opt->key          = "map";
00386             Opt->type         = TYPE_STRING;
00387             Opt->key_desc     = "name";
00388             Opt->required     = YES;
00389             Opt->gisprompt    = "old,cell,raster";
00390             Opt->description  = _("Name of input raster map");
00391             break;
00392         case G_OPT_R_MAPS:
00393             Opt->key          = "map";
00394             Opt->type         = TYPE_STRING;
00395             Opt->key_desc     = "name";
00396             Opt->required     = YES;
00397             Opt->multiple     = YES;
00398             Opt->gisprompt    = "old,cell,raster";
00399             Opt->description  = _("Name of input raster map(s)");
00400             break;
00401         case G_OPT_R_BASE:
00402             Opt->key          = "base";
00403             Opt->type         = TYPE_STRING;
00404             Opt->key_desc     = "name";
00405             Opt->required     = YES;
00406             Opt->gisprompt    = "old,cell,raster";
00407             Opt->description  = _("Name of base raster map");
00408             break;
00409         case G_OPT_R_COVER:
00410             Opt->key          = "cover";
00411             Opt->type         = TYPE_STRING;
00412             Opt->key_desc     = "name";
00413             Opt->required     = YES;
00414             Opt->gisprompt    = "old,cell,raster";
00415             Opt->description  = _("Name of cover raster map");
00416             break;
00417         case G_OPT_R_ELEV:
00418             Opt->key          = "elevation";
00419             Opt->type         = TYPE_STRING;
00420             Opt->key_desc     = "name";
00421             Opt->required     = YES;
00422             Opt->gisprompt    = "old,cell,raster";
00423             Opt->description  = _("Name of elevation raster map");
00424             break;
00425         case G_OPT_R_ELEVS:
00426             Opt->key          = "elevation";
00427             Opt->type         = TYPE_STRING;
00428             Opt->key_desc     = "name";
00429             Opt->required     = YES;
00430             Opt->multiple     = YES;
00431             Opt->gisprompt    = "old,cell,raster";
00432             Opt->description  = _("Name of elevation raster map(s)");
00433             break;
00434 
00435         /*g3d maps*/    
00436         case G_OPT_R3_INPUT:
00437             Opt->key          = "input";
00438             Opt->type         = TYPE_STRING;
00439             Opt->key_desc     = "name";
00440             Opt->required     = YES;
00441             Opt->gisprompt    = "old,grid3,3d-raster";
00442             Opt->description  = _("Name of input raster3d map");
00443             break;
00444         case G_OPT_R3_INPUTS:
00445             Opt->key          = "input";
00446             Opt->type         = TYPE_STRING;
00447             Opt->key_desc     = "name";
00448             Opt->required     = YES;
00449             Opt->multiple     = YES;
00450             Opt->gisprompt    = "old,grid3,3d-raster";
00451             Opt->description  = _("Name of input raster3d map(s)");
00452             break;
00453         case G_OPT_R3_OUTPUT:
00454             Opt->key          = "output";
00455             Opt->type         = TYPE_STRING;
00456             Opt->key_desc     = "name";
00457             Opt->required     = YES;
00458             Opt->gisprompt    = "new,grid3,3d-raster";
00459             Opt->description  = _("Name for output raster3d map");
00460             break;
00461 
00462         /*vector maps*/    
00463         case G_OPT_V_INPUT:
00464             Opt->key          = "input";
00465             Opt->type         = TYPE_STRING;
00466             Opt->key_desc     = "name";
00467             Opt->required     = YES;
00468             Opt->gisprompt    = "old,vector,vector";
00469             Opt->description  = _("Name of input vector map");
00470             break;
00471         case G_OPT_V_OUTPUT:
00472             Opt->key          = "output";
00473             Opt->type         = TYPE_STRING;
00474             Opt->key_desc     = "name";
00475             Opt->required     = YES;
00476             Opt->gisprompt    = "new,vector,vector";
00477             Opt->description  = _("Name for output vector map");
00478             break;
00479         case G_OPT_V_MAP:
00480             Opt->key          = "map";
00481             Opt->type         = TYPE_STRING;
00482             Opt->key_desc     = "name";
00483             Opt->required     = YES;
00484             Opt->gisprompt    = "old,vector,vector";
00485             Opt->description  = _("Name of input vector map");
00486             break;
00487         case G_OPT_V_TYPE:
00488             Opt->key          = "type";
00489             Opt->type         = TYPE_STRING;
00490             Opt->required     = NO;
00491             Opt->multiple     = YES;
00492             Opt->answer       = "point,line,boundary,centroid,area";
00493             Opt->options      = "point,line,boundary,centroid,area";
00494             Opt->description  = _("Type");
00495             break;
00496         case G_OPT_V_FIELD:
00497             Opt->key          = "layer";
00498             Opt->type         = TYPE_INTEGER;
00499             Opt->required     = NO;
00500             Opt->answer       = "1";
00501             Opt->description  = _("Layer number");
00502             break;
00503         case G_OPT_V_CAT:
00504             Opt->key          = "cat";
00505             Opt->type         = TYPE_INTEGER;
00506             Opt->required     = NO;
00507             Opt->description  = _("Category value");
00508             break;
00509         case G_OPT_V_CATS:
00510             Opt->key          = "cats";
00511             Opt->type         = TYPE_STRING;
00512             Opt->key_desc     = "range";
00513             Opt->required     = NO;
00514             Opt->label        = _("Category values");
00515             Opt->description  = _("Example: 1,3,7-9,13");
00516             break;
00517 
00518         /* files */
00519         case G_OPT_F_INPUT:
00520             Opt->key          = "input";
00521             Opt->type         = TYPE_STRING;
00522             Opt->key_desc     = "name";
00523             Opt->required     = YES;
00524             Opt->gisprompt    = "old_file,file,input";
00525             Opt->description  = _("Name of input file");
00526             break;
00527         case G_OPT_F_OUTPUT:
00528             Opt->key          = "output";
00529             Opt->type         = TYPE_STRING;
00530             Opt->key_desc     = "name";
00531             Opt->required     = YES;
00532             Opt->gisprompt    = "new_file,file,output";
00533             Opt->description  = _("Name for output file");
00534             break;
00535         case G_OPT_F_SEP:
00536             Opt->key          = "fs";
00537             Opt->type         = TYPE_STRING;
00538             Opt->key_desc     = "character";
00539             Opt->required     = NO;
00540             Opt->answer       = "|";
00541             Opt->description  = _("Field separator");
00542             break;
00543     }
00544 
00545     return(Opt);
00546 }
00547 
00548 struct GModule *
00549 G_define_module (void)
00550 {
00551         struct GModule *module ;
00552 
00553         /* Allocate memory */
00554 
00555         module = &module_info;
00556 
00557         /* Zero structure */
00558 
00559         G_zero ((char *) module, sizeof(struct GModule));
00560 
00561         return(module) ;
00562 }
00563 
00564 /* The main parsing routine */
00565 
00585 int G_parser (int argc, char **argv)
00586 {
00587         int need_first_opt ;
00588         int opt_checked = 0;
00589         int error ;
00590         char *ptr ;
00591         int i;
00592         struct Option *opt ;
00593         char force_gui = FALSE;
00594 
00595         error = 0 ;
00596         need_first_opt = 1 ;
00597         i = strlen(pgm_name = argv[0]) ;
00598         while (--i >= 0)
00599         {
00600                 if (pgm_name[i] == '/')
00601                 {
00602                         pgm_name += i+1;
00603                         break;
00604                 }
00605         }
00606 
00607         /* Stash default answers */
00608 
00609         opt= &first_option;
00610         while(opt != NULL)
00611         {
00612                 /* Parse options */
00613                 if(opt->options)
00614                 {
00615                     int  cnt = 0;
00616                     char **tokens, delm[2];
00617                     
00618                     delm[0] = ','; delm[1] = '\0';
00619                     tokens = G_tokenize ( opt->options, delm );
00620                     
00621                     i = 0;
00622                     while ( tokens[i] ) {
00623                         cnt++;
00624                         i++;
00625                     }
00626 
00627                     opt->opts = (char **)G_calloc( cnt+1, sizeof(char*) );
00628                     
00629                     i = 0;
00630                     while ( tokens[i] ) {
00631                         opt->opts[i] = G_store ( tokens[i] );
00632                         i++;
00633                     }
00634                     G_free_tokens ( tokens );
00635 
00636                     if(opt->descriptions ) {
00637                         delm[0] = ';';
00638 
00639                         opt->descs = (char **)G_calloc( cnt+1, sizeof(char*) );
00640                         tokens = G_tokenize ( opt->descriptions, delm );
00641                         
00642                         i = 0;
00643                         while ( tokens[i] ) {
00644                             int j, found;
00645 
00646                             if ( !tokens[i+1] ) break;
00647 
00648                             j = 0; found = 0;
00649                             while ( opt->opts[j] ) {
00650                                 if ( strcmp(opt->opts[j],tokens[i]) == 0 ) {
00651                                     found = 1;
00652                                     break;
00653                                 }
00654                                 j++;
00655                             }
00656                             if ( !found ) {
00657                                 G_warning ( "BUG in descriptions, option %s in %s does not exist",
00658                                              tokens[i], opt->key );
00659                             } else {
00660                                 opt->descs[j] = G_store ( tokens[i+1] );
00661                             }
00662 
00663                             i += 2;
00664                         }
00665                         G_free_tokens ( tokens );
00666                     }
00667                 }
00668                     
00669                 /* Copy answer */
00670                 if(opt->multiple && opt->answers && opt->answers[0])
00671                 {
00672                         opt->answer = (char *)G_malloc(strlen(opt->answers[0])+1);
00673                         strcpy(opt->answer, opt->answers[0]);
00674                         for(i=1; opt->answers[i]; i++)
00675                         {
00676                                 opt->answer = (char *)G_realloc (opt->answer,
00677                                                 strlen(opt->answer)+
00678                                                 strlen(opt->answers[i])+2);
00679                                 strcat(opt->answer, ",");
00680                                 strcat(opt->answer, opt->answers[i]);
00681                         }
00682                 }
00683                 opt->def = opt->answer ;
00684                 opt = opt->next_opt ;
00685         }
00686         
00687         /* If there are NO arguments, go interactive */
00688 
00689         if (argc < 2 && interactive_ok && isatty(0) )
00690         {
00691             if (getenv("GRASS_UI_TERM")) {
00692                 interactive(argv[0]) ;
00693                 opt_checked = 1; 
00694                 /* all options have been already checked interactively */
00695             } else {
00696                 G_gui();
00697                 return -1;
00698             }
00699         }
00700         else if (argc < 2 && isatty(0))
00701         {
00702             G_usage();
00703             return -1;
00704         }
00705         else if (argc >= 2)
00706         {
00707 
00708                 /* If first arg is "help" give a usage/syntax message */
00709                 if (strcmp(argv[1],"help") == 0 ||
00710                         strcmp(argv[1], "-help") == 0 ||
00711                         strcmp(argv[1], "--help") == 0)
00712                 {
00713                         G_usage();
00714                         exit(EXIT_SUCCESS);
00715                 }
00716 
00717                 /* If first arg is "--interface-description" then print out
00718                  * a xml description of the task */
00719                 if (strcmp(argv[1],"--interface-description") == 0)
00720                 {
00721                         G_usage_xml();
00722                         exit(EXIT_SUCCESS);
00723                 }
00724 
00725                 /* If first arg is "--html-description" then print out
00726                  * a html description of the task */
00727                 if (strcmp(argv[1],"--html-description") == 0)
00728                 {
00729                         G_usage_html();
00730                         exit(EXIT_SUCCESS);
00731                 }
00732 
00733                 /* If first arg is "--tcltk" then then generate
00734                  * code for tcltkgrass */
00735                 if (strcmp(argv[1],"--tcltk") == 0)
00736                 {
00737                         G_tcltk();
00738                         exit(EXIT_SUCCESS);
00739                 }
00740 
00741                 /* Loop thru all command line arguments */
00742 
00743                 while(--argc)
00744                 {
00745                         ptr = *(++argv) ;
00746 
00747                         /* Overwrite option */
00748                         if ( strcmp(ptr,"--o") == 0 || strcmp(ptr,"--overwrite") == 0 )
00749                         {
00750                             overwrite = 1;
00751                         }
00752 
00753                         /* Verbose option for forward compatibility with GRASS 6.3+ */
00754                         else if ( strcmp(ptr,"--v") == 0 || strcmp(ptr,"--verbose") == 0 )
00755                             G_debug(1, "Verbose mode requested but not used in GRASS 6.2");
00756 
00757                         /* Quiet option for forward compatibility with GRASS 6.3+ */
00758                         else if ( strcmp(ptr,"--q") == 0 || strcmp(ptr,"--quiet") == 0 )
00759                             G_debug(1, "Quiet mode requested but not used in GRASS 6.2");
00760 
00761                         /* Force gui to come up */
00762                         else if ( strcmp(ptr,"--ui") == 0 )
00763                         {
00764                             force_gui = TRUE;
00765                         }
00766 
00767                         /* If we see a flag */
00768                         else if(*ptr == '-')
00769                         {
00770                                 while(*(++ptr))
00771                                         error += set_flag(*ptr) ;
00772 
00773                         }
00774                         /* If we see standard option format (option=val) */
00775                         else if (contains(ptr, '='))
00776                         {
00777                                 error += set_option(ptr) ;
00778                                 need_first_opt = 0 ;
00779                         }
00780 
00781                         /* If we see the first option with no equal sign */
00782                         else if (need_first_opt && n_opts)
00783                         {
00784                                 first_option.answer = G_store(ptr) ;
00785                                 need_first_opt = 0 ;
00786                         }
00787 
00788                         /* If we see the non valid argument (no "=", just argument) */
00789                         else if (contains(ptr, '=') == 0)
00790                         {
00791                                 fprintf(stderr, _("Sorry <%s> is not a valid option\n"), ptr);
00792                                 error = 1;
00793                         }
00794 
00795                 }
00796         }
00797 
00798         /* Run the gui if it was specifically requested */
00799         if (force_gui) {
00800                 G_gui();
00801                 return -1;
00802         }
00803 
00804         /* Split options where multiple answers are OK */
00805         split_opts() ;
00806 
00807         /* Check multiple options */
00808         error += check_multiple_opts() ;
00809 
00810         /* Check answers against options and check subroutines */
00811         if(!opt_checked)
00812            error += check_opts() ;
00813 
00814         /* Make sure all required options are set */
00815         error += check_required() ;
00816 
00817 
00818         if(error)
00819         {
00820                 G_usage();
00821                 return -1;
00822         }
00823 
00824         if ( check_overwrite () )
00825             return -1;
00826 
00827         return(0) ;
00828 }
00829 
00830 
00831 static int uses_new_gisprompt (void)
00832 {
00833         struct Option *opt ;
00834         char age[KEYLENGTH] ;
00835         char element[KEYLENGTH] ;
00836         char desc[KEYLENGTH] ;
00837 
00838         /* figure out if any of the options use a "new" gisprompt */
00839         /* This is to see if we should spit out the --o flag      */
00840         if(n_opts)
00841         {
00842                 opt= &first_option;
00843                 while(opt != NULL)
00844                 {
00845                         if ( opt->gisprompt )
00846                         {
00847                                 split_gisprompt (opt->gisprompt, age, element, desc) ;
00848                                 if (strcmp (age, "new") == 0)
00849                                         return 1;
00850                         }
00851                         opt=opt->next_opt;
00852                 }
00853         }
00854 
00855         return 0;
00856 }
00857 
00878 int G_usage (void)
00879 {
00880         struct Option *opt ;
00881         struct Flag *flag ;
00882         char item[256];
00883         char *key_desc;
00884         int maxlen;
00885         int len, n;
00886         int new_prompt = 0;
00887 
00888         new_prompt = uses_new_gisprompt();
00889         
00890         if (!pgm_name)          /* v.dave && r.michael */
00891             pgm_name = G_program_name ();
00892         if (!pgm_name)
00893             pgm_name = "??";
00894 
00895         if (module_info.description) {
00896                 fprintf (stderr, _("\nDescription:\n"));
00897                 fprintf (stderr, " %s\n", module_info.description);
00898         }
00899         if (module_info.keywords) {
00900                 fprintf (stderr, _("\nKeywords:\n"));
00901                 fprintf (stderr, " %s\n", module_info.keywords);
00902         }
00903 
00904         fprintf (stderr, _("\nUsage:\n "));
00905 
00906         len = show(pgm_name,1);
00907 
00908         /* Print flags */
00909 
00910         if(n_flags)
00911         {
00912                 item[0] = ' ';
00913                 item[1] = '[';
00914                 item[2] = '-';
00915                 flag= &first_flag;
00916                 for(n = 3; flag != NULL; n++, flag = flag->next_flag)
00917                         item[n] = flag->key;
00918                 item[n++] = ']';
00919                 item[n] = 0;
00920                 len=show(item,len);
00921         }
00922 
00923         maxlen = 0;
00924         if(n_opts)
00925         {
00926                 opt= &first_option;
00927                 while(opt != NULL)
00928                 {
00929                         if (opt->key_desc != NULL)
00930                                 key_desc = opt->key_desc;
00931                         else if (opt->type == TYPE_STRING)
00932                                 key_desc = "string";
00933                         else
00934                                 key_desc = "value";
00935 
00936                         n = strlen (opt->key);
00937                         if (n > maxlen) maxlen = n;
00938 
00939                         strcpy(item," ");
00940                         if(!opt->required )
00941                                 strcat (item, "[");
00942                         strcat (item, opt->key);
00943                         strcat (item, "=");
00944                         strcat (item, key_desc);
00945                         if (opt->multiple)
00946                         {
00947                                 strcat(item,"[,");
00948                                 strcat(item,key_desc);
00949                                 strcat(item,",...]");
00950                         }
00951                         if(!opt->required )
00952                                 strcat(item,"]") ;
00953 
00954                         len = show(item,len);
00955 
00956                         opt = opt->next_opt ;
00957                 }
00958         }
00959         if (new_prompt)
00960         {
00961                 strcpy (item, " [--overwrite]");
00962                 len=show(item,len);
00963         }
00964 
00965         fprintf (stderr, "\n");
00966 
00967         /* Print help info for flags */
00968 
00969         if(n_flags || new_prompt)       
00970                 fprintf (stderr, _("\nFlags:\n"));
00971 
00972         if(n_flags)
00973         {
00974                 flag= &first_flag;
00975                 while(flag != NULL)
00976                 {
00977                         fprintf(stderr,"  -%c   ", flag->key) ;
00978 
00979                         if ( flag->label ) {
00980                             fprintf (stderr, "%s\n", flag->label );
00981                             if ( flag->description )
00982                                 fprintf (stderr, "      %s\n", flag->description);
00983 
00984                         } else if ( flag->description ) {
00985                             fprintf (stderr, "%s\n", flag->description);
00986                         }
00987 
00988                         flag = flag->next_flag ;
00989                 }
00990         }
00991 
00992         if (new_prompt)
00993                 fprintf(stderr," --o   %s\n", _("Force overwrite of output files")) ;
00994                 
00995 
00996         /* Print help info for options */
00997 
00998         if(n_opts)
00999         {
01000                 fprintf (stderr, _("\nParameters:\n"));
01001                 opt= &first_option;
01002                 while(opt != NULL)
01003                 {
01004                         fprintf (stderr, "  %*s   ", maxlen, opt->key );
01005 
01006                         if ( opt->label ) {
01007                             fprintf (stderr, "%s\n", opt->label );
01008                             if ( opt->description )
01009                                 fprintf (stderr, "           %*s\n", maxlen, opt->description);
01010 
01011                         } else if ( opt->description ) {
01012                             fprintf (stderr, "%s\n", opt->description);
01013                         }
01014 
01015                         if(opt->options)
01016                                 show_options(maxlen, opt->options) ;
01017                                 /*
01018                                 fprintf (stderr, "  %*s   options: %s\n", maxlen, " ",
01019                                         _(opt->options)) ;
01020                                 */
01021                         if(opt->def)
01022                                 fprintf (stderr, _("  %*s   default: %s\n"), maxlen, " ",
01023                                         opt->def) ;
01024                         
01025                         if(opt->descs) {
01026                             int i = 0;
01027 
01028                             while ( opt->opts[i] ) {
01029                                 fprintf (stderr, "  %*s   %s: ", maxlen, " ", opt->opts[i] );
01030 
01031                                 if (  opt->descs[i] )
01032                                     fprintf (stderr, "%s\n", opt->descs[i] );
01033                                 
01034                                 i++;
01035                             }
01036                         }
01037 
01038                         opt = opt->next_opt ;
01039                 }
01040         }
01041 
01042         return 0;
01043 }
01044 
01045 void print_escaped_for_xml (FILE * fp, char * str) {
01046         for (;*str;str++) {
01047                 switch (*str) {
01048                         case '&':
01049                                 fputs("&amp;", fp);
01050                                 break;
01051                         case '<':
01052                                 fputs("&lt;", fp);
01053                                 break;
01054                         case '>':
01055                                 fputs("&gt;", fp);
01056                                 break;
01057                         default:
01058                                 fputc(*str, fp);
01059                 }
01060         }
01061 }
01062 
01063 static void G_usage_xml (void)
01064 {
01065         struct Option *opt ;
01066         struct Flag *flag ;
01067         char *type;
01068         char *s, *top;
01069         int i;
01070         char *encoding;
01071 
01072 /* gettext converts strings to encoding returned by nl_langinfo(CODESET) */
01073 
01074 #if defined(HAVE_LANGINFO_H)
01075         encoding = nl_langinfo (CODESET);
01076         if ( !encoding || strlen( encoding ) == 0 ) {
01077             encoding = "UTF-8";
01078         }
01079 #else
01080         encoding = "UTF-8";
01081 #endif
01082         
01083         if (!pgm_name)          /* v.dave && r.michael */
01084             pgm_name = G_program_name ();
01085         if (!pgm_name)
01086             pgm_name = "??";
01087 
01088         fprintf(stdout, "<?xml version=\"1.0\" encoding=\"%s\"?>\n", encoding);
01089         fprintf(stdout, "<!DOCTYPE task SYSTEM \"grass-interface.dtd\">\n");
01090 
01091         fprintf(stdout, "<task name=\"%s\">\n", pgm_name);  
01092 
01093         if (module_info.label) {
01094                 fprintf(stdout, "\t<label>\n\t\t");
01095                 print_escaped_for_xml (stdout, module_info.label);
01096                 fprintf(stdout, "\n\t</label>\n");
01097         }
01098 
01099         if (module_info.description) {
01100                 fprintf(stdout, "\t<description>\n\t\t");
01101                 print_escaped_for_xml (stdout, module_info.description);
01102                 fprintf(stdout, "\n\t</description>\n");
01103         }
01104 
01105         if (module_info.keywords) {
01106                 fprintf(stdout, "\t<keywords>\n\t\t");
01107                 print_escaped_for_xml (stdout, module_info.keywords);
01108                 fprintf(stdout, "\n\t</keywords>\n");
01109         }
01110 
01111         /***** Don't use parameter-groups for now.  We'll reimplement this later 
01112          ***** when we have a concept of several mutually exclusive option
01113          ***** groups
01114         if (n_opts || n_flags)
01115                 fprintf(stdout, "\t<parameter-group>\n");
01116          *****
01117          *****
01118          *****/
01119         
01120         if(n_opts)
01121         {
01122                 opt= &first_option;
01123                 while(opt != NULL)
01124                 {
01125                         /* TODO: make this a enumeration type? */
01126                         switch (opt->type) {
01127                                 case TYPE_INTEGER:
01128                                         type = "integer";
01129                                         break ;
01130                                 case TYPE_DOUBLE:
01131                                         type = "float";
01132                                         break ;
01133                                 case TYPE_STRING:
01134                                         type = "string";
01135                                         break ;
01136                                 default:
01137                                         type = "string";
01138                                         break;
01139                         }
01140                         fprintf (stdout, "\t<parameter "
01141                                 "name=\"%s\" "
01142                                 "type=\"%s\" "
01143                                 "required=\"%s\" "
01144                                 "multiple=\"%s\">\n",
01145                                 opt->key,
01146                                 type,
01147                                 opt->required == YES ? "yes" : "no",
01148                                 opt->multiple == YES ? "yes" : "no");
01149 
01150                         if (opt->label) {
01151                                 fprintf(stdout, "\t\t<label>\n\t\t\t");
01152                                 print_escaped_for_xml(stdout, opt->label);
01153                                 fprintf(stdout, "\n\t\t</label>\n");
01154                         }
01155 
01156                         if (opt->description) {
01157                                 fprintf(stdout, "\t\t<description>\n\t\t\t");
01158                                 print_escaped_for_xml(stdout, opt->description);
01159                                 fprintf(stdout, "\n\t\t</description>\n");
01160                         }
01161 
01162                         if (opt->key_desc)
01163                         {
01164                                 fprintf (stdout, "\t\t<keydesc>\n");
01165                                 top = G_calloc (strlen (opt->key_desc) + 1, 1);
01166                                 strcpy (top, opt->key_desc);
01167                                 s = strtok (top, ",");
01168                                 for (i = 1; s != NULL; i++)
01169                                 {
01170                                         fprintf (stdout, "\t\t\t<item order=\"%d\">", i);
01171                                         print_escaped_for_xml (stdout, s);
01172                                         fprintf (stdout, "</item>\n");
01173                                         s = strtok (NULL, ",");
01174                                 }
01175                                 fprintf (stdout, "\t\t</keydesc>\n");
01176                                 G_free (top);
01177                         }
01178                         
01179                         if (opt->gisprompt)
01180                         {
01181                                 const char *atts[] = {"age", "element", "prompt", NULL};
01182                                 top = G_calloc (strlen (opt->gisprompt) + 1, 1);
01183                                 strcpy (top, opt->gisprompt);
01184                                 s = strtok (top, ",");
01185                                 fprintf (stdout, "\t\t<gisprompt ");
01186                                 for (i = 0; s != NULL && atts[i] != NULL; i++)
01187                                 {
01188                                         fprintf (stdout, "%s=\"%s\" ", atts[i], s);
01189                                         s = strtok (NULL, ",");
01190                                 }
01191                                 fprintf (stdout, "/>\n");
01192                                 G_free (top);
01193                         }
01194 
01195                         if(opt->def) {
01196                                 fprintf(stdout, "\t\t\t<default>\n\t\t\t");
01197                                 print_escaped_for_xml(stdout, opt->def);
01198                                 fprintf(stdout, "\n\t\t\t</default>\n");
01199                         }
01200 
01201                         if(opt->options) {
01202                                 i = 0;
01203                                 fprintf(stdout, "\t\t<values>\n");
01204                                 while ( opt->opts[i] ) {
01205                                         fprintf(stdout, "\t\t\t<value>\n");
01206                                         fprintf(stdout, "\t\t\t\t<name>");
01207                                         print_escaped_for_xml(stdout, opt->opts[i]);
01208                                         fprintf(stdout, "</name>\n");
01209                                         if(opt->descs && opt->opts[i]) {
01210                                             fprintf(stdout, "\t\t\t\t<description>");
01211                                             print_escaped_for_xml(stdout, opt->descs[i]);
01212                                             fprintf(stdout, "</description>");
01213                                         }
01214                                         fprintf(stdout, "\t\t\t</value>\n");
01215                                         i++;
01216                                 }
01217                                 fprintf(stdout, "\t\t</values>\n");
01218                         }
01219 
01220                         /* TODO:
01221                          * add something like
01222                          *       <range min="xxx" max="xxx"/>
01223                          * to <values>
01224                          * - key_desc?
01225                          * - there surely are some more. which ones?
01226                          */
01227 
01228                         opt = opt->next_opt ;
01229                         fprintf (stdout, "\t</parameter>\n");
01230                 }
01231         }
01232 
01233         
01234         if(n_flags)
01235         {
01236                 flag= &first_flag;
01237                 while(flag != NULL)
01238                 {
01239                         fprintf (stdout, "\t<flag name=\"%c\">\n", flag->key);
01240 
01241                         if (flag->label) {
01242                                 fprintf(stdout, "\t\t<label>\n\t\t\t");
01243                                 print_escaped_for_xml(stdout, flag->label);
01244                                 fprintf(stdout, "\n\t\t</label>\n");
01245                         }
01246 
01247                         if (flag->description) {
01248                                 fprintf(stdout, "\t\t<description>\n\t\t\t");
01249                                 print_escaped_for_xml(stdout, flag->description);
01250                                 fprintf(stdout, "\n\t\t</description>\n");
01251                         }
01252                         flag = flag->next_flag ;
01253                         fprintf (stdout, "\t</flag>\n");
01254                 }
01255         }
01256 
01257         /***** Don't use parameter-groups for now.  We'll reimplement this later 
01258          ***** when we have a concept of several mutually exclusive option
01259          ***** groups
01260         if (n_opts || n_flags)
01261                 fprintf(stdout, "\t</parameter-group>\n");
01262          *****
01263          *****
01264          *****/
01265 
01266         fprintf(stdout, "</task>\n");
01267 }
01268 
01269 static void G_usage_html (void)
01270 {
01271         struct Option *opt ;
01272         struct Flag *flag ;
01273         char *type;
01274         char *newbuf;
01275         int new_prompt = 0;
01276 
01277         new_prompt = uses_new_gisprompt();
01278         
01279         if (!pgm_name)          /* v.dave && r.michael */
01280             pgm_name = G_program_name ();
01281         if (!pgm_name)
01282             pgm_name = "??";
01283 
01284         fprintf(stdout, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n");
01285         fprintf(stdout, "<html>\n<head>\n");
01286         fprintf(stdout, "<title>%s</title>\n", pgm_name);
01287         fprintf(stdout, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n");
01288         fprintf(stdout, "<link rel=\"stylesheet\" href=\"grassdocs.css\" type=\"text/css\">\n");
01289         fprintf(stdout, "</head>\n");
01290         fprintf(stdout, "<body bgcolor=\"white\">\n\n");
01291         fprintf(stdout, "<img src=\"grass.smlogo.gif\" alt=\"GRASS logo\"><hr align=center size=6 noshade>\n\n");
01292         fprintf(stdout, "<h2>NAME</h2>\n");
01293         fprintf(stdout, "<em><b>%s</b></em> ", pgm_name);
01294 
01295         if (module_info.description) {
01296                 fprintf(stdout, " - ");
01297                 fprintf(stdout, "%s", module_info.description);
01298                 fprintf(stdout, "\n");
01299         }
01300 
01301         fprintf(stdout, "<h2>KEYWORDS</h2>\n");
01302         if (module_info.keywords) {
01303                 fprintf(stdout, "%s", module_info.keywords);
01304                 fprintf(stdout, "\n");
01305         }
01306         fprintf(stdout, "<h2>SYNOPSIS</h2>\n");
01307         fprintf(stdout, "<b>%s</b><br>\n", pgm_name);
01308         fprintf(stdout, "<b>%s help</b><br>\n", pgm_name);
01309 
01310         fprintf(stdout, "<b>%s</b>", pgm_name);
01311 
01312 
01313 
01314         /* print short version first */
01315         if(n_flags)
01316         {
01317                 flag= &first_flag;
01318                 fprintf(stdout, " [-<b>");
01319                 while(flag != NULL)
01320                 {
01321                         fprintf (stdout, "%c", flag->key);
01322                         flag = flag->next_flag ;
01323                 }
01324                 fprintf(stdout, "</b>] ");
01325         }
01326         else
01327           fprintf(stdout, " ");
01328 
01329         if(n_opts)
01330         {
01331                 opt= &first_option;
01332 
01333                 while(opt != NULL)
01334                 {
01335                         if (opt->key_desc != NULL)
01336                             type = opt->key_desc;
01337                         else switch (opt->type) {
01338                                 case TYPE_INTEGER:
01339                                         type = "integer";
01340                                         break ;
01341                                 case TYPE_DOUBLE:
01342                                         type = "float";
01343                                         break ;
01344                                 case TYPE_STRING:
01345                                         type = "string";
01346                                         break ;
01347                                 default:
01348                                         type = "string";
01349                                         break;
01350                         }
01351                         if( !opt->required )
01352                              fprintf(stdout," [");
01353                         fprintf(stdout,
01354                                 "<b>%s</b>=<em>%s</em>", opt->key, type);
01355                         if (opt->multiple)
01356                         {
01357                                 fprintf(stdout,"[,<i>%s</i>,...]", type);
01358                         }
01359                         if( !opt->required )
01360                              fprintf(stdout,"] ");
01361 
01362                         opt = opt->next_opt ;
01363                         fprintf(stdout," ");
01364                 }
01365         }
01366         if (new_prompt)
01367         {
01368                 fprintf(stdout, " [--<b>overwrite</b>] ");
01369         }
01370         fprintf(stdout, "\n");
01371 
01372 
01373         /* now long version */
01374         fprintf(stdout, "\n");
01375         if(n_flags || new_prompt)
01376         {
01377                 flag= &first_flag;
01378                 fprintf(stdout, "<h3>Flags:</h3>\n");
01379                 fprintf(stdout, "<DL>\n");
01380                 while(n_flags && flag != NULL )
01381                 {
01382                         fprintf (stdout, "<DT><b>-%c</b></DT>\n", flag->key);
01383 
01384                         if ( flag->label ) {
01385                                 fprintf(stdout, "<DD>");
01386                                 fprintf(stdout, "%s", flag->label);
01387                                 fprintf(stdout, "</DD>\n");
01388                         }
01389 
01390                         if (flag->description) {
01391                                 fprintf(stdout, "<DD>");
01392                                 fprintf(stdout, "%s", flag->description);
01393                                 fprintf(stdout, "</DD>\n");
01394                         }
01395 
01396                         flag = flag->next_flag ;
01397                         fprintf (stdout, "\n");
01398                 }
01399                 if (new_prompt)
01400                 {
01401                         fprintf(stdout, "<DT><b>--overwrite</b></DT>\n");
01402                         fprintf(stdout, "<DD>Force overwrite of output files</DD>");
01403                 }
01404                 fprintf(stdout, "</DL>\n");
01405         }
01406 
01407         fprintf(stdout, "\n");
01408         if(n_opts)
01409         {
01410                 opt= &first_option;
01411                 fprintf(stdout, "<h3>Parameters:</h3>\n");
01412                 fprintf(stdout, "<DL>\n");
01413                 
01414                 while(opt != NULL)
01415                 {
01416                         /* TODO: make this a enumeration type? */
01417                         if (opt->key_desc != NULL)
01418                             type = opt->key_desc;
01419                         else switch (opt->type) {
01420                                 case TYPE_INTEGER:
01421                                         type = "integer";
01422                                         break ;
01423                                 case TYPE_DOUBLE:
01424                                         type = "float";
01425                                         break ;
01426                                 case TYPE_STRING:
01427                                         type = "string";
01428                                         break ;
01429                                 default:
01430                                         type = "string";
01431                                         break;
01432                         }
01433                         fprintf(stdout,
01434                                 "<DT><b>%s</b>=<em>%s", opt->key, type);
01435                         if (opt->multiple) {
01436                                 fprintf(stdout,"[,<i>%s</i>,...]", type);
01437                         }
01438                         fprintf(stdout,"</em></DT>\n");
01439 
01440                         if ( opt->label ) {
01441                                 fprintf(stdout, "<DD>");
01442                                 fprintf(stdout, "%s", opt->label);
01443                                 fprintf(stdout, "</DD>\n");
01444                         }
01445                         if (opt->description) {
01446                                 fprintf(stdout, "<DD>");
01447                                 newbuf = G_str_replace(opt->description, "\n","<br>");
01448                                 if (newbuf) {
01449                                         fprintf(stdout, "%s", newbuf);
01450                                         G_free(newbuf);
01451                                 } else
01452                                         fprintf(stdout, "%s", opt->description);
01453                                 fprintf(stdout, "</DD>\n");
01454                                 
01455                         }
01456 
01457                         if(opt->options) {
01458                                 fprintf(stdout, "<DD>Options: <em>");
01459                                 fprintf(stdout, "%s", opt->options);
01460                                 fprintf(stdout, "</em></DD>\n");
01461                         }
01462 
01463                         if(opt->def) {
01464                                 fprintf(stdout, "<DD>Default: <em>");
01465                                 fprintf(stdout, "%s", opt->def);
01466                                 fprintf(stdout, "</em></DD>\n");
01467                         }
01468 
01469                         if(opt->descs) {
01470                             int i = 0;
01471 
01472                             while ( opt->opts[i] ) {
01473                                 fprintf(stdout, "<DD><b>%s</b>: ", opt->opts[i]);
01474 
01475                                 if (  opt->descs[i] )
01476                                     fprintf (stdout, "%s", opt->descs[i] );
01477                                 
01478                                 fprintf(stdout, "</DD>\n");
01479                                 
01480                                 i++;
01481                             }
01482                         }
01483 
01484                         opt = opt->next_opt ;
01485                         fprintf (stdout, "\n");
01486                 }
01487                 fprintf(stdout, "</DL>\n");
01488         }
01489         
01490     fprintf(stdout, "</body>\n</html>\n");
01491 }
01492 
01493 static void generate_tcl(FILE *fp)
01494 {
01495         int new_prompt = uses_new_gisprompt();
01496         char *type;
01497         int optn;
01498 
01499         fprintf(fp, "begin_dialog {%s} {\n", pgm_name);
01500         fprintf(fp, " label {%s}\n", module_info.label ? module_info.label : "");
01501         fprintf(fp, " desc {%s}\n", module_info.description ? module_info.description : "");
01502         fprintf(fp, " key {%s}\n", module_info.keywords ? module_info.keywords : "");
01503         fprintf(fp, "}\n");
01504 
01505         optn = 1;
01506     
01507         if (n_flags)
01508         {
01509                 struct Flag *flag;
01510 
01511                 for (flag = &first_flag; flag; flag = flag->next_flag, optn++) {
01512                         fprintf(fp, "add_flag %d {\n", optn);
01513                         fprintf(fp, " name {%c}\n", flag->key);
01514                         fprintf(fp, " desc {%s}\n", flag->description);
01515                         fprintf(fp, " answer %d\n", flag->answer);
01516                         /* It should be up to the gui as to what
01517                            to do with the label and description */
01518                         fprintf(fp, " label {%s}\n", flag->label ? flag->label : "");
01519                         fprintf(fp, " guisection {%s}\n", flag->guisection ? flag->guisection : "");
01520                         fprintf(fp, "}\n");
01521                 }
01522         }
01523 
01524         if (n_opts)
01525         {
01526                 struct Option *opt;
01527 
01528                 for (opt = &first_option; opt; opt = opt->next_opt, optn++)
01529                 {
01530                         if (opt->key_desc != NULL)
01531                             type = opt->key_desc;
01532                         else switch (opt->type)
01533                         {
01534                         case TYPE_INTEGER:
01535                                 type = "integer";
01536                                 break;
01537                         case TYPE_DOUBLE:
01538                                 type = "float";
01539                                 break;
01540                         case TYPE_STRING:
01541                                 type = "string";
01542                                 break;
01543                         default:
01544                                 type = "string";
01545                                 break;
01546                         }
01547 
01548                         fprintf(fp, "add_option %d {\n", optn);
01549                         fprintf(fp, " name {%s}\n", opt->key);
01550                         fprintf(fp, " type {%s}\n", type);
01551                         fprintf(fp, " multi %d\n", opt->multiple);
01552                         fprintf(fp, " desc {%s}\n", opt->description);
01553                         fprintf(fp, " required %d\n", opt->required);
01554                         fprintf(fp, " options {%s}\n", opt->options ? opt->options : "");
01555                         fprintf(fp, " answer {%s}\n", opt->answer ? opt->answer : "");
01556                         fprintf(fp, " prompt {%s}\n", opt->gisprompt ? opt->gisprompt : "");
01557                         /* It should be up to the gui as to what
01558                            to do with the label and description */
01559                         fprintf(fp, " label {%s}\n", opt->label ? opt->label : "");
01560                         fprintf(fp, " guisection {%s}\n", opt->guisection ? opt->guisection : "");
01561                         fprintf(fp, "}\n");
01562                 }
01563         }
01564    
01565         if (new_prompt)
01566         {
01567                 fprintf(fp, "add_xflag %d {\n", optn);
01568                 fprintf(fp, " name {overwrite}\n");
01569                 fprintf(fp, " desc {Force overwrite of output files}\n");
01570                 fprintf(fp, " answer %d\n", overwrite);
01571                 fprintf(fp, " label {Overwrite}\n");
01572                 fprintf(fp, " guisection {}\n");
01573                 fprintf(fp, "}\n");
01574                 optn++;
01575         }
01576 
01577         fprintf(fp, "end_dialog %d\n", optn - 1);
01578 }
01579 
01580 /* Build gui */
01581 static void G_gui (void)
01582 {
01583         FILE *fp;
01584 
01585         if (!pgm_name)
01586                 pgm_name = G_program_name ();
01587         if (!pgm_name)
01588                 pgm_name = "??";
01589 
01590         if (getenv("GRASS_DEBUG_GUI"))
01591                 fp = popen("tee gui_dump.tcl | $GRASS_WISH", "w");
01592         else
01593                 fp = popen("$GRASS_WISH", "w");
01594 
01595         if (!fp)
01596                 G_fatal_error("unable to spawn wish");
01597 
01598         fprintf(fp, "source $env(GISBASE)/etc/gui.tcl\n");
01599 
01600         generate_tcl(fp);
01601 
01602         pclose(fp);
01603 }
01604 
01605 /* Send Tcl/Tk code to tcltkgrass */
01606 static void G_tcltk (void)
01607 {
01608         if (!pgm_name)
01609                 pgm_name = G_program_name ();
01610         if (!pgm_name)
01611                 pgm_name = "??";
01612 
01613         generate_tcl(stdout);
01614 }
01615 
01616 /**************************************************************************
01617  *
01618  * The remaining routines are all local (static) routines used to support
01619  * the parsing process.
01620  *
01621  **************************************************************************/
01622 
01623 static int show_options(int maxlen,char *str)
01624 {
01625         char buff[1024] ;
01626         char *p1, *p2 ;
01627         int totlen, len ;
01628 
01629         strcpy(buff, str) ;
01630         fprintf (stderr, _("  %*s   options: "), maxlen, " ") ;
01631         totlen = maxlen + 13 ;
01632         p1 = buff ;
01633         while( (p2 = G_index(p1, ',')) )
01634         {
01635                 *p2 = '\0' ;
01636                 len = strlen(p1) + 1 ;
01637                 if ((len + totlen) > 76)
01638                 {
01639                         totlen = maxlen + 13 ;
01640                         fprintf(stderr, "\n %*s", maxlen + 13, " ") ;
01641                 }
01642                 fprintf (stderr, "%s,",  p1) ;
01643                 totlen += len ;
01644                 p1 = p2 + 1 ;
01645         }
01646         len = strlen(p1) ;
01647         if ((len + totlen) > 76 )
01648                 fprintf(stderr, "\n %*s", maxlen + 13, " ") ;
01649         fprintf (stderr, "%s\n",  p1) ;
01650 
01651         return 0;
01652 }
01653 
01654 static int show (const char *item, int len)
01655 {
01656         int n;
01657 
01658         n = strlen (item)+(len>0);
01659         if (n + len > 76)
01660         {
01661                 if (len)
01662                         fprintf (stderr, "\n  ");
01663                 len = 0;
01664         }
01665         fprintf (stderr, "%s", item);
01666         return n+len;
01667 }
01668 
01669 static int set_flag (int f)
01670 {
01671         struct Flag *flag ;
01672 
01673         /* Flag is not valid if there are no flags to set */
01674 
01675         if(!n_flags)
01676         {
01677                 fprintf(stderr,_("Sorry, <%c> is not a valid flag\n"), f) ;
01678                 return(1) ;
01679         }
01680 
01681         /* Find flag with corrrect keyword */
01682 
01683         flag= &first_flag;
01684         while(flag != NULL)
01685         {
01686                 if( flag->key == f)
01687                 {
01688                         flag->answer = 1 ;
01689                         return(0) ;
01690                 }
01691                 flag = flag->next_flag ;
01692         }
01693 
01694         fprintf(stderr,_("Sorry, <%c> is not a valid flag\n"), f) ;
01695         return(1) ;
01696 }
01697 
01698 /* contents() is used to find things strings with characters like commas and
01699  * dashes.
01700  */
01701 static int contains (char *s, int c)
01702 {
01703         while(*s)
01704         {
01705                 if(*s == c)
01706                         return(1) ;
01707                 s++ ;
01708         }
01709         return(0) ;
01710 }
01711 
01712 static int set_option (char *string)
01713 {
01714         struct Option *at_opt = NULL;
01715         struct Option *opt = NULL;
01716         int got_one ;
01717         size_t key_len ;
01718         char the_key[KEYLENGTH] ;
01719         char *ptr ;
01720 
01721         for(ptr=the_key; *string!='='; ptr++, string++)
01722                 *ptr = *string ;
01723         *ptr = '\0' ;
01724         string++ ;
01725 
01726         /* Find option with best keyword match */
01727         got_one = 0 ;
01728         key_len = strlen(the_key) ;
01729         for(at_opt= &first_option; at_opt != NULL; at_opt=at_opt->next_opt)
01730         {
01731                 if (strncmp(the_key,at_opt->key,key_len))
01732                         continue ;
01733 
01734                 got_one++;
01735                 opt = at_opt ;
01736 
01737                 /* changed 1/15/91 -dpg   old code is in parser.old */
01738                 /* overide ambiguous check, if we get an exact match */
01739                 if (strlen (at_opt->key) == key_len)    
01740                 {
01741                     opt = at_opt;
01742                     got_one = 1;
01743                     break;
01744                 }
01745         }
01746 
01747         if (got_one > 1)
01748         {
01749                 fprintf(stderr,_("Sorry, <%s=> is ambiguous\n"), the_key) ;
01750                 return(1) ;
01751         }
01752 
01753         /* If there is no match, complain */
01754         if(got_one == 0)
01755         {
01756                 fprintf(stderr,_("Sorry, <%s> is not a valid parameter\n"),
01757                         the_key) ;
01758                 return(1) ;
01759         }
01760                 
01761         /* Allocate memory where answer is stored */
01762         if (opt->count++)
01763         {
01764                 opt->answer = (char *)G_realloc (opt->answer,
01765                         strlen (opt->answer)+strlen(string)+2);
01766                 strcat (opt->answer, ",");
01767                 strcat (opt->answer, string);
01768         }
01769         else
01770                 opt->answer = G_store(string) ;
01771         return(0) ;
01772 }
01773 
01774 static int check_opts (void)
01775 {
01776         struct Option *opt ;
01777         int error ;
01778         int ans ;
01779 
01780         error = 0 ;
01781 
01782         if(! n_opts)
01783                 return(0) ;
01784 
01785         opt= &first_option;
01786         while(opt != NULL)
01787         {
01788                 /* Check answer against options if any */
01789 
01790                 if(opt->options && opt->answer)
01791                 {
01792                         if(opt->multiple == 0)
01793                                 error += check_an_opt(opt->key, opt->type,
01794                                     opt->options, opt->answer) ;
01795                         else
01796                         {
01797                                 for(ans=0; opt->answers[ans] != '\0'; ans++)
01798                                         error += check_an_opt(opt->key, opt->type,
01799                                             opt->options, opt->answers[ans]) ;
01800                         }
01801                 }
01802 
01803                 /* Check answer against user's check subroutine if any */
01804 
01805                 if(opt->checker)
01806                         error += opt->checker(opt->answer) ;
01807 
01808                 opt = opt->next_opt ;
01809         }
01810         return(error) ;
01811 }
01812 
01813 static int check_an_opt (char *key, int type, char *options, char *answer)
01814 {
01815         int error ;
01816 
01817         error = 0 ;
01818 
01819         switch(type)
01820         {
01821         case TYPE_INTEGER:
01822                 error = check_int(answer,options) ;
01823                 break ;
01824         case TYPE_DOUBLE:
01825                 error = check_double(answer,options) ;
01826                 break ;
01827         case TYPE_STRING:
01828                 error = check_string(answer,options) ;
01829                 break ;
01830 /*
01831         case TYPE_COORDINATE:
01832                 error = check_coor(answer,options) ;
01833                 break ;
01834 */
01835         }
01836         switch(error)
01837         {
01838         case 0:
01839                 break ;
01840         case BAD_SYNTAX:
01841                 fprintf(stderr,_("\nError: illegal range syntax for parameter <%s>\n"),
01842                     key) ;
01843                 fprintf(stderr,_("       Presented as: %s\n"), options) ;
01844                 break ;
01845         case OUT_OF_RANGE:
01846                 fprintf(stderr,_("\nError: value <%s> out of range for parameter <%s>\n"),
01847                     answer, key) ;
01848                 fprintf(stderr,_("       Legal range: %s\n"), options) ;
01849                 break ;
01850         case MISSING_VALUE:
01851                 fprintf(stderr,_("\nError: Missing value for parameter <%s>\n"),
01852                     key) ;
01853         }
01854         return(error) ;
01855 }
01856 
01857 static int check_int (char *ans, char *opts)
01858 {
01859         int d, lo, hi;
01860 
01861         if (1 != sscanf(ans,"%d", &d))
01862                 return(MISSING_VALUE) ;
01863 
01864         if (contains(opts, '-'))
01865         {
01866                 if (2 != sscanf(opts,"%d-%d",&lo, &hi))
01867                         return(BAD_SYNTAX) ;
01868                 if (d < lo || d > hi)
01869                         return(OUT_OF_RANGE) ;
01870                 else
01871                         return(0) ;
01872         }
01873         else if (contains(opts, ','))
01874         {
01875                 for(;;)
01876                 {
01877                         if (1 != sscanf(opts,"%d",&lo))
01878                                 return(BAD_SYNTAX) ;
01879                         if (d == lo)
01880                                 return(0) ;
01881                         while(*opts != '\0' && *opts != ',')
01882                                 opts++ ;
01883                         if (*opts == '\0')
01884                                 return(OUT_OF_RANGE) ;
01885                         if (*(++opts) == '\0')
01886                                 return(OUT_OF_RANGE) ;
01887                 }
01888         }
01889         else
01890         {
01891                 if (1 != sscanf(opts,"%d",&lo))
01892                         return(BAD_SYNTAX) ;
01893                 if (d == lo)
01894                         return(0) ;
01895                 return(OUT_OF_RANGE) ;
01896         }
01897 }
01898 
01899 /*
01900 static int
01901 check_coor(ans, opts)
01902 char *ans ;
01903 char *opts ;
01904 {
01905         double xd, xlo, xhi;
01906         double yd, ylo, yhi;
01907 
01908         if (1 != sscanf(ans,"%lf,%lf", &xd, &yd))
01909                 return(MISSING_VALUE) ;
01910 
01911         if (contains(opts, '-'))
01912         {
01913                 if (2 != sscanf(opts,"%lf-%lf,%lf-%lf",&xlo, &xhi, &ylo, &yhi))
01914                         return(BAD_SYNTAX) ;
01915                 if (xd < xlo || xd > xhi)
01916                         return(OUT_OF_RANGE) ;
01917                 if (yd < ylo || yd > yhi)
01918                         return(OUT_OF_RANGE) ;
01919                 return(0) ;
01920         }
01921         return(BAD_SYNTAX) ;
01922 }
01923 */
01924 
01925 static int check_double (char *ans, char *opts)
01926 {
01927         double d, lo, hi;
01928 
01929         if (1 != sscanf(ans,"%lf", &d))
01930                 return(MISSING_VALUE) ;
01931 
01932         if (contains(opts, '-'))
01933         {
01934                 if (2 != sscanf(opts,"%lf-%lf",&lo, &hi))
01935                         return(BAD_SYNTAX) ;
01936                 if (d < lo || d > hi)
01937                         return(OUT_OF_RANGE) ;
01938                 else
01939                         return(0) ;
01940         }
01941         else if (contains(opts, ','))
01942         {
01943                 for(;;)
01944                 {
01945                         if (1 != sscanf(opts,"%lf",&lo))
01946                                 return(BAD_SYNTAX) ;
01947                         if (d == lo)
01948                                 return(0) ;
01949                         while(*opts != '\0' && *opts != ',')
01950                                 opts++ ;
01951                         if (*opts == '\0')
01952                                 return(OUT_OF_RANGE) ;
01953                         if (*(++opts) == '\0')
01954                                 return(OUT_OF_RANGE) ;
01955                 }
01956         }
01957         else
01958         {
01959                 if (1 != sscanf(opts,"%lf",&lo))
01960                         return(BAD_SYNTAX) ;
01961                 if (d == lo)
01962                         return(0) ;
01963                 return(OUT_OF_RANGE) ;
01964         }
01965 }
01966 
01967 static int check_string (char *ans, char *opts)
01968 {
01969         if (*opts == '\0')
01970                 return(0) ;
01971 
01972         if (contains(opts, ','))
01973         {
01974                 for(;;)
01975                 {
01976                         if ((! strncmp(ans, opts, strlen(ans)))
01977                             && ( *(opts+strlen(ans)) == ','
01978                                ||  *(opts+strlen(ans)) == '\0'))
01979                                 return(0) ;
01980                         while(*opts != '\0' && *opts != ',')
01981                                 opts++ ;
01982                         if (*opts == '\0')
01983                                 return(OUT_OF_RANGE) ;
01984                         if (*(++opts) == '\0')
01985                                 return(OUT_OF_RANGE) ;
01986                 }
01987         }
01988         else
01989         {
01990                 if (! strcmp(ans, opts))
01991                         return(0) ;
01992                 return(OUT_OF_RANGE) ;
01993         }
01994 }
01995 
01996 static int check_required (void)
01997 {
01998         struct Option *opt ;
01999         int err ;
02000 
02001         err = 0 ;
02002 
02003         if(! n_opts)
02004                 return(0) ;
02005 
02006         opt= &first_option;
02007         while(opt != NULL)
02008         {
02009                 if(opt->required && opt->answer == NULL)
02010                 {
02011                         fprintf(stderr,_("\nERROR: Required parameter <%s> not set:\n    (%s).\n"),
02012                             opt->key, opt->description) ;
02013                         err++ ;
02014                 }
02015                 opt = opt->next_opt ;
02016         }
02017 
02018         return(err) ;
02019 }
02020 
02021 static int split_opts (void)
02022 {
02023         struct Option *opt ;
02024         char *ptr1 ;
02025         char *ptr2 ;
02026         int allocated ;
02027         int ans_num ;
02028         int len ;
02029 
02030 
02031         if(! n_opts)
02032                 return 0;
02033 
02034         opt= &first_option;
02035         while(opt != NULL)
02036         {
02037                 if (/*opt->multiple && */(opt->answer != NULL))
02038                 {
02039                         /* Allocate some memory to store array of pointers */
02040                         allocated = 10 ;
02041                         opt->answers = (char **)G_malloc(allocated * sizeof(char *)) ;
02042 
02043                         ans_num = 0 ;
02044                         ptr1 = opt->answer ;
02045                         opt->answers[ans_num] = NULL ;
02046 
02047                         for(;;)
02048                         {
02049                                 for(len=0, ptr2=ptr1; *ptr2 != '\0' && *ptr2 != ','; ptr2++, len++)
02050                                         ;
02051 
02052                                 if (len > 0)        /* skip ,, */
02053                                 {
02054                                         opt->answers[ans_num]=(char *)G_malloc(len+1) ;
02055                                         G_copy(opt->answers[ans_num], ptr1, len) ;
02056                                         opt->answers[ans_num][len] = 0;
02057 
02058                                         ans_num++ ;
02059 
02060                                         if(ans_num >= allocated)
02061                                         {
02062                                                 allocated += 10 ;
02063                                                 opt->answers =
02064                                                     (char **)G_realloc((char *)opt->answers,
02065                                                     allocated * sizeof(char *)) ;
02066                                         }
02067 
02068                                         opt->answers[ans_num] = NULL ;
02069                                 }
02070 
02071                                 if(*ptr2 == '\0')
02072                                         break ;
02073 
02074                                 ptr1 = ptr2+1 ;
02075 
02076                                 if(*ptr1 == '\0')
02077                                         break ;
02078                         }
02079                 }
02080                 opt = opt->next_opt ;
02081         }
02082 
02083         return 0;
02084 }
02085 
02086 static int check_multiple_opts (void)
02087 {
02088         struct Option *opt ;
02089         char *ptr ;
02090         int n_commas ;
02091         int n ;
02092         int error ;
02093 
02094         if(! n_opts)
02095                 return (0) ;
02096 
02097         error = 0 ;
02098         opt= &first_option;
02099         while(opt != NULL)
02100         {
02101                 if ((opt->answer != NULL) && (opt->key_desc != NULL))
02102                 {
02103                         /* count commas */
02104                         n_commas = 1 ;
02105                         for(ptr=opt->key_desc; *ptr!='\0'; ptr++)
02106                                 if (*ptr == ',')
02107                                         n_commas++ ;
02108                         /* count items */
02109                         for(n=0;opt->answers[n] != '\0';n++)
02110                                 ;
02111                         /* if not correct multiple of items */
02112                         if(n % n_commas)
02113                         {
02114                                 fprintf(stderr,_("\nError: option <%s> must be provided in multiples of %d\n"),
02115                                         opt->key, n_commas) ;
02116                                 fprintf(stderr,_("       You provided %d items:\n"), n) ;
02117                                 fprintf(stderr,"       %s\n", opt->answer) ;
02118                                 error++ ;
02119                         }
02120                 }
02121                 opt = opt->next_opt ;
02122         }
02123         return(error) ;
02124 }
02125 
02126 /* Check for all 'new' if element already exists */
02127 static int check_overwrite (void)
02128 {
02129         struct Option *opt ;
02130         char age[KEYLENGTH] ;
02131         char element[KEYLENGTH] ;
02132         char desc[KEYLENGTH] ;
02133         int error = 0;
02134         char *overstr;
02135         int over;
02136 
02137         if(! n_opts)
02138                 return (0) ;
02139 
02140         over = 0;
02141         /* Check the GRASS OVERWRITE variable */
02142         if ( (overstr = G__getenv ( "OVERWRITE" )) ) {
02143             over = atoi ( overstr );
02144         }
02145 
02146         /* Check the GRASS_OVERWRITE environment variable */
02147         if ( (overstr = getenv ( "GRASS_OVERWRITE" )) ) {
02148             if (atoi ( overstr ))
02149                 over = 1;
02150         }
02151 
02152         if ( overwrite || over ) {
02153             module_info.overwrite = 1;
02154             /* Set the environment so that programs run in a script also obey --o */
02155             putenv("GRASS_OVERWRITE=1");
02156             /* No need to check options for existing files if overwrite is true */
02157             return error;
02158         }
02159 
02160         opt= &first_option;
02161         while(opt != NULL)
02162         {
02163                 if ((opt->answer != NULL) && (opt->gisprompt != NULL))
02164                 {
02165                         split_gisprompt (opt->gisprompt, age, element, desc);
02166             
02167                         if ( strcmp(age,"new") == 0 ) {
02168                             if ( G_find_file (element, opt->answer, G_mapset()) ) /* found */
02169                             {
02170                                 if ( !overwrite && !over ) { 
02171                                     fprintf(stderr,_("Error: option <%s>: <%s> exists.\n"), 
02172                                                    opt->key, opt->answer );
02173 
02174                                     error = 1;
02175                                 }
02176                             }
02177                         }
02178                 }
02179                 opt = opt->next_opt ;
02180         }
02181 
02182         return(error) ;
02183 }
02184 
02185 static int interactive( char *command)
02186 {
02187         struct Item *item ;
02188 
02189         /* Query for flags */
02190 
02191         if(!n_items)
02192         {
02193                 fprintf(stderr,"Programmer error: no flags or options\n") ;
02194                 exit(EXIT_FAILURE) ;
02195         }
02196 
02197         for (item= &first_item ;;)
02198         {
02199                 if (item->flag)
02200                         interactive_flag(item->flag) ;
02201                 else if (item->option)
02202                         interactive_option(item->option) ;
02203                 else
02204                         break ;
02205 
02206                 item=item->next_item ;
02207 
02208                 if (item == NULL)
02209                         break ;
02210         }
02211 
02212         return 0;
02213 }
02214 
02215 static int interactive_flag( struct Flag *flag )
02216 {
02217         char buff[1024] ;
02218         fprintf(stderr, _("\nFLAG: Set the following flag?\n")) ;
02219         sprintf(buff,"    %s?", flag->description) ;
02220         flag->answer = G_yes(buff, 0) ;
02221 
02222         return 0;
02223 }
02224 
02225 static int interactive_option(struct Option *opt )
02226 {
02227         char buff[1024],*bptr ;
02228         char buff2[1024] ;
02229         int set_one ;
02230         int no_prompt ;
02231 
02232         fprintf(stderr,_("\nOPTION:   %s\n"), opt->description) ;
02233         fprintf(stderr,_("     key: %s\n"), opt->key) ;
02234         if (opt->key_desc)
02235         fprintf(stderr,_("  format: %s\n"), opt->key_desc) ;
02236         if (opt->def)
02237         fprintf(stderr,_(" default: %s\n"), opt->def) ;
02238         fprintf(stderr,_("required: %s\n"), opt->required ? "YES" : "NO") ;
02239         if (opt->multiple)
02240         fprintf(stderr,_("multiple: %s\n"), opt->multiple ? "YES" : "NO") ;
02241         if (opt->options)
02242         fprintf(stderr,_(" options: %s\n"), opt->options) ;
02243         /*
02244         show_options(0, opt->options) ;
02245         */
02246 
02247         set_one = 0 ;
02248         for(;;)
02249         {
02250            *buff='\0' ;
02251            if(opt->gisprompt)
02252                 no_prompt = gis_prompt(opt, buff) ;
02253            else
02254                 no_prompt = -1;
02255            if (no_prompt)
02256            {
02257                 fprintf(stderr,_("enter option > ")) ;
02258                 if(fgets(buff,1024,stdin) == 0) exit(EXIT_SUCCESS); ;
02259                 bptr = buff;  /* strip newline  */
02260                 while(*bptr) {if(*bptr=='\n') *bptr='\0'; bptr++;}
02261 
02262            }
02263 
02264            if(strlen(buff) != 0)
02265            {
02266                 if(opt->options)
02267                 /* then check option */
02268                 {
02269                     if (check_an_opt(opt->key, opt->type, opt->options, buff))
02270                     {
02271                         if (G_yes(_("   Try again? "), 1))
02272                                 continue ;
02273                         else
02274                                 exit(EXIT_FAILURE) ;
02275                     }
02276                 }
02277                 if (opt->checker)
02278                     if (opt->checker(buff))
02279                     {
02280                             fprintf(stderr,_("Sorry, %s is not accepted.\n"), buff) ;
02281                             *buff = '\0' ;
02282                             if (G_yes(_("   Try again? "), 1))
02283                                 continue ;
02284                             else
02285                                 exit(EXIT_FAILURE) ;
02286                     }
02287 
02288                 sprintf(buff2,"%s=%s", opt->key, buff) ;
02289                 if(! opt->gisprompt)
02290                 {
02291                         fprintf(stderr,_("\nYou have chosen:\n  %s\n"), buff2) ;
02292                         if (G_yes(_("Is this correct? "), 1))
02293                         {
02294                                 set_option(buff2) ;
02295                                 set_one++ ;
02296                         }
02297                 }
02298                 else 
02299                 {
02300                         set_option(buff2) ;
02301                         set_one++ ;
02302                 }
02303            } /* if strlen(buf ) !=0 */
02304 
02305            if ((strlen(buff) == 0) && opt->required && (set_one == 0))
02306                 exit(EXIT_FAILURE) ;
02307            if ((strlen(buff) == 0) && (set_one > 0) && opt->multiple )
02308                 break ;
02309            if ((strlen(buff) == 0) && !opt->required)
02310                 break ;
02311            if ((set_one == 1) && !opt->multiple)
02312                 break ;
02313         }
02314         return(0) ;
02315 }
02316 
02317 static int split_gisprompt (const char *gisprompt, char *age, char *element, char *desc)
02318 {
02319         const char *ptr1 ;
02320         char *ptr2 ;
02321 
02322         for(ptr1=gisprompt,ptr2=age; *ptr1!='\0'; ptr1++, ptr2++)
02323         {
02324                 if (*ptr1 == ',')
02325                         break ;
02326                 *ptr2 = *ptr1 ;
02327         }
02328         *ptr2 = '\0' ;
02329 
02330         for(ptr1++, ptr2=element; *ptr1!='\0'; ptr1++, ptr2++)
02331         {
02332                 if (*ptr1 == ',')
02333                         break ;
02334                 *ptr2 = *ptr1 ;
02335         }
02336         *ptr2 = '\0' ;
02337 
02338         for(ptr1++, ptr2=desc; *ptr1!='\0'; ptr1++, ptr2++)
02339         {
02340                 if (*ptr1 == ',')
02341                         break ;
02342                 *ptr2 = *ptr1 ;
02343         }
02344         *ptr2 = '\0' ;
02345 
02346         return 0 ;
02347 }
02348 
02349 static int gis_prompt (struct Option *opt, char *buff)
02350 {
02351         char age[KEYLENGTH] ;
02352         char element[KEYLENGTH] ;
02353         char desc[KEYLENGTH] ;
02354         char *ptr1 ;
02355 
02356         split_gisprompt ( opt->gisprompt, age, element, desc );
02357 
02358         /*********ptr1 points to current mapset description***********/
02359 
02360         if (opt->answer)
02361                 G_set_ask_return_msg (_("to accept the default"));
02362         if (! strcmp("old",age))
02363         {
02364                 ptr1 = G_ask_old("", buff, element, desc) ;
02365                 if (ptr1)
02366                 {
02367                     strcpy (buff, G_fully_qualified_name(buff,ptr1));
02368                 }
02369         }
02370         else if (! strcmp("new",age))
02371                 ptr1 = G_ask_new("", buff, element, desc) ;
02372         else if (! strcmp("mapset",age))
02373                 ptr1 = G_ask_in_mapset("", buff, element, desc) ;
02374         else if (! strcmp("any",age))
02375                 ptr1 = G_ask_any("", buff, element, desc, 1) ;
02376         else if (! strcmp("old_file",age)) /* file must exist */
02377                 ptr1 = G_ask_old_file("", buff, element, desc) ;
02378         else if (! strcmp("new_file",age)) /* file shouldn't exist unless overwrite is enabled*/
02379                 ptr1 = G_ask_new_file("", buff, element, desc) ;
02380         else if (! strcmp("color",age))
02381                 /* These prompts are only implemented in the gui */
02382                 /* The data can still be entered in the console */
02383                 return -1;
02384         else
02385         {
02386                 fprintf(stderr,"\nPROGRAMMER ERROR: first item in gisprompt is <%s>\n", age) ;
02387                 fprintf(stderr,"        Must be either new, old, mapset, any, old_file, new_file, or color\n") ;
02388                 return -1;
02389         }
02390         if (ptr1 == '\0')
02391                 *buff = '\0';
02392 
02393         return 0;
02394 }
02395 
02396 char *G_recreate_command (void)
02397 {
02398         static char *buff;
02399         char flg[4] ;
02400         char *cur;
02401         const char *tmp;
02402         struct Flag *flag ;
02403         struct Option *opt ;
02404         int n , len, slen;
02405         int nalloced = 0;
02406 
02407         G_debug ( 3, "G_recreate_command()");
02408 
02409         /* Flag is not valid if there are no flags to set */
02410         
02411         buff = G_calloc (1024, sizeof(char));
02412         nalloced += 1024;
02413         tmp = G_program_name();
02414         len = strlen (tmp);
02415         if (len >= nalloced)
02416         {
02417                 nalloced += (1024 > len) ? 1024 : len + 1;
02418                 buff = G_realloc (buff, nalloced);
02419         }
02420         cur = buff;
02421         strcpy (cur, tmp);
02422         cur += len;
02423 
02424         if(n_flags)
02425         {
02426                 flag= &first_flag;
02427                 while(flag != '\0')
02428                 {
02429                         if( flag->answer == 1 )
02430                         {
02431                                 flg[0] = ' '; flg[1] = '-'; flg[2] = flag->key; flg[3] = '\0';
02432                                 slen = strlen (flg);
02433                                 if (len + slen >= nalloced)
02434                                 {
02435                                         nalloced += (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
02436                                         buff = G_realloc (buff, nalloced);
02437                                         cur = buff + len;
02438                                 }
02439                                 strcpy (cur, flg);
02440                                 cur += slen;
02441                                 len += slen;
02442                         }
02443                         flag = flag->next_flag ;
02444                 }
02445         }
02446 
02447         opt= &first_option;
02448         while(opt != '\0')
02449         {
02450                 if ( opt->answer != '\0' && opt->answers[0] != NULL )
02451                 {
02452                         slen = strlen (opt->key) + strlen (opt->answers[0]) + 4; /* +4 for: ' ' = " " */
02453                         if (len + slen >= nalloced)
02454                         {
02455                                 nalloced += (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
02456                                 buff = G_realloc (buff, nalloced);
02457                                 cur = buff + len;
02458                         }
02459                         strcpy (cur, " ");
02460                         cur++;
02461                         strcpy (cur, opt->key);
02462                         cur = strchr (cur, '\0');
02463                         strcpy (cur, "=");
02464                         cur++;
02465                         if ( opt->type == TYPE_STRING ) {
02466                             strcpy (cur, "\"");
02467                             cur++;
02468                         }
02469                         strcpy (cur, opt->answers[0]);
02470                         cur = strchr (cur, '\0');
02471                         len = cur - buff;
02472                         for(n=1; opt->answers[n] != NULL && opt->answers[n] != '\0';n++)
02473                         {
02474                                 if ( opt->answers[n] == NULL ) break;
02475                                 slen = strlen (opt->answers[n]) + 2; /* +2 for , " */
02476                                 if (len + slen >= nalloced)
02477                                 {
02478                                         nalloced += (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
02479                                         buff = G_realloc (buff, nalloced);
02480                                         cur = buff + len;
02481                                 }
02482                                 strcpy (cur, ",");
02483                                 cur++;
02484                                 strcpy (cur, opt->answers[n]);
02485                                 cur = strchr(cur, '\0');
02486                                 len = cur - buff;
02487                         }
02488                         if ( opt->type == TYPE_STRING ) {
02489                             strcpy (cur, "\"");
02490                             cur++;
02491                             len = cur - buff;
02492                         }
02493                 }
02494                 opt = opt->next_opt ;
02495         }
02496 
02497         return(buff) ;
02498 }
02499 

Generated on Fri Nov 21 11:02:18 2008 for GRASS by  doxygen 1.5.1