#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#define OPTERRCOLON (1)
#define OPTERRNF (2)
#define OPTERRARG (3)
char
*optarg;
int
optind = 1;
int
opterr = 1;
int
optopt;
static
int
optiserr(
int
argc,
char
*
const
*argv,
int
oint,
const
char
*optstr,
int
optchr,
int
err)
{
if
(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,
"no argument for option %c\n"
, argv[oint][optchr]);
break
;
default
:
fprintf
(stderr,
"unknown\n"
);
break
;
}
}
optopt = argv[oint][optchr];
return
(
'?'
);
}
int
getopt(
int
argc,
char
*
const
*argv,
const
char
*optstr)
{
static
int
optchr = 0;
static
int
dash = 0;
char
*cp;
if
(optind >= argc)
return
(EOF);
if
(!dash && (argv[optind][0] !=
'-'
))
return
(EOF);
if
(!dash && (argv[optind][0] ==
'-'
) && !argv[optind][1]) {
return
(EOF);
}
if
((argv[optind][0] ==
'-'
) && (argv[optind][1] ==
'-'
)) {
optind++;
return
(EOF);
}
if
(!dash) {
assert
((argv[optind][0] ==
'-'
) && argv[optind][1]);
dash = 1;
optchr = 1;
}
assert
(dash);
if
(argv[optind][optchr] ==
':'
) {
dash = 0;
optind++;
return
(optiserr(argc, argv, optind-1, optstr, optchr, OPTERRCOLON));
}
if
(!(cp =
strchr
(optstr, argv[optind][optchr]))) {
int
errind = optind;
int
errchr = optchr;
if
(!argv[optind][optchr+1]) {
dash = 0;
optind++;
}
else
optchr++;
return
(optiserr(argc, argv, errind, optstr, errchr, OPTERRNF));
}
if
(cp[1] ==
':'
) {
dash = 0;
optind++;
if
(optind == argc)
return
(optiserr(argc, argv, optind-1, optstr, optchr, OPTERRARG));
optarg = argv[optind++];
return
(*cp);
}
else
{
if
(!argv[optind][optchr+1]) {
dash = 0;
optind++;
}
else
optchr++;
return
(*cp);
}
assert
(0);
return
(0);
}
#ifdef TESTGETOPT
int
main(
int
argc,
char
**argv)
{
int
c;
extern
char
*optarg;
extern
int
optind;
int
aflg = 0;
int
bflg = 0;
int
errflg = 0;
char
*ofile = NULL;
while
((c = 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 = optarg;
(
void
)
printf
(
"ofile = %s\n"
, ofile);
break
;
case
'?'
:
errflg++;
}
if
(errflg) {
(
void
)
fprintf
(stderr,
"usage: cmd [-a|-b] [-o <filename>] files...\n"
);
exit
(2);
}
for
( ; optind < argc; optind++)
(
void
)
printf
(
"%s\n"
, argv[optind]);
return
0;
}
#endif /* TESTGETOPT */