Logo Search packages:      
Sourcecode: virtualbox-ose version File versions  Download package

getopt.h

Go to the documentation of this file.
/** @file
 * IPRT - Command Line Parsing.
 */

/*
 * Copyright (C) 2007 Oracle Corporation
 *
 * This file is part of VirtualBox Open Source Edition (OSE), as
 * available from http://www.virtualbox.org. This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 *
 * The contents of this file may alternatively be used under the terms
 * of the Common Development and Distribution License Version 1.0
 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
 * VirtualBox OSE distribution, in which case the provisions of the
 * CDDL are applicable instead of those of the GPL.
 *
 * You may elect to license modified versions of this file under the
 * terms and conditions of either the GPL or the CDDL or both.
 */

#ifndef ___iprt_getopt_h
#define ___iprt_getopt_h


#include <iprt/cdefs.h>
#include <iprt/types.h>

RT_C_DECLS_BEGIN

/** @defgroup grp_rt_getopt    RTGetOpt - Command Line Parsing
 * @ingroup grp_rt
 * @{
 */

/** @name RTGETOPTDEF::fFlags
 *
 * @remarks When neither of the RTGETOPT_FLAG_HEX, RTGETOPT_FLAG_OCT and RTGETOPT_FLAG_DEC
 *          flags are specified with a integer value format, RTGetOpt will default to
 *          decimal but recognize the 0x prefix when present. RTGetOpt will not look for
 *          for the octal prefix (0).
 * @{ */
/** Requires no extra argument.
 * (Can be assumed to be 0 for ever.) */
00049 #define RTGETOPT_REQ_NOTHING                    0
/** A value is required or error will be returned. */
00051 #define RTGETOPT_REQ_STRING                     1
/** The value must be a valid signed 8-bit integer or an error will be returned. */
00053 #define RTGETOPT_REQ_INT8                       2
/** The value must be a valid unsigned 8-bit integer or an error will be returned. */
00055 #define RTGETOPT_REQ_UINT8                      3
/** The value must be a valid signed 16-bit integer or an error will be returned. */
00057 #define RTGETOPT_REQ_INT16                      4
/** The value must be a valid unsigned 16-bit integer or an error will be returned. */
00059 #define RTGETOPT_REQ_UINT16                     5
/** The value must be a valid signed 32-bit integer or an error will be returned. */
00061 #define RTGETOPT_REQ_INT32                      6
/** The value must be a valid unsigned 32-bit integer or an error will be returned. */
00063 #define RTGETOPT_REQ_UINT32                     7
/** The value must be a valid signed 64-bit integer or an error will be returned. */
00065 #define RTGETOPT_REQ_INT64                      8
/** The value must be a valid unsigned 64-bit integer or an error will be returned. */
00067 #define RTGETOPT_REQ_UINT64                     9
/** The value must be a valid IPv4 address.
 * (Not a name, but 4 values in the 0..255 range with dots separating them). */
00070 #define RTGETOPT_REQ_IPV4ADDR                   10
#if 0
/** The value must be a valid IPv4 CIDR.
 * As with RTGETOPT_REQ_IPV4ADDR, no name.
 * @todo Mix CIDR with types.h or/and net.h first and find a way to make the
 *       mask optional like with ifconfig. See RTCidrStrToIPv4. */
#define RTGETOPT_REQ_IPV4CIDR                   11
#endif
/** The value must be a valid ethernet MAC address. */
00079 #define RTGETOPT_REQ_MACADDR                    14
/** The value must be a valid UUID. */
00081 #define RTGETOPT_REQ_UUID                       15
/** The value must be a string with value as "on" or "off". */
00083 #define RTGETOPT_REQ_BOOL_ONOFF                 16
/** The mask of the valid required types. */
00085 #define RTGETOPT_REQ_MASK                       31
/** Treat the value as hexadecimal - only applicable with the RTGETOPT_REQ_*INT*. */
00087 #define RTGETOPT_FLAG_HEX                       RT_BIT(16)
/** Treat the value as octal - only applicable with the RTGETOPT_REQ_*INT*. */
00089 #define RTGETOPT_FLAG_OCT                       RT_BIT(17)
/** Treat the value as decimal - only applicable with the RTGETOPT_REQ_*INT*. */
00091 #define RTGETOPT_FLAG_DEC                       RT_BIT(18)
/** The index value is attached to the argument - only valid for long arguments. */
00093 #define RTGETOPT_FLAG_INDEX                     RT_BIT(19)
/** Mask of valid bits - for validation. */
00095 #define RTGETOPT_VALID_MASK                     (  RTGETOPT_REQ_MASK \
                                                 | RTGETOPT_FLAG_HEX \
                                                 | RTGETOPT_FLAG_OCT \
                                                 | RTGETOPT_FLAG_DEC \
                                                 | RTGETOPT_FLAG_INDEX)
/** @} */

/**
 * An option definition.
 */
00105 typedef struct RTGETOPTDEF
{
    /** The long option.
     * This is optional */
00109     const char     *pszLong;
    /** The short option character.
     * This doesn't have to be a character, it may also be a \#define or enum value if
     * there isn't any short version of this option. Must be greater than 0. */
00113     int             iShort;
    /** The flags (RTGETOPT_*). */
00115     unsigned        fFlags;
} RTGETOPTDEF;
/** Pointer to an option definition. */
00118 typedef RTGETOPTDEF *PRTGETOPTDEF;
/** Pointer to an const option definition. */
00120 typedef const RTGETOPTDEF *PCRTGETOPTDEF;

/**
 * Option argument union.
 *
 * What ends up here depends on argument format in the option definition.
 *
 * @remarks Integers will bet put in the \a i and \a u members and sign/zero extended
 *          according to the signedness indicated by the \a fFlags. So, you can choose
 *          use which ever of the integer members for accessing the value regardless
 *          of restrictions indicated in the \a fFlags.
 */
00132 typedef union RTGETOPTUNION
{
    /** Pointer to the definition on failure or when the option doesn't take an argument.
     * This can be NULL for some errors. */
00136     PCRTGETOPTDEF   pDef;
    /** A RTGETOPT_REQ_STRING option argument. */
00138     const char     *psz;

    /** A RTGETOPT_REQ_INT8 option argument. */
00141     int8_t          i8;
    /** A RTGETOPT_REQ_UINT8 option argument . */
00143     uint8_t         u8;
    /** A RTGETOPT_REQ_INT16 option argument. */
00145     int16_t         i16;
    /** A RTGETOPT_REQ_UINT16 option argument . */
00147     uint16_t        u16;
    /** A RTGETOPT_REQ_INT16 option argument. */
00149     int32_t         i32;
    /** A RTGETOPT_REQ_UINT32 option argument . */
00151     uint32_t        u32;
    /** A RTGETOPT_REQ_INT64 option argument. */
00153     int64_t         i64;
    /** A RTGETOPT_REQ_UINT64 option argument. */
00155     uint64_t        u64;
#ifdef ___iprt_net_h
    /** A RTGETOPT_REQ_IPV4ADDR option argument. */
    RTNETADDRIPV4   IPv4Addr;
#endif
    /** A RTGETOPT_REQ_MACADDR option argument. */
00161     RTMAC           MacAddr;
    /** A RTGETOPT_REQ_UUID option argument. */
00163     RTUUID          Uuid;
    /** A boolean flag. */
00165     bool            f;
} RTGETOPTUNION;
/** Pointer to an option argument union. */
00168 typedef RTGETOPTUNION *PRTGETOPTUNION;
/** Pointer to a const option argument union. */
00170 typedef RTGETOPTUNION const *PCRTGETOPTUNION;


/**
 * RTGetOpt state.
 */
00176 typedef struct RTGETOPTSTATE
{
    /** The next argument. */
00179     int             iNext;
    /** Argument array. */
00181     char          **argv;
    /** Number of items in argv. */
00183     int             argc;
    /** Option definition array. */
00185     PCRTGETOPTDEF   paOptions;
    /** Number of items in paOptions. */
00187     size_t          cOptions;
    /** The next short option.
     * (For parsing ls -latrT4 kind of option lists.) */
00190     const char     *pszNextShort;
    /** The option definition which matched. NULL otherwise. */
00192     PCRTGETOPTDEF   pDef;
    /** The index of an index option, otherwise UINT32_MAX. */
00194     uint32_t        uIndex;
    /** The flags passed to RTGetOptInit.  */
00196     uint32_t        fFlags;
    /** Number of non-options that we're skipping during a sorted get.  The value
     * INT32_MAX is used to indicate that there are no more options.  This is used
     * to implement '--'.   */
00200     int32_t         cNonOptions;

    /* More members may be added later for dealing with new features. */
} RTGETOPTSTATE;
/** Pointer to RTGetOpt state. */
00205 typedef RTGETOPTSTATE *PRTGETOPTSTATE;


/**
 * Initialize the RTGetOpt state.
 *
 * The passed in argument vector may be sorted if fFlags indicates that this is
 * desired (to be implemented).
 *
 * @returns VINF_SUCCESS, VERR_INVALID_PARAMETER or VERR_INVALID_POINTER.
 * @param   pState      The state.
 *
 * @param   argc        Argument count, to be copied from what comes in with
 *                      main().
 * @param   argv        Argument array, to be copied from what comes in with
 *                      main(). This may end up being modified by the
 *                      option/argument sorting.
 * @param   paOptions   Array of RTGETOPTDEF structures, which must specify what
 *                      options are understood by the program.
 * @param   cOptions    Number of array items passed in with paOptions.
 * @param   iFirst      The argument to start with (in argv).
 * @param   fFlags      The flags. MBZ for now.
 */
RTDECL(int) RTGetOptInit(PRTGETOPTSTATE pState, int argc, char **argv,
                         PCRTGETOPTDEF paOptions, size_t cOptions,
                         int iFirst, uint32_t fFlags);

/** @name RTGetOptInit flags.
 * @{ */
/** Sort the arguments so that options comes first, then non-options. */
00235 #define RTGETOPTINIT_FLAGS_OPTS_FIRST   RT_BIT_32(0)
/** Prevent add the standard version and help options:
 *     - "--help", "-h" and "-?" returns 'h'.
 *     - "--version" and "-V" return 'V'.
 */
00240 #define RTGETOPTINIT_FLAGS_NO_STD_OPTS  RT_BIT_32(1)
/** @} */

/**
 * Command line argument parser, handling both long and short options and checking
 * argument formats, if desired.
 *
 * This is to be called in a loop until it returns 0 (meaning that all options
 * were parsed) or a negative value (meaning that an error occured). How non-option
 * arguments are dealt with depends on the flags passed to RTGetOptInit. The default
 * (fFlags = 0) is to return VINF_GETOPT_NOT_OPTION with pValueUnion->psz pointing to
 * the argument string.
 *
 * For example, for a program which takes the following options:
 *
 *   --optwithstring (or -s) and a string argument;
 *   --optwithint (or -i) and a 32-bit signed integer argument;
 *   --verbose (or -v) with no arguments,
 *
 * code would look something like this:
 *
 * @code
int main(int argc, char **argv)
{
     RTR3Init();

     static const RTGETOPTDEF s_aOptions[] =
     {
         { "--optwithstring",    's', RTGETOPT_REQ_STRING },
         { "--optwithint",       'i', RTGETOPT_REQ_INT32 },
         { "--verbose",          'v', 0 },
     };

     int ch;
     RTGETOPTUNION ValueUnion;
     RTGETOPTSTATE GetState;
     RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
     while ((ch = RTGetOpt(&GetState, &ValueUnion)))
     {
         // for options that require an argument, ValueUnion has received the value
         switch (ch)
         {
             case 's': // --optwithstring or -s
                 // string argument, copy ValueUnion.psz
                 break;

             case 'i': // --optwithint or -i
                 // integer argument, copy ValueUnion.i32
                 break;

             case 'v': // --verbose or -v
                 g_fOptVerbose = true;
                 break;

             case VINF_GETOPT_NOT_OPTION:
                 // handle non-option argument in ValueUnion.psz.
                 break;

             default:
                 return RTGetOptPrintError(ch, &ValueUnion);
         }
     }

     return 0;
}
   @endcode
 *
 * @returns 0 when done parsing.
 * @returns the iShort value of the option. pState->pDef points to the option
 *          definition which matched.
 * @returns IPRT error status on parse error.
 * @returns VINF_GETOPT_NOT_OPTION when encountering a non-option argument and
 *          RTGETOPT_FLAG_SORT was not specified. pValueUnion->psz points to the
 *          argument string.
 * @returns VERR_GETOPT_UNKNOWN_OPTION when encountering an unknown option.
 *          pValueUnion->psz points to the option string.
 * @returns VERR_GETOPT_REQUIRED_ARGUMENT_MISSING and pValueUnion->pDef if
 *          a required argument (aka value) was missing for an option.
 * @returns VERR_GETOPT_INVALID_ARGUMENT_FORMAT and pValueUnion->pDef if
 *          argument (aka value) conversion failed.
 *
 * @param   pState      The state previously initialized with RTGetOptInit.
 * @param   pValueUnion Union with value; in the event of an error, psz member
 *                      points to erroneous parameter; otherwise, for options
 *                      that require an argument, this contains the value of
 *                      that argument, depending on the type that is required.
 */
RTDECL(int) RTGetOpt(PRTGETOPTSTATE pState, PRTGETOPTUNION pValueUnion);

/**
 * Fetch an additional value.
 *
 * This is used for special cases where an option have more than one value.
 *
 *
 * @returns VINF_SUCCESS on success.
 * @returns IPRT error status on parse error.
 * @returns VERR_INVALID_PARAMETER if the flags are wrong.
 * @returns VERR_GETOPT_UNKNOWN_OPTION when pState->pDef is null.
 * @returns VERR_GETOPT_REQUIRED_ARGUMENT_MISSING if there are no more
 *          available arguments. pValueUnion->pDef is NULL.
 * @returns VERR_GETOPT_INVALID_ARGUMENT_FORMAT and pValueUnion->pDef if
 *          value conversion failed.
 *
 * @param   pState      The state previously initialized with RTGetOptInit.
 * @param   pValueUnion Union with value; in the event of an error, psz member
 *                      points to erroneous parameter; otherwise, for options
 *                      that require an argument, this contains the value of
 *                      that argument, depending on the type that is required.
 * @param   fFlags      The flags.
 */
RTDECL(int) RTGetOptFetchValue(PRTGETOPTSTATE pState, PRTGETOPTUNION pValueUnion, uint32_t fFlags);

/**
 * Print error messages for a RTGetOpt default case.
 *
 * Uses RTMsgError.
 *
 * @returns Suitable exit code.
 *
 * @param   ch          The RTGetOpt return value.
 * @param   pValueUnion The value union returned by RTGetOpt.
 */
RTDECL(RTEXITCODE) RTGetOptPrintError(int ch, PCRTGETOPTUNION pValueUnion);

/**
 * Parses the @a pszCmdLine string into an argv array.
 *
 * This is useful for converting a response file or similar to an argument
 * vector that can be used with RTGetOptInit().
 *
 * This function aims at following the bourn shell string quoting rules.
 *
 * @returns IPRT status code.
 *
 * @param   ppapszArgv      Where to return the argument vector.  This must be
 *                          freed by calling RTGetOptArgvFree.
 * @param   pcArgs          Where to return the argument count.
 * @param   pszCmdLine      The string to parse.
 * @param   pszSeparators   String containing the argument separators. If NULL,
 *                          then space, tab, line feed (\\n) and return (\\r)
 *                          are used.
 */
RTDECL(int) RTGetOptArgvFromString(char ***ppapszArgv, int *pcArgs, const char *pszCmdLine, const char *pszSeparators);

/**
 * Frees and argument vector returned by RTGetOptStringToArgv.
 *
 * @param   papszArgv       Argument vector.  NULL is fine.
 */
RTDECL(void) RTGetOptArgvFree(char **paArgv);

/**
 * Turns an argv array into a command line string.
 *
 * This is useful for calling CreateProcess on Windows, but can also be used for
 * displaying an argv array.
 *
 * This function aims at following the bourn shell string quoting rules.
 *
 * @returns IPRT status code.
 *
 * @param   ppszCmdLine     Where to return the command line string.  This must
 *                          be freed by calling RTStrFree.
 * @param   papszArgs       The argument vector to convert.
 * @param   fFlags          A combination of the RTGETOPTARGV_CNV_XXX flags.
 */
RTDECL(int) RTGetOptArgvToString(char **ppszCmdLine, const char * const *papszArgv, uint32_t fFlags);

/** @name RTGetOptArgvToString and RTGetOptArgvToUtf16String flags
 * @{ */
/** Quote strings according to the Microsoft CRT rules. */
00412 #define RTGETOPTARGV_CNV_QUOTE_MS_CRT       UINT32_C(0)
/** Quote strings according to the Unix Bourne Shell. */
00414 #define RTGETOPTARGV_CNV_QUOTE_BOURNE_SH    UINT32_C(1)
/** Mask for the quoting style. */
00416 #define RTGETOPTARGV_CNV_QUOTE_MASK         UINT32_C(1)
/** @} */

/**
 * Convenience wrapper around RTGetOpArgvToString and RTStrToUtf16.
 *
 * @returns IPRT status code.
 *
 * @param   ppwszCmdLine    Where to return the command line string.  This must
 *                          be freed by calling RTUtf16Free.
 * @param   papszArgs       The argument vector to convert.
 * @param   fFlags          A combination of the RTGETOPTARGV_CNV_XXX flags.
 */
RTDECL(int) RTGetOptArgvToUtf16String(PRTUTF16 *ppwszCmdLine, const char * const *papszArgv, uint32_t fFlags);

/** @} */

RT_C_DECLS_END

#endif


Generated by  Doxygen 1.6.0   Back to index