1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2008, 2010, 2011 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include "ui/syntax-gen.h"
24 #include "data/data-in.h"
25 #include "data/data-out.h"
26 #include "data/format.h"
27 #include "data/value.h"
28 #include "libpspp/assertion.h"
29 #include "libpspp/cast.h"
30 #include "libpspp/i18n.h"
31 #include "libpspp/message.h"
32 #include "libpspp/str.h"
34 #include "gl/ftoastr.h"
36 /* Appends to OUTPUT a pair of hex digits for each byte in IN. */
38 syntax_gen_hex_digits (struct string *output, struct substring in)
41 for (i = 0; i < in.length; i++)
43 unsigned char c = in.string[i];
44 ds_put_byte (output, "0123456789ABCDEF"[c >> 4]);
45 ds_put_byte (output, "0123456789ABCDEF"[c & 0xf]);
49 /* Returns true if IN contains any control characters, false
52 has_control_chars (struct substring in)
56 for (i = 0; i < in.length; i++)
57 if (iscntrl ((unsigned char) in.string[i]))
63 has_single_quote (struct substring str)
65 return (SIZE_MAX != ss_find_byte (str, '\''));
69 has_double_quote (struct substring str)
71 return (SIZE_MAX != ss_find_byte (str, '"'));
74 /* Appends to OUTPUT valid PSPP syntax for a quoted string that
77 IN must be encoded in UTF-8, and the quoted result will also
80 The string will be output as a regular quoted string unless it
81 contains control characters, in which case it is output as a
84 syntax_gen_string (struct string *output, struct substring in)
86 if (has_control_chars (in))
88 ds_put_cstr (output, "X'");
89 syntax_gen_hex_digits (output, in);
90 ds_put_byte (output, '\'');
97 /* This seemingly simple implementation is possible, because UTF-8
98 guarantees that bytes corresponding to basic characters (such as
99 '\'') cannot appear in a multi-byte character sequence except to
100 represent that basic character.
102 assert (is_basic ('\''));
104 quote = has_double_quote (in) && !has_single_quote (in) ? '\'' : '"';
105 ds_put_byte (output, quote);
106 for (i = 0; i < in.length; i++)
108 char c = in.string[i];
110 ds_put_byte (output, quote);
111 ds_put_byte (output, c);
113 ds_put_byte (output, quote);
117 /* Appends to OUTPUT a representation of NUMBER in PSPP syntax.
118 The representation is precise, that is, when PSPP parses the
119 representation, its value will be exactly NUMBER. (This might
120 not be the case on a C implementation where double has a
121 different representation.)
123 If NUMBER is the system-missing value, it is output as the
124 identifier SYSMIS. This may not be appropriate, because
125 SYSMIS is not consistently parsed throughout PSPP syntax as
126 the system-missing value. But in such circumstances the
127 system-missing value would not be meaningful anyhow, so the
128 caller should refrain from supplying the system-missing value
131 A value of LOWEST or HIGHEST is not treated specially.
133 If FORMAT is null, then the representation will be in numeric
134 form, e.g. 123 or 1.23e10.
136 If FORMAT is non-null, then it must point to a numeric format.
137 If the format is one easier for a user to understand when
138 expressed as a string than as a number (for example, a date
139 format), and the string representation precisely represents
140 NUMBER, then the string representation is written to OUTPUT.
141 Otherwise, NUMBER is output as if FORMAT was a null
144 syntax_gen_number (struct string *output,
145 double number, const struct fmt_spec *format)
147 assert (format == NULL || fmt_is_numeric (format->type));
150 & (FMT_CAT_DATE | FMT_CAT_TIME | FMT_CAT_DATE_COMPONENT)))
152 union value v_in, v_out;
157 s = data_out (&v_in, "FIXME", format);
159 /* FIXME: UTF8 encoded strings will fail here */
160 error = data_in (ss_cstr (s), C_ENCODING, format->type, &v_out, 0, NULL);
164 if (ok && v_out.f == number)
166 syntax_gen_string (output, ss_cstr (s));
173 if (number == SYSMIS)
174 ds_put_cstr (output, "SYSMIS");
177 char s[DBL_BUFSIZE_BOUND];
179 dtoastr (s, sizeof s, 0, 0, number);
180 ds_put_cstr (output, s);
184 /* Appends to OUTPUT a representation of VALUE, which has the
185 specified WIDTH. If FORMAT is non-null, it influences the
186 output format. The representation is precise, that is, when
187 PSPP parses the representation, its value will be exactly
190 syntax_gen_value (struct string *output, const union value *value, int width,
191 const struct fmt_spec *format)
193 assert (format == NULL || fmt_var_width (format) == width);
195 syntax_gen_number (output, value->f, format);
198 char *s = CHAR_CAST_BUG (char *, value_str (value, width));
199 syntax_gen_string (output, ss_buffer (s, width));
203 /* Appends <low> THRU <high> to OUTPUT. If LOW is LOWEST, then
204 it is formatted as the identifier LO; if HIGH is HIGHEST, then
205 it is formatted as the identifier HI. Otherwise, LOW and HIGH
206 are formatted as with a call to syntax_gen_num with the specified
209 This is the opposite of the function parse_num_range. */
211 syntax_gen_num_range (struct string *output, double low, double high,
212 const struct fmt_spec *format)
215 ds_put_cstr (output, "LO");
217 syntax_gen_number (output, low, format);
219 ds_put_cstr (output, " THRU ");
222 ds_put_cstr (output, "HI");
224 syntax_gen_number (output, high, format);
227 /* Same as syntax_gen_pspp, below, but takes a va_list. */
229 syntax_gen_pspp_valist (struct string *output, const char *format,
234 size_t copy = strcspn (format, "%");
235 ds_put_substring (output, ss_buffer (format, copy));
240 assert (*format == '%');
246 const char *s = va_arg (args, char *);
250 syntax_gen_string (output, ss_cstr (s));
253 ds_put_cstr (output, s);
263 int i = va_arg (args, int);
264 ds_put_format (output, "%d", i);
270 double d = va_arg (args, double);
274 ds_put_format (output, "%f", d);
283 ds_put_byte (output, '%');
292 /* printf-like function specialized for outputting PSPP syntax.
293 FORMAT is appended to OUTPUT. The following substitutions are
296 %sq: The char * argument is formatted as a PSPP string, as
297 if with a call to syntax_gen_string.
299 %ss: The char * argument is appended literally.
301 %d: Same as printf's %d.
303 %fp: The double argument is formatted precisely as a PSPP
304 number, as if with a call to syntax_gen_number with a
305 null FORMAT argument.
309 (These substitutions were chosen to allow GCC to check for
310 correct argument types.)
312 This function is somewhat experimental. If it proves useful,
313 the allowed substitutions will almost certainly be
316 syntax_gen_pspp (struct string *output, const char *format, ...)
319 va_start (args, format);
320 syntax_gen_pspp_valist (output, format, args);