diff options
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 156 |
1 files changed, 89 insertions, 67 deletions
@@ -1,23 +1,23 @@ /* - * main.c -- Code generator and main program for gawk. + * main.c -- Code generator and main program for gawk. */ -/* +/* * Copyright (C) 1986, 1988, 1989, 1991-2016 the Free Software Foundation, Inc. - * + * * This file is part of GAWK, the GNU implementation of the * AWK Programming Language. - * + * * GAWK is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. - * + * * GAWK is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA @@ -58,7 +58,7 @@ static void init_args(int argc0, int argc, const char *argv0, char **argv); static void init_vars(void); static NODE *load_environ(void); static NODE *load_procinfo(void); -static RETSIGTYPE catchsig(int sig); +static void catchsig(int sig); #ifdef HAVE_LIBSIGSEGV static int catchsegv(void *fault_address, int serious); static void catchstackoverflow(int emergency, stackoverflow_context_t scp); @@ -85,7 +85,7 @@ long NF; long NR; long FNR; int BINMODE; -int IGNORECASE; +bool IGNORECASE; char *OFS; char *ORS; char *OFMT; @@ -147,7 +147,7 @@ static void set_locale_stuff(void); static bool stopped_early = false; int do_flags = false; -bool do_optimize = false; /* apply default optimizations */ +bool do_optimize = true; /* 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 */ @@ -194,6 +194,7 @@ static const struct option optab[] = { { "locale", required_argument, NULL, 'Z' }, #endif { "non-decimal-data", no_argument, NULL, 'n' }, + { "no-optimize", no_argument, NULL, 's' }, { "nostalgia", no_argument, & do_nostalgia, 1 }, { "optimize", no_argument, NULL, 'O' }, #if defined(YYDEBUG) || defined(GAWKDEBUG) @@ -254,7 +255,7 @@ main(int argc, char **argv) #ifdef SIGBUS (void) signal(SIGBUS, catchsig); #endif -#ifdef SIGPIPE + /* * Ignore SIGPIPE so that writes to pipes that fail don't * kill the process but instead return -1 and set errno. @@ -268,8 +269,7 @@ main(int argc, char **argv) * should not give us "broken pipe" messages --- mainly because * it did not do so in the past and people would complain. */ - signal(SIGPIPE, SIG_IGN); -#endif + ignore_sigpipe(); (void) sigsegv_install_handler(catchsegv); #define STACK_SIZE (16*1024) @@ -307,22 +307,10 @@ main(int argc, char **argv) * this value once makes a speed difference. */ gawk_mb_cur_max = MB_CUR_MAX; -#ifdef LIBC_IS_BORKED -{ - const char *env_lc; - - env_lc = getenv("LC_ALL"); - if (env_lc == NULL) - env_lc = getenv("LANG"); - if (env_lc != NULL && env_lc[1] == '\0' && tolower(env_lc[0]) == 'c') - gawk_mb_cur_max = 1; -} -#endif /* init the cache for checking bytes if they're characters */ init_btowc_cache(); - if (do_nostalgia) nostalgia(); @@ -368,7 +356,7 @@ main(int argc, char **argv) init_debug(); #ifdef HAVE_MPFR - /* Set up MPFR defaults, and register pre-exec hook to process arithmetic opcodes */ + /* Set up MPFR defaults, and register pre-exec hook to process arithmetic opcodes */ if (do_mpfr) init_mpfr(DEFAULT_PREC, DEFAULT_ROUNDMODE); #endif @@ -469,7 +457,7 @@ main(int argc, char **argv) /* Read in the program */ if (parse_program(& code_block) != 0) exit(EXIT_FAILURE); - + if (do_intl) exit(EXIT_SUCCESS); @@ -511,9 +499,8 @@ main(int argc, char **argv) if (do_debug) debug_prog(code_block); - else if (do_pretty_print && ! do_debug && getenv("GAWK_NO_PP_RUN") != NULL) - /* hack to run pretty printer only. need a better solution */ - ; + else if (do_pretty_print && ! do_profile) + ; /* run pretty printer only. */ else interpret(code_block); @@ -532,7 +519,7 @@ main(int argc, char **argv) if (do_tidy_mem) release_all_vars(); - + /* keep valgrind happier */ if (extra_stack) efree(extra_stack); @@ -609,6 +596,7 @@ usage(int exitval, FILE *fp) fputs(_("\t-p[file]\t\t--profile[=file]\n"), fp); fputs(_("\t-P\t\t\t--posix\n"), fp); fputs(_("\t-r\t\t\t--re-interval\n"), fp); + fputs(_("\t-s\t\t\t--no-optimize\n"), fp); fputs(_("\t-S\t\t\t--sandbox\n"), fp); fputs(_("\t-t\t\t\t--lint-old\n"), fp); fputs(_("\t-V\t\t\t--version\n"), fp); @@ -639,13 +627,20 @@ By default it reads standard input and writes standard output.\n\n"), fp); fflush(fp); if (ferror(fp)) { +#ifdef __MINGW32__ + if (errno == 0 || errno == EINVAL) + w32_maybe_set_errno(); +#endif /* don't warn about stdout/stderr if EPIPE, but do error exit */ - if (errno != EPIPE) { - if (fp == stdout) - warning(_("error writing standard output (%s)"), strerror(errno)); - else if (fp == stderr) - warning(_("error writing standard error (%s)"), strerror(errno)); - } + if (errno == EPIPE) + die_via_sigpipe(); + + if (fp == stdout) + warning(_("error writing standard output (%s)"), strerror(errno)); + else if (fp == stderr) + warning(_("error writing standard error (%s)"), strerror(errno)); + + // some other problem than SIGPIPE exit(EXIT_FAILURE); } @@ -674,7 +669,7 @@ GNU General Public License for more details.\n\ static const char blurb_part3[] = N_("You should have received a copy of the GNU General Public License\n\ along with this program. If not, see http://www.gnu.org/licenses/.\n"); - + /* multiple blurbs are needed for some brain dead compilers. */ printf(_(blurb_part1), UPDATE_YEAR); /* Last update year */ fputs(_(blurb_part2), stdout); @@ -682,6 +677,10 @@ along with this program. If not, see http://www.gnu.org/licenses/.\n"); fflush(stdout); if (ferror(stdout)) { +#ifdef __MINGW32__ + if (errno == 0 || errno == EINVAL) + w32_maybe_set_errno(); +#endif /* don't warn about stdout if EPIPE, but do error exit */ if (errno != EPIPE) warning(_("error writing standard output (%s)"), strerror(errno)); @@ -733,14 +732,14 @@ init_args(int argc0, int argc, const char *argv0, char **argv) unref(tmp); unref(*aptr); *aptr = make_string(argv0, strlen(argv0)); - (*aptr)->flags |= MAYBE_NUM; + (*aptr)->flags |= USER_INPUT; for (i = argc0, j = 1; i < argc; i++, j++) { tmp = make_number((AWKNUM) j); aptr = assoc_lookup(ARGV_node, tmp); unref(tmp); unref(*aptr); *aptr = make_string(argv[i], strlen(argv[i])); - (*aptr)->flags |= MAYBE_NUM; + (*aptr)->flags |= USER_INPUT; } ARGC_node = install_symbol(estrdup("ARGC", 4), Node_var); @@ -785,7 +784,7 @@ static const struct varinit varinit[] = { {&FPAT_node, "FPAT", "[^[:space:]]+", 0, NULL, set_FPAT, false, NON_STANDARD }, {&IGNORECASE_node, "IGNORECASE", NULL, 0, NULL, set_IGNORECASE, false, NON_STANDARD }, {&LINT_node, "LINT", NULL, 0, NULL, set_LINT, false, NON_STANDARD }, -{&PREC_node, "PREC", NULL, DEFAULT_PREC, NULL, set_PREC, false, NON_STANDARD}, +{&PREC_node, "PREC", NULL, DEFAULT_PREC, NULL, set_PREC, false, NON_STANDARD}, {&NF_node, "NF", NULL, -1, update_NF, set_NF, false, 0 }, {&NR_node, "NR", NULL, 0, update_NR, set_NR, true, 0 }, {&OFMT_node, "OFMT", "%.6g", 0, NULL, set_OFMT, true, 0 }, @@ -894,7 +893,7 @@ load_environ() unref(tmp); unref(*aptr); *aptr = make_string(val, strlen(val)); - (*aptr)->flags |= MAYBE_NUM; + (*aptr)->flags |= USER_INPUT; /* restore '=' so that system() gets a valid environment */ if (val != nullstr) @@ -911,9 +910,40 @@ load_environ() */ path_environ("AWKPATH", defpath); path_environ("AWKLIBPATH", deflibpath); + + /* set up array functions */ + init_env_array(ENVIRON_node); + return ENVIRON_node; } +static void +load_procinfo_argv() +{ + NODE *tmp; + NODE **aptr; + NODE *argv_array; + int i; + + tmp = make_string("argv", 4); + aptr = assoc_lookup(PROCINFO_node, tmp); + unref(tmp); + unref(*aptr); + getnode(argv_array); + memset(argv_array, '\0', sizeof(NODE)); /* valgrind wants this */ + null_array(argv_array); + *aptr = argv_array; + argv_array->parent_array = PROCINFO_node; + argv_array->vname = estrdup("argv", 4); + for (i = 0; d_argv[i] != NULL; i++) { + tmp = make_number(i); + aptr = assoc_lookup(argv_array, tmp); + unref(tmp); + unref(*aptr); + *aptr = make_string(d_argv[i], strlen(d_argv[i])); + } +} + /* load_procinfo --- populate the PROCINFO array */ static NODE * @@ -985,22 +1015,7 @@ load_procinfo() value = getegid(); update_PROCINFO_num("egid", value); - switch (current_field_sep()) { - case Using_FIELDWIDTHS: - update_PROCINFO_str("FS", "FIELDWIDTHS"); - break; - case Using_FPAT: - update_PROCINFO_str("FS", "FPAT"); - break; - case Using_FS: - update_PROCINFO_str("FS", "FS"); - break; - default: - fatal(_("unknown value for field spec: %d\n"), - current_field_sep()); - break; - } - + update_PROCINFO_str("FS", current_field_sep_str()); #if defined (HAVE_GETGROUPS) && defined(NGROUPS_MAX) && NGROUPS_MAX > 0 for (i = 0; i < ngroups; i++) { @@ -1013,6 +1028,7 @@ load_procinfo() groupset = NULL; } #endif + load_procinfo_argv(); return PROCINFO_node; } @@ -1109,7 +1125,7 @@ arg_assign(char *arg, bool initing) /* first check that the variable name has valid syntax */ badvar = false; - if (! is_alpha((unsigned char) arg[0]) && arg[0] != '_') + if (! is_letter((unsigned char) arg[0])) badvar = true; else for (cp2 = arg+1; *cp2; cp2++) @@ -1132,7 +1148,7 @@ arg_assign(char *arg, bool initing) if (! initing) { var = lookup(arg); if (var != NULL && var->type == Node_func) - fatal(_("cannot use function `%s' as variable name"), arg); + fatal(_("cannot use function `%s' as variable name"), arg); } /* @@ -1140,7 +1156,7 @@ arg_assign(char *arg, bool initing) * This makes sense, so we do it too. */ it = make_str_node(cp, strlen(cp), SCAN); - it->flags |= MAYBE_NUM; + it->flags |= USER_INPUT; #ifdef LC_NUMERIC /* * See comment above about locale decimal point. @@ -1183,7 +1199,7 @@ arg_assign(char *arg, bool initing) /* catchsig --- catch signals */ -static RETSIGTYPE +static void catchsig(int sig) { if (sig == SIGFPE) { @@ -1254,7 +1270,7 @@ version() #ifdef HAVE_MPFR printf(" (GNU MPFR %s, GNU MP %s)", mpfr_get_version(), gmp_version); #endif - printf("\n"); + printf("\n"); print_ext_versions(); /* @@ -1337,7 +1353,7 @@ estrdup(const char *str, size_t len) s[len] = '\0'; return s; } - + #if defined(HAVE_LOCALE_H) /* init_locale --- initialize locale info. */ @@ -1407,7 +1423,7 @@ long getenv_long(const char *name) { const char *val; - long newval; + long newval; if ((val = getenv(name)) != NULL && isdigit((unsigned char) *val)) { for (newval = 0; *val && isdigit((unsigned char) *val); val++) newval = (newval * 10) + *val - '0'; @@ -1424,7 +1440,7 @@ 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:"; + const char *optlist = "+F:f:v:W;bcCd::D::e:E:ghi:l:L:nNo::Op::MPrSstVYZ:"; int old_optind; int c; char *scan; @@ -1433,7 +1449,7 @@ parse_args(int argc, char **argv) /* we do error messages ourselves on invalid options */ opterr = false; - /* copy argv before getopt gets to it; used to restart the debugger */ + /* copy argv before getopt gets to it; used to restart the debugger */ save_argv(argc, argv); /* option processing. ready, set, go! */ @@ -1583,7 +1599,11 @@ parse_args(int argc, char **argv) case 'r': do_flags |= DO_INTERVALS; break; - + + case 's': + do_optimize = false; + break; + case 'S': do_flags |= DO_SANDBOX; break; @@ -1658,6 +1678,8 @@ parse_args(int argc, char **argv) break; } out: + do_optimize = (do_optimize && ! do_pretty_print); + return; } |