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