/* PSPPIRE - a graphical user interface for PSPP.
- Copyright (C) 2008, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2010, 2011, 2014 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include <config.h>
-#include <ui/syntax-gen.h>
+#include "ui/syntax-gen.h"
#include <ctype.h>
#include <mbchar.h>
#include "data/value.h"
#include "libpspp/assertion.h"
#include "libpspp/cast.h"
+#include "libpspp/i18n.h"
#include "libpspp/message.h"
+#include "data/settings.h"
#include "libpspp/str.h"
+#include "libpspp/misc.h"
+
+#include "gl/c-ctype.h"
+#include "gl/ftoastr.h"
/* Appends to OUTPUT a pair of hex digits for each byte in IN. */
static void
for (i = 0; i < in.length; i++)
{
unsigned char c = in.string[i];
- ds_put_char (output, "0123456789ABCDEF"[c >> 4]);
- ds_put_char (output, "0123456789ABCDEF"[c & 0xf]);
+ ds_put_byte (output, "0123456789ABCDEF"[c >> 4]);
+ ds_put_byte (output, "0123456789ABCDEF"[c & 0xf]);
}
}
static bool
has_single_quote (struct substring str)
{
- return (SIZE_MAX != ss_find_char (str, '\''));
+ return (SIZE_MAX != ss_find_byte (str, '\''));
}
static bool
has_double_quote (struct substring str)
{
- return (SIZE_MAX != ss_find_char (str, '"'));
+ return (SIZE_MAX != ss_find_byte (str, '"'));
}
/* Appends to OUTPUT valid PSPP syntax for a quoted string that
{
ds_put_cstr (output, "X'");
syntax_gen_hex_digits (output, in);
- ds_put_char (output, '\'');
+ ds_put_byte (output, '\'');
}
else
{
assert (is_basic ('\''));
quote = has_double_quote (in) && !has_single_quote (in) ? '\'' : '"';
- ds_put_char (output, quote);
+ ds_put_byte (output, quote);
for (i = 0; i < in.length; i++)
{
char c = in.string[i];
if (c == quote)
- ds_put_char (output, quote);
- ds_put_char (output, c);
+ ds_put_byte (output, quote);
+ ds_put_byte (output, c);
}
- ds_put_char (output, quote);
+ ds_put_byte (output, quote);
}
}
& (FMT_CAT_DATE | FMT_CAT_TIME | FMT_CAT_DATE_COMPONENT)))
{
union value v_in, v_out;
- char *s;
+ char *s, *error;
bool ok;
v_in.f = number;
- s = data_out (&v_in, "FIXME", format);
- msg_disable ();
+ s = data_out (&v_in, "FIXME", format, settings_get_fmt_settings ());
+
/* FIXME: UTF8 encoded strings will fail here */
- ok = data_in (ss_cstr (s), LEGACY_NATIVE,
- format->type, 0, 0, NULL, &v_out, 0);
- msg_enable ();
+ error = data_in (ss_cstr (s), C_ENCODING, format->type,
+ settings_get_fmt_settings (), &v_out, 0, NULL);
+ ok = error == NULL;
+ free (error);
+
if (ok && v_out.f == number)
{
syntax_gen_string (output, ss_cstr (s));
ds_put_cstr (output, "SYSMIS");
else
{
- /* FIXME: This should consistently yield precisely the same
- value as NUMBER on input, but its results for values
- cannot be exactly represented in decimal are ugly: many
- of them will have far more decimal digits than are
- needed. The free-format floating point output routine
- from Steele and White, "How to Print Floating-Point
- Numbers Accurately" is really what we want. The MPFR
- library has an implementation of this, or equivalent
- functionality, in its mpfr_strtofr routine, but it would
- not be nice to make PSPP depend on this. Probably, we
- should implement something equivalent to it. */
- ds_put_format (output, "%.*g", DBL_DIG + 1, number);
+ char s[DBL_BUFSIZE_BOUND];
+
+ c_dtoastr (s, sizeof s, 0, 0, number);
+ ds_put_cstr (output, s);
}
}
if (width == 0)
syntax_gen_number (output, value->f, format);
else
- {
- char *s = CHAR_CAST_BUG (char *, value_str (value, width));
- syntax_gen_string (output, ss_buffer (s, width));
- }
+ syntax_gen_string (output,
+ ss_buffer (CHAR_CAST (const char *, value->s), width));
}
/* Appends <low> THRU <high> to OUTPUT. If LOW is LOWEST, then
{
for (;;)
{
+ char qualifier[16];
+ int precision = -1;
+ char directive;
size_t copy = strcspn (format, "%");
ds_put_substring (output, ss_buffer (format, copy));
format += copy;
return;
assert (*format == '%');
format++;
- switch (*format++)
+ directive = *format++;
+ if (directive == '.')
+ {
+ int x = 0;
+ while (directive = *format++, c_isdigit (directive))
+ {
+ assert (x < 16);
+ qualifier[x++] = directive;
+ }
+ qualifier[x++] = '\0';
+ precision = atoi (qualifier);
+ }
+ switch (directive)
{
case 's':
{
break;
case 'f':
+ case 'g':
{
+ char conv[32];
double d = va_arg (args, double);
- switch (*format++)
+ int x = 0;
+ conv[x++] = '%';
+ conv[x] = '\0';
+ if (precision != -1)
{
- case 'p':
- ds_put_format (output, "%f", d);
- break;
- default:
- NOT_REACHED ();
+ strcat (conv, ".");
+ strcat (conv, qualifier);
+ x += strlen (qualifier) + 1;
}
+ conv[x++] = directive;
+ conv[x++] = '\0';
+
+ ds_put_c_format (output, conv, d);
break;
}
case '%':
- ds_put_char (output, '%');
+ ds_put_byte (output, '%');
break;
default:
%d: Same as printf's %d.
- %fp: The double argument is formatted precisely as a PSPP
- number, as if with a call to syntax_gen_number with a
- null FORMAT argument.
+ %f %g: Same as printf.
%%: Literal %.