NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
bin/44013: awk fails to parse numeric constants when LC_NUMERIC is set
>Number: 44013
>Category: bin
>Synopsis: awk fails to parse numeric constants when LC_NUMERIC is set
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Oct 30 08:30:00 +0000 2010
>Originator: Dominik Zaczkowski
>Release: 5.1_RC4
>Organization:
>Environment:
NetBSD kraina-oz.ath.cx 5.1_RC4 NetBSD 5.1_RC4 (GENERIC) #0: Thu Oct 28
23:40:02 CEST 2010
root%kraina-oz.ath.cx@localhost:/usr/obj/usr/obj/netbsd-5/src/sys/arch/i386/compile/GENERIC
i386
>Description:
AWK standard(?)
http://www.opengroup.org/onlinepubs/009695399/utilities/awk.html says that
LC_NUMERIC should affect only input and constants in program should always use
'.' for decimal separator. AWK however tries to respect LC_NUMERIC for fp
constants, in result its impossible to put fp constant in program when
LC_NUMERIC is set to locale in which decimal separator is something different
than '.'
>How-To-Repeat:
dominik@kraina-oz$ awk 'BEGIN {print 5 * 0.5}'
awk: syntax error at source line 1
context is
BEGIN {print 5 * >>> 0.5 <<<
awk: illegal statement at source line 1
in pl locale ',' is decimal separator...
dominik@kraina-oz$ locale|grep LC_NUMERIC
LC_NUMERIC="pl_PL.ISO8859-2"
dominik@kraina-oz$ awk 'BEGIN {print 5 * 0,5}'
0 5
dominik@kraina-oz$ LC_NUMERIC=C awk 'BEGIN {print 5 * 0.5}'
2.5
>Fix:
My fix is to provide locale independent version of strtod.
cd /usr/src && patch < this_patch_below
--- dist/nawk/lex.c 2010-10-29 15:54:06.000000000 +0200
+++ /root/lex.c 2010-10-29 15:53:03.000000000 +0200
@@ -26,10 +26,13 @@
#include "nbtool_config.h"
#endif
+#include <sys/cdefs.h> /* for __restrict */
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
+#include <locale.h>
#include "awk.h"
#include "awkgram.h"
@@ -50,6 +53,7 @@
int peek(void);
int gettok(char **, int *);
int binsearch(const char *, const Keyword *, int);
+static double c_locale_strtod(const char * __restrict nptr, char ** __restrict
endptr);
const Keyword keywords[] ={ /* keep sorted: binary searched */
{ "BEGIN", XBEGIN, XBEGIN },
@@ -156,7 +160,7 @@
}
}
*bp = 0;
- strtod(buf, &rem); /* parse the number */
+ c_locale_strtod(buf, &rem); /* parse the number */
if (rem == (char *)buf) { /* it wasn't a valid number at
all */
buf[1] = 0; /* return one character as token */
retc = buf[0]; /* character is its own type */
@@ -201,7 +205,8 @@
if (isalpha(c) || c == '_')
return word(buf);
if (isdigit(c)) {
- yylval.cp = setsymtab(buf, tostring(buf), atof(buf),
CON|NUM, symtab);
+ yylval.cp = setsymtab(buf, tostring(buf),
+ c_locale_strtod(buf, NULL), CON|NUM, symtab);
/* should this also have STR set? */
RET(NUMBER);
}
@@ -594,3 +599,14 @@
for (i = strlen(s)-1; i >= 0; i--)
unput(s[i]);
}
+
+static double
+c_locale_strtod(const char * __restrict nptr, char ** __restrict endptr)
+{
+ double ret;
+
+ setlocale(LC_NUMERIC, "C");
+ ret = strtod(nptr, endptr);
+ setlocale(LC_NUMERIC, "");
+ return ret;
+}
Home |
Main Index |
Thread Index |
Old Index