Skip to content

Commit

Permalink
optstring 先頭の + に対応。--が現れたら解析を終了
Browse files Browse the repository at this point in the history
  • Loading branch information
takamin committed Apr 6, 2015
1 parent 33cbd36 commit 3f0a9a9
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 10 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ __関数__

関数の動作は、[POSIXのgetopt](http://linuxjm.sourceforge.jp/html/LDP_man-pages/man3/getopt.3.html)にあわせているつもりです。

* argvを並べ替えることはありません。
* オプションでない引数が現れた時点で解析を終了します。
* オプションは1文字だけです。長いオプション名には対応していません。
* optstring の先頭が '-' である場合の動作は正しくありません。

### 使用例

Expand Down
67 changes: 60 additions & 7 deletions source/getopt.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,35 @@ int optind = 1;
int opterr = 1;
int optopt = 0;

static void postpone(int argc, char* const argv[], int index) {
char** nc_argv = (char**)argv;
char* p = nc_argv[index];
int j = index;
for(; j < argc - 1; j++) {
nc_argv[j] = nc_argv[j + 1];
}
nc_argv[argc - 1] = p;
}
static int postpone_noopt(int argc, char* const argv[], int index) {
int i = index;
for(; i < argc; i++) {
if(*(argv[i]) == '-') {
postpone(argc, argv, index);
return 1;
}
}
return 0;
}
int getopt(int argc, char* const argv[],
const char* optstring)
{
static int postpone_count = 0;
static int nextchar = 0;
while(1) {
int c;
const char* optptr = 0;
if(optind >= argc) {
nextchar = 0;
return -1;
if(optind >= argc - postpone_count) {
break;
}
c = *(argv[optind] + nextchar);
if(c == '\0') {
Expand All @@ -33,10 +52,31 @@ int getopt(int argc, char* const argv[],
continue;
}
if(nextchar == 0) {
if(optstring[0] != '+') {
/*************************
if(optstring[0] == '-') {
optarg = argv[optind];
nextchar = 0;
++optind;
return 1;
}
*************************/
while(c != '-') {
/* postpone non-opt parameter */
if(!postpone_noopt(argc, argv, optind)) {
break; /* all args are non-opt param */
}
++postpone_count;
c = *argv[optind];
}
}
if(c != '-') {
nextchar = 0;
return -1;
break;
} else {
if(strcmp(argv[optind], "--") == 0) {
optind++;
break;
}
++nextchar;
continue;
}
Expand Down Expand Up @@ -65,7 +105,7 @@ int getopt(int argc, char* const argv[],
optarg = argv[optind] + nextchar;
} else {
++optind;
if(optind < argc) {
if(optind < argc - postpone_count) {
optarg = argv[optind];
} else {
optopt = c;
Expand All @@ -74,7 +114,9 @@ int getopt(int argc, char* const argv[],
"%s : argument required for option '%c'.\n",
argv[0], c);
}
if(optstring[0] == ':') {
if(optstring[0] == ':'
|| (optstring[0] == '-' || optstring[0] == '+') && optstring[1] == ':')
{
c = ':';
} else {
c = '?';
Expand All @@ -86,6 +128,17 @@ int getopt(int argc, char* const argv[],
}
return c;
}

/* end of option analysis */

/* fix the order of non-opt params to original */
while((argc - optind - postpone_count) > 0) {
postpone(argc, argv, optind);
++postpone_count;
}

nextchar = 0;
postpone_count = 0;
return -1;
}

Expand Down
2 changes: 1 addition & 1 deletion test/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ int main(int argc, char* argv[]) {
} while(opt >= 0);
cout << "non option parameter ---- " << endl;
for(int i = 0; optind + i < argc; i++) {
cout << "argv[optind+" << i << "]=" << argv[optind + i];
cout << "argv[optind+" << i << "]=" << argv[optind + i] << endl;
}
}

0 comments on commit 3f0a9a9

Please sign in to comment.