1 /*-
2 ***********************************************************************
3 *
4 * $Id: options.c,v 1.6 2012/05/01 14:43:49 mavrik Exp $
5 *
6 ***********************************************************************
7 *
8 * Copyright 2006-2012 The WebJob Project, All Rights Reserved.
9 *
10 ***********************************************************************
11 */
12 #include "all-includes.h"
13
14 /*-
15 ***********************************************************************
16 *
17 * OptionsFreeOptionsContext
18 *
19 ***********************************************************************
20 */
21 void
OptionsFreeOptionsContext(OPTIONS_CONTEXT * psOptionsContext)22 OptionsFreeOptionsContext(OPTIONS_CONTEXT *psOptionsContext)
23 {
24 if (psOptionsContext != NULL)
25 {
26 free(psOptionsContext);
27 }
28 }
29
30
31 /*-
32 ***********************************************************************
33 *
34 * OptionsGetArgumentIndex
35 *
36 ***********************************************************************
37 */
38 int
OptionsGetArgumentIndex(OPTIONS_CONTEXT * psOptionsContext)39 OptionsGetArgumentIndex(OPTIONS_CONTEXT *psOptionsContext)
40 {
41 return psOptionsContext->iArgumentIndex;
42 }
43
44
45 /*-
46 ***********************************************************************
47 *
48 * OptionsGetArgumentsLeft
49 *
50 ***********************************************************************
51 */
52 int
OptionsGetArgumentsLeft(OPTIONS_CONTEXT * psOptionsContext)53 OptionsGetArgumentsLeft(OPTIONS_CONTEXT *psOptionsContext)
54 {
55 return (psOptionsContext->iArgumentCount - (psOptionsContext->iArgumentIndex + 1));
56 }
57
58
59 /*-
60 ***********************************************************************
61 *
62 * OptionsGetCommand
63 *
64 ***********************************************************************
65 */
66 TCHAR *
OptionsGetCommand(OPTIONS_CONTEXT * psOptionsContext)67 OptionsGetCommand(OPTIONS_CONTEXT *psOptionsContext)
68 {
69 return psOptionsContext->pptcArgumentVector[0];
70 }
71
72
73 /*-
74 ***********************************************************************
75 *
76 * OptionsGetCurrentArgument
77 *
78 ***********************************************************************
79 */
80 TCHAR *
OptionsGetCurrentArgument(OPTIONS_CONTEXT * psOptionsContext)81 OptionsGetCurrentArgument(OPTIONS_CONTEXT *psOptionsContext)
82 {
83 TCHAR *ptcArgument = NULL;
84
85 if (psOptionsContext->iArgumentIndex < psOptionsContext->iArgumentCount)
86 {
87 ptcArgument = psOptionsContext->pptcArgumentVector[psOptionsContext->iArgumentIndex];
88 }
89
90 return ptcArgument;
91 }
92
93
94 /*-
95 ***********************************************************************
96 *
97 * OptionsGetFirstArgument
98 *
99 ***********************************************************************
100 */
101 TCHAR *
OptionsGetFirstArgument(OPTIONS_CONTEXT * psOptionsContext)102 OptionsGetFirstArgument(OPTIONS_CONTEXT *psOptionsContext)
103 {
104 TCHAR *ptcArgument = NULL;
105
106 psOptionsContext->iArgumentIndex = 1;
107 if (psOptionsContext->iArgumentIndex < psOptionsContext->iArgumentCount)
108 {
109 ptcArgument = psOptionsContext->pptcArgumentVector[psOptionsContext->iArgumentIndex];
110 }
111
112 return ptcArgument;
113 }
114
115
116 /*-
117 ***********************************************************************
118 *
119 * OptionsGetNextArgument
120 *
121 ***********************************************************************
122 */
123 TCHAR *
OptionsGetNextArgument(OPTIONS_CONTEXT * psOptionsContext)124 OptionsGetNextArgument(OPTIONS_CONTEXT *psOptionsContext)
125 {
126 TCHAR *ptcArgument = NULL;
127
128 if ((psOptionsContext->iArgumentIndex + 1) < psOptionsContext->iArgumentCount)
129 {
130 ptcArgument = psOptionsContext->pptcArgumentVector[++psOptionsContext->iArgumentIndex];
131 }
132
133 return ptcArgument;
134 }
135
136
137 /*-
138 ***********************************************************************
139 *
140 * OptionsHaveRequiredOptions
141 *
142 ***********************************************************************
143 */
144 int
OptionsHaveRequiredOptions(OPTIONS_CONTEXT * psOptionsContext)145 OptionsHaveRequiredOptions(OPTIONS_CONTEXT *psOptionsContext)
146 {
147 int iIndex = 0;
148
149 for (iIndex = 0; iIndex < psOptionsContext->iNOptions; iIndex++)
150 {
151 if (psOptionsContext->psOptions[iIndex].iRequired == 1 && psOptionsContext->psOptions[iIndex].iFound == 0)
152 {
153 return 0;
154 }
155 }
156
157 return 1;
158 }
159
160
161 /*-
162 ***********************************************************************
163 *
164 * OptionsHaveSpecifiedOption
165 *
166 ***********************************************************************
167 */
168 int
OptionsHaveSpecifiedOption(OPTIONS_CONTEXT * psOptionsContext,int iId)169 OptionsHaveSpecifiedOption(OPTIONS_CONTEXT *psOptionsContext, int iId)
170 {
171 int iIndex = 0;
172
173 for (iIndex = 0; iIndex < psOptionsContext->iNOptions; iIndex++)
174 {
175 if (iId == psOptionsContext->psOptions[iIndex].iId && psOptionsContext->psOptions[iIndex].iFound)
176 {
177 return 1;
178 }
179 }
180
181 return 0;
182 }
183
184
185 /*-
186 ***********************************************************************
187 *
188 * OptionsNewOptionsContext
189 *
190 ***********************************************************************
191 */
192 OPTIONS_CONTEXT *
OptionsNewOptionsContext(int iArgumentCount,TCHAR * pptcArgumentVector[],TCHAR * ptcError)193 OptionsNewOptionsContext(int iArgumentCount, TCHAR *pptcArgumentVector[], TCHAR *ptcError)
194 {
195 OPTIONS_CONTEXT *psOptionsContext = NULL;
196
197 /*-
198 *********************************************************************
199 *
200 * Allocate and clear memory for the structure.
201 *
202 *********************************************************************
203 */
204 psOptionsContext = (OPTIONS_CONTEXT *) calloc(sizeof(OPTIONS_CONTEXT), 1);
205 if (psOptionsContext == NULL)
206 {
207 _sntprintf(ptcError, MESSAGE_SIZE, _T("OptionsNewOptionsContext(): calloc(): %s"), strerror(errno));
208 return NULL;
209 }
210
211 /*-
212 *********************************************************************
213 *
214 * Initialize members.
215 *
216 *********************************************************************
217 */
218 psOptionsContext->pptcArgumentVector = pptcArgumentVector;
219 psOptionsContext->iArgumentCount = iArgumentCount;
220
221 return psOptionsContext;
222 }
223
224
225 /*-
226 ***********************************************************************
227 *
228 * OptionsProcessOptions
229 *
230 ***********************************************************************
231 */
232 int
OptionsProcessOptions(OPTIONS_CONTEXT * psOptionsContext,void * pvProperties,TCHAR * ptcError)233 OptionsProcessOptions(OPTIONS_CONTEXT *psOptionsContext, void *pvProperties, TCHAR *ptcError)
234 {
235 TCHAR atcLocalError[MESSAGE_SIZE] = { 0 };
236 TCHAR *ptcArgument = NULL;
237 int iError = 0;
238 int iIndex = 0;
239 OPTIONS_TABLE *psOptions = NULL;
240
241 /*-
242 *********************************************************************
243 *
244 * Define local variables to make the code easier to read.
245 *
246 *********************************************************************
247 */
248 psOptions = psOptionsContext->psOptions;
249
250 /*-
251 *********************************************************************
252 *
253 * Walk the argument list.
254 *
255 *********************************************************************
256 */
257 while ((ptcArgument = OptionsGetNextArgument(psOptionsContext)) != NULL)
258 {
259 /*-
260 *******************************************************************
261 *
262 * Check for the end of options token ("--"), and break if found.
263 *
264 *******************************************************************
265 */
266 if (_tcscmp(ptcArgument, _T("--")) == 0)
267 {
268 break;
269 }
270
271 /*-
272 *******************************************************************
273 *
274 * Scan the options table looking for a match on the nick name or
275 * the full name. If a match is found, pass the option and its
276 * argument, if any, to the designated handler.
277 *
278 *******************************************************************
279 */
280 for (iIndex = 0; iIndex < psOptionsContext->iNOptions; iIndex++)
281 {
282 if (
283 (psOptions[iIndex].atcNickName[0] && _tcscmp(ptcArgument, psOptions[iIndex].atcNickName) == 0) ||
284 (psOptions[iIndex].atcFullName[0] && _tcscmp(ptcArgument, psOptions[iIndex].atcFullName) == 0)
285 )
286 {
287 if (psOptions[iIndex].iAllowRepeats == 0 && psOptions[iIndex].iFound == 1)
288 {
289 _sntprintf(ptcError, MESSAGE_SIZE, _T("OptionsProcessOptions(): The %s option may not be specified more than once."), ptcArgument);
290 return OPTIONS_ER;
291 }
292 /* TODO: Modify this section (down to the break) to support multiple arguments per option. */
293 if (psOptions[iIndex].iNArguments > 0)
294 {
295 if (OptionsGetArgumentsLeft(psOptionsContext) < 1)
296 {
297 return OPTIONS_USAGE;
298 }
299 ptcArgument = OptionsGetNextArgument(psOptionsContext);
300 }
301 else
302 {
303 ptcArgument = NULL;
304 }
305 psOptions[iIndex].iFound = 1;
306 iError = psOptions[iIndex].piHandler(&psOptions[iIndex], ptcArgument, pvProperties, atcLocalError);
307 if (iError != OPTIONS_OK)
308 {
309 _sntprintf(ptcError, MESSAGE_SIZE, _T("OptionsProcessOptions(): %s"), atcLocalError);
310 return OPTIONS_ER;
311 }
312 break;
313 }
314 }
315
316 /*-
317 *******************************************************************
318 *
319 * Reject unmatched arguments that look like options. Treat single
320 * hyphens ("-") as arguments/operands, rather than options. Stop
321 * searching for options at the first argument that looks like an
322 * operand.
323 *
324 *******************************************************************
325 */
326 if (iIndex == psOptionsContext->iNOptions)
327 {
328 if (ptcArgument[0] == '-' && ptcArgument[1] != 0)
329 {
330 _sntprintf(ptcError, MESSAGE_SIZE, _T("OptionsProcessOptions(): option=[%s]: Unknown option."), ptcArgument);
331 return OPTIONS_ER;
332 }
333 else
334 {
335 psOptionsContext->iArgumentIndex--; /* Decrement the index so the next OptionsGetNextArgument() will get this argument. */
336 break;
337 }
338 }
339 }
340
341 return OPTIONS_OK;
342 }
343
344
345 /*-
346 ***********************************************************************
347 *
348 * OptionsSetOptions
349 *
350 ***********************************************************************
351 */
352 void
OptionsSetOptions(OPTIONS_CONTEXT * psOptionsContext,OPTIONS_TABLE * psOptions,int iNOptions)353 OptionsSetOptions(OPTIONS_CONTEXT *psOptionsContext, OPTIONS_TABLE *psOptions, int iNOptions)
354 {
355 psOptionsContext->psOptions = psOptions;
356 psOptionsContext->iNOptions = iNOptions;
357 }
358