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  * parser() will respond to the following command lines as described:
00061  *
00062  * command      (No command line arguments)
00063  *    Parser enters interactive mode.
00064  *
00065  * command map=map.name
00066  *    Parser will accept this line.  Map will be set to "map.name", the
00067  *    'a' and 'b' flags will remain off and the num option will be set
00068  *    to the default of 5.
00069  *
00070  * command -ab map=map.name num=9
00071  * command -a -b map=map.name num=9
00072  * command -ab map.name num=9
00073  * command map.name num=9 -ab
00074  * command num=9 -a map=map.name -b
00075  *    These are all treated as acceptable and identical. Both flags are
00076  *    set to on, the map option is "map.name" and the num option is "9".
00077  *    Note that the "map=" may be omitted from the command line if it
00078  *    is part of the first option (flags do not count).
00079  *
00080  * command num=12
00081  *    This command line is in error in two ways.  The user will be told 
00082  *    that the "map" option is required and also that the number 12 is
00083  *    out of range.  The acceptable range (or list) will be printed.
00084  *
00085  * On error, G_parser() prints call G_usage() and returns -1.
00086  * Otherwise returns 0
00087  *
00088  ***************************************************************************
00089  *
00090  * G_recreate_command()
00091  *
00092  * Creates a command-line that runs the current command completely
00093  * non-interactive
00094  *
00095  ***************************************************************************
00096 */
00097 
00098 #include <stdio.h>
00099 #include <stdlib.h>
00100 #include <string.h>
00101 #include <ctype.h>
00102 #include <unistd.h>
00103 #include <stdarg.h>
00104 #include "gis.h"
00105 #include "glocale.h"
00106 
00107 #define BAD_SYNTAX  1
00108 #define OUT_OF_RANGE    2
00109 #define MISSING_VALUE   3
00110 
00111 
00112 static int interactive_ok = 1 ;
00113 static int n_opts = 0 ;
00114 static int n_flags = 0 ;
00115 static int overwrite = 0 ;
00116 
00117 static struct Flag first_flag;    /* First flag in a linked list      */
00118 static struct Flag *current_flag; /* Pointer for traversing list      */
00119 
00120 static struct Option first_option ;
00121 static struct Option *current_option ;
00122 
00123 static struct GModule module_info; /* general information on the corresponding module */
00124 
00125 static char *pgm_name = NULL;
00126 
00127 struct Item
00128 {
00129         struct Option *option ;
00130         struct Flag *flag ;
00131         struct Item *next_item ;
00132 } ;
00133 
00134 static struct Item first_item ;
00135 static struct Item *current_item ;
00136 static int n_items = 0 ;
00137 static int show_options(int ,char *);
00138 static int show(char *,int);
00139 static int set_flag (int);
00140 static int contains (char *,int);
00141 static int set_option( char *);
00142 static int check_opts();
00143 static int check_an_opt( char *, int , char *,char *);
00144 static int check_int(char *, char *);
00145 static int check_double( char *, char *);
00146 static int check_string( char *, char *);
00147 static int check_required();
00148 static int split_opts();
00149 static int check_multiple_opts();
00150 static int check_overwrite();
00151 static int interactive( char *);
00152 static int interactive_flag( struct Flag *);
00153 static int interactive_option( struct Option *);
00154 static int gis_prompt( struct Option *, char *);
00155 
00156 static void G_gui (void);
00157 static void G_tcltk (void);
00158 static void G_usage_xml (void);
00159 static void G_usage_html (void);
00160 
00161 
00175 int 
00176 G_disable_interactive (void)
00177 {
00178         interactive_ok = 0 ;
00179 
00180         return 0;
00181 }
00182 
00183  
00194 struct Flag *
00195 G_define_flag (void)
00196 {
00197         struct Flag *flag ;
00198         struct Item *item ;
00199 
00200         /* Allocate memory if not the first flag */
00201 
00202         if (n_flags)
00203         {
00204                 flag = (struct Flag *)G_malloc(sizeof(struct Flag)) ;
00205                 current_flag->next_flag = flag ;
00206         }
00207         else
00208                 flag = &first_flag ;
00209 
00210         /* Zero structure */
00211 
00212         G_zero ((char *) flag, sizeof(struct Flag));
00213 
00214         current_flag = flag ;
00215         n_flags++ ;
00216 
00217         if (n_items)
00218         {
00219                 item = (struct Item *)G_malloc(sizeof(struct Item)) ;
00220                 current_item->next_item = item ;
00221         }
00222         else
00223                 item = &first_item ;
00224 
00225         G_zero ((char *) item, sizeof(struct Item));
00226         
00227         item->flag = flag ;
00228         item->option = NULL ;
00229 
00230         current_item = item ;
00231         n_items++ ;
00232 
00233         return(flag) ;
00234 }
00235 
00245 struct Option *
00246 G_define_option (void)
00247 {
00248         struct Option *opt ;
00249         struct Item *item ;
00250 
00251         /* Allocate memory if not the first option */
00252 
00253         if (n_opts)
00254         {
00255                 opt = (struct Option *)G_malloc(sizeof(struct Option)) ;
00256                 current_option->next_opt = opt ;
00257         }
00258         else
00259                 opt = &first_option ;
00260 
00261         /* Zero structure */
00262         G_zero ((char *) opt, sizeof(struct Option));
00263 
00264         opt->required  = NO ;
00265         opt->multiple  = NO ;
00266         opt->answer    = NULL ;
00267         opt->answers   = NULL ;
00268         opt->def       = NULL ;
00269         opt->checker   = NULL ;
00270         opt->options   = NULL ;
00271         opt->key_desc  = NULL ;
00272         opt->gisprompt = NULL ;
00273         opt->label     = NULL ;
00274         opt->opts      = NULL ;
00275         opt->description  = NULL ;
00276         opt->descriptions = NULL ;
00277 
00278         current_option = opt ;
00279         n_opts++ ;
00280 
00281         if (n_items)
00282         {
00283                 item = (struct Item *)G_malloc(sizeof(struct Item)) ;
00284                 current_item->next_item = item ;
00285         }
00286         else
00287                 item = &first_item ;
00288 
00289         G_zero ((char *) item, sizeof(struct Item));
00290         
00291         item->option = opt ;
00292         item->flag = NULL ;
00293 
00294         current_item = item ;
00295         n_items++ ;
00296 
00297         return(opt) ;
00298 }
00299 
00300 struct Option *
00301 G_define_standard_option (int opt)
00302 {
00303     struct Option *Opt ;
00304     
00305     Opt = G_define_option();
00306 
00307     switch ( opt ) {
00308         case G_OPT_WHERE:
00309             Opt->key          = "where";
00310             Opt->type         = TYPE_STRING;
00311             Opt->required     = NO;
00312             Opt->description  = _("WHERE conditions of SQL statement without 'where' keyword. (example: income < 1000 and inhab >= 10000)");
00313             break;
00314             
00315         case G_OPT_R_INPUT:
00316             Opt->key          = "input";
00317             Opt->type         = TYPE_STRING;
00318             Opt->required     = YES;
00319             Opt->gisprompt    = "old,cell,raster";
00320             Opt->description  = _("Name of input raster");
00321             break;
00322         case G_OPT_R_OUTPUT:
00323             Opt->key          = "output";
00324             Opt->type         = TYPE_STRING;
00325             Opt->required     = YES;
00326             Opt->gisprompt    = "new,cell,raster";
00327             Opt->description  = _("Name of output raster");
00328             break;
00329         case G_OPT_R_MAP:
00330             Opt->key          = "map";
00331             Opt->type         = TYPE_STRING;
00332             Opt->required     = YES;
00333             Opt->gisprompt    = "old,cell,raster";
00334             Opt->description  = _("Name of input raster");
00335             break;
00336             
00337         case G_OPT_V_INPUT:
00338             Opt->key          = "input";
00339             Opt->type         = TYPE_STRING;
00340             Opt->required     = YES;
00341             Opt->gisprompt    = "old,vector,vector";
00342             Opt->description  = _("Name of input vector");
00343             break;
00344         case G_OPT_V_OUTPUT:
00345             Opt->key          = "output";
00346             Opt->type         = TYPE_STRING;
00347             Opt->required     = YES;
00348             Opt->gisprompt    = "new,vector,vector";
00349             Opt->description  = _("Name of output vector");
00350             break;
00351         case G_OPT_V_MAP:
00352             Opt->key          = "map";
00353             Opt->type         = TYPE_STRING;
00354             Opt->required     = YES;
00355             Opt->gisprompt    = "old,vector,vector";
00356             Opt->description  = _("Name of input vector");
00357             break;
00358         case G_OPT_V_TYPE:
00359             Opt->key          = "type";
00360             Opt->type         = TYPE_STRING;
00361             Opt->required     = NO;
00362             Opt->multiple     = YES;
00363             Opt->answer       = "point,line,boundary,centroid,area";
00364             Opt->options      = "point,line,boundary,centroid,area";
00365             Opt->description  = _("Type");
00366             break;
00367         case G_OPT_V_FIELD:
00368             Opt->key          = "layer";
00369             Opt->type         = TYPE_INTEGER;
00370             Opt->required     = NO;
00371             Opt->answer       = "1";
00372             Opt->description  = _("Layer number");
00373             break;
00374         case G_OPT_V_CAT:
00375             Opt->key          = "cat";
00376             Opt->type         = TYPE_INTEGER;
00377             Opt->required     = NO;
00378             Opt->description  = _("Category value");
00379             break;
00380         case G_OPT_V_CATS:
00381             Opt->key          = "cats";
00382             Opt->type         = TYPE_STRING;
00383             Opt->required     = NO;
00384             Opt->label        = _("Category values.");
00385             Opt->description  = _("Example: 1,3,7-9,13");
00386             break;
00387     }
00388 
00389     return(Opt);
00390 }
00391 
00392 struct GModule *
00393 G_define_module (void)
00394 {
00395         struct GModule *module ;
00396 
00397         /* Allocate memory */
00398 
00399         module = &module_info;
00400 
00401         /* Zero structure */
00402 
00403         G_zero ((char *) module, sizeof(struct GModule));
00404 
00405         return(module) ;
00406 }
00407 
00408 /* The main parsing routine */
00409 
00429 int G_parser (int argc, char **argv)
00430 {
00431         int need_first_opt ;
00432         int opt_checked = 0;
00433         int error ;
00434         char *ptr ;
00435         int i;
00436         struct Option *opt ;
00437 
00438         error = 0 ;
00439         need_first_opt = 1 ;
00440         i = strlen(pgm_name = argv[0]) ;
00441         while (--i >= 0)
00442         {
00443                 if (pgm_name[i] == '/')
00444                 {
00445                         pgm_name += i+1;
00446                         break;
00447                 }
00448         }
00449 
00450         /* Stash default answers */
00451 
00452         opt= &first_option;
00453         while(opt != NULL)
00454         {
00455                 /* Parse options */
00456                 if(opt->options)
00457                 {
00458                     int  cnt = 0;
00459                     char **tokens, delm[2];
00460                     
00461                     delm[0] = ','; delm[1] = '\0';
00462                     tokens = G_tokenize ( opt->options, delm );
00463                     
00464                     i = 0;
00465                     while ( tokens[i] ) {
00466                         cnt++;
00467                         i++;
00468                     }
00469 
00470                     opt->opts = (char **)G_calloc( cnt+1, sizeof(char*) );
00471                     
00472                     i = 0;
00473                     while ( tokens[i] ) {
00474                         opt->opts[i] = G_store ( tokens[i] );
00475                         i++;
00476                     }
00477                     G_free_tokens ( tokens );
00478 
00479                     if(opt->descriptions ) {
00480                         delm[0] = ';';
00481 
00482                         opt->descs = (char **)G_calloc( cnt+1, sizeof(char*) );
00483                         tokens = G_tokenize ( opt->descriptions, delm );
00484                         
00485                         i = 0;
00486                         while ( tokens[i] ) {
00487                             int j, found;
00488 
00489                             if ( !tokens[i+1] ) break;
00490 
00491                             j = 0; found = 0;
00492                             while ( opt->opts[j] ) {
00493                                 if ( strcmp(opt->opts[j],tokens[i]) == 0 ) {
00494                                     found = 1;
00495                                     break;
00496                                 }
00497                                 j++;
00498                             }
00499                             if ( !found ) {
00500                                 G_warning ( "BUG in descriptions, option %s in %s does not exist",
00501                                              tokens[i], opt->key );
00502                             } else {
00503                                 opt->descs[j] = G_store ( tokens[i+1] );
00504                             }
00505 
00506                             i += 2;
00507                         }
00508                         G_free_tokens ( tokens );
00509                     }
00510                 }
00511                     
00512                 /* Copy answer */
00513                 if(opt->multiple && opt->answers && opt->answers[0])
00514                 {
00515                         opt->answer = (char *)G_malloc(strlen(opt->answers[0])+1);
00516                         strcpy(opt->answer, opt->answers[0]);
00517                         for(i=1; opt->answers[i]; i++)
00518                         {
00519                                 opt->answer = (char *)G_realloc (opt->answer,
00520                                                 strlen(opt->answer)+
00521                                                 strlen(opt->answers[i])+2);
00522                                 strcat(opt->answer, ",");
00523                                 strcat(opt->answer, opt->answers[i]);
00524                         }
00525                 }
00526                 opt->def = opt->answer ;
00527                 opt = opt->next_opt ;
00528         }
00529         
00530         /* If there are NO arguments, go interactive */
00531 
00532         if (argc < 2 && interactive_ok && isatty(0) )
00533         {
00534             if (getenv("GRASS_UI_TERM")) {
00535                 interactive(argv[0]) ;
00536                 opt_checked = 1; 
00537                 /* all options have been already checked interactively */
00538             } else {
00539                 G_gui();
00540                 return -1;
00541             }
00542         }
00543         else if (argc < 2 && isatty(0))
00544         {
00545             G_usage();
00546             return -1;
00547         }
00548         else if (argc >= 2)
00549         {
00550 
00551                 /* If first arg is "help" give a usage/syntax message */
00552                 if (strcmp(argv[1],"help") == 0 ||
00553                         strcmp(argv[1], "-help") == 0 ||
00554                         strcmp(argv[1], "--help") == 0)
00555                 {
00556                         G_usage();
00557                         return -1;
00558                 }
00559 
00560                 /* If first arg is "--interface-description" then print out
00561                  * a xml description of the task */
00562                 if (strcmp(argv[1],"--interface-description") == 0)
00563                 {
00564                         G_usage_xml();
00565                         return -1;
00566                 }
00567 
00568                 /* If first arg is "--html-description" then print out
00569                  * a xml description of the task */
00570                 if (strcmp(argv[1],"--html-description") == 0)
00571                 {
00572                         G_usage_html();
00573                         return -1;
00574                 }
00575 
00576                 /* If first arg is "--ui" then run G_gui() */
00577                 if (strcmp(argv[1],"--ui") == 0)
00578                 {
00579                         G_gui();
00580                         return -1;
00581                 }
00582 
00583                 /* If first arg is "--tcltk" then then generate
00584                  * code for tcltkgrass */
00585                 if (strcmp(argv[1],"--tcltk") == 0)
00586                 {
00587                         G_tcltk();
00588                         exit(0);
00589                 }
00590 
00591                 /* Loop thru all command line arguments */
00592 
00593                 while(--argc)
00594                 {
00595                         ptr = *(++argv) ;
00596 
00597                         /* Overwrite option */
00598                         if ( strncmp(ptr,"--o", 3) == 0 || strncmp(ptr,"--overwrite",11) == 0 )
00599                         {
00600                             overwrite = 1;
00601                         }
00602                         /* If we see a flag */
00603                         else if(*ptr == '-')
00604                         {
00605                                 while(*(++ptr))
00606                                         error += set_flag(*ptr) ;
00607 
00608                         }
00609                         /* If we see standard option format (option=val) */
00610                         else if (contains(ptr, '='))
00611                         {
00612                                 error += set_option(ptr) ;
00613                                 need_first_opt = 0 ;
00614                         }
00615 
00616                         /* If we see the first option with no equal sign */
00617                         else if (need_first_opt && n_opts)
00618                         {
00619                                 first_option.answer = G_store(ptr) ;
00620                                 need_first_opt = 0 ;
00621                         }
00622 
00623                 /* If we see the non valid argument (no "=", just argument) */
00624                         else if (contains(ptr, '=') == 0)
00625                         {
00626                                 fprintf(stderr, _("Sorry <%s> is not a valid option\n"), ptr);
00627                                 error = 1;
00628                         }
00629 
00630                 }
00631         }
00632 
00633         /* Split options where multiple answers are OK */
00634         split_opts() ;
00635 
00636         /* Check multiple options */
00637         error += check_multiple_opts() ;
00638 
00639         /* Check answers against options and check subroutines */
00640         if(!opt_checked)
00641            error += check_opts() ;
00642 
00643         /* Make sure all required options are set */
00644         error += check_required() ;
00645 
00646 
00647         if(error)
00648         {
00649                 G_usage();
00650                 return -1;
00651         }
00652 
00653         if ( check_overwrite () )
00654             return -1;
00655 
00656         return(0) ;
00657 }
00658 
00659 
00680 int G_usage (void)
00681 {
00682         struct Option *opt ;
00683         struct Flag *flag ;
00684         char item[256];
00685         char *key_desc;
00686         int maxlen;
00687         int len, n;
00688         
00689         if (!pgm_name)          /* v.dave && r.michael */
00690             pgm_name = G_program_name ();
00691         if (!pgm_name)
00692             pgm_name = "??";
00693 
00694         if (module_info.description) {
00695                 fprintf (stderr, _("\nDescription:\n"));
00696                 fprintf (stderr, " %s\n", module_info.description);
00697         }
00698 
00699         fprintf (stderr, _("\nUsage:\n "));
00700 
00701         len = show(pgm_name,1);
00702 
00703         /* Print flags */
00704 
00705         if(n_flags)
00706         {
00707                 item[0] = ' ';
00708                 item[1] = '[';
00709                 item[2] = '-';
00710                 flag= &first_flag;
00711                 for(n = 3; flag != NULL; n++, flag = flag->next_flag)
00712                         item[n] = flag->key;
00713                 item[n++] = ']';
00714                 item[n] = 0;
00715                 len=show(item,len);
00716         }
00717 
00718         maxlen = 0;
00719         if(n_opts)
00720         {
00721                 opt= &first_option;
00722                 while(opt != NULL)
00723                 {
00724                         if (opt->key_desc != NULL)
00725                                 key_desc = opt->key_desc;
00726                         else if (opt->type == TYPE_STRING)
00727                                 key_desc = "name";
00728                         else
00729                                 key_desc = "value";
00730 
00731                         n = strlen (opt->key);
00732                         if (n > maxlen) maxlen = n;
00733 
00734                         strcpy(item," ");
00735                         if(!opt->required )
00736                                 strcat (item, "[");
00737                         strcat (item, opt->key);
00738                         strcat (item, "=");
00739                         strcat (item, key_desc);
00740                         if (opt->multiple)
00741                         {
00742                                 strcat(item,"[,");
00743                                 strcat(item,key_desc);
00744                                 strcat(item,",...]");
00745                         }
00746                         if(!opt->required )
00747                                 strcat(item,"]") ;
00748 
00749                         len = show(item,len);
00750 
00751                         opt = opt->next_opt ;
00752                 }
00753         }
00754         fprintf (stderr, "\n");
00755 
00756         /* Print help info for flags */
00757 
00758         if(n_flags)
00759         {
00760                 fprintf (stderr, _("\nFlags:\n"));
00761                 flag= &first_flag;
00762                 while(flag != NULL)
00763                 {
00764                         fprintf(stderr,"  -%c   ", flag->key) ;
00765 
00766                         if ( flag->label ) {
00767                             fprintf (stderr, "%s\n", flag->label );
00768                             if ( flag->description )
00769                                 fprintf (stderr, "      %s\n", flag->description);
00770 
00771                         } else if ( flag->description ) {
00772                             fprintf (stderr, "%s\n", flag->description);
00773                         }
00774 
00775                         flag = flag->next_flag ;
00776                 }
00777         }
00778 
00779         /* Print help info for options */
00780 
00781         if(n_opts)
00782         {
00783                 fprintf (stderr, _("\nParameters:\n"));
00784                 opt= &first_option;
00785                 while(opt != NULL)
00786                 {
00787                         fprintf (stderr, "  %*s   ", maxlen, opt->key );
00788 
00789                         if ( opt->label ) {
00790                             fprintf (stderr, "%s\n", opt->label );
00791                             if ( opt->description )
00792                                 fprintf (stderr, "           %*s\n", maxlen, opt->description);
00793 
00794                         } else if ( opt->description ) {
00795                             fprintf (stderr, "%s\n", opt->description);
00796                         }
00797 
00798                         if(opt->options)
00799                                 show_options(maxlen, opt->options) ;
00800                                 /*
00801                                 fprintf (stderr, "  %*s   options: %s\n", maxlen, " ",
00802                                         _(opt->options)) ;
00803                                 */
00804                         if(opt->def)
00805                                 fprintf (stderr, _("  %*s   default: %s\n"), maxlen, " ",
00806                                         opt->def) ;
00807                         
00808                         if(opt->descs) {
00809                             int i = 0;
00810 
00811                             while ( opt->opts[i] ) {
00812                                 fprintf (stderr, "  %*s   %s: ", maxlen, " ", opt->opts[i] );
00813 
00814                                 if (  opt->descs[i] )
00815                                     fprintf (stderr, "%s\n", opt->descs[i] );
00816                                 
00817                                 i++;
00818                             }
00819                         }
00820 
00821                         opt = opt->next_opt ;
00822                 }
00823         }
00824 
00825         return 0;
00826 }
00827 
00828 void print_escaped_for_xml (FILE * fp, char * str) {
00829         for (;*str;str++) {
00830                 switch (*str) {
00831                         case '&':
00832                                 fputs("&amp;", fp);
00833                                 break;
00834                         case '<':
00835                                 fputs("&lt;", fp);
00836                                 break;
00837                         case '>':
00838                                 fputs("&gt;", fp);
00839                                 break;
00840                         default:
00841                                 fputc(*str, fp);
00842                 }
00843         }
00844 }
00845 
00846 static void G_usage_xml (void)
00847 {
00848         struct Option *opt ;
00849         struct Flag *flag ;
00850         char *type;
00851         char *s, *top;
00852         int i;
00853         
00854         if (!pgm_name)          /* v.dave && r.michael */
00855             pgm_name = G_program_name ();
00856         if (!pgm_name)
00857             pgm_name = "??";
00858 
00859         fprintf(stdout, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
00860         fprintf(stdout, "<!DOCTYPE task SYSTEM \"grass-interface.dtd\">\n");
00861 
00862         fprintf(stdout, "<task name=\"%s\">\n", pgm_name);  
00863 
00864         if (module_info.label) {
00865                 fprintf(stdout, "\t<label>\n\t\t");
00866                 print_escaped_for_xml (stdout, module_info.label);
00867                 fprintf(stdout, "\n\t</label>\n");
00868         }
00869 
00870         if (module_info.description) {
00871                 fprintf(stdout, "\t<description>\n\t\t");
00872                 print_escaped_for_xml (stdout, module_info.description);
00873                 fprintf(stdout, "\n\t</description>\n");
00874         }
00875 
00876         /***** Don't use parameter-groups for now.  We'll reimplement this later 
00877          ***** when we have a concept of several mutually exclusive option
00878          ***** groups
00879         if (n_opts || n_flags)
00880                 fprintf(stdout, "\t<parameter-group>\n");
00881          *****
00882          *****
00883          *****/
00884         
00885         if(n_opts)
00886         {
00887                 opt= &first_option;
00888                 while(opt != NULL)
00889                 {
00890                         /* TODO: make this a enumeration type? */
00891                         switch (opt->type) {
00892                                 case TYPE_INTEGER:
00893                                         type = "integer";
00894                                         break ;
00895                                 case TYPE_DOUBLE:
00896                                         type = "float";
00897                                         break ;
00898                                 case TYPE_STRING:
00899                                         type = "string";
00900                                         break ;
00901                                 default:
00902                                         type = "string";
00903                                         break;
00904                         }
00905                         fprintf (stdout, "\t<parameter "
00906                                 "name=\"%s\" "
00907                                 "type=\"%s\" "
00908                                 "required=\"%s\" "
00909                                 "multiple=\"%s\">\n",
00910                                 opt->key,
00911                                 type,
00912                                 opt->required == YES ? "yes" : "no",
00913                                 opt->multiple == YES ? "yes" : "no");
00914 
00915                         if (opt->label) {
00916                                 fprintf(stdout, "\t\t<label>\n\t\t\t");
00917                                 print_escaped_for_xml(stdout, opt->label);
00918                                 fprintf(stdout, "\n\t\t</label>\n");
00919                         }
00920 
00921                         if (opt->description) {
00922                                 fprintf(stdout, "\t\t<description>\n\t\t\t");
00923                                 print_escaped_for_xml(stdout, opt->description);
00924                                 fprintf(stdout, "\n\t\t</description>\n");
00925                         }
00926 
00927                         if (opt->key_desc)
00928                         {
00929                                 fprintf (stdout, "\t\t<keydesc>\n");
00930                                 top = G_calloc (strlen (opt->key_desc) + 1, 1);
00931                                 strcpy (top, opt->key_desc);
00932                                 s = strtok (top, ",");
00933                                 for (i = 1; s != NULL; i++)
00934                                 {
00935                                         fprintf (stdout, "\t\t\t<item order=\"%d\">", i);
00936                                         print_escaped_for_xml (stdout, s);
00937                                         fprintf (stdout, "</item>\n");
00938                                         s = strtok (NULL, ",");
00939                                 }
00940                                 fprintf (stdout, "\t\t</keydesc>\n");
00941                                 G_free (top);
00942                         }
00943                         
00944                         if (opt->gisprompt)
00945                         {
00946                                 const char *atts[] = {"age", "element", "prompt", NULL};
00947                                 top = G_calloc (strlen (opt->gisprompt) + 1, 1);
00948                                 strcpy (top, opt->gisprompt);
00949                                 s = strtok (top, ",");
00950                                 fprintf (stdout, "\t\t<gisprompt ");
00951                                 for (i = 0; s != NULL && atts[i] != NULL; i++)
00952                                 {
00953                                         fprintf (stdout, "%s=\"%s\" ", atts[i], s);
00954                                         s = strtok (NULL, ",");
00955                                 }
00956                                 fprintf (stdout, "/>\n");
00957                                 G_free (top);
00958                         }
00959 
00960                         if(opt->def) {
00961                                 fprintf(stdout, "\t\t\t<default>\n\t\t\t");
00962                                 print_escaped_for_xml(stdout, opt->def);
00963                                 fprintf(stdout, "\n\t\t\t</default>\n");
00964                         }
00965                         if(opt->descs) {
00966                             int i = 0;
00967 
00968                             while ( opt->opts[i] ) {
00969                                 fprintf(stdout, "<DD><b>%s</b>: ", opt->opts[i]);
00970 
00971                                 if (  opt->descs[i] )
00972                                     fprintf (stdout, "%s", opt->descs[i] );
00973                                 
00974                                 fprintf(stdout, "</DD>\n");
00975                                 
00976                                 i++;
00977                             }
00978                         }
00979 
00980                         if(opt->options) {
00981                                 i = 0;
00982                                 fprintf(stdout, "\t\t<values>\n");
00983                                 while ( opt->opts[i] ) {
00984                                         fprintf(stdout, "\t\t\t<value>\n");
00985                                         fprintf(stdout, "\t\t\t\t<name>");
00986                                         print_escaped_for_xml(stdout, opt->opts[i]);
00987                                         fprintf(stdout, "</name>\n");
00988                                         if(opt->descs && opt->opts[i]) {
00989                                             fprintf(stdout, "\t\t\t\t<description>");
00990                                             print_escaped_for_xml(stdout, opt->descs[i]);
00991                                             fprintf(stdout, "</description>");
00992                                         }
00993                                         fprintf(stdout, "\t\t\t</value>\n");
00994                                         i++;
00995                                 }
00996                                 fprintf(stdout, "\t\t</values>\n");
00997                         }
00998 
00999                         /* TODO:
01000                          * add something like
01001                          *       <range min="xxx" max="xxx"/>
01002                          * to <values>
01003                          * - key_desc?
01004                          * - there surely are some more. which ones?
01005                          */
01006 
01007                         opt = opt->next_opt ;
01008                         fprintf (stdout, "\t</parameter>\n");
01009                 }
01010         }
01011 
01012         
01013         if(n_flags)
01014         {
01015                 flag= &first_flag;
01016                 while(flag != NULL)
01017                 {
01018                         fprintf (stdout, "\t<flag name=\"%c\">\n", flag->key);
01019 
01020                         if (flag->label) {
01021                                 fprintf(stdout, "\t\t<label>\n\t\t\t");
01022                                 print_escaped_for_xml(stdout, flag->label);
01023                                 fprintf(stdout, "\n\t\t</label>\n");
01024                         }
01025 
01026                         if (flag->description) {
01027                                 fprintf(stdout, "\t\t<description>\n\t\t\t");
01028                                 print_escaped_for_xml(stdout, flag->description);
01029                                 fprintf(stdout, "\n\t\t</description>\n");
01030                         }
01031                         flag = flag->next_flag ;
01032                         fprintf (stdout, "\t</flag>\n");
01033                 }
01034         }
01035 
01036         /***** Don't use parameter-groups for now.  We'll reimplement this later 
01037          ***** when we have a concept of several mutually exclusive option
01038          ***** groups
01039         if (n_opts || n_flags)
01040                 fprintf(stdout, "\t</parameter-group>\n");
01041          *****
01042          *****
01043          *****/
01044 
01045         fprintf(stdout, "</task>\n");
01046 }
01047 
01048 static void G_usage_html (void)
01049 {
01050         struct Option *opt ;
01051         struct Flag *flag ;
01052         char *type;
01053         char *newbuf;
01054         
01055         if (!pgm_name)          /* v.dave && r.michael */
01056             pgm_name = G_program_name ();
01057         if (!pgm_name)
01058             pgm_name = "??";
01059 
01060         fprintf(stdout, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n");
01061         fprintf(stdout, "<html>\n<head>\n"),
01062         fprintf(stdout, "<title>%s</title>\n", pgm_name);
01063         fprintf(stdout, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n"),
01064         fprintf(stdout, "</head>\n"),
01065         fprintf(stdout, "<body bgcolor=\"white\">\n");
01066 
01067         fprintf(stdout, "<h2>NAME</h2>\n");
01068         fprintf(stdout, "<em><b>%s</b></em> ", pgm_name);
01069 
01070         if (module_info.description) {
01071                 fprintf(stdout, " - ");
01072                 fprintf(stdout, "%s", module_info.description);
01073                 fprintf(stdout, "\n");
01074         }
01075         fprintf(stdout, "<h2>SYNOPSIS</h2>\n");
01076         fprintf(stdout, "<b>%s</b><br>\n", pgm_name);
01077         fprintf(stdout, "<b>%s help</b><br>\n", pgm_name);
01078 
01079         fprintf(stdout, "<b>%s</b>", pgm_name);
01080 
01081         /* print short version first */
01082         if(n_flags)
01083         {
01084                 flag= &first_flag;
01085                 fprintf(stdout, " [-<b>");
01086                 while(flag != NULL)
01087                 {
01088                         fprintf (stdout, "%c", flag->key);
01089                         flag = flag->next_flag ;
01090                 }
01091                 fprintf(stdout, "</b>] ");
01092         }
01093         else
01094           fprintf(stdout, " ");
01095 
01096         /* print short version first */
01097         if(n_opts)
01098         {
01099                 opt= &first_option;
01100 
01101                 while(opt != NULL)
01102                 {
01103                         if (opt->key_desc != NULL)
01104                             type = opt->key_desc;
01105                         else switch (opt->type) {
01106                                 case TYPE_INTEGER:
01107                                         type = "integer";
01108                                         break ;
01109                                 case TYPE_DOUBLE:
01110                                         type = "float";
01111                                         break ;
01112                                 case TYPE_STRING:
01113                                         type = "string";
01114                                         break ;
01115                                 default:
01116                                         type = "string";
01117                                         break;
01118                         }
01119                         if( !opt->required )
01120                              fprintf(stdout," [");
01121                         fprintf(stdout,
01122                                 "<b>%s</b>=<em>%s</em>", opt->key, type);
01123                         if (opt->multiple)
01124                         {
01125                                 fprintf(stdout,"[,<i>%s</i>,...]", type);
01126                         }
01127                         if( !opt->required )
01128                              fprintf(stdout,"] ");
01129 
01130 
01131                         opt = opt->next_opt ;
01132                         fprintf(stdout," ");
01133                 }
01134                 fprintf(stdout, "\n");
01135         }
01136 
01137         /* now long version */
01138         fprintf(stdout, "\n");
01139         if(n_flags)
01140         {
01141                 flag= &first_flag;
01142                 fprintf(stdout, "<h3>Flags:</h3>\n");
01143                 fprintf(stdout, "<DL>\n");
01144                 while(flag != NULL)
01145                 {
01146                         fprintf (stdout, "<DT><b>-%c</b>\n", flag->key);
01147 
01148                         if ( flag->label ) {
01149                                 fprintf(stdout, "<DD>");
01150                                 fprintf(stdout, "%s", flag->label);
01151                                 fprintf(stdout, "</DD>\n");
01152                         }
01153 
01154                         if (flag->description) {
01155                                 fprintf(stdout, "<DD>");
01156                                 fprintf(stdout, "%s", flag->description);
01157                                 fprintf(stdout, "</DD>\n");
01158                         }
01159 
01160                         flag = flag->next_flag ;
01161                         fprintf (stdout, "\n");
01162                 }
01163                 fprintf(stdout, "</DL>\n");
01164         }
01165 
01166         fprintf(stdout, "\n");
01167         if(n_opts)
01168         {
01169                 opt= &first_option;
01170                 fprintf(stdout, "<h3>Parameters:</h3>\n");
01171                 fprintf(stdout, "<DL>\n");
01172                 
01173                 while(opt != NULL)
01174                 {
01175                         /* TODO: make this a enumeration type? */
01176                         if (opt->key_desc != NULL)
01177                             type = opt->key_desc;
01178                         else switch (opt->type) {
01179                                 case TYPE_INTEGER:
01180                                         type = "integer";
01181                                         break ;
01182                                 case TYPE_DOUBLE:
01183                                         type = "float";
01184                                         break ;
01185                                 case TYPE_STRING:
01186                                         type = "string";
01187                                         break ;
01188                                 default:
01189                                         type = "string";
01190                                         break;
01191                         }
01192                         fprintf(stdout,
01193                                 "<DT><b>%s</b>=<em>%s", opt->key, type);
01194                         if (opt->multiple) {
01195                                 fprintf(stdout,"[,<i>%s</i>,...]", type);
01196                         }
01197                         fprintf(stdout,"</em>\n");
01198 
01199                         if ( opt->label ) {
01200                                 fprintf(stdout, "<DD>");
01201                                 fprintf(stdout, "%s", opt->label);
01202                                 fprintf(stdout, "</DD>\n");
01203                         }
01204                         if (opt->description) {
01205                                 fprintf(stdout, "<DD>");
01206                                 newbuf = G_str_replace(opt->description, "\n","<br>");
01207                                 if (newbuf) {
01208                                         fprintf(stdout, "%s", newbuf);
01209                                         G_free(newbuf);
01210                                 } else
01211                                         fprintf(stdout, "%s", opt->description);
01212                                 fprintf(stdout, "</DD>\n");
01213                                 
01214                         }
01215 
01216                         if(opt->options) {
01217                                 fprintf(stdout, "<DD>Options: <em>");
01218                                 fprintf(stdout, "%s", opt->options);
01219                                 fprintf(stdout, "</em></DD>\n");
01220                         }
01221 
01222                         if(opt->def) {
01223                                 fprintf(stdout, "<DD>Default: <em>");
01224                                 fprintf(stdout, "%s", opt->def);
01225                                 fprintf(stdout, "</em></DD>\n");
01226                         }
01227 
01228                         if(opt->descs) {
01229                             int i = 0;
01230 
01231                             while ( opt->opts[i] ) {
01232                                 fprintf(stdout, "<DD><b>%s</b>: ", opt->opts[i]);
01233 
01234                                 if (  opt->descs[i] )
01235                                     fprintf (stdout, "%s", opt->descs[i] );
01236                                 
01237                                 fprintf(stdout, "</DD>\n");
01238                                 
01239                                 i++;
01240                             }
01241                         }
01242 
01243                         opt = opt->next_opt ;
01244                         fprintf (stdout, "\n");
01245                 }
01246                 fprintf(stdout, "</DL>\n");
01247         }
01248         
01249     fprintf(stdout, "</body></html>\n");
01250 }
01251 
01252 static void generate_tcl(FILE *fp)
01253 {
01254         char *type, *desc;
01255         int optn;
01256 
01257         fprintf(fp, "begin_dialog {%s} {%s}\n", pgm_name,
01258                 module_info.label ? module_info.label : 
01259                 module_info.description ? module_info.description : "");
01260 
01261         optn = 1;
01262     
01263         if (n_opts)
01264         {
01265                 struct Option *opt;
01266 
01267                 for (opt = &first_option; opt; opt = opt->next_opt, optn++)
01268                 {
01269                         if (opt->key_desc != NULL)
01270                             type = opt->key_desc;
01271                         else switch (opt->type)
01272                         {
01273                         case TYPE_INTEGER:
01274                                 type = "integer";
01275                                 break;
01276                         case TYPE_DOUBLE:
01277                                 type = "float";
01278                                 break;
01279                         case TYPE_STRING:
01280                                 type = "string";
01281                                 break;
01282                         default:
01283                                 type = "string";
01284                                 break;
01285                         }
01286 
01287                         desc = opt->label ? opt->label : opt->description;
01288 
01289                         fprintf(fp, "add_option %d {\n", optn);
01290                         fprintf(fp, " name {%s}\n", opt->key);
01291                         fprintf(fp, " type {%s}\n", type);
01292                         fprintf(fp, " multi %d\n", opt->multiple);
01293                         fprintf(fp, " desc {%s}\n", desc);
01294                         fprintf(fp, " required %d\n", opt->required);
01295                         fprintf(fp, " options {%s}\n", opt->options ? opt->options : "");
01296                         fprintf(fp, " answer {%s}\n", opt->answer ? opt->answer : "");
01297                         fprintf(fp, " prompt {%s}\n", opt->gisprompt ? opt->gisprompt : "");
01298                         fprintf(fp, "}\n");
01299                 }
01300         }
01301 
01302         if (n_flags)
01303         {
01304                 struct Flag *flag;
01305 
01306                 for (flag = &first_flag; flag; flag = flag->next_flag, optn++) {
01307                         desc = flag->label ? flag->label : flag->description;
01308                         fprintf(fp, "add_flag %d {%c} {%s}\n", optn, flag->key, desc);
01309                 }
01310         }
01311    
01312         fprintf(fp, "end_dialog %d\n", optn - 1);
01313 }
01314 
01315 /* Build gui */
01316 static void G_gui (void)
01317 {
01318         FILE *fp;
01319 
01320         if (!pgm_name)
01321                 pgm_name = G_program_name ();
01322         if (!pgm_name)
01323                 pgm_name = "??";
01324 
01325         if (getenv("GRASS_DEBUG_GUI"))
01326                 fp = popen("tee gui_dump.tcl | $GRASS_WISH", "w");
01327         else
01328                 fp = popen("$GRASS_WISH", "w");
01329 
01330         if (!fp)
01331                 G_fatal_error("unable to spawn wish");
01332 
01333         fprintf(fp, "source $env(GISBASE)/etc/gui.tcl\n");
01334 
01335         generate_tcl(fp);
01336 
01337         pclose(fp);
01338 }
01339 
01340 /* Send Tcl/Tk code to tcltkgrass */
01341 static void G_tcltk (void)
01342 {
01343         if (!pgm_name)
01344                 pgm_name = G_program_name ();
01345         if (!pgm_name)
01346                 pgm_name = "??";
01347 
01348         generate_tcl(stdout);
01349 }
01350 
01351 /**************************************************************************
01352  *
01353  * The remaining routines are all local (static) routines used to support
01354  * the parsing process.
01355  *
01356  **************************************************************************/
01357 
01358 static int show_options(int maxlen,char *str)
01359 {
01360         char buff[1024] ;
01361         char *p1, *p2 ;
01362         int totlen, len ;
01363 
01364         strcpy(buff, str) ;
01365         fprintf (stderr, _("  %*s   options: "), maxlen, " ") ;
01366         totlen = maxlen + 13 ;
01367         p1 = buff ;
01368         while( (p2 = G_index(p1, ',')) )
01369         {
01370                 *p2 = '\0' ;
01371                 len = strlen(p1) + 1 ;
01372                 if ((len + totlen) > 76)
01373                 {
01374                         totlen = maxlen + 13 ;
01375                         fprintf(stderr, "\n %*s", maxlen + 13, " ") ;
01376                 }
01377                 fprintf (stderr, "%s,",  p1) ;
01378                 totlen += len ;
01379                 p1 = p2 + 1 ;
01380         }
01381         len = strlen(p1) ;
01382         if ((len + totlen) > 76 )
01383                 fprintf(stderr, "\n %*s", maxlen + 13, " ") ;
01384         fprintf (stderr, "%s\n",  p1) ;
01385 
01386         return 0;
01387 }
01388 
01389 static int show (char *item, int len)
01390 {
01391         int n;
01392 
01393         n = strlen (item)+(len>0);
01394         if (n + len > 76)
01395         {
01396                 if (len)
01397                         fprintf (stderr, "\n  ");
01398                 len = 0;
01399         }
01400         fprintf (stderr, "%s", item);
01401         return n+len;
01402 }
01403 
01404 static int set_flag (int f)
01405 {
01406         struct Flag *flag ;
01407 
01408         /* Flag is not valid if there are no flags to set */
01409 
01410         if(!n_flags)
01411         {
01412                 fprintf(stderr,_("Sorry, <%c> is not a valid flag\n"), f) ;
01413                 return(1) ;
01414         }
01415 
01416         /* Find flag with corrrect keyword */
01417 
01418         flag= &first_flag;
01419         while(flag != NULL)
01420         {
01421                 if( flag->key == f)
01422                 {
01423                         flag->answer = 1 ;
01424                         return(0) ;
01425                 }
01426                 flag = flag->next_flag ;
01427         }
01428 
01429         fprintf(stderr,_("Sorry, <%c> is not a valid flag\n"), f) ;
01430         return(1) ;
01431 }
01432 
01433 /* contents() is used to find things strings with characters like commas and
01434  * dashes.
01435  */
01436 static int contains (char *s, int c)
01437 {
01438         while(*s)
01439         {
01440                 if(*s == c)
01441                         return(1) ;
01442                 s++ ;
01443         }
01444         return(0) ;
01445 }
01446 
01447 static int set_option (char *string)
01448 {
01449         struct Option *at_opt ;
01450         struct Option *opt ;
01451         int got_one ;
01452         size_t key_len ;
01453         char the_key[64] ;
01454         char *ptr ;
01455 
01456         for(ptr=the_key; *string!='='; ptr++, string++)
01457                 *ptr = *string ;
01458         *ptr = '\0' ;
01459         string++ ;
01460 
01461         /* Find option with best keyword match */
01462         got_one = 0 ;
01463         key_len = strlen(the_key) ;
01464         for(at_opt= &first_option; at_opt != NULL; at_opt=at_opt->next_opt)
01465         {
01466                 if (strncmp(the_key,at_opt->key,key_len))
01467                         continue ;
01468 
01469                 got_one++;
01470                 opt = at_opt ;
01471 
01472                 /* changed 1/15/91 -dpg   old code is in parser.old */
01473                 /* overide ambiguous check, if we get an exact match */
01474                 if (strlen (at_opt->key) == key_len)    
01475                 {
01476                     opt = at_opt;
01477                     got_one = 1;
01478                     break;
01479                 }
01480         }
01481 
01482         if (got_one > 1)
01483         {
01484                 fprintf(stderr,_("Sorry, <%s=> is ambiguous\n"), the_key) ;
01485                 return(1) ;
01486         }
01487 
01488         /* If there is no match, complain */
01489         if(got_one == 0)
01490         {
01491                 fprintf(stderr,_("Sorry, <%s> is not a valid parameter\n"),
01492                         the_key) ;
01493                 return(1) ;
01494         }
01495                 
01496         /* Allocate memory where answer is stored */
01497         if (opt->count++)
01498         {
01499                 opt->answer = (char *)G_realloc (opt->answer,
01500                         strlen (opt->answer)+strlen(string)+2);
01501                 strcat (opt->answer, ",");
01502                 strcat (opt->answer, string);
01503         }
01504         else
01505                 opt->answer = G_store(string) ;
01506         return(0) ;
01507 }
01508 
01509 static int check_opts (void)
01510 {
01511         struct Option *opt ;
01512         int error ;
01513         int ans ;
01514 
01515         error = 0 ;
01516 
01517         if(! n_opts)
01518                 return(0) ;
01519 
01520         opt= &first_option;
01521         while(opt != NULL)
01522         {
01523                 /* Check answer against options if any */
01524 
01525                 if(opt->options && opt->answer)
01526                 {
01527                         if(opt->multiple == 0)
01528                                 error += check_an_opt(opt->key, opt->type,
01529                                     opt->options, opt->answer) ;
01530                         else
01531                         {
01532                                 for(ans=0; opt->answers[ans] != '\0'; ans++)
01533                                         error += check_an_opt(opt->key, opt->type,
01534                                             opt->options, opt->answers[ans]) ;
01535                         }
01536                 }
01537 
01538                 /* Check answer against user's check subroutine if any */
01539 
01540                 if(opt->checker)
01541                         error += opt->checker(opt->answer) ;
01542 
01543                 opt = opt->next_opt ;
01544         }
01545         return(error) ;
01546 }
01547 
01548 static int check_an_opt (char *key, int type, char *options, char *answer)
01549 {
01550         int error ;
01551 
01552         error = 0 ;
01553 
01554         switch(type)
01555         {
01556         case TYPE_INTEGER:
01557                 error = check_int(answer,options) ;
01558                 break ;
01559         case TYPE_DOUBLE:
01560                 error = check_double(answer,options) ;
01561                 break ;
01562         case TYPE_STRING:
01563                 error = check_string(answer,options) ;
01564                 break ;
01565 /*
01566         case TYPE_COORDINATE:
01567                 error = check_coor(answer,options) ;
01568                 break ;
01569 */
01570         }
01571         switch(error)
01572         {
01573         case 0:
01574                 break ;
01575         case BAD_SYNTAX:
01576                 fprintf(stderr,_("\nError: illegal range syntax for parameter <%s>\n"),
01577                     key) ;
01578                 fprintf(stderr,_("       Presented as: %s\n"), options) ;
01579                 break ;
01580         case OUT_OF_RANGE:
01581                 fprintf(stderr,_("\nError: value <%s> out of range for parameter <%s>\n"),
01582                     answer, key) ;
01583                 fprintf(stderr,_("       Legal range: %s\n"), options) ;
01584                 break ;
01585         case MISSING_VALUE:
01586                 fprintf(stderr,_("\nError: Missing value for parameter <%s>\n"),
01587                     key) ;
01588         }
01589         return(error) ;
01590 }
01591 
01592 static int check_int (char *ans, char *opts)
01593 {
01594         int d, lo, hi;
01595 
01596         if (1 != sscanf(ans,"%d", &d))
01597                 return(MISSING_VALUE) ;
01598 
01599         if (contains(opts, '-'))
01600         {
01601                 if (2 != sscanf(opts,"%d-%d",&lo, &hi))
01602                         return(BAD_SYNTAX) ;
01603                 if (d < lo || d > hi)
01604                         return(OUT_OF_RANGE) ;
01605                 else
01606                         return(0) ;
01607         }
01608         else if (contains(opts, ','))
01609         {
01610                 for(;;)
01611                 {
01612                         if (1 != sscanf(opts,"%d",&lo))
01613                                 return(BAD_SYNTAX) ;
01614                         if (d == lo)
01615                                 return(0) ;
01616                         while(*opts != '\0' && *opts != ',')
01617                                 opts++ ;
01618                         if (*opts == '\0')
01619                                 return(OUT_OF_RANGE) ;
01620                         if (*(++opts) == '\0')
01621                                 return(OUT_OF_RANGE) ;
01622                 }
01623         }
01624         else
01625         {
01626                 if (1 != sscanf(opts,"%d",&lo))
01627                         return(BAD_SYNTAX) ;
01628                 if (d == lo)
01629                         return(0) ;
01630                 return(OUT_OF_RANGE) ;
01631         }
01632 }
01633 
01634 /*
01635 static int
01636 check_coor(ans, opts)
01637 char *ans ;
01638 char *opts ;
01639 {
01640         double xd, xlo, xhi;
01641         double yd, ylo, yhi;
01642 
01643         if (1 != sscanf(ans,"%lf,%lf", &xd, &yd))
01644                 return(MISSING_VALUE) ;
01645 
01646         if (contains(opts, '-'))
01647         {
01648                 if (2 != sscanf(opts,"%lf-%lf,%lf-%lf",&xlo, &xhi, &ylo, &yhi))
01649                         return(BAD_SYNTAX) ;
01650                 if (xd < xlo || xd > xhi)
01651                         return(OUT_OF_RANGE) ;
01652                 if (yd < ylo || yd > yhi)
01653                         return(OUT_OF_RANGE) ;
01654                 return(0) ;
01655         }
01656         return(BAD_SYNTAX) ;
01657 }
01658 */
01659 
01660 static int check_double (char *ans, char *opts)
01661 {
01662         double d, lo, hi;
01663 
01664         if (1 != sscanf(ans,"%lf", &d))
01665                 return(MISSING_VALUE) ;
01666 
01667         if (contains(opts, '-'))
01668         {
01669                 if (2 != sscanf(opts,"%lf-%lf",&lo, &hi))
01670                         return(BAD_SYNTAX) ;
01671                 if (d < lo || d > hi)
01672                         return(OUT_OF_RANGE) ;
01673                 else
01674                         return(0) ;
01675         }
01676         else if (contains(opts, ','))
01677         {
01678                 for(;;)
01679                 {
01680                         if (1 != sscanf(opts,"%lf",&lo))
01681                                 return(BAD_SYNTAX) ;
01682                         if (d == lo)
01683                                 return(0) ;
01684                         while(*opts != '\0' && *opts != ',')
01685                                 opts++ ;
01686                         if (*opts == '\0')
01687                                 return(OUT_OF_RANGE) ;
01688                         if (*(++opts) == '\0')
01689                                 return(OUT_OF_RANGE) ;
01690                 }
01691         }
01692         else
01693         {
01694                 if (1 != sscanf(opts,"%lf",&lo))
01695                         return(BAD_SYNTAX) ;
01696                 if (d == lo)
01697                         return(0) ;
01698                 return(OUT_OF_RANGE) ;
01699         }
01700 }
01701 
01702 static int check_string (char *ans, char *opts)
01703 {
01704         if (*opts == '\0')
01705                 return(0) ;
01706 
01707         if (contains(opts, ','))
01708         {
01709                 for(;;)
01710                 {
01711                         if ((! strncmp(ans, opts, strlen(ans)))
01712                             && ( *(opts+strlen(ans)) == ','
01713                                ||  *(opts+strlen(ans)) == '\0'))
01714                                 return(0) ;
01715                         while(*opts != '\0' && *opts != ',')
01716                                 opts++ ;
01717                         if (*opts == '\0')
01718                                 return(OUT_OF_RANGE) ;
01719                         if (*(++opts) == '\0')
01720                                 return(OUT_OF_RANGE) ;
01721                 }
01722         }
01723         else
01724         {
01725                 if (! strcmp(ans, opts))
01726                         return(0) ;
01727                 return(OUT_OF_RANGE) ;
01728         }
01729 }
01730 
01731 static int check_required (void)
01732 {
01733         struct Option *opt ;
01734         int err ;
01735 
01736         err = 0 ;
01737 
01738         if(! n_opts)
01739                 return(0) ;
01740 
01741         opt= &first_option;
01742         while(opt != NULL)
01743         {
01744                 if(opt->required && opt->answer == NULL)
01745                 {
01746                         fprintf(stderr,_("\nERROR: Required parameter <%s> not set:\n    (%s).\n"),
01747                             opt->key, opt->description) ;
01748                         err++ ;
01749                 }
01750                 opt = opt->next_opt ;
01751         }
01752 
01753         return(err) ;
01754 }
01755 
01756 static int split_opts (void)
01757 {
01758         struct Option *opt ;
01759         char *ptr1 ;
01760         char *ptr2 ;
01761         int allocated ;
01762         int ans_num ;
01763         int len ;
01764 
01765 
01766         if(! n_opts)
01767                 return 0;
01768 
01769         opt= &first_option;
01770         while(opt != NULL)
01771         {
01772                 if (/*opt->multiple && */(opt->answer != NULL))
01773                 {
01774                         /* Allocate some memory to store array of pointers */
01775                         allocated = 10 ;
01776                         opt->answers = (char **)G_malloc(allocated * sizeof(char *)) ;
01777 
01778                         ans_num = 0 ;
01779                         ptr1 = opt->answer ;
01780                         opt->answers[ans_num] = NULL ;
01781 
01782                         for(;;)
01783                         {
01784                                 for(len=0, ptr2=ptr1; *ptr2 != '\0' && *ptr2 != ','; ptr2++, len++)
01785                                         ;
01786 
01787                                 if (len > 0)        /* skip ,, */
01788                                 {
01789                                         opt->answers[ans_num]=(char *)G_malloc(len+1) ;
01790                                         G_copy(opt->answers[ans_num], ptr1, len) ;
01791                                         opt->answers[ans_num][len] = 0;
01792 
01793                                         ans_num++ ;
01794 
01795                                         if(ans_num >= allocated)
01796                                         {
01797                                                 allocated += 10 ;
01798                                                 opt->answers =
01799                                                     (char **)G_realloc((char *)opt->answers,
01800                                                     allocated * sizeof(char *)) ;
01801                                         }
01802 
01803                                         opt->answers[ans_num] = NULL ;
01804                                 }
01805 
01806                                 if(*ptr2 == '\0')
01807                                         break ;
01808 
01809                                 ptr1 = ptr2+1 ;
01810 
01811                                 if(*ptr1 == '\0')
01812                                         break ;
01813                         }
01814                 }
01815                 opt = opt->next_opt ;
01816         }
01817 
01818         return 0;
01819 }
01820 
01821 static int check_multiple_opts (void)
01822 {
01823         struct Option *opt ;
01824         char *ptr ;
01825         int n_commas ;
01826         int n ;
01827         int error ;
01828 
01829         if(! n_opts)
01830                 return (0) ;
01831 
01832         error = 0 ;
01833         opt= &first_option;
01834         while(opt != NULL)
01835         {
01836                 if ((opt->answer != NULL) && (opt->key_desc != NULL))
01837                 {
01838                         /* count commas */
01839                         n_commas = 1 ;
01840                         for(ptr=opt->key_desc; *ptr!='\0'; ptr++)
01841                                 if (*ptr == ',')
01842                                         n_commas++ ;
01843                         /* count items */
01844                         for(n=0;opt->answers[n] != '\0';n++)
01845                                 ;
01846                         /* if not correct multiple of items */
01847                         if(n % n_commas)
01848                         {
01849                                 fprintf(stderr,_("\nError: option <%s> must be provided in multiples of %d\n"),
01850                                         opt->key, n_commas) ;
01851                                 fprintf(stderr,_("       You provided %d items:\n"), n) ;
01852                                 fprintf(stderr,"       %s\n", opt->answer) ;
01853                                 error++ ;
01854                         }
01855                 }
01856                 opt = opt->next_opt ;
01857         }
01858         return(error) ;
01859 }
01860 
01861 /* Check for all 'new' if element already exists */
01862 static int check_overwrite (void)
01863 {
01864         struct Option *opt ;
01865         char age[64] ;
01866         char element[64] ;
01867         char *ptr1, *ptr2 ;
01868         int error = 0;
01869         char *overstr;
01870         int over;
01871 
01872         if(! n_opts)
01873                 return (0) ;
01874 
01875         over = 0;
01876         if ( (overstr = G__getenv ( "OVERWRITE" )) ) {
01877             over = atoi ( overstr );
01878         }
01879 
01880         if ( overwrite || over )
01881             module_info.overwrite = 1;
01882 
01883         opt= &first_option;
01884         while(opt != NULL)
01885         {
01886                 if ((opt->answer != NULL) && (opt->gisprompt != NULL))
01887                 {
01888                         for(ptr1=opt->gisprompt,ptr2=age; *ptr1!='\0'; ptr1++, ptr2++)
01889                         {
01890                                 if (*ptr1 == ',')
01891                                         break ;
01892                                 *ptr2 = *ptr1 ;
01893                         }
01894                         *ptr2 = '\0' ;
01895                         for(ptr1++, ptr2=element; *ptr1!='\0'; ptr1++, ptr2++)
01896                         {
01897                                 if (*ptr1 == ',')
01898                                         break ;
01899                                 *ptr2 = *ptr1 ;
01900                         }
01901                         *ptr2 = '\0' ;
01902             
01903                         if ( strcmp(age,"new") == 0 ) {
01904                             if ( G_find_file (element, opt->answer, G_mapset()) ) /* found */
01905                             {
01906                                 if ( !overwrite && !over ) { 
01907                                     fprintf(stderr,_("Error: option <%s>: <%s> exists.\n"), 
01908                                                    opt->key, opt->answer );
01909 
01910                                     error = 1;
01911                                 }
01912                             }
01913                         }
01914                 }
01915                 opt = opt->next_opt ;
01916         }
01917 
01918         return(error) ;
01919 }
01920 
01921 static int interactive( char *command)
01922 {
01923         struct Item *item ;
01924 
01925         /* Query for flags */
01926 
01927         if(!n_items)
01928         {
01929                 fprintf(stderr,"Programmer error: no flags or options\n") ;
01930                 exit(-1) ;
01931         }
01932 
01933         for (item= &first_item ;;)
01934         {
01935                 if (item->flag)
01936                         interactive_flag(item->flag) ;
01937                 else if (item->option)
01938                         interactive_option(item->option) ;
01939                 else
01940                         break ;
01941 
01942                 item=item->next_item ;
01943 
01944                 if (item == NULL)
01945                         break ;
01946         }
01947 
01948         return 0;
01949 }
01950 
01951 static int interactive_flag( struct Flag *flag )
01952 {
01953         char buff[1024] ;
01954         fprintf(stderr, _("\nFLAG: Set the following flag?\n")) ;
01955         sprintf(buff,"    %s?", flag->description) ;
01956         flag->answer = G_yes(buff, 0) ;
01957 
01958         return 0;
01959 }
01960 
01961 static int interactive_option(struct Option *opt )
01962 {
01963         char buff[1024],*bptr ;
01964         char buff2[1024] ;
01965         int set_one ;
01966 
01967         fprintf(stderr,_("\nOPTION:   %s\n"), opt->description) ;
01968         fprintf(stderr,_("     key: %s\n"), opt->key) ;
01969         if (opt->key_desc)
01970         fprintf(stderr,_("  format: %s\n"), opt->key_desc) ;
01971         if (opt->def)
01972         fprintf(stderr,_(" default: %s\n"), opt->def) ;
01973         fprintf(stderr,_("required: %s\n"), opt->required ? "YES" : "NO") ;
01974         if (opt->multiple)
01975         fprintf(stderr,_("multiple: %s\n"), opt->multiple ? "YES" : "NO") ;
01976         if (opt->options)
01977         fprintf(stderr,_(" options: %s\n"), opt->options) ;
01978         /*
01979         show_options(0, opt->options) ;
01980         */
01981 
01982         set_one = 0 ;
01983         for(;;)
01984         {
01985            *buff='\0' ;
01986            if(opt->gisprompt)
01987                 gis_prompt(opt, buff) ;
01988            else
01989            {
01990                 fprintf(stderr,_("enter option > ")) ;
01991                 if(fgets(buff,1024,stdin) == 0) exit(1); ;
01992                 bptr = buff;  /* strip newline  */
01993                 while(*bptr) {if(*bptr=='\n') *bptr='\0'; bptr++;}
01994 
01995            }
01996 
01997            if(strlen(buff) != 0)
01998            {
01999                 if(opt->options)
02000                 /* then check option */
02001                 {
02002                     if (check_an_opt(opt->key, opt->type, opt->options, buff))
02003                     {
02004                         if (G_yes(_("   Try again? "), 1))
02005                                 continue ;
02006                         else
02007                                 exit(-1) ;
02008                     }
02009                 }
02010                 if (opt->checker)
02011                     if (opt->checker(buff))
02012                     {
02013                             fprintf(stderr,_("Sorry, %s is not accepted.\n"), buff) ;
02014                             *buff = '\0' ;
02015                             if (G_yes(_("   Try again? "), 1))
02016                                 continue ;
02017                             else
02018                                 exit(-1) ;
02019                     }
02020 
02021                 sprintf(buff2,"%s=%s", opt->key, buff) ;
02022                 if(! opt->gisprompt)
02023                 {
02024                         fprintf(stderr,_("\nYou have chosen:\n  %s\n"), buff2) ;
02025                         if (G_yes(_("Is this correct? "), 1))
02026                         {
02027                                 set_option(buff2) ;
02028                                 set_one++ ;
02029                         }
02030                 }
02031                 else 
02032                 {
02033                         set_option(buff2) ;
02034                         set_one++ ;
02035                 }
02036            } /* if strlen(buf ) !=0 */
02037 
02038            if ((strlen(buff) == 0) && opt->required && (set_one == 0))
02039                 exit(-1) ;
02040            if ((strlen(buff) == 0) && (set_one > 0) && opt->multiple )
02041                 break ;
02042            if ((strlen(buff) == 0) && !opt->required)
02043                 break ;
02044            if ((set_one == 1) && !opt->multiple)
02045                 break ;
02046         }
02047         return(0) ;
02048 }
02049 
02050 static int gis_prompt (struct Option *opt, char *buff)
02051 {
02052         char age[64] ;
02053         char element[64] ;
02054         char desc[64] ;
02055         char *ptr1, *ptr2 ;
02056 
02057         for(ptr1=opt->gisprompt,ptr2=age; *ptr1!='\0'; ptr1++, ptr2++)
02058         {
02059                 if (*ptr1 == ',')
02060                         break ;
02061                 *ptr2 = *ptr1 ;
02062         }
02063         *ptr2 = '\0' ;
02064 
02065         for(ptr1++, ptr2=element; *ptr1!='\0'; ptr1++, ptr2++)
02066         {
02067                 if (*ptr1 == ',')
02068                         break ;
02069                 *ptr2 = *ptr1 ;
02070         }
02071         *ptr2 = '\0' ;
02072 
02073         for(ptr1++, ptr2=desc; *ptr1!='\0'; ptr1++, ptr2++)
02074         {
02075                 if (*ptr1 == ',')
02076                         break ;
02077                 *ptr2 = *ptr1 ;
02078         }
02079         *ptr2 = '\0' ;
02080         /*********ptr1 points to current mapset description***********/
02081 
02082         if (opt->answer)
02083                 G_set_ask_return_msg (_("to accept the default"));
02084         if (! strcmp("old",age))
02085         {
02086                 ptr1 = G_ask_old("", buff, element, desc) ;
02087                 if (ptr1)
02088                 {
02089                     strcpy (buff, G_fully_qualified_name(buff,ptr1));
02090                 }
02091         }
02092         else if (! strcmp("new",age))
02093                 ptr1 = G_ask_new("", buff, element, desc) ;
02094         else if (! strcmp("mapset",age))
02095                 ptr1 = G_ask_in_mapset("", buff, element, desc) ;
02096         else if (! strcmp("any",age))
02097                 ptr1 = G_ask_any("", buff, element, desc, 1) ;
02098         else if (! strcmp("old_file",age))
02099                 ptr1 = G_ask_old_file("", buff, element, desc) ;
02100         else if (! strcmp("new_file",age))
02101                 ptr1 = G_ask_new_file("", buff, element, desc) ;
02102         else
02103         {
02104                 fprintf(stderr,"\nPROGRAMMER ERROR: first item in gisprompt is <%s>\n", age) ;
02105                 fprintf(stderr,"        Must be either new, old, mapset, any, old_file, or new_file\n") ;
02106                 return -1;
02107         }
02108         if (ptr1 == '\0')
02109                 *buff = '\0';
02110 
02111         return 0;
02112 }
02113 
02114 char *G_recreate_command (void)
02115 {
02116         char flg[4] ;
02117         static char *buff, *cur, *tmp;
02118         struct Flag *flag ;
02119         struct Option *opt ;
02120         int n , len, slen;
02121         int nalloced = 0;
02122 
02123         G_debug ( 3, "G_recreate_command()");
02124 
02125         /* Flag is not valid if there are no flags to set */
02126         
02127         buff = G_calloc (1024, sizeof(char));
02128         nalloced += 1024;
02129         tmp = G_program_name();
02130         len = strlen (tmp);
02131         if (len >= nalloced)
02132         {
02133                 nalloced += (1024 > len) ? 1024 : len + 1;
02134                 buff = G_realloc (buff, nalloced);
02135         }
02136         cur = buff;
02137         strcpy (cur, tmp);
02138         cur += len;
02139 
02140         if(n_flags)
02141         {
02142                 flag= &first_flag;
02143                 while(flag != '\0')
02144                 {
02145                         if( flag->answer == 1 )
02146                         {
02147                                 flg[0] = ' '; flg[1] = '-'; flg[2] = flag->key; flg[3] = '\0';
02148                                 slen = strlen (flg);
02149                                 if (len + slen >= nalloced)
02150                                 {
02151                                         nalloced += (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
02152                                         buff = G_realloc (buff, nalloced);
02153                                         cur = buff + len;
02154                                 }
02155                                 strcpy (cur, flg);
02156                                 cur += slen;
02157                                 len += slen;
02158                         }
02159                         flag = flag->next_flag ;
02160                 }
02161         }
02162 
02163         opt= &first_option;
02164         while(opt != '\0')
02165         {
02166                 if ( opt->answer != '\0' && opt->answers[0] != NULL )
02167                 {
02168                         slen = strlen (opt->key) + strlen (opt->answers[0]) + 4; /* +4 for: ' ' = " " */
02169                         if (len + slen >= nalloced)
02170                         {
02171                                 nalloced += (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
02172                                 buff = G_realloc (buff, nalloced);
02173                                 cur = buff + len;
02174                         }
02175                         strcpy (cur, " ");
02176                         cur++;
02177                         strcpy (cur, opt->key);
02178                         cur = strchr (cur, '\0');
02179                         strcpy (cur, "=");
02180                         cur++;
02181                         if ( opt->type == TYPE_STRING ) {
02182                             strcpy (cur, "\"");
02183                             cur++;
02184                         }
02185                         strcpy (cur, opt->answers[0]);
02186                         cur = strchr (cur, '\0');
02187                         len = cur - buff;
02188                         for(n=1; opt->answers[n] != NULL && opt->answers[n] != '\0';n++)
02189                         {
02190                                 if ( opt->answers[n] == NULL ) break;
02191                                 slen = strlen (opt->answers[n]) + 2; /* +2 for , " */
02192                                 if (len + slen >= nalloced)
02193                                 {
02194                                         nalloced += (nalloced + 1024 > len + slen) ? 1024 : slen + 1;
02195                                         buff = G_realloc (buff, nalloced);
02196                                         cur = buff + len;
02197                                 }
02198                                 strcpy (cur, ",");
02199                                 cur++;
02200                                 strcpy (cur, opt->answers[n]);
02201                                 cur = strchr(cur, '\0');
02202                                 len = cur - buff;
02203                         }
02204                         if ( opt->type == TYPE_STRING ) {
02205                             strcpy (cur, "\"");
02206                             cur++;
02207                             len = cur - buff;
02208                         }
02209                 }
02210                 opt = opt->next_opt ;
02211         }
02212 
02213         return(buff) ;
02214 }
02215 

Generated on Mon Jan 1 19:49:25 2007 for GRASS by  doxygen 1.5.1