1 | /* getopt.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
|
---|
2 |
|
---|
3 | #include <stdio.h>
|
---|
4 | #include <stdlib.h>
|
---|
5 | #include <string.h>
|
---|
6 | #include <getopt.h>
|
---|
7 |
|
---|
8 | char *optarg = NULL;
|
---|
9 | int optind = 1; /* Default: first call */
|
---|
10 | int opterr = 1; /* Default: error messages enabled */
|
---|
11 | char *optswchar = "-"; /* Default: '-' starts options */
|
---|
12 | enum optmode optmode = GETOPT_UNIX;
|
---|
13 | int optopt;
|
---|
14 |
|
---|
15 | static char * next_opt; /* Next character in cluster of options */
|
---|
16 |
|
---|
17 | static char done;
|
---|
18 | static char sw_char;
|
---|
19 | static char init;
|
---|
20 |
|
---|
21 | static char ** options; /* List of entries which are options */
|
---|
22 | static char ** non_options; /* List of entries which are not options */
|
---|
23 | static int options_count;
|
---|
24 | static int non_options_count;
|
---|
25 |
|
---|
26 | #define BEGIN do {
|
---|
27 | #define END } while (0)
|
---|
28 |
|
---|
29 | #define PUT(dst) BEGIN \
|
---|
30 | if (optmode == GETOPT_ANY) \
|
---|
31 | dst[dst##_count++] = argv[optind]; \
|
---|
32 | END
|
---|
33 |
|
---|
34 | /* Note: `argv' is not const as GETOPT_ANY reorders argv[]. */
|
---|
35 |
|
---|
36 | int getopt (int argc, char * argv[], const char *opt_str)
|
---|
37 | {
|
---|
38 | char c, *q;
|
---|
39 | int i, j;
|
---|
40 |
|
---|
41 | if (!init || optind == 0)
|
---|
42 | {
|
---|
43 | if (optind == 0) optind = 1;
|
---|
44 | done = 0; init = 1;
|
---|
45 | next_opt = "";
|
---|
46 | if (optmode == GETOPT_ANY)
|
---|
47 | {
|
---|
48 | options = (char **)malloc (argc * sizeof (char *));
|
---|
49 | non_options = (char **)malloc (argc * sizeof (char *));
|
---|
50 | if (options == NULL || non_options == NULL)
|
---|
51 | {
|
---|
52 | fprintf (stderr, "out of memory in getopt()\n");
|
---|
53 | exit (255);
|
---|
54 | }
|
---|
55 | options_count = 0; non_options_count = 0;
|
---|
56 | }
|
---|
57 | }
|
---|
58 | if (done)
|
---|
59 | return -1;
|
---|
60 | restart:
|
---|
61 | optarg = NULL;
|
---|
62 | if (*next_opt == 0)
|
---|
63 | {
|
---|
64 | if (optind >= argc)
|
---|
65 | {
|
---|
66 | if (optmode == GETOPT_ANY)
|
---|
67 | {
|
---|
68 | j = 1;
|
---|
69 | for (i = 0; i < options_count; ++i)
|
---|
70 | argv[j++] = options[i];
|
---|
71 | for (i = 0; i < non_options_count; ++i)
|
---|
72 | argv[j++] = non_options[i];
|
---|
73 | optind = options_count+1;
|
---|
74 | free (options); free (non_options);
|
---|
75 | }
|
---|
76 | done = 1;
|
---|
77 | return -1;
|
---|
78 | }
|
---|
79 | else if (!strchr (optswchar, argv[optind][0]) || argv[optind][1] == 0)
|
---|
80 | {
|
---|
81 | if (optmode == GETOPT_UNIX)
|
---|
82 | {
|
---|
83 | done = 1;
|
---|
84 | return -1;
|
---|
85 | }
|
---|
86 | PUT (non_options);
|
---|
87 | optarg = argv[optind++];
|
---|
88 | if (optmode == GETOPT_ANY)
|
---|
89 | goto restart;
|
---|
90 | /* optmode==GETOPT_KEEP */
|
---|
91 | return 0;
|
---|
92 | }
|
---|
93 | else if (argv[optind][0] == argv[optind][1] && argv[optind][2] == 0)
|
---|
94 | {
|
---|
95 | if (optmode == GETOPT_ANY)
|
---|
96 | {
|
---|
97 | j = 1;
|
---|
98 | for (i = 0; i < options_count; ++i)
|
---|
99 | argv[j++] = options[i];
|
---|
100 | argv[j++] = argv[optind];
|
---|
101 | for (i = 0; i < non_options_count; ++i)
|
---|
102 | argv[j++] = non_options[i];
|
---|
103 | for (i = optind+1; i < argc; ++i)
|
---|
104 | argv[j++] = argv[i];
|
---|
105 | optind = options_count+2;
|
---|
106 | free (options); free (non_options);
|
---|
107 | }
|
---|
108 | ++optind;
|
---|
109 | done = 1;
|
---|
110 | return -1;
|
---|
111 | }
|
---|
112 | else
|
---|
113 | {
|
---|
114 | PUT (options);
|
---|
115 | sw_char = argv[optind][0];
|
---|
116 | next_opt = argv[optind]+1;
|
---|
117 | }
|
---|
118 | }
|
---|
119 | c = *next_opt++;
|
---|
120 | if (*next_opt == 0) /* Move to next argument if end of argument reached */
|
---|
121 | ++optind;
|
---|
122 | if (c == ':' || (q = strchr (opt_str, c)) == NULL)
|
---|
123 | {
|
---|
124 | if (opterr && opt_str[0] != ':')
|
---|
125 | {
|
---|
126 | if (c < ' ' || c >= 127)
|
---|
127 | fprintf (stderr, "%s: invalid option; character code=0x%.2x\n",
|
---|
128 | argv[0], c);
|
---|
129 | else
|
---|
130 | fprintf (stderr, "%s: invalid option `%c%c'\n",
|
---|
131 | argv[0], sw_char, c);
|
---|
132 | }
|
---|
133 | optopt = c;
|
---|
134 | return '?';
|
---|
135 | }
|
---|
136 | if (q[1] == ':')
|
---|
137 | {
|
---|
138 | if (*next_opt != 0) /* Argument given */
|
---|
139 | {
|
---|
140 | optarg = next_opt;
|
---|
141 | next_opt = "";
|
---|
142 | ++optind;
|
---|
143 | }
|
---|
144 | else if (q[2] == ':')
|
---|
145 | optarg = NULL; /* Optional argument missing */
|
---|
146 | else if (optind >= argc)
|
---|
147 | { /* Required argument missing */
|
---|
148 | if (opterr && opt_str[0] != ':')
|
---|
149 | fprintf (stderr, "%s: no argument for `%c%c' option\n",
|
---|
150 | argv[0], sw_char, c);
|
---|
151 | optopt = c;
|
---|
152 | return (opt_str[0] == ':' ? ':' : '?');
|
---|
153 | }
|
---|
154 | else
|
---|
155 | {
|
---|
156 | PUT (options);
|
---|
157 | optarg = argv[optind++];
|
---|
158 | }
|
---|
159 | }
|
---|
160 | return c;
|
---|
161 | }
|
---|