int getopt(int argc, char** argv, const char* optstr) { int c = 0; /* If we have new argv, reinitialize */ if(prev_argv != argv || prev_argc != argc) { /* Initialize variables */ prev_argv = argv; prev_argc = argc; argv_index = 1; argv_index2 = 1; opt_offset = 1; dashdash = 0; nonopt = 0; } /* Jump point in case we want to ignore the current argv_index */ getopt_top: /* Misc. initializations */ optarg = NULL; /* Dash-dash check */ if(argv[argv_index] && !strcmp(argv[argv_index], "--")) { dashdash = 1; increment_index(); } /* If we're at the end of argv, that's it. */ if(argv[argv_index] == NULL) { c = -1; } /* Are we looking at a string? Single dash is also a string */ else if(dashdash || argv[argv_index][0] != '-' || !strcmp(argv[argv_index], "-")) { /* If we want a string... */ if(optstr[0] == '-') { c = 1; optarg = argv[argv_index]; increment_index(); } /* If we really don't want it (we're in POSIX mode), we're done */ else if(optstr[0] == '+' || getenv("POSIXLY_CORRECT")) { c = -1; /* Everything else is a non-opt argument */ nonopt = argc - argv_index; } /* If we mildly don't want it, then move it back */ else { if(!permute_argv_once()) goto getopt_top; else c = -1; } } /* Otherwise we're looking at an option */ else { char* opt_ptr = NULL; /* Grab the option */ c = argv[argv_index][opt_offset++]; /* Is the option in the optstr? */ if(optstr[0] == '-') opt_ptr = strchr(optstr+1, c); else opt_ptr = strchr(optstr, c); /* Invalid argument */ if(!opt_ptr) { if(opterr) { fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c); } optopt = c; c = '?'; /* Move onto the next option */ increment_index(); } /* Option takes argument */ else if(opt_ptr[1] == ':') { /* ie, -oARGUMENT, -xxxoARGUMENT, etc. */ if(argv[argv_index][opt_offset] != '\0') { optarg = &argv[argv_index][opt_offset]; increment_index(); } /* ie, -o ARGUMENT (only if it's a required argument) */ else if(opt_ptr[2] != ':') { /* One of those "you're not expected to understand this" moment */ if(argv_index2 < argv_index) argv_index2 = argv_index; while(argv[++argv_index2] && argv[argv_index2][0] == '-'); optarg = argv[argv_index2]; /* Don't cross into the non-option argument list */ if(argv_index2 + nonopt >= prev_argc) optarg = NULL; /* Move onto the next option */ increment_index(); } else { /* Move onto the next option */ increment_index(); } /* In case we got no argument for an option with required argument */ if(optarg == NULL && opt_ptr[2] != ':') { optopt = c; c = '?'; if(opterr) { fprintf(stderr,"%s: option requires an argument -- %c\n", argv[0], optopt); } } } /* Option does not take argument */ else { /* Next argv_index */ if(argv[argv_index][opt_offset] == '\0') { increment_index(); } } } /* Calculate optind */ if(c == -1) { optind = argc - nonopt; } else { optind = argv_index; } return c; }
int getopt(int argc, char** argv, char* optstr) { int c = 0; if(prev_argv != argv || prev_argc != argc) { prev_argv = argv; prev_argc = argc; argv_index = 1; argv_index2 = 1; opt_offset = 1; dashdash = 0; nonopt = 0; } getopt_top: optarg = NULL; if(argv[argv_index] && !strcmp(argv[argv_index], "--")) { dashdash = 1; increment_index(); } if(argv[argv_index] == NULL) { c = -1; } else if(dashdash || argv[argv_index][0] != '-' || !strcmp(argv[argv_index], "-")) { if(optstr[0] == '-') { c = 1; optarg = argv[argv_index]; increment_index(); } else if(optstr[0] == '+' || getenv("POSIXLY_CORRECT")) { c = -1; nonopt = argc - argv_index; } else { if(!permute_argv_once()) goto getopt_top; else c = -1; } } else { char* opt_ptr = NULL; c = argv[argv_index][opt_offset++]; if(optstr[0] == '-') opt_ptr = strchr(optstr+1, c); else opt_ptr = strchr(optstr, c); if(!opt_ptr) { if(opterr) { fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c); } optopt = c; c = '?'; increment_index(); } else if(opt_ptr[1] == ':') { if(argv[argv_index][opt_offset] != '\0') { optarg = &argv[argv_index][opt_offset]; increment_index(); } else if(opt_ptr[2] != ':') { if(argv_index2 < argv_index) argv_index2 = argv_index; while(argv[++argv_index2] && argv[argv_index2][0] == '-'); optarg = argv[argv_index2]; if(argv_index2 + nonopt >= prev_argc) optarg = NULL; increment_index(); } else { increment_index(); } if(optarg == NULL && opt_ptr[2] != ':') { optopt = c; c = '?'; if(opterr) { fprintf(stderr,"%s: option requires an argument -- %c\n", argv[0], optopt); } } } else { if(argv[argv_index][opt_offset] == '\0') { increment_index(); } } } if(c == -1) { optind = argc - nonopt; } else { optind = argv_index; } return c; }