lexer: Reimplement for better testability and internationalization.
[pspp-builds.git] / src / ui / terminal / terminal-opts.c
index d1296a36252ac449734bb6bd15875a23febd3e3f..121d89d5712a5bb127ff73f1778d5e498bb7a234 100644 (file)
 #include "terminal-opts.h"
 
 #include <stdbool.h>
-#include <xalloc.h>
 #include <stdlib.h>
-#include <unistd.h>
 
 #include "data/settings.h"
 #include "data/file-name.h"
-#include "language/syntax-file.h"
+#include "language/lexer/include-path.h"
 #include "libpspp/argv-parser.h"
 #include "libpspp/assertion.h"
+#include "libpspp/cast.h"
 #include "libpspp/compiler.h"
-#include "libpspp/getl.h"
 #include "libpspp/llx.h"
 #include "libpspp/str.h"
 #include "libpspp/string-array.h"
 #include "output/driver.h"
 #include "output/driver-provider.h"
 #include "output/msglog.h"
-#include "ui/terminal/msg-ui.h"
-#include "ui/terminal/read-line.h"
 
 #include "gl/error.h"
 #include "gl/progname.h"
 #include "gl/version-etc.h"
 #include "gl/xmemdup0.h"
+#include "gl/xalloc.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 
 struct terminal_opts
   {
-    struct source_stream *source_stream;
-    enum syntax_mode syntax_mode;
     struct string_map options;  /* Output driver options. */
     bool has_output_driver;
     bool has_terminal_driver;
     bool has_error_file;
-    bool process_statrc;
+    enum lex_syntax_mode *syntax_mode;
+    bool *process_statrc;
+    char **syntax_encoding;
   };
 
 enum
@@ -68,7 +65,10 @@ enum
     OPT_ERROR_FILE,
     OPT_OUTPUT,
     OPT_OUTPUT_OPTION,
+    OPT_NO_OUTPUT,
+    OPT_BATCH,
     OPT_INTERACTIVE,
+    OPT_SYNTAX_ENCODING,
     OPT_NO_STATRC,
     OPT_HELP,
     OPT_VERSION,
@@ -81,7 +81,10 @@ static struct argv_option terminal_argv_options[N_TERMINAL_OPTIONS] =
     {"error-file", 'e', required_argument, OPT_ERROR_FILE},
     {"output", 'o', required_argument, OPT_OUTPUT},
     {NULL, 'O', required_argument, OPT_OUTPUT_OPTION},
+    {"no-output", 0, no_argument, OPT_NO_OUTPUT},
+    {"batch", 'b', no_argument, OPT_BATCH},
     {"interactive", 'i', no_argument, OPT_INTERACTIVE},
+    {"syntax-encoding", 0, required_argument, OPT_SYNTAX_ENCODING},
     {"no-statrc", 'r', no_argument, OPT_NO_STATRC},
     {"help", 'h', no_argument, OPT_HELP},
     {"version", 'V', no_argument, OPT_VERSION},
@@ -159,31 +162,13 @@ get_supported_formats (void)
   return format_string;
 }
 
-static char *
-get_default_include_path (void)
-{
-  struct source_stream *ss;
-  struct string dst;
-  char **path;
-  size_t i;
-
-  ss = create_source_stream ();
-  path = getl_include_path (ss);
-  ds_init_empty (&dst);
-  for (i = 0; path[i] != NULL; i++)
-    ds_put_format (&dst, " %s", path[i]);
-  destroy_source_stream (ss);
-
-  return ds_steal_cstr (&dst);
-}
-
 static void
 usage (void)
 {
   char *supported_formats = get_supported_formats ();
-  char *default_include_path = get_default_include_path ();
+  char *inc_path = string_array_join (include_path_default (), " ");
 
-  printf ("\
+  printf (_("\
 PSPP, a program for statistical analysis of sample data.\n\
 Usage: %s [OPTION]... FILE...\n\
 \n\
@@ -195,6 +180,7 @@ Output options:\n\
   -O OPTION=VALUE           set output option to customize previous -o\n\
   -O device={terminal|listing}  override device type for previous -o\n\
   -e, --error-file=FILE     append errors, warnings, and notes to FILE\n\
+  --no-output               disable default output driver\n\
 Supported output formats: %s\n\
 \n\
 Language options:\n\
@@ -206,19 +192,21 @@ Language options:\n\
                             calculated from broken algorithms\n\
   -x, --syntax={compatible|enhanced}\n\
                             set to `compatible' to disable PSPP extensions\n\
+  -b, --batch               interpret syntax in batch mode\n\
   -i, --interactive         interpret syntax in interactive mode\n\
+  --syntax-encoding=ENCODING  specify encoding for syntax files\n\
   -s, --safer               don't allow some unsafe operations\n\
-Default search path:%s\n\
+Default search path: %s\n\
 \n\
 Informative output:\n\
   -h, --help                display this help and exit\n\
   -V, --version             output version information and exit\n\
 \n\
-Non-option arguments are interpreted as syntax files to execute.\n",
-          program_name, supported_formats, default_include_path);
+Non-option arguments are interpreted as syntax files to execute.\n"),
+          program_name, supported_formats, inc_path);
 
   free (supported_formats);
-  free (default_include_path);
+  free (inc_path);
 
   emit_bug_reporting_address ();
   exit (EXIT_SUCCESS);
@@ -249,12 +237,26 @@ terminal_option_callback (int id, void *to_)
       parse_output_option (to, optarg);
       break;
 
+    case OPT_NO_OUTPUT:
+      /* Pretend that we already have an output driver, which disables adding
+         one in terminal_opts_done() when we don't already have one. */
+      to->has_output_driver = true;
+      break;
+
+    case OPT_BATCH:
+      *to->syntax_mode = LEX_SYNTAX_BATCH;
+      break;
+
     case OPT_INTERACTIVE:
-      to->syntax_mode = GETL_INTERACTIVE;
+      *to->syntax_mode = LEX_SYNTAX_INTERACTIVE;
+      break;
+
+    case OPT_SYNTAX_ENCODING:
+      *to->syntax_encoding = optarg;
       break;
 
     case OPT_NO_STATRC:
-      to->process_statrc = false;
+      *to->process_statrc = false;
       break;
 
     case OPT_HELP:
@@ -264,7 +266,7 @@ terminal_option_callback (int id, void *to_)
     case OPT_VERSION:
       version_etc (stdout, "pspp", PACKAGE_NAME, PACKAGE_VERSION,
                    "Ben Pfaff", "John Darrington", "Jason Stover",
-                   (char *) NULL);
+                   NULL_SENTINEL);
       exit (EXIT_SUCCESS);
 
     default:
@@ -273,60 +275,33 @@ terminal_option_callback (int id, void *to_)
 }
 
 struct terminal_opts *
-terminal_opts_init (struct argv_parser *ap, struct source_stream *ss)
+terminal_opts_init (struct argv_parser *ap,
+                    enum lex_syntax_mode *syntax_mode, bool *process_statrc,
+                    char **syntax_encoding)
 {
   struct terminal_opts *to;
 
-  to = xmalloc (sizeof *to);
-  to->source_stream = ss;
-  to->syntax_mode = GETL_BATCH;
+  *syntax_mode = LEX_SYNTAX_AUTO;
+  *process_statrc = true;
+  *syntax_encoding = "Auto";
+
+  to = xzalloc (sizeof *to);
+  to->syntax_mode = syntax_mode;
   string_map_init (&to->options);
   to->has_output_driver = false;
   to->has_error_file = false;
-  to->process_statrc = true;
+  to->syntax_mode = syntax_mode;
+  to->process_statrc = process_statrc;
+  to->syntax_encoding = syntax_encoding;
 
   argv_parser_add_options (ap, terminal_argv_options, N_TERMINAL_OPTIONS,
                            terminal_option_callback, to);
   return to;
 }
 
-static void
-add_syntax_file (struct terminal_opts *to, const char *file_name)
-{
-  if (!strcmp (file_name, "-") && isatty (STDIN_FILENO))
-    getl_append_source (to->source_stream, create_readln_source (),
-                        GETL_INTERACTIVE, ERRMODE_CONTINUE);
-  else
-    getl_append_source (to->source_stream,
-                        create_syntax_file_source (file_name),
-                        to->syntax_mode, ERRMODE_CONTINUE);
-}
-
 void
 terminal_opts_done (struct terminal_opts *to, int argc, char *argv[])
 {
-  if (to->process_statrc)
-    {
-      char *rc = fn_search_path ("rc", getl_include_path (to->source_stream));
-      if (rc != NULL)
-        {
-          getl_append_source (to->source_stream,
-                              create_syntax_file_source (rc), GETL_BATCH,
-                              ERRMODE_CONTINUE);
-          free (rc);
-        }
-    }
-
-  if (optind < argc)
-    {
-      int i;
-
-      for (i = optind; i < argc; i++)
-        add_syntax_file (to, argv[i]);
-    }
-  else
-    add_syntax_file (to, "-");
-
   register_output_driver (to);
   if (!to->has_output_driver)
     {