/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "format.h"
#include "value.h"
#include "xalloc.h"
+#include <data/case.h>
#include <libpspp/i18n.h>
#include <libpspp/integer-format.h>
#include <libpspp/message.h>
#include "error.h"
+#include "minmax.h"
#include "gettext.h"
#define _(msgid) gettext (msgid)
int *viewlength;
int *viewwidth;
bool safer_mode;
- bool do_echo;
bool include;
int epoch;
- bool errorbreak;
bool route_errors_to_terminal;
bool route_errors_to_listing;
bool scompress;
bool undefined;
double blanks;
- int mxwarns;
- int mxerrs;
+ int max_messages[MSG_N_SEVERITIES];
bool printback;
bool mprint;
int mxloops;
int *algorithm;
int syntax;
- struct fmt_number_style *styles;
+ struct fmt_settings *styles;
+
+ enum settings_output_devices output_routing[SETTINGS_N_OUTPUT_TYPES];
};
static struct settings the_settings = {
- /* input_integer_format */
- INTEGER_NATIVE,
- /* input_float_format */
- FLOAT_NATIVE_DOUBLE,
- /* output_integer_format */
- INTEGER_NATIVE,
- /* output_float_format */
- FLOAT_NATIVE_DOUBLE,
- /* viewlength */
- NULL,
- /* viewwidth */
- NULL,
- /* safer_mode */
- false,
- /* do_echo */
- false,
- /* include */
- true,
- /* epoch */
- -1,
- /* errorbreak */
- false,
- /* route_errors_to_terminal */
- true,
- /* route_errors_to_listing */
- true,
- /* scompress */
- true,
- /* undefined */
- true,
- /* blanks */
- SYSMIS,
- /* mxwarns */
- 100,
- /* mxerrs */
- 100,
- /* printback */
- true,
- /* mprint */
- true,
- /* mxloops */
- 1,
- /* nulline */
- true,
- /* endcmd */
- '.',
- /* workspace */
- 64L * 1024 * 1024,
- /* default_format */
- {FMT_F, 8, 2},
- /* testing_mode */
- false,
- /* cmd_algorithm */
- ENHANCED,
- /* algorithm */
- &global_algorithm,
- /* syntax */
- ENHANCED,
- /* styles */
- NULL
+ INTEGER_NATIVE, /* input_integer_format */
+ FLOAT_NATIVE_DOUBLE, /* input_float_format */
+ INTEGER_NATIVE, /* output_integer_format */
+ FLOAT_NATIVE_DOUBLE, /* output_float_format */
+ NULL, /* viewlength */
+ NULL, /* viewwidth */
+ false, /* safer_mode */
+ true, /* include */
+ -1, /* epoch */
+ true, /* route_errors_to_terminal */
+ true, /* route_errors_to_listing */
+ true, /* scompress */
+ true, /* undefined */
+ SYSMIS, /* blanks */
+
+ /* max_messages */
+ {
+ 100, /* MSG_S_ERROR */
+ 100, /* MSG_S_WARNING */
+ 100 /* MSG_S_NOTE */
+ },
+
+ true, /* printback */
+ true, /* mprint */
+ 1, /* mxloops */
+ true, /* nulline */
+ '.', /* endcmd */
+ 64L * 1024 * 1024, /* workspace */
+ {FMT_F, 8, 2}, /* default_format */
+ false, /* testing_mode */
+ ENHANCED, /* cmd_algorithm */
+ &global_algorithm, /* algorithm */
+ ENHANCED, /* syntax */
+ NULL, /* styles */
+
+ /* output_routing */
+ {SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL,
+ SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL,
+ 0,
+ SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL}
};
static void init_viewport ( int *, int *);
{
init_viewport (width, length);
settings_set_epoch (-1);
- i18n_init ();
- the_settings.styles = fmt_create ();
+ the_settings.styles = fmt_settings_create ();
settings_set_decimal_char (get_system_decimal ());
}
void
settings_done (void)
{
- fmt_done (the_settings.styles);
- i18n_done ();
+ fmt_settings_destroy (the_settings.styles);
}
/* Returns the floating-point format used for RB and RBHEX
the_settings.safer_mode = true;
}
-/* Echo commands to the listing file/printer? */
-bool
-settings_get_echo (void)
-{
- return the_settings.do_echo;
-}
-
-/* Set echo. */
-void
-settings_set_echo ( bool echo)
-{
- the_settings.do_echo = echo;
-}
-
/* If echo is on, whether commands from include files are echoed. */
bool
settings_get_include (void)
assert (the_settings.epoch >= 0);
}
-/* Does an error stop execution? */
-bool
-settings_get_errorbreak (void)
-{
- return the_settings.errorbreak;
-}
-
-/* Sets whether an error stops execution. */
-void
-settings_set_errorbreak ( bool errorbreak)
-{
- the_settings.errorbreak = errorbreak;
-}
-
-/* Route error messages to terminal? */
-bool
-settings_get_error_routing_to_terminal (void)
-{
- return the_settings.route_errors_to_terminal;
-}
-
-/* Sets whether error messages should be routed to the
- terminal. */
-void
-settings_set_error_routing_to_terminal ( bool route_to_terminal)
-{
- the_settings.route_errors_to_terminal = route_to_terminal;
-}
-
-/* Route error messages to listing file? */
-bool
-settings_get_error_routing_to_listing (void)
-{
- return the_settings.route_errors_to_listing;
-}
-
-/* Sets whether error messages should be routed to the
- listing file. */
-void
-settings_set_error_routing_to_listing ( bool route_to_listing)
-{
- the_settings.route_errors_to_listing = route_to_listing;
-}
-
/* Compress system files by default? */
bool
settings_get_scompression (void)
the_settings.blanks = blanks;
}
-/* Maximum number of warnings + errors. */
+/* Returns the maximum number of messages to show of the given SEVERITY before
+ aborting. (The value for MSG_S_WARNING is interpreted as maximum number of
+ warnings and errors combined.) */
int
-settings_get_mxwarns (void)
+settings_get_max_messages (enum msg_severity severity)
{
- return the_settings.mxwarns;
+ assert (severity < MSG_N_SEVERITIES);
+ return the_settings.max_messages[severity];
}
-/* Sets maximum number of warnings + errors. */
+/* Sets the maximum number of messages to show of the given SEVERITY before
+ aborting to MAX. (The value for MSG_S_WARNING is interpreted as maximum
+ number of warnings and errors combined.) In addition, in the case of
+ warnings the special value of zero indicates that no warnings are to be
+ issued.
+*/
void
-settings_set_mxwarns ( int mxwarns)
-{
- the_settings.mxwarns = mxwarns;
-}
-
-/* Maximum number of errors. */
-int
-settings_get_mxerrs (void)
+settings_set_max_messages (enum msg_severity severity, int max)
{
- return the_settings.mxerrs;
-}
+ assert (severity < MSG_N_SEVERITIES);
-/* Sets maximum number of errors. */
-void
-settings_set_mxerrs ( int mxerrs)
-{
- the_settings.mxerrs = mxerrs;
-}
-
-/* Whether commands are written to the display. */
-bool
-settings_get_printback (void)
-{
- return the_settings.printback;
-}
+ if (severity == MSG_S_WARNING)
+ {
+ if ( max == 0)
+ {
+ msg (MW,
+ _("MXWARNS set to zero. No further warnings will be given even when potentially problematic situations are encountered."));
+ msg_ui_disable_warnings (true);
+ }
+ else if ( the_settings.max_messages [MSG_S_WARNING] == 0)
+ {
+ msg_ui_disable_warnings (false);
+ the_settings.max_messages[MSG_S_WARNING] = max;
+ msg (MW, _("Warnings re-enabled. %d warnings will be issued before aborting syntax processing."), max);
+ }
+ }
-/* Sets whether commands are written to the display. */
-void
-settings_set_printback ( bool printback)
-{
- the_settings.printback = printback;
+ the_settings.max_messages[severity] = max;
}
/* Independent of get_printback, controls whether the commands
}
/* Approximate maximum number of cases to allocate in-core, given
- that each case contains VALUE_CNT values. */
+ that each case has the format given in PROTO. */
size_t
-settings_get_workspace_cases (size_t value_cnt)
+settings_get_workspace_cases (const struct caseproto *proto)
{
- size_t case_size = sizeof (union value) * value_cnt + 4 * sizeof (void *);
- size_t case_cnt = MAX (settings_get_workspace () / case_size, 4);
- return case_cnt;
+ size_t n_cases = settings_get_workspace () / case_get_cost (proto);
+ return MAX (n_cases, 4);
}
/* Set approximate maximum amount of memory to use for cases, in
return true;
}
-/* Extracts a token from IN into a newly allocated AFFIX. Tokens
- are delimited by GROUPING. The token is truncated to at most
- FMT_STYLE_AFFIX_MAX characters. Returns the first character
- following the token. */
+/* Extracts a token from IN into AFFIX, using BUFFER for storage. BUFFER must
+ have at least FMT_STYLE_AFFIX_MAX + 1 bytes of space. Tokens are delimited
+ by GROUPING. The token is truncated to at most FMT_STYLE_AFFIX_MAX bytes,
+ followed by a null terminator. Returns the first character following the
+ token. */
static const char *
-extract_cc_token (const char *in, int grouping, struct substring *affix)
+extract_cc_token (const char *in, int grouping, struct substring *affix,
+ char buffer[FMT_STYLE_AFFIX_MAX + 1])
{
size_t ofs = 0;
- ss_alloc_uninit (affix, FMT_STYLE_AFFIX_MAX);
+
for (; *in != '\0' && *in != grouping; in++)
{
if (*in == '\'' && in[1] == grouping)
in++;
if (ofs < FMT_STYLE_AFFIX_MAX)
- ss_data (*affix)[ofs++] = *in;
+ buffer[ofs++] = *in;
}
- affix->length = ofs;
+ *affix = ss_buffer (buffer, ofs);
if (*in == grouping)
in++;
return in;
}
-
/* Sets custom currency specifier CC having name CC_NAME ('A' through
'E') to correspond to the settings in CC_STRING. */
bool
settings_set_cc (const char *cc_string, enum fmt_type type)
{
- struct fmt_number_style *cc = &the_settings.styles[type];
+ char a[FMT_STYLE_AFFIX_MAX + 1];
+ char b[FMT_STYLE_AFFIX_MAX + 1];
+ char c[FMT_STYLE_AFFIX_MAX + 1];
+ char d[FMT_STYLE_AFFIX_MAX + 1];
+ struct fmt_number_style cc;
assert (fmt_get_category (type) == FMT_CAT_CUSTOM);
/* Determine separators. */
- if (!find_cc_separators (cc_string, cc))
+ if (!find_cc_separators (cc_string, &cc))
{
msg (SE, _("%s: Custom currency string `%s' does not contain "
"exactly three periods or commas (or it contains both)."),
return false;
}
- cc_string = extract_cc_token (cc_string, cc->grouping, &cc->neg_prefix);
- cc_string = extract_cc_token (cc_string, cc->grouping, &cc->prefix);
- cc_string = extract_cc_token (cc_string, cc->grouping, &cc->suffix);
- cc_string = extract_cc_token (cc_string, cc->grouping, &cc->neg_suffix);
+ cc_string = extract_cc_token (cc_string, cc.grouping, &cc.neg_prefix, a);
+ cc_string = extract_cc_token (cc_string, cc.grouping, &cc.prefix, b);
+ cc_string = extract_cc_token (cc_string, cc.grouping, &cc.suffix, c);
+ cc_string = extract_cc_token (cc_string, cc.grouping, &cc.neg_suffix, d);
- fmt_check_style (cc);
+ fmt_settings_set_style (the_settings.styles, type, &cc);
return true;
}
int
settings_get_decimal_char (enum fmt_type type)
{
- return fmt_get_style (the_settings.styles, type)->decimal;
+ return fmt_settings_get_style (the_settings.styles, type)->decimal;
}
void
settings_set_decimal_char (char decimal)
{
- fmt_set_decimal (the_settings.styles, decimal);
+ fmt_settings_set_decimal (the_settings.styles, decimal);
}
-
-
/* Returns the number formatting style associated with the given
format TYPE. */
const struct fmt_number_style *
settings_get_style (enum fmt_type type)
{
assert (is_fmt_type (type));
- return &the_settings.styles[type];
+ return fmt_settings_get_style (the_settings.styles, type);
}
-
/* Returns a string of the form "$#,###.##" according to FMT,
which must be of type FMT_DOLLAR. The caller must free the
string. */
char *
settings_dollar_template (const struct fmt_spec *fmt)
{
- const struct fmt_number_style *styles = the_settings.styles;
struct string str = DS_EMPTY_INITIALIZER;
int c;
const struct fmt_number_style *fns ;
assert (fmt->type == FMT_DOLLAR);
- fns = fmt_get_style (styles, fmt->type);
+ fns = fmt_settings_get_style (the_settings.styles, fmt->type);
ds_put_char (&str, '$');
for (c = MAX (fmt->w - fmt->d - 1, 0); c > 0; )
return ds_cstr (&str);
}
+
+void
+settings_set_output_routing (enum settings_output_type type,
+ enum settings_output_devices devices)
+{
+ assert (type < SETTINGS_N_OUTPUT_TYPES);
+ the_settings.output_routing[type] = devices;
+}
+
+enum settings_output_devices
+settings_get_output_routing (enum settings_output_type type)
+{
+ assert (type < SETTINGS_N_OUTPUT_TYPES);
+ return the_settings.output_routing[type] | SETTINGS_DEVICE_UNFILTERED;
+}