1
0
This repository has been archived on 2024-07-22. You can view files and clone it, but cannot push or open issues or pull requests.
2024-07-22 01:58:46 -03:00

143 lines
2.7 KiB
C
Executable File

/*
* getopt() - command option parsing
*
* Gunnar Ritter, Freiburg i. Br., Germany, March 2002.
*/
/* Sccsid @(#)getopt.c 1.7 (gritter) 12/16/07 */
#include "config.h"
#include <sys/types.h>
#ifdef HAVE_ALLOCA
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#else /* !HAVE_ALLOCA_H */
#include <stdlib.h>
#endif /* !HAVE_ALLOCA_H */
#endif /* HAVE_ALLOCA */
#include <string.h>
#ifdef HAVE_ALLOCA
#define ac_alloc(n) alloca(n)
#define ac_free(n)
#else /* !HAVE_ALLOCA */
extern void *smalloc(size_t);
#define ac_alloc(n) smalloc(n)
#define ac_free(n) free(n)
#endif /* !HAVE_ALLOCA */
#ifndef HAVE_SSIZE_T
typedef int ssize_t;
#endif /* !HAVE_SSIZE_T */
/*
* One should not think that re-implementing this is necessary, but
*
* - Some libcs print weird messages.
*
* - GNU libc getopt() is totally brain-damaged, as it requires special
* care _not_ to reorder parameters and can't be told to work correctly
* with ':' as first optstring character at all.
*/
char *optarg;
int optind = 1;
int opterr = 1;
int optopt;
static void
error(const char *s, int c)
{
/*
* Avoid including <unistd.h>, in case its getopt() declaration
* conflicts.
*/
extern ssize_t write(int, const void *, size_t);
const char *msg = 0;
char *buf, *bp;
switch (c) {
case '?':
msg = ": illegal option -- ";
break;
case ':':
msg = ": option requires an argument -- ";
break;
}
bp = buf = ac_alloc(strlen(s) + strlen(msg) + 2);
while (*s)
*bp++ = *s++;
while (*msg)
*bp++ = *msg++;
*bp++ = optopt;
*bp++ = '\n';
write(2, buf, bp - buf);
ac_free(buf);
}
int
getopt(int argc, char *const argv[], const char *optstring)
{
int colon;
static const char *lastp;
const char *curp;
if (optstring[0] == ':') {
colon = 1;
optstring++;
} else
colon = 0;
if (lastp) {
curp = lastp;
lastp = 0;
} else {
if (optind >= argc || argv[optind] == 0 ||
argv[optind][0] != '-' ||
argv[optind][1] == '\0')
return -1;
if (argv[optind][1] == '-' && argv[optind][2] == '\0') {
optind++;
return -1;
}
curp = &argv[optind][1];
}
optopt = curp[0] & 0377;
while (optstring[0]) {
if (optstring[0] == ':') {
optstring++;
continue;
}
if ((optstring[0] & 0377) == optopt) {
if (optstring[1] == ':') {
if (curp[1] != '\0') {
optarg = (char *)&curp[1];
optind++;
} else {
if ((optind += 2) > argc) {
if (!colon && opterr)
error(argv[0], ':');
return colon ? ':' : '?';
}
optarg = argv[optind - 1];
}
} else {
if (curp[1] != '\0')
lastp = &curp[1];
else
optind++;
optarg = 0;
}
return optopt;
}
optstring++;
}
if (!colon && opterr)
error(argv[0], '?');
if (curp[1] != '\0')
lastp = &curp[1];
else
optind++;
optarg = 0;
return '?';
}