summaryrefslogtreecommitdiff
path: root/src/VBox/Runtime/common/misc/getopt.cpp
blob: 299b361dcdc37395e634417531d1515bd480e7c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/* $Id$ */
/** @file
 * innotek Portable Runtime - Command Line Parsing
 */

/*
 * Copyright (C) 2007 innotek GmbH
 *
 * innotek GmbH confidential
 * All rights reserved
 */

/*******************************************************************************
*   Header Files                                                               *
*******************************************************************************/
#include <iprt/getopt.h>
#include <iprt/err.h>
#include <iprt/string.h>
#include <iprt/assert.h>



RTDECL(int) RTGetOpt(int argc, char *argv[], PCRTOPTIONDEF paOptions, size_t cOptions, int *piThis, PRTOPTIONUNION pValueUnion)
{
    pValueUnion->pDef = NULL;

    if (    !piThis
         || *piThis >= argc
       )
        return 0;

    int iThis = (*piThis)++;
    const char *pszArgThis = argv[iThis];

    if (*pszArgThis == '-')
    {
        for (size_t i = 0; i < cOptions; i++)
        {
            bool fShort = false;
            if (    (   paOptions[i].pszLong
                     && !strcmp(pszArgThis, paOptions[i].pszLong))
                ||  (   (fShort = (pszArgThis[1] == paOptions[i].iShort))
                     && pszArgThis[2] == '\0'
                    )
               )
            {
                Assert(!(paOptions[i].fFlags & ~RTGETOPT_REQ_MASK));
                pValueUnion->pDef = &paOptions[i];

                if ((paOptions[i].fFlags & RTGETOPT_REQ_MASK) != RTGETOPT_REQ_NOTHING)
                {
                    if (iThis >= argc - 1)
                        return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING;

                    int iNext = (*piThis)++;
                    switch (paOptions[i].fFlags & RTGETOPT_REQ_MASK)
                    {
                        case RTGETOPT_REQ_STRING:
                            pValueUnion->psz = argv[iNext];
                            break;

                        case RTGETOPT_REQ_INT32:
                        {
                            int32_t i32;
                            if (RTStrToInt32Full(argv[iNext], 10, &i32))
                                return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;

                            pValueUnion->i32 = i32;
                            break;
                        }

                        case RTGETOPT_REQ_UINT32:
                        {
                            uint32_t u32;
                            if (RTStrToUInt32Full(argv[iNext], 10, &u32))
                                return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
    
                            pValueUnion->u32 = u32;
                            break;
                        }

                        default:
                            AssertMsgFailed(("i=%d f=%#x\n", i, paOptions[i].fFlags));
                            return VERR_INTERNAL_ERROR;
                    }
                }

                return paOptions[i].iShort;
            }
        }
    }

    /** @todo Sort options and arguments (i.e. stuff that doesn't start with '-'), stop when 
     * encountering the first argument. */

    return VERR_GETOPT_UNKNOWN_OPTION;
}