Fix bug reported by Jason Stover.
[pspp] / src / data / settings.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18 #include "settings.h"
19 #include <assert.h>
20 #include <stdlib.h>
21 #include <time.h>
22 #include "format.h"
23 #include "value.h"
24 #include "xalloc.h"
25 #include <libpspp/i18n.h>
26
27 #include "error.h"
28
29 #include "gettext.h"
30 #define _(msgid) gettext (msgid)
31
32 static int viewlength = 24;
33 static int viewwidth = 79;
34 static bool long_view = false;
35
36 static bool safer_mode = false;
37
38 static bool do_echo = false;
39 static bool include = true;
40
41 static int epoch = -1;
42
43 static bool errorbreak = false;
44
45 static bool route_errors_to_terminal = true;
46 static bool route_errors_to_listing = true;
47
48 static bool scompress = true;
49
50 static bool undefined = true;
51 static double blanks = SYSMIS;
52
53 static int mxwarns = 100;
54 static int mxerrs = 100;
55
56 static bool printback = true;
57 static bool mprint = true;
58
59 static int mxloops = 1;
60
61 static bool nulline = true;
62
63 static char endcmd = '.';
64
65 static size_t workspace = 4L * 1024 * 1024;
66
67 static struct fmt_spec default_format = {FMT_F, 8, 2};
68
69 static bool testing_mode = false;
70
71 static int global_algorithm = ENHANCED;
72 static int cmd_algorithm = ENHANCED;
73 static int *algorithm = &global_algorithm;
74
75 static int syntax = ENHANCED;
76
77 static void init_viewport (void);
78 static void get_termcap_viewport (void);
79
80 void
81 settings_init (void)
82 {
83   init_viewport ();
84   i18n_init ();
85 }
86
87 void
88 settings_done (void)
89 {
90   i18n_done ();
91 }
92
93 /* Screen length in lines. */
94 int
95 get_viewlength (void)
96 {
97   return viewlength;
98 }
99
100 /* Sets the view length. */
101 void
102 set_viewlength (int viewlength_)
103 {
104   viewlength = viewlength_;
105 }
106
107 /* Set view width to a very long value, and prevent it from ever
108    changing. */
109 void
110 force_long_view (void)
111 {
112   long_view = true;
113   viewwidth = 9999;
114 }
115
116 /* Screen width. */
117 int
118 get_viewwidth(void)
119 {
120   return viewwidth;
121 }
122
123 /* Sets the screen width. */
124 void
125 set_viewwidth (int viewwidth_)
126 {
127   viewwidth = viewwidth_;
128 }
129
130 static void
131 init_viewport (void)
132 {
133   if (long_view)
134     return;
135
136   viewwidth = viewlength = -1;
137
138   get_termcap_viewport ();
139
140   if (viewwidth < 0 && getenv ("COLUMNS") != NULL)
141     viewwidth = atoi (getenv ("COLUMNS"));
142   if (viewlength < 0 && getenv ("LINES") != NULL)
143     viewlength = atoi (getenv ("LINES"));
144
145   if (viewwidth < 0)
146     viewwidth = 79;
147   if (viewlength < 0)
148     viewlength = 24;
149 }
150
151 /* Whether PSPP can erase and overwrite files. */
152 bool
153 get_safer_mode (void)
154 {
155   return safer_mode;
156 }
157
158 /* Set safer mode. */
159 void
160 set_safer_mode (void)
161 {
162   safer_mode = true;
163 }
164
165 /* Echo commands to the listing file/printer? */
166 bool
167 get_echo (void)
168 {
169   return do_echo;
170 }
171
172 /* Set echo. */
173 void
174 set_echo (bool echo_)
175 {
176   do_echo = echo_;
177 }
178
179 /* If echo is on, whether commands from include files are echoed. */
180 bool
181 get_include (void)
182 {
183   return include;
184 }
185
186 /* Set include file echo. */
187 void
188 set_include (bool include_)
189 {
190   include = include_;
191 }
192
193 /* What year to use as the start of the epoch. */
194 int
195 get_epoch (void)
196 {
197   if (epoch < 0)
198     {
199       time_t t = time (0);
200       struct tm *tm = localtime (&t);
201       epoch = (tm != NULL ? tm->tm_year + 1900 : 2000) - 69;
202     }
203
204   return epoch;
205 }
206
207 /* Sets the year that starts the epoch. */
208 void
209 set_epoch (int epoch_)
210 {
211   epoch = epoch_;
212 }
213
214 /* Does an error stop execution? */
215 bool
216 get_errorbreak (void)
217 {
218   return errorbreak;
219 }
220
221 /* Sets whether an error stops execution. */
222 void
223 set_errorbreak (bool errorbreak_)
224 {
225   errorbreak = errorbreak_;
226 }
227
228 /* Route error messages to terminal? */
229 bool
230 get_error_routing_to_terminal (void)
231 {
232   return route_errors_to_terminal;
233 }
234
235 /* Sets whether error messages should be routed to the
236    terminal. */
237 void
238 set_error_routing_to_terminal (bool route_to_terminal)
239 {
240   route_errors_to_terminal = route_to_terminal;
241 }
242
243 /* Route error messages to listing file? */
244 bool
245 get_error_routing_to_listing (void)
246 {
247   return route_errors_to_listing;
248 }
249
250 /* Sets whether error messages should be routed to the
251    listing file. */
252 void
253 set_error_routing_to_listing (bool route_to_listing)
254 {
255   route_errors_to_listing = route_to_listing;
256 }
257
258 /* Compress system files by default? */
259 bool
260 get_scompression (void)
261 {
262   return scompress;
263 }
264
265 /* Set system file default compression. */
266 void
267 set_scompression (bool scompress_)
268 {
269   scompress = scompress_;
270 }
271
272 /* Whether to warn on undefined values in numeric data. */
273 bool
274 get_undefined (void)
275 {
276   return undefined;
277 }
278
279 /* Set whether to warn on undefined values. */
280 void
281 set_undefined (bool undefined_)
282 {
283   undefined = undefined_;
284 }
285
286 /* The value that blank numeric fields are set to when read in. */
287 double
288 get_blanks (void)
289 {
290   return blanks;
291 }
292
293 /* Set the value that blank numeric fields are set to when read
294    in. */
295 void
296 set_blanks (double blanks_)
297 {
298   blanks = blanks_;
299 }
300
301 /* Maximum number of warnings + errors. */
302 int
303 get_mxwarns (void)
304 {
305   return mxwarns;
306 }
307
308 /* Sets maximum number of warnings + errors. */
309 void
310 set_mxwarns (int mxwarns_)
311 {
312   mxwarns = mxwarns_;
313 }
314
315 /* Maximum number of errors. */
316 int
317 get_mxerrs (void)
318 {
319   return mxerrs;
320 }
321
322 /* Sets maximum number of errors. */
323 void
324 set_mxerrs (int mxerrs_)
325 {
326   mxerrs = mxerrs_;
327 }
328
329 /* Whether commands are written to the display. */
330 bool
331 get_printback (void)
332 {
333   return printback;
334 }
335
336 /* Sets whether commands are written to the display. */
337 void
338 set_printback (bool printback_)
339 {
340   printback = printback_;
341 }
342
343 /* Independent of get_printback, controls whether the commands
344    generated by macro invocations are displayed. */
345 bool
346 get_mprint (void)
347 {
348   return mprint;
349 }
350
351 /* Sets whether the commands generated by macro invocations are
352    displayed. */
353 void
354 set_mprint (bool mprint_)
355 {
356   mprint = mprint_;
357 }
358
359 /* Implied limit of unbounded loop. */
360 int
361 get_mxloops (void)
362 {
363   return mxloops;
364 }
365
366 /* Set implied limit of unbounded loop. */
367 void
368 set_mxloops (int mxloops_)
369 {
370   mxloops = mxloops_;
371 }
372
373 /* Whether a blank line is a command terminator. */
374 bool
375 get_nulline (void)
376 {
377   return nulline;
378 }
379
380 /* Set whether a blank line is a command terminator. */
381 void
382 set_nulline (bool nulline_)
383 {
384   nulline = nulline_;
385 }
386
387 /* The character used to terminate commands. */
388 char
389 get_endcmd (void)
390 {
391   return endcmd;
392 }
393
394 /* Set the character used to terminate commands. */
395 void
396 set_endcmd (char endcmd_)
397 {
398   endcmd = endcmd_;
399 }
400
401 /* Approximate maximum amount of memory to use for cases, in
402    bytes. */
403 size_t
404 get_workspace (void)
405 {
406   return workspace;
407 }
408
409 /* Approximate maximum number of cases to allocate in-core, given
410    that each case contains VALUE_CNT values. */
411 size_t
412 get_workspace_cases (size_t value_cnt)
413 {
414   size_t case_size = sizeof (union value) * value_cnt + 4 * sizeof (void *);
415   size_t case_cnt = MAX (get_workspace () / case_size, 4);
416   return case_cnt;
417 }
418
419 /* Set approximate maximum amount of memory to use for cases, in
420    bytes. */
421
422 void
423 set_workspace (size_t workspace_)
424 {
425   workspace = workspace_;
426 }
427
428 /* Default format for variables created by transformations and by
429    DATA LIST {FREE,LIST}. */
430 const struct fmt_spec *
431 get_format (void)
432 {
433   return &default_format;
434 }
435
436 /* Set default format for variables created by transformations
437    and by DATA LIST {FREE,LIST}. */
438 void
439 set_format (const struct fmt_spec *default_format_)
440 {
441   default_format = *default_format_;
442 }
443
444 /* Are we in testing mode?  (e.g. --testing-mode command line
445    option) */
446 bool
447 get_testing_mode (void)
448 {
449   return testing_mode;
450 }
451
452 /* Set testing mode. */
453 void
454 set_testing_mode (bool testing_mode_)
455 {
456   testing_mode = testing_mode_;
457 }
458
459 /* Return the current algorithm setting */
460 enum behavior_mode
461 get_algorithm (void)
462 {
463   return *algorithm;
464 }
465
466 /* Set the algorithm option globally. */
467 void
468 set_algorithm (enum behavior_mode mode)
469 {
470   global_algorithm = mode;
471 }
472
473 /* Set the algorithm option for this command only */
474 void
475 set_cmd_algorithm (enum behavior_mode mode)
476 {
477   cmd_algorithm = mode;
478   algorithm = &cmd_algorithm;
479 }
480
481 /* Unset the algorithm option for this command */
482 void
483 unset_cmd_algorithm (void)
484 {
485   algorithm = &global_algorithm;
486 }
487
488 /* Get the current syntax setting */
489 enum behavior_mode
490 get_syntax (void)
491 {
492   return syntax;
493 }
494
495 /* Set the syntax option */
496 void
497 set_syntax (enum behavior_mode mode)
498 {
499   syntax = mode;
500 }
501 \f
502 /* Code that interfaces to ncurses.  This must be at the very end
503    of this file because curses.h redefines "bool" on some systems
504    (e.g. OpenBSD), causing declaration mismatches with functions
505    that have parameters or return values of type "bool". */
506 #if HAVE_LIBNCURSES
507 #include <curses.h>
508 #include <term.h>
509
510 static void
511 get_termcap_viewport (void)
512 {
513   char term_buffer[16384];
514   if (getenv ("TERM") == NULL)
515     return;
516   else if (tgetent (term_buffer, getenv ("TERM")) <= 0)
517     {
518       error (0,0, _("could not access definition for terminal `%s'"),
519              getenv ("TERM"));
520       return;
521     }
522
523   if (tgetnum ("li") > 0)
524     viewlength = tgetnum ("li");
525
526   if (tgetnum ("co") > 1)
527     viewwidth = tgetnum ("co") - 1;
528 }
529 #else /* !HAVE_LIBNCURSES */
530 static void
531 get_termcap_viewport (void)
532 {
533   /* Nothing to do. */
534 }
535 #endif /* !HAVE_LIBNCURSES */