From 1abc97f5cfc1ebee9611772cd7b8b639784ac66e Mon Sep 17 00:00:00 2001 From: Sheldon Hearn Date: Mon, 27 Sep 1999 08:57:04 +0000 Subject: [PATCH] Fix conflicts. Add $FreeBSD$ as needed. --- contrib/awk/awk.h | 16 +++++- contrib/awk/builtin.c | 111 ++++++++++++++++++++++++++++++++---------- contrib/awk/doc/awk.1 | 17 +++++-- contrib/awk/eval.c | 78 +++++++++++++++++++++-------- contrib/awk/field.c | 66 +++++++++++++++---------- contrib/awk/io.c | 105 +++++++++++++++++++++++---------------- contrib/awk/main.c | 10 ++-- contrib/awk/node.c | 33 +++++++------ 8 files changed, 296 insertions(+), 140 deletions(-) diff --git a/contrib/awk/awk.h b/contrib/awk/awk.h index 3ab2015c8bb6..621a98109574 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 #endif @@ -34,6 +44,7 @@ #endif /* _GNU_SOURCE */ #include +#include #ifdef HAVE_LIMITS_H #include #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 dc2c1d3cff94..0fee05459a2a 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 #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 @@ register NODE *carg; 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 @@ register NODE *carg; 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 @@ register NODE *carg; 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 @@ register NODE *carg; 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 @@ register NODE *carg; *--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 @@ register NODE *carg; 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 @@ register NODE *carg; 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 @@ register NODE *carg; *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 6be430a133f4..807f79f156b9 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 aa2e88162f15..37c5fef86789 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 - 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 31c962879582..72cbd78e8c20 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 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) { + NODE *n; + getnode(n); - if (fields_arr[i]->stlen > 0 - && f0start <= field_data && field_data < f0end) - fields_arr[i]->stptr = cops; + 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 74d9a8d73a37..0a24f8af30ce 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 - #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 @@ IOBUF *iop; 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 92445de4e62f..27452f00aed3 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 6f10b9f3c6d4..a8892a35678b 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';