1 /*
2 Author: Marcus Boerger <helly@users.sourceforge.net>
3 */
4
5 #include <stdio.h>
6 #include <string.h>
7 #include <assert.h>
8 #include <stdlib.h>
9 #include "mbo_getopt.h"
10 #define OPTERRCOLON (1)
11 #define OPTERRNF (2)
12 #define OPTERRARG (3)
13
mbo_opt_error(int argc,char * const * argv,int oint,int optchr,int err,int show_err)14 static int mbo_opt_error(int argc, char * const *argv, int oint, int optchr, int err, int show_err)
15 {
16 if (show_err)
17 {
18 fprintf(stderr, "Error in argument %d, char %d: ", oint, optchr + 1);
19
20 switch (err)
21 {
22
23 case OPTERRCOLON:
24 fprintf(stderr, ": in flags\n");
25 break;
26
27 case OPTERRNF:
28 fprintf(stderr, "option not found %c\n", argv[oint][optchr]);
29 break;
30
31 case OPTERRARG:
32 fprintf(stderr, "no argument for option %c\n", argv[oint][optchr]);
33 break;
34
35 default:
36 fprintf(stderr, "unknown\n");
37 break;
38 }
39 }
40
41 return ('?');
42 }
43
mbo_getopt(int argc,char * const * argv,const mbo_opt_struct opts[],char ** optarg,int * optind,int show_err)44 int mbo_getopt(int argc, char* const *argv, const mbo_opt_struct opts[], char **optarg, int *optind, int show_err)
45 {
46 static int optchr = 0;
47 static int dash = 0; /* have already seen the - */
48 int arg_start = 2;
49
50 int opts_idx = -1;
51
52 if (*optind >= argc)
53 {
54 return (EOF);
55 }
56
57 if (!dash)
58 {
59 if ((argv[*optind][0] != '-'))
60 {
61 return (EOF);
62 }
63 else
64 {
65 if (!argv[*optind][1])
66 {
67 /*
68 * use to specify stdin. Need to let pgm process this and
69 * the following args
70 */
71 return (EOF);
72 }
73 }
74 }
75
76 if ((argv[*optind][0] == '-') && (argv[*optind][1] == '-'))
77 {
78 /* '--' indicates end of args if not followed by a known long option name */
79
80 while (1)
81 {
82 opts_idx++;
83
84 if (opts[opts_idx].opt_char == '-')
85 {
86 (*optind)++;
87 return (EOF);
88 }
89 else if (opts[opts_idx].opt_name && !strcmp(&argv[*optind][2], opts[opts_idx].opt_name))
90 {
91 break;
92 }
93 }
94
95 optchr = 0;
96 dash = 1;
97 arg_start = 2 + strlen(opts[opts_idx].opt_name);
98 }
99
100 if (!dash)
101 {
102 dash = 1;
103 optchr = 1;
104 }
105
106 /* Check if the guy tries to do a -: kind of flag */
107 if (argv[*optind][optchr] == ':')
108 {
109 dash = 0;
110 (*optind)++;
111 return (mbo_opt_error(argc, argv, *optind - 1, optchr, OPTERRCOLON, show_err));
112 }
113
114 if (opts_idx < 0)
115 {
116 while (1)
117 {
118 opts_idx++;
119
120 if (opts[opts_idx].opt_char == '-')
121 {
122 int errind = *optind;
123 int errchr = optchr;
124
125 if (!argv[*optind][optchr + 1])
126 {
127 dash = 0;
128 (*optind)++;
129 }
130 else
131 {
132 optchr++;
133 }
134
135 return (mbo_opt_error(argc, argv, errind, errchr, OPTERRNF, show_err));
136 }
137 else if (argv[*optind][optchr] == opts[opts_idx].opt_char)
138 {
139 break;
140 }
141 }
142 }
143
144 if (opts[opts_idx].need_param)
145 {
146 /* Check for cases where the value of the argument
147 is in the form -<arg> <val> or in the form -<arg><val> */
148 dash = 0;
149
150 if (!argv[*optind][arg_start])
151 {
152 (*optind)++;
153
154 if (*optind == argc)
155 {
156 return (mbo_opt_error(argc, argv, *optind - 1, optchr, OPTERRARG, show_err));
157 }
158
159 *optarg = argv[(*optind)++];
160 }
161 else
162 {
163 *optarg = &argv[*optind][arg_start];
164 (*optind)++;
165 }
166
167 return opts[opts_idx].opt_char;
168 }
169 else
170 {
171 if (arg_start == 2)
172 {
173 if (!argv[*optind][optchr + 1])
174 {
175 dash = 0;
176 (*optind)++;
177 }
178 else
179 {
180 optchr++;
181 }
182 }
183 else
184 {
185 (*optind)++;
186 }
187
188 return opts[opts_idx].opt_char;
189 }
190
191 assert(0);
192 return (0); /* never reached */
193 }
194
195