Patch #6427. Reviewed by John Darrington.
authorBen Pfaff <blp@gnu.org>
Wed, 5 Mar 2008 06:30:31 +0000 (06:30 +0000)
committerBen Pfaff <blp@gnu.org>
Wed, 5 Mar 2008 06:30:31 +0000 (06:30 +0000)
* comments-dialog.c: Adapt to new syntax generating code in
ui/syntax-gen.[ch].

* data-editor.c: Ditto.

* recode-dialog.c: Ditto.

* t-test-independent-samples-dialog.c: Ditto.

* automake.mk: Add new files.

* syntax-gen.c: New file.  Based on former
src/libpspp/syntax-gen.c but rewritten.

* syntax-gen.h: New file.  Based on former
src/libpspp/syntax-gen.h but rewritten.

* automake.mk: Remove moved files.

* syntax-gen.c: Moved to src/ui (and rewritten).

* syntax-gen.h: Ditto.

13 files changed:
src/libpspp/ChangeLog
src/libpspp/automake.mk
src/libpspp/syntax-gen.c [deleted file]
src/libpspp/syntax-gen.h [deleted file]
src/ui/ChangeLog
src/ui/automake.mk
src/ui/gui/ChangeLog
src/ui/gui/comments-dialog.c
src/ui/gui/data-editor.c
src/ui/gui/recode-dialog.c
src/ui/gui/t-test-independent-samples-dialog.c
src/ui/syntax-gen.c [new file with mode: 0644]
src/ui/syntax-gen.h [new file with mode: 0644]

index c201dc0770fd222489db551eb4936ccbe4b648ee..fcd88f1e27ed6a01c87d3ad1c0b1397d45c6dbd1 100644 (file)
@@ -1,3 +1,13 @@
+2008-03-04  Ben Pfaff  <blp@gnu.org>
+
+       Patch #6427.  Reviewed by John Darrington.
+
+       * automake.mk: Remove moved files.
+
+       * syntax-gen.c: Moved to src/ui (and rewritten).
+
+       * syntax-gen.h: Ditto.
+
 2008-03-04  Ben Pfaff  <blp@gnu.org>
 
        Patch #6441.  Reviewed by John Darrington.
index 4c714f20dc883041d8b2369e744ba7651242a2ad..a697e4021b3c6893d6061875cce62db02c30f234 100644 (file)
@@ -57,8 +57,6 @@ src_libpspp_libpspp_a_SOURCES = \
        src/libpspp/start-date.h \
        src/libpspp/str.c \
        src/libpspp/str.h \
-       src/libpspp/syntax-gen.c \
-       src/libpspp/syntax-gen.h \
        src/libpspp/taint.c \
        src/libpspp/taint.h \
        src/libpspp/tower.c \
diff --git a/src/libpspp/syntax-gen.c b/src/libpspp/syntax-gen.c
deleted file mode 100644 (file)
index a1cfaf5..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/* PSPP - a program for statistical analysis.
-   Copyright (C) 2007 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
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
-
-#include <config.h>
-#include <stdbool.h>
-#include <stdint.h>
-
-#include <libpspp/str.h>
-#include <libpspp/assertion.h>
-#include <string.h>
-#include <mbchar.h>
-
-#include "syntax-gen.h"
-
-
-static bool
-has_single_quote (const struct string *str)
-{
-  return (SIZE_MAX != ds_find_char (str, '\''));
-}
-
-static bool
-has_double_quote (const struct string *str)
-{
-  return (SIZE_MAX != ds_find_char (str, '"'));
-}
-
-/*
-   Quotes the string STR. If STR contains no '\'' character, then
-   the returned value will be enclosed in single quotes.  Else, if STR
-   contains no '"' character, then it will be enclosed in double
-   quotes. Otherwise, it will be enclosed in single quotes, and each
-   '\'' will be padded with another '\''.
-
-   STR must be encoded in UTF-8, and the quoted result will also be
-   encoded in UTF-8.
-*/
-void
-gen_quoted_string (struct string *str)
-{
-  char c;
-  static const char single_quote[] = "'";
-  static const char double_quote[] = "\"";
-
-  struct string quoted_str;
-
-  bool pad_single_quotes = false;
-  const char *delimiter ;
-  char *s = ds_cstr (str);
-
-  if ( has_double_quote (str))
-    {
-      delimiter = single_quote;
-      if ( has_single_quote (str))
-       pad_single_quotes = true;
-    }
-  else
-    {
-      delimiter = double_quote;
-    }
-
-  /* This seemingly simple implementation is possible, because UTF-8
-     guarantees that bytes corresponding to basic characters (such as
-     '\'') cannot appear in a multi-byte character sequence except to
-     represent that basic character.
-  */
-  assert (is_basic ('\''));
-
-  /* Initialise with the opening delimiter */
-  ds_init_cstr (&quoted_str, delimiter);
-  while ((c = *s++))
-    {
-      ds_put_char (&quoted_str, c);
-
-      /* If c is a single quote, then append another one */
-      if ( c == '\'' && pad_single_quotes)
-       ds_put_char (&quoted_str, c);
-    }
-
-  /* Add the closing delimiter */
-  ds_put_cstr (&quoted_str, delimiter);
-
-  /* Copy the quoted string into str */
-  ds_swap (str, &quoted_str);
-  ds_destroy (&quoted_str);
-}
-
diff --git a/src/libpspp/syntax-gen.h b/src/libpspp/syntax-gen.h
deleted file mode 100644 (file)
index d8bcb4e..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/* PSPP - a program for statistical analysis.
-   Copyright (C) 2007 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
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
-
-#ifndef SYNTAX_GEN_H
-#define SYNTAX_GEN_H
-
-struct string;
-
-void gen_quoted_string (struct string *);
-
-#endif
index e17fe343ea631da37748343dd3c32f49f4932d83..bc9c192f676cddec8edaff64e45e5657001c33f2 100644 (file)
@@ -1,3 +1,15 @@
+2008-03-04  Ben Pfaff  <blp@gnu.org>
+
+       Patch #6427.  Reviewed by John Darrington.
+
+       * automake.mk: Add new files.
+
+       * syntax-gen.c: New file.  Based on former
+       src/libpspp/syntax-gen.c but rewritten.
+
+       * syntax-gen.h: New file.  Based on former
+       src/libpspp/syntax-gen.h but rewritten.
+
 2007-10-10  Ben Pfaff  <blp@gnu.org>
 
        * src/ui/debugger.c: Use debugger if HAVE_FORK is defined, not
index e1915b283f666bc45dfadb3edc19c3b68131f920..18b6914801fb058dae2555a6a07358e6db76ff38 100644 (file)
@@ -10,4 +10,6 @@ noinst_LIBRARIES += src/ui/libuicommon.a
 
 src_ui_libuicommon_a_SOURCES = \
        src/ui/debugger.c \
-       src/ui/debugger.h
+       src/ui/debugger.h \
+       src/ui/syntax-gen.c \
+       src/ui/syntax-gen.h
index 580971cb4621b097bd4c678aef6c880006204136..6e16fdae5cca7e86a9321413db4191becdabe05f 100644 (file)
@@ -1,3 +1,16 @@
+2008-03-04  Ben Pfaff  <blp@gnu.org>
+
+       Patch #6427.  Reviewed by John Darrington.
+
+       * comments-dialog.c: Adapt to new syntax generating code in
+       ui/syntax-gen.[ch].
+
+       * data-editor.c: Ditto.
+
+       * recode-dialog.c: Ditto.
+
+       * t-test-independent-samples-dialog.c: Ditto.
+
 2008-02-29  John Darrington <john@darrington.wattle.id.au>
 
        * psppire-data-editor.c psppire-data-editor.h: New files.  Contains functionality
index b584c0b5c78b9b771017e3157a1396f6022a37e6..f1a4936e6de06e9df95abcff13966f09faa8705e 100644 (file)
@@ -22,7 +22,7 @@
 #include <language/syntax-string-source.h>
 #include "syntax-editor.h"
 #include "psppire-var-store.h"
-#include <libpspp/syntax-gen.h>
+#include <ui/syntax-gen.h>
 
 #include "comments-dialog.h"
 
@@ -244,27 +244,27 @@ generate_syntax (const struct comment_dialog *cd)
 
   for (i = 0 ; i < gtk_text_buffer_get_line_count (buffer) ; ++i )
     {
-      struct string line;
-      GtkTextIter start, end;
-      gtk_text_buffer_get_iter_at_line (buffer, &start, i);
-
-      end = start;
+      struct string tmp;
+      GtkTextIter start;
+      char *line;
 
-      gtk_text_iter_forward_to_line_end (&end);
-
-      if ( gtk_text_iter_ends_line (&start))
-       ds_init_cstr (&line, "");
+      gtk_text_buffer_get_iter_at_line (buffer, &start, i);
+      if (gtk_text_iter_ends_line (&start))
+       line = g_strdup ("");
       else
-       ds_init_cstr (&line,
-                     gtk_text_buffer_get_text (buffer,
-                                               &start, &end,
-                                               FALSE));
+        {
+          GtkTextIter end = start;
+          gtk_text_iter_forward_to_line_end (&end);
+          line = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+        }
 
-      gen_quoted_string (&line);
+      ds_init_empty (&tmp);
+      syntax_gen_string (&tmp, ss_cstr (line));
+      g_free (line);
 
-      g_string_append_printf (str, " %s\n", ds_cstr (&line));
+      g_string_append_printf (str, " %s\n", ds_cstr (&tmp));
 
-      ds_destroy (&line);
+      ds_destroy (&tmp);
     }
   g_string_append (str, " .\n");
 
index 0af3c8ffda74b12954d8df45d792fe9b71c64716..8afdfa0fa2a04f5023c9c67a33a1a5590f88af5f 100644 (file)
@@ -61,7 +61,7 @@
 #include "syntax-editor.h"
 #include <language/syntax-string-source.h>
 #include <language/command.h>
-#include <libpspp/syntax-gen.h>
+#include <ui/syntax-gen.h>
 #include "window-manager.h"
 
 #include "psppire-data-store.h"
@@ -1262,8 +1262,8 @@ save_file (struct data_editor *de)
 
   g_assert (de->file_name);
 
-  ds_init_cstr (&file_name, de->file_name);
-  gen_quoted_string (&file_name);
+  ds_init_empty (&file_name);
+  syntax_gen_string (&file_name, ss_cstr (de->file_name));
 
   if ( de->save_as_portable )
     {
@@ -1398,9 +1398,8 @@ open_data_file (const gchar *file_name, struct data_editor *de)
   struct getl_interface *sss;
   struct string filename;
 
-  ds_init_cstr (&filename, file_name);
-
-  gen_quoted_string (&filename);
+  ds_init_empty (&filename);
+  syntax_gen_string (&filename, ss_cstr (file_name));
 
   sss = create_syntax_string_source ("GET FILE=%s.",
                                     ds_cstr (&filename));
index 041566cf290bdc2ea30a401e81ba00e224373388..314367462e6f403d691f2c9896972086b610075f 100644 (file)
@@ -34,7 +34,7 @@
 #include <ui/gui/psppire-dialog.h>
 #include <ui/gui/psppire-var-store.h>
 #include <ui/gui/syntax-editor.h>
-#include <libpspp/syntax-gen.h>
+#include <ui/syntax-gen.h>
 
 #include "psppire-acr.h"
 
@@ -1338,9 +1338,8 @@ new_value_append_syntax (GString *str, const struct new_value *nv)
       break;
     case NV_STRING:
       {
-       struct string ds;
-       ds_init_cstr (&ds, nv->v.s);
-       gen_quoted_string (&ds);
+       struct string ds = DS_EMPTY_INITIALIZER;
+       syntax_gen_string (&ds, ss_cstr (nv->v.s));
        g_string_append (str, ds_cstr (&ds));
        ds_destroy (&ds);
       }
@@ -1371,9 +1370,8 @@ old_value_append_syntax (GString *str, const struct old_value *ov)
       break;
     case OV_STRING:
       {
-       struct string ds;
-       ds_init_cstr (&ds, ov->v.s);
-       gen_quoted_string (&ds);
+       struct string ds = DS_EMPTY_INITIALIZER;
+       syntax_gen_string (&ds, ss_cstr (ov->v.s));
        g_string_append (str, ds_cstr (&ds));
        ds_destroy (&ds);
       }
@@ -1537,9 +1535,9 @@ generate_syntax (const struct recode_dialog *rd)
              continue;
            }
 
-         ds_init_cstr (&ls, label);
+         ds_init_empty (&ls);
+         syntax_gen_string (&ls, ss_cstr (label));
          g_free (label);
-         gen_quoted_string (&ls);
 
          g_string_append_printf (str, "\nVARIABLE LABELS %s %s.",
                                  name, ds_cstr (&ls));
index d5f9eaa6406c7908f96f8f55f35269642f5d13e6..9c3ea41daeb3f4511884ac6be6c6a359ad2af7f7 100644 (file)
@@ -29,7 +29,7 @@
 #include "dict-display.h"
 #include "widget-io.h"
 #include "t-test-options.h"
-#include <libpspp/syntax-gen.h>
+#include <ui/syntax-gen.h>
 
 #include <language/syntax-string-source.h>
 #include "syntax-editor.h"
@@ -177,9 +177,8 @@ generate_syntax (const struct tt_indep_samples_dialog *d)
 
       if ( var_is_alpha (group_variable))
        {
-         struct string s;
-         ds_init_cstr (&s, d->grps->val[0]);
-         gen_quoted_string (&s);
+         struct string s = DS_EMPTY_INITIALIZER;
+         syntax_gen_string (&s, ss_cstr (d->grps->val[0]));
          g_string_append (str, ds_cstr (&s));
          ds_destroy (&s);
        }
@@ -194,9 +193,8 @@ generate_syntax (const struct tt_indep_samples_dialog *d)
 
          if ( var_is_alpha (group_variable))
            {
-             struct string s;
-             ds_init_cstr (&s, d->grps->val[1]);
-             gen_quoted_string (&s);
+             struct string s = DS_EMPTY_INITIALIZER;
+             syntax_gen_string (&s, ss_cstr (d->grps->val[1]));
              g_string_append (str, ds_cstr (&s));
              ds_destroy (&s);
            }
diff --git a/src/ui/syntax-gen.c b/src/ui/syntax-gen.c
new file mode 100644 (file)
index 0000000..84415c3
--- /dev/null
@@ -0,0 +1,319 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2008 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
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <ui/syntax-gen.h>
+
+#include <ctype.h>
+#include <mbchar.h>
+
+#include <data/data-in.h>
+#include <data/data-out.h>
+#include <data/format.h>
+#include <data/value.h>
+#include <libpspp/assertion.h>
+#include <libpspp/message.h>
+#include <libpspp/str.h>
+
+/* Appends to OUTPUT a pair of hex digits for each byte in IN. */
+static void
+syntax_gen_hex_digits (struct string *output, struct substring in)
+{
+  size_t i;
+  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]);
+    }
+}
+
+/* Returns true if IN contains any control characters, false
+   otherwise */
+static bool
+has_control_chars (struct substring in)
+{
+  size_t i;
+
+  for (i = 0; i < in.length; i++)
+    if (iscntrl ((unsigned char) in.string[i]))
+      return true;
+  return false;
+}
+
+static bool
+has_single_quote (struct substring str)
+{
+  return (SIZE_MAX != ss_find_char (str, '\''));
+}
+
+static bool
+has_double_quote (struct substring str)
+{
+  return (SIZE_MAX != ss_find_char (str, '"'));
+}
+
+/* Appends to OUTPUT valid PSPP syntax for a quoted string that
+   contains IN.
+
+   IN must be encoded in UTF-8, and the quoted result will also
+   be encoded in UTF-8.
+
+   The string will be output as a regular quoted string unless it
+   contains control characters, in which case it is output as a
+   hex string. */
+void
+syntax_gen_string (struct string *output, struct substring in)
+{
+  if (has_control_chars (in))
+    {
+      ds_put_cstr (output, "X'");
+      syntax_gen_hex_digits (output, in);
+      ds_put_char (output, '\'');
+    }
+  else
+    {
+      int quote;
+      size_t i;
+
+      /* This seemingly simple implementation is possible, because UTF-8
+         guarantees that bytes corresponding to basic characters (such as
+         '\'') cannot appear in a multi-byte character sequence except to
+         represent that basic character.
+      */
+      assert (is_basic ('\''));
+
+      quote = has_double_quote (in) && !has_single_quote (in) ? '\'' : '"';
+      ds_put_char (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_char (output, quote);
+    }
+}
+
+/* Appends to OUTPUT a representation of NUMBER in PSPP syntax.
+   The representation is precise, that is, when PSPP parses the
+   representation, its value will be exactly NUMBER.  (This might
+   not be the case on a C implementation where double has a
+   different representation.)
+
+   If NUMBER is the system-missing value, it is output as the
+   identifier SYSMIS.  This may not be appropriate, because
+   SYSMIS is not consistently parsed throughout PSPP syntax as
+   the system-missing value.  But in such circumstances the
+   system-missing value would not be meaningful anyhow, so the
+   caller should refrain from supplying the system-missing value
+   in such cases.
+
+   A value of LOWEST or HIGHEST is not treated specially.
+
+   If FORMAT is null, then the representation will be in numeric
+   form, e.g. 123 or 1.23e10.
+
+   If FORMAT is non-null, then it must point to a numeric format.
+   If the format is one easier for a user to understand when
+   expressed as a string than as a number (for example, a date
+   format), and the string representation precisely represents
+   NUMBER, then the string representation is written to OUTPUT.
+   Otherwise, NUMBER is output as if FORMAT was a null
+   pointer. */
+void
+syntax_gen_number (struct string *output,
+                   double number, const struct fmt_spec *format)
+{
+  assert (format == NULL || fmt_is_numeric (format->type));
+  if (format != NULL
+      && (format->type
+          & (FMT_CAT_DATE | FMT_CAT_TIME | FMT_CAT_DATE_COMPONENT)))
+    {
+      union value v_in, v_out;
+      char buffer[FMT_MAX_NUMERIC_WIDTH];
+      bool ok;
+
+      v_in.f = number;
+      data_out (&v_in, format, buffer);
+      msg_disable ();
+      ok = data_in (ss_buffer (buffer, format->w), LEGACY_NATIVE,
+                    format->type, false, 0, 0, &v_out, 0);
+      msg_enable ();
+      if (ok && v_out.f == number)
+        {
+          syntax_gen_string (output, ss_buffer (buffer, format->w));
+          return;
+        }
+    }
+
+  if (number == SYSMIS)
+    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);
+    }
+}
+
+/* Appends to OUTPUT a representation of VALUE, which has the
+   specified WIDTH.  If FORMAT is non-null, it influences the
+   output format.  The representation is precise, that is, when
+   PSPP parses the representation, its value will be exactly
+   VALUE. */
+void
+syntax_gen_value (struct string *output, const union value *value, int width,
+                  const struct fmt_spec *format)
+{
+  assert (format == NULL || fmt_var_width (format) == width);
+  if (width == 0)
+    syntax_gen_number (output, value->f, format);
+  else
+    syntax_gen_string (output, ss_buffer (value->s, width));
+}
+
+/* Appends <low> THRU <high> to OUTPUT.  If LOW is LOWEST, then
+   it is formatted as the identifier LO; if HIGH is HIGHEST, then
+   it is formatted as the identifier HI.  Otherwise, LOW and HIGH
+   are formatted as with a call to syntax_gen_num with the specified
+   FORMAT.
+
+   This is the opposite of the function parse_num_range. */
+void
+syntax_gen_num_range (struct string *output, double low, double high,
+                      const struct fmt_spec *format)
+{
+  if (low == LOWEST)
+    ds_put_cstr (output, "LO");
+  else
+    syntax_gen_number (output, low, format);
+
+  ds_put_cstr (output, " THRU ");
+
+  if (high == HIGHEST)
+    ds_put_cstr (output, "HI");
+  else
+    syntax_gen_number (output, high, format);
+}
+
+/* Same as syntax_gen_pspp, below, but takes a va_list. */
+void
+syntax_gen_pspp_valist (struct string *output, const char *format,
+                        va_list args)
+{
+  for (;;)
+    {
+      size_t copy = strcspn (format, "%");
+      ds_put_substring (output, ss_buffer (format, copy));
+      format += copy;
+
+      if (*format == '\0')
+        return;
+      assert (*format == '%');
+      format++;
+      switch (*format++)
+        {
+        case 's':
+          {
+            const char *s = va_arg (args, char *);
+            switch (*format++)
+              {
+              case 'q':
+                syntax_gen_string (output, ss_cstr (s));
+                break;
+              case 's':
+                ds_put_cstr (output, s);
+                break;
+              default:
+                NOT_REACHED ();
+              }
+          }
+          break;
+
+        case 'd':
+          {
+            int i = va_arg (args, int);
+            ds_put_format (output, "%d", i);
+          }
+          break;
+
+        case 'f':
+          {
+            double d = va_arg (args, double);
+            switch (*format++)
+              {
+              case 'p':
+                ds_put_format (output, "%f", d);
+                break;
+              default:
+                NOT_REACHED ();
+              }
+            break;
+          }
+
+        case '%':
+          ds_put_char (output, '%');
+          break;
+
+        default:
+          NOT_REACHED ();
+        }
+    }
+}
+
+/* printf-like function specialized for outputting PSPP syntax.
+   FORMAT is appended to OUTPUT.  The following substitutions are
+   supported:
+
+     %sq: The char * argument is formatted as a PSPP string, as
+          if with a call to syntax_gen_string.
+
+     %ss: The char * argument is appended literally.
+
+     %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.
+
+     %%: Literal %.
+
+   (These substitutions were chosen to allow GCC to check for
+   correct argument types.)
+
+   This function is somewhat experimental.  If it proves useful,
+   the allowed substitutions will almost certainly be
+   expanded. */
+void
+syntax_gen_pspp (struct string *output, const char *format, ...)
+{
+  va_list args;
+  va_start (args, format);
+  syntax_gen_pspp_valist (output, format, args);
+  va_end (args);
+}
diff --git a/src/ui/syntax-gen.h b/src/ui/syntax-gen.h
new file mode 100644 (file)
index 0000000..501f1f3
--- /dev/null
@@ -0,0 +1,45 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2007, 2008 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
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef SYNTAX_GEN_H
+#define SYNTAX_GEN_H 1
+
+/* These functions aid in composing PSPP syntax. */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <libpspp/compiler.h>
+
+struct fmt_spec;
+struct substring;
+struct string;
+union value;
+
+void syntax_gen_string (struct string *output, struct substring in);
+void syntax_gen_number (struct string *output,
+                        double, const struct fmt_spec *format);
+void syntax_gen_value (struct string *output, const union value *value,
+                       int width, const struct fmt_spec *format);
+void syntax_gen_num_range (struct string *output, double low, double high,
+                           const struct fmt_spec *format);
+
+void syntax_gen_pspp_valist (struct string *output, const char *format,
+                             va_list)
+  PRINTF_FORMAT (2, 0);
+void syntax_gen_pspp (struct string *output, const char *format, ...)
+  PRINTF_FORMAT (2, 3);
+
+#endif /* format-syntax.h */