From 1ff2195f72283b7f02df25a61d249ab9594ef3f2 Mon Sep 17 00:00:00 2001 From: Evan Lucas Date: Mon, 1 Jun 2015 09:15:10 -0500 Subject: [PATCH] Revert "src: add getopt option parser" This reverts commit c0e7bf2d8ceb65ad3840bc4ebf3cbd9fef8e8c14. There are a few edge cases that can cause a crash and need to be properly handled. PR-URL: https://github.com/nodejs/io.js/pull/1862 Reviewed-By: Ben Noordhuis --- deps/getopt/getopt.gyp | 15 - deps/getopt/getopt.h | 100 ---- deps/getopt/getopt_long.c | 634 ---------------------- node.gyp | 4 - src/node.cc | 86 +-- src/node_options.cc | 305 ----------- src/node_options.h | 62 --- test/parallel/test-cli-debug.js | 20 - test/parallel/test-cli-help.js | 10 - test/parallel/test-cli-v8-options.js | 16 - test/parallel/test-cli-version.js | 11 - test/sequential/test-deprecation-flags.js | 11 - 12 files changed, 47 insertions(+), 1227 deletions(-) delete mode 100644 deps/getopt/getopt.gyp delete mode 100644 deps/getopt/getopt.h delete mode 100644 deps/getopt/getopt_long.c delete mode 100644 src/node_options.cc delete mode 100644 src/node_options.h delete mode 100644 test/parallel/test-cli-debug.js delete mode 100644 test/parallel/test-cli-help.js delete mode 100644 test/parallel/test-cli-v8-options.js delete mode 100644 test/parallel/test-cli-version.js diff --git a/deps/getopt/getopt.gyp b/deps/getopt/getopt.gyp deleted file mode 100644 index 1260a9306..000000000 --- a/deps/getopt/getopt.gyp +++ /dev/null @@ -1,15 +0,0 @@ -{ - 'targets': [ - { - 'target_name': 'getopt', - 'type': 'static_library', - 'sources': [ - 'getopt.h', - 'getopt_long.c' - ], - 'defines': [ - 'REPLACE_GETOPT' - ] - } - ] -} diff --git a/deps/getopt/getopt.h b/deps/getopt/getopt.h deleted file mode 100644 index 4c0a5ee7c..000000000 --- a/deps/getopt/getopt.h +++ /dev/null @@ -1,100 +0,0 @@ -/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */ -/* $FreeBSD$ */ - -/*- - * 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. - * - * 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. - */ - -#ifndef _GETOPT_H_ -#define _GETOPT_H_ - -#ifndef __BEGIN_DECLS -#ifdef __cplusplus -#define __BEGIN_DECLS extern "C" { -#define __END_DECLS } -#else -#define __BEGIN_DECLS -#define __END_DECLS -#endif /* __cplusplus */ -#endif /* __BEGIN_DECLS */ - -#ifdef WIN32 -#ifdef _MSC_VER -/* ignore MSVC++ warnings that are annoying and hard to remove: - 4702 unreachable code - (there is an unreachable assert(0) in case somehow it is reached) - */ -#pragma warning( disable : 4702 ) -#endif - -#endif /* WIN32 */ - -/* - * GNU-like getopt_long()/getopt_long_only() with 4.4BSD optreset extension. - * getopt() is declared here too for GNU programs. - */ -#define no_argument 0 -#define required_argument 1 -#define optional_argument 2 - -struct option { - /* name of long option */ - const char *name; - /* - * one of no_argument, required_argument, and optional_argument: - * whether option takes an argument - */ - int has_arg; - /* if not NULL, set *flag to val when option found */ - int *flag; - /* if flag not NULL, value to set *flag to; else return value */ - int val; - - /* add description for usage */ - const char *desc; -}; - -__BEGIN_DECLS -extern int getopt_long(int, char * const *, const char *, - const struct option *, int *); -extern int getopt_long_only(int, char * const *, const char *, - const struct option *, int *); -#ifndef _GETOPT_DECLARED -#define _GETOPT_DECLARED -int getopt(int, char * const [], const char *); - -extern char *optarg; /* getopt(3) external variables */ -extern int optind, opterr, optopt; -#endif -#ifndef _OPTRESET_DECLARED -#define _OPTRESET_DECLARED -extern int optreset; /* getopt(3) external variable */ -#endif -__END_DECLS - -#endif /* !_GETOPT_H_ */ diff --git a/deps/getopt/getopt_long.c b/deps/getopt/getopt_long.c deleted file mode 100644 index 1e8168055..000000000 --- a/deps/getopt/getopt_long.c +++ /dev/null @@ -1,634 +0,0 @@ -/* $OpenBSD: getopt_long.c,v 1.26 2013/06/08 22:47:56 millert Exp $ */ -/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ - -/* - * Copyright (c) 2002 Todd C. Miller - * - * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. - * - * Sponsored in part by the Defense Advanced Research Projects - * Agency (DARPA) and Air Force Research Laboratory, Air Force - * Materiel Command, USAF, under agreement number F39502-99-1-0512. - */ -/*- - * 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. - * - * 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. - */ - -#if 0 -#if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: getopt_long.c,v 1.16 2004/02/04 18:17:25 millert Exp $"; -#endif /* LIBC_SCCS and not lint */ -#endif - -#include -#include -#include "getopt.h" -#include -#include - -#ifdef WIN32 -#include -#if !defined(GETOPT_API) -#define GETOPT_API __declspec(dllimport) -#endif - -#ifdef _MSC_VER -/* ignore MSVC++ warnings that are annoying and hard to remove: - 4702 unreachable code - (there is an unreachable assert(0) in case somehow it is reached) - */ -#pragma warning( disable : 4702 ) -#endif - -GETOPT_API extern char opterrmsg[128]; -char opterrmsg[128]; /* last error message is stored here */ - -static void warnx(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - if (fmt != NULL) - _vsnprintf(opterrmsg, 128, fmt, ap); - else - opterrmsg[0]='\0'; - va_end(ap); - fprintf(stderr, opterrmsg); - fprintf(stderr, "\n"); -} - -#else /* WIN32 */ -#include -#endif - -#define GNU_COMPATIBLE /* Be more compatible, configure's use us! */ - -#if 0 /* we prefer to keep our getopt(3) */ -#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ -#endif - -#ifdef REPLACE_GETOPT -int opterr = 1; /* if error message should be printed */ -int optind = 1; /* index into parent argv vector */ -int optopt = '?'; /* character checked for validity */ -int optreset; /* reset getopt */ -char *optarg; /* argument associated with option */ -#endif - -#define PRINT_ERROR ((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 getopt_long_only */ - -/* return values */ -#define BADCH (int)'?' -#define BADARG ((*options == ':') ? (int)':' : (int)'?') -#define INORDER (int)1 - -#define EMSG "" - -#ifdef GNU_COMPATIBLE -#define NO_PREFIX (-1) -#define D_PREFIX 0 -#define DD_PREFIX 1 -#define W_PREFIX 2 -#endif - -static int getopt_internal(int, char * const *, const char *, - const struct option *, int *, int); -static int parse_long_options(char * const *, const char *, - const struct option *, int *, int, int); -static int gcd(int, int); -static void permute_args(int, int, int, char * const *); - -static char *place = EMSG; /* option letter processing */ - -/* XXX: set 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 illoptchar[] = "illegal option -- %c"; /* From P1003.2 */ -#ifdef GNU_COMPATIBLE -static int dash_prefix = NO_PREFIX; -static const char gnuoptchar[] = "invalid option -- %c"; - -static const char recargstring[] = "option `%s%s' requires an argument"; -static const char ambig[] = "option `%s%.*s' is ambiguous"; -static const char noarg[] = "option `%s%.*s' doesn't allow an argument"; -static const char illoptstring[] = "unrecognized option `%s%s'"; -#else -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 illoptstring[] = "unknown option -- %s"; -#endif - -/* - * Compute the greatest common divisor of a and b. - */ -static int -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 -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 = 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; - } - } -} - -/* - * 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 -parse_long_options(char * const *nargv, const char *options, - const struct option *long_options, int *idx, int short_too, int flags) -{ - char *current_argv, *has_equal; -#ifdef GNU_COMPATIBLE - char *current_dash; -#endif - size_t current_argv_len; - int i, match, exact_match, second_partial_match; - - current_argv = place; -#ifdef GNU_COMPATIBLE - switch (dash_prefix) { - case D_PREFIX: - current_dash = "-"; - break; - case DD_PREFIX: - current_dash = "--"; - break; - case W_PREFIX: - current_dash = "-W "; - break; - default: - current_dash = ""; - break; - } -#endif - match = -1; - exact_match = 0; - second_partial_match = 0; - - 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; - exact_match = 1; - 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) /* first partial match */ - match = i; - else if ((flags & FLAG_LONGONLY) || - long_options[i].has_arg != - long_options[match].has_arg || - long_options[i].flag != long_options[match].flag || - long_options[i].val != long_options[match].val) - second_partial_match = 1; - } - if (!exact_match && second_partial_match) { - /* ambiguous abbreviation */ - if (PRINT_ERROR) - warnx(ambig, -#ifdef GNU_COMPATIBLE - current_dash, -#endif - (int)current_argv_len, - current_argv); - optopt = 0; - return (BADCH); - } - if (match != -1) { /* option found */ - if (long_options[match].has_arg == no_argument - && has_equal) { - if (PRINT_ERROR) - warnx(noarg, -#ifdef GNU_COMPATIBLE - current_dash, -#endif - (int)current_argv_len, - current_argv); - /* - * XXX: GNU sets optopt to val regardless of flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; -#ifdef GNU_COMPATIBLE - return (BADCH); -#else - return (BADARG); -#endif - } - if (long_options[match].has_arg == required_argument || - long_options[match].has_arg == optional_argument) { - if (has_equal) - optarg = has_equal; - else if (long_options[match].has_arg == - required_argument) { - /* - * optional argument doesn't use next nargv - */ - optarg = nargv[optind++]; - } - } - if ((long_options[match].has_arg == required_argument) - && (optarg == NULL)) { - /* - * Missing argument; leading ':' indicates no error - * should be generated. - */ - if (PRINT_ERROR) - warnx(recargstring, -#ifdef GNU_COMPATIBLE - current_dash, -#endif - current_argv); - /* - * XXX: GNU sets optopt to val regardless of flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; - --optind; - return (BADARG); - } - } else { /* unknown option */ - if (short_too) { - --optind; - return (-1); - } - if (PRINT_ERROR) - warnx(illoptstring, -#ifdef GNU_COMPATIBLE - current_dash, -#endif - current_argv); - optopt = 0; - return (BADCH); - } - if (idx) - *idx = match; - if (long_options[match].flag) { - *long_options[match].flag = long_options[match].val; - return (0); - } else - return (long_options[match].val); -} - -/* - * getopt_internal -- - * Parse argc/argv argument vector. Called by user level routines. - */ -static int -getopt_internal(int nargc, char * const *nargv, const char *options, - const struct option *long_options, int *idx, int flags) -{ - char *oli; /* option letter list index */ - int optchar, short_too; - - if (options == NULL) - return (-1); - - /* - * XXX Some GNU programs (like cvs) set optind to 0 instead of - * XXX using optreset. Work around this braindamage. - */ - if (optind == 0) - optind = optreset = 1; - - if (*options == '-') - flags |= FLAG_ALLARGS; - if (*options == '+' || *options == '-') - options++; - - optarg = NULL; - if (optreset) - nonopt_start = nonopt_end = -1; -start: - if (optreset || !*place) { /* update scanning pointer */ - optreset = 0; - if (optind >= nargc) { /* end of argument vector */ - place = EMSG; - if (nonopt_end != -1) { - /* do permutation, if we have to */ - permute_args(nonopt_start, nonopt_end, - optind, nargv); - optind -= nonopt_end - nonopt_start; - } - else if (nonopt_start != -1) { - /* - * If we skipped non-options, set optind - * to the first of them. - */ - optind = nonopt_start; - } - nonopt_start = nonopt_end = -1; - return (-1); - } - if (*(place = nargv[optind]) != '-' || -#ifdef GNU_COMPATIBLE - place[1] == '\0') { -#else - (place[1] == '\0' && strchr(options, '-') == NULL)) { -#endif - place = EMSG; /* found non-option */ - if (flags & FLAG_ALLARGS) { - /* - * GNU extension: - * return non-option as argument to option 1 - */ - optarg = nargv[optind++]; - return (INORDER); - } - if (!(flags & FLAG_PERMUTE)) { - /* - * If no permutation wanted, stop parsing - * at first non-option. - */ - return (-1); - } - /* do permutation */ - if (nonopt_start == -1) - nonopt_start = optind; - else if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, nargv); - nonopt_start = optind - - (nonopt_end - nonopt_start); - nonopt_end = -1; - } - optind++; - /* process next argument */ - goto start; - } - if (nonopt_start != -1 && nonopt_end == -1) - nonopt_end = optind; - - /* - * If we have "-" do nothing, if "--" we are done. - */ - if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { - optind++; - place = EMSG; - /* - * We found an option (--), so if we skipped - * non-options, we have to permute. - */ - if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, nargv); - optind -= nonopt_end - nonopt_start; - } - nonopt_start = nonopt_end = -1; - return (-1); - } - } - - /* - * Check long options if: - * 1) we were passed some - * 2) the arg is not just "-" - * 3) either the arg starts with -- we are getopt_long_only() - */ - if (long_options != NULL && place != nargv[optind] && - (*place == '-' || (flags & FLAG_LONGONLY))) { - short_too = 0; -#ifdef GNU_COMPATIBLE - dash_prefix = D_PREFIX; -#endif - if (*place == '-') { - place++; /* --foo long option */ -#ifdef GNU_COMPATIBLE - dash_prefix = DD_PREFIX; -#endif - } else if (*place != ':' && strchr(options, *place) != NULL) - short_too = 1; /* could be short option too */ - - optchar = parse_long_options(nargv, options, long_options, - idx, short_too, flags); - if (optchar != -1) { - place = EMSG; - return (optchar); - } - } - - if ((optchar = (int)*place++) == (int)':' || - (optchar == (int)'-' && *place != '\0') || - (oli = strchr(options, optchar)) == NULL) { - /* - * If the user specified "-" and '-' isn't listed in - * options, return -1 (non-option) as per POSIX. - * Otherwise, it is an unknown option character (or ':'). - */ - if (optchar == (int)'-' && *place == '\0') - return (-1); - if (!*place) - ++optind; -#ifdef GNU_COMPATIBLE - if (PRINT_ERROR) - warnx(gnuoptchar, optchar); -#else - if (PRINT_ERROR) - warnx(illoptchar, optchar); -#endif - optopt = optchar; - return (BADCH); - } - if (long_options != NULL && optchar == 'W' && oli[1] == ';') { - /* -W long-option */ - if (*place) /* no space */ - /* NOTHING */; - else if (++optind >= nargc) { /* no arg */ - place = EMSG; - if (PRINT_ERROR) - warnx(recargchar, optchar); - optopt = optchar; - return (BADARG); - } else /* white space */ - place = nargv[optind]; -#ifdef GNU_COMPATIBLE - dash_prefix = W_PREFIX; -#endif - optchar = parse_long_options(nargv, options, long_options, - idx, 0, flags); - place = EMSG; - return (optchar); - } - if (*++oli != ':') { /* doesn't take argument */ - if (!*place) - ++optind; - } else { /* takes (optional) argument */ - optarg = NULL; - if (*place) /* no white space */ - optarg = place; - else if (oli[1] != ':') { /* arg not optional */ - if (++optind >= nargc) { /* no arg */ - place = EMSG; - if (PRINT_ERROR) - warnx(recargchar, optchar); - optopt = optchar; - return (BADARG); - } else - optarg = nargv[optind]; - } - place = EMSG; - ++optind; - } - /* dump back option letter */ - return (optchar); -} - -#ifdef REPLACE_GETOPT -/* - * getopt -- - * Parse argc/argv argument vector. - * - * [eventually this will replace the BSD getopt] - */ -int -getopt(int nargc, char * const *nargv, const char *options) -{ - - /* - * We don't pass FLAG_PERMUTE to getopt_internal() since - * the BSD getopt(3) (unlike GNU) has never done this. - * - * Furthermore, since many privileged programs call getopt() - * before dropping privileges it makes sense to keep things - * as simple (and bug-free) as possible. - */ - return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); -} -#endif /* REPLACE_GETOPT */ - -/* - * getopt_long -- - * Parse argc/argv argument vector. - */ -int -getopt_long(int nargc, char * const *nargv, const char *options, - const struct option *long_options, int *idx) -{ - - return (getopt_internal(nargc, nargv, options, long_options, idx, - FLAG_PERMUTE)); -} - -/* - * getopt_long_only -- - * Parse argc/argv argument vector. - */ -int -getopt_long_only(int nargc, char * const *nargv, const char *options, - const struct option *long_options, int *idx) -{ - - return (getopt_internal(nargc, nargv, options, long_options, idx, - FLAG_PERMUTE|FLAG_LONGONLY)); -} diff --git a/node.gyp b/node.gyp index 938bf7872..9509b800d 100644 --- a/node.gyp +++ b/node.gyp @@ -86,7 +86,6 @@ 'dependencies': [ 'node_js2c#host', 'deps/cares/cares.gyp:cares', - 'deps/getopt/getopt.gyp:getopt', 'deps/v8/tools/gyp/v8.gyp:v8', 'deps/v8/tools/gyp/v8.gyp:v8_libplatform' ], @@ -95,7 +94,6 @@ 'src', 'tools/msvs/genfiles', 'deps/uv/src/ares', - 'deps/getopt', '<(SHARED_INTERMEDIATE_DIR)', # for node_natives.h 'deps/v8' # include/v8_platform.h ], @@ -116,7 +114,6 @@ 'src/node_http_parser.cc', 'src/node_javascript.cc', 'src/node_main.cc', - 'src/node_options.cc', 'src/node_os.cc', 'src/node_v8.cc', 'src/node_stat_watcher.cc', @@ -153,7 +150,6 @@ 'src/node_http_parser.h', 'src/node_internals.h', 'src/node_javascript.h', - 'src/node_options.h', 'src/node_root_certs.h', 'src/node_version.h', 'src/node_watchdog.h', diff --git a/src/node.cc b/src/node.cc index 46b02913a..6b24daa36 100644 --- a/src/node.cc +++ b/src/node.cc @@ -4,7 +4,6 @@ #include "node_file.h" #include "node_http_parser.h" #include "node_javascript.h" -#include "node_options.h" #include "node_version.h" #if defined HAVE_PERFCTR @@ -112,6 +111,18 @@ using v8::V8; using v8::Value; using v8::kExternalUint32Array; +static bool print_eval = false; +static bool force_repl = false; +static bool trace_deprecation = false; +static bool throw_deprecation = false; +static bool abort_on_uncaught_exception = false; +static bool trace_sync_io = false; +static const char* eval_string = nullptr; +static unsigned int preload_module_count = 0; +static const char** preload_modules = nullptr; +static bool use_debug_agent = false; +static bool debug_wait_connect = false; +static int debug_port = 5858; static bool v8_is_profiling = false; static bool node_is_initialized = false; static node_module* modpending; @@ -119,8 +130,10 @@ static node_module* modlist_builtin; static node_module* modlist_linked; static node_module* modlist_addon; -// cli options -NodeOptions node_options; +#if defined(NODE_HAVE_I18N_SUPPORT) +// Path to ICU data (for i18n / Intl) +static const char* icu_data_dir = nullptr; +#endif // used by C++ modules as well bool no_deprecation = false; @@ -1253,13 +1266,13 @@ enum encoding ParseEncoding(const char* encoding, } else if (strcasecmp(encoding, "hex") == 0) { return HEX; } else if (strcasecmp(encoding, "raw") == 0) { - if (!node_options.no_deprecation) { + if (!no_deprecation) { fprintf(stderr, "'raw' (array of integers) has been removed. " "Use 'binary'.\n"); } return BINARY; } else if (strcasecmp(encoding, "raws") == 0) { - if (!node_options.no_deprecation) { + if (!no_deprecation) { fprintf(stderr, "'raws' encoding has been renamed to 'binary'. " "Please update your code.\n"); } @@ -2535,14 +2548,14 @@ static Handle GetFeatures(Environment* env) { static void DebugPortGetter(Local property, const PropertyCallbackInfo& info) { - info.GetReturnValue().Set(node_options.debug_port); + info.GetReturnValue().Set(debug_port); } static void DebugPortSetter(Local property, Local value, const PropertyCallbackInfo& info) { - node_options.debug_port = value->Int32Value(); + debug_port = value->Int32Value(); } @@ -2776,58 +2789,56 @@ void SetupProcessObject(Environment* env, env->as_external()); // -e, --eval - if (node_options.eval_string) { + if (eval_string) { READONLY_PROPERTY(process, "_eval", - String::NewFromUtf8(env->isolate(), - node_options.eval_string)); + String::NewFromUtf8(env->isolate(), eval_string)); } // -p, --print - if (node_options.print_eval) { + if (print_eval) { READONLY_PROPERTY(process, "_print_eval", True(env->isolate())); } // -i, --interactive - if (node_options.force_repl) { + if (force_repl) { READONLY_PROPERTY(process, "_forceRepl", True(env->isolate())); } - if (node_options.preload_module_count) { - CHECK(node_options.preload_modules); + if (preload_module_count) { + CHECK(preload_modules); Local array = Array::New(env->isolate()); - for (unsigned int i = 0; i < node_options.preload_module_count; ++i) { - Local module = String::NewFromUtf8( - env->isolate(), - node_options.preload_modules[i]); + for (unsigned int i = 0; i < preload_module_count; ++i) { + Local module = String::NewFromUtf8(env->isolate(), + preload_modules[i]); array->Set(i, module); } READONLY_PROPERTY(process, "_preload_modules", array); - delete[] node_options.preload_modules; - node_options.preload_modules = nullptr; - node_options.preload_module_count = 0; + delete[] preload_modules; + preload_modules = nullptr; + preload_module_count = 0; } // --no-deprecation - if (node_options.no_deprecation) { + if (no_deprecation) { READONLY_PROPERTY(process, "noDeprecation", True(env->isolate())); } // --throw-deprecation - if (node_options.throw_deprecation) { + if (throw_deprecation) { READONLY_PROPERTY(process, "throwDeprecation", True(env->isolate())); } // --trace-deprecation - if (node_options.trace_deprecation) { + if (trace_deprecation) { READONLY_PROPERTY(process, "traceDeprecation", True(env->isolate())); } // --trace-sync-io - if (node_options.trace_sync_io) { + if (trace_sync_io) { READONLY_PROPERTY(process, "traceSyncIO", True(env->isolate())); // Don't env->set_trace_sync_io(true) because it will be enabled // after LoadEnvironment() has run. @@ -3238,6 +3249,7 @@ static void ParseArgs(int* argc, delete[] local_preload_modules; } + // Called from V8 Debug Agent TCP thread. static void DispatchMessagesDebugAgentCallback(Environment* env) { // TODO(indutny): move async handle to environment @@ -3250,12 +3262,9 @@ static void StartDebug(Environment* env, bool wait) { env->debugger_agent()->set_dispatch_handler( DispatchMessagesDebugAgentCallback); - debugger_running = env->debugger_agent()->Start(node_options.debug_port, - wait); + debugger_running = env->debugger_agent()->Start(debug_port, wait); if (debugger_running == false) { - fprintf(stderr, - "Starting debugger on port %d failed\n", - node_options.debug_port); + fprintf(stderr, "Starting debugger on port %d failed\n", debug_port); fflush(stderr); return; } @@ -3625,8 +3634,8 @@ void Init(int* argc, // Parse a few arguments which are specific to Node. int v8_argc; const char** v8_argv; - node_options.ParseArgs(argc, argv, exec_argc, exec_argv, &v8_argc, &v8_argv); - no_deprecation = node_options.no_deprecation; + ParseArgs(argc, argv, exec_argc, exec_argv, &v8_argc, &v8_argv); + // TODO(bnoordhuis) Intercept --prof arguments and start the CPU profiler // manually? That would give us a little more control over its runtime // behavior but it could also interfere with the user's intentions in ways @@ -3665,14 +3674,14 @@ void Init(int* argc, exit(9); } - if (node_options.debug_wait_connect) { + if (debug_wait_connect) { const char expose_debug_as[] = "--expose_debug_as=v8debug"; V8::SetFlagsFromString(expose_debug_as, sizeof(expose_debug_as) - 1); } V8::SetArrayBufferAllocator(&ArrayBufferAllocator::the_singleton); - if (!node_options.use_debug_agent) { + if (!use_debug_agent) { RegisterDebugSignalHandler(); } @@ -3885,15 +3894,14 @@ static void StartNodeInstance(void* arg) { Environment* env = CreateEnvironment(isolate, context, instance_data); Context::Scope context_scope(context); if (instance_data->is_main()) - env->set_using_abort_on_uncaught_exc( - node_options.abort_on_uncaught_exception); + env->set_using_abort_on_uncaught_exc(abort_on_uncaught_exception); // Start debug agent when argv has --debug if (instance_data->use_debug_agent()) - StartDebug(env, node_options.debug_wait_connect); + StartDebug(env, debug_wait_connect); LoadEnvironment(env); - env->set_trace_sync_io(node_options.trace_sync_io); + env->set_trace_sync_io(trace_sync_io); // Enable debugger if (instance_data->use_debug_agent()) @@ -3970,7 +3978,7 @@ int Start(int argc, char** argv) { const_cast(argv), exec_argc, exec_argv, - node_options.use_debug_agent); + use_debug_agent); StartNodeInstance(&instance_data); exit_code = instance_data.exit_code(); } diff --git a/src/node_options.cc b/src/node_options.cc deleted file mode 100644 index 276c5cd32..000000000 --- a/src/node_options.cc +++ /dev/null @@ -1,305 +0,0 @@ -#include "node_options.h" -#include "node_version.h" -#include "node_internals.h" -#include "getopt.h" -#include -#include -#include - -namespace node { - -enum { - OPT_NO_DEPRECATION = 1000, - OPT_THROW_DEPRECATION, - OPT_TRACE_DEPRECATION, - OPT_TRACE_SYNC_IO, - OPT_V8_OPTIONS, - OPT_ABORT_UNCAUGHT, - OPT_EXPOSE_INTERNALS, - OPT_DEBUG, - OPT_DEBUG_BRK, - OPT_DEBUG_PORT, -#if defined(NODE_HAVE_I18N_SUPPORT) - OPT_ICU_DATA_DIR -#endif -}; - -static struct option longopts[] = { - { "help", no_argument, nullptr, 'h', "show help and usage" }, - { "version", no_argument, nullptr, 'v', "print io.js version" }, - { "eval", optional_argument, nullptr, 'e', "evaluate script" }, - { "print", optional_argument, nullptr, 'p', - "evaluate script and print result" }, - { "interactive", no_argument, nullptr, 'i', - "always enter the REPL even if stdin " - "does not appear to be a terminal" }, - { "require", required_argument, nullptr, 'r', "module to preload" }, - { "no-deprecation", no_argument, nullptr, OPT_NO_DEPRECATION, - "silence deprecation warnings" }, - { "throw-deprecation", no_argument, nullptr, OPT_THROW_DEPRECATION, - "throw an exception anytime a deprecated function is used" }, - { "trace-deprecation", no_argument, nullptr, OPT_TRACE_DEPRECATION, - "show stack traces on deprecations" }, - { "trace-sync-io", no_argument, nullptr, OPT_TRACE_SYNC_IO, - "show stake trace when use of sync IO " - "is detected after the first tick" }, - { "v8-options", no_argument, nullptr, OPT_V8_OPTIONS, - "print v8 command line options" }, - { "v8_options", no_argument, nullptr, OPT_V8_OPTIONS, - "print v8 command line options" }, - { "abort-on-uncaught-exception", no_argument, nullptr, OPT_ABORT_UNCAUGHT, - "abort on uncaught exception" }, - { "abort_on_uncaught_exception", no_argument, nullptr, OPT_ABORT_UNCAUGHT, - "abort on uncaught exception" }, - { "expose-internals", no_argument, nullptr, OPT_EXPOSE_INTERNALS, - "expose internal modules" }, - { "expose_internals", no_argument, nullptr, OPT_EXPOSE_INTERNALS, - "expose internal modules" }, - { "debug", optional_argument, nullptr, OPT_DEBUG, "enable debug mode" }, - { "debug-brk", optional_argument, nullptr, OPT_DEBUG_BRK, - "break before starting" }, - { "debug-port", required_argument, nullptr, OPT_DEBUG_PORT, - "specify debug port (defaults to 5858)" }, -#if defined(NODE_HAVE_I18N_SUPPORT) - { "icu-data-dir", required_argument, nullptr, OPT_ICU_DATA_DIR }, -#endif - { nullptr, 0, nullptr, 0, "" } -}; - -void NodeOptions::PrintHelp() { - printf("Usage: iojs [options] [ -e script | script.js ] [arguments] \n" - " iojs debug script.js [arguments] \n" - "\n" - "Options:\n"); - for (size_t i = 0; i < ARRAY_SIZE(longopts); i++) { - if (longopts[i].name == nullptr) - continue; - if (longopts[i].val < 1000) { - printf("\t-%c, --%-30s %-50s\n", - longopts[i].val, - longopts[i].name, - longopts[i].desc); - } else { - printf("\t --%-30s %-50s\n", longopts[i].name, longopts[i].desc); - } - } - - printf("\n"); - - printf("Environment variables:\n" -#ifdef _WIN32 - "\t NODE_PATH ';'-separated list of directories\n" -#else - "\t NODE_PATH ':'-separated list of directories\n" -#endif - "\t prefixed to the module search path.\n" - "\t NODE_DISABLE_COLORS Set to 1 to disable colors in the REPL\n" -#if defined(NODE_HAVE_I18N_SUPPORT) - "\t NODE_ICU_DATA Data path for ICU (Intl object) data\n" -#if !defined(NODE_HAVE_SMALL_ICU) - "\t (will extend linked-in data)\n" -#endif -#endif - "\n" - "Documentation can be found at https://iojs.org/\n"); -} - -void NodeOptions::ParseArgs(int* argc, - const char** argv, - int* exec_argc, - const char*** exec_argv, - int* v8_argc, - const char*** v8_argv) { - const unsigned int nargs = static_cast(*argc); - const char** new_exec_argv = new const char*[nargs]; - const char** new_v8_argv = new const char*[nargs]; - const char** new_argv = new const char*[nargs]; - const char** local_preload_modules = new const char*[nargs]; - - // we are mutating the strings vector but not the strings themselves - char** largv = const_cast(argv); - for (unsigned int i = 0; i < nargs; ++i) { - new_exec_argv[i] = nullptr; - new_v8_argv[i] = nullptr; - new_argv[i] = nullptr; - local_preload_modules[i] = nullptr; - } - - const char* port = nullptr; - - // exec_argv starts with the first option, the other two start with argv[0]. - unsigned int new_exec_argc = 0; - unsigned int new_v8_argc = 1; - unsigned int new_argc = 1; - new_v8_argv[0] = argv[0]; - new_argv[0] = argv[0]; - int rc = 0; - unsigned int index = 1; - bool is_eval = false; - bool is_print = false; - const char optstring[] = ":hve:p::ir:d::b::x:"; - while ((rc = getopt_long(*argc, largv, optstring, longopts, NULL)) != -1 && - argv[index][0] == '-') { - unsigned int args_consumed = 1; - const char* const arg = argv[index]; - switch (rc) { - case 'h': - PrintHelp(); - exit(0); - break; - case 'v': - printf("%s\n", NODE_VERSION); - exit(0); - break; - case 'e': - case 'p': - { - if (!is_eval) - is_eval = (rc == 'e'); - - if (!is_print) - is_print = (rc == 'p'); - const char* name = is_eval ? "eval" : "print"; - print_eval = print_eval || is_print; - if (is_eval == true) { - eval_string = argv[index + 1]; - args_consumed += 1; - if (eval_string == nullptr) { - fprintf(stderr, "%s: %s requires an argument\n", argv[0], name); - exit(9); - } - } else if ((index + 1 < nargs) && - argv[index + 1] != nullptr && - argv[index + 1][0] != '-') { - eval_string = argv[index + 1]; - args_consumed += 1; - if (strncmp(eval_string, "\\-", 2) == 0) { - // Starts with "\\-": escaped expression, drop the backslash. - eval_string += 1; - } - } - break; - } - case 'i': - force_repl = true; - break; - case 'r': - { - const char* module = argv[index + 1]; - args_consumed += 1; - if (module == nullptr) { - fprintf(stderr, "%s: %s requires an argument\n", argv[0], arg); - exit(9); - } - local_preload_modules[preload_module_count++] = module; - break; - } - case OPT_NO_DEPRECATION: - no_deprecation = true; - break; - case OPT_THROW_DEPRECATION: - throw_deprecation = true; - break; - case OPT_TRACE_DEPRECATION: - trace_deprecation = true; - break; - case OPT_TRACE_SYNC_IO: - trace_sync_io = true; - break; - case OPT_V8_OPTIONS: - new_v8_argv[new_v8_argc] = "--help"; - new_v8_argc += 1; - break; - case OPT_ABORT_UNCAUGHT: - abort_on_uncaught_exception = true; - break; - case OPT_EXPOSE_INTERNALS: - // pass through - break; - case OPT_DEBUG: - { - use_debug_agent = true; - if (optarg != nullptr) { - port = const_cast(optarg); - } - break; - } - case OPT_DEBUG_BRK: - { - use_debug_agent = true; - debug_wait_connect = true; - if (optarg != nullptr) { - port = const_cast(optarg); - } - break; - } - case OPT_DEBUG_PORT: - { - port = optarg; - break; - } -#if defined(NODE_HAVE_I18N_SUPPORT) - case OPT_ICU_DATA_DIR: - { - if (optarg != nullptr) { - icu_data_dir = const_cast(optarg); - } - break; - } -#endif - case '?': - { - if (arg[0] == '-') { - // V8 option. Pass through as-is. - new_v8_argv[new_v8_argc] = arg; - new_v8_argc += 1; - } - break; - } - } - - memcpy(new_exec_argv + new_exec_argc, - largv + index, - args_consumed * sizeof(*largv)); - - new_exec_argc += args_consumed; - index += args_consumed; - } - - if (port != nullptr) { - debug_port = atoi(port); - if (debug_port < 1024 || debug_port > 65535) { - fprintf(stderr, "Debug port must be in range 1024 to 65535.\n"); - PrintHelp(); - exit(12); - } - } - - // Copy remaining arguments. - const unsigned int args_left = nargs - index; - memcpy(new_argv + new_argc, argv + index, args_left * sizeof(*argv)); - new_argc += args_left; - - *exec_argc = new_exec_argc; - *exec_argv = new_exec_argv; - *v8_argc = new_v8_argc; - *v8_argv = new_v8_argv; - - // Copy new_argv over argv and update argc. - memcpy(argv, new_argv, new_argc * sizeof(*argv)); - delete[] new_argv; - *argc = static_cast(new_argc); - - // Copy the preload_modules from the local array to an appropriately sized - // global array. - if (preload_module_count > 0) { - CHECK(!preload_modules); - preload_modules = new const char*[preload_module_count]; - memcpy(preload_modules, - local_preload_modules, - preload_module_count * sizeof(*preload_modules)); - } - delete[] local_preload_modules; -} - -} // namespace node diff --git a/src/node_options.h b/src/node_options.h deleted file mode 100644 index 1d356a1a1..000000000 --- a/src/node_options.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef SRC_NODE_OPTIONS_H_ -#define SRC_NODE_OPTIONS_H_ - -#include "node_version.h" -#include "util.h" -#include "getopt.h" -#include -#include -#include - -namespace node { - -class NodeOptions { - public: - bool print_eval = false; - bool force_repl = false; - bool trace_deprecation = false; - bool throw_deprecation = false; - bool abort_on_uncaught_exception = false; - bool trace_sync_io = false; - const char* eval_string = nullptr; - unsigned int preload_module_count = 0; - const char** preload_modules = nullptr; - bool use_debug_agent = false; - bool debug_wait_connect = false; - int debug_port = 5858; - bool no_deprecation = false; -#if defined(NODE_HAVE_I18N_SUPPORT) - // Path to ICU data (for i18n / Intl) - const char* icu_data_dir = nullptr; -#endif - - NodeOptions() = default; - - // Print help to stdout - void PrintHelp(); - - // Parse command line arguments. - // - // argv is modified in place. exec_argv and v8_argv are out arguments that - // ParseArgs() allocates memory for and stores a pointer to the output - // vector in. The caller should free them with delete[]. - // - // On exit: - // - // * argv contains the arguments with node and V8 options filtered out. - // * exec_argv contains both node and V8 options and nothing else. - // * v8_argv contains argv[0] plus any V8 options - void ParseArgs(int* argc, - const char** argv, - int* exec_argc, - const char*** exec_argv, - int* v8_argc, - const char*** v8_argv); - - private: - DISALLOW_COPY_AND_ASSIGN(NodeOptions); -}; - -} // namespace node - -#endif // SRC_NODE_OPTIONS_H_ diff --git a/test/parallel/test-cli-debug.js b/test/parallel/test-cli-debug.js deleted file mode 100644 index 76e24fafb..000000000 --- a/test/parallel/test-cli-debug.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; -const common = require('../common'); -const assert = require('assert'); -const execFile = require('child_process').execFile; -const EOL = require('os').EOL; -var depmod = require.resolve('../fixtures/printA.js'); -var node = process.execPath; - -var debug = ['--debug', depmod]; -var debugPort = ['--debug=5859', depmod]; - -function handle(port) { - return function(er, stdout, stderr) { - assert.equal(er, null); - assert.equal(stderr, `Debugger listening on port ${port}${EOL}`); - }; -} - -execFile(node, debug, handle(5858)); -execFile(node, debugPort, handle(5859)); diff --git a/test/parallel/test-cli-help.js b/test/parallel/test-cli-help.js deleted file mode 100644 index 1f5e489b1..000000000 --- a/test/parallel/test-cli-help.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; -const assert = require('assert'); -const execFile = require('child_process').execFile; - -// test --help -execFile(process.execPath, ['--help'], function(err, stdout, stderr) { - assert.equal(err, null); - assert.equal(stderr, ''); - assert.equal(/Usage/.test(stdout), true); -}); diff --git a/test/parallel/test-cli-v8-options.js b/test/parallel/test-cli-v8-options.js deleted file mode 100644 index 2b2808a23..000000000 --- a/test/parallel/test-cli-v8-options.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; -const common = require('../common'); -const assert = require('assert'); -const execFile = require('child_process').execFile; - -// test --v8-options and --v8_options -(function runTest(flags) { - var flag = flags.pop(); - execFile(process.execPath, [flag], function(err, stdout, stderr) { - assert.equal(err, null); - assert.equal(stderr, ''); - assert.equal(stdout.indexOf('Usage') > -1, true); - if (flags.length > 0) - setImmediate(runTest, flags); - }); -})(['--v8-options', '--v8_options']); diff --git a/test/parallel/test-cli-version.js b/test/parallel/test-cli-version.js deleted file mode 100644 index f0ecdd229..000000000 --- a/test/parallel/test-cli-version.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; -const assert = require('assert'); -const execFile = require('child_process').execFile; - -// test --version -execFile(process.execPath, ['--version'], function(err, stdout, stderr) { - assert.equal(err, null); - assert.equal(stderr, ''); - // just in case the version ever has anything appended to it (nightlies?) - assert.equal(/v([\d]+).([\d]+).([\d]+)(.*)/.test(stdout), true); -}); diff --git a/test/sequential/test-deprecation-flags.js b/test/sequential/test-deprecation-flags.js index 7a5595b06..e8565a336 100644 --- a/test/sequential/test-deprecation-flags.js +++ b/test/sequential/test-deprecation-flags.js @@ -8,7 +8,6 @@ var node = process.execPath; var normal = [depmod]; var noDep = ['--no-deprecation', depmod]; var traceDep = ['--trace-deprecation', depmod]; -var throwDep = ['--throw-deprecation', depmod]; execFile(node, normal, function(er, stdout, stderr) { console.error('normal: show deprecation warning'); @@ -37,13 +36,3 @@ execFile(node, traceDep, function(er, stdout, stderr) { assert.equal(stack.pop(), '\'This is deprecated\''); console.log('trace ok'); }); - -execFile(node, throwDep, function(er, stdout, stderr) { - console.error('--throw-deprecation: show stack'); - assert.equal(/Error: Command failed/.test(er), true); - assert.equal(stdout, ''); - var stack = stderr.trim().split('\n'); - assert.equal(/util.js:([\d]+)/.test(stack[0]), true); - assert.equal(/throw new Error\(msg\)/.test(stack[1]), true); - console.log('throw ok'); -});