📄 bsd-getopt_long.c
字号:
/* $OpenBSD: getopt_long.c,v 1.13 2003/06/03 01:52:40 millert Exp $ *//* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ *//* * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *//*- * Copyright (c) 2000 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Dieter Baron and Thomas Klausner. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the NetBSD * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */#define IN_GETOPT_LONG_C 1#include <config.h>#include "ftpd.h"#ifndef HAVE_GETOPT_LONG# include "bsd-getopt_long.h"# ifdef WITH_DMALLOC# include <dmalloc.h># endifint pure_opterr = 1; /* if error message should be printed */int pure_optind = 1; /* index into parent argv vector */int pure_optopt = '?'; /* character checked for validity */int pure_optreset; /* reset getopt */const char *pure_optarg; /* argument associated with option */# define PRINT_ERROR ((pure_opterr) && (*options != ':'))# define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */# define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */# define FLAG_LONGONLY 0x04 /* operate as pure_pure_getopt_long_only *//* return values */# define BADCH (int)'?'# define BADARG ((*options == ':') ? (int)':' : (int)'?')# define INORDER (int)1# define EMSG ""static int pure_getopt_internal(int, char * const *, const char *, const struct pure_option *, int *, int);static int pure_parse_long_options(char * const *, const char *, const struct pure_option *, int *, int);static int pure_gcd(int, int);static void pure_permute_args(int, int, int, char * const *);static const char *pure_place = EMSG; /* option letter processing *//* XXX: set pure_optreset to 1 rather than these two */static int nonopt_start = -1; /* first non option argument (for permute) */static int nonopt_end = -1; /* first option after non options (for permute) *//* Error messages */static const char *recargchar = "option requires an argument -- %c";static const char *recargstring = "option requires an argument -- %s";static const char *ambig = "ambiguous option -- %.*s";static const char *noarg = "option doesn't take an argument -- %.*s";static const char *illoptchar = "unknown option -- %c";static const char *illoptstring = "unknown option -- %s";/* * Compute the greatest common divisor of a and b. */static int pure_gcd(int a, int b){ int c; c = a % b; while (c != 0) { a = b; b = c; c = a % b; } return b;}/* * Exchange the block from nonopt_start to nonopt_end with the block * from nonopt_end to opt_end (keeping the same order of arguments * in each block). */static void pure_permute_args(int panonopt_start, int panonopt_end, int opt_end, char * const *nargv){ int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; char *swap; /* * compute lengths of blocks and number and size of cycles */ nnonopts = panonopt_end - panonopt_start; nopts = opt_end - panonopt_end; ncycle = pure_gcd(nnonopts, nopts); cyclelen = (opt_end - panonopt_start) / ncycle; for (i = 0; i < ncycle; i++) { cstart = panonopt_end+i; pos = cstart; for (j = 0; j < cyclelen; j++) { if (pos >= panonopt_end) pos -= nnonopts; else pos += nopts; swap = nargv[pos]; /* LINTED const cast */ ((char **) nargv)[pos] = nargv[cstart]; /* LINTED const cast */ ((char **)nargv)[cstart] = swap; } }}/* * pure_parse_long_options -- * Parse long options in argc/argv argument vector. * Returns -1 if short_too is set and the option does not match long_options. */static int pure_parse_long_options(char * const *nargv, const char *options, const struct pure_option *long_options, int *idx, int short_too){ const char *current_argv, *has_equal; size_t current_argv_len; int i, match; current_argv = pure_place; match = -1; pure_optind++; if ((has_equal = strchr(current_argv, '=')) != NULL) { /* argument found (--option=arg) */ current_argv_len = has_equal - current_argv; has_equal++; } else current_argv_len = strlen(current_argv); for (i = 0; long_options[i].name; i++) { /* find matching long option */ if (strncmp(current_argv, long_options[i].name, current_argv_len)) continue; if (strlen(long_options[i].name) == current_argv_len) { /* exact match */ match = i; break; } /* * If this is a known short option, don't allow * a partial match of a single character. */ if (short_too && current_argv_len == 1) continue; if (match == -1) /* partial match */ match = i; else { /* ambiguous abbreviation */ if (PRINT_ERROR) fprintf(stderr, ambig, (int)current_argv_len, current_argv); pure_optopt = 0; return BADCH; } } if (match != -1) { /* option found */ if (long_options[match].has_arg == no_argument && has_equal) { if (PRINT_ERROR) fprintf(stderr, noarg, (int)current_argv_len, current_argv); /* * XXX: GNU sets pure_optopt to val regardless of flag */ if (long_options[match].flag == NULL) pure_optopt = long_options[match].val; else pure_optopt = 0; return BADARG; } if (long_options[match].has_arg == required_argument || long_options[match].has_arg == optional_argument) { if (has_equal) pure_optarg = has_equal; else if (long_options[match].has_arg == required_argument) { /* * optional argument doesn't use next nargv */ pure_optarg = nargv[pure_optind++]; } } if ((long_options[match].has_arg == required_argument) && (pure_optarg == NULL)) { /* * Missing argument; leading ':' indicates no error * should be generated. */ if (PRINT_ERROR) fprintf(stderr, recargstring, current_argv); /* * XXX: GNU sets pure_optopt to val regardless of flag */ if (long_options[match].flag == NULL) pure_optopt = long_options[match].val; else pure_optopt = 0; --pure_optind; return BADARG; } } else { /* unknown option */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -