getopt.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977
  1. /* Getopt for Microsoft C
  2. This code is a modification of the Free Software Foundation, Inc.
  3. Getopt library for parsing command line argument the purpose was
  4. to provide a Microsoft Visual C friendly derivative. This code
  5. provides functionality for both Unicode and Multibyte builds.
  6. Date: 02/03/2011 - Ludvik Jerabek - Initial Release
  7. Version: 1.0
  8. Comment: Supports getopt, getopt_long, and getopt_long_only
  9. and POSIXLY_CORRECT environment flag
  10. License: LGPL
  11. Revisions:
  12. 02/03/2011 - Ludvik Jerabek - Initial Release
  13. 02/20/2011 - Ludvik Jerabek - Fixed compiler warnings at Level 4
  14. 07/05/2011 - Ludvik Jerabek - Added no_argument, required_argument, optional_argument defs
  15. 08/03/2011 - Ludvik Jerabek - Fixed non-argument runtime bug which caused runtime exception
  16. 08/09/2011 - Ludvik Jerabek - Added code to export functions for DLL and LIB
  17. 02/15/2012 - Ludvik Jerabek - Fixed _GETOPT_THROW definition missing in implementation file
  18. 08/01/2012 - Ludvik Jerabek - Created separate functions for char and wchar_t characters so single dll can do both unicode and ansi
  19. 10/15/2012 - Ludvik Jerabek - Modified to match latest GNU features
  20. 06/19/2015 - Ludvik Jerabek - Fixed maximum option limitation caused by option_a (255) and option_w (65535) structure val variable
  21. **DISCLAIMER**
  22. THIS MATERIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
  23. EITHER EXPRESS OR IMPLIED, INCLUDING, BUT Not LIMITED TO, THE
  24. IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  25. PURPOSE, OR NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE
  26. EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT
  27. APPLY TO YOU. IN NO EVENT WILL I BE LIABLE TO ANY PARTY FOR ANY
  28. DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY
  29. USE OF THIS MATERIAL INCLUDING, WITHOUT LIMITATION, ANY LOST
  30. PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON
  31. YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN If WE ARE
  32. EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  33. */
  34. #ifndef _CRT_SECURE_NO_WARNINGS
  35. #define _CRT_SECURE_NO_WARNINGS
  36. #endif
  37. #include <stdlib.h>
  38. #include <stdio.h>
  39. #include <malloc.h>
  40. #include "getopt.h"
  41. #ifdef __cplusplus
  42. #define _GETOPT_THROW throw()
  43. #else
  44. #define _GETOPT_THROW
  45. #endif
  46. int optind = 1;
  47. int opterr = 1;
  48. int optopt = '?';
  49. enum ENUM_ORDERING { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER };
  50. //
  51. //
  52. // Ansi structures and functions follow
  53. //
  54. //
  55. static struct _getopt_data_a
  56. {
  57. int optind;
  58. int opterr;
  59. int optopt;
  60. char *optarg;
  61. int __initialized;
  62. char *__nextchar;
  63. enum ENUM_ORDERING __ordering;
  64. int __posixly_correct;
  65. int __first_nonopt;
  66. int __last_nonopt;
  67. } getopt_data_a;
  68. char *optarg_a;
  69. static void exchange_a(char **argv, struct _getopt_data_a *d)
  70. {
  71. int bottom = d->__first_nonopt;
  72. int middle = d->__last_nonopt;
  73. int top = d->optind;
  74. char *tem;
  75. while (top > middle && middle > bottom)
  76. {
  77. if (top - middle > middle - bottom)
  78. {
  79. int len = middle - bottom;
  80. int i;
  81. for (i = 0; i < len; i++)
  82. {
  83. tem = argv[bottom + i];
  84. argv[bottom + i] = argv[top - (middle - bottom) + i];
  85. argv[top - (middle - bottom) + i] = tem;
  86. }
  87. top -= len;
  88. }
  89. else
  90. {
  91. int len = top - middle;
  92. int i;
  93. for (i = 0; i < len; i++)
  94. {
  95. tem = argv[bottom + i];
  96. argv[bottom + i] = argv[middle + i];
  97. argv[middle + i] = tem;
  98. }
  99. bottom += len;
  100. }
  101. }
  102. d->__first_nonopt += (d->optind - d->__last_nonopt);
  103. d->__last_nonopt = d->optind;
  104. }
  105. static const char *_getopt_initialize_a (const char *optstring, struct _getopt_data_a *d, int posixly_correct)
  106. {
  107. d->__first_nonopt = d->__last_nonopt = d->optind;
  108. d->__nextchar = NULL;
  109. d->__posixly_correct = posixly_correct | !!getenv("POSIXLY_CORRECT");
  110. if (optstring[0] == '-')
  111. {
  112. d->__ordering = RETURN_IN_ORDER;
  113. ++optstring;
  114. }
  115. else if (optstring[0] == '+')
  116. {
  117. d->__ordering = REQUIRE_ORDER;
  118. ++optstring;
  119. }
  120. else if (d->__posixly_correct)
  121. d->__ordering = REQUIRE_ORDER;
  122. else
  123. d->__ordering = PERMUTE;
  124. return optstring;
  125. }
  126. int _getopt_internal_r_a (int argc, char *const *argv, const char *optstring, const struct option_a *longopts, int *longind, int long_only, struct _getopt_data_a *d, int posixly_correct)
  127. {
  128. int print_errors = d->opterr;
  129. if (argc < 1)
  130. return -1;
  131. d->optarg = NULL;
  132. if (d->optind == 0 || !d->__initialized)
  133. {
  134. if (d->optind == 0)
  135. d->optind = 1;
  136. optstring = _getopt_initialize_a (optstring, d, posixly_correct);
  137. d->__initialized = 1;
  138. }
  139. else if (optstring[0] == '-' || optstring[0] == '+')
  140. optstring++;
  141. if (optstring[0] == ':')
  142. print_errors = 0;
  143. if (d->__nextchar == NULL || *d->__nextchar == '\0')
  144. {
  145. if (d->__last_nonopt > d->optind)
  146. d->__last_nonopt = d->optind;
  147. if (d->__first_nonopt > d->optind)
  148. d->__first_nonopt = d->optind;
  149. if (d->__ordering == PERMUTE)
  150. {
  151. if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind)
  152. exchange_a ((char **) argv, d);
  153. else if (d->__last_nonopt != d->optind)
  154. d->__first_nonopt = d->optind;
  155. while (d->optind < argc && (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0'))
  156. d->optind++;
  157. d->__last_nonopt = d->optind;
  158. }
  159. if (d->optind != argc && !strcmp(argv[d->optind], "--"))
  160. {
  161. d->optind++;
  162. if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind)
  163. exchange_a((char **) argv, d);
  164. else if (d->__first_nonopt == d->__last_nonopt)
  165. d->__first_nonopt = d->optind;
  166. d->__last_nonopt = argc;
  167. d->optind = argc;
  168. }
  169. if (d->optind == argc)
  170. {
  171. if (d->__first_nonopt != d->__last_nonopt)
  172. d->optind = d->__first_nonopt;
  173. return -1;
  174. }
  175. if ((argv[d->optind][0] != '-' || argv[d->optind][1] == '\0'))
  176. {
  177. if (d->__ordering == REQUIRE_ORDER)
  178. return -1;
  179. d->optarg = argv[d->optind++];
  180. return 1;
  181. }
  182. d->__nextchar = (argv[d->optind] + 1 + (longopts != NULL && argv[d->optind][1] == '-'));
  183. }
  184. if (longopts != NULL && (argv[d->optind][1] == '-' || (long_only && (argv[d->optind][2] || !strchr(optstring, argv[d->optind][1])))))
  185. {
  186. char *nameend;
  187. unsigned int namelen;
  188. const struct option_a *p;
  189. const struct option_a *pfound = NULL;
  190. struct option_list
  191. {
  192. const struct option_a *p;
  193. struct option_list *next;
  194. } *ambig_list = NULL;
  195. int exact = 0;
  196. int indfound = -1;
  197. int option_index;
  198. for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++);
  199. namelen = (unsigned int)(nameend - d->__nextchar);
  200. for (p = longopts, option_index = 0; p->name; p++, option_index++)
  201. if (!strncmp(p->name, d->__nextchar, namelen))
  202. {
  203. if (namelen == (unsigned int)strlen(p->name))
  204. {
  205. pfound = p;
  206. indfound = option_index;
  207. exact = 1;
  208. break;
  209. }
  210. else if (pfound == NULL)
  211. {
  212. pfound = p;
  213. indfound = option_index;
  214. }
  215. else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
  216. {
  217. struct option_list *newp = (struct option_list*)alloca(sizeof(*newp));
  218. newp->p = p;
  219. newp->next = ambig_list;
  220. ambig_list = newp;
  221. }
  222. }
  223. if (ambig_list != NULL && !exact)
  224. {
  225. if (print_errors)
  226. {
  227. struct option_list first;
  228. first.p = pfound;
  229. first.next = ambig_list;
  230. ambig_list = &first;
  231. fprintf (stderr, "%s: option '%s' is ambiguous; possibilities:", argv[0], argv[d->optind]);
  232. do
  233. {
  234. fprintf (stderr, " '--%s'", ambig_list->p->name);
  235. ambig_list = ambig_list->next;
  236. }
  237. while (ambig_list != NULL);
  238. fputc ('\n', stderr);
  239. }
  240. d->__nextchar += strlen(d->__nextchar);
  241. d->optind++;
  242. d->optopt = 0;
  243. return '?';
  244. }
  245. if (pfound != NULL)
  246. {
  247. option_index = indfound;
  248. d->optind++;
  249. if (*nameend)
  250. {
  251. if (pfound->has_arg)
  252. d->optarg = nameend + 1;
  253. else
  254. {
  255. if (print_errors)
  256. {
  257. if (argv[d->optind - 1][1] == '-')
  258. {
  259. fprintf(stderr, "%s: option '--%s' doesn't allow an argument\n",argv[0], pfound->name);
  260. }
  261. else
  262. {
  263. fprintf(stderr, "%s: option '%c%s' doesn't allow an argument\n",argv[0], argv[d->optind - 1][0],pfound->name);
  264. }
  265. }
  266. d->__nextchar += strlen(d->__nextchar);
  267. d->optopt = pfound->val;
  268. return '?';
  269. }
  270. }
  271. else if (pfound->has_arg == 1)
  272. {
  273. if (d->optind < argc)
  274. d->optarg = argv[d->optind++];
  275. else
  276. {
  277. if (print_errors)
  278. {
  279. fprintf(stderr,"%s: option '--%s' requires an argument\n",argv[0], pfound->name);
  280. }
  281. d->__nextchar += strlen(d->__nextchar);
  282. d->optopt = pfound->val;
  283. return optstring[0] == ':' ? ':' : '?';
  284. }
  285. }
  286. d->__nextchar += strlen(d->__nextchar);
  287. if (longind != NULL)
  288. *longind = option_index;
  289. if (pfound->flag)
  290. {
  291. *(pfound->flag) = pfound->val;
  292. return 0;
  293. }
  294. return pfound->val;
  295. }
  296. if (!long_only || argv[d->optind][1] == '-' || strchr(optstring, *d->__nextchar) == NULL)
  297. {
  298. if (print_errors)
  299. {
  300. if (argv[d->optind][1] == '-')
  301. {
  302. fprintf(stderr, "%s: unrecognized option '--%s'\n",argv[0], d->__nextchar);
  303. }
  304. else
  305. {
  306. fprintf(stderr, "%s: unrecognized option '%c%s'\n",argv[0], argv[d->optind][0], d->__nextchar);
  307. }
  308. }
  309. d->__nextchar = (char *)"";
  310. d->optind++;
  311. d->optopt = 0;
  312. return '?';
  313. }
  314. }
  315. {
  316. char c = *d->__nextchar++;
  317. char *temp = (char*)strchr(optstring, c);
  318. if (*d->__nextchar == '\0')
  319. ++d->optind;
  320. if (temp == NULL || c == ':' || c == ';')
  321. {
  322. if (print_errors)
  323. {
  324. fprintf(stderr, "%s: invalid option -- '%c'\n", argv[0], c);
  325. }
  326. d->optopt = c;
  327. return '?';
  328. }
  329. if (temp[0] == 'W' && temp[1] == ';')
  330. {
  331. char *nameend;
  332. const struct option_a *p;
  333. const struct option_a *pfound = NULL;
  334. int exact = 0;
  335. int ambig = 0;
  336. int indfound = 0;
  337. int option_index;
  338. if (longopts == NULL)
  339. goto no_longs;
  340. if (*d->__nextchar != '\0')
  341. {
  342. d->optarg = d->__nextchar;
  343. d->optind++;
  344. }
  345. else if (d->optind == argc)
  346. {
  347. if (print_errors)
  348. {
  349. fprintf(stderr,"%s: option requires an argument -- '%c'\n",argv[0], c);
  350. }
  351. d->optopt = c;
  352. if (optstring[0] == ':')
  353. c = ':';
  354. else
  355. c = '?';
  356. return c;
  357. }
  358. else
  359. d->optarg = argv[d->optind++];
  360. for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; nameend++);
  361. for (p = longopts, option_index = 0; p->name; p++, option_index++)
  362. if (!strncmp(p->name, d->__nextchar, nameend - d->__nextchar))
  363. {
  364. if ((unsigned int) (nameend - d->__nextchar) == strlen(p->name))
  365. {
  366. pfound = p;
  367. indfound = option_index;
  368. exact = 1;
  369. break;
  370. }
  371. else if (pfound == NULL)
  372. {
  373. pfound = p;
  374. indfound = option_index;
  375. }
  376. else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
  377. ambig = 1;
  378. }
  379. if (ambig && !exact)
  380. {
  381. if (print_errors)
  382. {
  383. fprintf(stderr, "%s: option '-W %s' is ambiguous\n",argv[0], d->optarg);
  384. }
  385. d->__nextchar += strlen(d->__nextchar);
  386. d->optind++;
  387. return '?';
  388. }
  389. if (pfound != NULL)
  390. {
  391. option_index = indfound;
  392. if (*nameend)
  393. {
  394. if (pfound->has_arg)
  395. d->optarg = nameend + 1;
  396. else
  397. {
  398. if (print_errors)
  399. {
  400. fprintf(stderr, "%s: option '-W %s' doesn't allow an argument\n",argv[0], pfound->name);
  401. }
  402. d->__nextchar += strlen(d->__nextchar);
  403. return '?';
  404. }
  405. }
  406. else if (pfound->has_arg == 1)
  407. {
  408. if (d->optind < argc)
  409. d->optarg = argv[d->optind++];
  410. else
  411. {
  412. if (print_errors)
  413. {
  414. fprintf(stderr, "%s: option '-W %s' requires an argument\n",argv[0], pfound->name);
  415. }
  416. d->__nextchar += strlen(d->__nextchar);
  417. return optstring[0] == ':' ? ':' : '?';
  418. }
  419. }
  420. else
  421. d->optarg = NULL;
  422. d->__nextchar += strlen(d->__nextchar);
  423. if (longind != NULL)
  424. *longind = option_index;
  425. if (pfound->flag)
  426. {
  427. *(pfound->flag) = pfound->val;
  428. return 0;
  429. }
  430. return pfound->val;
  431. }
  432. no_longs:
  433. d->__nextchar = NULL;
  434. return 'W';
  435. }
  436. if (temp[1] == ':')
  437. {
  438. if (temp[2] == ':')
  439. {
  440. if (*d->__nextchar != '\0')
  441. {
  442. d->optarg = d->__nextchar;
  443. d->optind++;
  444. }
  445. else
  446. d->optarg = NULL;
  447. d->__nextchar = NULL;
  448. }
  449. else
  450. {
  451. if (*d->__nextchar != '\0')
  452. {
  453. d->optarg = d->__nextchar;
  454. d->optind++;
  455. }
  456. else if (d->optind == argc)
  457. {
  458. if (print_errors)
  459. {
  460. fprintf(stderr,"%s: option requires an argument -- '%c'\n",argv[0], c);
  461. }
  462. d->optopt = c;
  463. if (optstring[0] == ':')
  464. c = ':';
  465. else
  466. c = '?';
  467. }
  468. else
  469. d->optarg = argv[d->optind++];
  470. d->__nextchar = NULL;
  471. }
  472. }
  473. return c;
  474. }
  475. }
  476. int _getopt_internal_a (int argc, char *const *argv, const char *optstring, const struct option_a *longopts, int *longind, int long_only, int posixly_correct)
  477. {
  478. int result;
  479. getopt_data_a.optind = optind;
  480. getopt_data_a.opterr = opterr;
  481. result = _getopt_internal_r_a (argc, argv, optstring, longopts,longind, long_only, &getopt_data_a,posixly_correct);
  482. optind = getopt_data_a.optind;
  483. optarg_a = getopt_data_a.optarg;
  484. optopt = getopt_data_a.optopt;
  485. return result;
  486. }
  487. int getopt_a (int argc, char *const *argv, const char *optstring) _GETOPT_THROW
  488. {
  489. return _getopt_internal_a (argc, argv, optstring, (const struct option_a *) 0, (int *) 0, 0, 0);
  490. }
  491. int getopt_long_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW
  492. {
  493. return _getopt_internal_a (argc, argv, options, long_options, opt_index, 0, 0);
  494. }
  495. int getopt_long_only_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW
  496. {
  497. return _getopt_internal_a (argc, argv, options, long_options, opt_index, 1, 0);
  498. }
  499. int _getopt_long_r_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index, struct _getopt_data_a *d)
  500. {
  501. return _getopt_internal_r_a (argc, argv, options, long_options, opt_index,0, d, 0);
  502. }
  503. int _getopt_long_only_r_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index, struct _getopt_data_a *d)
  504. {
  505. return _getopt_internal_r_a (argc, argv, options, long_options, opt_index, 1, d, 0);
  506. }
  507. //
  508. //
  509. // Unicode Structures and Functions
  510. //
  511. //
  512. static struct _getopt_data_w
  513. {
  514. int optind;
  515. int opterr;
  516. int optopt;
  517. wchar_t *optarg;
  518. int __initialized;
  519. wchar_t *__nextchar;
  520. enum ENUM_ORDERING __ordering;
  521. int __posixly_correct;
  522. int __first_nonopt;
  523. int __last_nonopt;
  524. } getopt_data_w;
  525. wchar_t *optarg_w;
  526. static void exchange_w(wchar_t **argv, struct _getopt_data_w *d)
  527. {
  528. int bottom = d->__first_nonopt;
  529. int middle = d->__last_nonopt;
  530. int top = d->optind;
  531. wchar_t *tem;
  532. while (top > middle && middle > bottom)
  533. {
  534. if (top - middle > middle - bottom)
  535. {
  536. int len = middle - bottom;
  537. int i;
  538. for (i = 0; i < len; i++)
  539. {
  540. tem = argv[bottom + i];
  541. argv[bottom + i] = argv[top - (middle - bottom) + i];
  542. argv[top - (middle - bottom) + i] = tem;
  543. }
  544. top -= len;
  545. }
  546. else
  547. {
  548. int len = top - middle;
  549. int i;
  550. for (i = 0; i < len; i++)
  551. {
  552. tem = argv[bottom + i];
  553. argv[bottom + i] = argv[middle + i];
  554. argv[middle + i] = tem;
  555. }
  556. bottom += len;
  557. }
  558. }
  559. d->__first_nonopt += (d->optind - d->__last_nonopt);
  560. d->__last_nonopt = d->optind;
  561. }
  562. static const wchar_t *_getopt_initialize_w (const wchar_t *optstring, struct _getopt_data_w *d, int posixly_correct)
  563. {
  564. d->__first_nonopt = d->__last_nonopt = d->optind;
  565. d->__nextchar = NULL;
  566. d->__posixly_correct = posixly_correct | !!_wgetenv(L"POSIXLY_CORRECT");
  567. if (optstring[0] == L'-')
  568. {
  569. d->__ordering = RETURN_IN_ORDER;
  570. ++optstring;
  571. }
  572. else if (optstring[0] == L'+')
  573. {
  574. d->__ordering = REQUIRE_ORDER;
  575. ++optstring;
  576. }
  577. else if (d->__posixly_correct)
  578. d->__ordering = REQUIRE_ORDER;
  579. else
  580. d->__ordering = PERMUTE;
  581. return optstring;
  582. }
  583. int _getopt_internal_r_w (int argc, wchar_t *const *argv, const wchar_t *optstring, const struct option_w *longopts, int *longind, int long_only, struct _getopt_data_w *d, int posixly_correct)
  584. {
  585. int print_errors = d->opterr;
  586. if (argc < 1)
  587. return -1;
  588. d->optarg = NULL;
  589. if (d->optind == 0 || !d->__initialized)
  590. {
  591. if (d->optind == 0)
  592. d->optind = 1;
  593. optstring = _getopt_initialize_w (optstring, d, posixly_correct);
  594. d->__initialized = 1;
  595. }
  596. else if (optstring[0] == L'-' || optstring[0] == L'+')
  597. optstring++;
  598. if (optstring[0] == L':')
  599. print_errors = 0;
  600. if (d->__nextchar == NULL || *d->__nextchar == L'\0')
  601. {
  602. if (d->__last_nonopt > d->optind)
  603. d->__last_nonopt = d->optind;
  604. if (d->__first_nonopt > d->optind)
  605. d->__first_nonopt = d->optind;
  606. if (d->__ordering == PERMUTE)
  607. {
  608. if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind)
  609. exchange_w((wchar_t **) argv, d);
  610. else if (d->__last_nonopt != d->optind)
  611. d->__first_nonopt = d->optind;
  612. while (d->optind < argc && (argv[d->optind][0] != L'-' || argv[d->optind][1] == L'\0'))
  613. d->optind++;
  614. d->__last_nonopt = d->optind;
  615. }
  616. if (d->optind != argc && !wcscmp(argv[d->optind], L"--"))
  617. {
  618. d->optind++;
  619. if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind)
  620. exchange_w((wchar_t **) argv, d);
  621. else if (d->__first_nonopt == d->__last_nonopt)
  622. d->__first_nonopt = d->optind;
  623. d->__last_nonopt = argc;
  624. d->optind = argc;
  625. }
  626. if (d->optind == argc)
  627. {
  628. if (d->__first_nonopt != d->__last_nonopt)
  629. d->optind = d->__first_nonopt;
  630. return -1;
  631. }
  632. if ((argv[d->optind][0] != L'-' || argv[d->optind][1] == L'\0'))
  633. {
  634. if (d->__ordering == REQUIRE_ORDER)
  635. return -1;
  636. d->optarg = argv[d->optind++];
  637. return 1;
  638. }
  639. d->__nextchar = (argv[d->optind] + 1 + (longopts != NULL && argv[d->optind][1] == L'-'));
  640. }
  641. if (longopts != NULL && (argv[d->optind][1] == L'-' || (long_only && (argv[d->optind][2] || !wcschr(optstring, argv[d->optind][1])))))
  642. {
  643. wchar_t *nameend;
  644. unsigned int namelen;
  645. const struct option_w *p;
  646. const struct option_w *pfound = NULL;
  647. struct option_list
  648. {
  649. const struct option_w *p;
  650. struct option_list *next;
  651. } *ambig_list = NULL;
  652. int exact = 0;
  653. int indfound = -1;
  654. int option_index;
  655. for (nameend = d->__nextchar; *nameend && *nameend != L'='; nameend++);
  656. namelen = (unsigned int)(nameend - d->__nextchar);
  657. for (p = longopts, option_index = 0; p->name; p++, option_index++)
  658. if (!wcsncmp(p->name, d->__nextchar, namelen))
  659. {
  660. if (namelen == (unsigned int)wcslen(p->name))
  661. {
  662. pfound = p;
  663. indfound = option_index;
  664. exact = 1;
  665. break;
  666. }
  667. else if (pfound == NULL)
  668. {
  669. pfound = p;
  670. indfound = option_index;
  671. }
  672. else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
  673. {
  674. struct option_list *newp = (struct option_list*)alloca(sizeof(*newp));
  675. newp->p = p;
  676. newp->next = ambig_list;
  677. ambig_list = newp;
  678. }
  679. }
  680. if (ambig_list != NULL && !exact)
  681. {
  682. if (print_errors)
  683. {
  684. struct option_list first;
  685. first.p = pfound;
  686. first.next = ambig_list;
  687. ambig_list = &first;
  688. fwprintf(stderr, L"%s: option '%s' is ambiguous; possibilities:", argv[0], argv[d->optind]);
  689. do
  690. {
  691. fwprintf (stderr, L" '--%s'", ambig_list->p->name);
  692. ambig_list = ambig_list->next;
  693. }
  694. while (ambig_list != NULL);
  695. fputwc (L'\n', stderr);
  696. }
  697. d->__nextchar += wcslen(d->__nextchar);
  698. d->optind++;
  699. d->optopt = 0;
  700. return L'?';
  701. }
  702. if (pfound != NULL)
  703. {
  704. option_index = indfound;
  705. d->optind++;
  706. if (*nameend)
  707. {
  708. if (pfound->has_arg)
  709. d->optarg = nameend + 1;
  710. else
  711. {
  712. if (print_errors)
  713. {
  714. if (argv[d->optind - 1][1] == L'-')
  715. {
  716. fwprintf(stderr, L"%s: option '--%s' doesn't allow an argument\n",argv[0], pfound->name);
  717. }
  718. else
  719. {
  720. fwprintf(stderr, L"%s: option '%c%s' doesn't allow an argument\n",argv[0], argv[d->optind - 1][0],pfound->name);
  721. }
  722. }
  723. d->__nextchar += wcslen(d->__nextchar);
  724. d->optopt = pfound->val;
  725. return L'?';
  726. }
  727. }
  728. else if (pfound->has_arg == 1)
  729. {
  730. if (d->optind < argc)
  731. d->optarg = argv[d->optind++];
  732. else
  733. {
  734. if (print_errors)
  735. {
  736. fwprintf(stderr,L"%s: option '--%s' requires an argument\n",argv[0], pfound->name);
  737. }
  738. d->__nextchar += wcslen(d->__nextchar);
  739. d->optopt = pfound->val;
  740. return optstring[0] == L':' ? L':' : L'?';
  741. }
  742. }
  743. d->__nextchar += wcslen(d->__nextchar);
  744. if (longind != NULL)
  745. *longind = option_index;
  746. if (pfound->flag)
  747. {
  748. *(pfound->flag) = pfound->val;
  749. return 0;
  750. }
  751. return pfound->val;
  752. }
  753. if (!long_only || argv[d->optind][1] == L'-' || wcschr(optstring, *d->__nextchar) == NULL)
  754. {
  755. if (print_errors)
  756. {
  757. if (argv[d->optind][1] == L'-')
  758. {
  759. fwprintf(stderr, L"%s: unrecognized option '--%s'\n",argv[0], d->__nextchar);
  760. }
  761. else
  762. {
  763. fwprintf(stderr, L"%s: unrecognized option '%c%s'\n",argv[0], argv[d->optind][0], d->__nextchar);
  764. }
  765. }
  766. d->__nextchar = (wchar_t *)L"";
  767. d->optind++;
  768. d->optopt = 0;
  769. return L'?';
  770. }
  771. }
  772. {
  773. wchar_t c = *d->__nextchar++;
  774. wchar_t *temp = (wchar_t*)wcschr(optstring, c);
  775. if (*d->__nextchar == L'\0')
  776. ++d->optind;
  777. if (temp == NULL || c == L':' || c == L';')
  778. {
  779. if (print_errors)
  780. {
  781. fwprintf(stderr, L"%s: invalid option -- '%c'\n", argv[0], c);
  782. }
  783. d->optopt = c;
  784. return L'?';
  785. }
  786. if (temp[0] == L'W' && temp[1] == L';')
  787. {
  788. wchar_t *nameend;
  789. const struct option_w *p;
  790. const struct option_w *pfound = NULL;
  791. int exact = 0;
  792. int ambig = 0;
  793. int indfound = 0;
  794. int option_index;
  795. if (longopts == NULL)
  796. goto no_longs;
  797. if (*d->__nextchar != L'\0')
  798. {
  799. d->optarg = d->__nextchar;
  800. d->optind++;
  801. }
  802. else if (d->optind == argc)
  803. {
  804. if (print_errors)
  805. {
  806. fwprintf(stderr,L"%s: option requires an argument -- '%c'\n",argv[0], c);
  807. }
  808. d->optopt = c;
  809. if (optstring[0] == L':')
  810. c = L':';
  811. else
  812. c = L'?';
  813. return c;
  814. }
  815. else
  816. d->optarg = argv[d->optind++];
  817. for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != L'='; nameend++);
  818. for (p = longopts, option_index = 0; p->name; p++, option_index++)
  819. if (!wcsncmp(p->name, d->__nextchar, nameend - d->__nextchar))
  820. {
  821. if ((unsigned int) (nameend - d->__nextchar) == wcslen(p->name))
  822. {
  823. pfound = p;
  824. indfound = option_index;
  825. exact = 1;
  826. break;
  827. }
  828. else if (pfound == NULL)
  829. {
  830. pfound = p;
  831. indfound = option_index;
  832. }
  833. else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
  834. ambig = 1;
  835. }
  836. if (ambig && !exact)
  837. {
  838. if (print_errors)
  839. {
  840. fwprintf(stderr, L"%s: option '-W %s' is ambiguous\n",argv[0], d->optarg);
  841. }
  842. d->__nextchar += wcslen(d->__nextchar);
  843. d->optind++;
  844. return L'?';
  845. }
  846. if (pfound != NULL)
  847. {
  848. option_index = indfound;
  849. if (*nameend)
  850. {
  851. if (pfound->has_arg)
  852. d->optarg = nameend + 1;
  853. else
  854. {
  855. if (print_errors)
  856. {
  857. fwprintf(stderr, L"%s: option '-W %s' doesn't allow an argument\n",argv[0], pfound->name);
  858. }
  859. d->__nextchar += wcslen(d->__nextchar);
  860. return L'?';
  861. }
  862. }
  863. else if (pfound->has_arg == 1)
  864. {
  865. if (d->optind < argc)
  866. d->optarg = argv[d->optind++];
  867. else
  868. {
  869. if (print_errors)
  870. {
  871. fwprintf(stderr, L"%s: option '-W %s' requires an argument\n",argv[0], pfound->name);
  872. }
  873. d->__nextchar += wcslen(d->__nextchar);
  874. return optstring[0] == L':' ? L':' : L'?';
  875. }
  876. }
  877. else
  878. d->optarg = NULL;
  879. d->__nextchar += wcslen(d->__nextchar);
  880. if (longind != NULL)
  881. *longind = option_index;
  882. if (pfound->flag)
  883. {
  884. *(pfound->flag) = pfound->val;
  885. return 0;
  886. }
  887. return pfound->val;
  888. }
  889. no_longs:
  890. d->__nextchar = NULL;
  891. return L'W';
  892. }
  893. if (temp[1] == L':')
  894. {
  895. if (temp[2] == L':')
  896. {
  897. if (*d->__nextchar != L'\0')
  898. {
  899. d->optarg = d->__nextchar;
  900. d->optind++;
  901. }
  902. else
  903. d->optarg = NULL;
  904. d->__nextchar = NULL;
  905. }
  906. else
  907. {
  908. if (*d->__nextchar != L'\0')
  909. {
  910. d->optarg = d->__nextchar;
  911. d->optind++;
  912. }
  913. else if (d->optind == argc)
  914. {
  915. if (print_errors)
  916. {
  917. fwprintf(stderr,L"%s: option requires an argument -- '%c'\n",argv[0], c);
  918. }
  919. d->optopt = c;
  920. if (optstring[0] == L':')
  921. c = L':';
  922. else
  923. c = L'?';
  924. }
  925. else
  926. d->optarg = argv[d->optind++];
  927. d->__nextchar = NULL;
  928. }
  929. }
  930. return c;
  931. }
  932. }
  933. int _getopt_internal_w (int argc, wchar_t *const *argv, const wchar_t *optstring, const struct option_w *longopts, int *longind, int long_only, int posixly_correct)
  934. {
  935. int result;
  936. getopt_data_w.optind = optind;
  937. getopt_data_w.opterr = opterr;
  938. result = _getopt_internal_r_w (argc, argv, optstring, longopts,longind, long_only, &getopt_data_w,posixly_correct);
  939. optind = getopt_data_w.optind;
  940. optarg_w = getopt_data_w.optarg;
  941. optopt = getopt_data_w.optopt;
  942. return result;
  943. }
  944. int getopt_w (int argc, wchar_t *const *argv, const wchar_t *optstring) _GETOPT_THROW
  945. {
  946. return _getopt_internal_w (argc, argv, optstring, (const struct option_w *) 0, (int *) 0, 0, 0);
  947. }
  948. int getopt_long_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW
  949. {
  950. return _getopt_internal_w (argc, argv, options, long_options, opt_index, 0, 0);
  951. }
  952. int getopt_long_only_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW
  953. {
  954. return _getopt_internal_w (argc, argv, options, long_options, opt_index, 1, 0);
  955. }
  956. int _getopt_long_r_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index, struct _getopt_data_w *d)
  957. {
  958. return _getopt_internal_r_w (argc, argv, options, long_options, opt_index,0, d, 0);
  959. }
  960. int _getopt_long_only_r_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index, struct _getopt_data_w *d)
  961. {
  962. return _getopt_internal_r_w (argc, argv, options, long_options, opt_index, 1, d, 0);
  963. }