diff options
author | Andrew J. Schorr <aschorr@telemetry-investments.com> | 2016-06-29 14:25:31 -0400 |
---|---|---|
committer | Andrew J. Schorr <aschorr@telemetry-investments.com> | 2016-06-29 14:25:31 -0400 |
commit | 2ab2d5f2c468b647615d984cb7953217c63695af (patch) | |
tree | 6bce09ff8f8b9ea7e8e6c890c70b21d34e18edb5 /node.c | |
parent | 6e3f3560c1be80583b4045a627e483c572c895b3 (diff) | |
download | egawk-2ab2d5f2c468b647615d984cb7953217c63695af.tar.gz egawk-2ab2d5f2c468b647615d984cb7953217c63695af.tar.bz2 egawk-2ab2d5f2c468b647615d984cb7953217c63695af.zip |
Optimize r_force_number and fix obscure bug in get_ieee_magic_val.
Diffstat (limited to 'node.c')
-rw-r--r-- | node.c | 42 |
1 files changed, 24 insertions, 18 deletions
@@ -30,7 +30,7 @@ static int is_ieee_magic_val(const char *val); static NODE *r_make_number(double x); -static AWKNUM get_ieee_magic_val(const char *val); +static AWKNUM get_ieee_magic_val(char *val); extern NODE **fmt_list; /* declared in eval.c */ NODE *(*make_number)(double) = r_make_number; @@ -77,10 +77,21 @@ r_force_number(NODE *n) n->flags |= NUMCUR; n->numbr = 0.0; - if (n->stlen == 0) - goto badnum; - + /* Trim leading white space, bailing out if there's nothing else */ cp = n->stptr; + cpend = cp + n->stlen; + while (1) { + if (cp == cpend) + goto badnum; + if (!isspace((unsigned char) *cp)) + break; + cp++; + } + /* At this point, we know the string is not entirely white space */ + /* Trim trailing white space */ + while (isspace((unsigned char) cpend[-1])) + cpend--; + /* * 2/2007: * POSIX, by way of severe language lawyering, seems to @@ -91,8 +102,8 @@ r_force_number(NODE *n) if (! do_posix) { if (is_alpha((unsigned char) *cp)) goto badnum; - else if (n->stlen == 4 && is_ieee_magic_val(n->stptr)) { - n->numbr = get_ieee_magic_val(n->stptr); + else if (cpend == cp+4 && is_ieee_magic_val(cp)) { + n->numbr = get_ieee_magic_val(cp); goto goodnum; } /* else @@ -101,12 +112,7 @@ r_force_number(NODE *n) /* else POSIX, so fall through */ - cpend = cp + n->stlen; - while (cp < cpend && isspace((unsigned char) *cp)) - cp++; - - if ( cp == cpend /* only spaces, or */ - || (! do_posix /* not POSIXLY paranoid and */ + if ( (! do_posix /* not POSIXLY paranoid and */ && (is_alpha((unsigned char) *cp) /* letter, or */ /* CANNOT do non-decimal and saw 0x */ || (! do_non_decimal_data && is_hex(cp))))) { @@ -116,7 +122,7 @@ r_force_number(NODE *n) if (cpend - cp == 1) { /* only one character */ if (isdigit((unsigned char) *cp)) { /* it's a digit! */ n->numbr = (AWKNUM)(*cp - '0'); - if (cp == n->stptr) /* no leading spaces */ + if (n->stlen == 1) /* no white space */ n->flags |= NUMINT; goto goodnum; } @@ -135,10 +141,6 @@ r_force_number(NODE *n) *cpend = save; } - /* POSIX says trailing space is OK for NUMBER */ - while (ptr < cpend && isspace((unsigned char) *ptr)) - ptr++; - if (errno == 0) { if (ptr == cpend) goto goodnum; @@ -937,14 +939,18 @@ is_ieee_magic_val(const char *val) /* get_ieee_magic_val --- return magic value for string */ static AWKNUM -get_ieee_magic_val(const char *val) +get_ieee_magic_val(char *val) { static bool first = true; static AWKNUM inf; static AWKNUM nan; + char save; char *ptr; + save = val[4]; + val[4] = '\0'; AWKNUM v = strtod(val, &ptr); + val[4] = save; if (val == ptr) { /* Older strtod implementations don't support inf or nan. */ if (first) { |