optparser.c

changeset 3
b1fbfab67908
parent 0
86b7f6f9c5c0
child 5
f878a9ffa3e0
equal deleted inserted replaced
2:e14a1aba4c56 3:b1fbfab67908
14 #include "include/misc.h" 14 #include "include/misc.h"
15 #include "include/optparser.h" 15 #include "include/optparser.h"
16 #include "include/output.h" 16 #include "include/output.h"
17 17
18 18
19 #define O_CHAINABLE(o) (o->flags&OPT_CHAINABLE)
20 #define O_IMM_ARG(o) (o->flags&OPT__IMM_ARG)
21 #define O_NO_DASH(o) (o->flags&OPT_NO_DASH)
22 #define O_MIDLONG(o) (o->flags&OPT_MIDLONG)
23 #define O_NO_LONG(o) (o->flags&OPT_NO_LONG)
24 #define O_ARGS(o) (o->flags&OPT_OPT_ARG) 19 #define O_ARGS(o) (o->flags&OPT_OPT_ARG)
25 #define O_ARG(o) (o->flasg&OPT_ARG) 20 #define O_ARG(o) (o->flasg&OPT_ARG)
26 #define O_OPT_ARG(o) (O_ARGS(o)==OPT_OPT_ARG) 21 #define O_OPT_ARG(o) (O_ARGS(o)==OPT_OPT_ARG)
27 #define O_ID(o) (o->optid) 22 #define O_ID(o) (o->optid)
28 23
32 static int o_left=0; 27 static int o_left=0;
33 static const char* o_chain_ptr=NULL; 28 static const char* o_chain_ptr=NULL;
34 static int o_args_left=0; 29 static int o_args_left=0;
35 static const char*o_tmp=NULL; 30 static const char*o_tmp=NULL;
36 static int o_error=0; 31 static int o_error=0;
37 32 static int o_mode=OPTP_CHAIN;
38 33
39 /* */ 34
40 35 /* */
41 36
42 void optparser_init(int argc, char *const argv[], const OptParserOpt *opts) 37
43 { 38 void optparser_init(int argc, char *const argv[], int mode,
39 const OptParserOpt *opts)
40 {
41 o_mode=mode;
44 o_opts=opts; 42 o_opts=opts;
45 o_current=argv+1; 43 o_current=argv+1;
46 o_left=argc-1; 44 o_left=argc-1;
47 o_chain_ptr=NULL; 45 o_chain_ptr=NULL;
48 o_args_left=0; 46 o_args_left=0;
54 52
55 53
56 static const OptParserOpt *find_chain_opt(char p, const OptParserOpt *o) 54 static const OptParserOpt *find_chain_opt(char p, const OptParserOpt *o)
57 { 55 {
58 for(;O_ID(o);o++){ 56 for(;O_ID(o);o++){
59 if(O_CHAINABLE(o) && O_ID(o)==p) 57 if(O_ID(o)==p)
60 return o; 58 return o;
61 } 59 }
62 return NULL; 60 return NULL;
63 } 61 }
64 62
65 63
66 static bool valid_chain(const char *p, const OptParserOpt *o) 64 /*static bool valid_chain(const char *p, const OptParserOpt *o)
67 { 65 {
68 while(*p!='\0'){ 66 while(*p!='\0'){
69 if(!find_chain_opt(*p, o)) 67 if(!find_chain_opt(*p, o))
70 return FALSE; 68 return FALSE;
71 p++; 69 p++;
72 } 70 }
73 return TRUE; 71 return TRUE;
74 } 72 }*/
75 73
76 74
77 static bool is_option(const char *p) 75 static bool is_option(const char *p)
78 { 76 {
79 if(p==NULL) 77 if(p==NULL)
88 } 86 }
89 87
90 88
91 /* */ 89 /* */
92 90
91 enum{
92 SHORT, MIDLONG, LONG
93 };
94
93 95
94 int optparser_get_opt() 96 int optparser_get_opt()
95 { 97 {
96 #define RET(X) return o_tmp=p, o_error=X 98 #define RET(X) return o_tmp=p, o_error=X
97 const char *p, *p2=NULL; 99 const char *p, *p2=NULL;
98 bool lo=FALSE, dash=TRUE; 100 bool dash=TRUE;
101 int type=SHORT;
99 const OptParserOpt *o; 102 const OptParserOpt *o;
100 int l; 103 int l;
101 104
102 while(o_args_left) 105 while(o_args_left)
103 optparser_get_arg(); 106 optparser_get_arg();
104 107
105 o_tmp=NULL; 108 o_tmp=NULL;
106 109
107 /* Are we doing a chain (i.e. opt. of style 'tar xzf') ? */ 110 /* Are we doing a chain (i.e. opt. of style 'tar xzf')? */
108 if(o_chain_ptr!=NULL){ 111 if(o_chain_ptr!=NULL){
109 p=o_chain_ptr++; 112 p=o_chain_ptr++;
110 if(!*o_chain_ptr) 113 if(!*o_chain_ptr)
111 o_chain_ptr=NULL; 114 o_chain_ptr=NULL;
112 115
123 126
124 o_left--; 127 o_left--;
125 p=*o_current++; 128 p=*o_current++;
126 129
127 if(*p!='-'){ 130 if(*p!='-'){
128 /* foo */
129 dash=FALSE; 131 dash=FALSE;
132 if(o_mode!=OPTP_NO_DASH)
133 RET(OPT_ID_ARGUMENT);
130 }else if(*(p+1)=='-'){ 134 }else if(*(p+1)=='-'){
131 /* --foo */ 135 /* --foo */
132 if(*(p+2)=='\0'){ 136 if(*(p+2)=='\0'){
133 /* -- */ 137 /* -- arguments */
134 o_args_left=o_left; 138 o_args_left=o_left;
135 RET(OPT_ID_ARGUMENT); 139 RET(OPT_ID_ARGUMENT);
136 } 140 }
137 lo=TRUE; 141 /*argptr=strchr(p, '=');
142 if(argptr!=NULL)
143 argptr++;
144 */
145 type=LONG;
138 p2=p+2; 146 p2=p+2;
139 }else{ 147 }else{
140 /* -foo */ 148 /* -foo */
141 if(*(p+1)=='\0'){ 149 if(*(p+1)=='\0'){
142 /* - */ 150 /* - */
143 o_args_left=1; 151 o_args_left=1;
144 RET(OPT_ID_ARGUMENT); 152 RET(OPT_ID_ARGUMENT);
145 } 153 }
154 if(*(p+2)!='\0' && o_mode==OPTP_MIDLONG)
155 type=MIDLONG;
156
146 p2=p+1; 157 p2=p+1;
147 } 158 }
148 159
149 o=o_opts; 160 o=o_opts;
150 161
151 again: 162 again:
152 for(;O_ID(o);o++){ 163 for(;O_ID(o);o++){
153 if(lo){ 164 if(type==LONG){
154 /* Do long option (--foo=bar) */ 165 /* Do long option (--foo=bar) */
155 if(o->longopt==NULL) 166 if(o->longopt==NULL)
156 continue; 167 continue;
157 l=strlen(o->longopt); 168 l=strlen(o->longopt);
158 if(strncmp(p2, o->longopt, l)!=0) 169 if(strncmp(p2, o->longopt, l)!=0)
159 continue; 170 continue;
160 171
161 if(O_NO_LONG(o))
162 RET(E_OPT_INVALID_OPTION);
163
164 if(p2[l]=='\0'){ 172 if(p2[l]=='\0'){
165 if(O_ARGS(o)==OPT_ARG) 173 if(O_ARGS(o)==OPT_ARG)
166 RET(E_OPT_MISSING_ARGUMENT); 174 RET(E_OPT_MISSING_ARGUMENT);
167 return O_ID(o); 175 return O_ID(o);
168 }else if(p2[l]=='='){ 176 }else if(p2[l]=='='){
172 RET(E_OPT_MISSING_ARGUMENT); 180 RET(E_OPT_MISSING_ARGUMENT);
173 o_tmp=p2+l+1; 181 o_tmp=p2+l+1;
174 o_args_left=1; 182 o_args_left=1;
175 return O_ID(o); 183 return O_ID(o);
176 } 184 }
177 }else{ 185 continue;
178 /* Do midlong option (-foobar) */ 186 }else if(type==MIDLONG){
179 if(dash && o->longopt!=NULL && strcmp(p2, o->longopt)==0){ 187 if(o->longopt==NULL)
180 if(!O_MIDLONG(o)) 188 continue;
181 RET(E_OPT_INVALID_OPTION); 189
182 goto do_arg; 190 if(strcmp(p2, o->longopt)!=0)
183 } 191 continue;
184 192 }else{ /* type==SHORT */
185 /* Do short option (-f) */ 193 if(*p2!=O_ID(o))
186 if((!dash && !O_NO_DASH(o)) || *p2!=O_ID(o))
187 continue; 194 continue;
188 195
189 if(*(p2+1)!='\0'){ 196 if(*(p2+1)!='\0'){
190 if(O_CHAINABLE(o) && valid_chain(p2+1, o_opts)){ 197 if(o_mode==OPTP_CHAIN || o_mode==OPTP_NO_DASH){
191 o_chain_ptr=p2+1; 198 /*valid_chain(p2+1, o_opts)*/
192 }else if(O_IMM_ARG(o)){ 199 o_chain_ptr=p2+1;
193 o_tmp=p2+1; 200 p++;
194 o_args_left=1; 201 }else if(o_mode==OPTP_IMMEDIATE){
195 return O_ID(o); 202 if(!O_ARGS(o)){
203 if(*(p2+1)!='\0')
204 RET(E_OPT_UNEXPECTED_ARGUMENT);
205 }else{
206 if(*(p2+1)=='\0')
207 RET(E_OPT_MISSING_ARGUMENT);
208 o_tmp=p2+1;
209 o_args_left=1;
210 }
211 return O_ID(o);
196 }else{ 212 }else{
197 continue; 213 RET(E_OPT_SYNTAX_ERROR);
198 } 214 }
199 } 215 }
200 do_arg: 216 }
201 if(!O_ARGS(o)) 217
218 do_arg:
219
220 if(!O_ARGS(o))
221 return O_ID(o);
222
223 if(!o_left || is_option(*o_current)){
224 if(O_ARGS(o)==OPT_OPT_ARG)
202 return O_ID(o); 225 return O_ID(o);
203 226 RET(E_OPT_MISSING_ARGUMENT);
204 if(O_ARGS(o)==OPT_ARG){
205 if(o_left==0)
206 RET(E_OPT_MISSING_ARGUMENT);
207 }else{
208 if(!o_left || is_option(*o_current))
209 return O_ID(o);
210 }
211
212 o_args_left=1;
213 return O_ID(o);
214 } 227 }
228
229 o_args_left=1;
230 return O_ID(o);
215 } 231 }
216 232
217 if(dash) 233 if(dash)
218 RET(E_OPT_INVALID_OPTION); 234 RET(E_OPT_INVALID_OPTION);
219 235
252 268
253 /* */ 269 /* */
254 270
255 static void warn_arg(const char *e) 271 static void warn_arg(const char *e)
256 { 272 {
257 const char*p=optparser_get_arg(); 273 const char *p=optparser_get_arg();
258 274
259 if(p==NULL) 275 if(p==NULL)
260 warn("%s (null)", e); 276 warn("%s (null)", e);
261 else 277 else
262 warn("%s \'%s\'", e, p); 278 warn("%s \'%s\'", e, p);
263 } 279 }
264 280
265 281
266 static void warn_opt(const char *e) 282 static void warn_opt(const char *e)
267 { 283 {
268 if(o_chain_ptr!=NULL && o_tmp!=NULL) 284 if(o_tmp!=NULL && o_chain_ptr!=NULL)
269 warn("%s \'-%c\'", e, *o_tmp); 285 warn("%s \'-%c\'", e, *o_tmp);
270 else 286 else
271 warn_arg(e); 287 warn_arg(e);
272 } 288 }
273 289
274 290
275 void optparser_print_error() 291 void optparser_print_error()
276 { 292 {
277 switch(o_error){ 293 switch(o_error){
278 case E_OPT_INVALID_OPTION: 294 case E_OPT_INVALID_OPTION:
295 case E_OPT_INVALID_CHAIN_OPTION:
279 warn_opt(TR("Invalid option")); 296 warn_opt(TR("Invalid option"));
280 break; 297 break;
281
282 case E_OPT_INVALID_CHAIN_OPTION:
283 warn_opt(TR("Invalid option in chain (this cannot happen)"));
284 break;
285 298
286 case E_OPT_SYNTAX_ERROR: 299 case E_OPT_SYNTAX_ERROR:
287 warn_arg(TR("Syntax error while parsing")); 300 warn_arg(TR("Syntax error while parsing"));
288 break; 301 break;
289 302
290 case E_OPT_MISSING_ARGUMENT: 303 case E_OPT_MISSING_ARGUMENT:
291 warn_opt(TR("Missing argument to")); 304 warn_opt(TR("Missing argument to"));
292 break; 305 break;
293 306
294 case E_OPT_UNEXPECTED_ARGUMENT: 307 case E_OPT_UNEXPECTED_ARGUMENT:
295 warn_opt(TR("No argument expected to")); 308 warn_opt(TR("No argument expected:"));
296 break; 309 break;
297 310
298 case OPT_ID_ARGUMENT: 311 case OPT_ID_ARGUMENT:
299 warn(TR("Unexpected argument")); 312 warn(TR("Unexpected argument"));
300 break; 313 break;

mercurial