|
1 /* |
|
2 ******************************************************************************* |
|
3 * |
|
4 * Copyright (C) 2000, International Business Machines |
|
5 * Corporation and others. All Rights Reserved. |
|
6 * |
|
7 ******************************************************************************* |
|
8 * file name: uoptions.c |
|
9 * encoding: US-ASCII |
|
10 * tab size: 8 (not used) |
|
11 * indentation:4 |
|
12 * |
|
13 * created on: 2000apr17 |
|
14 * created by: Markus W. Scherer |
|
15 * |
|
16 * This file provides a command line argument parser. |
|
17 */ |
|
18 |
|
19 #include "unicode/utypes.h" |
|
20 #include "cstring.h" |
|
21 #include "uoptions.h" |
|
22 |
|
23 U_CAPI int U_EXPORT2 |
|
24 u_parseArgs(int argc, char* argv[], |
|
25 int optionCount, UOption options[]) { |
|
26 char *arg; |
|
27 int i=1, remaining=1; |
|
28 char c, stopOptions=0; |
|
29 |
|
30 while(i<argc) { |
|
31 arg=argv[i]; |
|
32 if(!stopOptions && *arg=='-' && (c=arg[1])!=0) { |
|
33 /* process an option */ |
|
34 UOption *option=NULL; |
|
35 arg+=2; |
|
36 if(c=='-') { |
|
37 /* process a long option */ |
|
38 if(*arg==0) { |
|
39 /* stop processing options after "--" */ |
|
40 stopOptions=1; |
|
41 } else { |
|
42 /* search for the option string */ |
|
43 int j; |
|
44 for(j=0; j<optionCount; ++j) { |
|
45 if(options[j].longName && uprv_strcmp(arg, options[j].longName)==0) { |
|
46 option=options+j; |
|
47 break; |
|
48 } |
|
49 } |
|
50 if(option==NULL) { |
|
51 /* no option matches */ |
|
52 return -i; |
|
53 } |
|
54 option->doesOccur=1; |
|
55 |
|
56 if(option->hasArg!=UOPT_NO_ARG) { |
|
57 /* parse the argument for the option, if any */ |
|
58 if(i+1<argc && !(argv[i+1][0]=='-' && argv[i+1][1]!=0)) { |
|
59 /* argument in the next argv[], and there is not an option in there */ |
|
60 option->value=argv[++i]; |
|
61 } else if(option->hasArg==UOPT_REQUIRES_ARG) { |
|
62 /* there is no argument, but one is required: return with error */ |
|
63 return -i; |
|
64 } |
|
65 } |
|
66 } |
|
67 } else { |
|
68 /* process one or more short options */ |
|
69 do { |
|
70 /* search for the option letter */ |
|
71 int j; |
|
72 for(j=0; j<optionCount; ++j) { |
|
73 if(c==options[j].shortName) { |
|
74 option=options+j; |
|
75 break; |
|
76 } |
|
77 } |
|
78 if(option==NULL) { |
|
79 /* no option matches */ |
|
80 return -i; |
|
81 } |
|
82 option->doesOccur=1; |
|
83 |
|
84 if(option->hasArg!=UOPT_NO_ARG) { |
|
85 /* parse the argument for the option, if any */ |
|
86 if(*arg!=0) { |
|
87 /* argument following in the same argv[] */ |
|
88 option->value=arg; |
|
89 /* do not process the rest of this arg as option letters */ |
|
90 break; |
|
91 } else if(i+1<argc && !(argv[i+1][0]=='-' && argv[i+1][1]!=0)) { |
|
92 /* argument in the next argv[], and there is not an option in there */ |
|
93 option->value=argv[++i]; |
|
94 /* this break is redundant because we know that *arg==0 */ |
|
95 break; |
|
96 } else if(option->hasArg==UOPT_REQUIRES_ARG) { |
|
97 /* there is no argument, but one is required: return with error */ |
|
98 return -i; |
|
99 } |
|
100 } |
|
101 |
|
102 /* get the next option letter */ |
|
103 option=NULL; |
|
104 c=*arg++; |
|
105 } while(c!=0); |
|
106 } |
|
107 |
|
108 if(option!=0 && option->optionFn!=0 && option->optionFn(option->context, option)<0) { |
|
109 /* the option function was called and returned an error */ |
|
110 return -i; |
|
111 } |
|
112 |
|
113 /* go to next argv[] */ |
|
114 ++i; |
|
115 } else { |
|
116 /* move a non-option up in argv[] */ |
|
117 argv[remaining++]=arg; |
|
118 ++i; |
|
119 } |
|
120 } |
|
121 return remaining; |
|
122 } |