comparison th_args.c @ 377:9ad157feb99a

Sync th-libs.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 03 Oct 2011 00:04:33 +0300
parents 69aed051f84d
children afbc3bfd3e03
comparison
equal deleted inserted replaced
376:1617d0a0c58e 377:9ad157feb99a
126 126
127 /* Check if option requires an argument 127 /* Check if option requires an argument
128 */ 128 */
129 static BOOL th_args_check_arg(optarg_t *o, char *optArg) 129 static BOOL th_args_check_arg(optarg_t *o, char *optArg)
130 { 130 {
131 if ((o->optFlags & OPT_ARGMASK) == OPT_ARGREQ && optArg == NULL) { 131 if ((o->optFlags & OPT_ARGMASK) == OPT_ARGREQ && optArg == NULL)
132 if (o->optShort != 0 && o->optLong != NULL) { 132 {
133 if (o->optShort != 0 && o->optLong != NULL)
134 {
133 THERR("Option '-%c ARG' (--%s=ARG) requires an argument!\n", 135 THERR("Option '-%c ARG' (--%s=ARG) requires an argument!\n",
134 o->optShort, o->optLong); 136 o->optShort, o->optLong);
135 } else if (o->optShort != 0) { 137 }
138 else if (o->optShort != 0)
139 {
136 THERR("Option '-%c ARG' requires an argument!\n", o->optShort); 140 THERR("Option '-%c ARG' requires an argument!\n", o->optShort);
137 } else if (o->optLong != NULL) { 141 }
142 else if (o->optLong != NULL)
143 {
138 THERR("Option --%s=ARG requires an argument!\n", o->optLong); 144 THERR("Option --%s=ARG requires an argument!\n", o->optLong);
139 } 145 }
140 146
141 return FALSE; 147 return FALSE;
142 } else 148 }
149 else
143 return TRUE; 150 return TRUE;
144
145 } 151 }
146 152
147 153
148 /* Handle short options 154 /* Handle short options
149 */ 155 */
153 BOOL (*handleOpt)(int, char *, char *)) 159 BOOL (*handleOpt)(int, char *, char *))
154 { 160 {
155 char *tmpArg = currArg, *optArg; 161 char *tmpArg = currArg, *optArg;
156 int optN; 162 int optN;
157 BOOL isFound; 163 BOOL isFound;
158 164
159 /* Short options can be combined: -a -b -c == -abc */ 165 /* Short options can be combined: -a -b -c == -abc */
160 while (*tmpArg) { 166 while (*tmpArg)
161 167 {
162 for (optN = 0, isFound = FALSE; (optN < optListN) && !isFound; optN++) 168 for (optN = 0, isFound = FALSE; (optN < optListN) && !isFound; optN++)
163 if (*tmpArg == optList[optN].optShort) { 169 if (*tmpArg == optList[optN].optShort)
164 /* Get possible option argument, if needed */ 170 {
165 if ((optList[optN].optFlags & OPT_ARGMASK) != 0 && (++(*newArgIndex) < argc)) 171 /* Get possible option argument, if needed */
166 optArg = argv[*newArgIndex]; 172 if ((optList[optN].optFlags & OPT_ARGMASK) != 0
167 else 173 && (++(*newArgIndex) < argc))
168 optArg = NULL; 174 optArg = argv[*newArgIndex];
169 175 else
170 /* Check if option argument is required */ 176 optArg = NULL;
171 if (!th_args_check_arg(&optList[optN], optArg)) 177
172 return FALSE; 178 /* Check if option argument is required */
173 else { 179 if (!th_args_check_arg(&optList[optN], optArg))
174 char tmpStr[2] = { 0, 0 };
175
176 /* Option was given succesfully, try to handle it */
177 wasGiven[optN] = TRUE;
178
179 tmpStr[0] = *tmpArg;
180
181 if (!handleOpt(optList[optN].optID, optArg, tmpStr))
182 return FALSE; 180 return FALSE;
183 } 181 else
184 182 {
185 isFound = TRUE; 183 char tmpStr[2] = { 0, 0 };
186 } 184
187 185 /* Option was given succesfully, try to handle it */
188 if (!isFound) { 186 wasGiven[optN] = TRUE;
187
188 tmpStr[0] = *tmpArg;
189
190 if (!handleOpt(optList[optN].optID, optArg, tmpStr))
191 return FALSE;
192 }
193
194 isFound = TRUE;
195 }
196
197 if (!isFound)
198 {
189 THERR("Unknown short option '%c' in argument '-%s'\n", 199 THERR("Unknown short option '%c' in argument '-%s'\n",
190 *tmpArg, currArg); 200 *tmpArg, currArg);
191 return FALSE; 201 return FALSE;
192 } 202 }
193 203
194 tmpArg++; 204 tmpArg++;
195 } 205 }
205 optarg_t optList[], int optListN, 215 optarg_t optList[], int optListN,
206 BOOL (*handleOpt)(int, char *, char *)) 216 BOOL (*handleOpt)(int, char *, char *))
207 { 217 {
208 int optN, optLen, i; 218 int optN, optLen, i;
209 char *optArg; 219 char *optArg;
210 220
211 (void) argc; (void) argv; (void) newArgIndex; 221 (void) argc;
212 222 (void) argv;
223 (void) newArgIndex;
224
213 /* Long option */ 225 /* Long option */
214 for (optN = -1, optLen = i = 0; (i < optListN) && (optN < 0); i++) 226 for (optN = -1, optLen = i = 0; (i < optListN) && (optN < 0); i++)
215 if (optList[i].optLong) { 227 if (optList[i].optLong)
216 optLen = strlen(optList[i].optLong); 228 {
217 if (strncmp(currArg, optList[i].optLong, optLen) == 0) 229 optLen = strlen(optList[i].optLong);
218 optN = i; 230 if (strncmp(currArg, optList[i].optLong, optLen) == 0)
219 } 231 optN = i;
220 232 }
233
221 /* Get possible option argument, if needed */ 234 /* Get possible option argument, if needed */
222 if (optN >= 0) { 235 if (optN >= 0)
223 if ((optList[optN].optFlags & OPT_ARGMASK) != 0) { 236 {
237 if ((optList[optN].optFlags & OPT_ARGMASK) != 0)
238 {
224 if (currArg[optLen] == '=') 239 if (currArg[optLen] == '=')
225 optArg = &currArg[optLen + 1]; 240 optArg = &currArg[optLen + 1];
226 else 241 else
227 optArg = NULL; 242 optArg = NULL;
228 } else 243 }
244 else
229 optArg = NULL; 245 optArg = NULL;
230 246
231 /* Check if option argument is required */ 247 /* Check if option argument is required */
232 if (!th_args_check_arg(&optList[optN], optArg)) 248 if (!th_args_check_arg(&optList[optN], optArg))
233 return FALSE; 249 return FALSE;
234 else { 250 else
251 {
235 /* Option was given succesfully, try to handle it */ 252 /* Option was given succesfully, try to handle it */
236 wasGiven[optN] = TRUE; 253 wasGiven[optN] = TRUE;
237 if (!handleOpt(optList[optN].optID, optArg, currArg)) 254 if (!handleOpt(optList[optN].optID, optArg, currArg))
238 return FALSE; 255 return FALSE;
239 } 256 }
240 } else { 257 }
258 else
259 {
241 THERR("Unknown long option '--%s'\n", currArg); 260 THERR("Unknown long option '--%s'\n", currArg);
242 return FALSE; 261 return FALSE;
243 } 262 }
244 263
245 return TRUE; 264 return TRUE;
248 267
249 /* Process arguments, handling short and long options by 268 /* Process arguments, handling short and long options by
250 * calling the given callback functions. 269 * calling the given callback functions.
251 */ 270 */
252 BOOL th_args_process(int argc, char *argv[], 271 BOOL th_args_process(int argc, char *argv[],
253 optarg_t optList[], int optListN, 272 optarg_t optList[], int optListN,
254 BOOL (*handleOpt) (int, char *, char *), 273 BOOL(*handleOpt) (int, char *, char *),
255 BOOL (*handleNonOption) (char *), BOOL bailOut) 274 BOOL(*handleNonOption) (char *), BOOL bailOut)
256 { 275 {
257 BOOL endOptions, optionsOK; 276 BOOL endOptions, optionsOK;
258 int argIndex, newArgIndex, i; 277 int argIndex, newArgIndex, i;
259 char *currArg; 278 char *currArg;
260 BOOL *wasGiven; 279 BOOL *wasGiven;
261 280
262 /* Allocate wasGiven */ 281 /* Allocate wasGiven */
263 wasGiven = (BOOL *) th_calloc(optListN, sizeof(BOOL)); 282 wasGiven = (BOOL *) th_calloc(optListN, sizeof(BOOL));
264 if (!wasGiven) { 283 if (!wasGiven)
265 THERR("FATAL ERROR! Could not allocate wasGiven in th_args_process()!\n"); 284 {
285 THERR
286 ("FATAL ERROR! Could not allocate wasGiven in th_args_process()!\n");
266 exit(128); 287 exit(128);
267 } 288 }
268 289
269 /* Parse arguments */ 290 /* Parse arguments */
270 argIndex = 1; 291 argIndex = 1;
271 optionsOK = TRUE; 292 optionsOK = TRUE;
272 endOptions = FALSE; 293 endOptions = FALSE;
273 while (argIndex < argc) { 294 while (argIndex < argc)
295 {
274 currArg = argv[argIndex]; 296 currArg = argv[argIndex];
275 if ((currArg[0] == '-') && !endOptions) { 297 if ((currArg[0] == '-') && !endOptions)
298 {
276 newArgIndex = argIndex; 299 newArgIndex = argIndex;
277 currArg++; 300 currArg++;
278 if (*currArg == '-') { 301 if (*currArg == '-')
302 {
279 /* Check for "--", which ends the options-list */ 303 /* Check for "--", which ends the options-list */
280 currArg++; 304 currArg++;
281 if (*currArg == 0) { 305 if (*currArg == 0)
306 {
282 endOptions = TRUE; 307 endOptions = TRUE;
283 continue; 308 continue;
284 } 309 }
285 310
286 /* Long options */ 311 /* Long options */
287 if (!th_args_process_long(currArg, &newArgIndex, 312 if (!th_args_process_long(currArg, &newArgIndex,
288 wasGiven, argc, argv, optList, optListN, 313 wasGiven, argc, argv, optList,
289 handleOpt)) 314 optListN, handleOpt))
290 optionsOK = FALSE; 315 optionsOK = FALSE;
291 } else { 316 }
317 else
318 {
292 /* Short options */ 319 /* Short options */
293 if (!th_args_process_short(currArg, &newArgIndex, 320 if (!th_args_process_short(currArg, &newArgIndex,
294 wasGiven, argc, argv, optList, optListN, 321 wasGiven, argc, argv, optList,
295 handleOpt)) 322 optListN, handleOpt))
296 optionsOK = FALSE; 323 optionsOK = FALSE;
297 } 324 }
298 325
299 argIndex = newArgIndex; 326 argIndex = newArgIndex;
300 } else { 327 }
328 else
329 {
301 /* Was not option argument */ 330 /* Was not option argument */
302 if (handleNonOption == NULL || (handleNonOption != NULL && !handleNonOption(currArg))) { 331 if (handleNonOption == NULL
332 || (handleNonOption != NULL && !handleNonOption(currArg)))
333 {
303 THERR("Invalid argument '%s'\n", currArg); 334 THERR("Invalid argument '%s'\n", currArg);
304 optionsOK = FALSE; 335 optionsOK = FALSE;
305 } 336 }
306 } 337 }
307 338
308 /* Check if we bail out on invalid argument */ 339 /* Check if we bail out on invalid argument */
309 if (!optionsOK && bailOut) { 340 if (!optionsOK && bailOut)
341 {
310 th_free(wasGiven); 342 th_free(wasGiven);
311 return FALSE; 343 return FALSE;
312 } 344 }
313 345
314 argIndex++; 346 argIndex++;
315 } 347 }
316 348
317 /* Check wasGiven by isRequired */ 349 /* Check wasGiven by isRequired */
318 for (i = 0; i < optListN; i++) 350 for (i = 0; i < optListN; i++)
319 if ((optList[i].optFlags & OPT_REQUIRED) != 0 && !wasGiven[i]) { 351 if ((optList[i].optFlags & OPT_REQUIRED) != 0 && !wasGiven[i])
320 THERR("Option -%s (--%s) is required.\n", 352 {
321 optList[i].optShort, optList[i].optLong); 353 THERR("Option -%s (--%s) is required.\n",
322 354 optList[i].optShort, optList[i].optLong);
323 optionsOK = FALSE; 355
324 if (bailOut) break; 356 optionsOK = FALSE;
325 } 357 if (bailOut)
326 358 break;
359 }
360
327 th_free(wasGiven); 361 th_free(wasGiven);
328 return optionsOK; 362 return optionsOK;
329 } 363 }
330 364
331 365
332 /* Print help for commandline arguments/options 366 /* Print help for commandline arguments/options
333 */ 367 */
334 void th_args_help(FILE * outFile, 368 void th_args_help(FILE * outFile,
335 optarg_t optList[], int optListN, 369 optarg_t optList[], int optListN,
336 char * progName, char * progUsage) 370 char *progName, char *progUsage)
337 { 371 {
338 int i, nrequired; 372 int i, nrequired;
339 373
340 fprintf(outFile, 374 fprintf(outFile,
341 "\n%s v%s (%s)\n" 375 "\n%s v%s (%s)\n"
342 "%s\n" 376 "%s\n"
343 "%s\n" 377 "%s\n"
344 "Usage: %s %s\n", 378 "Usage: %s %s\n",
345 th_prog_name, th_prog_version, th_prog_fullname, 379 th_prog_name, th_prog_version, th_prog_fullname,
346 th_prog_author, th_prog_license, progName, progUsage); 380 th_prog_author, th_prog_license, progName, progUsage);
347 381
348 382
349 for (i = nrequired = 0; i < optListN; i++) { 383 for (i = nrequired = 0; i < optListN; i++)
384 {
350 optarg_t *o = &optList[i]; 385 optarg_t *o = &optList[i];
351 386
352 /* Print short option */ 387 /* Print short option */
353 if (o->optShort != 0) 388 if (o->optShort != 0)
354 fprintf(outFile, " -%c, ", o->optShort); 389 fprintf(outFile, " -%c, ", o->optShort);
355 else 390 else
356 fprintf(outFile, " "); 391 fprintf(outFile, " ");
357 392
358 /* Print long option */ 393 /* Print long option */
359 if (o->optLong) { 394 if (o->optLong)
395 {
360 char tmpStr[64], *p; 396 char tmpStr[64], *p;
361 397
362 if ((o->optFlags & OPT_ARGMASK) == OPT_ARGOPT) { 398 if ((o->optFlags & OPT_ARGMASK) == OPT_ARGOPT)
363 snprintf(tmpStr, sizeof(tmpStr), "%s[=ARG]", optList[i].optLong); 399 {
400 snprintf(tmpStr, sizeof(tmpStr), "%s[=ARG]",
401 optList[i].optLong);
364 p = tmpStr; 402 p = tmpStr;
365 } else if ((o->optFlags & OPT_ARGMASK) == OPT_ARGREQ) { 403 }
366 snprintf(tmpStr, sizeof(tmpStr), "%s=ARG", optList[i].optLong); 404 else if ((o->optFlags & OPT_ARGMASK) == OPT_ARGREQ)
405 {
406 snprintf(tmpStr, sizeof(tmpStr), "%s=ARG",
407 optList[i].optLong);
367 p = tmpStr; 408 p = tmpStr;
368 } else 409 }
410 else
369 p = o->optLong; 411 p = o->optLong;
370 412
371 fprintf(outFile, "--%-15s", p); 413 fprintf(outFile, "--%-15s", p);
372 } else 414 }
415 else
373 fprintf(outFile, " "); 416 fprintf(outFile, " ");
374 417
375 fprintf(outFile, " %s.", optList[i].optDesc); 418 fprintf(outFile, " %s.", optList[i].optDesc);
376 419
377 if (o->optFlags & OPT_REQUIRED) { 420 if (o->optFlags & OPT_REQUIRED)
421 {
378 fprintf(outFile, " [*]\n"); 422 fprintf(outFile, " [*]\n");
379 nrequired++; 423 nrequired++;
380 } else 424 }
425 else
381 fprintf(outFile, "\n"); 426 fprintf(outFile, "\n");
382 } 427 }
383 428
384 if (nrequired > 0) 429 if (nrequired > 0)
385 fprintf(outFile, "(Options marked with [*] are required)\n"); 430 fprintf(outFile, "(Options marked with [*] are required)\n");
386 } 431 }
387