aboutsummaryrefslogtreecommitdiffstats
path: root/main.c
diff options
context:
space:
mode:
authorAndrew J. Schorr <aschorr@telemetry-investments.com>2014-12-14 12:53:35 -0500
committerAndrew J. Schorr <aschorr@telemetry-investments.com>2014-12-14 12:53:35 -0500
commit1fc7a1fe6aba3c1ba98c44f8df1926c10ff79c87 (patch)
treee6eff5ba1ffaa2250c59ce02464d783b08508f4c /main.c
parentf9c7ec30542ef2550761f49cd25503e0775ef271 (diff)
parent0d52289482d468c8566976d77c0c6a6a4e602add (diff)
downloadegawk-1fc7a1fe6aba3c1ba98c44f8df1926c10ff79c87.tar.gz
egawk-1fc7a1fe6aba3c1ba98c44f8df1926c10ff79c87.tar.bz2
egawk-1fc7a1fe6aba3c1ba98c44f8df1926c10ff79c87.zip
Merge branch 'master' into select
Diffstat (limited to 'main.c')
-rw-r--r--main.c588
1 files changed, 307 insertions, 281 deletions
diff --git a/main.c b/main.c
index 44021e50..93f94998 100644
--- a/main.c
+++ b/main.c
@@ -142,17 +142,20 @@ static bool disallow_var_assigns = false; /* true for --exec */
static void add_preassign(enum assign_type type, char *val);
+static void parse_args(int argc, char **argv);
+static void set_locale_stuff(void);
+static bool stopped_early = false;
+
int do_flags = false;
bool do_optimize = false; /* apply default optimizations */
static int do_nostalgia = false; /* provide a blast from the past */
static int do_binary = false; /* hands off my data! */
static int do_version = false; /* print version info */
+static const char *locale = ""; /* default value to setlocale */
int use_lc_numeric = false; /* obey locale for decimal point */
-#if MBS_SUPPORT
int gawk_mb_cur_max; /* MB_CUR_MAX value, see comment in main() */
-#endif
FILE *output_fp; /* default gawk output, can be redirected in the debugger */
bool output_is_tty = false; /* control flushing of output */
@@ -186,6 +189,9 @@ static const struct option optab[] = {
{ "lint", optional_argument, NULL, 'L' },
{ "lint-old", no_argument, NULL, 't' },
{ "load", required_argument, NULL, 'l' },
+#if defined(LOCALEDEBUG)
+ { "locale", required_argument, NULL, 'Z' },
+#endif
{ "non-decimal-data", no_argument, NULL, 'n' },
{ "nostalgia", no_argument, & do_nostalgia, 1 },
{ "optimize", no_argument, NULL, 'O' },
@@ -209,15 +215,7 @@ static const struct option optab[] = {
int
main(int argc, char **argv)
{
- /*
- * The + on the front tells GNU getopt not to rearrange argv.
- */
- const char *optlist = "+F:f:v:W;bcCd::D::e:E:ghi:l:L:nNo::Op::MPrStVY";
- bool stopped_early = false;
- int old_optind;
int i;
- int c;
- char *scan, *src;
char *extra_stack;
int have_srcfile = 0;
SRCFILE *s;
@@ -233,49 +231,11 @@ main(int argc, char **argv)
#endif /* HAVE_MTRACE */
#endif /* HAVE_MCHECK_H */
-#if defined(LC_CTYPE)
- setlocale(LC_CTYPE, "");
-#endif
-#if defined(LC_COLLATE)
- setlocale(LC_COLLATE, "");
-#endif
-#if defined(LC_MESSAGES)
- setlocale(LC_MESSAGES, "");
-#endif
-#if defined(LC_NUMERIC) && defined(HAVE_LOCALE_H)
- /*
- * Force the issue here. According to POSIX 2001, decimal
- * point is used for parsing source code and for command-line
- * assignments and the locale value for processing input,
- * number to string conversion, and printing output.
- *
- * 10/2005 --- see below also; we now only use the locale's
- * decimal point if do_posix in effect.
- *
- * 9/2007:
- * This is a mess. We need to get the locale's numeric info for
- * the thousands separator for the %'d flag.
- */
- setlocale(LC_NUMERIC, "");
- init_locale(& loc);
- setlocale(LC_NUMERIC, "C");
-#endif
-#if defined(LC_TIME)
- setlocale(LC_TIME, "");
-#endif
-
-#if MBS_SUPPORT
- /*
- * In glibc, MB_CUR_MAX is actually a function. This value is
- * tested *a lot* in many speed-critical places in gawk. Caching
- * this value once makes a speed difference.
- */
- gawk_mb_cur_max = MB_CUR_MAX;
- /* Without MBS_SUPPORT, gawk_mb_cur_max is 1. */
+ myname = gawk_name(argv[0]);
+ os_arg_fixup(&argc, &argv); /* emulate redirection, expand wildcards */
- /* init the cache for checking bytes if they're characters */
- init_btowc_cache();
-#endif
+ if (argc < 2)
+ usage(EXIT_FAILURE, stderr);
(void) bindtextdomain(PACKAGE, LOCALEDIR);
(void) textdomain(PACKAGE);
@@ -307,12 +267,6 @@ main(int argc, char **argv)
(void) stackoverflow_install_handler(catchstackoverflow, extra_stack, STACK_SIZE);
#undef STACK_SIZE
- myname = gawk_name(argv[0]);
- os_arg_fixup(&argc, &argv); /* emulate redirection, expand wildcards */
-
- if (argc < 2)
- usage(EXIT_FAILURE, stderr);
-
/* initialize the null string */
Nnull_string = make_string("", 0);
@@ -327,230 +281,22 @@ main(int argc, char **argv)
output_fp = stdout;
- /* we do error messages ourselves on invalid options */
- opterr = false;
-
- /* copy argv before getopt gets to it; used to restart the debugger */
- save_argv(argc, argv);
-
/* initialize global (main) execution context */
push_context(new_context());
- /* option processing. ready, set, go! */
- for (optopt = 0, old_optind = 1;
- (c = getopt_long(argc, argv, optlist, optab, NULL)) != EOF;
- optopt = 0, old_optind = optind) {
- if (do_posix)
- opterr = true;
-
- switch (c) {
- case 'F':
- add_preassign(PRE_ASSIGN_FS, optarg);
- break;
-
- case 'E':
- disallow_var_assigns = true;
- /* fall through */
- case 'f':
- /*
- * Allow multiple -f options.
- * This makes function libraries real easy.
- * Most of the magic is in the scanner.
- *
- * The following is to allow for whitespace at the end
- * of a #! /bin/gawk line in an executable file
- */
- scan = optarg;
- if (argv[optind-1] != optarg)
- while (isspace((unsigned char) *scan))
- scan++;
- src = (*scan == '\0' ? argv[optind++] : optarg);
- (void) add_srcfile((src && src[0] == '-' && src[1] == '\0') ?
- SRC_STDIN : SRC_FILE,
- src, srcfiles, NULL, NULL);
-
- break;
-
- case 'v':
- add_preassign(PRE_ASSIGN, optarg);
- break;
-
- case 'b':
- do_binary = true;
- break;
-
- case 'c':
- do_flags |= DO_TRADITIONAL;
- break;
-
- case 'C':
- copyleft();
- break;
-
- case 'd':
- do_flags |= DO_DUMP_VARS;
- if (optarg != NULL && optarg[0] != '\0')
- varfile = optarg;
- break;
-
- case 'D':
- do_flags |= DO_DEBUG;
- if (optarg != NULL && optarg[0] != '\0')
- command_file = optarg;
- break;
-
- case 'e':
- if (optarg[0] == '\0')
- warning(_("empty argument to `-e/--source' ignored"));
- else
- (void) add_srcfile(SRC_CMDLINE, optarg, srcfiles, NULL, NULL);
- break;
-
- case 'g':
- do_flags |= DO_INTL;
- break;
-
- case 'h':
- /* write usage to stdout, per GNU coding stds */
- usage(EXIT_SUCCESS, stdout);
- break;
-
- case 'i':
- (void) add_srcfile(SRC_INC, optarg, srcfiles, NULL, NULL);
- break;
+ parse_args(argc, argv);
- case 'l':
- (void) add_srcfile(SRC_EXTLIB, optarg, srcfiles, NULL, NULL);
- break;
+ set_locale_stuff();
-#ifndef NO_LINT
- case 'L':
- do_flags |= DO_LINT_ALL;
- if (optarg != NULL) {
- if (strcmp(optarg, "fatal") == 0)
- lintfunc = r_fatal;
- else if (strcmp(optarg, "invalid") == 0) {
- do_flags &= ~DO_LINT_ALL;
- do_flags |= DO_LINT_INVALID;
- }
- }
- break;
-
- case 't':
- do_flags |= DO_LINT_OLD;
- break;
-#else
- case 'L':
- case 't':
- break;
-#endif
-
- case 'n':
- do_flags |= DO_NON_DEC_DATA;
- break;
-
- case 'N':
- use_lc_numeric = true;
- break;
-
- case 'O':
- do_optimize = true;
- break;
-
- case 'p':
- do_flags |= DO_PROFILE;
- /* fall through */
- case 'o':
- do_flags |= DO_PRETTY_PRINT;
- if (optarg != NULL)
- set_prof_file(optarg);
- else
- set_prof_file(DEFAULT_PROFILE);
- break;
-
- case 'M':
-#ifdef HAVE_MPFR
- do_flags |= DO_MPFR;
-#else
- warning(_("-M ignored: MPFR/GMP support not compiled in"));
-#endif
- break;
-
- case 'P':
- do_flags |= DO_POSIX;
- break;
-
- case 'r':
- do_flags |= DO_INTERVALS;
- break;
-
- case 'S':
- do_flags |= DO_SANDBOX;
- break;
-
- case 'V':
- do_version = true;
- break;
-
- case 'W': /* gawk specific options - now in getopt_long */
- fprintf(stderr, _("%s: option `-W %s' unrecognized, ignored\n"),
- argv[0], optarg);
- break;
-
- case 0:
- /*
- * getopt_long found an option that sets a variable
- * instead of returning a letter. Do nothing, just
- * cycle around for the next one.
- */
- break;
+ /*
+ * In glibc, MB_CUR_MAX is actually a function. This value is
+ * tested *a lot* in many speed-critical places in gawk. Caching
+ * this value once makes a speed difference.
+ */
+ gawk_mb_cur_max = MB_CUR_MAX;
- case 'Y':
-#if defined(YYDEBUG) || defined(GAWKDEBUG)
- if (c == 'Y') {
- yydebug = 2;
- break;
- }
-#endif
- /* if not debugging, fall through */
- case '?':
- default:
- /*
- * If not posix, an unrecognized option stops argument
- * processing so that it can go into ARGV for the awk
- * program to see. This makes use of ``#! /bin/gawk -f''
- * easier.
- *
- * However, it's never simple. If optopt is set,
- * an option that requires an argument didn't get the
- * argument. We care because if opterr is 0, then
- * getopt_long won't print the error message for us.
- */
- if (! do_posix
- && (optopt == '\0' || strchr(optlist, optopt) == NULL)) {
- /*
- * can't just do optind--. In case of an
- * option with >= 2 letters, getopt_long
- * won't have incremented optind.
- */
- optind = old_optind;
- stopped_early = true;
- goto out;
- } else if (optopt != '\0') {
- /* Use POSIX required message format */
- fprintf(stderr,
- _("%s: option requires an argument -- %c\n"),
- myname, optopt);
- usage(EXIT_FAILURE, stderr);
- }
- /* else
- let getopt print error message for us */
- break;
- }
- if (c == 'E') /* --exec ends option processing */
- break;
- }
-out:
+ /* init the cache for checking bytes if they're characters */
+ init_btowc_cache();
if (do_nostalgia)
nostalgia();
@@ -583,7 +329,6 @@ out:
if (do_lint && os_is_setuid())
warning(_("running %s setuid root may be a security problem"), myname);
-#if MBS_SUPPORT
if (do_binary) {
if (do_posix)
warning(_("`--posix' overrides `--characters-as-bytes'"));
@@ -593,7 +338,6 @@ out:
setlocale(LC_ALL, "C");
#endif
}
-#endif
if (do_debug) /* Need to register the debugger pre-exec hook before any other */
init_debug();
@@ -734,9 +478,9 @@ out:
* data using the local decimal point.
*/
if (use_lc_numeric)
- setlocale(LC_NUMERIC, "");
+ setlocale(LC_NUMERIC, locale);
#endif
-
+
init_io();
output_fp = stdout;
@@ -1379,7 +1123,7 @@ arg_assign(char *arg, bool initing)
setlocale(LC_NUMERIC, "C");
(void) force_number(it);
if (do_posix)
- setlocale(LC_NUMERIC, "");
+ setlocale(LC_NUMERIC, locale);
#endif /* LC_NUMERIC */
/*
@@ -1643,3 +1387,285 @@ getenv_long(const char *name)
}
return -1;
}
+
+/* parse_args --- do the getopt_long thing */
+
+static void
+parse_args(int argc, char **argv)
+{
+ /*
+ * The + on the front tells GNU getopt not to rearrange argv.
+ */
+ const char *optlist = "+F:f:v:W;bcCd::D::e:E:ghi:l:L:nNo::Op::MPrStVYZ:";
+ int old_optind;
+ int c;
+ char *scan;
+ char *src;
+
+ /* we do error messages ourselves on invalid options */
+ opterr = false;
+
+ /* copy argv before getopt gets to it; used to restart the debugger */
+ save_argv(argc, argv);
+
+ /* option processing. ready, set, go! */
+ for (optopt = 0, old_optind = 1;
+ (c = getopt_long(argc, argv, optlist, optab, NULL)) != EOF;
+ optopt = 0, old_optind = optind) {
+ if (do_posix)
+ opterr = true;
+
+ switch (c) {
+ case 'F':
+ add_preassign(PRE_ASSIGN_FS, optarg);
+ break;
+
+ case 'E':
+ disallow_var_assigns = true;
+ /* fall through */
+ case 'f':
+ /*
+ * Allow multiple -f options.
+ * This makes function libraries real easy.
+ * Most of the magic is in the scanner.
+ *
+ * The following is to allow for whitespace at the end
+ * of a #! /bin/gawk line in an executable file
+ */
+ scan = optarg;
+ if (argv[optind-1] != optarg)
+ while (isspace((unsigned char) *scan))
+ scan++;
+ src = (*scan == '\0' ? argv[optind++] : optarg);
+ (void) add_srcfile((src && src[0] == '-' && src[1] == '\0') ?
+ SRC_STDIN : SRC_FILE,
+ src, srcfiles, NULL, NULL);
+
+ break;
+
+ case 'v':
+ add_preassign(PRE_ASSIGN, optarg);
+ break;
+
+ case 'b':
+ do_binary = true;
+ break;
+
+ case 'c':
+ do_flags |= DO_TRADITIONAL;
+ break;
+
+ case 'C':
+ copyleft();
+ break;
+
+ case 'd':
+ do_flags |= DO_DUMP_VARS;
+ if (optarg != NULL && optarg[0] != '\0')
+ varfile = optarg;
+ break;
+
+ case 'D':
+ do_flags |= DO_DEBUG;
+ if (optarg != NULL && optarg[0] != '\0')
+ command_file = optarg;
+ break;
+
+ case 'e':
+ if (optarg[0] == '\0')
+ warning(_("empty argument to `-e/--source' ignored"));
+ else
+ (void) add_srcfile(SRC_CMDLINE, optarg, srcfiles, NULL, NULL);
+ break;
+
+ case 'g':
+ do_flags |= DO_INTL;
+ break;
+
+ case 'h':
+ /* write usage to stdout, per GNU coding stds */
+ usage(EXIT_SUCCESS, stdout);
+ break;
+
+ case 'i':
+ (void) add_srcfile(SRC_INC, optarg, srcfiles, NULL, NULL);
+ break;
+
+ case 'l':
+ (void) add_srcfile(SRC_EXTLIB, optarg, srcfiles, NULL, NULL);
+ break;
+
+#ifndef NO_LINT
+ case 'L':
+ do_flags |= DO_LINT_ALL;
+ if (optarg != NULL) {
+ if (strcmp(optarg, "fatal") == 0)
+ lintfunc = r_fatal;
+ else if (strcmp(optarg, "invalid") == 0) {
+ do_flags &= ~DO_LINT_ALL;
+ do_flags |= DO_LINT_INVALID;
+ }
+ }
+ break;
+
+ case 't':
+ do_flags |= DO_LINT_OLD;
+ break;
+#else
+ case 'L':
+ case 't':
+ break;
+#endif
+
+ case 'n':
+ do_flags |= DO_NON_DEC_DATA;
+ break;
+
+ case 'N':
+ use_lc_numeric = true;
+ break;
+
+ case 'O':
+ do_optimize = true;
+ break;
+
+ case 'p':
+ do_flags |= DO_PROFILE;
+ /* fall through */
+ case 'o':
+ do_flags |= DO_PRETTY_PRINT;
+ if (optarg != NULL)
+ set_prof_file(optarg);
+ else
+ set_prof_file(DEFAULT_PROFILE);
+ break;
+
+ case 'M':
+#ifdef HAVE_MPFR
+ do_flags |= DO_MPFR;
+#else
+ warning(_("-M ignored: MPFR/GMP support not compiled in"));
+#endif
+ break;
+
+ case 'P':
+ do_flags |= DO_POSIX;
+ break;
+
+ case 'r':
+ do_flags |= DO_INTERVALS;
+ break;
+
+ case 'S':
+ do_flags |= DO_SANDBOX;
+ break;
+
+ case 'V':
+ do_version = true;
+ break;
+
+ case 'W': /* gawk specific options - now in getopt_long */
+ fprintf(stderr, _("%s: option `-W %s' unrecognized, ignored\n"),
+ argv[0], optarg);
+ break;
+
+ case 0:
+ /*
+ * getopt_long found an option that sets a variable
+ * instead of returning a letter. Do nothing, just
+ * cycle around for the next one.
+ */
+ break;
+
+ case 'Y':
+ case 'Z':
+#if defined(YYDEBUG) || defined(GAWKDEBUG)
+ if (c == 'Y') {
+ yydebug = 2;
+ break;
+ }
+#endif
+#if defined(LOCALEDEBUG)
+ if (c == 'Z') {
+ locale = optarg;
+ break;
+ }
+#endif
+ /* if not debugging, fall through */
+ case '?':
+ default:
+ /*
+ * If not posix, an unrecognized option stops argument
+ * processing so that it can go into ARGV for the awk
+ * program to see. This makes use of ``#! /bin/gawk -f''
+ * easier.
+ *
+ * However, it's never simple. If optopt is set,
+ * an option that requires an argument didn't get the
+ * argument. We care because if opterr is 0, then
+ * getopt_long won't print the error message for us.
+ */
+ if (! do_posix
+ && (optopt == '\0' || strchr(optlist, optopt) == NULL)) {
+ /*
+ * can't just do optind--. In case of an
+ * option with >= 2 letters, getopt_long
+ * won't have incremented optind.
+ */
+ optind = old_optind;
+ stopped_early = true;
+ goto out;
+ } else if (optopt != '\0') {
+ /* Use POSIX required message format */
+ fprintf(stderr,
+ _("%s: option requires an argument -- %c\n"),
+ myname, optopt);
+ usage(EXIT_FAILURE, stderr);
+ }
+ /* else
+ let getopt print error message for us */
+ break;
+ }
+ if (c == 'E') /* --exec ends option processing */
+ break;
+ }
+out:
+ return;
+}
+
+/* set_locale_stuff --- setup the locale stuff */
+
+static void
+set_locale_stuff(void)
+{
+#if defined(LC_CTYPE)
+ setlocale(LC_CTYPE, locale);
+#endif
+#if defined(LC_COLLATE)
+ setlocale(LC_COLLATE, locale);
+#endif
+#if defined(LC_MESSAGES)
+ setlocale(LC_MESSAGES, locale);
+#endif
+#if defined(LC_NUMERIC) && defined(HAVE_LOCALE_H)
+ /*
+ * Force the issue here. According to POSIX 2001, decimal
+ * point is used for parsing source code and for command-line
+ * assignments and the locale value for processing input,
+ * number to string conversion, and printing output.
+ *
+ * 10/2005 --- see below also; we now only use the locale's
+ * decimal point if do_posix in effect.
+ *
+ * 9/2007:
+ * This is a mess. We need to get the locale's numeric info for
+ * the thousands separator for the %'d flag.
+ */
+ setlocale(LC_NUMERIC, locale);
+ init_locale(& loc);
+ setlocale(LC_NUMERIC, "C");
+#endif
+#if defined(LC_TIME)
+ setlocale(LC_TIME, locale);
+#endif
+}