bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

gawk: improved non-numeric testing patch


From: Aharon Robbins
Subject: gawk: improved non-numeric testing patch
Date: Mon, 11 Oct 2004 11:08:58 +0200

Greetings.  I recently posted a patch to gawk for "improved" handling of
non-numeric constants, such that numbers like 00.34 didn't get
confused as being octal.  Stepan Kasal pointed out some problems with
my patch.  Here is an improved patch, relative to distributed gawk 3.1.4.

Arnold
----------------------------------------------------
--- ../gawk-3.1.4/awk.h 2004-07-26 17:11:05.000000000 +0300
+++ awk.h       2004-10-03 22:59:47.000000000 +0200
@@ -742,8 +744,6 @@
 /* ------------------------- Pseudo-functions ------------------------- */
 
 #define is_identchar(c)                (isalnum(c) || (c) == '_')
-#define isnondecimal(str)      (((str)[0]) == '0' && (ISDIGIT((str)[1]) \
-                                       || (str)[1] == 'x' || (str)[1] == 'X'))
 
 #define var_uninitialized(n)   ((n)->var_value == Nnull_string)
 
@@ -1138,6 +1138,7 @@
 extern int avoid_dfa P((NODE *re, char *str, size_t len));     /* temporary */
 extern int reisstring P((const char *text, size_t len, Regexp *re, const char 
*buf));
 extern int remaybelong P((const char *text, size_t len));
+extern int isnondecimal P((const char *str, int use_locale));
 
 /* strncasecmp.c */
 #ifndef BROKEN_STRNCASECMP
--- ../gawk-3.1.4/awkgram.y     2004-07-26 17:11:12.000000000 +0300
+++ awkgram.y   2004-10-11 11:01:55.000000000 +0200
@@ -2069,12 +2058,14 @@
                        eof_warned = TRUE;
                }
                tokadd('\0');
-               if (! do_traditional && isnondecimal(tokstart)) {
-                       static short warned = FALSE;
-                       if (do_lint && ! warned) {
-                               warned = TRUE;
-                               lintwarn("numeric constant `%.*s' treated as 
octal or hexadecimal",
-                                       strlen(tokstart)-1, tokstart);
+               if (! do_traditional && isnondecimal(tokstart, FALSE)) {
+                       if (do_lint) {
+                               if (ISDIGIT(tokstart[1]))       /* not an 'x' 
or 'X' */
+                                       lintwarn("numeric constant `%.*s' 
treated as octal",
+                                               strlen(tokstart)-1, tokstart);
+                               else if (tokstart[1] == 'x' || tokstart[1] == 
'X')
+                                       lintwarn("numeric constant `%.*s' 
treated as hexadecimal",
+                                               strlen(tokstart)-1, tokstart);
                        }
                        yylval.nodeval = make_number(nondec2awknum(tokstart, 
strlen(tokstart)));
                } else
--- ../gawk-3.1.4/builtin.c     2004-07-13 10:55:28.000000000 +0300
+++ builtin.c   2004-10-03 23:04:10.000000000 +0200
@@ -2779,7 +2773,7 @@
 
        if ((tmp->flags & (NUMBER|NUMCUR)) != 0)
                d = (double) force_number(tmp);
-       else if (isnondecimal(tmp->stptr))
+       else if (isnondecimal(tmp->stptr, TRUE))
                d = nondec2awknum(tmp->stptr, tmp->stlen);
        else
                d = (double) force_number(tmp);
--- ../gawk-3.1.4/node.c        2004-07-28 16:45:04.000000000 +0300
+++ node.c      2004-10-11 11:04:18.000000000 +0200
@@ -91,7 +91,7 @@
 
        if (do_non_decimal_data) {
                errno = 0;
-               if (! do_traditional && isnondecimal(cp)) {
+               if (! do_traditional && isnondecimal(cp, TRUE)) {
                        n->numbr = nondec2awknum(cp, cpend - cp);
                        goto finish;
                }
@@ -584,3 +584,37 @@
                return c;
        }
 }
+
+/* isnondecimal --- return true if number is not a decimal number */
+
+int
+isnondecimal(const char *str, int use_locale)
+{
+       int dec_point = '.';
+#if ENABLE_NLS && defined(HAVE_LOCALE_H)
+       if (use_locale)
+               dec_point = loc.decimal_point[0];       /* XXX --- assumes one 
char */
+#endif
+
+       if (str[0] != '0')
+               return FALSE;
+
+       /* leading 0x or 0X */
+       if (str[1] == 'x' || str[1] == 'X')
+               return TRUE;
+
+       /*
+        * Numbers with '.', 'e', or 'E' are decimal.
+        * Have to check so that things like 00.34 are handled right.
+        *
+        * These beasts can have trailing whitespace. Deal with that too.
+        */
+       for (; *str != '\0'; str++) {
+               if (*str == 'e' || *str == 'E' || *str == dec_point)
+                       return FALSE;
+               else if (! ISDIGIT(*str))
+                       break;
+       }
+
+       return TRUE;
+}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]