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