diff options
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 117 |
1 files changed, 84 insertions, 33 deletions
@@ -3,7 +3,7 @@ */ /* - * Copyright (C) 1986, 1988, 1989, 1991-2011 the Free Software Foundation, Inc. + * Copyright (C) 1986, 1988, 1989, 1991-2012 the Free Software Foundation, Inc. * * This file is part of GAWK, the GNU implementation of the * AWK Programming Language. @@ -24,7 +24,7 @@ */ /* FIX THIS BEFORE EVERY RELEASE: */ -#define UPDATE_YEAR 2011 +#define UPDATE_YEAR 2012 #include "awk.h" #include "getopt.h" @@ -35,6 +35,8 @@ #define DEFAULT_PROFILE "awkprof.out" /* where to put profile */ #define DEFAULT_VARFILE "awkvars.out" /* where to put vars */ +#define DEFAULT_PREC 53 +#define DEFAULT_ROUNDMODE "N" /* round to nearest */ static const char *varfile = DEFAULT_VARFILE; const char *command_file = NULL; /* debugger commands */ @@ -55,11 +57,10 @@ static void nostalgia(void) ATTRIBUTE_NORETURN; static void version(void) ATTRIBUTE_NORETURN; static void init_fds(void); static void init_groupset(void); - static void save_argv(int, char **); extern int debug_prog(INSTRUCTION *pc); /* debug.c */ - +extern int init_debug(); /* debug.c */ /* These nodes store all the special variables AWK uses */ NODE *ARGC_node, *ARGIND_node, *ARGV_node, *BINMODE_node, *CONVFMT_node; @@ -67,6 +68,7 @@ NODE *ENVIRON_node, *ERRNO_node, *FIELDWIDTHS_node, *FILENAME_node; NODE *FNR_node, *FPAT_node, *FS_node, *IGNORECASE_node, *LINT_node; NODE *NF_node, *NR_node, *OFMT_node, *OFS_node, *ORS_node, *PROCINFO_node; NODE *RLENGTH_node, *RSTART_node, *RS_node, *RT_node, *SUBSEP_node; +NODE *PREC_node, *ROUNDMODE_node; NODE *TEXTDOMAIN_node; NODE *_r; /* used as temporary in stack macros */ @@ -160,30 +162,31 @@ void (*lintfunc)(const char *mesg, ...) = warning; static const struct option optab[] = { { "traditional", no_argument, NULL, 'c' }, - { "lint", optional_argument, NULL, 'L' }, + { "lint", optional_argument, NULL, 'L' }, { "lint-old", no_argument, NULL, 't' }, { "optimize", no_argument, NULL, 'O' }, { "posix", no_argument, NULL, 'P' }, { "nostalgia", no_argument, & do_nostalgia, 1 }, { "gen-pot", no_argument, NULL, 'g' }, - { "non-decimal-data", no_argument, NULL, 'n' }, - { "pretty-print", optional_argument, NULL, 'o' }, - { "profile", optional_argument, NULL, 'p' }, - { "debug", optional_argument, NULL, 'D' }, - { "copyright", no_argument, NULL, 'C' }, - { "field-separator", required_argument, NULL, 'F' }, - { "file", required_argument, NULL, 'f' }, + { "non-decimal-data", no_argument, NULL, 'n' }, + { "pretty-print", optional_argument, NULL, 'o' }, + { "profile", optional_argument, NULL, 'p' }, + { "debug", optional_argument, NULL, 'D' }, + { "copyright", no_argument, NULL, 'C' }, + { "field-separator", required_argument, NULL, 'F' }, + { "file", required_argument, NULL, 'f' }, { "re-interval", no_argument, NULL, 'r' }, - { "source", required_argument, NULL, 'e' }, - { "load", required_argument, NULL, 'l' }, - { "dump-variables", optional_argument, NULL, 'd' }, - { "assign", required_argument, NULL, 'v' }, - { "version", no_argument, NULL, 'V' }, - { "help", no_argument, NULL, 'h' }, - { "exec", required_argument, NULL, 'E' }, + { "source", required_argument, NULL, 'e' }, + { "load", required_argument, NULL, 'l' }, + { "dump-variables", optional_argument, NULL, 'd' }, + { "assign", required_argument, NULL, 'v' }, + { "version", no_argument, NULL, 'V' }, + { "help", no_argument, NULL, 'h' }, + { "exec", required_argument, NULL, 'E' }, { "use-lc-numeric", no_argument, & use_lc_numeric, 1 }, { "characters-as-bytes", no_argument, & do_binary, 'b' }, { "sandbox", no_argument, NULL, 'S' }, + { "bignum", no_argument, NULL, 'M' }, #if defined(YYDEBUG) || defined(GAWKDEBUG) { "parsedebug", no_argument, NULL, 'Y' }, #endif @@ -198,9 +201,8 @@ main(int argc, char **argv) { /* * The + on the front tells GNU getopt not to rearrange argv. - * Note: reserve -l for future use, for xgawk's -l option. */ - const char *optlist = "+F:f:v:W;m:bcCd::D::e:E:gh:l:L:nNo::Op::PrStVY"; + const char *optlist = "+F:f:v:W;m:bcCd::D::e:E:gh:l:L:nNo::Op::MPrStVY"; int stopped_early = FALSE; int old_optind; int i; @@ -291,6 +293,8 @@ main(int argc, char **argv) /* init array handling. */ array_init(); + output_fp = stdout; + /* we do error messages ourselves on invalid options */ opterr = FALSE; @@ -442,6 +446,12 @@ main(int argc, char **argv) set_prof_file(DEFAULT_PROFILE); break; + case 'M': +#ifdef HAVE_MPFR + do_flags |= DO_MPFR; +#endif + break; + case 'P': do_flags |= DO_POSIX; break; @@ -558,13 +568,30 @@ out: } #endif + if (do_debug) /* Need to register the debugger pre-exec hook before any other */ + init_debug(); + +#ifdef HAVE_MPFR + /* Set up MPFR defaults, and register pre-exec hook to process arithmetic opcodes */ + if (do_mpfr) + init_mpfr(DEFAULT_PREC, DEFAULT_ROUNDMODE); +#endif + /* load group set */ init_groupset(); /* initialize the null string */ Nnull_string = make_string("", 0); - Nnull_string->numbr = 0.0; - Nnull_string->flags = (MALLOC|STRCUR|STRING|NUMCUR|NUMBER); +#ifdef HAVE_MPFR + if (do_mpfr) { + mpz_init(Nnull_string->mpg_i); + Nnull_string->flags = (MALLOC|STRCUR|STRING|MPZN|NUMCUR|NUMBER); + } else +#endif + { + Nnull_string->numbr = 0.0; + Nnull_string->flags = (MALLOC|STRCUR|STRING|NUMCUR|NUMBER); + } /* * Tell the regex routines how they should work. @@ -573,8 +600,6 @@ out: */ resetup(); - init_interpret(); - /* Set up the special variables */ init_vars(); @@ -625,6 +650,9 @@ out: optind++; } + /* Select the interpreter routine */ + init_interpret(); + init_args(optind, argc, do_posix ? argv[0] : myname, argv); @@ -756,6 +784,7 @@ usage(int exitval, FILE *fp) fputs(_("\t-l library\t\t--load=library\n"), fp); fputs(_("\t-L [fatal]\t\t--lint[=fatal]\n"), fp); fputs(_("\t-n\t\t\t--non-decimal-data\n"), fp); + fputs(_("\t-M\t\t\t--bignum\n"), fp); fputs(_("\t-N\t\t\t--use-lc-numeric\n"), fp); fputs(_("\t-o[file]\t\t--pretty-print[=file]\n"), fp); fputs(_("\t-O\t\t\t--optimize\n"), fp); @@ -930,6 +959,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}, {&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 }, @@ -937,6 +967,7 @@ static const struct varinit varinit[] = { {&ORS_node, "ORS", "\n", 0, NULL, set_ORS, TRUE, 0 }, {NULL, "PROCINFO", NULL, 0, NULL, NULL, FALSE, NO_INSTALL | NON_STANDARD }, {&RLENGTH_node, "RLENGTH", NULL, 0, NULL, NULL, FALSE, 0 }, +{&ROUNDMODE_node, "ROUNDMODE", DEFAULT_ROUNDMODE, 0, NULL, set_ROUNDMODE, FALSE, NON_STANDARD }, {&RS_node, "RS", "\n", 0, NULL, set_RS, TRUE, 0 }, {&RSTART_node, "RSTART", NULL, 0, NULL, NULL, FALSE, 0 }, {&RT_node, "RT", "", 0, NULL, NULL, FALSE, NON_STANDARD }, @@ -957,8 +988,10 @@ init_vars() if ((vp->flags & NO_INSTALL) != 0) continue; n = *(vp->spec) = install_symbol(estrdup(vp->name, strlen(vp->name)), Node_var); - n->var_value = vp->strval == NULL ? make_number(vp->numval) - : make_string(vp->strval, strlen(vp->strval)); + if (vp->strval != NULL) + n->var_value = make_string(vp->strval, strlen(vp->strval)); + else + n->var_value = make_number(vp->numval); n->var_assign = (Func_ptr) vp->assign; n->var_update = (Func_ptr) vp->update; if (vp->do_assign) @@ -1046,6 +1079,8 @@ load_procinfo() { #if defined (HAVE_GETGROUPS) && defined(NGROUPS_MAX) && NGROUPS_MAX > 0 int i; +#endif +#if (defined (HAVE_GETGROUPS) && defined(NGROUPS_MAX) && NGROUPS_MAX > 0) || defined(HAVE_MPFR) char name[100]; #endif AWKNUM value; @@ -1055,6 +1090,15 @@ load_procinfo() update_PROCINFO_str("version", VERSION); update_PROCINFO_str("strftime", def_strftime_format); +#ifdef HAVE_MPFR + sprintf(name, "GNU MPFR %s", mpfr_get_version()); + update_PROCINFO_str("mpfr_version", name); + sprintf(name, "GNU MP %s", gmp_version); + update_PROCINFO_str("gmp_version", name); + update_PROCINFO_num("prec_max", MPFR_PREC_MAX); + update_PROCINFO_num("prec_min", MPFR_PREC_MIN); +#endif + #ifdef GETPGRP_VOID #define getpgrp_arg() /* nothing */ #else @@ -1331,7 +1375,11 @@ nostalgia() static void version() { - printf("%s\n", version_string); + printf("%s", version_string); +#ifdef HAVE_MPFR + printf(" (GNU MPFR %s, GNU MP %s)", mpfr_get_version(), gmp_version); +#endif + printf("\n"); /* * Per GNU coding standards, print copyright info, * then exit successfully, do nothing else. @@ -1384,17 +1432,20 @@ init_groupset() */ ngroups = getgroups(0, NULL); #endif - if (ngroups == -1) - fatal(_("could not find groups: %s"), strerror(errno)); - else if (ngroups == 0) + /* If an error or no groups, just give up and get on with life. */ + if (ngroups <= 0) return; /* fill in groups */ emalloc(groupset, GETGROUPS_T *, ngroups * sizeof(GETGROUPS_T), "init_groupset"); ngroups = getgroups(ngroups, groupset); - if (ngroups == -1) - fatal(_("could not find groups: %s"), strerror(errno)); + /* same thing here, give up but keep going */ + if (ngroups == -1) { + efree(groupset); + ngroups = 0; + groupset = NULL; + } #endif } |