[PATCH 4/4] Fix the XML gps parsing and saving when using non-US locales

Linus Torvalds torvalds at linux-foundation.org
Sun Nov 18 10:22:11 PST 2012

From: Linus Torvalds <torvalds at linux-foundation.org>
Date: Sun, 18 Nov 2012 07:55:41 -1000
Subject: [PATCH 4/4] Fix the XML gps parsing and saving when using non-US locales

The GPS parsing and saving was using sscanf and sprintf respecively, and
since it is using floating point values (boo!) that affects both of
them.  In a C/US locale, we use a period for decimal values, while most
European locales use a comma.

We really should probably just fix things to use integer values (degrees
and nanodegrees?) but this is the simplest fix/workaround for the issue.

Probably nobody ever really noticed until I tested the Swedish locale
for grins, since we don't have a good way to actually set the GPS
coordinates yet.  I've got a few dives with GPS information that I
entered manually.

Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>

The f*cking behavior of sscanf/sprintf with floating point values and 
locales is really annoying. The C standards people were $%!#@ morons: the 
locale should change printf etc only if there was some "use locale" 
modifier to the printf control string.

Oh well. We'll have to take the reality of incompetent people into 
account. And I'd actually want to avoid using floating point anywhere 
in subsurface (except for conversion for input/output), so maybe I'll 
convert the position values to integer pairs or something. 

Some day.

 parse-xml.c | 10 +++-------
 save-xml.c  | 10 ++++++++--
 2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/parse-xml.c b/parse-xml.c
index f62ce98917ac..15138f43e8b2 100644
--- a/parse-xml.c
+++ b/parse-xml.c
@@ -1045,15 +1045,11 @@ static int uddf_dive_match(struct dive **divep, const char *name, int len, char
 static void gps_location(char *buffer, void *_dive)
-	int i;
+	char *end;
 	struct dive *dive = _dive;
-	double latitude, longitude;
-	i = sscanf(buffer, "%lf %lf", &latitude, &longitude);
-	if (i == 2) {
-		dive->latitude = latitude;
-		dive->longitude = longitude;
-	}
+	dive->latitude = g_ascii_strtod(buffer, &end);
+	dive->longitude = g_ascii_strtod(end, &end);
diff --git a/save-xml.c b/save-xml.c
index 824763c44f74..a70aacc3e543 100644
--- a/save-xml.c
+++ b/save-xml.c
@@ -193,8 +193,14 @@ static void show_location(FILE *f, struct dive *dive)
 	if (latitude || longitude) {
 		int len = snprintf(buffer, sizeof(buffer)-4,
-			"  <location gps='%.12g %.12g'>",
-			latitude, longitude);
+			"  <location gps=");
+		char *buf = buffer + len;
+		len = strlen(g_ascii_formatd(buf, 80, "'%.12g ", latitude));
+		buf += len;
+		len = strlen(g_ascii_formatd(buf, 80, "%.12g'>", longitude));
+		buf += len;
+		len = buf - buffer;
 		if (!dive->location) {
 			memcpy(&buffer[len-1], "/>\n", 4);
 			fputs(buffer, f);

More information about the subsurface mailing list