Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Examples  

option.c

Go to the documentation of this file.
00001 /*! \file option.c
00002     This file implements the options' reader.
00003  */
00004 
00005 #include <strings.h>
00006 #include <sys/types.h>
00007 #include <regex.h>
00008 #include "option.h"
00009 
00010 /*! \brief Pointer used to set the argument of the options that do not require arguments (ex: --help).
00011  */
00012 
00013 static char  self_option[] = "";
00014 
00015 /*! \brief Returns a pointer to the <I>Option</I> data structure that represents a given option.
00016     \param opt Pointer to a <I>Option_set</I> data structure that defines all options.
00017     \param flag Pointer to a zero terminated string of characters that represents the option's flag to 
00018                 locate.
00019     \return If the option represented by the string pointed by <I>flag</I> is found, then the function returns
00020             a non NULL pointer to the <I>Option</I> data structure that defines the option. Otherwize (the
00021             option was not found), the function returns the value NULL.
00022  */
00023 
00024 static Option* find_option (Option_set *opt, char *flag)
00025 {
00026   Option *opt_found;
00027   int    i;
00028 
00029   opt_found = opt->opt;
00030   for (i=0; i<opt->count; i++)
00031   {
00032     if (strcmp(opt_found->flag, flag) == 0) { return opt_found; }
00033     opt_found++;
00034   }
00035 
00036   return NULL;
00037 }
00038 
00039 /*! \brief Returns a pointer to the argument associated with a given option.
00040     \param opt Pointer to a <I>Option_set</I> data structure that defines all options.
00041     \param flag Pointer to a zero terminated string of characters that represents the option's flag that you
00042                 want to get the argument.
00043     \param arg If the option is valid (defined in the list of options), then the content of <I>arg</I> pointes
00044                to the argument associated with the option. If the content of <I>arg</I> is equal to NULL, this
00045                means that the option is not activated in the command line.
00046     \return If the option is found (that is: the option is defined in the <I>Option_set</I> data structure
00047             pointed by <I>opt</I>), the function returns the value 0. In this case:
00048             <UL>
00049                 <LI>if <I>arg</I> is NULL, it means that the option was not activated.
00050                 <LI>if <I>arg</I> is not NULL, it means that the option was activated.
00051                     <UL>
00052                         <LI>If the option requires one argument, then <I>arg</I> pointes to a zero terminated
00053                             string of characters that represents the argument.
00054                         <LI>If the option does not require any argument, then you don't care about the string
00055                             of characters pointed by <I>arg</I> (this string exists, but it does not mean
00056                             anything).
00057                     </UL>
00058             </UL>
00059             If the option can not be found (the option is not defined in the <I>Option_set</I> data structure
00060             pointed by <I>opt</I>), the function returns the value 1. Please note that a return value of 1 means
00061             that you've made an programming error (in your code, you are testing for options that you did not
00062             define earlier).
00063  */
00064 
00065 int get_argument (Option_set *opt, char *flag, char **arg)
00066 {
00067   Option *opt_found;
00068 
00069   *arg = NULL;
00070   opt_found = find_option (opt, flag);
00071 
00072   if (opt_found == NULL) { return 1; }
00073   *arg = *(opt_found->pointer);
00074 
00075   return 0;
00076 }
00077 
00078 /*! \example test_options.c
00079     This file shows how to use all the function of the library libmy_option.
00080  */
00081 
00082 /*! \brief This function returns a value that represents the number of arguments (0 or 1 argument) required by
00083            for a given option.
00084     \param opt Pointer to a <I>Option_set</I> data structure that contains the definitions of all options.
00085     \param flag Pointer to a zero terminated string of characters that represents the option's flag to test.
00086     \return The function may return one of the following values:
00087             <UL>
00088                <LI>-1: An error occured. The option's flag pointed by <I>flag</I> does not represent any
00089                        pre-defined options. This is a programming error. You are trying to test an option that
00090                        you did not define previously.
00091                <LI>0:  The option does not require any argument.
00092                <LI>1:  The option requires one argument.
00093             </UL>
00094  */
00095 
00096 int is_argument_required (Option_set *opt, char *flag)
00097 {
00098   Option *opt_found;
00099 
00100   opt_found = find_option (opt, flag);
00101   if (opt_found == NULL) { return -1; }
00102 
00103   if (opt_found->arg != 0) { return 1; }
00104 
00105   return 0;
00106 }
00107 
00108 /*! \example test_options.c
00109     This file shows how to use all the function of the library libmy_option.
00110  */
00111 
00112 /*! \brief Initialize the array of option definitions.
00113     \param opt Pointer to a <I>Option_set</I> data structure that contains the definitions of all options.
00114     \return Upon successful completion the function returns the value 0. Otherwise it returns the value 1.
00115     \warning Please note that an option's flag should verify the following rules:
00116              <UL>
00117                 <LI>At least 2 characters.
00118                 <LI>Begin with a '-'.
00119                 <LI>No spaces.
00120                 <LI>Not all '-'.
00121              </UL>
00122 */
00123 
00124 int init_options (Option_set *opt)
00125 {
00126   int     i, j, s;
00127   Option  *o;
00128   char    *pt;
00129 
00130   /* ------------------------------------------------------------- */
00131   /* Initialize options' array                                     */
00132   /* ------------------------------------------------------------- */
00133 
00134   opt->last_index = -1;
00135   for (i=0; i<opt->count; i++) { *((opt->opt + i)->pointer) = NULL; }
00136 
00137   /* ------------------------------------------------------------- */
00138   /* Check the syntax of all option's tags                         */
00139   /*  - At least 2 characters.                                     */
00140   /*  - Begin with a '-'.                                          */
00141   /*  - No spaces.                                                 */
00142   /*  - Not all '-'.                                               */
00143   /*                                                               */
00144   /* Note: the algo is not fast, but who cares. Command line is    */
00145   /*       not very long and we parse it only once. At least, this */
00146   /*       algo is pretty simple.                                  */
00147   /* ------------------------------------------------------------- */
00148 
00149   for (i=0; i<opt->count; i++)
00150   {
00151     o  = opt->opt + i;
00152     pt = o->flag;
00153     s  = strlen(pt);
00154 
00155     if ((s < 2) || (*pt != '-')) { return 1; }
00156     for (j=0; j<s; j++) { if (*(pt+j) == ' ') { return 1; } }
00157     for (j=0; j<s; j++) { if (*(pt+j) != '-') { break;    } }
00158     if (j == s) { return 1; }
00159   }
00160 
00161   return 0;
00162 }
00163 
00164 /*! \example test_options.c
00165     This file shows how to use all the function of the library libmy_option.
00166  */
00167 
00168 /*! \brief Parse the command line and set up the option's data structure.
00169     \param argv Array of sero terminated strings of characters that represents the command line. Please
00170                 note that the first element of the array (indice 0) should point to the name of the process.
00171     \param argc Number of elements in the array <I>argv</I>.
00172     \param opt Pointer to the <I>Option_set</I> data structure that contains the option's definitions.
00173     \param err Pointer to a pointer that will be used to store the address of a zero terminated string of 
00174                characters. If an error occured, this string contains a literal description of the error.
00175     \param flag Pointer to a pointer that will be used to store the address of a zero terminated string of
00176                 characters. If an error occured, this string contains the option that generated the error.
00177     \param arg Pointer to a pointer that will be used to store the address of a zero terminated string of
00178                characters. If an error occured, this string contains the argument that caused the error.
00179     \return Upon successful completion, the function returns the value 0. Otherwise the function returns the
00180             value 1.
00181     \warning A valid command line should look something like:<P>
00182              &lt;process name&gt; [-flag1 [arg1]] [-flag2 [arg2]] [...] &lt;required arg 1&gt; ...
00183  */
00184 
00185 int parse_command_line (char *argv[], int argc, Option_set *opt, char **err, char **flag, char **arg)
00186 {
00187   int         i, oflag, rv;
00188   static char err1[]     = "Success";
00189   static char err2[]     = "";
00190   static char err3[]     = "Unknown option";
00191   static char err4[]     = "Missing option's argument";
00192   static char err5[]     = "Duplicated option";
00193   static char err6[]     = "Argument too long";
00194   static char err7[]     = "Invalid regular expression";
00195   static char err8[]     = "Invalid argument (syntax error)";
00196   static char last_opt[] = "";
00197   regex_t     reg;
00198   regmatch_t  pmatch[1];
00199   Option      *ofound;
00200   char        *last_option;
00201 
00202   /* ------------------------------------------------------------- */
00203   /* Initialize variables                                          */
00204   /* ------------------------------------------------------------- */
00205 
00206   *err            = err1;
00207   *flag           = err2;
00208   *arg            = self_option;
00209   last_option     = last_opt;
00210   oflag           = 0;
00211   opt->last_index = 0;
00212 
00213   /* ------------------------------------------------------------- */
00214   /* Parse command line now                                        */
00215   /* ------------------------------------------------------------- */
00216 
00217   for (i=1; i<argc; i++)
00218   {
00219     if ((*(argv[i]) != '-') && (oflag == 0)) { return 0; }
00220 
00221     /* ----------------------------------------------------------- */
00222     /* Is it an option ?                                           */
00223     /* ----------------------------------------------------------- */
00224 
00225     if (*(argv[i]) == '-')
00226     {
00227       if (oflag == 1)
00228       {
00229         /* ------------------------------------------------------- */
00230         /* We get an option's flag, but we expected an argument    */
00231         /* ------------------------------------------------------- */
00232 
00233         *err  = err4;
00234         *flag = last_option;
00235         return 1;
00236       } 
00237 
00238       ofound = find_option (opt, argv[i]);
00239       if (ofound == NULL)
00240       {
00241         /* ------------------------------------------------------- */
00242         /* This option is bot defined                              */
00243         /* ------------------------------------------------------- */
00244 
00245         *err  = err3;
00246         *flag = argv[i];
00247         return 1;
00248       }
00249 
00250       if (*(ofound->pointer) != NULL)
00251       {
00252         /* ------------------------------------------------------- */
00253         /* This option is already activated                        */
00254         /* ------------------------------------------------------- */
00255 
00256         *err  = err5;
00257         *flag = argv[i];
00258         return 1;
00259       }
00260 
00261       /* --------------------------------------------------------- */
00262       /* Option found. Is it a "self option" ?                     */
00263       /* --------------------------------------------------------- */
00264 
00265       if (ofound->arg == 0) { oflag = 0; *(ofound->pointer) = self_option; }
00266       else { oflag = 1; }
00267 
00268       last_option = argv[i];
00269     }
00270 
00271     /* ----------------------------------------------------------- */
00272     /* Is it an argument ?                                         */
00273     /* ----------------------------------------------------------- */
00274 
00275     if (*(argv[i]) != '-')
00276     {
00277       if (oflag == 0) { return 0; }
00278 
00279       /* --------------------------------------------------------- */
00280       /* Testing the size of the argument                          */
00281       /* --------------------------------------------------------- */
00282 
00283       if (strlen(argv[i]) > ofound->max_size)
00284       {
00285         *err  = err6;
00286         *arg  = argv[i];
00287         *flag = last_option;
00288         return 1;
00289       }
00290 
00291       /* --------------------------------------------------------- */
00292       /* Check argumment against regular expression                */
00293       /* --------------------------------------------------------- */
00294 
00295       rv = regcomp (&reg, ofound->reg_exp, REG_EXTENDED);
00296       if (rv != 0)
00297       {
00298         *err  = err7;
00299         *flag = last_option;
00300         *arg  = argv[i];
00301         return 1;
00302       }
00303 
00304       rv = regexec (&reg, argv[i], 1, pmatch, 0);
00305       if (rv != 0)
00306       {
00307         *err  = err8;
00308         *flag = last_option;
00309         *arg  = argv[i];
00310         regfree (&reg);
00311         return 1;
00312       } 
00313 
00314       regfree (&reg);
00315 
00316       *(ofound->pointer) = argv[i];
00317       oflag = 0;
00318     }
00319 
00320     opt->last_index = i;
00321   }
00322 
00323   if (oflag == 1)
00324   {
00325     *err  = err4;
00326     *flag = last_option;
00327     return 1;
00328   }
00329 
00330   return 0;
00331 }
00332 
00333 /*! \example test_options.c
00334     This file shows how to use all the function of the library libmy_option.
00335  */
00336 
00337 
00338 

Generated on Thu Apr 3 16:23:43 2003 for Common_C_libraries by doxygen1.3-rc1