Advertisement
Guest User

Untitled

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