Clean up file handle code in preparation to add temporary file
[pspp] / src / main.c
index c747287c715fededddc1250a247d02e3acf1e01c..d52741d1bd8605c35c73daf67f09fa541d933d3c 100644 (file)
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA. */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA. */
 
 #include <config.h>
 #include "main.h"
-#include <assert.h>
+#include <gsl/gsl_errno.h>
+#include <signal.h>
 #include <stdio.h>
 #include "cmdline.h"
 #include "command.h"
+#include "dictionary.h"
 #include "error.h"
-#include "getline.h"
+#include "file-handle-def.h"
+#include "filename.h"
+#include "getl.h"
 #include "glob.h"
 #include "lexer.h"
 #include "output.h"
+#include "progname.h"
+#include "random.h"
+#include "readln.h"
+#include "settings.h"
+#include "var.h"
 #include "version.h"
-#include <signal.h>
+
+#if HAVE_FPU_CONTROL_H
+#include <fpu_control.h>
+#endif
+
+#if HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#if HAVE_FENV_H
+#include <fenv.h>
+#endif
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
 
 #include <stdlib.h>
 
 #include "debug-print.h"
 
-static void parse_script (void) NO_RETURN;
+static void i18n_init (void);
+static void fpu_init (void);
 static void handle_error (int code);
 static int execute_command (void);
 
-/* argv[0] with stripped leading directories. */
-char *pgmname;
-
 /* Whether FINISH. has been executed. */
 int finished;
 
-/* The current date in the form DD MMM YYYY. */
-char curdate[12];
-
-
 /* If a segfault happens, issue a message to that effect and halt */
 void bug_handler(int sig);
 
+/* Handle quit/term/int signals */
+void interrupt_handler(int sig);
+
 /* Whether we're dropping down to interactive mode immediately because
    we hit end-of-file unexpectedly (or whatever). */
 int start_interactive;
@@ -60,46 +80,71 @@ int start_interactive;
 int
 main (int argc, char **argv)
 {
-  struct sigaction bug ;
-  bug.sa_handler = bug_handler;
+  signal (SIGSEGV, bug_handler);
+  signal (SIGFPE, bug_handler);
+  signal (SIGINT, interrupt_handler);
 
-  sigaction(SIGSEGV, &bug,0);
+  set_program_name ("pspp");
+  i18n_init ();
+  fpu_init ();
+  gsl_set_error_handler_off ();
 
-  /* Initialization. */
-  if (!outp_init ())
-    err_hcf (0);
-  init_glob (argc, argv);
-  parse_command_line (argc, argv);
-  if (!outp_read_devices ())
-    msg (FE, _("Error initializing output drivers."));
+  outp_init ();
+  fn_init ();
+  fh_init ();
+  getl_initialize ();
+  readln_initialize ();
+  settings_init ();
+  random_init ();
 
-  lex_init ();
-  cmd_init ();
+  default_dict = dict_create ();
 
-  /* Execution. */
-  parse_script ();
+  parse_command_line (argc, argv);
+  outp_read_devices ();
 
-  /* Should never be reached */
-  return (-1);
-}
+  lex_init ();
 
-/* Parses the entire script. */
-static void
-parse_script (void)
-{
   while (!finished)
     {
       err_check_count ();
       handle_error (execute_command ());
     }
 
-  err_hcf (err_error_count==0);
+  terminate (err_error_count == 0);
+  abort ();
+}
+
+/* Terminate PSPP.  SUCCESS should be true to exit successfully,
+   false to exit as a failure.  */
+void
+terminate (bool success)
+{
+  static bool terminating = false;
+  if (terminating)
+    return;
+  terminating = true;
+
+  err_done ();
+  outp_done ();
+
+  cancel_transformations ();
+  dict_destroy (default_dict);
+
+  random_done ();
+  settings_done ();
+  fh_done ();
+  lex_done ();
+  getl_uninitialize ();
+
+  exit (success ? EXIT_SUCCESS : EXIT_FAILURE);
 }
 
 /* Parse and execute a command, returning its return code. */
 static int
 execute_command (void)
 {
+  int result;
+  
   /* Read the command's first token.
      We may hit end of file.
      If so, give the line reader a chance to proceed to the next file.
@@ -112,13 +157,30 @@ execute_command (void)
       if (token != T_STOP)
        break;
 
-      if (!getl_perform_delayed_reset ())
-       err_hcf (err_error_count==0);
+      /* Sets the options flag of the current script to 0, thus allowing it
+        to be read in.  Returns nonzero if this action was taken, zero
+        otherwise. */
+      if (getl_head && getl_head->separate)
+       {
+         getl_head->separate = 0;
+         discard_variables ();
+         lex_reset_eof ();
+       }
+      else
+       terminate (err_error_count == 0);
     }
 
   /* Parse the command. */
   getl_prompt = GETL_PRPT_CONTINUATION;
-  return cmd_parse ();
+  result =  cmd_parse ();
+  /* Unset the /ALGORITHM subcommand if it was used */
+  unset_cmd_algorithm ();
+
+  /* Clear any auxiliary data from the dictionary. */
+  dict_clear_aux (default_dict);
+
+  return result;
 }
 
 /* Print an error message corresponding to the command return code
@@ -155,52 +217,64 @@ handle_error (int code)
       assert (0);
     }
 
-  if (getl_reading_script)
+  if (getl_reading_script())
     {
       err_break ();
       while (token != T_STOP && token != '.')
        lex_get ();
     }
-  else
-    lex_discard_line ();
+  else 
+    {
+      msg (SW, _("The rest of this command has been discarded."));
+      lex_discard_line (); 
+    }
+}
+\f
+static void
+i18n_init (void) 
+{
+#if ENABLE_NLS
+#if HAVE_LC_MESSAGES
+  setlocale (LC_MESSAGES, "");
+#endif
+  setlocale (LC_MONETARY, "");
+  bindtextdomain (PACKAGE, locale_dir);
+  textdomain (PACKAGE);
+#endif /* ENABLE_NLS */
 }
 
-
+static void
+fpu_init (void) 
+{
+#if HAVE_FEHOLDEXCEPT
+  fenv_t foo;
+  feholdexcept (&foo);
+#elif HAVE___SETFPUCW && defined(_FPU_IEEE)
+  __setfpucw (_FPU_IEEE);
+#endif
+}
 
 /* If a segfault happens, issue a message to that effect and halt */
 void 
-bug_handler(int sig UNUSED)
+bug_handler(int sig)
 {
-  fprintf(stderr,
-         "******************************************************************\n"
-         "You have discovered a bug in PSPP.\n\n"
-         "  Please report this, by sending "
-         "an email to " PACKAGE_BUGREPORT ",\n"
-         "explaining what you were doing when this happened, and including\n"
-         "a sample of your input file which caused it.\n");
-
-  fprintf(stderr,
-         "Also, please copy the following lines into your bug report:\n\n"
-         "bare_version:        %s\n" 
-         "version:             %s\n"
-         "stat_version:        %s\n"
-         "host_system:         %s\n"
-         "build_system:        %s\n"
-         "default_config_path: %s\n"
-         "include_path:        %s\n"
-         "groff_font_path:     %s\n"
-         "locale_dir:          %s\n"
-         "******************************************************************\n",
-         bare_version,         
-         version,
-         stat_version,
-         host_system,        
-         build_system,
-         default_config_path,
-         include_path, 
-         groff_font_path,
-         locale_dir);     
-
-  exit(-1);
+  switch (sig) 
+    {
+    case SIGFPE:
+      request_bug_report_and_abort("Floating Point Exception");
+      break;
+    case SIGSEGV:
+      request_bug_report_and_abort("Segmentation Violation");
+      break;
+    default:
+      request_bug_report_and_abort("");
+      break;
+    }
 }
 
+
+void 
+interrupt_handler(int sig UNUSED)
+{
+  terminate (false);
+}