1 // XGetopt.cpp Version 1.2
2 //
3 // Author: Hans Dietrich
4 // hdietrich2@hotmail.com
5 //
6 // Description:
7 // XGetopt.cpp implements getopt(), a function to parse command lines.
8 //
9 // History
10 // Version 1.2 - 2003 May 17
11 // - Added Unicode support
12 //
13 // Version 1.1 - 2002 March 10
14 // - Added example to XGetopt.cpp module header
15 //
16 // This software is released into the public domain.
17 // You are free to use it in any way you like.
18 //
19 // This software is provided "as is" with no expressed
20 // or implied warranty. I accept no liability for any
21 // damage or loss of business that this software may cause.
22 //
23 ///////////////////////////////////////////////////////////////////////////////
24
25
26 ///////////////////////////////////////////////////////////////////////////////
27 // if you are not using precompiled headers then include these lines:
28
29 ///////////////////////////////////////////////////////////////////////////////
30
31
32 #include "XGetopt.h"
33
34
35 ///////////////////////////////////////////////////////////////////////////////
36 //
37 // X G e t o p t . c p p
38 //
39 //
40 // NAME
41 // getopt -- parse command line options
42 //
43 // SYNOPSIS
44 // int getopt(int argc, TCHAR *argv[], TCHAR *optstring)
45 //
46 // extern TCHAR *optarg;
47 // extern int optind;
48 //
49 // DESCRIPTION
50 // The getopt() function parses the command line arguments. Its
51 // arguments argc and argv are the argument count and array as
52 // passed into the application on program invocation. In the case
53 // of Visual C++ programs, argc and argv are available via the
54 // variables __argc and __argv (double underscores), respectively.
55 // getopt returns the next option letter in argv that matches a
56 // letter in optstring. (Note: Unicode programs should use
57 // __targv instead of __argv. Also, all character and string
58 // literals should be enclosed in _T( ) ).
59 //
60 // optstring is a string of recognized option letters; if a letter
61 // is followed by a colon, the option is expected to have an argument
62 // that may or may not be separated from it by white space. optarg
63 // is set to point to the start of the option argument on return from
64 // getopt.
65 //
66 // Option letters may be combined, e.g., "-ab" is equivalent to
67 // "-a -b". Option letters are case sensitive.
68 //
69 // getopt places in the external variable optind the argv index
70 // of the next argument to be processed. optind is initialized
71 // to 0 before the first call to getopt.
72 //
73 // When all options have been processed (i.e., up to the first
74 // non-option argument), getopt returns EOF, optarg will point
75 // to the argument, and optind will be set to the argv index of
76 // the argument. If there are no non-option arguments, optarg
77 // will be set to NULL.
78 //
79 // The special option "--" may be used to delimit the end of the
80 // options; EOF will be returned, and "--" (and everything after it)
81 // will be skipped.
82 //
83 // RETURN VALUE
84 // For option letters contained in the string optstring, getopt
85 // will return the option letter. getopt returns a question mark (?)
86 // when it encounters an option letter not included in optstring.
87 // EOF is returned when processing is finished.
88 //
89 // BUGS
90 // 1) Long options are not supported.
91 // 2) The GNU double-colon extension is not supported.
92 // 3) The environment variable POSIXLY_CORRECT is not supported.
93 // 4) The + syntax is not supported.
94 // 5) The automatic permutation of arguments is not supported.
95 // 6) This implementation of getopt() returns EOF if an error is
96 // encountered, instead of -1 as the latest standard requires.
97 //
98 // EXAMPLE
99 // BOOL CMyApp::ProcessCommandLine(int argc, TCHAR *argv[])
100 // {
101 // int c;
102 //
103 // while ((c = getopt(argc, argv, _T("aBn:"))) != EOF)
104 // {
105 // switch (c)
106 // {
107 // case _T('a'):
108 // TRACE(_T("option a\n"));
109 // //
110 // // set some flag here
111 // //
112 // break;
113 //
114 // case _T('B'):
115 // TRACE( _T("option B\n"));
116 // //
117 // // set some other flag here
118 // //
119 // break;
120 //
121 // case _T('n'):
122 // TRACE(_T("option n: value=%d\n"), atoi(optarg));
123 // //
124 // // do something with value here
125 // //
126 // break;
127 //
128 // case _T('?'):
129 // TRACE(_T("ERROR: illegal option %s\n"), argv[optind-1]);
130 // return FALSE;
131 // break;
132 //
133 // default:
134 // TRACE(_T("WARNING: no handler for option %c\n"), c);
135 // return FALSE;
136 // break;
137 // }
138 // }
139 // //
140 // // check for non-option args here
141 // //
142 // return TRUE;
143 // }
144 //
145 ///////////////////////////////////////////////////////////////////////////////
146
147 TCHAR *optarg; // global argument pointer
148 int optind = 0; // global argv index
149
getopt(int argc,TCHAR * argv[],TCHAR * optstring)150 int getopt(int argc, TCHAR *argv[], TCHAR *optstring)
151 {
152 static TCHAR *next = NULL;
153 TCHAR c;
154 TCHAR *cp = malloc(sizeof(TCHAR)*1024);
155
156 if (optind == 0)
157 next = NULL;
158
159 optarg = NULL;
160
161 if (next == NULL || *next == _T('\0'))
162 {
163 if (optind == 0)
164 optind++;
165
166 if (optind >= argc || argv[optind][0] != _T('-') || argv[optind][1] == _T('\0'))
167 {
168 optarg = NULL;
169 if (optind < argc)
170 optarg = argv[optind];
171 return EOF;
172 }
173
174 if (_tcscmp(argv[optind], _T("--")) == 0)
175 {
176 optind++;
177 optarg = NULL;
178 if (optind < argc)
179 optarg = argv[optind];
180 return EOF;
181 }
182
183 next = argv[optind];
184 next++; // skip past -
185 optind++;
186 }
187
188 c = *next++;
189 cp = strchr(optstring, c);
190
191 if (cp == NULL || c == _T(':'))
192 return _T('?');
193
194 cp++;
195 if (*cp == _T(':'))
196 {
197 if (*next != _T('\0'))
198 {
199 optarg = next;
200 next = NULL;
201 }
202 else if (optind < argc)
203 {
204 optarg = argv[optind];
205 optind++;
206 }
207 else
208 {
209 return _T('?');
210 }
211 }
212
213 return c;
214 }
215