#include "data/file-handle-def.h"
#include "language/lexer/lexer.h"
+#include "language/lexer/format-parser.h"
#include "libpspp/assertion.h"
#include "libpspp/compiler.h"
#include "libpspp/i18n.h"
string_map_insert (&options, "box", box);
register_driver (&options, "-");
- /* Render to <base>.txt. */
- register_driver (&options, "%s.txt", output_base);
#ifdef HAVE_CAIRO
/* Render to <base>.pdf. */
register_driver (&options, "%s.pdf", output_base);
#endif
- /* Render to <base>.csv. */
+ register_driver (&options, "%s.txt", output_base);
register_driver (&options, "%s.csv", output_base);
-
- /* Render to <base>.odt. */
register_driver (&options, "%s.odt", output_base);
+ register_driver (&options, "%s.spv", output_base);
string_map_destroy (&options);
}
exit (EXIT_SUCCESS);
}
+static bool
+parse_settings_value_show (struct lexer *lexer, const char *name,
+ enum settings_value_show *show)
+{
+ if (lex_match_id (lexer, name))
+ {
+ if (!lex_force_match (lexer, T_EQUALS))
+ exit (1);
+
+ if (lex_match_id (lexer, "DEFAULT"))
+ *show = SETTINGS_VALUE_SHOW_DEFAULT;
+ else if (lex_match_id (lexer, "VALUE"))
+ *show = SETTINGS_VALUE_SHOW_VALUE;
+ else if (lex_match_id (lexer, "LABEL"))
+ *show = SETTINGS_VALUE_SHOW_LABEL;
+ else if (lex_match_id (lexer, "BOTH"))
+ *show = SETTINGS_VALUE_SHOW_BOTH;
+ else
+ {
+ lex_error_expecting (lexer, "DEFAULT", "VALUE", "LABEL", "BOTH");
+ exit (1);
+ }
+
+ return true;
+ }
+ else
+ return false;
+}
+
+static bool
+parse_string_setting (struct lexer *lexer, const char *name, char **stringp)
+{
+ if (lex_match_id (lexer, name))
+ {
+ lex_match (lexer, T_EQUALS);
+ if (!lex_force_string (lexer))
+ exit (1);
+
+ free (*stringp);
+ *stringp = xstrdup (lex_tokcstr (lexer));
+
+ lex_get (lexer);
+ return true;
+ }
+ else
+ return false;
+}
+
+static void
+read_value_option (struct lexer *lexer, struct pivot_value *value)
+{
+ enum settings_value_show *show
+ = (value->type == PIVOT_VALUE_NUMERIC ? &value->numeric.show
+ : value->type == PIVOT_VALUE_STRING ? &value->string.show
+ : value->type == PIVOT_VALUE_VARIABLE ? &value->variable.show
+ : NULL);
+ if (show && parse_settings_value_show (lexer, "SHOW", show))
+ return;
+
+ char **var_name
+ = (value->type == PIVOT_VALUE_NUMERIC ? &value->numeric.var_name
+ : value->type == PIVOT_VALUE_STRING ? &value->string.var_name
+ : NULL);
+ if (var_name && parse_string_setting (lexer, "VAR", var_name))
+ return;
+
+ char **label
+ = (value->type == PIVOT_VALUE_NUMERIC ? &value->numeric.value_label
+ : value->type == PIVOT_VALUE_STRING ? &value->string.value_label
+ : value->type == PIVOT_VALUE_VARIABLE ? &value->variable.var_label
+ : NULL);
+ if (label && parse_string_setting (lexer, "LABEL", label))
+ return;
+
+ if (value->type == PIVOT_VALUE_STRING && lex_match_id (lexer, "HEX"))
+ {
+ value->string.hex = true;
+ return;
+ }
+
+ if (value->type == PIVOT_VALUE_NUMERIC)
+ {
+ msg_disable ();
+ struct fmt_spec fmt;
+ bool ok = parse_format_specifier (lexer, &fmt);
+ msg_enable ();
+
+ if (ok)
+ {
+ if (!fmt_check_output (&fmt)
+ || !fmt_check_type_compat (&fmt, VAL_NUMERIC))
+ exit (1);
+
+ value->numeric.format = fmt;
+ return;
+ }
+ }
+
+ if (lex_match_id (lexer, "SUBSCRIPTS"))
+ {
+ lex_match (lexer, T_EQUALS);
+ size_t allocated_subscripts = value->n_subscripts;
+ while (lex_token (lexer) == T_STRING)
+ {
+ if (value->n_subscripts >= allocated_subscripts)
+ value->subscripts = x2nrealloc (value->subscripts,
+ &allocated_subscripts,
+ sizeof *value->subscripts);
+
+ value->subscripts[value->n_subscripts++] = xstrdup (
+ lex_tokcstr (lexer));
+ lex_get (lexer);
+ }
+ return;
+ }
+
+ lex_error (lexer, "Expecting valid value option");
+ exit (1);
+}
+
static struct pivot_value *
read_value (struct lexer *lexer)
{
}
else if (lex_is_string (lexer))
{
- value = pivot_value_new_user_text (lex_tokcstr (lexer), SIZE_MAX);
+ value = xmalloc (sizeof *value);
+ *value = (struct pivot_value) {
+ .type = PIVOT_VALUE_STRING,
+ .string = { .s = xstrdup (lex_tokcstr (lexer)) },
+ };
+ lex_get (lexer);
+ }
+ else if (lex_token (lexer) == T_ID)
+ {
+ value = xmalloc (sizeof *value);
+ *value = (struct pivot_value) {
+ .type = PIVOT_VALUE_VARIABLE,
+ .variable = { .var_name = xstrdup (lex_tokcstr (lexer)) },
+ };
lex_get (lexer);
}
else
exit (1);
}
- if (!lex_match (lexer, T_LBRACK))
- return value;
- do
+ while (lex_match (lexer, T_LBRACK))
{
- msg (SE, "Options not yet supported");
- exit (1);
+ read_value_option (lexer, value);
+
+ if (!lex_force_match (lexer, T_RBRACK))
+ exit (1);
}
- while (lex_match (lexer, T_COMMA));
- if (!lex_force_match (lexer, T_RBRACK))
- exit (1);
+
+ return value;
}
static void
&& !parse_bool_setting (lexer, "TOPCONTINUATION", "YES", "NO",
&look->top_continuation)
&& !parse_bool_setting (lexer, "BOTTOMCONTINUATION", "YES", "NO",
- &look->bottom_continuation))
+ &look->bottom_continuation)
+ && !parse_string_setting (lexer, "CONTINUATION",
+ &look->continuation))
break;
}
pivot_table_set_look (pt, look);
exit (1);
}
+static struct cell_color
+read_color (struct lexer *lexer)
+{
+ struct cell_color color;
+ if (!parse_color__ (lex_tokcstr (lexer), &color))
+ {
+ msg (SE, "%s: unknown color", lex_tokcstr (lexer));
+ exit (1);
+ }
+ lex_get (lexer);
+ return color;
+}
+
+static bool
+parse_value_setting (struct lexer *lexer, const char *name,
+ struct pivot_value **valuep)
+{
+ if (lex_match_id (lexer, name))
+ {
+ lex_match (lexer, T_EQUALS);
+
+ pivot_value_destroy (*valuep);
+ *valuep = read_value (lexer);
+
+ return true;
+ }
+ else
+ return false;
+}
+
static void
read_border (struct lexer *lexer, struct pivot_table *pt)
{
struct table_border_style style = TABLE_BORDER_STYLE_INITIALIZER;
style.stroke = read_stroke (lexer);
if (lex_is_string (lexer))
- {
- if (!parse_color__ (lex_tokcstr (lexer), &style.color))
- {
- msg (SE, "%s: unknown color", lex_tokcstr (lexer));
- exit (1);
- }
- lex_get (lexer);
- }
+ style.color = read_color (lexer);
if (!lex_force_match (lexer, T_RPAREN))
exit (1);
{
lex_match (lexer, T_EQUALS);
while (lex_token (lexer) == T_ID)
- if (!parse_bool_setting (lexer, "GRID", "YES", "NO",
- &pt->show_grid_lines)
- && !parse_bool_setting (lexer, "CAPTION", "YES", "NO",
- &pt->show_caption)
- && !parse_bool_setting (lexer, "TITLE", "YES", "NO",
- &pt->show_caption))
+ {
+ if (parse_bool_setting (lexer, "GRID", "YES", "NO",
+ &pt->show_grid_lines)
+ || parse_bool_setting (lexer, "CAPTION", "YES", "NO",
+ &pt->show_caption)
+ || parse_bool_setting (lexer, "TITLE", "YES", "NO",
+ &pt->show_title))
+ continue;
+
+ if (parse_settings_value_show (lexer, "VALUES", &pt->show_values)
+ || parse_settings_value_show (lexer, "VARIABLES",
+ &pt->show_variables))
+ continue;
+
break;
+ }
+ }
+ else if (parse_value_setting (lexer, "TITLE", &pt->title)
+ || parse_value_setting (lexer, "SUBTYPE", &pt->subtype)
+ || parse_value_setting (lexer, "CORNER", &pt->corner_text)
+ || parse_value_setting (lexer, "CAPTION", &pt->caption)
+ || parse_string_setting (lexer, "NOTES", &pt->notes))
+ {
+ /* Nothing. */
}
else if (lex_match_id (lexer, "BORDER"))
read_border (lexer, pt);
}
}
+ size_t *dindexes = xcalloc (pt->n_dimensions, sizeof *dindexes);
+ for (size_t i = 0; ; i++)
+ {
+ pivot_table_put (pt, dindexes, pt->n_dimensions,
+ pivot_value_new_integer (i));
+
+ for (size_t j = 0; j < pt->n_dimensions; j++)
+ {
+ if (++dindexes[j] < pt->dimensions[j]->n_leaves)
+ goto next;
+ dindexes[j] = 0;
+ }
+ break;
+ next:;
+ }
+ free (dindexes);
+
if (!lex_force_match (lexer, T_ENDCMD))
exit (1);
return pt;