jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

615 lines
17KB

  1. /**
  2. * DISCLAIMER
  3. * This file is part of the mingw-w64 runtime package.
  4. *
  5. * The mingw-w64 runtime package and its code is distributed in the hope that it
  6. * will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR
  7. * IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to
  8. * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. */
  10. /*
  11. * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
  12. *
  13. * Permission to use, copy, modify, and distribute this software for any
  14. * purpose with or without fee is hereby granted, provided that the above
  15. * copyright notice and this permission notice appear in all copies.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  18. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  19. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  20. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  21. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  22. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  23. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  24. *
  25. * Sponsored in part by the Defense Advanced Research Projects
  26. * Agency (DARPA) and Air Force Research Laboratory, Air Force
  27. * Materiel Command, USAF, under agreement number F39502-99-1-0512.
  28. */
  29. /*-
  30. * Copyright (c) 2000 The NetBSD Foundation, Inc.
  31. * All rights reserved.
  32. *
  33. * This code is derived from software contributed to The NetBSD Foundation
  34. * by Dieter Baron and Thomas Klausner.
  35. *
  36. * Redistribution and use in source and binary forms, with or without
  37. * modification, are permitted provided that the following conditions
  38. * are met:
  39. * 1. Redistributions of source code must retain the above copyright
  40. * notice, this list of conditions and the following disclaimer.
  41. * 2. Redistributions in binary form must reproduce the above copyright
  42. * notice, this list of conditions and the following disclaimer in the
  43. * documentation and/or other materials provided with the distribution.
  44. *
  45. * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  46. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  47. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  48. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  49. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  50. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  51. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  52. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  53. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  54. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  55. * POSSIBILITY OF SUCH DAMAGE.
  56. */
  57. #pragma warning(disable:4996)
  58. #include <crtdefs.h>
  59. #include <errno.h>
  60. #include <stdlib.h>
  61. #include <string.h>
  62. #include <stdarg.h>
  63. #include <stdio.h>
  64. #include <windows.h>
  65. #include "getopt.h"
  66. int opterr = 1; /* if error message should be printed */
  67. int optind = 1; /* index into parent argv vector */
  68. int optopt = '?'; /* character checked for validity */
  69. #undef optreset /* see getopt.h */
  70. #define optreset __mingw_optreset
  71. int optreset; /* reset getopt */
  72. char *optarg; /* argument associated with option */
  73. #define PRINT_ERROR ((opterr) && (*options != ':'))
  74. #define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
  75. #define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
  76. #define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
  77. /* return values */
  78. #define BADCH (int)'?'
  79. #define BADARG ((*options == ':') ? (int)':' : (int)'?')
  80. #define INORDER (int)1
  81. #ifndef __CYGWIN__
  82. #define __progname __argv[0]
  83. #else
  84. extern char __declspec(dllimport) *__progname;
  85. #endif
  86. #ifdef __CYGWIN__
  87. static char EMSG[] = "";
  88. #else
  89. #define EMSG ""
  90. #endif
  91. static int getopt_internal(int, char * const *, const char *,
  92. const struct option *, int *, int);
  93. static int parse_long_options(char * const *, const char *,
  94. const struct option *, int *, int);
  95. static int gcd(int, int);
  96. static void permute_args(int, int, int, char * const *);
  97. static char *place = EMSG; /* option letter processing */
  98. /* XXX: set optreset to 1 rather than these two */
  99. static int nonopt_start = -1; /* first non option argument (for permute) */
  100. static int nonopt_end = -1; /* first option after non options (for permute) */
  101. /* Error messages */
  102. static const char recargchar[] = "option requires an argument -- %c";
  103. static const char recargstring[] = "option requires an argument -- %s";
  104. static const char ambig[] = "ambiguous option -- %.*s";
  105. static const char noarg[] = "option doesn't take an argument -- %.*s";
  106. static const char illoptchar[] = "unknown option -- %c";
  107. static const char illoptstring[] = "unknown option -- %s";
  108. static void
  109. _vwarnx(const char *fmt,va_list ap)
  110. {
  111. (void)fprintf(stderr,"%s: ",__progname);
  112. if (fmt != NULL)
  113. (void)vfprintf(stderr,fmt,ap);
  114. (void)fprintf(stderr,"\n");
  115. }
  116. static void
  117. warnx(const char *fmt,...)
  118. {
  119. va_list ap;
  120. va_start(ap,fmt);
  121. _vwarnx(fmt,ap);
  122. va_end(ap);
  123. }
  124. /*
  125. * Compute the greatest common divisor of a and b.
  126. */
  127. static int
  128. gcd(int a, int b)
  129. {
  130. int c;
  131. c = a % b;
  132. while (c != 0) {
  133. a = b;
  134. b = c;
  135. c = a % b;
  136. }
  137. return (b);
  138. }
  139. /*
  140. * Exchange the block from nonopt_start to nonopt_end with the block
  141. * from nonopt_end to opt_end (keeping the same order of arguments
  142. * in each block).
  143. */
  144. static void
  145. permute_args(int panonopt_start, int panonopt_end, int opt_end,
  146. char * const *nargv)
  147. {
  148. int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
  149. char *swap;
  150. /*
  151. * compute lengths of blocks and number and size of cycles
  152. */
  153. nnonopts = panonopt_end - panonopt_start;
  154. nopts = opt_end - panonopt_end;
  155. ncycle = gcd(nnonopts, nopts);
  156. cyclelen = (opt_end - panonopt_start) / ncycle;
  157. for (i = 0; i < ncycle; i++) {
  158. cstart = panonopt_end+i;
  159. pos = cstart;
  160. for (j = 0; j < cyclelen; j++) {
  161. if (pos >= panonopt_end)
  162. pos -= nnonopts;
  163. else
  164. pos += nopts;
  165. swap = nargv[pos];
  166. /* LINTED const cast */
  167. ((char **) nargv)[pos] = nargv[cstart];
  168. /* LINTED const cast */
  169. ((char **)nargv)[cstart] = swap;
  170. }
  171. }
  172. }
  173. /*
  174. * getopt --
  175. * Parse argc/argv argument vector.
  176. *
  177. * [eventually this will replace the BSD getopt]
  178. */
  179. int
  180. getopt(int nargc, char * const *nargv, const char *options)
  181. {
  182. /*
  183. * We don't pass FLAG_PERMUTE to getopt_internal() since
  184. * the BSD getopt(3) (unlike GNU) has never done this.
  185. *
  186. * Furthermore, since many privileged programs call getopt()
  187. * before dropping privileges it makes sense to keep things
  188. * as simple (and bug-free) as possible.
  189. */
  190. return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
  191. }
  192. //extern int getopt(int nargc, char * const *nargv, const char *options);
  193. #ifdef _BSD_SOURCE
  194. /*
  195. * BSD adds the non-standard `optreset' feature, for reinitialisation
  196. * of `getopt' parsing. We support this feature, for applications which
  197. * proclaim their BSD heritage, before including this header; however,
  198. * to maintain portability, developers are advised to avoid it.
  199. */
  200. # define optreset __mingw_optreset
  201. extern int optreset;
  202. #endif
  203. #ifdef __cplusplus
  204. }
  205. #endif
  206. /*
  207. * POSIX requires the `getopt' API to be specified in `unistd.h';
  208. * thus, `unistd.h' includes this header. However, we do not want
  209. * to expose the `getopt_long' or `getopt_long_only' APIs, when
  210. * included in this manner. Thus, close the standard __GETOPT_H__
  211. * declarations block, and open an additional __GETOPT_LONG_H__
  212. * specific block, only when *not* __UNISTD_H_SOURCED__, in which
  213. * to declare the extended API.
  214. */
  215. #if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__)
  216. #define __GETOPT_LONG_H__
  217. #ifdef __cplusplus
  218. extern "C" {
  219. #endif
  220. /*
  221. * parse_long_options --
  222. * Parse long options in argc/argv argument vector.
  223. * Returns -1 if short_too is set and the option does not match long_options.
  224. */
  225. static int
  226. parse_long_options(char * const *nargv, const char *options,
  227. const struct option *long_options, int *idx, int short_too)
  228. {
  229. char *current_argv, *has_equal;
  230. size_t current_argv_len;
  231. int i, ambiguous, match;
  232. #define IDENTICAL_INTERPRETATION(_x, _y) \
  233. (long_options[(_x)].has_arg == long_options[(_y)].has_arg && \
  234. long_options[(_x)].flag == long_options[(_y)].flag && \
  235. long_options[(_x)].val == long_options[(_y)].val)
  236. current_argv = place;
  237. match = -1;
  238. ambiguous = 0;
  239. optind++;
  240. if ((has_equal = strchr(current_argv, '=')) != NULL) {
  241. /* argument found (--option=arg) */
  242. current_argv_len = has_equal - current_argv;
  243. has_equal++;
  244. } else
  245. current_argv_len = strlen(current_argv);
  246. for (i = 0; long_options[i].name; i++) {
  247. /* find matching long option */
  248. if (strncmp(current_argv, long_options[i].name,
  249. current_argv_len))
  250. continue;
  251. if (strlen(long_options[i].name) == current_argv_len) {
  252. /* exact match */
  253. match = i;
  254. ambiguous = 0;
  255. break;
  256. }
  257. /*
  258. * If this is a known short option, don't allow
  259. * a partial match of a single character.
  260. */
  261. if (short_too && current_argv_len == 1)
  262. continue;
  263. if (match == -1) /* partial match */
  264. match = i;
  265. else if (!IDENTICAL_INTERPRETATION(i, match))
  266. ambiguous = 1;
  267. }
  268. if (ambiguous) {
  269. /* ambiguous abbreviation */
  270. if (PRINT_ERROR)
  271. warnx(ambig, (int)current_argv_len,
  272. current_argv);
  273. optopt = 0;
  274. return (BADCH);
  275. }
  276. if (match != -1) { /* option found */
  277. if (long_options[match].has_arg == no_argument
  278. && has_equal) {
  279. if (PRINT_ERROR)
  280. warnx(noarg, (int)current_argv_len,
  281. current_argv);
  282. /*
  283. * XXX: GNU sets optopt to val regardless of flag
  284. */
  285. if (long_options[match].flag == NULL)
  286. optopt = long_options[match].val;
  287. else
  288. optopt = 0;
  289. return (BADARG);
  290. }
  291. if (long_options[match].has_arg == required_argument ||
  292. long_options[match].has_arg == optional_argument) {
  293. if (has_equal)
  294. optarg = has_equal;
  295. else if (long_options[match].has_arg ==
  296. required_argument) {
  297. /*
  298. * optional argument doesn't use next nargv
  299. */
  300. optarg = nargv[optind++];
  301. }
  302. }
  303. if ((long_options[match].has_arg == required_argument)
  304. && (optarg == NULL)) {
  305. /*
  306. * Missing argument; leading ':' indicates no error
  307. * should be generated.
  308. */
  309. if (PRINT_ERROR)
  310. warnx(recargstring,
  311. current_argv);
  312. /*
  313. * XXX: GNU sets optopt to val regardless of flag
  314. */
  315. if (long_options[match].flag == NULL)
  316. optopt = long_options[match].val;
  317. else
  318. optopt = 0;
  319. --optind;
  320. return (BADARG);
  321. }
  322. } else { /* unknown option */
  323. if (short_too) {
  324. --optind;
  325. return (-1);
  326. }
  327. if (PRINT_ERROR)
  328. warnx(illoptstring, current_argv);
  329. optopt = 0;
  330. return (BADCH);
  331. }
  332. if (idx)
  333. *idx = match;
  334. if (long_options[match].flag) {
  335. *long_options[match].flag = long_options[match].val;
  336. return (0);
  337. } else
  338. return (long_options[match].val);
  339. #undef IDENTICAL_INTERPRETATION
  340. }
  341. /*
  342. * getopt_internal --
  343. * Parse argc/argv argument vector. Called by user level routines.
  344. */
  345. static int
  346. getopt_internal(int nargc, char * const *nargv, const char *options,
  347. const struct option *long_options, int *idx, int flags)
  348. {
  349. char *oli; /* option letter list index */
  350. int optchar, short_too;
  351. static int posixly_correct = -1;
  352. if (options == NULL)
  353. return (-1);
  354. /*
  355. * XXX Some GNU programs (like cvs) set optind to 0 instead of
  356. * XXX using optreset. Work around this braindamage.
  357. */
  358. if (optind == 0)
  359. optind = optreset = 1;
  360. /*
  361. * Disable GNU extensions if POSIXLY_CORRECT is set or options
  362. * string begins with a '+'.
  363. *
  364. * CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or
  365. * optreset != 0 for GNU compatibility.
  366. */
  367. if (posixly_correct == -1 || optreset != 0)
  368. posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
  369. if (*options == '-')
  370. flags |= FLAG_ALLARGS;
  371. else if (posixly_correct || *options == '+')
  372. flags &= ~FLAG_PERMUTE;
  373. if (*options == '+' || *options == '-')
  374. options++;
  375. optarg = NULL;
  376. if (optreset)
  377. nonopt_start = nonopt_end = -1;
  378. start:
  379. if (optreset || !*place) { /* update scanning pointer */
  380. optreset = 0;
  381. if (optind >= nargc) { /* end of argument vector */
  382. place = EMSG;
  383. if (nonopt_end != -1) {
  384. /* do permutation, if we have to */
  385. permute_args(nonopt_start, nonopt_end,
  386. optind, nargv);
  387. optind -= nonopt_end - nonopt_start;
  388. }
  389. else if (nonopt_start != -1) {
  390. /*
  391. * If we skipped non-options, set optind
  392. * to the first of them.
  393. */
  394. optind = nonopt_start;
  395. }
  396. nonopt_start = nonopt_end = -1;
  397. return (-1);
  398. }
  399. if (*(place = nargv[optind]) != '-' ||
  400. (place[1] == '\0' && strchr(options, '-') == NULL)) {
  401. place = EMSG; /* found non-option */
  402. if (flags & FLAG_ALLARGS) {
  403. /*
  404. * GNU extension:
  405. * return non-option as argument to option 1
  406. */
  407. optarg = nargv[optind++];
  408. return (INORDER);
  409. }
  410. if (!(flags & FLAG_PERMUTE)) {
  411. /*
  412. * If no permutation wanted, stop parsing
  413. * at first non-option.
  414. */
  415. return (-1);
  416. }
  417. /* do permutation */
  418. if (nonopt_start == -1)
  419. nonopt_start = optind;
  420. else if (nonopt_end != -1) {
  421. permute_args(nonopt_start, nonopt_end,
  422. optind, nargv);
  423. nonopt_start = optind -
  424. (nonopt_end - nonopt_start);
  425. nonopt_end = -1;
  426. }
  427. optind++;
  428. /* process next argument */
  429. goto start;
  430. }
  431. if (nonopt_start != -1 && nonopt_end == -1)
  432. nonopt_end = optind;
  433. /*
  434. * If we have "-" do nothing, if "--" we are done.
  435. */
  436. if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
  437. optind++;
  438. place = EMSG;
  439. /*
  440. * We found an option (--), so if we skipped
  441. * non-options, we have to permute.
  442. */
  443. if (nonopt_end != -1) {
  444. permute_args(nonopt_start, nonopt_end,
  445. optind, nargv);
  446. optind -= nonopt_end - nonopt_start;
  447. }
  448. nonopt_start = nonopt_end = -1;
  449. return (-1);
  450. }
  451. }
  452. /*
  453. * Check long options if:
  454. * 1) we were passed some
  455. * 2) the arg is not just "-"
  456. * 3) either the arg starts with -- we are getopt_long_only()
  457. */
  458. if (long_options != NULL && place != nargv[optind] &&
  459. (*place == '-' || (flags & FLAG_LONGONLY))) {
  460. short_too = 0;
  461. if (*place == '-')
  462. place++; /* --foo long option */
  463. else if (*place != ':' && strchr(options, *place) != NULL)
  464. short_too = 1; /* could be short option too */
  465. optchar = parse_long_options(nargv, options, long_options,
  466. idx, short_too);
  467. if (optchar != -1) {
  468. place = EMSG;
  469. return (optchar);
  470. }
  471. }
  472. if ((optchar = (int)*place++) == (int)':' ||
  473. (optchar == (int)'-' && *place != '\0') ||
  474. (oli = (char*)strchr(options, optchar)) == NULL) {
  475. /*
  476. * If the user specified "-" and '-' isn't listed in
  477. * options, return -1 (non-option) as per POSIX.
  478. * Otherwise, it is an unknown option character (or ':').
  479. */
  480. if (optchar == (int)'-' && *place == '\0')
  481. return (-1);
  482. if (!*place)
  483. ++optind;
  484. if (PRINT_ERROR)
  485. warnx(illoptchar, optchar);
  486. optopt = optchar;
  487. return (BADCH);
  488. }
  489. if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
  490. /* -W long-option */
  491. if (*place) /* no space */
  492. /* NOTHING */;
  493. else if (++optind >= nargc) { /* no arg */
  494. place = EMSG;
  495. if (PRINT_ERROR)
  496. warnx(recargchar, optchar);
  497. optopt = optchar;
  498. return (BADARG);
  499. } else /* white space */
  500. place = nargv[optind];
  501. optchar = parse_long_options(nargv, options, long_options,
  502. idx, 0);
  503. place = EMSG;
  504. return (optchar);
  505. }
  506. if (*++oli != ':') { /* doesn't take argument */
  507. if (!*place)
  508. ++optind;
  509. } else { /* takes (optional) argument */
  510. optarg = NULL;
  511. if (*place) /* no white space */
  512. optarg = place;
  513. else if (oli[1] != ':') { /* arg not optional */
  514. if (++optind >= nargc) { /* no arg */
  515. place = EMSG;
  516. if (PRINT_ERROR)
  517. warnx(recargchar, optchar);
  518. optopt = optchar;
  519. return (BADARG);
  520. } else
  521. optarg = nargv[optind];
  522. }
  523. place = EMSG;
  524. ++optind;
  525. }
  526. /* dump back option letter */
  527. return (optchar);
  528. }
  529. /*
  530. * getopt_long --
  531. * Parse argc/argv argument vector.
  532. */
  533. int
  534. getopt_long(int nargc, char * const *nargv, const char *options,
  535. const struct option *long_options, int *idx)
  536. {
  537. return (getopt_internal(nargc, nargv, options, long_options, idx,
  538. FLAG_PERMUTE));
  539. }
  540. /*
  541. * getopt_long_only --
  542. * Parse argc/argv argument vector.
  543. */
  544. int
  545. getopt_long_only(int nargc, char * const *nargv, const char *options,
  546. const struct option *long_options, int *idx)
  547. {
  548. return (getopt_internal(nargc, nargv, options, long_options, idx,
  549. FLAG_PERMUTE|FLAG_LONGONLY));
  550. }
  551. //extern int getopt_long(int nargc, char * const *nargv, const char *options,
  552. // const struct option *long_options, int *idx);
  553. //extern int getopt_long_only(int nargc, char * const *nargv, const char *options,
  554. // const struct option *long_options, int *idx);
  555. /*
  556. * Previous MinGW implementation had...
  557. */
  558. #ifndef HAVE_DECL_GETOPT
  559. /*
  560. * ...for the long form API only; keep this for compatibility.
  561. */
  562. # define HAVE_DECL_GETOPT 1
  563. #endif
  564. #endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */