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 #include <assert.h>
00035 #include <stdarg.h>
00036 #include <err.h>
00037 #include <errno.h>
00038 #include <getopt.h>
00039 #include <stdlib.h>
00040 #include <str.h>
00041
00042
00043
00044
00045
00046 int opterr = 1;
00047 int optind = 1;
00048 int optopt = '?';
00049 int optreset;
00050 const char *optarg;
00051
00052
00053 #define IGNORE_FIRST (*options == '-' || *options == '+')
00054 #define PRINT_ERROR ((opterr) && ((*options != ':') \
00055 || (IGNORE_FIRST && options[1] != ':')))
00056
00057 #define IS_POSIXLY_CORRECT 0
00058 #define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST)
00059
00060 #define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-')
00061
00062
00063 #define BADCH (int)'?'
00064 #define BADARG ((IGNORE_FIRST && options[1] == ':') \
00065 || (*options == ':') ? (int)':' : (int)'?')
00066 #define INORDER (int)1
00067
00068 #define EMSG ""
00069
00070 static int getopt_internal(int, char **, const char *);
00071 static int gcd(int, int);
00072 static void permute_args(int, int, int, char **);
00073
00074 static const char *place = EMSG;
00075
00076
00077 static int nonopt_start = -1;
00078 static int nonopt_end = -1;
00079
00080
00081
00082
00083
00084
00085
00086 static const char recargchar[] = "option requires an argument -- %c\n";
00087 static const char recargstring[] = "option requires an argument -- %s\n";
00088 static const char ambig[] = "ambiguous option -- %.*s\n";
00089 static const char noarg[] = "option doesn't take an argument -- %.*s\n";
00090 static const char illoptchar[] = "unknown option -- %c\n";
00091 static const char illoptstring[] = "unknown option -- %s\n";
00092
00093
00094
00095
00096
00097 static int
00098 gcd(a, b)
00099 int a;
00100 int b;
00101 {
00102 int c;
00103
00104 c = a % b;
00105 while (c != 0) {
00106 a = b;
00107 b = c;
00108 c = a % b;
00109 }
00110
00111 return b;
00112 }
00113
00114
00115
00116
00117
00118
00119 static void
00120 permute_args(panonopt_start, panonopt_end, opt_end, nargv)
00121 int panonopt_start;
00122 int panonopt_end;
00123 int opt_end;
00124 char **nargv;
00125 {
00126 int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
00127 char *swap;
00128
00129 assert(nargv != NULL);
00130
00131
00132
00133
00134 nnonopts = panonopt_end - panonopt_start;
00135 nopts = opt_end - panonopt_end;
00136 ncycle = gcd(nnonopts, nopts);
00137 cyclelen = (opt_end - panonopt_start) / ncycle;
00138
00139 for (i = 0; i < ncycle; i++) {
00140 cstart = panonopt_end+i;
00141 pos = cstart;
00142 for (j = 0; j < cyclelen; j++) {
00143 if (pos >= panonopt_end)
00144 pos -= nnonopts;
00145 else
00146 pos += nopts;
00147 swap = nargv[pos];
00148 nargv[pos] = nargv[cstart];
00149 nargv[cstart] = swap;
00150 }
00151 }
00152 }
00153
00154
00155
00156
00157
00158
00159 static int
00160 getopt_internal(nargc, nargv, options)
00161 int nargc;
00162 char **nargv;
00163 const char *options;
00164 {
00165 const char *oli;
00166 int optchar;
00167
00168 assert(nargv != NULL);
00169 assert(options != NULL);
00170
00171 optarg = NULL;
00172
00173
00174
00175
00176
00177
00178 if (optind == 0)
00179 optind = 1;
00180
00181 if (optreset)
00182 nonopt_start = nonopt_end = -1;
00183 start:
00184 if (optreset || !*place) {
00185 optreset = 0;
00186 if (optind >= nargc) {
00187 place = EMSG;
00188 if (nonopt_end != -1) {
00189
00190 permute_args(nonopt_start, nonopt_end,
00191 optind, nargv);
00192 optind -= nonopt_end - nonopt_start;
00193 }
00194 else if (nonopt_start != -1) {
00195
00196
00197
00198
00199 optind = nonopt_start;
00200 }
00201 nonopt_start = nonopt_end = -1;
00202 return -1;
00203 }
00204 if ((*(place = nargv[optind]) != '-')
00205 || (place[1] == '\0')) {
00206 place = EMSG;
00207 if (IN_ORDER) {
00208
00209
00210
00211
00212 optarg = nargv[optind++];
00213 return INORDER;
00214 }
00215 if (!PERMUTE) {
00216
00217
00218
00219
00220 return -1;
00221 }
00222
00223 if (nonopt_start == -1)
00224 nonopt_start = optind;
00225 else if (nonopt_end != -1) {
00226 permute_args(nonopt_start, nonopt_end,
00227 optind, nargv);
00228 nonopt_start = optind -
00229 (nonopt_end - nonopt_start);
00230 nonopt_end = -1;
00231 }
00232 optind++;
00233
00234 goto start;
00235 }
00236 if (nonopt_start != -1 && nonopt_end == -1)
00237 nonopt_end = optind;
00238 if (place[1] && *++place == '-') {
00239 place++;
00240 return -2;
00241 }
00242 }
00243 if ((optchar = (int)*place++) == (int)':' ||
00244 (oli = str_chr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) {
00245
00246 if (!*place)
00247 ++optind;
00248 if (PRINT_ERROR)
00249 printf(illoptchar, optchar);
00250 optopt = optchar;
00251 return BADCH;
00252 }
00253 if (optchar == 'W' && oli[1] == ';') {
00254
00255 if (*place)
00256 return -2;
00257
00258 if (++optind >= nargc) {
00259 place = EMSG;
00260 if (PRINT_ERROR)
00261 printf(recargchar, optchar);
00262 optopt = optchar;
00263 return BADARG;
00264 } else
00265 place = nargv[optind];
00266
00267
00268
00269
00270 return -2;
00271 }
00272 if (*++oli != ':') {
00273 if (!*place)
00274 ++optind;
00275 } else {
00276 optarg = NULL;
00277 if (*place)
00278 optarg = place;
00279
00280 else if (oli[1] != ':') {
00281 if (++optind >= nargc) {
00282 place = EMSG;
00283 if (PRINT_ERROR)
00284 printf(recargchar, optchar);
00285 optopt = optchar;
00286 return BADARG;
00287 } else
00288 optarg = nargv[optind];
00289 }
00290 place = EMSG;
00291 ++optind;
00292 }
00293
00294 return optchar;
00295 }
00296
00297
00298
00299
00300
00301 int
00302 getopt(nargc, nargv, options)
00303 int nargc;
00304 char * const *nargv;
00305 const char *options;
00306 {
00307 int retval;
00308
00309 assert(nargv != NULL);
00310 assert(options != NULL);
00311
00312 retval = getopt_internal(nargc, (char **)nargv, options);
00313 if (retval == -2) {
00314 ++optind;
00315
00316
00317
00318
00319 if (nonopt_end != -1) {
00320 permute_args(nonopt_start, nonopt_end, optind,
00321 (char **)nargv);
00322 optind -= nonopt_end - nonopt_start;
00323 }
00324 nonopt_start = nonopt_end = -1;
00325 retval = -1;
00326 }
00327 return retval;
00328 }
00329
00330
00331
00332
00333
00334 int
00335 getopt_long(nargc, nargv, options, long_options, idx)
00336 int nargc;
00337 char * const *nargv;
00338 const char *options;
00339 const struct option *long_options;
00340 int *idx;
00341 {
00342 int retval;
00343
00344 #define IDENTICAL_INTERPRETATION(_x, _y) \
00345 (long_options[(_x)].has_arg == long_options[(_y)].has_arg && \
00346 long_options[(_x)].flag == long_options[(_y)].flag && \
00347 long_options[(_x)].val == long_options[(_y)].val)
00348
00349 assert(nargv != NULL);
00350 assert(options != NULL);
00351 assert(long_options != NULL);
00352
00353
00354 retval = getopt_internal(nargc, (char **)nargv, options);
00355 if (retval == -2) {
00356 char *current_argv;
00357 const char *has_equal;
00358 size_t current_argv_len;
00359 int i, ambiguous, match;
00360
00361 current_argv = (char *)place;
00362 match = -1;
00363 ambiguous = 0;
00364
00365 optind++;
00366 place = EMSG;
00367
00368 if (*current_argv == '\0') {
00369
00370
00371
00372
00373 if (nonopt_end != -1) {
00374 permute_args(nonopt_start, nonopt_end,
00375 optind, (char **)nargv);
00376 optind -= nonopt_end - nonopt_start;
00377 }
00378 nonopt_start = nonopt_end = -1;
00379 return -1;
00380 }
00381 if ((has_equal = str_chr(current_argv, '=')) != NULL) {
00382
00383 current_argv_len = has_equal - current_argv;
00384 has_equal++;
00385 } else
00386 current_argv_len = str_size(current_argv);
00387
00388 for (i = 0; long_options[i].name; i++) {
00389
00390 if (str_lcmp(current_argv, long_options[i].name,
00391 str_nlength(current_argv, current_argv_len)))
00392 continue;
00393
00394 if (str_size(long_options[i].name) ==
00395 (unsigned)current_argv_len) {
00396
00397 match = i;
00398 ambiguous = 0;
00399 break;
00400 }
00401 if (match == -1)
00402 match = i;
00403 else if (!IDENTICAL_INTERPRETATION(i, match))
00404 ambiguous = 1;
00405 }
00406 if (ambiguous) {
00407
00408 if (PRINT_ERROR)
00409 printf(ambig, (int)current_argv_len,
00410 current_argv);
00411 optopt = 0;
00412 return BADCH;
00413 }
00414 if (match != -1) {
00415 if (long_options[match].has_arg == no_argument
00416 && has_equal) {
00417 if (PRINT_ERROR)
00418 printf(noarg, (int)current_argv_len,
00419 current_argv);
00420
00421
00422
00423
00424 if (long_options[match].flag == NULL)
00425 optopt = long_options[match].val;
00426 else
00427 optopt = 0;
00428 return BADARG;
00429 }
00430 if (long_options[match].has_arg == required_argument ||
00431 long_options[match].has_arg == optional_argument) {
00432 if (has_equal)
00433 optarg = has_equal;
00434 else if (long_options[match].has_arg ==
00435 required_argument) {
00436
00437
00438
00439
00440 optarg = nargv[optind++];
00441 }
00442 }
00443 if ((long_options[match].has_arg == required_argument)
00444 && (optarg == NULL)) {
00445
00446
00447
00448
00449 if (PRINT_ERROR)
00450 printf(recargstring, current_argv);
00451
00452
00453
00454
00455 if (long_options[match].flag == NULL)
00456 optopt = long_options[match].val;
00457 else
00458 optopt = 0;
00459 --optind;
00460 return BADARG;
00461 }
00462 } else {
00463 if (PRINT_ERROR)
00464 printf(illoptstring, current_argv);
00465 optopt = 0;
00466 return BADCH;
00467 }
00468 if (long_options[match].flag) {
00469 *long_options[match].flag = long_options[match].val;
00470 retval = 0;
00471 } else
00472 retval = long_options[match].val;
00473 if (idx)
00474 *idx = match;
00475 }
00476 return retval;
00477 #undef IDENTICAL_INTERPRETATION
00478 }
00479