str.c: New functions ds_put_c_vformat and ds_put_c_format
authorJohn Darrington <john@darrington.wattle.id.au>
Sat, 22 Dec 2012 16:40:09 +0000 (17:40 +0100)
committerJohn Darrington <john@darrington.wattle.id.au>
Sun, 23 Dec 2012 16:18:08 +0000 (17:18 +0100)
Added a new printf-like functions which are locale independent.
Added this new function, and changed syntax_gen_pspp_valist to use it.
Rationale: syntax generation should never be locale dependent.

src/libpspp/str.c
src/libpspp/str.h
src/ui/syntax-gen.c

index 79e9ea1e14dae1def667b3f4edd1ea60f4e0ac5d..a58c52c36ef5d096fd937fd38d61b142e6705541 100644 (file)
@@ -28,6 +28,7 @@
 #include "libpspp/message.h"
 #include "libpspp/pool.h"
 
+#include "gl/c-vasnprintf.h"
 #include "gl/relocatable.h"
 #include "gl/minmax.h"
 #include "gl/xalloc.h"
@@ -1499,22 +1500,36 @@ ds_put_format (struct string *st, const char *format, ...)
   va_end (args);
 }
 
-/* Formats FORMAT as a printf string and appends the result to ST. */
+/* Formats FORMAT as a printf string as if in the C locale and appends the result to ST. */
 void
-ds_put_vformat (struct string *st, const char *format, va_list args_)
+ds_put_c_format (struct string *st, const char *format, ...)
+{
+  va_list args;
+
+  va_start (args, format);
+  ds_put_c_vformat (st, format, args);
+  va_end (args);
+}
+
+
+/* Formats FORMAT as a printf string, using fmt_func (a snprintf like function) 
+   and appends the result to ST. */
+static void
+ds_put_vformat_int (struct string *st, const char *format, va_list args_,
+                   int (*fmt_func) (char *, size_t, const char *, va_list))
 {
   int avail, needed;
   va_list args;
 
   va_copy (args, args_);
   avail = st->ss.string != NULL ? st->capacity - st->ss.length + 1 : 0;
-  needed = vsnprintf (st->ss.string + st->ss.length, avail, format, args);
+  needed = fmt_func (st->ss.string + st->ss.length, avail, format, args);
   va_end (args);
 
   if (needed >= avail)
     {
       va_copy (args, args_);
-      vsprintf (ds_put_uninit (st, needed), format, args);
+      fmt_func (ds_put_uninit (st, needed), needed + 1, format, args);
       va_end (args);
     }
   else
@@ -1527,13 +1542,36 @@ ds_put_vformat (struct string *st, const char *format, va_list args_)
           avail = st->capacity - st->ss.length + 1;
 
           va_copy (args, args_);
-          needed = vsnprintf (ds_end (st), avail, format, args);
+          needed = fmt_func (ds_end (st), avail, format, args);
           va_end (args);
         }
       st->ss.length += needed;
     }
 }
 
+
+static int
+vasnwrapper (char *str, size_t size,  const char *format, va_list ap)
+{
+  c_vasnprintf (str, &size, format, ap);
+  return size;
+}
+
+/* Formats FORMAT as a printf string and appends the result to ST. */
+void
+ds_put_vformat (struct string *st, const char *format, va_list args_)
+{
+  ds_put_vformat_int (st, format, args_, vsnprintf);
+}
+
+/* Formats FORMAT as a printf string, as if in the C locale, 
+   and appends the result to ST. */
+void
+ds_put_c_vformat (struct string *st, const char *format, va_list args_)
+{
+  ds_put_vformat_int (st, format, args_, vasnwrapper);
+}
+
 /* Appends byte CH to ST. */
 void
 ds_put_byte (struct string *st, int ch)
index c8ab726797f8fbf82bdea0e336059d1ab1eec895..99cc7afc31b018138c8632ea3aeaa08973da3592 100644 (file)
@@ -227,8 +227,14 @@ void ds_put_cstr (struct string *, const char *);
 void ds_put_substring (struct string *, struct substring);
 void ds_put_vformat (struct string *st, const char *, va_list)
      PRINTF_FORMAT (2, 0);
+void ds_put_c_vformat (struct string *st, const char *, va_list)
+     PRINTF_FORMAT (2, 0);
+
 void ds_put_format (struct string *, const char *, ...)
      PRINTF_FORMAT (2, 3);
+void ds_put_c_format (struct string *, const char *, ...)
+     PRINTF_FORMAT (2, 3);
+
 char *ds_put_uninit (struct string *st, size_t incr);
 
 char *ds_splice_uninit (struct string *, size_t ofs, size_t old_len,
index bcec18e5565bab56169eee50766d541c9f5e0999..fe88e62913d776cbc83331dbda25e6e09a018855 100644 (file)
@@ -271,7 +271,7 @@ syntax_gen_pspp_valist (struct string *output, const char *format,
             switch (*format++)
               {
               case 'p':
-                ds_put_format (output, "%f", d);
+                ds_put_c_format (output, "%f", d);
                 break;
               default:
                 NOT_REACHED ();