ab3a0b6d0ec30cf1eb710a1cc2e23b9d6aaea7c0
[pspp-builds.git] / src / main.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
3    Written by Ben Pfaff <blp@gnu.org>.
4
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18    02110-1301, USA. */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <gsl/gsl_errno.h>
23 #include "main.h"
24 #include "cmdline.h"
25 #include "command.h"
26 #include "dictionary.h"
27 #include "error.h"
28 #include "getline.h"
29 #include "glob.h"
30 #include "lexer.h"
31 #include "output.h"
32 #include "settings.h"
33 #include "var.h"
34 #include <signal.h>
35
36 #include <stdlib.h>
37
38 #include "debug-print.h"
39
40 static void parse_script (void) NO_RETURN;
41 static void handle_error (int code);
42 static int execute_command (void);
43
44 /* argv[0] with stripped leading directories. */
45 char *pgmname;
46
47 /* Whether FINISH. has been executed. */
48 int finished;
49
50 /* The current date in the form DD MMM YYYY. */
51 char curdate[12];
52
53
54 /* If a segfault happens, issue a message to that effect and halt */
55 void bug_handler(int sig);
56
57 /* Handle quit/term/int signals */
58 void interrupt_handler(int sig);
59
60 /* Whether we're dropping down to interactive mode immediately because
61    we hit end-of-file unexpectedly (or whatever). */
62 int start_interactive;
63
64
65
66
67
68
69 /* Program entry point. */
70 int
71 main (int argc, char **argv)
72 {
73
74   signal (SIGSEGV, bug_handler);
75   signal (SIGFPE,  bug_handler);
76   signal (SIGINT,  interrupt_handler);
77
78   gsl_set_error_handler_off();
79
80   /* Initialization. */
81   if (!outp_init ())
82     err_hcf (0);
83   init_glob (argc, argv);
84   parse_command_line (argc, argv);
85   if (!outp_read_devices ())
86     msg (FE, _("Error initializing output drivers."));
87
88   lex_init ();
89
90   /* Execution. */
91   parse_script ();
92
93   /* Should never be reached */
94   return (-1);
95 }
96
97 /* Parses the entire script. */
98 static void
99 parse_script (void)
100 {
101   while (!finished)
102     {
103       err_check_count ();
104       handle_error (execute_command ());
105     }
106
107   err_hcf (err_error_count==0);
108 }
109
110 /* Parse and execute a command, returning its return code. */
111 static int
112 execute_command (void)
113 {
114   int result;
115   
116   /* Read the command's first token.
117      We may hit end of file.
118      If so, give the line reader a chance to proceed to the next file.
119      End of file is not handled transparently since the user may want
120      the dictionary cleared between files. */
121   getl_prompt = GETL_PRPT_STANDARD;
122   for (;;)
123     {
124       lex_get ();
125       if (token != T_STOP)
126         break;
127
128       if (!getl_perform_delayed_reset ())
129         err_hcf (err_error_count==0);
130     }
131
132   /* Parse the command. */
133   getl_prompt = GETL_PRPT_CONTINUATION;
134   result =  cmd_parse ();
135  
136   /* Unset the /ALGORITHM subcommand if it was used */
137   unset_cmd_algorithm ();
138
139   /* Clear any auxiliary data from the dictionary. */
140   dict_clear_aux (default_dict);
141
142   return result;
143 }
144
145 /* Print an error message corresponding to the command return code
146    CODE. */
147 static void
148 handle_error (int code)
149 {
150   switch (code)
151     {
152     case CMD_SUCCESS:
153       return;
154           
155     case CMD_FAILURE:
156       msg (SW,  _("This command not executed."));
157       break;
158
159     case CMD_PART_SUCCESS_MAYBE:
160       msg (SW, _("Skipping the rest of this command.  Part of "
161                  "this command may have been executed."));
162       break;
163                   
164     case CMD_PART_SUCCESS:
165       msg (SW, _("Skipping the rest of this command.  This "
166                  "command was fully executed up to this point."));
167       break;
168
169     case CMD_TRAILING_GARBAGE:
170       msg (SW, _("Trailing garbage was encountered following "
171                  "this command.  The command was fully executed "
172                  "to this point."));
173       break;
174
175     default:
176       assert (0);
177     }
178
179   if (getl_reading_script)
180     {
181       err_break ();
182       while (token != T_STOP && token != '.')
183         lex_get ();
184     }
185   else 
186     {
187       msg (SW, _("The rest of this command has been discarded."));
188       lex_discard_line (); 
189     }
190 }
191
192
193
194 /* If a segfault happens, issue a message to that effect and halt */
195 void 
196 bug_handler(int sig UNUSED)
197 {
198   switch (sig) 
199     {
200     case SIGFPE:
201       request_bug_report_and_abort("Floating Point Exception");
202       break;
203     case SIGSEGV:
204       request_bug_report_and_abort("Segmentation Violation");
205       break;
206     default:
207       request_bug_report_and_abort("");
208       break;
209     }
210 }
211
212
213 void 
214 interrupt_handler(int sig UNUSED)
215 {
216   err_hcf(0);
217 }