#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include "getopt.h"
#ifdef WIN32
#ifdef _MSC_VER
#pragma warning( disable : 4702 )
#endif
#endif /* WIN32 */
#define OPTERRCOLON (1)
#define OPTERRNF (2)
#define OPTERRARG (3)
char
*spamc_optarg;
int
spamc_optreset = 0;
int
spamc_optind = 1;
int
spamc_opterr = 1;
int
spamc_optopt;
static
int
optiserr(
int
argc,
char
*
const
*argv,
int
oint,
const
char
*optstr,
int
optchr,
int
err)
{
(
void
) argc;
(
void
) optstr;
if
(spamc_opterr)
{
fprintf
(stderr,
"Error in argument %d, char %d: "
, oint, optchr+1);
switch
(err)
{
case
OPTERRCOLON:
fprintf
(stderr,
": in flags\n"
);
break
;
case
OPTERRNF:
fprintf
(stderr,
"option not found %c\n"
, argv[oint][optchr]);
break
;
case
OPTERRARG:
fprintf
(stderr,
"argument required for option %c\n"
, argv[oint][optchr]);
break
;
default
:
fprintf
(stderr,
"unknown\n"
);
break
;
}
}
spamc_optopt = argv[oint][optchr];
return
(
'?'
);
}
static
int
longoptiserr(
int
argc,
char
*
const
*argv,
int
oint,
int
err)
{
(
void
) argc;
if
(spamc_opterr)
{
fprintf
(stderr,
"Error in argument %d : "
, oint);
switch
(err)
{
case
OPTERRCOLON:
fprintf
(stderr,
": in flags\n"
);
break
;
case
OPTERRNF:
fprintf
(stderr,
"option not found %s\n"
, argv[oint]);
break
;
case
OPTERRARG:
fprintf
(stderr,
"argument required for option %s\n"
, argv[oint]);
break
;
default
:
fprintf
(stderr,
"unknown\n"
);
break
;
}
}
return
(
'?'
);
}
int
spamc_getopt(
int
argc,
char
*
const
*argv,
const
char
*optstr)
{
static
int
optchr = 0;
static
int
dash = 0;
char
*cp;
if
(spamc_optreset)
spamc_optreset = optchr = dash = 0;
if
(spamc_optind >= argc)
return
(EOF);
if
(!dash && (argv[spamc_optind][0] !=
'-'
))
return
(EOF);
if
(!dash && (argv[spamc_optind][0] ==
'-'
) && !argv[spamc_optind][1])
{
return
(EOF);
}
if
((argv[spamc_optind][0] ==
'-'
) && (argv[spamc_optind][1] ==
'-'
))
{
spamc_optind++;
return
(EOF);
}
if
(!dash)
{
assert
((argv[spamc_optind][0] ==
'-'
) && argv[spamc_optind][1]);
dash = 1;
optchr = 1;
}
assert
(dash);
if
(argv[spamc_optind][optchr] ==
':'
)
{
dash = 0;
spamc_optind++;
return
(optiserr(argc, argv, spamc_optind-1, optstr, optchr, OPTERRCOLON));
}
cp =
strchr
(optstr, argv[spamc_optind][optchr]);
if
(!cp)
{
int
errind = spamc_optind;
int
errchr = optchr;
if
(!argv[spamc_optind][optchr+1])
{
dash = 0;
spamc_optind++;
}
else
optchr++;
return
(optiserr(argc, argv, errind, optstr, errchr, OPTERRNF));
}
if
(cp[1] ==
':'
)
{
dash = 0;
spamc_optind++;
if
(spamc_optind == argc)
return
(optiserr(argc, argv, spamc_optind-1, optstr, optchr, OPTERRARG));
spamc_optarg = argv[spamc_optind++];
return
(*cp);
}
else
{
if
(!argv[spamc_optind][optchr+1])
{
dash = 0;
spamc_optind++;
}
else
optchr++;
return
(*cp);
}
assert
(0);
return
(0);
}
int
spamc_getopt_long(
int
argc,
char
*
const
argv[],
const
char
*optstring,
struct
option *longopts,
int
*longindex)
{
static
int
optchr = 0;
static
int
dash = 0;
char
*cp, *longopt;
char
*bp, *opt = NULL;
int
i, longoptlen;;
spamc_optarg = NULL;
if
(spamc_optreset)
spamc_optreset = optchr = dash = 0;
if
(spamc_optind >= argc) {
return
(EOF);
}
if
(!dash && (argv[spamc_optind][0] !=
'-'
)) {
return
(EOF);
}
if
(!dash && (argv[spamc_optind][0] ==
'-'
) && !argv[spamc_optind][1]) {
return
(EOF);
}
if
((argv[spamc_optind][0] ==
'-'
) && (argv[spamc_optind][1] ==
'-'
)
&& !argv[spamc_optind][2]) {
return
(EOF);
}
if
((argv[spamc_optind][0] ==
'-'
) && argv[spamc_optind][1] &&
(argv[spamc_optind][1] !=
'-'
)) {
optchr = 1;
if
(argv[spamc_optind][optchr] ==
':'
)
return
(optiserr(argc, argv, spamc_optind++, optstring, optchr, OPTERRCOLON));
cp =
strchr
(optstring, argv[spamc_optind++][optchr]);
if
(cp == NULL)
return
(optiserr(argc, argv, spamc_optind-1, optstring, optchr, OPTERRNF));
if
(cp[1] ==
':'
) {
if
(!argv[spamc_optind] || (argv[spamc_optind][0] ==
'-'
) ||
(spamc_optind >= argc)) {
return
(optiserr(argc, argv, spamc_optind-1, optstring, optchr, OPTERRARG));
}
spamc_optarg = argv[spamc_optind++];
return
(*cp);
}
else
{
dash = 0;
return
(*cp);
}
}
if
((argv[spamc_optind][0] ==
'-'
) && (argv[spamc_optind][1] ==
'-'
) &&
argv[spamc_optind][2]) {
optchr = 2;
longopt = argv[spamc_optind++];
if
(longopt[2] ==
':'
)
return
(longoptiserr(argc, argv, spamc_optind, OPTERRCOLON));
longoptlen =
strlen
(longopt) - 2;
if
((bp =
strchr
(longopt,
'='
))) {
opt = strdup(bp+1);
if
(opt == NULL) {
fprintf
(stderr,
"%s: %s\n"
, argv[0],
strerror
(
errno
));
exit
(1);
}
longoptlen -=
strlen
(bp);
}
for
(i=0; ; i++) {
if
((longopts[i].name == NULL) || (longopts[i].name[0] == 0)) {
free
(opt);
return
(longoptiserr(argc, argv, spamc_optind-1, OPTERRNF));
}
if
(((
strncmp
(longopt+2, longopts[i].name, longoptlen)) == 0) && (
strlen
(longopts[i].name) == longoptlen)) {
*longindex = i;
if
(longopts[i].has_arg == required_argument) {
if
(((spamc_optind >= argc) || (!argv[spamc_optind]) || (argv[spamc_optind][0] ==
'-'
)) &&
(opt == NULL)) {
free
(opt);
return
(longoptiserr(argc, argv, spamc_optind-1, OPTERRARG));
}
if
(opt != NULL) {
spamc_optarg = opt;
}
else
{
spamc_optarg = argv[spamc_optind++];
}
}
else
if
(longopts[i].has_arg == optional_argument) {
if
(((spamc_optind < argc) && (argv[spamc_optind]) && (argv[spamc_optind][0] !=
'-'
)) ||
(opt != NULL)) {
if
(opt != NULL) {
spamc_optarg = opt;
}
else
{
spamc_optarg = argv[spamc_optind++];
}
}
}
if
(longopts[i].flag == NULL) {
return
(longopts[i].val);
}
else
{
*longopts[i].flag = longopts[i].val;
return
(0);
}
}
}
}
return
(0);
}
#ifdef TESTGETOPT
int
main (
int
argc,
char
**argv)
{
int
c, l;
extern
char
*spamc_optarg;
extern
int
spamc_optind;
int
aflg = 0;
int
bflg = 0;
int
errflg = 0;
char
*ofile = NULL;
struct
option longopts[] = {
{
"test"
, required_argument, 0,
't'
},
};
while
((c = spamc_getopt(argc, argv,
"abo:"
)) != EOF)
switch
(c) {
case
'a'
:
if
(bflg)
errflg++;
else
aflg++;
break
;
case
'b'
:
if
(aflg)
errflg++;
else
bflg++;
break
;
case
'o'
:
ofile = spamc_optarg;
(
void
)
printf
(
"ofile = %s\n"
, ofile);
break
;
case
'?'
:
errflg++;
}
while
((l = spamc_getopt_long(argc, argv,
"t:"
, longopts, &l)) != EOF)
switch
(l) {
case
't'
:
printf
(
"--test = %s\n"
,spamc_optarg);
break
;
}
if
(errflg) {
(
void
)
fprintf
(stderr,
"usage: cmd [-a|-b] [-o <filename>] files...\n"
);
exit
(2);
}
return
0;
}
#endif /* TESTGETOPT */