diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2020-12-09 20:00:12 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2020-12-09 20:00:12 +0000 |
commit | c1262a2f42694e18e6e9179f755a231935f2b710 (patch) | |
tree | a3903d2e6d9fd26d5dc136320254565a30833788 /usr.bin/awk | |
parent | d748bb807f88a010d30ec3116ae990da076dc35c (diff) |
Update awk to December 8, 2020 version.
Prevents strings beginning with "inf" or "nan" from being interpreted
as infinity or not-a-number respectively which still parsing "inf"
and "nan" (with or without a leading sign) correctly.
Diffstat (limited to 'usr.bin/awk')
-rw-r--r-- | usr.bin/awk/FIXES | 21 | ||||
-rw-r--r-- | usr.bin/awk/README.md | 10 | ||||
-rw-r--r-- | usr.bin/awk/awk.1 | 58 | ||||
-rw-r--r-- | usr.bin/awk/b.c | 40 | ||||
-rw-r--r-- | usr.bin/awk/lex.c | 15 | ||||
-rw-r--r-- | usr.bin/awk/lib.c | 99 | ||||
-rw-r--r-- | usr.bin/awk/main.c | 6 | ||||
-rw-r--r-- | usr.bin/awk/parse.c | 4 | ||||
-rw-r--r-- | usr.bin/awk/proto.h | 6 | ||||
-rw-r--r-- | usr.bin/awk/run.c | 80 | ||||
-rw-r--r-- | usr.bin/awk/tran.c | 42 |
11 files changed, 272 insertions, 109 deletions
diff --git a/usr.bin/awk/FIXES b/usr.bin/awk/FIXES index 8341575f2c8..cb35981b64d 100644 --- a/usr.bin/awk/FIXES +++ b/usr.bin/awk/FIXES @@ -1,4 +1,4 @@ -/* $OpenBSD: FIXES,v 1.38 2020/08/11 16:57:05 millert Exp $ */ +/* $OpenBSD: FIXES,v 1.39 2020/12/09 20:00:11 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -26,6 +26,25 @@ THIS SOFTWARE. This file lists all bug fixes, changes, etc., made since the AWK book was sent to the printers in August, 1987. +December 8, 2020: + Merge PR #98: Disallow hex data. Allow only +nan, -nan, + +inf, -inf (case independent) to give NaN and infinity values. + Improve things so that string to double conversion is only + done once, yielding something of a speedup. This obviate + PR #95. Thanks to Arnold Robbins. + +December 3, 2020: + Fix to argument parsing to avoid printing spurious newlines. + Thanks to Todd Miller. Merges PR #97. + +October 13, 2020: + Add casts before all the calls to malloc/calloc/realloc in order + to get it to compile with g++. Thanks to Arnold Robbins. + +August 16, 2020: + Additional fixes for DJGPP. Thanks to Eli Zaretskii for + the testing. + August 7, 2020: Merge PR #93, which adds casts to (void*) for debug prints using the %p format specifier. Thanks to GitHub user YongHaoWu diff --git a/usr.bin/awk/README.md b/usr.bin/awk/README.md index 75e7305247c..655006e49fc 100644 --- a/usr.bin/awk/README.md +++ b/usr.bin/awk/README.md @@ -1,4 +1,4 @@ -$OpenBSD: README.md,v 1.3 2020/07/02 19:06:22 millert Exp $ +$OpenBSD: README.md,v 1.4 2020/12/09 20:00:11 millert Exp $ # The One True Awk @@ -101,6 +101,9 @@ welcome. This compiles without change on Macintosh OS X using `gcc` and the standard developer tools. +You can also use `make CC=g++` to build with the GNU C++ compiler, +should you choose to do so. + The version of `malloc` that comes with some systems is sometimes astonishly slow. If `awk` seems slow, you might try fixing that. More generally, turning on optimization can significantly improve @@ -114,8 +117,9 @@ as we can. Unfortunately, however, keeping this program going is not at the top of our priority list. _If_ you (yes, you!) are interested in taking over active maintenance of -`awk`, please open an issue to indicate that fact, give a little bit of +`awk`, please open an issue to indicate that fact, and give us a little bit of your background and some idea of your plans and dreams. Thanks! #### Last Updated -Thu Jul 2 21:39:31 IDT 2020 + +Tue Oct 13 20:00:09 IDT 2020 diff --git a/usr.bin/awk/awk.1 b/usr.bin/awk/awk.1 index 3c2dfcfcd03..9027bf80fb8 100644 --- a/usr.bin/awk/awk.1 +++ b/usr.bin/awk/awk.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: awk.1,v 1.58 2020/11/05 16:04:39 jmc Exp $ +.\" $OpenBSD: awk.1,v 1.59 2020/12/09 20:00:11 millert Exp $ .\" .\" Copyright (C) Lucent Technologies 1997 .\" All Rights Reserved @@ -22,7 +22,7 @@ .\" ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF .\" THIS SOFTWARE. .\" -.Dd $Mdocdate: November 5 2020 $ +.Dd $Mdocdate: December 9 2020 $ .Dt AWK 1 .Os .Sh NAME @@ -280,7 +280,7 @@ and concatenation .Pq indicated by whitespace . The operators .Ic \&! ++ \-\- += \-= *= /= %= ^= -.Ic > >= < <= == != ?: +.Ic > >= < <= == != ?\&: are also available in expressions. Variables may be scalars, array elements (denoted @@ -919,6 +919,58 @@ Print an error message to standard error: .Bd -literal -offset indent { print "error!" > "/dev/stderr" } .Ed +.Sh UNUSUAL FLOATING-POINT VALUES +.Nm +was designed before IEEE 754 arithmetic defined Not-A-Number (NaN) +and Infinity values, which are supported by all modern floating-point +hardware. +.Pp +Because +.Nm +uses +.Xr strtod 3 +and +.Xr atof 3 +to convert string values to double-precision floating-point values, +modern C libraries also convert strings starting with +.Dv inf +and +.Dv nan +into infinity and NaN values respectively. +This led to strange results, +with something like this: +.Pp +.Li echo nancy | awk '{ print $1 + 0 }' +.Pp +printing +.Dv nan +instead of zero. +.Pp +.Nm +now follows GNU +.Nm , +and prefilters string values before attempting +to convert them to numbers, as follows: +.Bl -tag -width Ds +.It Hexadecimal values +Hexadecimal values (allowed since C99) convert to zero, as they did +prior to C99. +.It NaN values +The two strings +.Dq +NAN +and +.Dq -NAN +(case independent) convert to NaN. +No others do. +(NaNs can have signs.) +.It Infinity values +The two strings +.Dq +INF +and +.Dq -INF +(case independent) convert to positive and negative infinity, respectively. +No others do. +.El .Sh SEE ALSO .Xr cut 1 , .Xr date 1 , diff --git a/usr.bin/awk/b.c b/usr.bin/awk/b.c index cef1bbd29bd..1c272cd5fea 100644 --- a/usr.bin/awk/b.c +++ b/usr.bin/awk/b.c @@ -1,4 +1,4 @@ -/* $OpenBSD: b.c,v 1.34 2020/07/30 17:45:44 millert Exp $ */ +/* $OpenBSD: b.c,v 1.35 2020/12/09 20:00:11 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -84,7 +84,7 @@ int nfatab = 0; /* entries in fatab */ static int * intalloc(size_t n, const char *f) { - void *p = calloc(n, sizeof(int)); + int *p = (int *) calloc(n, sizeof(int)); if (p == NULL) overflo(f); return p; @@ -94,8 +94,8 @@ static void allocsetvec(const char *f) { maxsetvec = MAXLIN; - setvec = reallocarray(setvec, maxsetvec, sizeof(*setvec)); - tmpset = reallocarray(tmpset, maxsetvec, sizeof(*tmpset)); + setvec = (int *) reallocarray(setvec, maxsetvec, sizeof(*setvec)); + tmpset = (int *) reallocarray(tmpset, maxsetvec, sizeof(*tmpset)); if (setvec == NULL || tmpset == NULL) overflo(f); } @@ -103,8 +103,8 @@ allocsetvec(const char *f) static void resizesetvec(const char *f) { - setvec = reallocarray(setvec, maxsetvec, 4 * sizeof(*setvec)); - tmpset = reallocarray(tmpset, maxsetvec, 4 * sizeof(*tmpset)); + setvec = (int *) reallocarray(setvec, maxsetvec, 4 * sizeof(*setvec)); + tmpset = (int *) reallocarray(tmpset, maxsetvec, 4 * sizeof(*tmpset)); if (setvec == NULL || tmpset == NULL) overflo(f); maxsetvec *= 4; @@ -113,7 +113,9 @@ resizesetvec(const char *f) static void resize_state(fa *f, int state) { - void *p; + unsigned int **p; + uschar *p2; + int **p3; int i, new_count; if (++state < f->state_count) @@ -121,23 +123,23 @@ resize_state(fa *f, int state) new_count = state + 10; /* needs to be tuned */ - p = reallocarray(f->gototab, new_count, sizeof(f->gototab[0])); + p = (unsigned int **) reallocarray(f->gototab, new_count, sizeof(f->gototab[0])); if (p == NULL) goto out; f->gototab = p; - p = reallocarray(f->out, new_count, sizeof(f->out[0])); - if (p == NULL) + p2 = (uschar *) reallocarray(f->out, new_count, sizeof(f->out[0])); + if (p2 == NULL) goto out; - f->out = p; + f->out = p2; - p = reallocarray(f->posns, new_count, sizeof(f->posns[0])); - if (p == NULL) + p3 = (int **) reallocarray(f->posns, new_count, sizeof(f->posns[0])); + if (p3 == NULL) goto out; - f->posns = p; + f->posns = p3; for (i = f->state_count; i < new_count; ++i) { - f->gototab[i] = calloc(NCHARS, sizeof(**f->gototab)); + f->gototab[i] = (unsigned int *) calloc(NCHARS, sizeof(**f->gototab)); if (f->gototab[i] == NULL) goto out; f->out[i] = 0; @@ -203,7 +205,7 @@ fa *mkdfa(const char *s, bool anchor) /* does the real work of making a dfa */ poscnt = 0; penter(p1); /* enter parent pointers and leaf indices */ - if ((f = calloc(1, sizeof(fa) + poscnt * sizeof(rrow))) == NULL) + if ((f = (fa *) calloc(1, sizeof(fa) + poscnt * sizeof(rrow))) == NULL) overflo(__func__); f->accept = poscnt-1; /* penter has computed number of positions in re */ cfoll(f, p1); /* set up follow sets */ @@ -373,7 +375,7 @@ char *cclenter(const char *argp) /* add a character class */ static int bufsz = 100; op = p; - if (buf == NULL && (buf = malloc(bufsz)) == NULL) + if (buf == NULL && (buf = (uschar *) malloc(bufsz)) == NULL) FATAL("out of space for character class [%.10s...] 1", p); bp = buf; for (i = 0; (c = *p++) != 0; ) { @@ -944,7 +946,7 @@ replace_repeat(const uschar *reptok, int reptoklen, const uschar *atom, } else if (special_case == REPEAT_ZERO) { size += 2; /* just a null ERE: () */ } - if ((buf = malloc(size + 1)) == NULL) + if ((buf = (uschar *) malloc(size + 1)) == NULL) FATAL("out of space in reg expr %.10s..", lastre); memcpy(buf, basestr, prefix_length); /* copy prefix */ j = prefix_length; @@ -1072,7 +1074,7 @@ rescan: rlxval = c; return CHAR; case '[': - if (buf == NULL && (buf = malloc(bufsz)) == NULL) + if (buf == NULL && (buf = (uschar *) malloc(bufsz)) == NULL) FATAL("out of space in reg expr %.10s..", lastre); bp = buf; if (*prestr == '^') { diff --git a/usr.bin/awk/lex.c b/usr.bin/awk/lex.c index 1dc1f991fa0..42feeae9962 100644 --- a/usr.bin/awk/lex.c +++ b/usr.bin/awk/lex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lex.c,v 1.26 2020/08/28 16:29:16 millert Exp $ */ +/* $OpenBSD: lex.c,v 1.27 2020/12/09 20:00:11 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -184,7 +184,7 @@ int yylex(void) static char *buf = NULL; static int bufsize = 5; /* BUG: setting this small causes core dump! */ - if (buf == NULL && (buf = malloc(bufsize)) == NULL) + if (buf == NULL && (buf = (char *) malloc(bufsize)) == NULL) FATAL( "out of space in yylex" ); if (sc) { sc = false; @@ -202,7 +202,12 @@ int yylex(void) return word(buf); if (isdigit(c)) { char *cp = tostring(buf); - yylval.cp = setsymtab(buf, cp, atof(buf), CON|NUM, symtab); + double result; + + if (is_number(cp, & result)) + yylval.cp = setsymtab(buf, cp, result, CON|NUM, symtab); + else + yylval.cp = setsymtab(buf, cp, 0.0, STR, symtab); free(cp); /* should this also have STR set? */ RET(NUMBER); @@ -381,7 +386,7 @@ int string(void) static char *buf = NULL; static int bufsz = 500; - if (buf == NULL && (buf = malloc(bufsz)) == NULL) + if (buf == NULL && (buf = (char *) malloc(bufsz)) == NULL) FATAL("out of space for strings"); for (bp = buf; (c = input()) != '"'; ) { if (!adjbuf(&buf, &bufsz, bp-buf+2, 500, &bp, "string")) @@ -530,7 +535,7 @@ int regexpr(void) static int bufsz = 500; char *bp, *cstart; - if (buf == NULL && (buf = malloc(bufsz)) == NULL) + if (buf == NULL && (buf = (char *) malloc(bufsz)) == NULL) FATAL("out of space for rex expr"); bp = buf; for ( ; ((c = input()) != '/' || openclass > 0) && c != 0; ) { diff --git a/usr.bin/awk/lib.c b/usr.bin/awk/lib.c index 173317a85ba..a02f7609534 100644 --- a/usr.bin/awk/lib.c +++ b/usr.bin/awk/lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lib.c,v 1.41 2020/07/30 17:46:54 millert Exp $ */ +/* $OpenBSD: lib.c,v 1.42 2020/12/09 20:00:11 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -31,6 +31,7 @@ THIS SOFTWARE. #include <stdlib.h> #include <stdarg.h> #include <limits.h> +#include <math.h> #include "awk.h" char EMPTY[] = { '\0' }; @@ -61,10 +62,10 @@ static Cell dollar1 = { OCELL, CFLD, NULL, EMPTY, 0.0, FLD|STR|DONTFREE, NULL, N void recinit(unsigned int n) { - if ( (record = malloc(n)) == NULL - || (fields = malloc(n+1)) == NULL - || (fldtab = calloc(nfields+2, sizeof(*fldtab))) == NULL - || (fldtab[0] = malloc(sizeof(**fldtab))) == NULL) + if ( (record = (char *) malloc(n)) == NULL + || (fields = (char *) malloc(n+1)) == NULL + || (fldtab = (Cell **) calloc(nfields+2, sizeof(*fldtab))) == NULL + || (fldtab[0] = (Cell *) malloc(sizeof(**fldtab))) == NULL) FATAL("out of space for $0 and fields"); *record = '\0'; *fldtab[0] = dollar0; @@ -79,7 +80,7 @@ void makefields(int n1, int n2) /* create $n1..$n2 inclusive */ int i; for (i = n1; i <= n2; i++) { - fldtab[i] = malloc(sizeof(**fldtab)); + fldtab[i] = (Cell *) malloc(sizeof(**fldtab)); if (fldtab[i] == NULL) FATAL("out of space in makefields %d", i); *fldtab[i] = dollar1; @@ -124,7 +125,7 @@ void savefs(void) size_t len = strlen(getsval(fsloc)); if (len >= len_inputFS) { len_inputFS = len + 1; - inputFS = realloc(inputFS, len_inputFS); + inputFS = (char *) realloc(inputFS, len_inputFS); if (inputFS == NULL) FATAL("field separator %.10s... is too long", *FS); } @@ -180,12 +181,14 @@ int getrec(char **pbuf, int *pbufsize, bool isrecord) /* get next input record * innew = false; if (c != 0 || buf[0] != '\0') { /* normal record */ if (isrecord) { + double result; + if (freeable(fldtab[0])) xfree(fldtab[0]->sval); fldtab[0]->sval = buf; /* buf == record */ fldtab[0]->tval = REC | STR | DONTFREE; - if (is_number(fldtab[0]->sval)) { - fldtab[0]->fval = atof(fldtab[0]->sval); + if (is_number(fldtab[0]->sval, & result)) { + fldtab[0]->fval = result; fldtab[0]->tval |= NUM; } } @@ -292,6 +295,7 @@ void setclvar(char *s) /* set var=value from s */ { char *p; Cell *q; + double result; for (p=s; *p != '='; p++) ; @@ -299,8 +303,8 @@ void setclvar(char *s) /* set var=value from s */ p = qstring(p, '\0'); q = setsymtab(s, p, 0.0, STR, symtab); setsval(q, p); - if (is_number(q->sval)) { - q->fval = atof(q->sval); + if (is_number(q->sval, & result)) { + q->fval = result; q->tval |= NUM; } DPRINTF("command line set %s to |%s|\n", s, p); @@ -324,7 +328,7 @@ void fldbld(void) /* create fields from current record */ n = strlen(r); if (n > fieldssize) { xfree(fields); - if ((fields = malloc(n+2)) == NULL) /* possibly 2 final \0s */ + if ((fields = (char *) malloc(n+2)) == NULL) /* possibly 2 final \0s */ FATAL("out of space for fields in fldbld %d", n); fieldssize = n; } @@ -401,9 +405,11 @@ void fldbld(void) /* create fields from current record */ lastfld = i; donefld = true; for (j = 1; j <= lastfld; j++) { + double result; + p = fldtab[j]; - if(is_number(p->sval)) { - p->fval = atof(p->sval); + if(is_number(p->sval, & result)) { + p->fval = result; p->tval |= NUM; } } @@ -473,7 +479,7 @@ void growfldtab(int n) /* make new fields up to at least $n */ nf = n; s = (nf+1) * (sizeof (struct Cell *)); /* freebsd: how much do we need? */ if (s / sizeof(struct Cell *) - 1 == (size_t)nf) /* didn't overflow */ - fldtab = realloc(fldtab, s); + fldtab = (Cell **) realloc(fldtab, s); else /* overflow sizeof int */ xfree(fldtab); /* make it null */ if (fldtab == NULL) @@ -493,7 +499,7 @@ int refldbld(const char *rec, const char *fs) /* build fields from reg expr in F n = strlen(rec); if (n > fieldssize) { xfree(fields); - if ((fields = malloc(n+1)) == NULL) + if ((fields = (char *) malloc(n+1)) == NULL) FATAL("out of space for fields in refldbld %d", n); fieldssize = n; } @@ -758,24 +764,67 @@ int isclvar(const char *s) /* is s of form var=something ? */ /* strtod is supposed to be a proper test of what's a valid number */ /* appears to be broken in gcc on linux: thinks 0x123 is a valid FP number */ /* wrong: violates 4.10.1.4 of ansi C standard */ + /* well, not quite. As of C99, hex floating point is allowed. so this is - * a bit of a mess. + * a bit of a mess. We work around the mess by checking for a hexadecimal + * value and disallowing it. Similarly, we now follow gawk and allow only + * +nan, -nan, +inf, and -inf for NaN and infinity values. */ -#include <math.h> -int is_number(const char *s) +/* + * This routine now has a more complicated interface, the main point + * being to avoid the double conversion of a string to double, and + * also to convey out, if requested, the information that the numeric + * value was a leading string or is all of the string. The latter bit + * is used in getfval(). + */ + +bool is_valid_number(const char *s, bool trailing_stuff_ok, + bool *no_trailing, double *result) { double r; char *ep; + bool retval = false; + + if (no_trailing) + *no_trailing = false; + + while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') + s++; + + if (s[0] == '0' && tolower(s[1]) == 'x') // no hex floating point, sorry + return false; + + // allow +nan, -nan, +inf, -inf, any other letter, no + if (s[0] == '+' || s[0] == '-') { + if (strcasecmp(s+1, "nan") == 0 || strcasecmp(s+1, "inf") == 0) + return true; + else if (! isdigit(s[1]) && s[1] != '.') + return false; + } + else if (! isdigit(s[0]) && s[0] != '.') + return false; + errno = 0; r = strtod(s, &ep); if (ep == s || r == HUGE_VAL || errno == ERANGE) - return 0; - /* allow \r as well. windows files aren't going to go away. */ + return false; + + if (result != NULL) + *result = r; + + /* + * check for trailing stuff + * allow \r as well. windows files aren't going to go away. + */ while (*ep == ' ' || *ep == '\t' || *ep == '\n' || *ep == '\r') ep++; - if (*ep == '\0') - return 1; - else - return 0; + + if (no_trailing) + *no_trailing = (*ep == '\0'); + + // return true if found the end, or trailing stuff is allowed + retval = (*ep == '\0') || trailing_stuff_ok; + + return retval; } diff --git a/usr.bin/awk/main.c b/usr.bin/awk/main.c index 9ffbf736b65..6aac4d5fa64 100644 --- a/usr.bin/awk/main.c +++ b/usr.bin/awk/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.45 2020/08/11 16:57:05 millert Exp $ */ +/* $OpenBSD: main.c,v 1.46 2020/12/09 20:00:11 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -23,7 +23,7 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ****************************************************************/ -const char *version = "version 20200807"; +const char *version = "version 20201208"; #define DEBUG #include <stdio.h> @@ -181,7 +181,7 @@ int main(int argc, char *argv[]) fn = getarg(&argc, &argv, "no program filename"); if (npfile >= maxpfile) { maxpfile += 20; - pfile = realloc(pfile, maxpfile * sizeof(*pfile)); + pfile = (char **) realloc(pfile, maxpfile * sizeof(*pfile)); if (pfile == NULL) FATAL("error allocating space for -f options"); } diff --git a/usr.bin/awk/parse.c b/usr.bin/awk/parse.c index 8b14f46f4e9..abd5c4fc6fc 100644 --- a/usr.bin/awk/parse.c +++ b/usr.bin/awk/parse.c @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.c,v 1.12 2020/07/30 17:45:44 millert Exp $ */ +/* $OpenBSD: parse.c,v 1.13 2020/12/09 20:00:11 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -34,7 +34,7 @@ Node *nodealloc(int n) { Node *x; - x = malloc(sizeof(*x) + (n-1) * sizeof(x)); + x = (Node *) malloc(sizeof(*x) + (n-1) * sizeof(x)); if (x == NULL) FATAL("out of space in nodealloc"); x->nnext = NULL; diff --git a/usr.bin/awk/proto.h b/usr.bin/awk/proto.h index de70e5896d8..0c37d53725d 100644 --- a/usr.bin/awk/proto.h +++ b/usr.bin/awk/proto.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proto.h,v 1.19 2020/06/13 01:21:01 millert Exp $ */ +/* $OpenBSD: proto.h,v 1.20 2020/12/09 20:00:11 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -149,7 +149,9 @@ extern void eprint(void); extern void bclass(int); extern double errcheck(double, const char *); extern int isclvar(const char *); -extern int is_number(const char *); +extern bool is_valid_number(const char *s, bool trailing_stuff_ok, + bool *no_trailing, double *result); +#define is_number(s, val) is_valid_number(s, false, NULL, val) extern int adjbuf(char **pb, int *sz, int min, int q, char **pbp, const char *what); extern void run(Node *); diff --git a/usr.bin/awk/run.c b/usr.bin/awk/run.c index f6b141c695c..d7570bcb31f 100644 --- a/usr.bin/awk/run.c +++ b/usr.bin/awk/run.c @@ -1,4 +1,4 @@ -/* $OpenBSD: run.c,v 1.68 2020/08/28 16:29:16 millert Exp $ */ +/* $OpenBSD: run.c,v 1.69 2020/12/09 20:00:11 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -119,7 +119,7 @@ int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr, /* round up to next multiple of quantum */ if (rminlen) minlen += quantum - rminlen; - tbuf = realloc(*pbuf, minlen); + tbuf = (char *) realloc(*pbuf, minlen); DPRINTF("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, *psiz, minlen, (void*)*pbuf, (void*)tbuf); if (tbuf == NULL) { if (whatrtn) @@ -241,7 +241,7 @@ Cell *call(Node **a, int n) /* function call. very kludgy and fragile */ if (!isfcn(fcn)) FATAL("calling undefined function %s", s); if (frame == NULL) { - frp = frame = calloc(nframe += 100, sizeof(*frame)); + frp = frame = (struct Frame *) calloc(nframe += 100, sizeof(*frame)); if (frame == NULL) FATAL("out of space for stack frames calling %s", s); } @@ -275,7 +275,7 @@ Cell *call(Node **a, int n) /* function call. very kludgy and fragile */ frp++; /* now ok to up frame */ if (frp >= frame + nframe) { int dfp = frp - frame; /* old index */ - frame = reallocarray(frame, (nframe += 100), sizeof(*frame)); + frame = (struct Frame *) reallocarray(frame, (nframe += 100), sizeof(*frame)); if (frame == NULL) FATAL("out of space for stack frames in %s", s); frp = frame + dfp; @@ -408,8 +408,9 @@ Cell *awkgetline(Node **a, int n) /* get next line from specific input */ int bufsize = recsize; int mode; bool newflag; + double result; - if ((buf = malloc(bufsize)) == NULL) + if ((buf = (char *) malloc(bufsize)) == NULL) FATAL("out of memory in getline"); fflush(stdout); /* in case someone is waiting for a prompt */ @@ -430,15 +431,15 @@ Cell *awkgetline(Node **a, int n) /* get next line from specific input */ } else if (a[0] != NULL) { /* getline var <file */ x = execute(a[0]); setsval(x, buf); - if (is_number(x->sval)) { - x->fval = atof(x->sval); + if (is_number(x->sval, & result)) { + x->fval = result; x->tval |= NUM; } tempfree(x); } else { /* getline <file */ setsval(fldtab[0], buf); - if (is_number(fldtab[0]->sval)) { - fldtab[0]->fval = atof(fldtab[0]->sval); + if (is_number(fldtab[0]->sval, & result)) { + fldtab[0]->fval = result; fldtab[0]->tval |= NUM; } } @@ -449,8 +450,8 @@ Cell *awkgetline(Node **a, int n) /* get next line from specific input */ n = getrec(&buf, &bufsize, false); x = execute(a[0]); setsval(x, buf); - if (is_number(x->sval)) { - x->fval = atof(x->sval); + if (is_number(x->sval, & result)) { + x->fval = result; x->tval |= NUM; } tempfree(x); @@ -475,7 +476,7 @@ makearraystring(Node *p, const char *func) int bufsz = recsize; size_t blen; - if ((buf = malloc(bufsz)) == NULL) { + if ((buf = (char *) malloc(bufsz)) == NULL) { FATAL("%s: out of memory", func); } @@ -702,7 +703,7 @@ Cell *gettemp(void) /* get a tempcell */ Cell *x; if (!tmps) { - tmps = calloc(100, sizeof(*tmps)); + tmps = (Cell *) calloc(100, sizeof(*tmps)); if (!tmps) FATAL("out of space for temporaries"); for (i = 1; i < 100; i++) @@ -727,7 +728,7 @@ Cell *indirect(Node **a, int n) /* $( a[0] ) */ if ((Awkfloat)INT_MAX < val) FATAL("trying to access out of range field %s", x->nval); m = (int) val; - if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */ + if (m == 0 && !is_number(s = getsval(x), NULL)) /* suspicion! */ FATAL("illegal field $(%s), name \"%s\"", s, x->nval); /* BUG: can x->nval ever be null??? */ tempfree(x); @@ -840,7 +841,7 @@ int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like co os = s; p = buf; - if ((fmt = malloc(fmtsz)) == NULL) + if ((fmt = (char *) malloc(fmtsz)) == NULL) FATAL("out of memory in format()"); while (*s) { adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format1"); @@ -983,7 +984,7 @@ Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */ char *buf; int bufsz=3*recsize; - if ((buf = malloc(bufsz)) == NULL) + if ((buf = (char *) malloc(bufsz)) == NULL) FATAL("out of memory in awksprintf"); y = a[0]->nnext; x = execute(a[0]); @@ -1006,7 +1007,7 @@ Cell *awkprintf(Node **a, int n) /* printf */ int len; int bufsz=3*recsize; - if ((buf = malloc(bufsz)) == NULL) + if ((buf = (char *) malloc(bufsz)) == NULL) FATAL("out of memory in awkprintf"); y = a[0]->nnext; x = execute(a[0]); @@ -1260,6 +1261,7 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ int sep; char temp, num[50]; int n, tempstat, arg3type; + double result; y = execute(a[0]); /* source string */ origs = s = strdup(getsval(y)); @@ -1308,8 +1310,8 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ snprintf(num, sizeof(num), "%d", n); temp = *patbeg; setptr(patbeg, '\0'); - if (is_number(s)) - setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval); + if (is_number(s, & result)) + setsymtab(num, s, result, STR|NUM, (Array *) ap->sval); else setsymtab(num, s, 0.0, STR, (Array *) ap->sval); setptr(patbeg, temp); @@ -1327,8 +1329,8 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ } n++; snprintf(num, sizeof(num), "%d", n); - if (is_number(s)) - setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval); + if (is_number(s, & result)) + setsymtab(num, s, result, STR|NUM, (Array *) ap->sval); else setsymtab(num, s, 0.0, STR, (Array *) ap->sval); spdone: @@ -1348,8 +1350,8 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ temp = *s; setptr(s, '\0'); snprintf(num, sizeof(num), "%d", n); - if (is_number(t)) - setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval); + if (is_number(t, & result)) + setsymtab(num, t, result, STR|NUM, (Array *) ap->sval); else setsymtab(num, t, 0.0, STR, (Array *) ap->sval); setptr(s, temp); @@ -1377,8 +1379,8 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ temp = *s; setptr(s, '\0'); snprintf(num, sizeof(num), "%d", n); - if (is_number(t)) - setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval); + if (is_number(t, & result)) + setsymtab(num, t, result, STR|NUM, (Array *) ap->sval); else setsymtab(num, t, 0.0, STR, (Array *) ap->sval); setptr(s, temp); @@ -1573,6 +1575,24 @@ static char *nawk_convert(const char *s, int (*fun_c)(int), } } +#ifdef __DJGPP__ +static wint_t towupper(wint_t wc) +{ + if (wc >= 0 && wc < 256) + return toupper(wc & 0xFF); + + return wc; +} + +static wint_t towlower(wint_t wc) +{ + if (wc >= 0 && wc < 256) + return tolower(wc & 0xFF); + + return wc; +} +#endif + static char *nawk_toupper(const char *s) { return nawk_convert(s, toupper, towupper); @@ -1794,7 +1814,7 @@ Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg lis sz = 32; buf = NULL; do { - if ((buf = reallocarray(buf, 2, sz)) == NULL) + if ((buf = (char *) reallocarray(buf, 2, sz)) == NULL) FATAL("out of memory in strftime"); sz *= 2; } while (strftime(buf, sz, fmt, tm) == 0 && fmt[0] != '\0'); @@ -1878,7 +1898,7 @@ size_t nfiles; static void stdinit(void) /* in case stdin, etc., are not constants */ { nfiles = FOPEN_MAX; - files = calloc(nfiles, sizeof(*files)); + files = (struct files *) calloc(nfiles, sizeof(*files)); if (files == NULL) FATAL("can't allocate file memory for %zu files", nfiles); files[0].fp = stdin; @@ -1918,7 +1938,7 @@ FILE *openfile(int a, const char *us, bool *pnewflag) if (i >= nfiles) { struct files *nf; size_t nnf = nfiles + FOPEN_MAX; - nf = reallocarray(files, nnf, sizeof(*nf)); + nf = (struct files *) reallocarray(files, nnf, sizeof(*nf)); if (nf == NULL) FATAL("cannot grow files for %s and %zu files", s, nnf); memset(&nf[nfiles], 0, FOPEN_MAX * sizeof(*nf)); @@ -2039,7 +2059,7 @@ Cell *sub(Node **a, int nnn) /* substitute command */ fa *pfa; int bufsz = recsize; - if ((buf = malloc(bufsz)) == NULL) + if ((buf = (char *) malloc(bufsz)) == NULL) FATAL("out of memory in sub"); x = execute(a[3]); /* target string */ t = getsval(x); @@ -2101,7 +2121,7 @@ Cell *gsub(Node **a, int nnn) /* global substitute */ int mflag, tempstat, num; int bufsz = recsize; - if ((buf = malloc(bufsz)) == NULL) + if ((buf = (char *) malloc(bufsz)) == NULL) FATAL("out of memory in gsub"); mflag = 0; /* if mflag == 0, can replace empty string */ num = 0; diff --git a/usr.bin/awk/tran.c b/usr.bin/awk/tran.c index ea67e6f2fc5..1ea64d240d8 100644 --- a/usr.bin/awk/tran.c +++ b/usr.bin/awk/tran.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tran.c,v 1.31 2020/08/11 16:57:05 millert Exp $ */ +/* $OpenBSD: tran.c,v 1.32 2020/12/09 20:00:11 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -130,9 +130,11 @@ void arginit(int ac, char **av) /* set up ARGV and ARGC */ free(cp->sval); cp->sval = (char *) ARGVtab; for (i = 0; i < ac; i++) { + double result; + snprintf(temp, sizeof temp, "%d", i); - if (is_number(*av)) - setsymtab(temp, *av, atof(*av), STR|NUM, ARGVtab); + if (is_number(*av, & result)) + setsymtab(temp, *av, result, STR|NUM, ARGVtab); else setsymtab(temp, *av, 0.0, STR, ARGVtab); av++; @@ -149,13 +151,15 @@ void envinit(char **envp) /* set up ENVIRON variable */ free(cp->sval); cp->sval = (char *) ENVtab; for ( ; *envp; envp++) { + double result; + if ((p = strchr(*envp, '=')) == NULL) continue; if( p == *envp ) /* no left hand side name in env string */ continue; *p++ = 0; /* split into two strings at = */ - if (is_number(p)) - setsymtab(*envp, p, atof(p), STR|NUM, ENVtab); + if (is_number(p, & result)) + setsymtab(*envp, p, result, STR|NUM, ENVtab); else setsymtab(*envp, p, 0.0, STR, ENVtab); p[-1] = '='; /* restore in case env is passed down to a shell */ @@ -167,8 +171,8 @@ Array *makesymtab(int n) /* make a new symbol table */ Array *ap; Cell **tp; - ap = malloc(sizeof(*ap)); - tp = calloc(n, sizeof(*tp)); + ap = (Array *) malloc(sizeof(*ap)); + tp = (Cell **) calloc(n, sizeof(*tp)); if (ap == NULL || tp == NULL) FATAL("out of space in makesymtab"); ap->nelem = 0; @@ -238,7 +242,7 @@ Cell *setsymtab(const char *n, const char *s, Awkfloat f, unsigned t, Array *tp) (void*)p, NN(p->nval), NN(p->sval), p->fval, p->tval); return(p); } - p = malloc(sizeof(*p)); + p = (Cell *) malloc(sizeof(*p)); if (p == NULL) FATAL("out of space for symbol table at %s", n); p->nval = tostring(n); @@ -273,7 +277,7 @@ void rehash(Array *tp) /* rehash items in small table into big one */ Cell *cp, *op, **np; nsz = GROWTAB * tp->size; - np = calloc(nsz, sizeof(*np)); + np = (Cell **) calloc(nsz, sizeof(*np)); if (np == NULL) /* can't do it, but can keep running. */ return; /* someone else will run out later. */ for (i = 0; i < tp->size; i++) { @@ -400,9 +404,15 @@ Awkfloat getfval(Cell *vp) /* get float val of a Cell */ else if (isrec(vp) && !donerec) recbld(); if (!isnum(vp)) { /* not a number */ - vp->fval = atof(vp->sval); /* best guess */ - if (is_number(vp->sval) && !(vp->tval&CON)) - vp->tval |= NUM; /* make NUM only sparingly */ + double fval; + bool no_trailing; + + if (is_valid_number(vp->sval, true, & no_trailing, & fval)) { + vp->fval = fval; + if (no_trailing && !(vp->tval&CON)) + vp->tval |= NUM; /* make NUM only sparingly */ + } else + vp->fval = 0.0; } DPRINTF("getfval %p: %s = %g, t=%o\n", (void*)vp, NN(vp->nval), vp->fval, vp->tval); @@ -521,7 +531,7 @@ char *tostringN(const char *s, size_t n) /* make a copy of string s */ { char *p; - p = malloc(n); + p = (char *) malloc(n); if (p == NULL) FATAL("out of space in tostringN %zu", n); if (strlcpy(p, s, n) >= n) @@ -536,13 +546,13 @@ Cell *catstr(Cell *a, Cell *b) /* concatenate a and b */ char *sa = getsval(a); char *sb = getsval(b); size_t l = strlen(sa) + strlen(sb) + 1; - p = malloc(l); + p = (char *) malloc(l); if (p == NULL) FATAL("out of space concatenating %s and %s", sa, sb); snprintf(p, l, "%s%s", sa, sb); l++; // add room for ' ' - char *newbuf = malloc(l); + char *newbuf = (char *) malloc(l); if (newbuf == NULL) FATAL("out of space concatenating %s and %s", sa, sb); // See string() in lex.c; a string "xx" is stored in the symbol @@ -561,7 +571,7 @@ char *qstring(const char *is, int delim) /* collect string up to next delim */ const uschar *s = (const uschar *) is; uschar *buf, *bp; - if ((buf = malloc(strlen(is)+3)) == NULL) + if ((buf = (uschar *) malloc(strlen(is)+3)) == NULL) FATAL( "out of space in qstring(%s)", s); for (bp = buf; (c = *s) != delim; s++) { if (c == '\n') |