source: bootcd/isolinux/syslinux-6.03/com32/lib/getopt.c

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 2.1 KB
Line 
1/*
2 * getopt.c
3 *
4 * Simple POSIX getopt(), no GNU extensions...
5 */
6
7#include <stdint.h>
8#include <unistd.h>
9#include <string.h>
10
11char *optarg;
12int optind, opterr, optopt;
13static struct getopt_private_state {
14        const char *optptr;
15        const char *last_optstring;
16        char *const *last_argv;
17} pvt;
18
19int getopt(int argc, char *const *argv, const char *optstring)
20{
21        const char *carg;
22        const char *osptr;
23        int opt;
24
25        /* getopt() relies on a number of different global state
26           variables, which can make this really confusing if there is
27           more than one use of getopt() in the same program.  This
28           attempts to detect that situation by detecting if the
29           "optstring" or "argv" argument have changed since last time
30           we were called; if so, reinitialize the query state. */
31
32        if (optstring != pvt.last_optstring || argv != pvt.last_argv ||
33            optind < 1 || optind > argc) {
34                /* optind doesn't match the current query */
35                pvt.last_optstring = optstring;
36                pvt.last_argv = argv;
37                optind = 1;
38                pvt.optptr = NULL;
39        }
40
41        carg = argv[optind];
42
43        /* First, eliminate all non-option cases */
44
45        if (!carg || carg[0] != '-' || !carg[1]) {
46                return -1;
47        }
48
49        if (carg[1] == '-' && !carg[2]) {
50                optind++;
51                return -1;
52        }
53
54        if ((uintptr_t) (pvt.optptr - carg) > (uintptr_t) strlen(carg)) {
55                /* Someone frobbed optind, change to new opt. */
56                pvt.optptr = carg + 1;
57        }
58
59        opt = *pvt.optptr++;
60
61        if (opt != ':' && (osptr = strchr(optstring, opt))) {
62                if (osptr[1] == ':') {
63                        if (*pvt.optptr) {
64                                /* Argument-taking option with attached
65                                   argument */
66                                optarg = (char *)pvt.optptr;
67                                optind++;
68                        } else {
69                                /* Argument-taking option with non-attached
70                                   argument */
71                                if (argv[optind + 1]) {
72                                        optarg = (char *)argv[optind+1];
73                                        optind += 2;
74                                } else {
75                                        /* Missing argument */
76                                        optind++;
77                                        return (optstring[0] == ':')
78                                                ? ':' : '?';
79                                }
80                        }
81                        return opt;
82                } else {
83                        /* Non-argument-taking option */
84                        /* pvt.optptr will remember the exact position to
85                           resume at */
86                        if (!*pvt.optptr)
87                                optind++;
88                        return opt;
89                }
90        } else {
91                /* Unknown option */
92                optopt = opt;
93                if (!*pvt.optptr)
94                        optind++;
95                return '?';
96        }
97}
Note: See TracBrowser for help on using the repository browser.