xref: /third_party/python/Python/getopt.c (revision 7db96d56)
1/*---------------------------------------------------------------------------*
2 * <RCS keywords>
3 *
4 * C++ Library
5 *
6 * Copyright 1992-1994, David Gottner
7 *
8 *                    All Rights Reserved
9 *
10 * Permission to use, copy, modify, and distribute this software and its
11 * documentation for any purpose and without fee is hereby granted,
12 * provided that the above copyright notice, this permission notice and
13 * the following disclaimer notice appear unmodified in all copies.
14 *
15 * I DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL I
17 * BE LIABLE FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
18 * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER
19 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 *---------------------------------------------------------------------------*/
22
23/* Modified to support --help and --version, as well as /? on Windows
24 * by Georg Brandl. */
25
26#include <Python.h>
27#include <stdio.h>
28#include <string.h>
29#include <wchar.h>
30#include "pycore_getopt.h"
31
32#ifdef __cplusplus
33extern "C" {
34#endif
35
36int _PyOS_opterr = 1;                 /* generate error messages */
37Py_ssize_t _PyOS_optind = 1;          /* index into argv array   */
38const wchar_t *_PyOS_optarg = NULL;   /* optional argument       */
39
40static const wchar_t *opt_ptr = L"";
41
42/* Python command line short and long options */
43
44#define SHORT_OPTS L"bBc:dEhiIJm:OPqRsStuvVW:xX:?"
45
46static const _PyOS_LongOption longopts[] = {
47    /* name, has_arg, val (used in switch in initconfig.c) */
48    {L"check-hash-based-pycs", 1, 0},
49    {L"help-all", 0, 1},
50    {L"help-env", 0, 2},
51    {L"help-xoptions", 0, 3},
52    {NULL, 0, -1},                     /* sentinel */
53};
54
55
56void _PyOS_ResetGetOpt(void)
57{
58    _PyOS_opterr = 1;
59    _PyOS_optind = 1;
60    _PyOS_optarg = NULL;
61    opt_ptr = L"";
62}
63
64int _PyOS_GetOpt(Py_ssize_t argc, wchar_t * const *argv, int *longindex)
65{
66    wchar_t *ptr;
67    wchar_t option;
68
69    if (*opt_ptr == '\0') {
70
71        if (_PyOS_optind >= argc)
72            return -1;
73#ifdef MS_WINDOWS
74        else if (wcscmp(argv[_PyOS_optind], L"/?") == 0) {
75            ++_PyOS_optind;
76            return 'h';
77        }
78#endif
79
80        else if (argv[_PyOS_optind][0] != L'-' ||
81                 argv[_PyOS_optind][1] == L'\0' /* lone dash */ )
82            return -1;
83
84        else if (wcscmp(argv[_PyOS_optind], L"--") == 0) {
85            ++_PyOS_optind;
86            return -1;
87        }
88
89        else if (wcscmp(argv[_PyOS_optind], L"--help") == 0) {
90            ++_PyOS_optind;
91            return 'h';
92        }
93
94        else if (wcscmp(argv[_PyOS_optind], L"--version") == 0) {
95            ++_PyOS_optind;
96            return 'V';
97        }
98
99        opt_ptr = &argv[_PyOS_optind++][1];
100    }
101
102    if ((option = *opt_ptr++) == L'\0')
103        return -1;
104
105    if (option == L'-') {
106        // Parse long option.
107        if (*opt_ptr == L'\0') {
108            if (_PyOS_opterr) {
109                fprintf(stderr, "expected long option\n");
110            }
111            return -1;
112        }
113        *longindex = 0;
114        const _PyOS_LongOption *opt;
115        for (opt = &longopts[*longindex]; opt->name; opt = &longopts[++(*longindex)]) {
116            if (!wcscmp(opt->name, opt_ptr))
117                break;
118        }
119        if (!opt->name) {
120            if (_PyOS_opterr) {
121                fprintf(stderr, "unknown option %ls\n", argv[_PyOS_optind - 1]);
122            }
123            return '_';
124        }
125        opt_ptr = L"";
126        if (!opt->has_arg) {
127            return opt->val;
128        }
129        if (_PyOS_optind >= argc) {
130            if (_PyOS_opterr) {
131                fprintf(stderr, "Argument expected for the %ls options\n",
132                        argv[_PyOS_optind - 1]);
133            }
134            return '_';
135        }
136        _PyOS_optarg = argv[_PyOS_optind++];
137        return opt->val;
138    }
139
140    if (option == 'J') {
141        if (_PyOS_opterr) {
142            fprintf(stderr, "-J is reserved for Jython\n");
143        }
144        return '_';
145    }
146
147    if ((ptr = wcschr(SHORT_OPTS, option)) == NULL) {
148        if (_PyOS_opterr) {
149            fprintf(stderr, "Unknown option: -%c\n", (char)option);
150        }
151        return '_';
152    }
153
154    if (*(ptr + 1) == L':') {
155        if (*opt_ptr != L'\0') {
156            _PyOS_optarg  = opt_ptr;
157            opt_ptr = L"";
158        }
159
160        else {
161            if (_PyOS_optind >= argc) {
162                if (_PyOS_opterr) {
163                    fprintf(stderr,
164                        "Argument expected for the -%c option\n", (char)option);
165                }
166                return '_';
167            }
168
169            _PyOS_optarg = argv[_PyOS_optind++];
170        }
171    }
172
173    return option;
174}
175
176#ifdef __cplusplus
177}
178#endif
179
180