00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #define IN_GETOPT_LONG_C 1
00058
00059 #include <config.h>
00060 #include <stdlib.h>
00061 #include <unistd.h>
00062 #include <stdio.h>
00063 #include <string.h>
00064
00065 #ifndef HAVE_GETOPT_LONG
00066
00067 # include "bsd-getopt-long.h"
00068
00069 # ifdef WITH_DMALLOC
00070 # include <dmalloc.h>
00071 # endif
00072
00073 int pure_opterr = 1;
00074 int pure_optind = 1;
00075 int pure_optopt = '?';
00076 int pure_optreset;
00077 const char *pure_optarg;
00078
00079 # define PRINT_ERROR ((pure_opterr) && (*options != ':'))
00080
00081 # define FLAG_PERMUTE 0x01
00082 # define FLAG_ALLARGS 0x02
00083 # define FLAG_LONGONLY 0x04
00084
00085
00086 # define BADCH (int)'?'
00087 # define BADARG ((*options == ':') ? (int)':' : (int)'?')
00088 # define INORDER (int)1
00089
00090 # define EMSG ""
00091
00092 static int pure_getopt_internal(int, char * const *, const char *,
00093 const struct pure_option *, int *, int);
00094 static int pure_parse_long_options(char * const *, const char *,
00095 const struct pure_option *, int *, int);
00096 static int pure_gcd(int, int);
00097 static void pure_permute_args(int, int, int, char * const *);
00098
00099 static const char *pure_place = EMSG;
00100
00101
00102 static int nonopt_start = -1;
00103 static int nonopt_end = -1;
00104
00105
00106 static const char *recargchar = "option requires an argument -- %c\n";
00107 static const char *recargstring = "option requires an argument -- %s\n";
00108 static const char *ambig = "ambiguous option -- %.*s\n";
00109 static const char *noarg = "option doesn't take an argument -- %.*s\n";
00110 static const char *illoptchar = "unknown option -- %c\n";
00111 static const char *illoptstring = "unknown option -- %s\n";
00112
00113
00114
00115
00116 static int pure_gcd(int a, int b)
00117 {
00118 int c;
00119
00120 c = a % b;
00121 while (c != 0) {
00122 a = b;
00123 b = c;
00124 c = a % b;
00125 }
00126 return b;
00127 }
00128
00129
00130
00131
00132
00133
00134 static void pure_permute_args(int panonopt_start, int panonopt_end,
00135 int opt_end, char * const *nargv)
00136 {
00137 int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
00138 char *swap;
00139
00140
00141
00142
00143 nnonopts = panonopt_end - panonopt_start;
00144 nopts = opt_end - panonopt_end;
00145 ncycle = pure_gcd(nnonopts, nopts);
00146 cyclelen = (opt_end - panonopt_start) / ncycle;
00147
00148 for (i = 0; i < ncycle; i++) {
00149 cstart = panonopt_end+i;
00150 pos = cstart;
00151 for (j = 0; j < cyclelen; j++) {
00152 if (pos >= panonopt_end)
00153 pos -= nnonopts;
00154 else
00155 pos += nopts;
00156 swap = nargv[pos];
00157
00158 ((char **) nargv)[pos] = nargv[cstart];
00159
00160 ((char **)nargv)[cstart] = swap;
00161 }
00162 }
00163 }
00164
00165
00166
00167
00168
00169
00170 static int pure_parse_long_options(char * const *nargv, const char *options,
00171 const struct pure_option *long_options,
00172 int *idx, int short_too)
00173 {
00174 const char *current_argv, *has_equal;
00175 size_t current_argv_len;
00176 int i, match;
00177
00178 current_argv = pure_place;
00179 match = -1;
00180
00181 pure_optind++;
00182
00183 if ((has_equal = strchr(current_argv, '=')) != NULL) {
00184
00185 current_argv_len = has_equal - current_argv;
00186 has_equal++;
00187 } else
00188 current_argv_len = strlen(current_argv);
00189
00190 for (i = 0; long_options[i].name; i++) {
00191
00192 if (strncmp(current_argv, long_options[i].name,
00193 current_argv_len))
00194 continue;
00195
00196 if (strlen(long_options[i].name) == current_argv_len) {
00197
00198 match = i;
00199 break;
00200 }
00201
00202
00203
00204
00205 if (short_too && current_argv_len == 1)
00206 continue;
00207
00208 if (match == -1)
00209 match = i;
00210 else {
00211
00212 if (PRINT_ERROR)
00213 fprintf(stderr, ambig, (int)current_argv_len,
00214 current_argv);
00215 pure_optopt = 0;
00216 return BADCH;
00217 }
00218 }
00219 if (match != -1) {
00220 if (long_options[match].has_arg == no_argument
00221 && has_equal) {
00222 if (PRINT_ERROR)
00223 fprintf(stderr, noarg, (int)current_argv_len,
00224 current_argv);
00225
00226
00227
00228 if (long_options[match].flag == NULL)
00229 pure_optopt = long_options[match].val;
00230 else
00231 pure_optopt = 0;
00232 return BADARG;
00233 }
00234 if (long_options[match].has_arg == required_argument ||
00235 long_options[match].has_arg == optional_argument) {
00236 if (has_equal)
00237 pure_optarg = has_equal;
00238 else if (long_options[match].has_arg ==
00239 required_argument) {
00240
00241
00242
00243 pure_optarg = nargv[pure_optind++];
00244 }
00245 }
00246 if ((long_options[match].has_arg == required_argument)
00247 && (pure_optarg == NULL)) {
00248
00249
00250
00251
00252 if (PRINT_ERROR)
00253 fprintf(stderr, recargstring,
00254 current_argv);
00255
00256
00257
00258 if (long_options[match].flag == NULL)
00259 pure_optopt = long_options[match].val;
00260 else
00261 pure_optopt = 0;
00262 --pure_optind;
00263 return BADARG;
00264 }
00265 } else {
00266 if (short_too) {
00267 --pure_optind;
00268 return -1;
00269 }
00270 if (PRINT_ERROR)
00271 fprintf(stderr, illoptstring, current_argv);
00272 pure_optopt = 0;
00273 return BADCH;
00274 }
00275 if (idx)
00276 *idx = match;
00277 if (long_options[match].flag) {
00278 *long_options[match].flag = long_options[match].val;
00279 return 0;
00280 } else
00281 return long_options[match].val;
00282 }
00283
00284
00285
00286
00287
00288 static int pure_getopt_internal(int nargc, char * const *nargv,
00289 const char *options,
00290 const struct pure_option *long_options,
00291 int *idx, int flags)
00292 {
00293 char *oli;
00294 int optchar, short_too;
00295 static int posixly_correct = -1;
00296
00297 if (options == NULL)
00298 return -1;
00299
00300
00301
00302
00303
00304 if (posixly_correct == -1)
00305 posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
00306 if (posixly_correct || *options == '+')
00307 flags &= ~FLAG_PERMUTE;
00308 else if (*options == '-')
00309 flags |= FLAG_ALLARGS;
00310 if (*options == '+' || *options == '-')
00311 options++;
00312
00313
00314
00315
00316
00317 if (pure_optind == 0)
00318 pure_optind = pure_optreset = 1;
00319
00320 pure_optarg = NULL;
00321 if (pure_optreset)
00322 nonopt_start = nonopt_end = -1;
00323 start:
00324 if (pure_optreset || !*pure_place) {
00325 pure_optreset = 0;
00326 if (pure_optind >= nargc) {
00327 pure_place = EMSG;
00328 if (nonopt_end != -1) {
00329
00330 pure_permute_args(nonopt_start, nonopt_end,
00331 pure_optind, nargv);
00332 pure_optind -= nonopt_end - nonopt_start;
00333 }
00334 else if (nonopt_start != -1) {
00335
00336
00337
00338
00339 pure_optind = nonopt_start;
00340 }
00341 nonopt_start = nonopt_end = -1;
00342 return -1;
00343 }
00344 if (*(pure_place = nargv[pure_optind]) != '-' ||
00345 (pure_place[1] == '\0' && strchr(options, '-') == NULL)) {
00346 pure_place = EMSG;
00347 if (flags & FLAG_ALLARGS) {
00348
00349
00350
00351
00352 pure_optarg = nargv[pure_optind++];
00353 return INORDER;
00354 }
00355 if (!(flags & FLAG_PERMUTE)) {
00356
00357
00358
00359
00360 return -1;
00361 }
00362
00363 if (nonopt_start == -1)
00364 nonopt_start = pure_optind;
00365 else if (nonopt_end != -1) {
00366 pure_permute_args(nonopt_start, nonopt_end,
00367 pure_optind, nargv);
00368 nonopt_start = pure_optind -
00369 (nonopt_end - nonopt_start);
00370 nonopt_end = -1;
00371 }
00372 pure_optind++;
00373
00374 goto start;
00375 }
00376 if (nonopt_start != -1 && nonopt_end == -1)
00377 nonopt_end = pure_optind;
00378
00379
00380
00381
00382
00383
00384 if (pure_place[1] != '\0' && *++pure_place == '-' &&
00385 (pure_place[1] == '\0' || long_options == NULL)) {
00386 pure_optind++;
00387 pure_place = EMSG;
00388
00389
00390
00391
00392 if (nonopt_end != -1) {
00393 pure_permute_args(nonopt_start, nonopt_end,
00394 pure_optind, nargv);
00395 pure_optind -= nonopt_end - nonopt_start;
00396 }
00397 nonopt_start = nonopt_end = -1;
00398 return -1;
00399 }
00400 }
00401
00402
00403
00404
00405
00406
00407
00408 if (long_options != NULL && pure_place != nargv[pure_optind] &&
00409 (*pure_place == '-' || (flags & FLAG_LONGONLY))) {
00410 short_too = 0;
00411 if (*pure_place == '-')
00412 pure_place++;
00413 else if (*pure_place != ':' && strchr(options, *pure_place) != NULL)
00414 short_too = 1;
00415
00416 optchar = pure_parse_long_options(nargv, options, long_options,
00417 idx, short_too);
00418 if (optchar != -1) {
00419 pure_place = EMSG;
00420 return optchar;
00421 }
00422 }
00423
00424 if ((optchar = (int) *pure_place++) == ':' ||
00425 (optchar == '-' && *pure_place != '\0') ||
00426 (oli = strchr(options, optchar)) == NULL) {
00427
00428
00429
00430
00431
00432 if (optchar == '-' && *pure_place == '\0')
00433 return -1;
00434 if (!*pure_place)
00435 ++pure_optind;
00436 if (PRINT_ERROR)
00437 fprintf(stderr, illoptchar, optchar);
00438 pure_optopt = optchar;
00439 return BADCH;
00440 }
00441 if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
00442
00443 if (*pure_place)
00444 ;
00445 else if (++pure_optind >= nargc) {
00446 pure_place = EMSG;
00447 if (PRINT_ERROR)
00448 fprintf(stderr, recargchar, optchar);
00449 pure_optopt = optchar;
00450 return BADARG;
00451 } else
00452 pure_place = nargv[pure_optind];
00453 optchar = pure_parse_long_options(nargv, options, long_options,
00454 idx, 0);
00455 pure_place = EMSG;
00456 return optchar;
00457 }
00458 if (*++oli != ':') {
00459 if (!*pure_place)
00460 ++pure_optind;
00461 } else {
00462 pure_optarg = NULL;
00463 if (*pure_place)
00464 pure_optarg = pure_place;
00465
00466 else if (oli[1] != ':') {
00467 if (++pure_optind >= nargc) {
00468 pure_place = EMSG;
00469 if (PRINT_ERROR)
00470 fprintf(stderr, recargchar, optchar);
00471 pure_optopt = optchar;
00472 return BADARG;
00473 } else {
00474 pure_optarg = nargv[pure_optind];
00475 }
00476 }
00477 pure_place = EMSG;
00478 ++pure_optind;
00479 }
00480
00481 return optchar;
00482 }
00483
00484
00485
00486
00487
00488 int pure_getopt(int nargc, char * const *nargv, const char *options)
00489 {
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499 return pure_getopt_internal(nargc, nargv, options, NULL, NULL, 0);
00500 }
00501
00502
00503
00504
00505
00506 int pure_getopt_long(int nargc, char * const *nargv, const char *options,
00507 const struct pure_option *long_options, int *idx)
00508 {
00509 return pure_getopt_internal(nargc, nargv, options, long_options, idx,
00510 FLAG_PERMUTE);
00511 }
00512
00513
00514
00515
00516
00517 int pure_getopt_long_only(int nargc, char * const *nargv,
00518 const char *options,
00519 const struct pure_option *long_options,
00520 int *idx)
00521 {
00522 return pure_getopt_internal(nargc, nargv, options, long_options, idx,
00523 FLAG_PERMUTE|FLAG_LONGONLY);
00524 }
00525
00526 #endif