You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

142 lines
3.9 KiB
C++

// ***************************************************************** -*- C++ -*-
/*
* Copyright (C) 2004-2021 Exiv2 authors
* This program is part of the Exiv2 distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
*/
#if _MSC_VER >= 1400
# pragma warning(disable : 4996)
#endif
// included header files
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <iostream>
#include "utils.hpp"
#include "getopt.hpp"
namespace Util {
// https://raw.githubusercontent.com/skeeto/getopt/master/getopt.h
int optind = 0;
int opterr = 1;
int optopt;
int optpos = 1;
const char* optarg;
/* A minimal POSIX getopt() implementation in ANSI C
*
* This is free and unencumbered software released into the public domain.
*
* This implementation supports the convention of resetting the option
* parser by assigning optind to 0. This resets the internal state
* appropriately.
*
* Ref: http://pubs.opengroup.org/onlinepubs/9699919799/functions/getopt.html
*/
int getopt(int argc, char * const argv[], const char *optstring)
{
const char *arg;
(void)argc;
/* Reset? */
if (optind == 0) {
optind = 1;
optpos = 1;
}
arg = argv[optind];
if (arg && strcmp(arg, "--") == 0) {
optind++;
return -1;
}
if (!arg || arg[0] != '-' || !isalnum(arg[1])) {
return -1;
}
const char *opt = strchr(optstring, arg[optpos]);
optopt = arg[optpos];
if (!opt) {
if (opterr && *optstring != ':')
fprintf(stderr, "%s: illegal option: %c\n", argv[0], optopt);
return '?';
}
if (opt[1] == ':') {
if (arg[optpos + 1]) {
optarg = const_cast<char*>(arg) + optpos + 1;
optind++;
optpos = 1;
return optopt;
}
if (argv[optind + 1]) {
optarg = argv[optind + 1];
optind += 2;
optpos = 1;
return optopt;
}
if (opterr && *optstring != ':')
fprintf(stderr, "%s: option requires an argument: %c\n", argv[0], optopt);
return *optstring == ':' ? ':' : '?';
}
if (!arg[++optpos]) {
optind++;
optpos = 1;
}
return optopt;
}
// *****************************************************************************
// class Getopt
Getopt::Getopt()
: errcnt_(0)
{
}
int Getopt::getopt(int argc, char* const argv[], const std::string& optstring)
{
progname_ = Util::basename(argv[0]);
Util::optind = 0; // reset the Util::Getopt scanner
7 years ago
for (;!errcnt_;) {
int c = Util::getopt(argc, argv, optstring.c_str());
if (c == -1) {
break;
}
errcnt_ += option(c, Util::optarg == nullptr ? "" : Util::optarg, Util::optopt);
if (c == '?' ) {
break;
}
}
for (int i = Util::optind; i < argc; i++) {
errcnt_ += nonoption(argv[i]);
}
return errcnt_;
}
int Getopt::nonoption(const std::string& /*argv*/)
{
return 0;
}
} // namespace Util