getopt.c
上传用户:hjq518
上传日期:2021-12-09
资源大小:5084k
文件大小:13k
源码类别:

Audio

开发平台:

Visual C++

  1. /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
  2. /*-
  3.  * Copyright (c) 2000 The NetBSD Foundation, Inc.
  4.  * All rights reserved.
  5.  *
  6.  * This code is derived from software contributed to The NetBSD Foundation
  7.  * by Dieter Baron and Thomas Klausner.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *        This product includes software developed by the NetBSD
  20.  *        Foundation, Inc. and its contributors.
  21.  * 4. Neither the name of The NetBSD Foundation nor the names of its
  22.  *    contributors may be used to endorse or promote products derived
  23.  *    from this software without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  26.  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  27.  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  28.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  29.  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  30.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  31.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  32.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  33.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  34.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  35.  * POSSIBILITY OF SUCH DAMAGE.
  36.  */
  37. #include <assert.h>
  38. #include <errno.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <getopt.h>
  42. #include <stdarg.h>
  43. #include <stdio.h>
  44. #define REPLACE_GETOPT
  45. #define _DIAGASSERT(x) do {} while (0)
  46. #ifdef REPLACE_GETOPT
  47. #ifdef __weak_alias
  48. __weak_alias(getopt,_getopt)
  49. #endif
  50. int opterr = 1; /* if error message should be printed */
  51. int optind = 1; /* index into parent argv vector */
  52. int optopt = '?'; /* character checked for validity */
  53. int optreset; /* reset getopt */
  54. char *optarg; /* argument associated with option */
  55. #endif
  56. #ifdef __weak_alias
  57. __weak_alias(getopt_long,_getopt_long)
  58. #endif
  59. char *__progname = "x264";
  60. #define IGNORE_FIRST (*options == '-' || *options == '+')
  61. #define PRINT_ERROR ((opterr) && ((*options != ':') 
  62.       || (IGNORE_FIRST && options[1] != ':')))
  63. #define IS_POSIXLY_CORRECT (getenv("POSIXLY_INCORRECT_GETOPT") == NULL)
  64. #define PERMUTE         (!IS_POSIXLY_CORRECT && !IGNORE_FIRST)
  65. /* XXX: GNU ignores PC if *options == '-' */
  66. #define IN_ORDER        (!IS_POSIXLY_CORRECT && *options == '-')
  67. /* return values */
  68. #define BADCH (int)'?'
  69. #define BADARG ((IGNORE_FIRST && options[1] == ':') 
  70.  || (*options == ':') ? (int)':' : (int)'?')
  71. #define INORDER (int)1
  72. static char EMSG[1];
  73. static int getopt_internal (int, char * const *, const char *);
  74. static int gcd (int, int);
  75. static void permute_args (int, int, int, char * const *);
  76. static char *place = EMSG; /* option letter processing */
  77. /* XXX: set optreset to 1 rather than these two */
  78. static int nonopt_start = -1; /* first non option argument (for permute) */
  79. static int nonopt_end = -1;   /* first option after non options (for permute) */
  80. /* Error messages */
  81. static const char recargchar[] = "option requires an argument -- %c";
  82. static const char recargstring[] = "option requires an argument -- %s";
  83. static const char ambig[] = "ambiguous option -- %.*s";
  84. static const char noarg[] = "option doesn't take an argument -- %.*s";
  85. static const char illoptchar[] = "unknown option -- %c";
  86. static const char illoptstring[] = "unknown option -- %s";
  87. static void
  88. _vwarnx(const char *fmt, va_list ap)
  89. {
  90.   (void)fprintf(stderr, "%s: ", __progname);
  91.   if (fmt != NULL)
  92.     (void)vfprintf(stderr, fmt, ap);
  93.   (void)fprintf(stderr, "n");
  94. }
  95. static void
  96. warnx(const char *fmt, ...)
  97. {
  98.   va_list ap;
  99.   va_start(ap, fmt);
  100.   _vwarnx(fmt, ap);
  101.   va_end(ap);
  102. }
  103. /*
  104.  * Compute the greatest common divisor of a and b.
  105.  */
  106. static int
  107. gcd(a, b)
  108. int a;
  109. int b;
  110. {
  111. int c;
  112. c = a % b;
  113. while (c != 0) {
  114. a = b;
  115. b = c;
  116. c = a % b;
  117. }
  118. return b;
  119. }
  120. /*
  121.  * Exchange the block from nonopt_start to nonopt_end with the block
  122.  * from nonopt_end to opt_end (keeping the same order of arguments
  123.  * in each block).
  124.  */
  125. static void
  126. permute_args(panonopt_start, panonopt_end, opt_end, nargv)
  127. int panonopt_start;
  128. int panonopt_end;
  129. int opt_end;
  130. char * const *nargv;
  131. {
  132. int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
  133. char *swap;
  134. _DIAGASSERT(nargv != NULL);
  135. /*
  136.  * compute lengths of blocks and number and size of cycles
  137.  */
  138. nnonopts = panonopt_end - panonopt_start;
  139. nopts = opt_end - panonopt_end;
  140. ncycle = gcd(nnonopts, nopts);
  141. cyclelen = (opt_end - panonopt_start) / ncycle;
  142. for (i = 0; i < ncycle; i++) {
  143. cstart = panonopt_end+i;
  144. pos = cstart;
  145. for (j = 0; j < cyclelen; j++) {
  146. if (pos >= panonopt_end)
  147. pos -= nnonopts;
  148. else
  149. pos += nopts;
  150. swap = nargv[pos];
  151. /* LINTED const cast */
  152. ((char **) nargv)[pos] = nargv[cstart];
  153. /* LINTED const cast */
  154. ((char **)nargv)[cstart] = swap;
  155. }
  156. }
  157. }
  158. /*
  159.  * getopt_internal --
  160.  * Parse argc/argv argument vector.  Called by user level routines.
  161.  *  Returns -2 if -- is found (can be long option or end of options marker).
  162.  */
  163. static int
  164. getopt_internal(nargc, nargv, options)
  165. int nargc;
  166. char * const *nargv;
  167. const char *options;
  168. {
  169. char *oli; /* option letter list index */
  170. int optchar;
  171. _DIAGASSERT(nargv != NULL);
  172. _DIAGASSERT(options != NULL);
  173. optarg = NULL;
  174. /*
  175.  * XXX Some programs (like rsyncd) expect to be able to
  176.  * XXX re-initialize optind to 0 and have getopt_long(3)
  177.  * XXX properly function again.  Work around this braindamage.
  178.  */
  179. if (optind == 0)
  180. optind = 1;
  181. if (optreset)
  182. nonopt_start = nonopt_end = -1;
  183. start:
  184. if (optreset || !*place) { /* update scanning pointer */
  185. optreset = 0;
  186. if (optind >= nargc) {          /* end of argument vector */
  187. place = EMSG;
  188. if (nonopt_end != -1) {
  189. /* do permutation, if we have to */
  190. permute_args(nonopt_start, nonopt_end,
  191.     optind, nargv);
  192. optind -= nonopt_end - nonopt_start;
  193. }
  194. else if (nonopt_start != -1) {
  195. /*
  196.  * If we skipped non-options, set optind
  197.  * to the first of them.
  198.  */
  199. optind = nonopt_start;
  200. }
  201. nonopt_start = nonopt_end = -1;
  202. return -1;
  203. }
  204. if ((*(place = nargv[optind]) != '-')
  205.     || (place[1] == '')) {    /* found non-option */
  206. place = EMSG;
  207. if (IN_ORDER) {
  208. /*
  209.  * GNU extension:
  210.  * return non-option as argument to option 1
  211.  */
  212. optarg = nargv[optind++];
  213. return INORDER;
  214. }
  215. if (!PERMUTE) {
  216. /*
  217.  * if no permutation wanted, stop parsing
  218.  * at first non-option
  219.  */
  220. return -1;
  221. }
  222. /* do permutation */
  223. if (nonopt_start == -1)
  224. nonopt_start = optind;
  225. else if (nonopt_end != -1) {
  226. permute_args(nonopt_start, nonopt_end,
  227.     optind, nargv);
  228. nonopt_start = optind -
  229.     (nonopt_end - nonopt_start);
  230. nonopt_end = -1;
  231. }
  232. optind++;
  233. /* process next argument */
  234. goto start;
  235. }
  236. if (nonopt_start != -1 && nonopt_end == -1)
  237. nonopt_end = optind;
  238. if (place[1] && *++place == '-') { /* found "--" */
  239. place++;
  240. return -2;
  241. }
  242. }
  243. if ((optchar = (int)*place++) == (int)':' ||
  244.     (oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) {
  245. /* option letter unknown or ':' */
  246. if (!*place)
  247. ++optind;
  248. if (PRINT_ERROR)
  249. warnx(illoptchar, optchar);
  250. optopt = optchar;
  251. return BADCH;
  252. }
  253. if (optchar == 'W' && oli[1] == ';') { /* -W long-option */
  254. /* XXX: what if no long options provided (called by getopt)? */
  255. if (*place)
  256. return -2;
  257. if (++optind >= nargc) { /* no arg */
  258. place = EMSG;
  259. if (PRINT_ERROR)
  260. warnx(recargchar, optchar);
  261. optopt = optchar;
  262. return BADARG;
  263. } else /* white space */
  264. place = nargv[optind];
  265. /*
  266.  * Handle -W arg the same as --arg (which causes getopt to
  267.  * stop parsing).
  268.  */
  269. return -2;
  270. }
  271. if (*++oli != ':') { /* doesn't take argument */
  272. if (!*place)
  273. ++optind;
  274. } else { /* takes (optional) argument */
  275. optarg = NULL;
  276. if (*place) /* no white space */
  277. optarg = place;
  278. /* XXX: disable test for :: if PC? (GNU doesn't) */
  279. else if (oli[1] != ':') { /* arg not optional */
  280. if (++optind >= nargc) { /* no arg */
  281. place = EMSG;
  282. if (PRINT_ERROR)
  283. warnx(recargchar, optchar);
  284. optopt = optchar;
  285. return BADARG;
  286. } else
  287. optarg = nargv[optind];
  288. }
  289. place = EMSG;
  290. ++optind;
  291. }
  292. /* dump back option letter */
  293. return optchar;
  294. }
  295. #ifdef REPLACE_GETOPT
  296. /*
  297.  * getopt --
  298.  * Parse argc/argv argument vector.
  299.  *
  300.  * [eventually this will replace the real getopt]
  301.  */
  302. int
  303. getopt(nargc, nargv, options)
  304. int nargc;
  305. char * const *nargv;
  306. const char *options;
  307. {
  308. int retval;
  309. _DIAGASSERT(nargv != NULL);
  310. _DIAGASSERT(options != NULL);
  311. if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
  312. ++optind;
  313. /*
  314.  * We found an option (--), so if we skipped non-options,
  315.  * we have to permute.
  316.  */
  317. if (nonopt_end != -1) {
  318. permute_args(nonopt_start, nonopt_end, optind,
  319.        nargv);
  320. optind -= nonopt_end - nonopt_start;
  321. }
  322. nonopt_start = nonopt_end = -1;
  323. retval = -1;
  324. }
  325. return retval;
  326. }
  327. #endif
  328. /*
  329.  * getopt_long --
  330.  * Parse argc/argv argument vector.
  331.  */
  332. int
  333. getopt_long(nargc, nargv, options, long_options, idx)
  334. int nargc;
  335. char * const *nargv;
  336. const char *options;
  337. const struct option *long_options;
  338. int *idx;
  339. {
  340. int retval;
  341. _DIAGASSERT(nargv != NULL);
  342. _DIAGASSERT(options != NULL);
  343. _DIAGASSERT(long_options != NULL);
  344. /* idx may be NULL */
  345. if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
  346. char *current_argv, *has_equal;
  347. size_t current_argv_len;
  348. int i, match;
  349. current_argv = place;
  350. match = -1;
  351. optind++;
  352. place = EMSG;
  353. if (*current_argv == '') { /* found "--" */
  354. /*
  355.  * We found an option (--), so if we skipped
  356.  * non-options, we have to permute.
  357.  */
  358. if (nonopt_end != -1) {
  359. permute_args(nonopt_start, nonopt_end,
  360.     optind, nargv);
  361. optind -= nonopt_end - nonopt_start;
  362. }
  363. nonopt_start = nonopt_end = -1;
  364. return -1;
  365. }
  366. if ((has_equal = strchr(current_argv, '=')) != NULL) {
  367. /* argument found (--option=arg) */
  368. current_argv_len = has_equal - current_argv;
  369. has_equal++;
  370. } else
  371. current_argv_len = strlen(current_argv);
  372. for (i = 0; long_options[i].name; i++) {
  373. /* find matching long option */
  374. if (strncmp(current_argv, long_options[i].name,
  375.     current_argv_len))
  376. continue;
  377. if (strlen(long_options[i].name) ==
  378.     (unsigned)current_argv_len) {
  379. /* exact match */
  380. match = i;
  381. break;
  382. }
  383. if (match == -1) /* partial match */
  384. match = i;
  385. else {
  386. /* ambiguous abbreviation */
  387. if (PRINT_ERROR)
  388. warnx(ambig, (int)current_argv_len,
  389.      current_argv);
  390. optopt = 0;
  391. return BADCH;
  392. }
  393. }
  394. if (match != -1) { /* option found */
  395. if (long_options[match].has_arg == no_argument
  396.     && has_equal) {
  397. if (PRINT_ERROR)
  398. warnx(noarg, (int)current_argv_len,
  399.      current_argv);
  400. /*
  401.  * XXX: GNU sets optopt to val regardless of
  402.  * flag
  403.  */
  404. if (long_options[match].flag == NULL)
  405. optopt = long_options[match].val;
  406. else
  407. optopt = 0;
  408. return BADARG;
  409. }
  410. if (long_options[match].has_arg == required_argument ||
  411.     long_options[match].has_arg == optional_argument) {
  412. if (has_equal)
  413. optarg = has_equal;
  414. else if (long_options[match].has_arg ==
  415.     required_argument) {
  416. /*
  417.  * optional argument doesn't use
  418.  * next nargv
  419.  */
  420. optarg = nargv[optind++];
  421. }
  422. }
  423. if ((long_options[match].has_arg == required_argument)
  424.     && (optarg == NULL)) {
  425. /*
  426.  * Missing argument; leading ':'
  427.  * indicates no error should be generated
  428.  */
  429. if (PRINT_ERROR)
  430. warnx(recargstring, current_argv);
  431. /*
  432.  * XXX: GNU sets optopt to val regardless
  433.  * of flag
  434.  */
  435. if (long_options[match].flag == NULL)
  436. optopt = long_options[match].val;
  437. else
  438. optopt = 0;
  439. --optind;
  440. return BADARG;
  441. }
  442. } else { /* unknown option */
  443. if (PRINT_ERROR)
  444. warnx(illoptstring, current_argv);
  445. optopt = 0;
  446. return BADCH;
  447. }
  448. if (long_options[match].flag) {
  449. *long_options[match].flag = long_options[match].val;
  450. retval = 0;
  451. } else
  452. retval = long_options[match].val;
  453. if (idx)
  454. *idx = match;
  455. }
  456. return retval;
  457. }