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                         /* Force gui to come up */
00754                         else if ( strcmp(ptr,"--ui") == 0 )
00755                         {
00756                             force_gui = TRUE;
00757                         }
00758 
00759                         /* If we see a flag */
00760                         else if(*ptr == '-')
00761                         {
00762                                 while(*(++ptr))
00763                                         error += set_flag(*ptr) ;
00764 
00765                         }
00766                         /* If we see standard option format (option=val) */
00767                         else if (contains(ptr, '='))
00768                         {
00769                                 error += set_option(ptr) ;
00770                                 need_first_opt = 0 ;
00771                         }
00772 
00773                         /* If we see the first option with no equal sign */
00774                         else if (need_first_opt && n_opts)
00775                         {
00776                                 first_option.answer = G_store(ptr) ;
00777                                 need_first_opt = 0 ;
00778                         }
00779 
00780                         /* If we see the non valid argument (no "=", just argument) */
00781                         else if (contains(ptr, '=') == 0)
00782                         {
00783                                 fprintf(stderr, _("Sorry <%s> is not a valid option\n"), ptr);
00784                                 error = 1;
00785                         }
00786 
00787                 }
00788         }
00789 
00790         /* Run the gui if it was specifically requested */
00791         if (force_gui) {
00792                 G_gui();
00793                 return -1;
00794         }
00795 
00796         /* Split options where multiple answers are OK */
00797         split_opts() ;
00798 
00799         /* Check multiple options */
00800         error += check_multiple_opts() ;
00801 
00802         /* Check answers against options and check subroutines */
00803         if(!opt_checked)
00804            error += check_opts() ;
00805 
00806         /* Make sure all required options are set */
00807         error += check_required() ;
00808 
00809 
00810         if(error)
00811         {
00812                 G_usage();
00813                 return -1;
00814         }
00815 
00816         if ( check_overwrite () )
00817             return -1;
00818 
00819         return(0) ;
00820 }
00821 
00822 
00823 static int uses_new_gisprompt (void)
00824 {
00825         struct Option *opt ;
00826         char age[KEYLENGTH] ;
00827         char element[KEYLENGTH] ;
00828         char desc[KEYLENGTH] ;
00829 
00830         /* figure out if any of the options use a "new" gisprompt */
00831         /* This is to see if we should spit out the --o flag      */
00832         if(n_opts)
00833         {
00834                 opt= &first_option;
00835                 while(opt != NULL)
00836                 {
00837                         if ( opt->gisprompt )
00838                         {
00839                                 split_gisprompt (opt->gisprompt, age, element, desc) ;
00840                                 if (strcmp (age, "new") == 0)
00841                                         return 1;
00842                         }
00843                         opt=opt->next_opt;
00844                 }
00845         }
00846 
00847         return 0;
00848 }
00849 
00870 int G_usage (void)
00871 {
00872         struct Option *opt ;
00873         struct Flag *flag ;
00874         char item[256];
00875         char *key_desc;
00876         int maxlen;
00877         int len, n;
00878         int new_prompt = 0;
00879 
00880         new_prompt = uses_new_gisprompt();
00881         
00882         if (!pgm_name)          /* v.dave && r.michael */
00883             pgm_name = G_program_name ();
00884         if (!pgm_name)
00885             pgm_name = "??";
00886 
00887         if (module_info.description) {
00888                 fprintf (stderr, _("\nDescription:\n"));
00889                 fprintf (stderr, " %s\n", module_info.description);
00890         }
00891         if (module_info.keywords) {
00892                 fprintf (stderr, _("\nKeywords:\n"));
00893                 fprintf (stderr, " %s\n", module_info.keywords);
00894         }
00895 
00896         fprintf (stderr, _("\nUsage:\n "));
00897 
00898         len = show(pgm_name,1);
00899 
00900         /* Print flags */
00901 
00902         if(n_flags)
00903         {
00904                 item[0] = ' ';
00905                 item[1] = '[';
00906                 item[2] = '-';
00907                 flag= &first_flag;
00908                 for(n = 3; flag != NULL; n++, flag = flag->next_flag)
00909                         item[n] = flag->key;
00910                 item[n++] = ']';
00911                 item[n] = 0;
00912                 len=show(item,len);
00913         }
00914 
00915         maxlen = 0;
00916         if(n_opts)
00917         {
00918                 opt= &first_option;
00919                 while(opt != NULL)
00920                 {
00921                         if (opt->key_desc != NULL)
00922                                 key_desc = opt->key_desc;
00923                         else if (opt->type == TYPE_STRING)
00924                                 key_desc = "string";
00925                         else
00926                                 key_desc = "value";
00927 
00928                         n = strlen (opt->key);
00929                         if (n > maxlen) maxlen = n;
00930 
00931                         strcpy(item," ");
00932                         if(!opt->required )
00933                                 strcat (item, "[");
00934                         strcat (item, opt->key);
00935                         strcat (item, "=");
00936                         strcat (item, key_desc);
00937                         if (opt->multiple)
00938                         {
00939                                 strcat(item,"[,");
00940                                 strcat(item,key_desc);
00941                                 strcat(item,",...]");
00942                         }
00943                         if(!opt->required )
00944                                 strcat(item,"]") ;
00945 
00946                         len = show(item,len);
00947 
00948                         opt = opt->next_opt ;
00949                 }
00950         }
00951         if (new_prompt)
00952         {
00953                 strcpy (item, " [--overwrite]");
00954                 len=show(item,len);
00955         }
00956 
00957         fprintf (stderr, "\n");
00958 
00959         /* Print help info for flags */
00960 
00961         if(n_flags || new_prompt)       
00962                 fprintf (stderr, _("\nFlags:\n"));
00963 
00964         if(n_flags)
00965         {
00966                 flag= &first_flag;
00967                 while(flag != NULL)
00968                 {
00969                         fprintf(stderr,"  -%c   ", flag->key) ;
00970 
00971                         if ( flag->label ) {
00972                             fprintf (stderr, "%s\n", flag->label );
00973                             if ( flag->description )
00974                                 fprintf (stderr, "      %s\n", flag->description);
00975 
00976                         } else if ( flag->description ) {
00977                             fprintf (stderr, "%s\n", flag->description);
00978                         }
00979 
00980                         flag = flag->next_flag ;
00981                 }
00982         }
00983 
00984         if (new_prompt)
00985                 fprintf(stderr," --o   %s\n", _("Force overwrite of output files")) ;
00986                 
00987 
00988         /* Print help info for options */
00989 
00990         if(n_opts)
00991         {
00992                 fprintf (stderr, _("\nParameters:\n"));
00993                 opt= &first_option;
00994                 while(opt != NULL)
00995                 {
00996                         fprintf (stderr, "  %*s   ", maxlen, opt->key );
00997 
00998                         if ( opt->label ) {
00999                             fprintf (stderr, "%s\n", opt->label );
01000                             if ( opt->description )
01001                                 fprintf (stderr, "           %*s\n", maxlen, opt->description);
01002 
01003                         } else if ( opt->description ) {
01004                             fprintf (stderr, "%s\n", opt->description);
01005                         }
01006 
01007                         if(opt->options)
01008                                 show_options(maxlen, opt->options) ;
01009                                 /*
01010                                 fprintf (stderr, "  %*s   options: %s\n", maxlen, " ",
01011                                         _(opt->options)) ;
01012                                 */
01013                         if(opt->def)
01014                                 fprintf (stderr, _("  %*s   default: %s\n"), maxlen, " ",
01015                                         opt->def) ;
01016                         
01017                         if(opt->descs) {
01018                             int i = 0;
01019 
01020                             while ( opt->opts[i] ) {
01021                                 fprintf (stderr, "  %*s   %s: ", maxlen, " ", opt->opts[i] );
01022 
01023                                 if (  opt->descs[i] )
01024                                     fprintf (stderr, "%s\n", opt->descs[i] );
01025                                 
01026                                 i++;
01027                             }
01028                         }
01029 
01030                         opt = opt->next_opt ;
01031                 }
01032         }
01033 
01034         return 0;
01035 }
01036 
01037 void print_escaped_for_xml (FILE * fp, char * str) {
01038         for (;*str;str++) {
01039                 switch (*str) {
01040                         case '&':
01041                                 fputs("&amp;", fp);
01042                                 break;
01043                         case '<':
01044                                 fputs("&lt;", fp);
01045                                 break;
01046                         case '>':
01047                                 fputs("&gt;", fp);
01048                                 break;
01049                         default:
01050                                 fputc(*str, fp);
01051                 }
01052         }
01053 }
01054 
01055 static void G_usage_xml (void)
01056 {
01057         struct Option *opt ;
01058         struct Flag *flag ;
01059         char *type;
01060         char *s, *top;
01061         int i;
01062         char *encoding;
01063 
01064 /* gettext converts strings to encoding returned by nl_langinfo(CODESET) */
01065 
01066 #if defined(HAVE_LANGINFO_H)
01067         encoding = nl_langinfo (CODESET);
01068         if ( !encoding || strlen( encoding ) == 0 ) {
01069             encoding = "UTF-8";
01070         }
01071 #else
01072         encoding = "UTF-8";
01073 #endif
01074         
01075         if (!pgm_name)          /* v.dave && r.michael */
01076             pgm_name = G_program_name ();
01077         if (!pgm_name)
01078             pgm_name = "??";
01079 
01080         fprintf(stdout, "<?xml version=\"1.0\" encoding=\"%s\"?>\n", encoding);
01081         fprintf(stdout, "<!DOCTYPE task SYSTEM \"grass-interface.dtd\">\n");
01082 
01083         fprintf(stdout, "<task name=\"%s\">\n", pgm_name);  
01084 
01085         if (module_info.label) {
01086                 fprintf(stdout, "\t<label>\n\t\t");
01087                 print_escaped_for_xml (stdout, module_info.label);
01088                 fprintf(stdout, "\n\t</label>\n");
01089         }
01090 
01091         if (module_info.description) {
01092                 fprintf(stdout, "\t<description>\n\t\t");
01093                 print_escaped_for_xml (stdout, module_info.description);
01094                 fprintf(stdout, "\n\t</description>\n");
01095         }
01096 
01097         if (module_info.keywords) {
01098                 fprintf(stdout, "\t<keywords>\n\t\t");
01099                 print_escaped_for_xml (stdout, module_info.keywords);
01100                 fprintf(stdout, "\n\t</keywords>\n");
01101         }
01102 
01103         /***** Don't use parameter-groups for now.  We'll reimplement this later 
01104          ***** when we have a concept of several mutually exclusive option
01105          ***** groups
01106         if (n_opts || n_flags)
01107                 fprintf(stdout, "\t<parameter-group>\n");
01108          *****
01109          *****
01110          *****/
01111         
01112         if(n_opts)
01113         {
01114                 opt= &first_option;
01115                 while(opt != NULL)
01116                 {
01117                         /* TODO: make this a enumeration type? */
01118                         switch (opt->type) {
01119                                 case TYPE_INTEGER:
01120                                         type = "integer";
01121                                         break ;
01122                                 case TYPE_DOUBLE:
01123                                         type = "float";
01124                                         break ;
01125                                 case TYPE_STRING:
01126                                         type = "string";
01127                                         break ;
01128                                 default:
01129                                         type = "string";
01130                                         break;
01131                         }
01132                         fprintf (stdout, "\t<parameter "
01133                                 "name=\"%s\" "
01134                                 "type=\"%s\" "
01135                                 "required=\"%s\" "
01136                                 "multiple=\"%s\">\n",
01137                                 opt->key,
01138                                 type,
01139                                 opt->required == YES ? "yes" : "no",
01140                                 opt->multiple == YES ? "yes" : "no");
01141 
01142                         if (opt->label) {
01143                                 fprintf(stdout, "\t\t<label>\n\t\t\t");
01144                                 print_escaped_for_xml(stdout, opt->label);
01145                                 fprintf(stdout, "\n\t\t</label>\n");
01146                         }
01147 
01148                         if (opt->description) {
01149                                 fprintf(stdout, "\t\t<description>\n\t\t\t");
01150                                 print_escaped_for_xml(stdout, opt->description);
01151                                 fprintf(stdout, "\n\t\t</description>\n");
01152                         }
01153 
01154                         if (opt->key_desc)
01155                         {
01156                                 fprintf (stdout, "\t\t<keydesc>\n");
01157                                 top = G_calloc (strlen (opt->key_desc) + 1, 1);
01158                                 strcpy (top, opt->key_desc);
01159                                 s = strtok (top, ",");
01160                                 for (i = 1; s != NULL; i++)
01161                                 {
01162                                         fprintf (stdout, "\t\t\t<item order=\"%d\">", i);
01163                                         print_escaped_for_xml (stdout, s);
01164                                         fprintf (stdout, "</item>\n");
01165                                         s = strtok (NULL, ",");
01166                                 }
01167                                 fprintf (stdout, "\t\t</keydesc>\n");
01168                                 G_free (top);
01169                         }
01170                         
01171                         if (opt->gisprompt)
01172                         {
01173                                 const char *atts[] = {"age", "element", "prompt", NULL};
01174                                 top = G_calloc (strlen (opt->gisprompt) + 1, 1);
01175                                 strcpy (top, opt->gisprompt);
01176                                 s = strtok (top, ",");
01177                                 fprintf (stdout, "\t\t<gisprompt ");
01178                                 for (i = 0; s != NULL && atts[i] != NULL; i++)
01179                                 {
01180                                         fprintf (stdout, "%s=\"%s\" ", atts[i], s);
01181                                         s = strtok (NULL, ",");
01182                                 }
01183                                 fprintf (stdout, "/>\n");
01184                                 G_free (top);
01185                         }
01186 
01187                         if(opt->def) {
01188                                 fprintf(stdout, "\t\t\t<default>\n\t\t\t");
01189                                 print_escaped_for_xml(stdout, opt->def);
01190                                 fprintf(stdout, "\n\t\t\t</default>\n");
01191                         }
01192 
01193                         if(opt->options) {
01194                                 i = 0;
01195                                 fprintf(stdout, "\t\t<values>\n");
01196                                 while ( opt->opts[i] ) {
01197                                         fprintf(stdout, "\t\t\t<value>\n");
01198                                         fprintf(stdout, "\t\t\t\t<name>");
01199                                         print_escaped_for_xml(stdout, opt->opts[i]);
01200                                         fprintf(stdout, "</name>\n");
01201                                         if(opt->descs && opt->opts[i]) {
01202                                             fprintf(stdout, "\t\t\t\t<description>");
01203                                             print_escaped_for_xml(stdout, opt->descs[i]);
01204                                             fprintf(stdout, "</description>");
01205                                         }
01206                                         fprintf(stdout, "\t\t\t</value>\n");
01207                                         i++;
01208                                 }
01209                                 fprintf(stdout, "\t\t</values>\n");
01210                         }
01211 
01212                         /* TODO:
01213                          * add something like
01214                          *       <range min="xxx" max="xxx"/>
01215                          * to <values>
01216                          * - key_desc?
01217                          * - there surely are some more. which ones?
01218                          */
01219 
01220                         opt = opt->next_opt ;
01221                         fprintf (stdout, "\t</parameter>\n");
01222                 }
01223         }
01224 
01225         
01226         if(n_flags)
01227         {
01228                 flag= &first_flag;
01229                 while(flag != NULL)
01230                 {
01231                         fprintf (stdout, "\t<flag name=\"%c\">\n", flag->key);
01232 
01233                         if (flag->label) {
01234                                 fprintf(stdout, "\t\t<label>\n\t\t\t");
01235                                 print_escaped_for_xml(stdout, flag->label);
01236                                 fprintf(stdout, "\n\t\t</label>\n");
01237                         }
01238 
01239                         if (flag->description) {
01240                                 fprintf(stdout, "\t\t<description>\n\t\t\t");
01241                                 print_escaped_for_xml(stdout, flag->description);
01242                                 fprintf(stdout, "\n\t\t</description>\n");
01243                         }
01244                         flag = flag->next_flag ;
01245                         fprintf (stdout, "\t</flag>\n");
01246                 }
01247         }
01248 
01249         /***** Don't use parameter-groups for now.  We'll reimplement this later 
01250          ***** when we have a concept of several mutually exclusive option
01251          ***** groups
01252         if (n_opts || n_flags)
01253                 fprintf(stdout, "\t</parameter-group>\n");
01254          *****
01255          *****
01256          *****/
01257 
01258         fprintf(stdout, "</task>\n");
01259 }
01260 
01261 static void G_usage_html (void)
01262 {
01263         struct Option *opt ;
01264         struct Flag *flag ;
01265         char *type;
01266         char *newbuf;
01267         int new_prompt = 0;
01268 
01269         new_prompt = uses_new_gisprompt();
01270         
01271         if (!pgm_name)          /* v.dave && r.michael */
01272             pgm_name = G_program_name ();
01273         if (!pgm_name)
01274             pgm_name = "??";
01275 
01276         fprintf(stdout, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n");
01277         fprintf(stdout, "<html>\n<head>\n");
01278         fprintf(stdout, "<title>%s</title>\n", pgm_name);
01279         fprintf(stdout, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n");
01280         fprintf(stdout, "<link rel=\"stylesheet\" href=\"grassdocs.css\" type=\"text/css\">\n");
01281         fprintf(stdout, "</head>\n");
01282         fprintf(stdout, "<body bgcolor=\"white\">\n\n");
01283         fprintf(stdout, "<img src=\"grass.smlogo.gif\" alt=\"GRASS logo\"><hr align=center size=6 noshade>\n\n");
01284         fprintf(stdout, "<h2>NAME</h2>\n");
01285         fprintf(stdout, "<em><b>%s</b></em> ", pgm_name);
01286 
01287         if (module_info.description) {
01288                 fprintf(stdout, " - ");
01289                 fprintf(stdout, "%s", module_info.description);
01290                 fprintf(stdout, "\n");
01291         }
01292 
01293         fprintf(stdout, "<h2>KEYWORDS</h2>\n");
01294         if (module_info.keywords) {
01295                 fprintf(stdout, "%s", module_info.keywords);
01296                 fprintf(stdout, "\n");
01297         }
01298         fprintf(stdout, "<h2>SYNOPSIS</h2>\n");
01299         fprintf(stdout, "<b>%s</b><br>\n", pgm_name);
01300         fprintf(stdout, "<b>%s help</b><br>\n", pgm_name);
01301 
01302         fprintf(stdout, "<b>%s</b>", pgm_name);
01303 
01304 
01305 
01306         /* print short version first */
01307         if(n_flags)
01308         {
01309                 flag= &first_flag;
01310                 fprintf(stdout, " [-<b>");
01311                 while(flag != NULL)
01312                 {
01313                         fprintf (stdout, "%c", flag->key);
01314                         flag = flag->next_flag ;
01315                 }
01316                 fprintf(stdout, "</b>] ");
01317         }
01318         else
01319           fprintf(stdout, " ");
01320 
01321         if(n_opts)
01322         {
01323                 opt= &first_option;
01324 
01325                 while(opt != NULL)
01326                 {
01327                         if (opt->key_desc != NULL)
01328                             type = opt->key_desc;
01329                         else switch (opt->type) {
01330                                 case TYPE_INTEGER:
01331                                         type = "integer";
01332                                         break ;
01333                                 case TYPE_DOUBLE:
01334                                         type = "float";
01335                                         break ;
01336                                 case TYPE_STRING:
01337                                         type = "string";
01338                                         break ;
01339                                 default:
01340                                         type = "string";
01341                                         break;
01342                         }
01343                         if( !opt->required )
01344                              fprintf(stdout," [");
01345                         fprintf(stdout,
01346                                 "<b>%s</b>=<em>%s</em>", opt->key, type);
01347                         if (opt->multiple)
01348                         {
01349                                 fprintf(stdout,"[,<i>%s</i>,...]", type);
01350                         }
01351                         if( !opt->required )
01352                              fprintf(stdout,"] ");
01353 
01354                         opt = opt->next_opt ;
01355                         fprintf(stdout," ");
01356                 }
01357         }
01358         if (new_prompt)
01359         {
01360                 fprintf(stdout, " [--<b>overwrite</b>] ");
01361         }
01362         fprintf(stdout, "\n");
01363 
01364 
01365         /* now long version */
01366         fprintf(stdout, "\n");
01367         if(n_flags || new_prompt)
01368         {
01369                 flag= &first_flag;
01370                 fprintf(stdout, "<h3>Flags:</h3>\n");
01371                 fprintf(stdout, "<DL>\n");
01372                 while(n_flags && flag != NULL )
01373                 {
01374                         fprintf (stdout, "<DT><b>-%c</b></DT>\n", flag->key);
01375 
01376                         if ( flag->label ) {
01377                                 fprintf(stdout, "<DD>");
01378                                 fprintf(stdout, "%s", flag->label);
01379                                 fprintf(stdout, "</DD>\n");
01380                         }
01381 
01382                         if (flag->description) {
01383                                 fprintf(stdout, "<DD>");
01384                                 fprintf(stdout, "%s", flag->description);
01385                                 fprintf(stdout, "</DD>\n");
01386                         }
01387 
01388                         flag = flag->next_flag ;
01389                         fprintf (stdout, "\n");
01390                 }
01391                 if (new_prompt)
01392                 {
01393                         fprintf(stdout, "<DT><b>--overwrite</b></DT>\n");
01394                         fprintf(stdout, "<DD>Force overwrite of output files</DD>");
01395                 }
01396                 fprintf(stdout, "</DL>\n");
01397         }
01398 
01399         fprintf(stdout, "\n");
01400         if(n_opts)
01401         {
01402                 opt= &first_option;
01403                 fprintf(stdout, "<h3>Parameters:</h3>\n");
01404                 fprintf(stdout, "<DL>\n");
01405                 
01406                 while(opt != NULL)
01407                 {
01408                         /* TODO: make this a enumeration type? */
01409                         if (opt->key_desc != NULL)
01410                             type = opt->key_desc;
01411                         else switch (opt->type) {
01412                                 case TYPE_INTEGER:
01413                                         type = "integer";
01414                                         break ;
01415                                 case TYPE_DOUBLE:
01416                                         type = "float";
01417                                         break ;
01418                                 case TYPE_STRING:
01419                                         type = "string";
01420                                         break ;
01421                                 default:
01422                                         type = "string";
01423                                         break;
01424                         }
01425                         fprintf(stdout,
01426                                 "<DT><b>%s</b>=<em>%s", opt->key, type);
01427                         if (opt->multiple) {
01428                                 fprintf(stdout,"[,<i>%s</i>,...]", type);
01429                         }
01430                         fprintf(stdout,"</em></DT>\n");
01431 
01432                         if ( opt->label ) {
01433                                 fprintf(stdout, "<DD>");
01434                                 fprintf(stdout, "%s", opt->label);
01435                                 fprintf(stdout, "</DD>\n");
01436                         }
01437                         if (opt->description) {
01438                                 fprintf(stdout, "<DD>");
01439                                 newbuf = G_str_replace(opt->description, "\n","<br>");
01440                                 if (newbuf) {
01441                                         fprintf(stdout, "%s", newbuf);
01442                                         G_free(newbuf);
01443                                 } else
01444                                         fprintf(stdout, "%s", opt->description);
01445                                 fprintf(stdout, "</DD>\n");
01446                                 
01447                         }
01448 
01449                         if(opt->options) {
01450                                 fprintf(stdout, "<DD>Options: <em>");
01451                                 fprintf(stdout, "%s", opt->options);
01452                                 fprintf(stdout, "</em></DD>\n");
01453                         }
01454 
01455                         if(opt->def) {
01456                                 fprintf(stdout, "<DD>Default: <em>");
01457                                 fprintf(stdout, "%s", opt->def);
01458                                 fprintf(stdout, "</em></DD>\n");
01459                         }
01460 
01461                         if(opt->descs) {
01462                             int i = 0;
01463 
01464                             while ( opt->opts[i] ) {
01465                                 fprintf(stdout, "<DD><b>%s</b>: ", opt->opts[i]);
01466 
01467                                 if (  opt->descs[i] )
01468                                     fprintf (stdout, "%s", opt->descs[i] );
01469                                 
01470                                 fprintf(stdout, "</DD>\n");
01471                                 
01472                                 i++;
01473                             }
01474                         }
01475 
01476                         opt = opt->next_opt ;
01477                         fprintf (stdout, "\n");
01478                 }
01479                 fprintf(stdout, "</DL>\n");
01480         }
01481         
01482     fprintf(stdout, "</body>\n</html>\n");
01483 }
01484 
01485 static void generate_tcl(FILE *fp)
01486 {
01487         int new_prompt = uses_new_gisprompt();
01488         char *type;
01489         int optn;
01490 
01491         fprintf(fp, "begin_dialog {%s} {\n", pgm_name);
01492         fprintf(fp, " label {%s}\n", module_info.label ? module_info.label : "");
01493         fprintf(fp, " desc {%s}\n", module_info.description ? module_info.description : "");
01494         fprintf(fp, " key {%s}\n", module_info.keywords ? module_info.keywords : "");
01495         fprintf(fp, "}\n");
01496 
01497         optn = 1;
01498     
01499         if (n_flags)
01500         {
01501                 struct Flag *flag;
01502 
01503                 for (flag = &first_flag; flag; flag = flag->next_flag, optn++) {
01504                         fprintf(fp, "add_flag %d {\n", optn);
01505                         fprintf(fp, " name {%c}\n", flag->key);
01506                         fprintf(fp, " desc {%s}\n", flag->description);
01507                         fprintf(fp, " answer %d\n", flag->answer);
01508                         /* It should be up to the gui as to what
01509                            to do with the label and description */
01510                         fprintf(fp, " label {%s}\n", flag->label ? flag->label : "");
01511                         fprintf(fp, " guisection {%s}\n", flag->guisection ? flag->guisection : "");
01512                         fprintf(fp, "}\n");
01513                 }
01514         }
01515 
01516         if (n_opts)
01517         {
01518                 struct Option *opt;
01519 
01520                 for (opt = &first_option; opt; opt = opt->next_opt, optn++)
01521                 {
01522                         if (opt->key_desc != NULL)
01523                             type = opt->key_desc;
01524                         else switch (opt->type)
01525                         {
01526                         case TYPE_INTEGER:
01527                                 type = "integer";
01528                                 break;
01529                         case TYPE_DOUBLE:
01530                                 type = "float";
01531                                 break;
01532                         case TYPE_STRING:
01533                                 type = "string";
01534                                 break;
01535                         default:
01536                                 type = "string";
01537                                 break;
01538                         }
01539 
01540                         fprintf(fp, "add_option %d {\n", optn);
01541                         fprintf(fp, " name {%s}\n", opt->key);
01542                         fprintf(fp, " type {%s}\n", type);
01543                         fprintf(fp, " multi %d\n", opt->multiple);
01544                         fprintf(fp, " desc {%s}\n", opt->description);
01545                         fprintf(fp, " required %d\n", opt->required);
01546                         fprintf(fp, " options {%s}\n", opt->options ? opt->options : "");
01547                         fprintf(fp, " answer {%s}\n", opt->answer ? opt->answer : "");
01548                         fprintf(fp, " prompt {%s}\n", opt->gisprompt ? opt->gisprompt : "");
01549                         /* It should be up to the gui as to what
01550                            to do with the label and description */
01551                         fprintf(fp, " label {%s}\n", opt->label ? opt->label : "");
01552                         fprintf(fp, " guisection {%s}\n", opt->guisection ? opt->guisection : "");
01553                         fprintf(fp, "}\n");
01554                 }
01555         }
01556    
01557         if (new_prompt)
01558         {
01559                 fprintf(fp, "add_xflag %d {\n", optn);
01560                 fprintf(fp, " name {overwrite}\n");
01561                 fprintf(fp, " desc {Force overwrite of output files}\n");
01562                 fprintf(fp, " answer %d\n", overwrite);
01563                 fprintf(fp, " label {Overwrite}\n");
01564                 fprintf(fp, " guisection {}\n");
01565                 fprintf(fp, "}\n");
01566                 optn++;
01567         }
01568 
01569         fprintf(fp, "end_dialog %d\n", optn - 1);
01570 }
01571 
01572 /* Build gui */
01573 static void G_gui (void)
01574 {
01575         FILE *fp;
01576 
01577         if (!pgm_name)
01578                 pgm_name = G_program_name ();
01579         if (!pgm_name)
01580                 pgm_name = "??";
01581 
01582         if (getenv("GRASS_DEBUG_GUI"))
01583                 fp = popen("tee gui_dump.tcl | $GRASS_WISH", "w");
01584         else
01585                 fp = popen("$GRASS_WISH", "w");
01586 
01587         if (!fp)
01588                 G_fatal_error("unable to spawn wish");
01589 
01590         fprintf(fp, "source $env(GISBASE)/etc/gui.tcl\n");
01591 
01592         generate_tcl(fp);
01593 
01594         pclose(fp);
01595 }
01596 
01597 /* Send Tcl/Tk code to tcltkgrass */
01598 static void G_tcltk (void)
01599 {
01600         if (!pgm_name)
01601                 pgm_name = G_program_name ();
01602         if (!pgm_name)
01603                 pgm_name = "??";
01604 
01605         generate_tcl(stdout);
01606 }
01607 
01608 /**************************************************************************
01609  *
01610  * The remaining routines are all local (static) routines used to support
01611  * the parsing process.
01612  *
01613  **************************************************************************/
01614 
01615 static int show_options(int maxlen,char *str)
01616 {
01617         char buff[1024] ;
01618         char *p1, *p2 ;
01619         int totlen, len ;
01620 
01621         strcpy(buff, str) ;
01622         fprintf (stderr, _("  %*s   options: "), maxlen, " ") ;
01623         totlen = maxlen + 13 ;
01624         p1 = buff ;
01625         while( (p2 = G_index(p1, ',')) )
01626         {
01627                 *p2 = '\0' ;
01628                 len = strlen(p1) + 1 ;
01629                 if ((len + totlen) > 76)
01630                 {
01631                         totlen = maxlen + 13 ;
01632                         fprintf(stderr, "\n %*s", maxlen + 13, " ") ;
01633                 }
01634                 fprintf (stderr, "%s,",  p1) ;
01635                 totlen += len ;
01636                 p1 = p2 + 1 ;
01637         }
01638         len = strlen(p1) ;
01639         if ((len + totlen) > 76 )
01640                 fprintf(stderr, "\n %*s", maxlen + 13, " ") ;
01641         fprintf (stderr, "%s\n",  p1) ;
01642 
01643         return 0;
01644 }
01645 
01646 static int show (const char *item, int len)
01647 {
01648         int n;
01649 
01650         n = strlen (item)+(len>0);
01651         if (n + len > 76)
01652         {
01653                 if (len)
01654                         fprintf (stderr, "\n  ");
01655                 len = 0;
01656         }
01657         fprintf (stderr, "%s", item);
01658         return n+len;
01659 }
01660 
01661 static int set_flag (int f)
01662 {
01663         struct Flag *flag ;
01664 
01665         /* Flag is not valid if there are no flags to set */
01666 
01667         if(!n_flags)
01668         {
01669                 fprintf(stderr,_("Sorry, <%c> is not a valid flag\n"), f) ;
01670                 return(1) ;
01671         }
01672 
01673         /* Find flag with corrrect keyword */
01674 
01675         flag= &first_flag;
01676         while(flag != NULL)
01677         {
01678                 if( flag->key == f)
01679                 {
01680                         flag->answer = 1 ;
01681                         return(0) ;
01682                 }
01683                 flag = flag->next_flag ;
01684         }
01685 
01686         fprintf(stderr,_("Sorry, <%c> is not a valid flag\n"), f) ;
01687         return(1) ;
01688 }
01689 
01690 /* contents() is used to find things strings with characters like commas and
01691  * dashes.
01692  */
01693 static int contains (char *s, int c)
01694 {
01695         while(*s)
01696         {
01697                 if(*s == c)
01698                         return(1) ;
01699                 s++ ;
01700         }
01701         return(0) ;
01702 }
01703 
01704 static int set_option (char *string)
01705 {
01706         struct Option *at_opt = NULL;
01707         struct Option *opt = NULL;
01708         int got_one ;
01709         size_t key_len ;
01710         char the_key[KEYLENGTH] ;
01711         char *ptr ;
01712 
01713         for(ptr=the_key; *string!='='; ptr++, string++)
01714                 *ptr = *string ;
01715         *ptr = '\0' ;
01716         string++ ;
01717 
01718         /* Find option with best keyword match */
01719         got_one = 0 ;
01720         key_len = strlen(the_key) ;
01721         for(at_opt= &first_option; at_opt != NULL; at_opt=at_opt->next_opt)
01722         {
01723                 if (strncmp(the_key,at_opt->key,key_len))
01724                         continue ;
01725 
01726                 got_one++;
01727                 opt = at_opt ;
01728 
01729                 /* changed 1/15/91 -dpg   old code is in parser.old */
01730                 /* overide ambiguous check, if we get an exact match */
01731                 if (strlen (at_opt->key) == key_len)    
01732                 {
01733                     opt = at_opt;
01734                     got_one = 1;
01735                     break;
01736                 }
01737         }
01738 
01739         if (got_one > 1)
01740         {
01741                 fprintf(stderr,_("Sorry, <%s=> is ambiguous\n"), the_key) ;
01742                 return(1) ;
01743         }
01744 
01745         /* If there is no match, complain */
01746         if(got_one == 0)
01747         {
01748                 fprintf(stderr,_("Sorry, <%s> is not a valid parameter\n"),
01749                         the_key) ;
01750                 return(1) ;
01751         }
01752                 
01753         /* Allocate memory where answer is stored */
01754         if (opt->count++)
01755         {
01756                 opt->answer = (char *)G_realloc (opt->answer,
01757                         strlen (opt->answer)+strlen(string)+2);
01758                 strcat (opt->answer, ",");
01759                 strcat (opt->answer, string);
01760         }
01761         else
01762                 opt->answer = G_store(string) ;
01763         return(0) ;
01764 }
01765 
01766 static int check_opts (void)
01767 {
01768         struct Option *opt ;
01769         int error ;
01770         int ans ;
01771 
01772         error = 0 ;
01773 
01774         if(! n_opts)
01775                 return(0) ;
01776 
01777         opt= &first_option;
01778         while(opt != NULL)
01779         {
01780                 /* Check answer against options if any */
01781 
01782                 if(opt->options && opt->answer)
01783                 {
01784                         if(opt->multiple == 0)
01785                                 error += check_an_opt(opt->key, opt->type,
01786                                     opt->options, opt->answer) ;
01787                         else
01788                         {
01789                                 for(ans=0; opt->answers[ans] != '\0'; ans++)
01790                                         error += check_an_opt(opt->key, opt->type,
01791                                             opt->options, opt->answers[ans]) ;
01792                         }
01793                 }
01794 
01795                 /* Check answer against user's check subroutine if any */
01796 
01797                 if(opt->checker)
01798                         error += opt->checker(opt->answer) ;
01799 
01800                 opt = opt->next_opt ;
01801         }
01802         return(error) ;
01803 }
01804 
01805 static int check_an_opt (char *key, int type, char *options, char *answer)
01806 {
01807         int error ;
01808 
01809         error = 0 ;
01810 
01811         switch(type)
01812         {
01813         case TYPE_INTEGER:
01814                 error = check_int(answer,options) ;
01815                 break ;
01816         case TYPE_DOUBLE:
01817                 error = check_double(answer,options) ;
01818                 break ;
01819         case TYPE_STRING:
01820                 error = check_string(answer,options) ;
01821                 break ;
01822 /*
01823         case TYPE_COORDINATE:
01824                 error = check_coor(answer,options) ;
01825                 break ;
01826 */
01827         }
01828         switch(error)
01829         {
01830         case 0:
01831                 break ;
01832         case BAD_SYNTAX:
01833                 fprintf(stderr,_("\nError: illegal range syntax for parameter <%s>\n"),
01834                     key) ;
01835                 fprintf(stderr,_("       Presented as: %s\n"), options) ;
01836                 break ;
01837         case OUT_OF_RANGE:
01838                 fprintf(stderr,_("\nError: value <%s> out of range for parameter <%s>\n"),
01839                     answer, key) ;
01840                 fprintf(stderr,_("       Legal range: %s\n"), options) ;
01841                 break ;
01842         case MISSING_VALUE:
01843                 fprintf(stderr,_("\nError: Missing value for parameter <%s>\n"),
01844                     key) ;
01845         }
01846         return(error) ;
01847 }
01848 
01849 static int check_int (char *ans, char *opts)
01850 {
01851         int d, lo, hi;
01852 
01853         if (1 != sscanf(ans,"%d", &d))
01854                 return(MISSING_VALUE) ;
01855 
01856         if (contains(opts, '-'))
01857         {
01858                 if (2 != sscanf(opts,"%d-%d",&lo, &hi))
01859                         return(BAD_SYNTAX) ;
01860                 if (d < lo || d > hi)
01861                         return(OUT_OF_RANGE) ;
01862                 else
01863                         return(0) ;
01864         }
01865         else if (contains(opts, ','))
01866         {
01867                 for(;;)
01868                 {
01869                         if (1 != sscanf(opts,"%d",&lo))
01870                                 return(BAD_SYNTAX) ;
01871                         if (d == lo)
01872                                 return(0) ;
01873                         while(*opts != '\0' && *opts != ',')
01874                                 opts++ ;
01875                         if (*opts == '\0')
01876                                 return(OUT_OF_RANGE) ;
01877                         if (*(++opts) == '\0')
01878                                 return(OUT_OF_RANGE) ;
01879                 }
01880         }
01881         else
01882         {
01883                 if (1 != sscanf(opts,"%d",&lo))
01884                         return(BAD_SYNTAX) ;
01885                 if (d == lo)
01886                         return(0) ;
01887                 return(OUT_OF_RANGE) ;
01888         }
01889 }
01890 
01891 /*
01892 static int
01893 check_coor(ans, opts)
01894 char *ans ;
01895 char *opts ;
01896 {
01897         double xd, xlo, xhi;
01898         double yd, ylo, yhi;
01899 
01900         if (1 != sscanf(ans,"%lf,%lf", &xd, &yd))
01901                 return(MISSING_VALUE) ;
01902 
01903         if (contains(opts, '-'))
01904         {
01905                 if (2 != sscanf(opts,"%lf-%lf,%lf-%lf",&xlo, &xhi, &ylo, &yhi))
01906                         return(BAD_SYNTAX) ;
01907                 if (xd < xlo || xd > xhi)
01908                         return(OUT_OF_RANGE) ;
01909                 if (yd < ylo || yd > yhi)
01910                         return(OUT_OF_RANGE) ;
01911                 return(0) ;
01912         }
01913         return(BAD_SYNTAX) ;
01914 }
01915 */
01916 
01917 static int check_double (char *ans, char *opts)
01918 {
01919         double d, lo, hi;
01920 
01921         if (1 != sscanf(ans,"%lf", &d))
01922                 return(MISSING_VALUE) ;
01923 
01924         if (contains(opts, '-'))
01925         {
01926                 if (2 != sscanf(opts,"%lf-%lf",&lo, &hi))
01927                         return(BAD_SYNTAX) ;
01928                 if (d < lo || d > hi)
01929                         return(OUT_OF_RANGE) ;
01930                 else
01931                         return(0) ;
01932         }
01933         else if (contains(opts, ','))
01934         {
01935                 for(;;)
01936                 {
01937                         if (1 != sscanf(opts,"%lf",&lo))
01938                                 return(BAD_SYNTAX) ;
01939                         if (d == lo)
01940                                 return(0) ;
01941                         while(*opts != '\0' && *opts != ',')
01942                                 opts++ ;
01943                         if (*opts == '\0')
01944                                 return(OUT_OF_RANGE) ;
01945                         if (*(++opts) == '\0')
01946                                 return(OUT_OF_RANGE) ;
01947                 }
01948         }
01949         else
01950         {
01951                 if (1 != sscanf(opts,"%lf",&lo))
01952                         return(BAD_SYNTAX) ;
01953                 if (d == lo)
01954                         return(0) ;
01955                 return(OUT_OF_RANGE) ;
01956         }
01957 }
01958 
01959 static int check_string (char *ans, char *opts)
01960 {
01961         if (*opts == '\0')
01962                 return(0) ;
01963 
01964         if (contains(opts, ','))
01965         {
01966                 for(;;)
01967                 {
01968                         if ((! strncmp(ans, opts, strlen(ans)))
01969                             && ( *(opts+strlen(ans)) == ','
01970                                ||  *(opts+strlen(ans)) == '\0'))
01971                                 return(0) ;
01972                         while(*opts != '\0' && *opts != ',')
01973                                 opts++ ;
01974                         if (*opts == '\0')
01975                                 return(OUT_OF_RANGE) ;
01976                         if (*(++opts) == '\0')
01977                                 return(OUT_OF_RANGE) ;
01978                 }
01979         }
01980         else
01981         {
01982                 if (! strcmp(ans, opts))
01983                         return(0) ;
01984                 return(OUT_OF_RANGE) ;
01985         }
01986 }
01987 
01988 static int check_required (void)
01989 {
01990         struct Option *opt ;
01991         int err ;
01992 
01993         err = 0 ;
01994 
01995         if(! n_opts)
01996                 return(0) ;
01997 
01998         opt= &first_option;
01999         while(opt != NULL)
02000         {
02001                 if(opt->required && opt->answer == NULL)
02002                 {
02003                         fprintf(stderr,_("\nERROR: Required parameter <%s> not set:\n    (%s).\n"),
02004                             opt->key, opt->description) ;
02005                         err++ ;
02006                 }
02007                 opt = opt->next_opt ;
02008         }
02009 
02010         return(err) ;
02011 }
02012 
02013 static int split_opts (void)
02014 {
02015         struct Option *opt ;
02016         char *ptr1 ;
02017         char *ptr2 ;
02018         int allocated ;
02019         int ans_num ;
02020         int len ;
02021 
02022 
02023         if(! n_opts)
02024                 return 0;
02025 
02026         opt= &first_option;
02027         while(opt != NULL)
02028         {
02029                 if (/*opt->multiple && */(opt->answer != NULL))
02030                 {
02031                         /* Allocate some memory to store array of pointers */
02032                         allocated = 10 ;
02033                         opt->answers = (char **)G_malloc(allocated * sizeof(char *)) ;
02034 
02035                         ans_num = 0 ;
02036                         ptr1 = opt->answer ;
02037                         opt->answers[ans_num] = NULL ;
02038 
02039                         for(;;)
02040                         {
02041                                 for(len=0, ptr2=ptr1; *ptr2 != '\0' && *ptr2 != ','; ptr2++, len++)
02042                                         ;
02043 
02044                                 if (len > 0)        /* skip ,, */
02045                                 {
02046                                         opt->answers[ans_num]=(char *)G_malloc(len+1) ;
02047                                         G_copy(opt->answers[ans_num], ptr1, len) ;
02048                                         opt->answers[ans_num][len] = 0;
02049 
02050                                         ans_num++ ;
02051 
02052                                         if(ans_num >= allocated)
02053                                         {
02054                                                 allocated += 10 ;
02055                                                 opt->answers =
02056                                                     (char **)G_realloc((char *)opt->answers,
02057                                                     allocated * sizeof(char *)) ;
02058                                         }
02059 
02060                                         opt->answers[ans_num] = NULL ;
02061                                 }
02062 
02063                                 if(*ptr2 == '\0')
02064                                         break ;
02065 
02066                                 ptr1 = ptr2+1 ;
02067 
02068                                 if(*ptr1 == '\0')
02069                                         break ;
02070                         }
02071                 }
02072                 opt = opt->next_opt ;
02073         }
02074 
02075         return 0;
02076 }
02077 
02078 static int check_multiple_opts (void)
02079 {
02080         struct Option *opt ;
02081         char *ptr ;
02082         int n_commas ;
02083         int n ;
02084         int error ;
02085 
02086         if(! n_opts)
02087                 return (0) ;
02088 
02089         error = 0 ;
02090         opt= &first_option;
02091         while(opt != NULL)
02092         {
02093                 if ((opt->answer != NULL) && (opt->key_desc != NULL))
02094                 {
02095                         /* count commas */
02096                         n_commas = 1 ;
02097                         for(ptr=opt->key_desc; *ptr!='\0'; ptr++)
02098                                 if (*ptr == ',')
02099                                         n_commas++ ;
02100                         /* count items */
02101                         for(n=0;opt->answers[n] != '\0';n++)
02102                                 ;
02103                         /* if not correct multiple of items */
02104                         if(n % n_commas)
02105                         {
02106                                 fprintf(stderr,_("\nError: option <%s> must be provided in multiples of %d\n"),
02107                                         opt->key, n_commas) ;
02108                                 fprintf(stderr,_("       You provided %d items:\n"), n) ;
02109                                 fprintf(stderr,"       %s\n", opt->answer) ;
02110                                 error++ ;
02111                         }
02112                 }
02113                 opt = opt->next_opt ;
02114         }
02115         return(error) ;
02116 }
02117 
02118 /* Check for all 'new' if element already exists */
02119 static int check_overwrite (void)
02120 {
02121         struct Option *opt ;
02122         char age[KEYLENGTH] ;
02123         char element[KEYLENGTH] ;
02124         char desc[KEYLENGTH] ;
02125         int error = 0;
02126         char *overstr;
02127         int over;
02128 
02129         if(! n_opts)
02130                 return (0) ;
02131 
02132         over = 0;
02133         /* Check the GRASS OVERWRITE variable */
02134         if ( (overstr = G__getenv ( "OVERWRITE" )) ) {
02135             over = atoi ( overstr );
02136         }
02137 
02138         /* Check the GRASS_OVERWRITE environment variable */
02139         if ( (overstr = getenv ( "GRASS_OVERWRITE" )) ) {
02140             if (atoi ( overstr ))
02141                 over = 1;
02142         }
02143 
02144         if ( overwrite || over ) {
02145             module_info.overwrite = 1;
02146             /* Set the environment so that programs run in a script also obey --o */
02147             putenv("GRASS_OVERWRITE=1");
02148             /* No need to check options for existing files if overwrite is true */
02149             return error;
02150         }
02151 
02152         opt= &first_option;
02153         while(opt != NULL)
02154         {
02155                 if ((opt->answer != NULL) && (opt->gisprompt != NULL))
02156                 {
02157                         split_gisprompt (opt->gisprompt, age, element, desc);
02158             
02159                         if ( strcmp(age,"new") == 0 ) {
02160                             if ( G_find_file (element, opt->answer, G_mapset()) ) /* found */
02161                             {
02162                                 if ( !overwrite && !over ) { 
02163                                     fprintf(stderr,_("Error: option <%s>: <%s> exists.\n"), 
02164                                                    opt->key, opt->answer );
02165 
02166                                     error = 1;
02167                                 }
02168                             }
02169                         }
02170                 }
02171                 opt = opt->next_opt ;
02172         }
02173 
02174         return(error) ;
02175 }
02176 
02177 static int interactive( char *command)
02178 {
02179         struct Item *item ;
02180 
02181         /* Query for flags */
02182 
02183         if(!n_items)
02184         {
02185                 fprintf(stderr,"Programmer error: no flags or options\n") ;
02186                 exit(EXIT_FAILURE) ;
02187         }
02188 
02189         for (item= &first_item ;;)
02190         {
02191                 if (item->flag)
02192                         interactive_flag(item->flag) ;
02193                 else if (item->option)
02194                         interactive_option(item->option) ;
02195                 else
02196                         break ;
02197 
02198                 item=item->next_item ;
02199 
02200                 if (item == NULL)
02201                         break ;
02202         }
02203 
02204         return 0;
02205 }
02206 
02207 static int interactive_flag( struct Flag *flag )
02208 {
02209         char buff[1024] ;
02210         fprintf(stderr, _("\nFLAG: Set the following flag?\n")) ;
02211         sprintf(buff,"    %s?", flag->description) ;
02212         flag->answer = G_yes(buff, 0) ;
02213 
02214         return 0;
02215 }
02216 
02217 static int interactive_option(struct Option *opt )
02218 {
02219         char buff[1024],*bptr ;
02220         char buff2[1024] ;
02221         int set_one ;
02222         int no_prompt ;
02223 
02224         fprintf(stderr,_("\nOPTION:   %s\n"), opt->description) ;
02225         fprintf(stderr,_("     key: %s\n"), opt->key) ;
02226         if (opt->key_desc)
02227         fprintf(stderr,_("  format: %s\n"), opt->key_desc) ;
02228         if (opt->def)
02229         fprintf(stderr,_(" default: %s\n"), opt->def) ;
02230         fprintf(stderr,_("required: %s\n"), opt->required ? "YES" : "NO") ;
02231         if (opt->multiple)
02232         fprintf(stderr,_("multiple: %s\n"), opt->multiple ? "YES" : "NO") ;
02233         if (opt->options)
02234         fprintf(stderr,_(" options: %s\n"), opt->options) ;
02235         /*
02236         show_options(0, opt->options) ;
02237         */
02238 
02239         set_one = 0 ;
02240         for(;;)
02241         {
02242            *buff='\0' ;
02243            if(opt->gisprompt)
02244                 no_prompt = gis_prompt(opt, buff) ;
02245            else
02246                 no_prompt = -1;
02247            if (no_prompt)
02248            {
02249                 fprintf(stderr,_("enter option > ")) ;
02250                 if(fgets(buff,1024,stdin) == 0) exit(EXIT_SUCCESS); ;
02251                 bptr = buff;  /* strip newline  */
02252                 while(*bptr) {if(*bptr=='\n') *bptr='\0'; bptr++;}
02253 
02254            }
02255 
02256            if(strlen(buff) != 0)
02257            {
02258                 if(opt->options)
02259                 /* then check option */
02260                 {
02261                     if (check_an_opt(opt->key, opt->type, opt->options, buff))
02262                     {
02263                         if (G_yes(_("   Try again? "), 1))
02264                                 continue ;
02265                         else
02266                                 exit(EXIT_FAILURE) ;
02267                     }
02268                 }
02269                 if (opt->checker)
02270                     if (opt->checker(buff))
02271                     {
02272                             fprintf(stderr,_("Sorry, %s is not accepted.\n"), buff) ;
02273                             *buff = '\0' ;
02274                             if (G_yes(_("   Try again? "), 1))
02275                                 continue ;
02276                             else
02277                                 exit(EXIT_FAILURE) ;
02278                     }
02279 
02280                 sprintf(buff2,"%s=%s", opt->key, buff) ;
02281                 if(! opt->gisprompt)
02282                 {
02283                         fprintf(stderr,_("\nYou have chosen:\n  %s\n"), buff2) ;
02284                         if (G_yes(_("Is this correct? "), 1))
02285                         {
02286                                 set_option(buff2) ;
02287                                 set_one++ ;
02288                         }
02289                 }
02290                 else 
02291                 {
02292                         set_option(buff2) ;
02293                         set_one++ ;
02294                 }
02295            } /* if strlen(buf ) !=0 */
02296 
02297            if ((strlen(buff) == 0) && opt->required && (set_one == 0))
02298                 exit(EXIT_FAILURE) ;
02299            if ((strlen(buff) == 0) && (set_one > 0) && opt->multiple )
02300                 break ;
02301            if ((strlen(buff) == 0) && !opt->required)
02302                 break ;
02303            if ((set_one == 1) && !opt->multiple)
02304                 break ;
02305         }
02306         return(0) ;
02307 }
02308 
02309 static int split_gisprompt (const char *gisprompt, char *age, char *element, char *desc)
02310 {
02311         const char *ptr1 ;
02312         char *ptr2 ;
02313 
02314         for(ptr1=gisprompt,ptr2=age; *ptr1!='\0'; ptr1++, ptr2++)
02315         {
02316                 if (*ptr1 == ',')
02317                         break ;
02318                 *ptr2 = *ptr1 ;
02319         }
02320         *ptr2 = '\0' ;
02321 
02322         for(ptr1++, ptr2=element; *ptr1!='\0'; ptr1++, ptr2++)
02323         {
02324                 if (*ptr1 == ',')
02325                         break ;
02326                 *ptr2 = *ptr1 ;
02327         }
02328         *ptr2 = '\0' ;
02329 
02330         for(ptr1++, ptr2=desc; *ptr1!='\0'; ptr1++, ptr2++)
02331         {
02332                 if (*ptr1 == ',')
02333                         break ;
02334                 *ptr2 = *ptr1 ;
02335         }
02336         *ptr2 = '\0' ;
02337 
02338         return 0 ;
02339 }
02340 
02341 static int gis_prompt (struct Option *opt, char *buff)
02342 {
02343         char age[KEYLENGTH] ;
02344         char element[KEYLENGTH] ;
02345         char desc[KEYLENGTH] ;
02346         char *ptr1 ;
02347 
02348         split_gisprompt ( opt->gisprompt, age, element, desc );
02349 
02350         /*********ptr1 points to current mapset description***********/
02351 
02352         if (opt->answer)
02353                 G_set_ask_return_msg (_("to accept the default"));
02354         if (! strcmp("old",age))
02355         {
02356                 ptr1 = G_ask_old("", buff, element, desc) ;
02357                 if (ptr1)
02358                 {
02359                     strcpy (buff, G_fully_qualified_name(buff,ptr1));
02360                 }
02361         }
02362         else if (! strcmp("new",age))
02363                 ptr1 = G_ask_new("", buff, element, desc) ;
02364         else if (! strcmp("mapset",age))
02365                 ptr1 = G_ask_in_mapset("", buff, element, desc) ;
02366         else if (! strcmp("any",age))
02367                 ptr1 = G_ask_any("", buff, element, desc, 1) ;
02368         else if (! strcmp("old_file",age)) /* file must exist */
02369                 ptr1 = G_ask_old_file("", buff, element, desc) ;
02370         else if (! strcmp("new_file",age)) /* file shouldn't exist unless overwrite is enabled*/
02371                 ptr1 = G_ask_new_file("", buff, element, desc) ;
02372         else if (! strcmp("color",age))
02373                 /* These prompts are only implemented in the gui */
02374                 /* The data can still be entered in the console */
02375                 return -1;
02376         else
02377         {
02378                 fprintf(stderr,"\nPROGRAMMER ERROR: first item in gisprompt is <%s>\n", age) ;
02379                 fprintf(stderr,"        Must be either new, old, mapset, any, old_file, new_file, or color\n") ;
02380                 return -1;
02381         }
02382         if (ptr1 == '\0')
02383                 *buff = '\0';
02384 
02385         return 0;
02386 }
02387 
02388 char *G_recreate_command (void)
02389 {
02390         static char *buff;
02391         char flg[4] ;
02392         char *cur;
02393         const char *tmp;
02394         struct Flag *flag ;
02395         struct Option *opt ;
02396         int n , len, slen;
02397         int nalloced = 0;
02398 
02399         G_debug ( 3, "G_recreate_command()");
02400 
02401         /* Flag is not valid if there are no flags to set */
02402         
02403         buff = G_calloc (1024, sizeof(char));
02404         nalloced += 1024;
02405         tmp = G_program_name();
02406         len = strlen (tmp);
02407         if (len >= nalloced)
02408         {
02409                 nalloced += (1024 > len) ? 1024 : len + 1;
02410                 buff = G_realloc (buff, nalloced);
02411         }
02412         cur = buff;
02413         strcpy (cur, tmp);
02414         cur += len;
02415 
02416         if(n_flags)
02417         {
02418                 flag= &first_flag;
02419                 while(flag != '\0')
02420                 {
02421                         if( flag->answer == 1 )
02422                         {
02423                                 flg[0] = ' '; flg[1] = '-'; flg[2] = flag->key; flg[3] = '\0';
02424                                 slen = strlen (flg);
02425                                 if (len + slen >= nalloced)
02426                                 {
02427                                         nalloced += (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
02428                                         buff = G_realloc (buff, nalloced);
02429                                         cur = buff + len;
02430                                 }
02431                                 strcpy (cur, flg);
02432                                 cur += slen;
02433                                 len += slen;
02434                         }
02435                         flag = flag->next_flag ;
02436                 }
02437         }
02438 
02439         opt= &first_option;
02440         while(opt != '\0')
02441         {
02442                 if ( opt->answer != '\0' && opt->answers[0] != NULL )
02443                 {
02444                         slen = strlen (opt->key) + strlen (opt->answers[0]) + 4; /* +4 for: ' ' = " " */
02445                         if (len + slen >= nalloced)
02446                         {
02447                                 nalloced += (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
02448                                 buff = G_realloc (buff, nalloced);
02449                                 cur = buff + len;
02450                         }
02451                         strcpy (cur, " ");
02452                         cur++;
02453                         strcpy (cur, opt->key);
02454                         cur = strchr (cur, '\0');
02455                         strcpy (cur, "=");
02456                         cur++;
02457                         if ( opt->type == TYPE_STRING ) {
02458                             strcpy (cur, "\"");
02459                             cur++;
02460                         }
02461                         strcpy (cur, opt->answers[0]);
02462                         cur = strchr (cur, '\0');
02463                         len = cur - buff;
02464                         for(n=1; opt->answers[n] != NULL && opt->answers[n] != '\0';n++)
02465                         {
02466                                 if ( opt->answers[n] == NULL ) break;
02467                                 slen = strlen (opt->answers[n]) + 2; /* +2 for , " */
02468                                 if (len + slen >= nalloced)
02469                                 {
02470                                         nalloced += (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
02471                                         buff = G_realloc (buff, nalloced);
02472                                         cur = buff + len;
02473                                 }
02474                                 strcpy (cur, ",");
02475                                 cur++;
02476                                 strcpy (cur, opt->answers[n]);
02477                                 cur = strchr(cur, '\0');
02478                                 len = cur - buff;
02479                         }
02480                         if ( opt->type == TYPE_STRING ) {
02481                             strcpy (cur, "\"");
02482                             cur++;
02483                             len = cur - buff;
02484                         }
02485                 }
02486                 opt = opt->next_opt ;
02487         }
02488 
02489         return(buff) ;
02490 }
02491 

Generated on Wed Dec 19 14:59:06 2007 for GRASS by  doxygen 1.5.4