opt.c

Go to the documentation of this file.
00001 /* LIBDGL -- a Directed Graph Library implementation
00002  * Copyright (C) 2002 Roberto Micarelli
00003  *
00004  * This program is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation; either version 2 of the License, or
00007  * (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 /* best view tabstop=4
00020  */
00021 
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025 
00026 #include "opt.h"
00027 
00028 static int _ParseLongOption( GnoOption_s * pOpt, char * pszArg )
00029 {
00030         char *          pszLong;
00031         char *          pszPar;
00032         char *          pszMatch = NULL;
00033         int                     nret;
00034 
00035 
00036         if ( pOpt->pszLong == NULL )
00037         {
00038                 return 0;
00039         }
00040 
00041         pszLong = strdup( pOpt->pszLong );
00042 
00043         if ( (pszPar = strchr( pszArg, '=' )) != NULL )
00044         {
00045                 *pszPar = 0;
00046         }
00047         pszMatch = strdup( pszArg );
00048         if ( pszPar ) *pszPar++ = '=';
00049 
00050         if ( strcmp( pszLong , pszMatch+2 ) == 0 )
00051         {
00052 
00053                 /* * mandatory parameter not found
00054                  * */
00055                 if ( pszPar == NULL )
00056                 {
00057                         nret = -1; goto free_and_exit;
00058                 }
00059 
00060                 if ( pOpt->ppszValue )
00061                 {
00062                         if ( pOpt->ppszValue[ 0 ] ) free( pOpt->ppszValue[ 0 ] );
00063                         pOpt->ppszValue[ 0 ] = strdup( pszPar );
00064                 }               
00065 
00066                 nret = 1; goto free_and_exit;
00067         }
00068         
00069         nret = 0;
00070 
00071 free_and_exit:
00072 
00073         free( pszLong );
00074         free( pszMatch );
00075 
00076         return nret;
00077 }
00078 
00079 static int _ParseLongSwitch( GnoOption_s * pOpt, char * pszArg )
00080 {
00081 
00082         if ( pOpt->pszLong == NULL )
00083         {
00084                 return 0;
00085         }
00086 
00087         if ( strcmp( pOpt->pszLong , pszArg+2 ) == 0 )
00088         {
00089                 if ( pOpt->pfValue ) *pOpt->pfValue = True;
00090 
00091                 return 1;
00092         }
00093         
00094         return 0;
00095 }
00096 
00097 
00098 static int _ParseShortOption( GnoOption_s * pOpt, char * pszArg, char * pszPar )
00099 {
00100         char *          pszShort;
00101         int                     ich;
00102 
00103         if ( pOpt->pszShort == NULL ) return 0;
00104 
00105         pszShort = strdup( pOpt->pszShort );
00106 
00107         for ( ich = 1; pszArg[ ich ]; ich ++ )
00108         {
00109                 if ( pszShort[ 0 ] == pszArg[ ich ] )
00110                 {
00111                         if ( pszPar == NULL || pszPar[ 0 ] == 0 )
00112                         {
00113                                 free( pszShort );
00114 
00115                                 return -1;
00116                         }
00117 
00118                         if ( pszPar[ 0 ] == '-' && pszPar[ 1 ] != 0 )
00119                         {
00120                                 free( pszShort );
00121 
00122                                 return -1;
00123                         }
00124 
00125                         if ( pOpt->ppszValue )
00126                         {
00127                                 if ( pOpt->ppszValue[ 0 ] ) free( pOpt->ppszValue[ 0 ] );
00128                                 pOpt->ppszValue[ 0 ] = strdup( pszPar );
00129                         }               
00130 
00131                         free( pszShort );
00132 
00133                         return 2;
00134                 }
00135         }
00136         
00137         free( pszShort );
00138 
00139         return 0;
00140 }
00141 
00142 static int _ParseShortSwitch( GnoOption_s * pOpt, char * pszArg )
00143 {
00144         int             ich;
00145 
00146         if ( pOpt->pszShort == NULL ) return 0;
00147 
00148         for ( ich = 1; pszArg[ ich ]; ich ++ )
00149         {
00150                 if ( pOpt->pszShort[ 0 ] == pszArg[ ich ] )
00151                 {
00152                         if ( pOpt->pfValue ) *pOpt->pfValue = True;
00153 
00154                         return 1;
00155                 }
00156         }
00157         
00158         return 0;
00159 }
00160 
00161 /***********************************************************************
00162  *                              CALLBACKS
00163  **********************************************************************/
00164 /***********************************************************************
00165  *                              PUBLIC FUNCTIONS
00166  **********************************************************************/
00167 
00168 /*@*--------------------------------------------------------------------
00169  * @func:       GnoParse()
00170  * @descr:      Parse argc, argv against the option array and setup option
00171  *                      values in the array.
00172  * 
00173  * @args:       I:      argc    =       count of argv entries
00174  *                      I:      argv    ->      array of pointer to string
00175  *                      I:      pOpt    ->      option array pointer
00176  *
00177  * @ret:        The number of 'orphan' entries found in the argv.
00178  * @see:        GnoOption_s
00179  *
00180  * @notes:      The argv array will be modified: each argv entry that contains a
00181  *                      recognized option ( '-.' or '--...' ) or each entry recognized as
00182  *                      a parametric option parameter, will be set to NULL.
00183  *                      Thus, at the function return the argv entries not set to NULL are
00184  *                      those of orphan entries (those not related to any option).
00185  *                      The user can then scan argv to find out orphans.
00186  *                      However the number of argv entries will not be altered.
00187  *
00188  *--------------------------------------------------------------------*/
00189 
00190 int GnoParse( int argc , char ** argv , GnoOption_s * pOpt )
00191 {
00192         char *  pszArgv;
00193         char *  pszArgvNxt;
00194         int             iArg, iOpt, cOrphan = 0;
00195         int             nret, cret;
00196         Boolean fParseError = False;
00197 
00198         /* * this first loop setup default values
00199          * * strdup is used for non-switch options
00200          * * to make life easier when freeing the field
00201          * */
00202         for     (
00203                         iOpt = 0 ;
00204                         pOpt[ iOpt ].pszShort || pOpt[ iOpt ].pszLong ;
00205                         iOpt ++
00206                 )
00207         {
00208                 if ( pOpt[ iOpt ].nFlg & GNO_FLG_SWITCH )
00209                 {
00210                         if ( pOpt[ iOpt ].pfValue )
00211                         {
00212                                 pOpt[ iOpt ].pfValue[ 0 ] = pOpt[ iOpt ].fDef;
00213                         }
00214                 }
00215                 else
00216                 {
00217                         if ( pOpt[ iOpt ].pszDef )
00218                         {
00219                                 if ( pOpt[ iOpt ].ppszValue )
00220                                 {
00221                                         pOpt[ iOpt ].ppszValue[ 0 ] = strdup( pOpt[ iOpt ].pszDef );
00222                                 }
00223                         }
00224                         else
00225                         {
00226                                 if ( pOpt[ iOpt ].ppszValue )
00227                                 {
00228                                         pOpt[ iOpt ].ppszValue[ 0 ] = NULL;
00229                                 }
00230                         }
00231                 }
00232         }
00233 
00234         /* * for each arg in argv lookup the matching options
00235          * */
00236         for     (
00237                         iArg = 0, pszArgv = NULL ;
00238                         iArg < argc && (pszArgv = strdup( argv[ iArg ] )) != NULL ;
00239                         iArg ++, free( pszArgv ), pszArgv = NULL
00240                 )
00241         {
00242 
00243                 if ( pszArgv[ 0 ] == '-' && pszArgv[ 1 ] == '-' && pszArgv[ 2 ] ) /* long style */
00244                 {
00245                         for     (
00246                                 iOpt = 0 ;
00247                                 (pOpt[ iOpt ].pszShort || pOpt[ iOpt ].pszLong) && argv[ iArg ] ;
00248                                 iOpt ++
00249                                 )
00250                         {
00251                                 if ( pOpt[ iOpt ].pszLong )
00252                                 {
00253                                         if ( pOpt[ iOpt ].nFlg & GNO_FLG_SWITCH )
00254                                         {
00255                                                 nret = _ParseLongSwitch( & pOpt[ iOpt ], pszArgv );
00256                                         }
00257                                         else
00258                                         {
00259                                                 nret = _ParseLongOption( & pOpt[ iOpt ], pszArgv );
00260                                         }
00261 
00262                                         if ( nret < 0 )
00263                                         {
00264                                                 fprintf( stderr, "parse option: syntax error at <%s>\n", pszArgv );
00265                                                 fParseError =  True;
00266                                         }
00267 
00268                                         if ( nret == 1 )
00269                                         {
00270                                                 argv[ iArg ] = NULL;
00271                                         }
00272                                 }
00273                         }
00274 
00275                         if ( argv[ iArg ] )
00276                         {
00277                                 fprintf( stderr, "parse option: <%s> is out of scope\n", pszArgv );
00278                                 fParseError =  True;
00279                         }
00280                 }
00281                 else if ( argv[iArg][ 0 ] == '-' && argv[iArg][ 1 ] ) /* short style */
00282                 {
00283                         if ( iArg + 1 < argc )
00284                         {
00285                                 pszArgvNxt = strdup( argv[ iArg + 1 ] );
00286                         }
00287                         else
00288                         {
00289                                 pszArgvNxt = NULL;
00290                         }
00291 
00292                         for     (
00293                                         cret = iOpt = 0 ;
00294                                         pOpt[ iOpt ].pszShort || pOpt[ iOpt ].pszLong ;
00295                                         iOpt ++
00296                                 )
00297                         {
00298                                 if ( pOpt[ iOpt ].pszShort )
00299                                 {
00300                                         if ( pOpt[ iOpt ].nFlg & GNO_FLG_SWITCH )
00301                                         {
00302                                                 nret = _ParseShortSwitch( & pOpt[ iOpt ], pszArgv );
00303                                         }
00304                                         else
00305                                         {
00306                                                 nret = _ParseShortOption( & pOpt[ iOpt ], pszArgv , pszArgvNxt );
00307                                         }
00308                                         if ( nret < 0 )
00309                                         {
00310                                                 fprintf( stderr, "parse option: syntax error at <%s>\n", pszArgv );
00311                                                 fParseError =  True;
00312                                         }
00313                                         else
00314                                         {
00315                                                 cret = (nret>cret) ? nret : cret;
00316                                         }
00317                                 }
00318                         }
00319 
00320                         if ( pszArgvNxt )
00321                         {
00322                                 free( pszArgvNxt );
00323                         }
00324 
00325                         if ( cret == 1 )
00326                         {
00327                                 argv[ iArg ] = NULL;
00328                         }
00329                         else if ( cret == 2 )
00330                         {
00331                                 argv[ iArg++ ] = NULL;
00332                                 argv[ iArg ] = NULL;
00333                         }
00334 
00335                 }
00336                 else
00337                 {
00338                         cOrphan ++;
00339                 }
00340         }
00341 
00342         if ( pszArgv ) free( pszArgv );
00343 
00344         return ( fParseError == True ) ? -1 : cOrphan;
00345 }
00346 
00347 
00348 /*@*--------------------------------------------------------------------
00349  * @func:       GnoFree()
00350  * @descr:      Free resource previously created with a call to GnoParse()
00351  * 
00352  * @args:       I:      pOpt    ->      option array pointer
00353  *
00354  * @see:        GnoOption_s, GnoParse()
00355  *
00356  *--------------------------------------------------------------------*/
00357 void GnoFree( GnoOption_s * pOpt )
00358 {
00359         int     iOpt;   
00360 
00361         for     (
00362                         iOpt = 0 ;
00363                         pOpt[ iOpt ].pszShort || pOpt[ iOpt ].pszLong ;
00364                         iOpt ++
00365                 )
00366         {
00367                 if ( pOpt[ iOpt ].ppszValue )
00368                 {
00369                         if ( pOpt[ iOpt ].ppszValue[ 0 ] )
00370                         {
00371                                 free( pOpt[ iOpt ].ppszValue[ 0 ] );
00372                                 pOpt[ iOpt ].ppszValue[ 0 ] = NULL;
00373                         }
00374                 }
00375         }
00376         
00377 }
00378 
00379 /*@*--------------------------------------------------------------------
00380  * @func:       GnoHelp()
00381  * @descr:      Print a brief option's help on the standard error
00382  * 
00383  * @args:       I:      pszHead ->      help header string
00384  *
00385  * @args:       I:      pOpt    ->      option array pointer
00386  *
00387  * @see:        GnoOption_s
00388  *
00389  *--------------------------------------------------------------------*/
00390 void GnoHelp( char *pszHead, GnoOption_s * pOpt )
00391 {
00392         int     iOpt;   
00393 
00394         fprintf( stderr, "%s\n", (pszHead) ? pszHead : "options" );
00395 
00396         for     (
00397                         iOpt = 0 ;
00398                         pOpt[ iOpt ].pszShort || pOpt[ iOpt ].pszLong ;
00399                         iOpt ++
00400                 )
00401         {
00402 
00403                 if ( pOpt[ iOpt ].nFlg & GNO_FLG_SWITCH )
00404                 {
00405                         if ( pOpt[ iOpt ].pszShort )
00406                         {
00407                                 fprintf( stderr, "-%s ", pOpt[ iOpt ].pszShort );
00408                         }
00409 
00410                         if ( pOpt[ iOpt ].pszLong )
00411                         {
00412                                 fprintf( stderr, "--%s", pOpt[ iOpt ].pszLong );
00413                         }
00414 
00415                         fprintf( stderr, "\n\t%s\n",
00416                                 ( pOpt[ iOpt ].pszDescr )
00417                                 ?
00418                                         pOpt[ iOpt ].pszDescr
00419                                 :
00420                                         "No description available."
00421                                 );
00422                 }
00423                 else
00424                 {
00425                         if ( pOpt[ iOpt ].pszShort )
00426                         {
00427                                 fprintf( stderr, "-%s ", pOpt[ iOpt ].pszShort );
00428 
00429                                 fprintf( stderr, "<value> " );
00430                         }
00431 
00432                         if ( pOpt[ iOpt ].pszLong )
00433                         {
00434                                 fprintf( stderr, "--%s", pOpt[ iOpt ].pszLong );
00435 
00436                                 fprintf( stderr, "=<value>" );
00437                         }
00438 
00439                         fprintf( stderr, "\n\t%s\n",
00440                                 ( pOpt[ iOpt ].pszDescr )
00441                                 ?
00442                                         pOpt[ iOpt ].pszDescr
00443                                 :
00444                                         "No description available."
00445                                 );
00446                 }
00447         }
00448         
00449 }
00450 
00451 /******************************* END OF FILE **************************/
00452 

Generated on Sun Apr 6 17:32:44 2008 for GRASS by  doxygen 1.5.5