system-file-format: More string fields with null bytes spotted.
[pspp] / src / language / control / repeat.c
index c0fa8fe0d8dfe165deb6f55968f17ed512d9b46f..0e464420a2bf6d43a4f8ca2bc0f405fc76e6ea3c 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2007, 2009-2012 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 <stdlib.h>
 
+#include "data/dataset.h"
 #include "data/dictionary.h"
-#include "data/procedure.h"
+#include "data/settings.h"
 #include "language/command.h"
 #include "language/lexer/lexer.h"
 #include "language/lexer/segment.h"
 #include "language/lexer/token.h"
 #include "language/lexer/variable-parser.h"
+#include "libpspp/assertion.h"
 #include "libpspp/cast.h"
 #include "libpspp/hash-functions.h"
 #include "libpspp/hmap.h"
+#include "libpspp/i18n.h"
 #include "libpspp/message.h"
 #include "libpspp/str.h"
+#include "libpspp/misc.h"
 
 #include "gl/ftoastr.h"
 #include "gl/minmax.h"
@@ -75,7 +79,7 @@ cmd_do_repeat (struct lexer *lexer, struct dataset *ds)
 static unsigned int
 hash_dummy (const char *name, size_t name_len)
 {
-  return hash_case_bytes (name, name_len, 0);
+  return utf8_hash_case_bytes (name, name_len, 0);
 }
 
 static const struct dummy_var *
@@ -85,7 +89,7 @@ find_dummy_var (struct hmap *hmap, const char *name, size_t name_len)
 
   HMAP_FOR_EACH_WITH_HASH (dv, struct dummy_var, hmap_node,
                            hash_dummy (name, name_len), hmap)
-    if (strcasecmp (dv->name, name))
+    if (utf8_strcasecmp (dv->name, name))
       return dv;
 
   return NULL;
@@ -158,8 +162,8 @@ parse_specification (struct lexer *lexer, struct dictionary *dict,
         first_dv = dv;
       else if (first_dv->n_values != dv->n_values)
        {
-         msg (SE, _("Dummy variable `%s' had %d substitutions, so `%s' must "
-                     "also, but %d were specified."),
+         msg (SE, _("Dummy variable `%s' had %zu substitutions, so `%s' must "
+                     "also, but %zu were specified."),
                first_dv->name, first_dv->n_values,
                dv->name, dv->n_values);
          goto error;
@@ -188,13 +192,13 @@ count_values (struct hmap *dummies)
 }
 
 static void
-do_parse_commands (struct substring s, enum lex_syntax_mode syntax_mode,
+do_parse_commands (struct substring s, enum segmenter_mode mode,
                    struct hmap *dummies,
                    struct string *outputs, size_t n_outputs)
 {
   struct segmenter segmenter;
 
-  segmenter_init (&segmenter, syntax_mode);
+  segmenter_init (&segmenter, mode);
 
   while (!ss_is_empty (s))
     {
@@ -218,7 +222,7 @@ do_parse_commands (struct substring s, enum lex_syntax_mode syntax_mode,
               n += k;
             }
 
-          do_parse_commands (ss_head (s, n), syntax_mode, dummies,
+          do_parse_commands (ss_head (s, n), mode, dummies,
                              outputs, n_outputs);
         }
       else if (type != SEG_END)
@@ -243,9 +247,10 @@ do_parse_commands (struct substring s, enum lex_syntax_mode syntax_mode,
 static bool
 parse_commands (struct lexer *lexer, struct hmap *dummies)
 {
+  enum lex_syntax_mode syntax_mode;
+  enum segmenter_mode mode;
   struct string *outputs;
   struct string input;
-  size_t input_len;
   size_t n_values;
   char *file_name;
   int line_number;
@@ -268,15 +273,22 @@ parse_commands (struct lexer *lexer, struct hmap *dummies)
   if (ds_is_empty (&input))
     ds_put_byte (&input, '\n');
   ds_put_byte (&input, '\0');
-  input_len = ds_length (&input);
 
   n_values = count_values (dummies);
   outputs = xmalloc (n_values * sizeof *outputs);
   for (i = 0; i < n_values; i++)
     ds_init_empty (&outputs[i]);
 
-  do_parse_commands (ds_ss (&input), lex_get_syntax_mode (lexer),
-                     dummies, outputs, n_values);
+  syntax_mode = lex_get_syntax_mode (lexer);
+  if (syntax_mode == LEX_SYNTAX_AUTO)
+    mode = SEG_MODE_AUTO;
+  else if (syntax_mode == LEX_SYNTAX_INTERACTIVE)
+    mode = SEG_MODE_INTERACTIVE;
+  else if (syntax_mode == LEX_SYNTAX_BATCH)
+    mode = SEG_MODE_BATCH;
+  else
+    NOT_REACHED ();
+  do_parse_commands (ds_ss (&input), mode, dummies, outputs, n_values);
 
   ds_destroy (&input);
 
@@ -293,14 +305,14 @@ parse_commands (struct lexer *lexer, struct hmap *dummies)
   for (i = 0; i < n_values; i++)
     {
       struct string *output = &outputs[n_values - i - 1];
-      struct lex_reader *reader;
-
-      reader = lex_reader_for_substring_nocopy (ds_ss (output));
+      const char *encoding = lex_get_encoding (lexer);
+      struct lex_reader *reader = lex_reader_for_substring_nocopy (ds_ss (output), encoding);
       lex_reader_set_file_name (reader, file_name);
       reader->line_number = line_number;
       lex_include (lexer, reader);
     }
   free (file_name);
+  free (outputs);
 
   return ok;
 }
@@ -388,7 +400,7 @@ parse_numbers (struct lexer *lexer, struct dummy_var *dv)
         {
           char s[DBL_BUFSIZE_BOUND];
 
-          dtoastr (s, sizeof s, 0, 0, lex_number (lexer));
+          c_dtoastr (s, sizeof s, 0, 0, lex_number (lexer));
           add_replacement (dv, xstrdup (s), &allocated);
           lex_get (lexer);
         }
@@ -410,7 +422,6 @@ parse_strings (struct lexer *lexer, struct dummy_var *dv)
     {
       if (!lex_force_string (lexer))
        {
-         msg (SE, _("String expected."));
          return false;
        }
 
@@ -427,6 +438,6 @@ parse_strings (struct lexer *lexer, struct dummy_var *dv)
 int
 cmd_end_repeat (struct lexer *lexer UNUSED, struct dataset *ds UNUSED)
 {
-  msg (SE, _("No matching DO REPEAT."));
+  msg (SE, _("No matching %s."), "DO REPEAT");
   return CMD_CASCADING_FAILURE;
 }