aboutsummaryrefslogtreecommitdiffstats
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c117
1 files changed, 84 insertions, 33 deletions
diff --git a/main.c b/main.c
index 9df5869f..2324d9a0 100644
--- a/main.c
+++ b/main.c
@@ -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
}