/* * getopt.c * * Simple POSIX getopt(), no GNU extensions... */ #include #include #include char *optarg; int optind = 1; int opterr, optopt; static const char *__optptr; int getopt(int argc, char * const *argv, const char *optstring) { const char *carg = argv[optind]; const char *osptr; int opt; /* We don't actually need argc */ (void)argc; /* First, eliminate all non-option cases */ if ( !carg || carg[0] != '-' || !carg[1] ) { return -1; } if ( carg[1] == '-' && !carg[2] ) { optind++; return -1; } if ( (uintptr_t)(__optptr-carg) > (uintptr_t)strlen(carg) ) __optptr = carg+1; /* Someone frobbed optind, change to new opt. */ opt = *__optptr++; if ( opt != ':' && (osptr = strchr(optstring, opt)) ) { if ( osptr[1] == ':' ) { if ( *__optptr ) { /* Argument-taking option with attached argument */ optarg = (char *)__optptr; optind++; } else { /* Argument-taking option with non-attached argument */ if ( argv[optind+1] ) { optarg = (char *)argv[optind+1]; optind += 2; } else { /* Missing argument */ return (optstring[0] == ':') ? ':' : '?'; } } return opt; } else { /* Non-argument-taking option */ /* __optptr will remember the exact position to resume at */ if ( ! *__optptr ) optind++; return opt; } } else { /* Unknown option */ optopt = opt; if ( ! *__optptr ) optind++; return '?'; } }