From: John Darrington Date: Sat, 22 Dec 2012 16:40:09 +0000 (+0100) Subject: str.c: New functions ds_put_c_vformat and ds_put_c_format X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b54cf7b8d3259f5de57a2e0ca53fa2e2c5185abf;p=pspp str.c: New functions ds_put_c_vformat and ds_put_c_format 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. --- diff --git a/src/libpspp/str.c b/src/libpspp/str.c index 79e9ea1e14..a58c52c36e 100644 --- a/src/libpspp/str.c +++ b/src/libpspp/str.c @@ -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) diff --git a/src/libpspp/str.h b/src/libpspp/str.h index c8ab726797..99cc7afc31 100644 --- a/src/libpspp/str.h +++ b/src/libpspp/str.h @@ -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, diff --git a/src/ui/syntax-gen.c b/src/ui/syntax-gen.c index bcec18e556..fe88e62913 100644 --- a/src/ui/syntax-gen.c +++ b/src/ui/syntax-gen.c @@ -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 ();