mirror of
https://github.com/python/cpython.git
synced 2026-10-29 02:45:15 +08:00
188 lines
5.1 KiB
C
188 lines
5.1 KiB
C
/*---------------------------------------------------------------------------*
|
|
* <RCS keywords>
|
|
*
|
|
* C++ Library
|
|
*
|
|
* Copyright 1992-1994, David Gottner
|
|
*
|
|
* All Rights Reserved
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software and its
|
|
* documentation for any purpose and without fee is hereby granted,
|
|
* provided that the above copyright notice, this permission notice and
|
|
* the following disclaimer notice appear unmodified in all copies.
|
|
*
|
|
* I DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL I
|
|
* BE LIABLE FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
|
|
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER
|
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
|
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*---------------------------------------------------------------------------*/
|
|
|
|
/* Modified to support --help and --version, as well as /? on Windows
|
|
* by Georg Brandl. */
|
|
|
|
#include <Python.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <wchar.h>
|
|
#include "pycore_getopt.h" // struct _PyOS_GetOpt
|
|
|
|
|
|
/* Python command line short and long options */
|
|
|
|
#define SHORT_OPTS L"bBc:dEhiIm:OPqRsStuvVW:xX:?"
|
|
|
|
typedef struct {
|
|
const wchar_t *name;
|
|
int has_arg;
|
|
int val;
|
|
} _PyOS_LongOption;
|
|
|
|
static const _PyOS_LongOption longopts[] = {
|
|
/* name, has_arg, val (used in switch in initconfig.c) */
|
|
{L"check-hash-based-pycs", 1, 1},
|
|
{L"help-all", 0, 2},
|
|
{L"help-env", 0, 3},
|
|
{L"help-xoptions", 0, 4},
|
|
{NULL, 0, -1}, /* sentinel */
|
|
};
|
|
|
|
|
|
void
|
|
_PyOS_GetOpt_Init(struct _PyOS_GetOpt *getopt,
|
|
Py_ssize_t argc, wchar_t * const *argv)
|
|
{
|
|
getopt->error = 1;
|
|
getopt->index = 1;
|
|
getopt->arg = NULL;
|
|
getopt->ptr = L"";
|
|
getopt->argc = argc;
|
|
getopt->argv = argv;
|
|
}
|
|
|
|
// Parse a command line option.
|
|
//
|
|
// Return a character for short option (ex: return 'h' for -h).
|
|
// Return a number for long options (see 'longopts' array).
|
|
// Return '_' on unknown option or missing argument.
|
|
// Return -1 when done.
|
|
//
|
|
// Return 'h' for --help and return 'V' for --version.
|
|
//
|
|
// If an option has an argument, set getopt->arg to the argument.
|
|
// If getopt->error is non-error, write error messages to stderr.
|
|
int
|
|
_PyOS_GetOpt(struct _PyOS_GetOpt *getopt)
|
|
{
|
|
// Local copy of read-only members to omit "getopt->"
|
|
const Py_ssize_t argc = getopt->argc;
|
|
wchar_t * const *argv = getopt->argv;
|
|
const int error = getopt->error;
|
|
|
|
if (*getopt->ptr == '\0') {
|
|
if (getopt->index >= argc) {
|
|
return -1;
|
|
}
|
|
|
|
const wchar_t *arg = argv[getopt->index];
|
|
#ifdef MS_WINDOWS
|
|
if (wcscmp(arg, L"/?") == 0) {
|
|
++getopt->index;
|
|
return 'h';
|
|
}
|
|
#endif
|
|
|
|
if (arg[0] != L'-' || arg[1] == L'\0' /* lone dash */ ) {
|
|
return -1;
|
|
}
|
|
|
|
if (wcscmp(arg, L"--") == 0) {
|
|
++getopt->index;
|
|
return -1;
|
|
}
|
|
if (wcscmp(arg, L"--help") == 0) {
|
|
++getopt->index;
|
|
return 'h';
|
|
}
|
|
if (wcscmp(arg, L"--version") == 0) {
|
|
++getopt->index;
|
|
return 'V';
|
|
}
|
|
|
|
getopt->ptr = &argv[getopt->index++][1];
|
|
}
|
|
|
|
wchar_t option = *getopt->ptr++;
|
|
if (option == L'\0') {
|
|
return -1;
|
|
}
|
|
|
|
if (option == L'-') {
|
|
// Parse long option.
|
|
if (*getopt->ptr == L'\0') {
|
|
if (error) {
|
|
fprintf(stderr, "Expected long option\n");
|
|
}
|
|
return -1;
|
|
}
|
|
int longindex = 0;
|
|
const _PyOS_LongOption *opt;
|
|
for (opt = &longopts[longindex]; opt->name; opt = &longopts[++longindex]) {
|
|
if (wcscmp(opt->name, getopt->ptr) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!opt->name) {
|
|
if (error) {
|
|
fprintf(stderr, "Invalid option '%ls'\n", argv[getopt->index - 1]);
|
|
}
|
|
return '_';
|
|
}
|
|
|
|
getopt->ptr = L"";
|
|
if (!opt->has_arg) {
|
|
return opt->val;
|
|
}
|
|
if (getopt->index >= argc) {
|
|
if (error) {
|
|
fprintf(stderr, "Argument expected for the %ls options\n",
|
|
argv[getopt->index - 1]);
|
|
}
|
|
return '_';
|
|
}
|
|
getopt->arg = argv[getopt->index++];
|
|
return opt->val;
|
|
}
|
|
|
|
wchar_t *ptr = wcschr(SHORT_OPTS, option);
|
|
if (ptr == NULL) {
|
|
if (error) {
|
|
fprintf(stderr, "Invalid option '-%lc'\n", option);
|
|
}
|
|
return '_';
|
|
}
|
|
|
|
if (*(ptr + 1) == L':') {
|
|
if (*getopt->ptr != L'\0') {
|
|
getopt->arg = getopt->ptr;
|
|
getopt->ptr = L"";
|
|
}
|
|
else {
|
|
if (getopt->index >= argc) {
|
|
if (error) {
|
|
fprintf(stderr,
|
|
"Argument expected for the -%lc option\n", option);
|
|
}
|
|
return '_';
|
|
}
|
|
|
|
getopt->arg = argv[getopt->index++];
|
|
}
|
|
}
|
|
|
|
return option;
|
|
}
|