We use the stock version of this file now, but since someone foolishly
took about 15 files off the vendor branch for what turned out to be good reason a Gawk update takes an order of magnitude more effort than it should...
This commit is contained in:
parent
3d77ae77d5
commit
5931acbb5f
@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 1986, 1988, 1989, 1991-2000 the Free Software Foundation, Inc.
|
||||
* Copyright (C) 1986, 1988, 1989, 1991-2001 the Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GAWK, the GNU implementation of the
|
||||
* AWK Programming Language.
|
||||
@ -27,7 +27,24 @@
|
||||
|
||||
#include "awk.h"
|
||||
#include "getopt.h"
|
||||
#include "patchlevel.h"
|
||||
#ifdef TANDEM
|
||||
#include "ptchlvl.h" /* blech */
|
||||
#else
|
||||
#include "patchlev.h"
|
||||
#endif
|
||||
|
||||
#ifndef O_BINARY
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MCHECK_H
|
||||
#include <mcheck.h>
|
||||
#endif
|
||||
|
||||
#define DEFAULT_PROFILE "awkprof.out" /* where to put profile */
|
||||
#define DEFAULT_VARFILE "awkvars.out" /* where to put vars */
|
||||
|
||||
static char *varfile = DEFAULT_VARFILE;
|
||||
|
||||
static void usage P((int exitval, FILE *fp));
|
||||
static void copyleft P((void));
|
||||
@ -38,20 +55,25 @@ static void pre_assign P((char *v));
|
||||
RETSIGTYPE catchsig P((int sig, int code));
|
||||
static void nostalgia P((void));
|
||||
static void version P((void));
|
||||
static void init_fds P((void));
|
||||
|
||||
/* These nodes store all the special variables AWK uses */
|
||||
NODE *ARGC_node, *ARGIND_node, *ARGV_node, *CONVFMT_node, *ENVIRON_node;
|
||||
NODE *ERRNO_node, *FIELDWIDTHS_node, *FILENAME_node, *FNR_node, *FS_node;
|
||||
NODE *IGNORECASE_node, *NF_node, *NR_node, *OFMT_node, *OFS_node;
|
||||
NODE *ORS_node, *RLENGTH_node, *RSTART_node, *RS_node, *RT_node, *SUBSEP_node;
|
||||
|
||||
NODE *ARGC_node, *ARGIND_node, *ARGV_node, *BINMODE_node, *CONVFMT_node;
|
||||
NODE *ENVIRON_node, *ERRNO_node, *FIELDWIDTHS_node, *FILENAME_node, *FNR_node;
|
||||
NODE *FS_node, *IGNORECASE_node, *NF_node, *NR_node, *OFMT_node, *OFS_node;
|
||||
NODE *ORS_node, *PROCINFO_node, *RLENGTH_node, *RSTART_node, *RS_node;
|
||||
NODE *RT_node, *SUBSEP_node, *LINT_node, *TEXTDOMAIN_node;
|
||||
|
||||
long NF;
|
||||
long NR;
|
||||
long FNR;
|
||||
int BINMODE;
|
||||
int IGNORECASE;
|
||||
char *OFS;
|
||||
char *ORS;
|
||||
char *OFMT;
|
||||
char *TEXTDOMAIN;
|
||||
int MRL; /* See -mr option for use of this variable */
|
||||
|
||||
/*
|
||||
* CONVFMT is a convenience pointer for the current number to string format.
|
||||
@ -61,6 +83,7 @@ char *OFMT;
|
||||
*/
|
||||
char *CONVFMT = "%.6g";
|
||||
|
||||
|
||||
int errcount = 0; /* error counter, used by yyerror() */
|
||||
|
||||
NODE *Nnull_string; /* The global null string */
|
||||
@ -77,7 +100,7 @@ NODE *end_block = NULL;
|
||||
int exiting = FALSE; /* Was an "exit" statement executed? */
|
||||
int exit_val = 0; /* optional exit value */
|
||||
|
||||
#if defined(YYDEBUG) || defined(DEBUG)
|
||||
#if defined(YYDEBUG) || defined(GAWKDEBUG)
|
||||
extern int yydebug;
|
||||
#endif
|
||||
|
||||
@ -88,8 +111,13 @@ int do_traditional = FALSE; /* no gnu extensions, add traditional weirdnesses */
|
||||
int do_posix = FALSE; /* turn off gnu and unix extensions */
|
||||
int do_lint = FALSE; /* provide warnings about questionable stuff */
|
||||
int do_lint_old = FALSE; /* warn about stuff not in V7 awk */
|
||||
int do_intl = FALSE; /* dump locale-izable strings to stdout */
|
||||
int do_non_decimal_data = FALSE; /* allow octal/hex C style DATA. Use with caution! */
|
||||
int do_nostalgia = FALSE; /* provide a blast from the past */
|
||||
int do_intervals = FALSE; /* allow {...,...} in regexps */
|
||||
int do_profiling = FALSE; /* profile and pretty print the program */
|
||||
int do_dump_vars = FALSE; /* dump all global variables at end */
|
||||
int do_tidy_mem = FALSE; /* release vars when done */
|
||||
|
||||
int in_begin_rule = FALSE; /* we're in a BEGIN rule */
|
||||
int in_end_rule = FALSE; /* we're in a END rule */
|
||||
@ -101,24 +129,34 @@ extern char *version_string; /* current version, for printing */
|
||||
/* The parse tree is stored here. */
|
||||
NODE *expression_value;
|
||||
|
||||
#if _MSC_VER == 510
|
||||
void (*lintfunc) P((va_list va_alist, ...)) = warning;
|
||||
#else
|
||||
void (*lintfunc) P((char *mesg, ...)) = warning;
|
||||
#endif
|
||||
|
||||
static struct option optab[] = {
|
||||
{ "compat", no_argument, & do_traditional, 1 },
|
||||
{ "traditional", no_argument, & do_traditional, 1 },
|
||||
{ "lint", no_argument, & do_lint, 1 },
|
||||
{ "lint", optional_argument, NULL, 'l' },
|
||||
{ "lint-old", no_argument, & do_lint_old, 1 },
|
||||
{ "posix", no_argument, & do_posix, 1 },
|
||||
{ "nostalgia", no_argument, & do_nostalgia, 1 },
|
||||
{ "gen-po", no_argument, & do_intl, 1 },
|
||||
{ "non-decimal-data", no_argument, & do_non_decimal_data, 1 },
|
||||
{ "profile", optional_argument, NULL, 'p' },
|
||||
{ "copyleft", no_argument, NULL, 'C' },
|
||||
{ "copyright", no_argument, NULL, 'C' },
|
||||
{ "field-separator", required_argument, NULL, 'F' },
|
||||
{ "file", required_argument, NULL, 'f' },
|
||||
{ "re-interval", no_argument, & do_intervals, 1 },
|
||||
{ "re-interval", no_argument, & do_intervals, 1 },
|
||||
{ "source", required_argument, NULL, 's' },
|
||||
{ "dump-variables", optional_argument, NULL, 'd' },
|
||||
{ "assign", required_argument, NULL, 'v' },
|
||||
{ "version", no_argument, NULL, 'V' },
|
||||
{ "usage", no_argument, NULL, 'u' },
|
||||
{ "help", no_argument, NULL, 'u' },
|
||||
#ifdef DEBUG
|
||||
#ifdef GAWKDEBUG
|
||||
{ "parsedebug", no_argument, NULL, 'D' },
|
||||
#endif
|
||||
{ NULL, 0, NULL, '\0' }
|
||||
@ -127,9 +165,7 @@ static struct option optab[] = {
|
||||
/* main --- process args, parse program, run it, clean up */
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
char *scan;
|
||||
@ -141,8 +177,21 @@ char **argv;
|
||||
extern int opterr;
|
||||
extern char *optarg;
|
||||
|
||||
/* do these checks early */
|
||||
if (getenv("TIDYMEM") != NULL)
|
||||
do_tidy_mem = TRUE;
|
||||
|
||||
#ifdef HAVE_MCHECK_H
|
||||
if (do_tidy_mem)
|
||||
mtrace();
|
||||
#endif /* HAVE_MCHECK_H */
|
||||
|
||||
|
||||
setlocale(LC_CTYPE, "");
|
||||
setlocale(LC_COLLATE, "");
|
||||
/* setlocale (LC_ALL, ""); */
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
(void) signal(SIGFPE, (RETSIGTYPE (*) P((int))) catchsig);
|
||||
(void) signal(SIGSEGV, (RETSIGTYPE (*) P((int))) catchsig);
|
||||
@ -188,6 +237,9 @@ char **argv;
|
||||
*/
|
||||
init_fields();
|
||||
|
||||
/* Robustness: check that 0, 1, 2, exist */
|
||||
init_fds();
|
||||
|
||||
/* worst case */
|
||||
emalloc(srcfiles, struct src *, argc * sizeof(struct src), "main");
|
||||
memset(srcfiles, '\0', argc * sizeof(struct src));
|
||||
@ -239,15 +291,26 @@ char **argv;
|
||||
* -mr nnn set record length, ditto
|
||||
*/
|
||||
if (do_lint)
|
||||
warning("-m[fr] option irrelevant in gawk");
|
||||
lintwarn(_("`-m[fr]' option irrelevant in gawk"));
|
||||
if (optarg[0] != 'r' && optarg[0] != 'f')
|
||||
warning("-m option usage: `-m[fr] nnn'");
|
||||
if (optarg[1] == '\0')
|
||||
warning(_("-m option usage: `-m[fr] nnn'"));
|
||||
/*
|
||||
* Set fixed length records for Tandem,
|
||||
* ignored on other platforms (see io.c:get_a_record).
|
||||
*/
|
||||
if (optarg[0] == 'r') {
|
||||
if (ISDIGIT(optarg[1]))
|
||||
MRL = atoi(optarg+1);
|
||||
else {
|
||||
MRL = atoi(argv[optind]);
|
||||
optind++;
|
||||
}
|
||||
} else if (optarg[1] == '\0')
|
||||
optind++;
|
||||
break;
|
||||
|
||||
case 'W': /* gawk specific options - now in getopt_long */
|
||||
fprintf(stderr, "%s: option `-W %s' unrecognized, ignored\n",
|
||||
fprintf(stderr, _("%s: option `-W %s' unrecognized, ignored\n"),
|
||||
argv[0], optarg);
|
||||
break;
|
||||
|
||||
@ -256,9 +319,29 @@ char **argv;
|
||||
copyleft();
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
do_dump_vars = TRUE;
|
||||
if (optarg != NULL && optarg[0] != '\0')
|
||||
varfile = optarg;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
do_lint = TRUE;
|
||||
if (optarg != NULL && strcmp(optarg, "fatal") == 0)
|
||||
lintfunc = r_fatal;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
do_profiling = TRUE;
|
||||
if (optarg != NULL)
|
||||
set_prof_file(optarg);
|
||||
else
|
||||
set_prof_file(DEFAULT_PROFILE);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if (optarg[0] == '\0')
|
||||
warning("empty argument to --source ignored");
|
||||
warning(_("empty argument to `--source' ignored"));
|
||||
else {
|
||||
srcfiles[++numfiles].stype = CMDLINE;
|
||||
srcfiles[numfiles].val = optarg;
|
||||
@ -273,7 +356,7 @@ char **argv;
|
||||
version();
|
||||
break;
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef GAWKDEBUG
|
||||
case 'D':
|
||||
yydebug = 2;
|
||||
break;
|
||||
@ -313,7 +396,7 @@ char **argv;
|
||||
} else if (optopt != '\0')
|
||||
/* Use 1003.2 required message format */
|
||||
fprintf(stderr,
|
||||
"%s: option requires an argument -- %c\n",
|
||||
_("%s: option requires an argument -- %c\n"),
|
||||
myname, optopt);
|
||||
/* else
|
||||
let getopt print error message for us */
|
||||
@ -329,13 +412,13 @@ out:
|
||||
if (! do_posix && getenv("POSIXLY_CORRECT") != NULL) {
|
||||
do_posix = TRUE;
|
||||
if (do_lint)
|
||||
warning(
|
||||
"environment variable `POSIXLY_CORRECT' set: turning on --posix");
|
||||
lintwarn(
|
||||
_("environment variable `POSIXLY_CORRECT' set: turning on `--posix'"));
|
||||
}
|
||||
|
||||
if (do_posix) {
|
||||
if (do_traditional) /* both on command line */
|
||||
warning("--posix overrides --traditional");
|
||||
warning(_("`--posix' overrides `--traditional'"));
|
||||
else
|
||||
do_traditional = TRUE;
|
||||
/*
|
||||
@ -344,6 +427,14 @@ out:
|
||||
*/
|
||||
}
|
||||
|
||||
if (do_traditional && do_non_decimal_data) {
|
||||
do_non_decimal_data = FALSE;
|
||||
warning(_("`--posix'/`--traditional' overrides `--non-decimal-data'"));
|
||||
}
|
||||
|
||||
if (do_lint && os_is_setuid())
|
||||
warning(_("runing %s setuid root may be a security problem"), myname);
|
||||
|
||||
/*
|
||||
* Tell the regex routines how they should work.
|
||||
* Do this again, after argument processing, since do_posix
|
||||
@ -361,7 +452,25 @@ out:
|
||||
set_FS();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* Initialize profiling info, do after parsing args,
|
||||
* in case this is pgawk. Don't bother if the command
|
||||
* line already set profling up.
|
||||
*/
|
||||
if (! do_profiling)
|
||||
init_profiling(& do_profiling, DEFAULT_PROFILE);
|
||||
|
||||
if ((BINMODE & 1) != 0)
|
||||
if (os_setbinmode(fileno(stdin), O_BINARY) == -1)
|
||||
fatal(_("can't set mode on stdin (%s)"), strerror(errno));
|
||||
if ((BINMODE & 2) != 0) {
|
||||
if (os_setbinmode(fileno(stdout), O_BINARY) == -1)
|
||||
fatal(_("can't set mode on stdout (%s)"), strerror(errno));
|
||||
if (os_setbinmode(fileno(stderr), O_BINARY) == -1)
|
||||
fatal(_("can't set mode on stderr (%s)"), strerror(errno));
|
||||
}
|
||||
|
||||
#ifdef GAWKDEBUG
|
||||
setbuf(stdout, (char *) NULL); /* make debugging easier */
|
||||
#endif
|
||||
if (isatty(fileno(stdout)))
|
||||
@ -381,14 +490,18 @@ out:
|
||||
/* Read in the program */
|
||||
if (yyparse() != 0 || errcount != 0)
|
||||
exit(1);
|
||||
/* recover any space from C based alloca */
|
||||
#ifdef C_ALLOCA
|
||||
(void) alloca(0);
|
||||
#endif
|
||||
|
||||
if (do_intl)
|
||||
exit(0);
|
||||
|
||||
if (do_lint && begin_block == NULL && expression_value == NULL
|
||||
&& end_block == NULL)
|
||||
warning("no program");
|
||||
lintwarn(_("no program text at all!"));
|
||||
|
||||
if (do_lint)
|
||||
shadow_funcs();
|
||||
|
||||
init_profiling_signals();
|
||||
|
||||
if (begin_block != NULL) {
|
||||
in_begin_rule = TRUE;
|
||||
@ -404,6 +517,18 @@ out:
|
||||
in_end_rule = FALSE;
|
||||
if (close_io() != 0 && exit_val == 0)
|
||||
exit_val = 1;
|
||||
|
||||
if (do_profiling) {
|
||||
dump_prog(begin_block, expression_value, end_block);
|
||||
dump_funcs();
|
||||
}
|
||||
|
||||
if (do_dump_vars)
|
||||
dump_vars(varfile);
|
||||
|
||||
if (do_tidy_mem)
|
||||
release_all_vars();
|
||||
|
||||
exit(exit_val); /* more portable */
|
||||
return exit_val; /* to suppress warnings */
|
||||
}
|
||||
@ -411,43 +536,46 @@ out:
|
||||
/* usage --- print usage information and exit */
|
||||
|
||||
static void
|
||||
usage(exitval, fp)
|
||||
int exitval;
|
||||
FILE *fp;
|
||||
usage(int exitval, FILE *fp)
|
||||
{
|
||||
char *opt1 = " -f progfile [--]";
|
||||
char *regops = " [POSIX or GNU style options]";
|
||||
/* Not factoring out common stuff makes it easier to translate. */
|
||||
|
||||
fprintf(fp, "Usage: %s%s%s file ...\n\t%s%s [--] %cprogram%c file ...\n",
|
||||
myname, regops, opt1, myname, regops, quote, quote);
|
||||
fprintf(fp, _("Usage: %s [POSIX or GNU style options] -f progfile [--] file ...\n"),
|
||||
myname);
|
||||
fprintf(fp, _("Usage: %s [POSIX or GNU style options] [--] %cprogram%c file ...\n"),
|
||||
myname, quote, quote);
|
||||
|
||||
/* GNU long options info. Gack. */
|
||||
fputs("POSIX options:\t\tGNU long options:\n", fp);
|
||||
fputs("\t-f progfile\t\t--file=progfile\n", fp);
|
||||
fputs("\t-F fs\t\t\t--field-separator=fs\n", fp);
|
||||
fputs("\t-v var=val\t\t--assign=var=val\n", fp);
|
||||
fputs("\t-m[fr] val\n", fp);
|
||||
fputs("\t-W compat\t\t--compat\n", fp);
|
||||
fputs("\t-W copyleft\t\t--copyleft\n", fp);
|
||||
fputs("\t-W copyright\t\t--copyright\n", fp);
|
||||
fputs("\t-W help\t\t\t--help\n", fp);
|
||||
fputs("\t-W lint\t\t\t--lint\n", fp);
|
||||
fputs("\t-W lint-old\t\t--lint-old\n", fp);
|
||||
/* GNU long options info. This is too many options. */
|
||||
|
||||
fputs(_("POSIX options:\t\tGNU long options:\n"), fp);
|
||||
fputs(_("\t-f progfile\t\t--file=progfile\n"), fp);
|
||||
fputs(_("\t-F fs\t\t\t--field-separator=fs\n"), fp);
|
||||
fputs(_("\t-v var=val\t\t--assign=var=val\n"), fp);
|
||||
fputs(_("\t-m[fr] val\n"), fp);
|
||||
fputs(_("\t-W compat\t\t--compat\n"), fp);
|
||||
fputs(_("\t-W copyleft\t\t--copyleft\n"), fp);
|
||||
fputs(_("\t-W copyright\t\t--copyright\n"), fp);
|
||||
fputs(_("\t-W dump-variables[=file]\t--dump-variables[=file]\n"), fp);
|
||||
fputs(_("\t-W gen-po\t\t--gen-po\n"), fp);
|
||||
fputs(_("\t-W help\t\t\t--help\n"), fp);
|
||||
fputs(_("\t-W lint[=fatal]\t\t--lint[=fatal]\n"), fp);
|
||||
fputs(_("\t-W lint-old\t\t--lint-old\n"), fp);
|
||||
fputs(_("\t-W non-decimal-data\t--non-decimal-data\n"), fp);
|
||||
#ifdef NOSTALGIA
|
||||
fputs("\t-W nostalgia\t\t--nostalgia\n", fp);
|
||||
fputs(_("\t-W nostalgia\t\t--nostalgia\n"), fp);
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
fputs("\t-W parsedebug\t\t--parsedebug\n", fp);
|
||||
#ifdef GAWKDEBUG
|
||||
fputs(_("\t-W parsedebug\t\t--parsedebug\n"), fp);
|
||||
#endif
|
||||
fputs("\t-W posix\t\t--posix\n", fp);
|
||||
fputs("\t-W re-interval\t\t--re-interval\n", fp);
|
||||
fputs("\t-W source=program-text\t--source=program-text\n", fp);
|
||||
fputs("\t-W traditional\t\t--traditional\n", fp);
|
||||
fputs("\t-W usage\t\t--usage\n", fp);
|
||||
fputs("\t-W version\t\t--version\n", fp);
|
||||
fputs("\nTo report bugs, see node `Bugs' in `gawk.info', which\n", fp);
|
||||
fputs("is section `Reporting Problems and Bugs' in the\n", fp);
|
||||
fputs("printed version.\n", fp);
|
||||
fputs(_("\t-W profile[=file]\t--profile[=file]\n"), fp);
|
||||
fputs(_("\t-W posix\t\t--posix\n"), fp);
|
||||
fputs(_("\t-W re-interval\t\t--re-interval\n"), fp);
|
||||
fputs(_("\t-W source=program-text\t--source=program-text\n"), fp);
|
||||
fputs(_("\t-W traditional\t\t--traditional\n"), fp);
|
||||
fputs(_("\t-W usage\t\t--usage\n"), fp);
|
||||
fputs(_("\t-W version\t\t--version\n"), fp);
|
||||
fputs(_("\nTo report bugs, see node `Bugs' in `gawk.info', which is\n"), fp);
|
||||
fputs(_("section `Reporting Problems and Bugs' in the printed version.\n"), fp);
|
||||
exit(exitval);
|
||||
}
|
||||
|
||||
@ -457,28 +585,28 @@ static void
|
||||
copyleft()
|
||||
{
|
||||
static char blurb_part1[] =
|
||||
"Copyright (C) 1989, 1991-2000 Free Software Foundation.\n\
|
||||
N_("Copyright (C) 1989, 1991-2001 Free Software Foundation.\n\
|
||||
\n\
|
||||
This program is free software; you can redistribute it and/or modify\n\
|
||||
it under the terms of the GNU General Public License as published by\n\
|
||||
the Free Software Foundation; either version 2 of the License, or\n\
|
||||
(at your option) any later version.\n\
|
||||
\n";
|
||||
\n");
|
||||
static char blurb_part2[] =
|
||||
"This program is distributed in the hope that it will be useful,\n\
|
||||
N_("This program is distributed in the hope that it will be useful,\n\
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
|
||||
GNU General Public License for more details.\n\
|
||||
\n";
|
||||
\n");
|
||||
static char blurb_part3[] =
|
||||
"You should have received a copy of the GNU General Public License\n\
|
||||
N_("You should have received a copy of the GNU General Public License\n\
|
||||
along with this program; if not, write to the Free Software\n\
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n";
|
||||
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n");
|
||||
|
||||
/* multiple blurbs are needed for some brain dead compilers. */
|
||||
fputs(blurb_part1, stdout);
|
||||
fputs(blurb_part2, stdout);
|
||||
fputs(blurb_part3, stdout);
|
||||
fputs(_(blurb_part1), stdout);
|
||||
fputs(_(blurb_part2), stdout);
|
||||
fputs(_(blurb_part3), stdout);
|
||||
fflush(stdout);
|
||||
exit(0);
|
||||
}
|
||||
@ -486,12 +614,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n";
|
||||
/* cmdline_fs --- set FS from the command line */
|
||||
|
||||
static void
|
||||
cmdline_fs(str)
|
||||
char *str;
|
||||
cmdline_fs(char *str)
|
||||
{
|
||||
register NODE **tmp;
|
||||
|
||||
tmp = get_lhs(FS_node, (Func_ptr *) 0);
|
||||
tmp = get_lhs(FS_node, (Func_ptr *) 0, FALSE);
|
||||
unref(*tmp);
|
||||
/*
|
||||
* Only if in full compatibility mode check for the stupid special
|
||||
@ -502,7 +629,7 @@ char *str;
|
||||
*/
|
||||
if (str[0] == 't' && str[1] == '\0') {
|
||||
if (do_lint)
|
||||
warning("-Ft does not set FS to tab in POSIX awk");
|
||||
lintwarn(_("-Ft does not set FS to tab in POSIX awk"));
|
||||
if (do_traditional && ! do_posix)
|
||||
str[0] = '\t';
|
||||
}
|
||||
@ -513,26 +640,25 @@ char *str;
|
||||
/* init_args --- set up ARGV from stuff on the command line */
|
||||
|
||||
static void
|
||||
init_args(argc0, argc, argv0, argv)
|
||||
int argc0, argc;
|
||||
char *argv0;
|
||||
char **argv;
|
||||
init_args(int argc0, int argc, char *argv0, char **argv)
|
||||
{
|
||||
int i, j;
|
||||
NODE **aptr;
|
||||
|
||||
ARGV_node = install("ARGV", node(Nnull_string, Node_var_array, (NODE *) NULL));
|
||||
aptr = assoc_lookup(ARGV_node, tmp_number(0.0));
|
||||
aptr = assoc_lookup(ARGV_node, tmp_number(0.0), FALSE);
|
||||
*aptr = make_string(argv0, strlen(argv0));
|
||||
(*aptr)->flags |= MAYBE_NUM;
|
||||
for (i = argc0, j = 1; i < argc; i++) {
|
||||
aptr = assoc_lookup(ARGV_node, tmp_number((AWKNUM) j));
|
||||
aptr = assoc_lookup(ARGV_node, tmp_number((AWKNUM) j), FALSE);
|
||||
*aptr = make_string(argv[i], strlen(argv[i]));
|
||||
(*aptr)->flags |= MAYBE_NUM;
|
||||
(*aptr)->flags &= ~UNINITIALIZED;
|
||||
j++;
|
||||
}
|
||||
ARGC_node = install("ARGC",
|
||||
node(make_number((AWKNUM) j), Node_var, (NODE *) NULL));
|
||||
ARGC_node->flags &= ~UNINITIALIZED;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -569,6 +695,9 @@ static struct varinit varinit[] = {
|
||||
{&ARGIND_node, "ARGIND", Node_var, NULL, 0, NULL },
|
||||
{&ERRNO_node, "ERRNO", Node_var, NULL, 0, NULL },
|
||||
{&RT_node, "RT", Node_var, "", 0, NULL },
|
||||
{&BINMODE_node, "BINMODE", Node_BINMODE, NULL, 0, NULL },
|
||||
{&LINT_node, "LINT", Node_LINT, NULL, 0, NULL },
|
||||
{&TEXTDOMAIN_node, "TEXTDOMAIN", Node_TEXTDOMAIN, "messages", 0, set_TEXTDOMAIN },
|
||||
{0, NULL, Node_illegal, NULL, 0, NULL },
|
||||
};
|
||||
|
||||
@ -586,6 +715,7 @@ init_vars()
|
||||
strlen(vp->strval)),
|
||||
vp->type, (NODE *) NULL));
|
||||
(*(vp->spec))->flags |= SCALAR;
|
||||
(*(vp->spec))->flags &= ~UNINITIALIZED;
|
||||
if (vp->assign)
|
||||
(*(vp->assign))();
|
||||
}
|
||||
@ -596,10 +726,11 @@ init_vars()
|
||||
void
|
||||
load_environ()
|
||||
{
|
||||
#if ! defined(TANDEM)
|
||||
#if ! (defined(MSDOS) && !defined(DJGPP)) && ! defined(OS2) && ! (defined(VMS) && defined(__DECC))
|
||||
extern char **environ;
|
||||
#endif
|
||||
register char *var, *val, *cp;
|
||||
register char *var, *val;
|
||||
NODE **aptr;
|
||||
register int i;
|
||||
|
||||
@ -614,7 +745,8 @@ load_environ()
|
||||
*val++ = '\0';
|
||||
else
|
||||
val = nullstr;
|
||||
aptr = assoc_lookup(ENVIRON_node, tmp_string(var, strlen(var)));
|
||||
aptr = assoc_lookup(ENVIRON_node,tmp_string(var, strlen(var)),
|
||||
FALSE);
|
||||
*aptr = make_string(val, strlen(val));
|
||||
(*aptr)->flags |= (MAYBE_NUM|SCALAR);
|
||||
|
||||
@ -624,20 +756,94 @@ load_environ()
|
||||
}
|
||||
/*
|
||||
* Put AWKPATH into ENVIRON if it's not there.
|
||||
* This allows querying it from outside gawk.
|
||||
* This allows querying it from within awk programs.
|
||||
*/
|
||||
if ((cp = getenv("AWKPATH")) == NULL) {
|
||||
aptr = assoc_lookup(ENVIRON_node, tmp_string("AWKPATH", 7));
|
||||
if (getenv("AWKPATH") == NULL) {
|
||||
aptr = assoc_lookup(ENVIRON_node, tmp_string("AWKPATH", 7), FALSE);
|
||||
*aptr = make_string(defpath, strlen(defpath));
|
||||
(*aptr)->flags |= SCALAR;
|
||||
}
|
||||
#endif /* TANDEM */
|
||||
}
|
||||
|
||||
/* load_procinfo --- populate the PROCINFO array */
|
||||
|
||||
void
|
||||
load_procinfo()
|
||||
{
|
||||
int i;
|
||||
NODE **aptr;
|
||||
char name[100];
|
||||
AWKNUM value;
|
||||
#if defined(NGROUPS_MAX) && NGROUPS_MAX > 0
|
||||
GETGROUPS_T groupset[NGROUPS_MAX];
|
||||
int ngroups;
|
||||
#endif
|
||||
|
||||
PROCINFO_node = install("PROCINFO",
|
||||
node(Nnull_string, Node_var, (NODE *) NULL));
|
||||
|
||||
#ifdef GETPGRP_VOID
|
||||
#define getpgrp_arg() /* nothing */
|
||||
#else
|
||||
#define getpgrp_arg() getpid()
|
||||
#endif
|
||||
|
||||
value = getpgrp(getpgrp_arg());
|
||||
aptr = assoc_lookup(PROCINFO_node, tmp_string("pgrpid", 6), FALSE);
|
||||
*aptr = make_number(value);
|
||||
|
||||
/*
|
||||
* could put a lot of this into a table, but then there's
|
||||
* portability problems declaring all the functions. so just
|
||||
* do it the slow and stupid way. sigh.
|
||||
*/
|
||||
|
||||
value = getpid();
|
||||
aptr = assoc_lookup(PROCINFO_node, tmp_string("pid", 3), FALSE);
|
||||
*aptr = make_number(value);
|
||||
|
||||
value = getppid();
|
||||
aptr = assoc_lookup(PROCINFO_node, tmp_string("ppid", 4), FALSE);
|
||||
*aptr = make_number(value);
|
||||
|
||||
value = getuid();
|
||||
aptr = assoc_lookup(PROCINFO_node, tmp_string("uid", 3), FALSE);
|
||||
*aptr = make_number(value);
|
||||
|
||||
value = geteuid();
|
||||
aptr = assoc_lookup(PROCINFO_node, tmp_string("euid", 4), FALSE);
|
||||
*aptr = make_number(value);
|
||||
|
||||
value = getgid();
|
||||
aptr = assoc_lookup(PROCINFO_node, tmp_string("gid", 3), FALSE);
|
||||
*aptr = make_number(value);
|
||||
|
||||
value = getegid();
|
||||
aptr = assoc_lookup(PROCINFO_node, tmp_string("egid", 4), FALSE);
|
||||
*aptr = make_number(value);
|
||||
|
||||
aptr = assoc_lookup(PROCINFO_node, tmp_string("FS", 2), FALSE);
|
||||
*aptr = make_string("FS", 2);
|
||||
|
||||
#if defined(NGROUPS_MAX) && NGROUPS_MAX > 0
|
||||
ngroups = getgroups(NGROUPS_MAX, groupset);
|
||||
if (ngroups == -1)
|
||||
fatal(_("could not find groups: %s"), strerror(errno));
|
||||
|
||||
for (i = 0; i < ngroups; i++) {
|
||||
sprintf(name, "group%d", i + 1);
|
||||
value = groupset[i];
|
||||
aptr = assoc_lookup(PROCINFO_node, tmp_string(name, strlen(name)), FALSE);
|
||||
*aptr = make_number(value);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* arg_assign --- process a command-line assignment */
|
||||
|
||||
char *
|
||||
arg_assign(arg)
|
||||
char *arg;
|
||||
arg_assign(char *arg)
|
||||
{
|
||||
char *cp, *cp2;
|
||||
int badvar;
|
||||
@ -651,18 +857,18 @@ char *arg;
|
||||
*cp++ = '\0';
|
||||
/* first check that the variable name has valid syntax */
|
||||
badvar = FALSE;
|
||||
if (! isalpha(arg[0]) && arg[0] != '_')
|
||||
if (! ISALPHA(arg[0]) && arg[0] != '_')
|
||||
badvar = TRUE;
|
||||
else
|
||||
for (cp2 = arg+1; *cp2; cp2++)
|
||||
if (! isalnum(*cp2) && *cp2 != '_') {
|
||||
if (! ISALNUM(*cp2) && *cp2 != '_') {
|
||||
badvar = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (badvar) {
|
||||
if (do_lint)
|
||||
warning("illegal name `%s' in variable assignment", arg);
|
||||
lintwarn(_("invalid syntax in name `%s' for variable assignment"), arg);
|
||||
*--cp = '='; /* restore original text of ARGV */
|
||||
return NULL;
|
||||
}
|
||||
@ -674,7 +880,7 @@ char *arg;
|
||||
it = make_str_node(cp, strlen(cp), SCAN);
|
||||
it->flags |= (MAYBE_NUM|SCALAR);
|
||||
var = variable(arg, FALSE, Node_var);
|
||||
lhs = get_lhs(var, &after_assign);
|
||||
lhs = get_lhs(var, &after_assign, FALSE);
|
||||
unref(*lhs);
|
||||
*lhs = it;
|
||||
if (after_assign != NULL)
|
||||
@ -687,35 +893,58 @@ char *arg;
|
||||
/* pre_assign --- handle -v, print a message and die if a problem */
|
||||
|
||||
static void
|
||||
pre_assign(v)
|
||||
char *v;
|
||||
pre_assign(char *v)
|
||||
{
|
||||
if (arg_assign(v) == NULL) {
|
||||
char *cp;
|
||||
/*
|
||||
* There is a problem when doing profiling. For -v x=y,
|
||||
* the variable x gets installed into the symbol table pointing
|
||||
* at the value in argv. This is what gets dumped. The string
|
||||
* ends up containing the full x=y, leading to stuff in the profile
|
||||
* of the form:
|
||||
*
|
||||
* if (x=y) ...
|
||||
*
|
||||
* Needless to say, this is gross, ugly and wrong. To fix, we
|
||||
* malloc a private copy of the storage that we can tweak to
|
||||
* our heart's content.
|
||||
*
|
||||
* This can't depend upon do_profiling; that variable isn't set up yet.
|
||||
* Sigh.
|
||||
*/
|
||||
|
||||
emalloc(cp, char *, strlen(v) + 1, "pre_assign");
|
||||
strcpy(cp, v);
|
||||
|
||||
if (arg_assign(cp) == NULL) {
|
||||
fprintf(stderr,
|
||||
"%s: `%s' argument to `-v' not in `var=value' form\n",
|
||||
myname, v);
|
||||
usage(1, stderr);
|
||||
}
|
||||
|
||||
cp = strchr(cp, '=');
|
||||
assert(cp);
|
||||
*cp = '\0';
|
||||
}
|
||||
|
||||
/* catchsig --- catch signals */
|
||||
|
||||
RETSIGTYPE
|
||||
catchsig(sig, code)
|
||||
int sig, code;
|
||||
catchsig(int sig, int code)
|
||||
{
|
||||
#ifdef lint
|
||||
code = 0; sig = code; code = sig;
|
||||
#endif
|
||||
if (sig == SIGFPE) {
|
||||
fatal("floating point exception");
|
||||
fatal(_("floating point exception"));
|
||||
} else if (sig == SIGSEGV
|
||||
#ifdef SIGBUS
|
||||
|| sig == SIGBUS
|
||||
#endif
|
||||
) {
|
||||
set_loc(__FILE__, __LINE__);
|
||||
msg("fatal error: internal error");
|
||||
msg(_("fatal error: internal error"));
|
||||
/* fatal won't abort() if not compiled for debugging */
|
||||
abort();
|
||||
} else
|
||||
@ -728,7 +957,12 @@ int sig, code;
|
||||
static void
|
||||
nostalgia()
|
||||
{
|
||||
/*
|
||||
* N.B.: This string is not gettextized, on purpose.
|
||||
* So there.
|
||||
*/
|
||||
fprintf(stderr, "awk: bailing out near line 1\n");
|
||||
fflush(stderr);
|
||||
abort();
|
||||
}
|
||||
|
||||
@ -745,3 +979,28 @@ version()
|
||||
copyleft();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* init_fds --- check for 0, 1, 2, open on /dev/null if possible */
|
||||
|
||||
static void
|
||||
init_fds()
|
||||
{
|
||||
struct stat sbuf;
|
||||
int fd;
|
||||
int newfd;
|
||||
|
||||
/* maybe no stderr, don't bother with error mesg */
|
||||
for (fd = 0; fd <= 2; fd++) {
|
||||
if (fstat(fd, &sbuf) < 0) {
|
||||
#if MAKE_A_HEROIC_EFFORT
|
||||
if (do_lint)
|
||||
lintwarn(_("no pre-opened fd %d"), fd);
|
||||
#endif
|
||||
newfd = devopen("/dev/null", "r+");
|
||||
#ifdef MAKE_A_HEROIC_EFFORT
|
||||
if (do_lint && newfd < 0)
|
||||
lintwarn(_("could not pre-open /dev/null for fd %d"), fd);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 1986, 1988, 1989, 1991-2000 the Free Software Foundation, Inc.
|
||||
* Copyright (C) 1986, 1988, 1989, 1991-2001 the Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GAWK, the GNU implementation of the
|
||||
* AWK Programming Language.
|
||||
@ -30,8 +30,7 @@
|
||||
/* r_force_number --- force a value to be numeric */
|
||||
|
||||
AWKNUM
|
||||
r_force_number(n)
|
||||
register NODE *n;
|
||||
r_force_number(register NODE *n)
|
||||
{
|
||||
register char *cp;
|
||||
register char *cpend;
|
||||
@ -40,7 +39,7 @@ register NODE *n;
|
||||
unsigned int newflags;
|
||||
extern double strtod();
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef GAWKDEBUG
|
||||
if (n == NULL)
|
||||
cant_happen();
|
||||
if (n->type != Node_val)
|
||||
@ -55,19 +54,29 @@ register NODE *n;
|
||||
|
||||
n->numbr = 0.0;
|
||||
n->flags |= NUM;
|
||||
n->flags &= ~UNINITIALIZED;
|
||||
|
||||
if (n->stlen == 0)
|
||||
if (n->stlen == 0) {
|
||||
if (0 && do_lint)
|
||||
lintwarn(_("can't convert string to float"));
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
cp = n->stptr;
|
||||
if (ISALPHA(*cp))
|
||||
if (ISALPHA(*cp)) {
|
||||
if (0 && do_lint)
|
||||
lintwarn(_("can't convert string to float"));
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
cpend = cp + n->stlen;
|
||||
while (cp < cpend && isspace(*cp))
|
||||
while (cp < cpend && ISSPACE(*cp))
|
||||
cp++;
|
||||
if (cp == cpend || isalpha(*cp))
|
||||
if (cp == cpend || ISALPHA(*cp)) {
|
||||
if (0 && do_lint)
|
||||
lintwarn(_("can't convert string to float"));
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (n->flags & MAYBE_NUM) {
|
||||
newflags = NUMBER;
|
||||
@ -78,17 +87,18 @@ register NODE *n;
|
||||
if (ISDIGIT(*cp)) {
|
||||
n->numbr = (AWKNUM)(*cp - '0');
|
||||
n->flags |= newflags;
|
||||
}
|
||||
} else if (0 && do_lint)
|
||||
lintwarn(_("can't convert string to float"));
|
||||
return n->numbr;
|
||||
}
|
||||
|
||||
#ifdef NONDECDATA
|
||||
errno = 0;
|
||||
if (! do_traditional && isnondecimal(cp)) {
|
||||
n->numbr = nondec2awknum(cp, cpend - cp);
|
||||
goto finish;
|
||||
if (do_non_decimal_data) {
|
||||
errno = 0;
|
||||
if (! do_traditional && isnondecimal(cp)) {
|
||||
n->numbr = nondec2awknum(cp, cpend - cp);
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
#endif /* NONDECDATA */
|
||||
|
||||
errno = 0;
|
||||
save = *cpend;
|
||||
@ -101,10 +111,13 @@ register NODE *n;
|
||||
*cpend = save;
|
||||
finish:
|
||||
/* the >= should be ==, but for SunOS 3.5 strtod() */
|
||||
if (errno == 0 && ptr >= cpend)
|
||||
if (errno == 0 && ptr >= cpend) {
|
||||
n->flags |= newflags;
|
||||
else
|
||||
} else {
|
||||
if (0 && do_lint && ptr < cpend)
|
||||
lintwarn(_("can't convert string to float"));
|
||||
errno = 0;
|
||||
}
|
||||
|
||||
return n->numbr;
|
||||
}
|
||||
@ -131,14 +144,23 @@ static const char *values[] = {
|
||||
/* format_val --- format a numeric value based on format */
|
||||
|
||||
NODE *
|
||||
format_val(format, index, s)
|
||||
char *format;
|
||||
int index;
|
||||
register NODE *s;
|
||||
format_val(char *format, int index, register NODE *s)
|
||||
{
|
||||
char buf[128];
|
||||
char buf[BUFSIZ];
|
||||
register char *sp = buf;
|
||||
double val;
|
||||
char *orig, *trans, save;
|
||||
|
||||
if (! do_traditional && (s->flags & INTLSTR) != 0) {
|
||||
save = s->stptr[s->stlen];
|
||||
s->stptr[s->stlen] = '\0';
|
||||
|
||||
orig = s->stptr;
|
||||
trans = dgettext(TEXTDOMAIN, orig);
|
||||
|
||||
s->stptr[s->stlen] = save;
|
||||
return tmp_string(trans, strlen(trans));
|
||||
}
|
||||
|
||||
/* not an integral value, or out of range */
|
||||
if ((val = double_to_int(s->numbr)) != s->numbr
|
||||
@ -155,16 +177,16 @@ register NODE *s;
|
||||
|
||||
NODE *dummy, *r;
|
||||
unsigned short oflags;
|
||||
extern NODE *format_tree P((const char *, int, NODE *));
|
||||
extern NODE **fmt_list; /* declared in eval.c */
|
||||
|
||||
/* create dummy node for a sole use of format_tree */
|
||||
getnode(dummy);
|
||||
dummy->type = Node_expression_list;
|
||||
dummy->lnode = s;
|
||||
dummy->rnode = NULL;
|
||||
oflags = s->flags;
|
||||
s->flags |= PERM; /* prevent from freeing by format_tree() */
|
||||
r = format_tree(format, fmt_list[index]->stlen, dummy);
|
||||
r = format_tree(format, fmt_list[index]->stlen, dummy, 2);
|
||||
s->flags = oflags;
|
||||
s->stfmt = (char) index;
|
||||
s->stlen = r->stlen;
|
||||
@ -191,24 +213,21 @@ register NODE *s;
|
||||
no_malloc:
|
||||
s->stref = 1;
|
||||
s->flags |= STR;
|
||||
s->flags &= ~UNINITIALIZED;
|
||||
return s;
|
||||
}
|
||||
|
||||
/* r_force_string --- force a value to be a string */
|
||||
|
||||
NODE *
|
||||
r_force_string(s)
|
||||
register NODE *s;
|
||||
r_force_string(register NODE *s)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
NODE *ret;
|
||||
#ifdef GAWKDEBUG
|
||||
if (s == NULL)
|
||||
cant_happen();
|
||||
if (s->type != Node_val)
|
||||
cant_happen();
|
||||
/*
|
||||
if ((s->flags & NUM) == 0)
|
||||
cant_happen();
|
||||
*/
|
||||
if (s->stref <= 0)
|
||||
cant_happen();
|
||||
if ((s->flags & STR) != 0
|
||||
@ -216,7 +235,8 @@ register NODE *s;
|
||||
return s;
|
||||
#endif
|
||||
|
||||
return format_val(CONVFMT, CONVFMTidx, s);
|
||||
ret = format_val(CONVFMT, CONVFMTidx, s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -226,8 +246,7 @@ register NODE *s;
|
||||
*/
|
||||
|
||||
NODE *
|
||||
dupnode(n)
|
||||
NODE *n;
|
||||
dupnode(NODE *n)
|
||||
{
|
||||
register NODE *r;
|
||||
|
||||
@ -236,6 +255,8 @@ NODE *n;
|
||||
n->flags |= MALLOC;
|
||||
return n;
|
||||
}
|
||||
if ((n->flags & PERM) != 0)
|
||||
return n;
|
||||
if ((n->flags & (MALLOC|STR)) == (MALLOC|STR)) {
|
||||
if (n->stref < LONG_MAX)
|
||||
n->stref++;
|
||||
@ -254,12 +275,26 @@ NODE *n;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* copy_node --- force a brand new copy of a node to be allocated */
|
||||
|
||||
NODE *
|
||||
copynode(NODE *old)
|
||||
{
|
||||
NODE *new;
|
||||
int saveflags;
|
||||
|
||||
assert(old != NULL);
|
||||
saveflags = old->flags;
|
||||
old->flags &= ~(MALLOC|PERM);
|
||||
new = dupnode(old);
|
||||
old->flags = saveflags;
|
||||
return new;
|
||||
}
|
||||
|
||||
/* mk_number --- allocate a node with defined number */
|
||||
|
||||
NODE *
|
||||
mk_number(x, flags)
|
||||
AWKNUM x;
|
||||
unsigned int flags;
|
||||
mk_number(AWKNUM x, unsigned int flags)
|
||||
{
|
||||
register NODE *r;
|
||||
|
||||
@ -267,7 +302,7 @@ unsigned int flags;
|
||||
r->type = Node_val;
|
||||
r->numbr = x;
|
||||
r->flags = flags | SCALAR;
|
||||
#ifdef DEBUG
|
||||
#ifdef GAWKDEBUG
|
||||
r->stref = 1;
|
||||
r->stptr = NULL;
|
||||
r->stlen = 0;
|
||||
@ -278,10 +313,7 @@ unsigned int flags;
|
||||
/* make_str_node --- make a string node */
|
||||
|
||||
NODE *
|
||||
make_str_node(s, len, flags)
|
||||
char *s;
|
||||
size_t len;
|
||||
int flags;
|
||||
make_str_node(char *s, size_t len, int flags)
|
||||
{
|
||||
register NODE *r;
|
||||
|
||||
@ -309,7 +341,7 @@ int flags;
|
||||
c = parse_escape(&pf);
|
||||
if (c < 0) {
|
||||
if (do_lint)
|
||||
warning("backslash at end of string");
|
||||
lintwarn(_("backslash at end of string"));
|
||||
c = '\\';
|
||||
}
|
||||
*ptm++ = c;
|
||||
@ -331,9 +363,7 @@ int flags;
|
||||
/* tmp_string --- allocate a temporary string */
|
||||
|
||||
NODE *
|
||||
tmp_string(s, len)
|
||||
char *s;
|
||||
size_t len;
|
||||
tmp_string(char *s, size_t len)
|
||||
{
|
||||
register NODE *r;
|
||||
|
||||
@ -354,9 +384,13 @@ more_nodes()
|
||||
register NODE *np;
|
||||
|
||||
/* get more nodes and initialize list */
|
||||
emalloc(nextfree, NODE *, NODECHUNK * sizeof(NODE), "newnode");
|
||||
emalloc(nextfree, NODE *, NODECHUNK * sizeof(NODE), "more_nodes");
|
||||
for (np = nextfree; np <= &nextfree[NODECHUNK - 1]; np++) {
|
||||
np->flags = 0;
|
||||
np->flags |= UNINITIALIZED;
|
||||
#ifndef NO_PROFILING
|
||||
np->exec_count = 0;
|
||||
#endif
|
||||
np->nextp = np + 1;
|
||||
}
|
||||
--np;
|
||||
@ -366,37 +400,40 @@ more_nodes()
|
||||
return np;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef MEMDEBUG
|
||||
#undef freenode
|
||||
/* freenode --- release a node back to the pool */
|
||||
|
||||
void
|
||||
freenode(it)
|
||||
NODE *it;
|
||||
freenode(NODE *it)
|
||||
{
|
||||
it->flags &= ~SCALAR;
|
||||
it->flags |= UNINITIALIZED;
|
||||
#ifdef MPROF
|
||||
it->stref = 0;
|
||||
free((char *) it);
|
||||
#else /* not MPROF */
|
||||
#ifndef NO_PROFILING
|
||||
it->exec_count = 0;
|
||||
#endif
|
||||
/* add it to head of freelist */
|
||||
it->nextp = nextfree;
|
||||
nextfree = it;
|
||||
#endif /* not MPROF */
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
#endif /* GAWKDEBUG */
|
||||
|
||||
/* unref --- remove reference to a particular node */
|
||||
|
||||
void
|
||||
unref(tmp)
|
||||
register NODE *tmp;
|
||||
unref(register NODE *tmp)
|
||||
{
|
||||
if (tmp == NULL)
|
||||
return;
|
||||
if ((tmp->flags & PERM) != 0)
|
||||
return;
|
||||
if ((tmp->flags & (MALLOC|TEMP)) != 0) {
|
||||
tmp->flags &= ~TEMP;
|
||||
tmp->flags &= ~TEMP;
|
||||
if ((tmp->flags & MALLOC) != 0) {
|
||||
if ((tmp->flags & STR) != 0) {
|
||||
if (tmp->stref > 1) {
|
||||
if (tmp->stref != LONG_MAX)
|
||||
@ -434,8 +471,7 @@ register NODE *tmp;
|
||||
*/
|
||||
|
||||
int
|
||||
parse_escape(string_ptr)
|
||||
char **string_ptr;
|
||||
parse_escape(char **string_ptr)
|
||||
{
|
||||
register int c = *(*string_ptr)++;
|
||||
register int i;
|
||||
@ -487,13 +523,13 @@ char **string_ptr;
|
||||
|
||||
if (! didwarn) {
|
||||
didwarn = TRUE;
|
||||
warning("POSIX does not allow \"\\x\" escapes");
|
||||
lintwarn(_("POSIX does not allow `\\x' escapes"));
|
||||
}
|
||||
}
|
||||
if (do_posix)
|
||||
return ('x');
|
||||
if (! isxdigit((*string_ptr)[0])) {
|
||||
warning("no hex digits in \\x escape sequence");
|
||||
if (! ISXDIGIT((*string_ptr)[0])) {
|
||||
warning(_("no hex digits in `\\x' escape sequence"));
|
||||
return ('x');
|
||||
}
|
||||
i = 0;
|
||||
@ -514,19 +550,22 @@ char **string_ptr;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
case '\\':
|
||||
case '"':
|
||||
return c;
|
||||
default:
|
||||
if (do_lint) {
|
||||
static short warned[256];
|
||||
unsigned char uc = (unsigned char) c;
|
||||
{
|
||||
static short warned[256];
|
||||
unsigned char uc = (unsigned char) c;
|
||||
|
||||
/* N.B.: use unsigned char here to avoid Latin-1 problems */
|
||||
/* N.B.: use unsigned char here to avoid Latin-1 problems */
|
||||
|
||||
if (! warned[uc]) {
|
||||
warned[uc] = TRUE;
|
||||
if (! warned[uc]) {
|
||||
warned[uc] = TRUE;
|
||||
|
||||
warning("escape sequence `\\%c' treated as plain `%c'", uc, uc);
|
||||
}
|
||||
warning(_("escape sequence `\\%c' treated as plain `%c'"), uc, uc);
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user