Added coefficient-handling routines
[pspp-builds.git] / src / main.c
index b0582c1b297a5e28bf298be6471869acbf95a9b8..be22605b822dec1d0b9d17ccc3a25b584614d039 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 <stdio.h>
-#include <gsl/gsl_errno.h>
 #include "main.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.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 <signal.h>
+#include "var.h"
+#include "version.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;
 
-/* Initialise error handling on the gsl library */
-static void 
-err_handler_gsl (const char *reason, const char *file,
-       int line, int gsl_errno UNUSED)
-{
-  msg(FE, _("gsl error at %s:%d; reason: \"%s\""), file,line,reason);
-}
-
 /* Program entry point. */
 int
 main (int argc, char **argv)
 {
   signal (SIGSEGV, bug_handler);
+  signal (SIGFPE, bug_handler);
+  signal (SIGINT, interrupt_handler);
 
-  gsl_set_error_handler(err_handler_gsl);
+  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 ();
+  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. */
@@ -107,6 +144,7 @@ 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.
@@ -119,8 +157,17 @@ 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. */
@@ -130,6 +177,9 @@ execute_command (void)
   /* 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;
 }
 
@@ -167,7 +217,7 @@ handle_error (int code)
       assert (0);
     }
 
-  if (getl_reading_script)
+  if (getl_reading_script())
     {
       err_break ();
       while (token != T_STOP && token != '.')
@@ -179,12 +229,52 @@ handle_error (int code)
       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)
+{
+  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)
 {
-  request_bug_report_and_abort("Segmentation Violation");
+  terminate (false);
 }