161 lines
3.1 KiB
C
161 lines
3.1 KiB
C
#include "getopt.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
int optind=1;
|
|
int opterr=1;
|
|
int optopt='?';
|
|
char* optarg=NULL;
|
|
|
|
int getopt_long(int argc, char **argv, const char* optstring,
|
|
const struct option *longopts, int* longind) {
|
|
int c;
|
|
const char* ctrl;
|
|
static const char* inlist;
|
|
int mode;
|
|
|
|
switch (*optstring) {
|
|
case '+':mode=REQUIRE_ORDER; optstring++; break;
|
|
case '-':mode=RETURN_IN_ORDER; optstring++; break;
|
|
default: mode=PERMUTE; break;
|
|
}
|
|
optarg=NULL;
|
|
if (inlist) {
|
|
c=*inlist++;
|
|
} else {
|
|
Q2:;
|
|
if (argc<=optind) return -1;
|
|
inlist=argv[optind];
|
|
if (!inlist) return -1;
|
|
c=*inlist++;
|
|
if ((c!='-') && (c!='/')) {
|
|
goto Q1;
|
|
}
|
|
c=*inlist++;
|
|
if (!c) {
|
|
Q1:;
|
|
if (mode == RETURN_IN_ORDER) {
|
|
optarg=argv[optind++];
|
|
inlist=NULL;
|
|
return 1;
|
|
} else if (mode == PERMUTE) {
|
|
int myoptind = optind+1;
|
|
|
|
while (myoptind < argc) {
|
|
inlist=argv[myoptind];
|
|
if (!inlist) return -1;
|
|
c=*inlist++;
|
|
if ((c=='-') || (c=='/')) {
|
|
c=*inlist++;
|
|
if (c) {
|
|
inlist=argv[myoptind];
|
|
memmove(argv+optind+1, argv+optind, sizeof(char*)*(myoptind-optind));
|
|
argv[optind]=inlist;
|
|
inlist=NULL;
|
|
goto Q2;
|
|
}
|
|
}
|
|
myoptind++;
|
|
}
|
|
}
|
|
inlist=NULL;
|
|
return -1;
|
|
}
|
|
if (c=='-') {
|
|
c=*inlist;
|
|
if (!c) {
|
|
optind++;
|
|
inlist=NULL;
|
|
return -1;
|
|
}
|
|
if (longopts) {
|
|
const char* q;
|
|
int ln;
|
|
int i;
|
|
|
|
optind++;
|
|
|
|
q=strchr(inlist, '=');
|
|
if (q) {
|
|
ln=q-inlist;
|
|
q++;
|
|
} else {
|
|
ln=strlen(inlist);
|
|
}
|
|
for (i=0; longopts[i].name; i++) {
|
|
int ln2;
|
|
|
|
ln2=strlen(longopts[i].name);
|
|
if (ln==ln2) if (!memcmp(inlist, longopts[i].name, ln2)) {
|
|
if (longind) *longind=i;
|
|
switch (longopts[i].has_arg) {
|
|
case 0: if (q) {
|
|
if (opterr)
|
|
fprintf(stderr, "%s: option `--%s' doesn't allow an argument\n", argv[0], longopts[i].name);
|
|
inlist=NULL;
|
|
return '?';
|
|
}
|
|
break;
|
|
case 2: break;
|
|
default:if (!q) {
|
|
if (optind>=argc) {
|
|
if (opterr)
|
|
fprintf(stderr, "%s: option `--%s' requires an argument\n", argv[0], longopts[i].name);
|
|
inlist=NULL;
|
|
return ':';
|
|
}
|
|
q=argv[optind++];
|
|
}
|
|
break;
|
|
}
|
|
optarg=q;
|
|
c=longopts[i].val;
|
|
if (longopts[i].flag) {*longopts[i].flag=c; c=0; }
|
|
inlist=NULL;
|
|
return c;
|
|
}
|
|
}
|
|
if (opterr)
|
|
fprintf(stderr, "%s: unrecognized option `%s'\n", argv[0], inlist);
|
|
inlist=NULL;
|
|
return '?';
|
|
}
|
|
}
|
|
}
|
|
if (c==':') {
|
|
ctrl=(optstring[0]==':')?optstring:NULL;
|
|
} else {
|
|
ctrl=strchr(optstring, c);
|
|
}
|
|
if (!*inlist) {
|
|
inlist=NULL;
|
|
optind++;
|
|
}
|
|
if (!ctrl) {
|
|
if (opterr) {
|
|
fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c);
|
|
}
|
|
optopt=c;
|
|
return '?';
|
|
}
|
|
if (ctrl[1]==':') {
|
|
if (!inlist) {
|
|
if ((argc<=optind) || !(inlist=argv[optind])) {
|
|
if (opterr) {
|
|
fprintf(stderr, "%s: option requires an argument -- %c\n", argv[0], c);
|
|
}
|
|
optopt=c;
|
|
return ':';
|
|
}
|
|
}
|
|
optarg=inlist;
|
|
optind++;
|
|
inlist=NULL;
|
|
}
|
|
return c;
|
|
}
|
|
|
|
int getopt(int argc, char ** argv, const char* optstring) {
|
|
return getopt_long(argc, argv, optstring, NULL, NULL);
|
|
}
|