summaryrefslogtreecommitdiffstats
path: root/contrib/awk
diff options
context:
space:
mode:
authorsheldonh <sheldonh@FreeBSD.org>1999-09-27 08:57:04 +0000
committersheldonh <sheldonh@FreeBSD.org>1999-09-27 08:57:04 +0000
commitfd12515e9fc4be7176fa5d58edeef092e5b4e09d (patch)
tree8e801099997d6dd9285e5794abcda7b7cdfdd155 /contrib/awk
parentb54765f9845daf3cf7b91b9709780162d1a3e9f3 (diff)
downloadFreeBSD-src-fd12515e9fc4be7176fa5d58edeef092e5b4e09d.zip
FreeBSD-src-fd12515e9fc4be7176fa5d58edeef092e5b4e09d.tar.gz
Fix conflicts. Add $FreeBSD$ as needed.
Diffstat (limited to 'contrib/awk')
-rw-r--r--contrib/awk/awk.h16
-rw-r--r--contrib/awk/builtin.c111
-rw-r--r--contrib/awk/doc/awk.117
-rw-r--r--contrib/awk/eval.c78
-rw-r--r--contrib/awk/field.c68
-rw-r--r--contrib/awk/io.c105
-rw-r--r--contrib/awk/main.c10
-rw-r--r--contrib/awk/node.c33
8 files changed, 297 insertions, 141 deletions
diff --git a/contrib/awk/awk.h b/contrib/awk/awk.h
index 3ab2015..621a981 100644
--- a/contrib/awk/awk.h
+++ b/contrib/awk/awk.h
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-1997 the Free Software Foundation, Inc.
+ * Copyright (C) 1986, 1988, 1989, 1991-1999 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -21,10 +21,20 @@
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $FreeBSD$
*/
/* ------------------------------ Includes ------------------------------ */
+/*
+ * config.h absolutely, positively, *M*U*S*T* be included before
+ * any system headers. Otherwise, extreme death, destruction
+ * and loss of life results.
+ *
+ * Well, OK, gawk just won't work on systems using egcs and LFS. But
+ * that's almost as bad.
+ */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -34,6 +44,7 @@
#endif /* _GNU_SOURCE */
#include <stdio.h>
+#include <assert.h>
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif /* HAVE_LIMITS_H */
@@ -588,7 +599,8 @@ extern char casetable[]; /* for case-independent regexp matching */
/* ------------------------- Pseudo-functions ------------------------- */
#define is_identchar(c) (isalnum(c) || (c) == '_')
-#define isnondecimal(str) (((str)[0]) == '0')
+#define isnondecimal(str) (((str)[0]) == '0' && (ISDIGIT((str)[1]) \
+ || (str)[1] == 'x' || (str)[1] == 'X'))
#ifdef MPROF
#define getnode(n) emalloc(n, NODE *, sizeof(NODE), "getnode")
diff --git a/contrib/awk/builtin.c b/contrib/awk/builtin.c
index dc2c1d3..0fee054 100644
--- a/contrib/awk/builtin.c
+++ b/contrib/awk/builtin.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-1997 the Free Software Foundation, Inc.
+ * Copyright (C) 1986, 1988, 1989, 1991-1999 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -21,11 +21,12 @@
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $FreeBSD$
*/
#include "awk.h"
-#include <assert.h>
#undef HUGE
#undef CHARBITS
#undef INTBITS
@@ -410,6 +411,7 @@ register NODE *carg;
double tmpval;
char signchar = FALSE;
size_t len;
+ int zero_flag = FALSE;
static char sp[] = " ";
static char zero_string[] = "0";
static char lchbuf[] = "0123456789abcdef";
@@ -437,6 +439,7 @@ register NODE *carg;
prec = 0;
have_prec = FALSE;
signchar = FALSE;
+ zero_flag = FALSE;
lj = alt = big = bigbig = small = FALSE;
fill = sp;
cp = cend;
@@ -460,10 +463,9 @@ check_pos:
break;
case '0':
+ zero_flag = TRUE;
if (lj)
goto retry;
- if (cur == &fw)
- fill = zero_string;
/* FALL through */
case '1':
case '2':
@@ -587,6 +589,8 @@ check_pos:
goto retry;
case 'c':
need_format = FALSE;
+ if (zero_flag && ! lj)
+ fill = zero_string;
parse_next_arg();
/* user input that looks numeric is numeric */
if ((arg->flags & (MAYBE_NUM|NUMBER)) == MAYBE_NUM)
@@ -611,6 +615,8 @@ check_pos:
goto pr_tail;
case 's':
need_format = FALSE;
+ if (zero_flag && ! lj)
+ fill = zero_string;
parse_next_arg();
arg = force_string(arg);
if (! have_prec || prec > arg->stlen)
@@ -622,6 +628,14 @@ check_pos:
need_format = FALSE;
parse_next_arg();
tmpval = force_number(arg);
+
+ /*
+ * ``The result of converting a zero value with a
+ * precision of zero is no characters.''
+ */
+ if (have_prec && prec == 0 && tmpval == 0)
+ goto pr_tail;
+
if (tmpval < 0) {
if (tmpval < LONG_MIN)
goto out_of_range;
@@ -639,17 +653,28 @@ check_pos:
*--cp = (char) ('0' + uval % 10);
uval /= 10;
} while (uval > 0);
+
+ /* add more output digits to match the precision */
+ if (have_prec) {
+ while (cend - cp < prec)
+ *--cp = '0';
+ }
+
if (sgn)
*--cp = '-';
else if (signchar)
*--cp = signchar;
/*
- * precision overrides '0' flags. however, for
- * integer formats, precsion is minimum number of
- * *digits*, not characters, thus we want to fill
- * with zeroes.
+ * When to fill with zeroes is of course not simple.
+ * First: No zero fill if left-justifying.
+ * Next: There seem to be two cases:
+ * A '0' without a precision, e.g. %06d
+ * A precision with no field width, e.g. %.10d
+ * Any other case, we don't want to fill with zeroes.
*/
- if (have_prec)
+ if (! lj
+ && ((zero_flag && ! have_prec)
+ || (fw == 0 && have_prec)))
fill = zero_string;
if (prec > fw)
fw = prec;
@@ -673,6 +698,22 @@ check_pos:
need_format = FALSE;
parse_next_arg();
tmpval = force_number(arg);
+
+ /*
+ * ``The result of converting a zero value with a
+ * precision of zero is no characters.''
+ *
+ * If I remember the ANSI C standard, though,
+ * it says that for octal conversions
+ * the precision is artificially increased
+ * to add an extra 0 if # is supplied.
+ * Indeed, in C,
+ * printf("%#.0o\n", 0);
+ * prints a single 0.
+ */
+ if (! alt && have_prec && prec == 0 && tmpval == 0)
+ goto pr_tail;
+
if (tmpval < 0) {
if (tmpval < LONG_MIN)
goto out_of_range;
@@ -685,18 +726,29 @@ check_pos:
uval = (unsigned long) tmpval;
}
/*
- * precision overrides '0' flags. however, for
- * integer formats, precsion is minimum number of
- * *digits*, not characters, thus we want to fill
- * with zeroes.
+ * When to fill with zeroes is of course not simple.
+ * First: No zero fill if left-justifying.
+ * Next: There seem to be two cases:
+ * A '0' without a precision, e.g. %06d
+ * A precision with no field width, e.g. %.10d
+ * Any other case, we don't want to fill with zeroes.
*/
- if (have_prec)
+ if (! lj
+ && ((zero_flag && ! have_prec)
+ || (fw == 0 && have_prec)))
fill = zero_string;
do {
*--cp = chbuf[uval % base];
uval /= base;
} while (uval > 0);
- if (alt) {
+
+ /* add more output digits to match the precision */
+ if (have_prec) {
+ while (cend - cp < prec)
+ *--cp = '0';
+ }
+
+ if (alt && tmpval != 0) {
if (base == 16) {
*--cp = cs1;
*--cp = '0';
@@ -755,7 +807,7 @@ check_pos:
*cp++ = signchar;
if (alt)
*cp++ = '#';
- if (fill != sp)
+ if (zero_flag)
*cp++ = '0';
cp = strcpy(cp, "*.*") + 3;
*cp++ = cs1;
@@ -1084,6 +1136,7 @@ register NODE *tree;
register FILE *fp;
int numnodes, i;
NODE *save;
+ NODE *tval;
if (tree->rnode) {
int errflg; /* not used, sigh */
@@ -1117,25 +1170,29 @@ register NODE *tree;
t[i] = dupnode(n);
free_temp(n);
- if (t[i]->flags & NUMBER) {
+ if ((t[i]->flags & (NUMBER|STRING)) == NUMBER) {
if (OFMTidx == CONVFMTidx)
(void) force_string(t[i]);
- else
- t[i] = format_val(OFMT, OFMTidx, t[i]);
+ else {
+ tval = tmp_number(t[i]->numbr);
+ unref(t[i]);
+ t[i] = format_val(OFMT, OFMTidx, tval);
+ }
}
}
for (i = 0; i < numnodes; i++) {
efwrite(t[i]->stptr, sizeof(char), t[i]->stlen, fp, "print", rp, FALSE);
unref(t[i]);
- if (i != numnodes - 1) {
- if (OFSlen > 0)
- efwrite(OFS, sizeof(char), (size_t) OFSlen,
- fp, "print", rp, FALSE);
- }
+
+ if (i != numnodes - 1 && OFSlen > 0)
+ efwrite(OFS, sizeof(char), (size_t) OFSlen,
+ fp, "print", rp, FALSE);
+
}
if (ORSlen > 0)
efwrite(ORS, sizeof(char), (size_t) ORSlen, fp, "print", rp, TRUE);
+
free(t);
}
@@ -1512,6 +1569,7 @@ int how_many, backdigs;
*/
if (lastmatchnonzero && matchstart == matchend) {
lastmatchnonzero = FALSE;
+ matches--;
goto empty;
}
/*
@@ -2022,6 +2080,7 @@ size_t len;
case 'c':
case 'd':
case 'e':
+ case 'f':
val = *str - 'a' + 10;
break;
case 'A':
@@ -2029,6 +2088,7 @@ size_t len;
case 'C':
case 'D':
case 'E':
+ case 'F':
val = *str - 'A' + 10;
break;
default:
@@ -2039,11 +2099,12 @@ size_t len;
} else if (*str == '0') {
for (; len > 0; len--) {
if (! isdigit(*str) || *str == '8' || *str == '9')
- goto done;
+ goto decimal;
retval = (retval * 8) + (*str - '0');
str++;
}
} else {
+decimal:
save = str[len];
retval = atof(str);
str[len] = save;
diff --git a/contrib/awk/doc/awk.1 b/contrib/awk/doc/awk.1
index 6be430a..807f79f 100644
--- a/contrib/awk/doc/awk.1
+++ b/contrib/awk/doc/awk.1
@@ -1,7 +1,8 @@
+.\" $FreeBSD$
.ds PX \s-1POSIX\s+1
.ds UX \s-1UNIX\s+1
.ds AN \s-1ANSI\s+1
-.TH GAWK 1 "Dec 19 1996" "Free Software Foundation" "Utility Commands"
+.TH GAWK 1 "Apr 28 1999" "Free Software Foundation" "Utility Commands"
.SH NAME
gawk \- pattern scanning and processing language
.SH SYNOPSIS
@@ -2150,6 +2151,12 @@ Functions may call each other and may be recursive.
Function parameters used as local variables are initialized
to the null string and the number zero upon function invocation.
.PP
+Use
+.BI return " expr"
+to return a value from a function. The return value is undefined if no
+value is provided, or if the function returns by ``falling off'' the
+end.
+.PP
If
.B \-\^\-lint
has been provided,
@@ -2535,7 +2542,7 @@ and the effort to do so really is not worth it.
.SH VERSION INFORMATION
This man page documents
.IR gawk ,
-version 3.0.2.
+version 3.0.4.
.SH AUTHORS
The original version of \*(UX
.I awk
@@ -2566,10 +2573,10 @@ help from Darrel Hankerson. Fred Fish supplied support for the Amiga.
If you find a bug in
.IR gawk ,
please send electronic mail to
-.BR bug-gnu-utils@prep.ai.mit.edu ,
+.BR bug-gnu-utils@gnu.org ,
.I with
a carbon copy to
-.BR arnold@gnu.ai.mit.edu .
+.BR arnold@gnu.org .
Please include your operating system and its revision, the version of
.IR gawk ,
what C compiler you used to compile it, and a test program
@@ -2598,7 +2605,7 @@ Brian Kernighan of Bell Labs
provided valuable assistance during testing and debugging.
We thank him.
.SH COPYING PERMISSIONS
-Copyright \(co\) 1996 Free Software Foundation, Inc.
+Copyright \(co) 1996,97,98,99 Free Software Foundation, Inc.
.PP
Permission is granted to make and distribute verbatim copies of
this manual page provided the copyright notice and this permission
diff --git a/contrib/awk/eval.c b/contrib/awk/eval.c
index aa2e881..37c5fef 100644
--- a/contrib/awk/eval.c
+++ b/contrib/awk/eval.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-1997 the Free Software Foundation, Inc.
+ * Copyright (C) 1986, 1988, 1989, 1991-1999 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -21,12 +21,12 @@
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $FreeBSD$
*/
#include "awk.h"
-#include <assert.h>
-
extern double pow P((double x, double y));
extern double modf P((double x, double *yp));
extern double fmod P((double x, double y));
@@ -566,14 +566,26 @@ register NODE *volatile tree;
break;
case Node_K_next:
+ if (in_begin_rule)
+ fatal("`next' cannot be called from a BEGIN rule");
+ else if (in_end_rule)
+ fatal("`next' cannot be called from an END rule");
+
if (in_function())
pop_fcall_stack();
+
longjmp(rule_tag, TAG_CONTINUE);
break;
case Node_K_nextfile:
+ if (in_begin_rule)
+ fatal("`nextfile' cannot be called from a BEGIN rule");
+ else if (in_end_rule)
+ fatal("`nextfile' cannot be called from an END rule");
+
if (in_function())
pop_fcall_stack();
+
do_nextfile();
break;
@@ -759,7 +771,8 @@ int iscond;
register size_t len;
char *str;
register char *dest;
- int count;
+ int alloc_count, str_count;
+ int i;
/*
* This is an efficiency hack for multiple adjacent string
@@ -773,16 +786,16 @@ int iscond;
/*
* But first, no arbitrary limits. Count the number of
* nodes and malloc the treelist and strlist arrays.
- * There will be count + 1 items to concatenate. We
+ * There will be alloc_count + 1 items to concatenate. We
* also leave room for an extra pointer at the end to
- * use as a sentinel. Thus, start count at 2.
+ * use as a sentinel. Thus, start alloc_count at 2.
*/
save_tree = tree;
- for (count = 2; tree && tree->type == Node_concat; tree = tree->lnode)
- count++;
+ for (alloc_count = 2; tree && tree->type == Node_concat; tree = tree->lnode)
+ alloc_count++;
tree = save_tree;
- emalloc(treelist, NODE **, sizeof(NODE *) * count, "tree_eval");
- emalloc(strlist, NODE **, sizeof(NODE *) * count, "tree_eval");
+ emalloc(treelist, NODE **, sizeof(NODE *) * alloc_count, "tree_eval");
+ emalloc(strlist, NODE **, sizeof(NODE *) * alloc_count, "tree_eval");
/* Now, here we go. */
treep = treelist;
@@ -795,15 +808,26 @@ int iscond;
* Now, evaluate to strings in LIFO order, accumulating
* the string length, so we can do a single malloc at the
* end.
+ *
+ * Evaluate the expressions first, then get their
+ * lengthes, in case one of the expressions has a
+ * side effect that changes one of the others.
+ * See test/nasty.awk.
*/
strp = strlist;
len = 0;
while (treep >= treelist) {
*strp = force_string(tree_eval(*treep--));
- len += (*strp)->stlen;
strp++;
}
*strp = NULL;
+
+ str_count = strp - strlist;
+ strp = strlist;
+ for (i = 0; i < str_count; i++) {
+ len += (*strp)->stlen;
+ strp++;
+ }
emalloc(str, char *, len+2, "tree_eval");
str[len] = str[len+1] = '\0'; /* for good measure */
dest = str;
@@ -1397,6 +1421,11 @@ NODE *arg_list; /* Node_expression_list of calling args. */
* r_get_lhs:
* This returns a POINTER to a node pointer. get_lhs(ptr) is the current
* value of the var, or where to store the var's new value
+ *
+ * For the special variables, don't unref their current value if it's
+ * the same as the internal copy; perhaps the current one is used in
+ * a concatenation or some other expression somewhere higher up in the
+ * call chain. Ouch.
*/
NODE **
@@ -1409,8 +1438,11 @@ Func_ptr *assign;
if (assign)
*assign = NULL; /* for safety */
- if (ptr->type == Node_param_list)
+ if (ptr->type == Node_param_list) {
+ if ((ptr->flags & FUNC) != 0)
+ fatal("can't use function name `%s' as variable or array", ptr->vname);
ptr = stack_ptr[ptr->param_cnt];
+ }
switch (ptr->type) {
case Node_var_array:
@@ -1444,26 +1476,32 @@ Func_ptr *assign;
break;
case Node_FNR:
- unref(FNR_node->var_value);
- FNR_node->var_value = make_number((AWKNUM) FNR);
+ if (FNR_node->var_value->numbr != FNR) {
+ unref(FNR_node->var_value);
+ FNR_node->var_value = make_number((AWKNUM) FNR);
+ }
aptr = &(FNR_node->var_value);
if (assign != NULL)
*assign = set_FNR;
break;
case Node_NR:
- unref(NR_node->var_value);
- NR_node->var_value = make_number((AWKNUM) NR);
+ if (NR_node->var_value->numbr != NR) {
+ unref(NR_node->var_value);
+ NR_node->var_value = make_number((AWKNUM) NR);
+ }
aptr = &(NR_node->var_value);
if (assign != NULL)
*assign = set_NR;
break;
case Node_NF:
- if (NF == -1)
- (void) get_field(HUGE-1, assign); /* parse record */
- unref(NF_node->var_value);
- NF_node->var_value = make_number((AWKNUM) NF);
+ if (NF == -1 || NF_node->var_value->numbr != NF) {
+ if (NF == -1)
+ (void) get_field(HUGE-1, assign); /* parse record */
+ unref(NF_node->var_value);
+ NF_node->var_value = make_number((AWKNUM) NF);
+ }
aptr = &(NF_node->var_value);
if (assign != NULL)
*assign = set_NF;
diff --git a/contrib/awk/field.c b/contrib/awk/field.c
index 31c9628..72cbd78 100644
--- a/contrib/awk/field.c
+++ b/contrib/awk/field.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-1997 the Free Software Foundation, Inc.
+ * Copyright (C) 1986, 1988, 1989, 1991-1999 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -21,10 +21,11 @@
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $FreeBSD$
*/
#include "awk.h"
-#include <assert.h>
typedef void (* Setfunc) P((long, char *, long, NODE *));
@@ -63,6 +64,9 @@ int default_FS; /* TRUE when FS == " " */
Regexp *FS_regexp = NULL;
static NODE *Null_field = NULL;
+/* using_FIELDWIDTHS --- static function, macro to avoid overhead */
+#define using_FIELDWIDTHS() (parse_field == fw_parse_field)
+
/* init_fields --- set up the fields array to start with */
void
@@ -140,7 +144,6 @@ rebuild_record()
char *ops;
register char *cops;
long i;
- char *f0start, *f0end;
assert(NF != -1);
@@ -184,15 +187,27 @@ rebuild_record()
* any fields that still point into it, and have them point
* into the new field zero.
*/
- f0start = fields_arr[0]->stptr;
- f0end = fields_arr[0]->stptr + fields_arr[0]->stlen;
for (cops = ops, i = 1; i <= NF; i++) {
- char *field_data = fields_arr[i]->stptr;
-
- if (fields_arr[i]->stlen > 0
- && f0start <= field_data && field_data < f0end)
- fields_arr[i]->stptr = cops;
+ if (fields_arr[i]->stlen > 0) {
+ NODE *n;
+ getnode(n);
+
+ if ((fields_arr[i]->flags & FIELD) == 0) {
+ *n = *Null_field;
+ n->stlen = fields_arr[i]->stlen;
+ if ((fields_arr[i]->flags & (NUM|NUMBER)) != 0) {
+ n->flags |= (fields_arr[i]->flags & (NUM|NUMBER));
+ n->numbr = fields_arr[i]->numbr;
+ }
+ } else {
+ *n = *(fields_arr[i]);
+ n->flags &= ~(MALLOC|TEMP|PERM|STRING);
+ }
+ n->stptr = cops;
+ unref(fields_arr[i]);
+ fields_arr[i] = n;
+ }
cops += fields_arr[i]->stlen + ofslen;
}
@@ -751,7 +766,7 @@ NODE *tree;
arr->type = Node_var_array;
assoc_clear(arr);
- if (sep->re_flags & FS_DFLT) {
+ if ((sep->re_flags & FS_DFLT) != 0 && ! using_FIELDWIDTHS()) {
parseit = parse_field;
fs = force_string(FS_node->var_value);
rp = FS_regexp;
@@ -851,20 +866,20 @@ set_FS()
if (fields_arr != NULL)
(void) get_field(HUGE - 1, 0);
- if (save_fs && cmp_nodes(FS_node->var_value, save_fs) == 0
- && save_rs && cmp_nodes(RS_node->var_value, save_rs) == 0)
- return;
- unref(save_fs);
- save_fs = dupnode(FS_node->var_value);
- unref(save_rs);
- save_rs = dupnode(RS_node->var_value);
- resave_fs = TRUE;
- buf[0] = '\0';
- default_FS = FALSE;
- if (FS_regexp) {
- refree(FS_regexp);
- FS_regexp = NULL;
+ if (! (save_fs && cmp_nodes(FS_node->var_value, save_fs) == 0
+ && save_rs && cmp_nodes(RS_node->var_value, save_rs) == 0)) {
+ unref(save_fs);
+ save_fs = dupnode(FS_node->var_value);
+ unref(save_rs);
+ save_rs = dupnode(RS_node->var_value);
+ resave_fs = TRUE;
+ if (FS_regexp) {
+ refree(FS_regexp);
+ FS_regexp = NULL;
+ }
}
+ buf[0] = '\0';
+ default_FS = FALSE;
fs = force_string(FS_node->var_value);
if (! do_traditional && fs->stlen == 0)
parse_field = null_parse_field;
@@ -887,7 +902,7 @@ set_FS()
if (fs->stptr[0] == ' ' && fs->stlen == 1)
default_FS = TRUE;
else if (fs->stptr[0] != ' ' && fs->stlen == 1) {
- if (! IGNORECASE)
+ if (! IGNORECASE || ! isalpha(fs->stptr[0]))
parse_field = sc_parse_field;
else if (fs->stptr[0] == '\\')
/* yet another special case */
@@ -910,6 +925,5 @@ set_FS()
int
using_fieldwidths()
{
- return parse_field == fw_parse_field;
+ return using_FIELDWIDTHS();
}
-
diff --git a/contrib/awk/io.c b/contrib/awk/io.c
index 74d9a8d..0a24f8a 100644
--- a/contrib/awk/io.c
+++ b/contrib/awk/io.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-1997 the Free Software Foundation, Inc.
+ * Copyright (C) 1976, 1988, 1989, 1991-1999 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -21,6 +21,8 @@
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $FreeBSD$
*/
#include "awk.h"
@@ -49,8 +51,6 @@
#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
#endif
-#include <assert.h>
-
#if ! defined(S_ISREG) && defined(S_IFREG)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
@@ -95,19 +95,8 @@ static int specfdopen P((IOBUF *iop, const char *name, const char *mode));
static int pidopen P((IOBUF *iop, const char *name, const char *mode));
static int useropen P((IOBUF *iop, const char *name, const char *mode));
-#if defined (MSDOS) && !defined (__GO32__)
+#if defined (HAVE_POPEN_H)
#include "popen.h"
-#define popen(c, m) os_popen(c, m)
-#define pclose(f) os_pclose(f)
-#else
-#if defined (OS2) /* OS/2, but not family mode */
-#if defined (_MSC_VER)
-#define popen(c, m) _popen(c, m)
-#define pclose(f) _pclose(f)
-#endif
-#else
-extern FILE *popen();
-#endif
#endif
static struct redirect *red_head = NULL;
@@ -125,6 +114,15 @@ extern NODE **fields_arr;
static jmp_buf filebuf; /* for do_nextfile() */
+#ifdef VMS
+/* File pointers have an extra level of indirection, and there are cases where
+ `stdin' can be null. That can crash gawk if fileno() is used as-is. */
+static int vmsrtl_fileno P((FILE *));
+static int vmsrtl_fileno(fp) FILE *fp; { return fileno(fp); }
+#undef fileno
+#define fileno(FP) (((FP) && *(FP)) ? vmsrtl_fileno(FP) : -1)
+#endif /* VMS */
+
/* do_nextfile --- implement gawk "nextfile" extension */
void
@@ -487,9 +485,10 @@ int *errflg;
/* too many files open -- close one and try again */
if (errno == EMFILE || errno == ENFILE)
close_one();
-#ifdef HAVE_MMAP
+#if defined __MINGW32__ || defined HAVE_MMAP
/* this works for solaris 2.5, not sunos */
- else if (errno == 0) /* HACK! */
+ /* it is also needed for MINGW32 */
+ else if (errno == 0) /* HACK! */
close_one();
#endif
else {
@@ -573,24 +572,22 @@ NODE *tree;
tmp = force_string(tree_eval(tree->subnode));
- /* icky special case: close(FILENAME) called. */
- if (tree->subnode == FILENAME_node
- || (tmp->stlen == FILENAME_node->var_value->stlen
- && STREQN(tmp->stptr, FILENAME_node->var_value->stptr, tmp->stlen))) {
- (void) nextfile(TRUE);
- free_temp(tmp);
- return tmp_number((AWKNUM) 0.0);
- }
-
for (rp = red_head; rp != NULL; rp = rp->next) {
if (strlen(rp->value) == tmp->stlen
&& STREQN(rp->value, tmp->stptr, tmp->stlen))
break;
}
+
if (rp == NULL) { /* no match */
- if (do_lint)
+ /* icky special case: close(FILENAME) called. */
+ if (tree->subnode == FILENAME_node
+ || (tmp->stlen == FILENAME_node->var_value->stlen
+ && STREQN(tmp->stptr, FILENAME_node->var_value->stptr, tmp->stlen))) {
+ (void) nextfile(TRUE);
+ } else if (do_lint)
warning("close: `%.*s' is not an open file or pipe",
tmp->stlen, tmp->stptr);
+
free_temp(tmp);
return tmp_number((AWKNUM) 0.0);
}
@@ -888,11 +885,11 @@ const char *name, *mode;
int i;
if (name[6] == 'g')
- sprintf(tbuf, "%d\n", getpgrp(getpgrp_arg()));
+ sprintf(tbuf, "%d\n", (int) getpgrp(getpgrp_arg()));
else if (name[6] == 'i')
- sprintf(tbuf, "%d\n", getpid());
+ sprintf(tbuf, "%d\n", (int) getpid());
else
- sprintf(tbuf, "%d\n", getppid());
+ sprintf(tbuf, "%d\n", (int) getppid());
i = strlen(tbuf);
spec_setup(iop, i, TRUE);
strcpy(iop->buf, tbuf);
@@ -923,7 +920,7 @@ const char *name, *mode;
int ngroups;
#endif
- sprintf(tbuf, "%d %d %d %d", getuid(), geteuid(), getgid(), getegid());
+ sprintf(tbuf, "%d %d %d %d", (int) getuid(), (int) geteuid(), (int) getgid(), (int) getegid());
cp = tbuf + strlen(tbuf);
#if defined(NGROUPS_MAX) && NGROUPS_MAX > 0
@@ -1008,7 +1005,7 @@ strictopen:
if (openfd == INVALID_HANDLE)
openfd = open(name, flag, 0666);
if (openfd != INVALID_HANDLE && fstat(openfd, &buf) > 0)
- if ((buf.st_mode & S_IFMT) == S_IFDIR)
+ if (S_ISDIR(buf.st_mode))
fatal("file `%s' is a directory", name);
return iop_alloc(openfd, name, iop);
}
@@ -1120,7 +1117,7 @@ struct redirect *rp;
* except if popen() provides real pipes too
*/
-#if defined(VMS) || defined(OS2) || defined (MSDOS)
+#if defined(VMS) || defined(OS2) || defined (MSDOS) || defined(WIN32)
/* gawk_popen --- open an IOBUF on a child process */
@@ -1135,7 +1132,7 @@ struct redirect *rp;
return NULL;
rp->iop = iop_alloc(fileno(current), cmd, NULL);
if (rp->iop == NULL) {
- (void) fclose(current);
+ (void) pclose(current);
current = NULL;
}
rp->ifp = current;
@@ -1434,7 +1431,12 @@ IOBUF *iop;
iop->name = name;
iop->getrec = get_a_record;
#ifdef HAVE_MMAP
- if (S_ISREG(sbuf.st_mode) && sbuf.st_size > 0) {
+ /* Use mmap only for regular files with positive sizes.
+ The size must fit into size_t, so that mmap works correctly.
+ Also, it must fit into int, so that iop->cnt won't overflow. */
+ if (S_ISREG(sbuf.st_mode) && sbuf.st_size > 0
+ && sbuf.st_size == (size_t) sbuf.st_size
+ && sbuf.st_size == (int) sbuf.st_size) {
register char *cp;
iop->buf = iop->off = mmap((caddr_t) 0, sbuf.st_size,
@@ -1535,7 +1537,7 @@ int *errcode; /* pointer to error variable */
return EOF;
}
- if (grRS == FALSE) /* special case: RS == "" */
+ if (RS_is_null) /* special case: RS == "" */
rs = '\n';
else
rs = (char) grRS;
@@ -1648,7 +1650,7 @@ int *errcode; /* pointer to error variable */
*/
if (! do_traditional && RSre != NULL) /* regexp */
rsre = RSre;
- else if (grRS == FALSE) /* RS = "" */
+ else if (RS_is_null) /* RS = "" */
rsre = RS_null_re;
else
rsre = NULL;
@@ -1675,6 +1677,21 @@ int *errcode; /* pointer to error variable */
/* cases 1 and 2 are simple, just keep going */
if (research(rsre, start, 0, iop->end - start, TRUE) == -1
|| RESTART(rsre, start) == REEND(rsre, start)) {
+ /*
+ * Leading newlines at the beginning of the file
+ * should be ignored. Whew!
+ */
+ if (RS_is_null && *start == '\n') {
+ /*
+ * have to catch the case of a
+ * single newline at the front of
+ * the record, which the regex
+ * doesn't. gurr.
+ */
+ while (*start == '\n' && start < iop->end)
+ start++;
+ goto again;
+ }
bp = iop->end;
continue;
}
@@ -1690,8 +1707,10 @@ int *errcode; /* pointer to error variable */
/*
* Leading newlines at the beginning of the file
* should be ignored. Whew!
+ *
+ * Is this code ever executed?
*/
- if (grRS == FALSE && RESTART(rsre, start) == 0) {
+ if (RS_is_null && RESTART(rsre, start) == 0) {
start += REEND(rsre, start);
goto again;
}
@@ -1737,7 +1756,7 @@ int *errcode; /* pointer to error variable */
bstart = bp;
}
*bp = '\0';
- } else if (grRS == FALSE && iop->cnt == EOF) {
+ } else if (RS_is_null && iop->cnt == EOF) {
/*
* special case, delete trailing newlines,
* should never be more than one.
@@ -1811,7 +1830,7 @@ int *errcode; /* pointer to error variable */
return EOF;
}
- if (grRS == FALSE) /* special case: RS == "" */
+ if (RS_is_null) /* special case: RS == "" */
rs = '\n';
else
rs = (char) grRS;
@@ -1821,7 +1840,7 @@ int *errcode; /* pointer to error variable */
rs = casetable[rs];
/* if RS = "", skip leading newlines at the front of the file */
- if (grRS == FALSE && iop->off == iop->buf) {
+ if (RS_is_null && iop->off == iop->buf) {
for (bp = iop->off; *bp == '\n'; bp++)
continue;
@@ -1835,7 +1854,7 @@ int *errcode; /* pointer to error variable */
*/
if (! do_traditional && RSre != NULL) /* regexp */
rsre = RSre;
- else if (grRS == FALSE) /* RS = "" */
+ else if (RS_is_null) /* RS = "" */
rsre = RS_null_re;
else
rsre = NULL;
@@ -1862,7 +1881,7 @@ int *errcode; /* pointer to error variable */
iop->off = iop->end; /* all done with the record */
set_RT_to_null();
/* special case, don't allow trailing newlines */
- if (grRS == FALSE && *(iop->end - 1) == '\n')
+ if (RS_is_null && *(iop->end - 1) == '\n')
return iop->end - start - 1;
else
return iop->end - start;
diff --git a/contrib/awk/main.c b/contrib/awk/main.c
index 92445de..27452f0 100644
--- a/contrib/awk/main.c
+++ b/contrib/awk/main.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-1997 the Free Software Foundation, Inc.
+ * Copyright (C) 1986, 1988, 1989, 1991-1999 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -21,6 +21,8 @@
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $FreeBSD$
*/
#include "awk.h"
@@ -439,8 +441,8 @@ FILE *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("\nReport bugs to bug-gnu-utils@prep.ai.mit.edu,\n", fp);
- fputs("with a Cc: to arnold@gnu.ai.mit.edu\n", fp);
+ fputs("\nReport bugs to bug-gnu-utils@gnu.org,\n", fp);
+ fputs("with a Cc: to arnold@gnu.org\n", fp);
exit(exitval);
}
@@ -450,7 +452,7 @@ static void
copyleft()
{
static char blurb_part1[] =
-"Copyright (C) 1989, 1991-1997 Free Software Foundation.\n\
+"Copyright (C) 1989, 1991-1999 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\
diff --git a/contrib/awk/node.c b/contrib/awk/node.c
index 6f10b9f..a8892a3 100644
--- a/contrib/awk/node.c
+++ b/contrib/awk/node.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-1997 the Free Software Foundation, Inc.
+ * Copyright (C) 1986, 1988, 1989, 1991-1999 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -21,6 +21,8 @@
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $FreeBSD$
*/
#include "awk.h"
@@ -36,6 +38,7 @@ register NODE *n;
char save;
char *ptr;
unsigned int newflags;
+ extern double strtod();
#ifdef DEBUG
if (n == NULL)
@@ -140,7 +143,16 @@ register NODE *s;
/* not an integral value, or out of range */
if ((val = double_to_int(s->numbr)) != s->numbr
|| val < LONG_MIN || val > LONG_MAX) {
-#ifdef GFMT_WORKAROUND
+ /*
+ * Once upon a time, if GFMT_WORKAROUND wasn't defined,
+ * we just blindly did this:
+ * sprintf(sp, format, s->numbr);
+ * s->stlen = strlen(sp);
+ * s->stfmt = (char) index;
+ * but that's no good if, e.g., OFMT is %s. So we punt,
+ * and just always format the value ourselves.
+ */
+
NODE *dummy, *r;
unsigned short oflags;
extern NODE *format_tree P((const char *, int, NODE *));
@@ -161,15 +173,6 @@ register NODE *s;
freenode(dummy); /* to keep s->stptr == r->stpr. */
goto no_malloc;
-#else
- /*
- * no need for a "replacement" formatting by gawk,
- * just use sprintf
- */
- sprintf(sp, format, s->numbr);
- s->stlen = strlen(sp);
- s->stfmt = (char) index;
-#endif /* GFMT_WORKAROUND */
} else {
/* integral value */
/* force conversion to long only once */
@@ -183,11 +186,9 @@ register NODE *s;
}
s->stfmt = -1;
}
- emalloc(s->stptr, char *, s->stlen + 2, "force_string");
+ emalloc(s->stptr, char *, s->stlen + 2, "format_val");
memcpy(s->stptr, sp, s->stlen+1);
-#ifdef GFMT_WORKAROUND
no_malloc:
-#endif /* GFMT_WORKAROUND */
s->stref = 1;
s->flags |= STR;
return s;
@@ -495,7 +496,9 @@ char **string_ptr;
}
i = 0;
for (;;) {
- if (ISXDIGIT((c = *(*string_ptr)++))) {
+ /* do outside test to avoid multiple side effects */
+ c = *(*string_ptr)++;
+ if (ISXDIGIT(c)) {
i *= 16;
if (ISDIGIT(c))
i += c - '0';
OpenPOWER on IntegriCloud