superscript
[pspp] / tests / output / pivot-table-test.c
index 514ce7f8dca4143faae393f0d0a0410938ae80f8..c9887399325e9f4345ded2a6ec8fab76345d6923 100644 (file)
@@ -25,6 +25,7 @@
 
 #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"
@@ -128,8 +129,6 @@ configure_drivers (int width, int length, int min_break)
     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. */
@@ -149,11 +148,10 @@ configure_drivers (int width, int length, int min_break)
   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);
 }
@@ -266,6 +264,126 @@ usage (void)
   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)
 {
@@ -277,7 +395,20 @@ 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
@@ -286,16 +417,15 @@ read_value (struct lexer *lexer)
       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
@@ -376,54 +506,6 @@ parse_bool_setting (struct lexer *lexer, const char *name,
     return false;
 }
 
-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_look (struct lexer *lexer, struct pivot_table *pt)
 {
@@ -487,6 +569,19 @@ read_stroke (struct lexer *lexer)
   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)
@@ -543,14 +638,7 @@ 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);
 
@@ -638,6 +726,23 @@ read_table (struct lexer *lexer)
         }
     }
 
+  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;