X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fsettings.c;h=c70635cec03fc06da0dd7c472a8da626e2010fd6;hb=3640237a5fc890a84cb814fbe8bf6fd9299624e4;hp=3e95b6b5bfd3bf64eec1dd8d17471c9d29ea0d84;hpb=43b1296aafe7582e7dbe6c2b6a8b478d7d9b0fcf;p=pspp diff --git a/src/data/settings.c b/src/data/settings.c index 3e95b6b5bf..c70635cec0 100644 --- a/src/data/settings.c +++ b/src/data/settings.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011, 2015 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 @@ -15,503 +15,725 @@ along with this program. If not, see . */ #include -#include "settings.h" -#include -#include -#include -#include "format.h" -#include "value.h" -#include "xalloc.h" -#include - -static int viewlength = 24; -static int viewwidth = 79; -static bool long_view = false; - -static bool safer_mode = false; - -static bool echo = false; -static bool include = true; - -static int epoch = -1; - -static bool errorbreak = false; - -static bool route_errors_to_terminal = true; -static bool route_errors_to_listing = true; - -static bool scompress = true; - -static bool undefined = true; -static double blanks = SYSMIS; - -static int mxwarns = 100; -static int mxerrs = 100; -static bool printback = true; -static bool mprint = true; +#include "data/settings.h" -static int mxloops = 1; - -static bool nulline = true; - -static char endcmd = '.'; - -static size_t workspace = 4L * 1024 * 1024; - -static struct fmt_spec default_format = {FMT_F, 8, 2}; - -static bool testing_mode = false; - -static int global_algorithm = ENHANCED; -static int cmd_algorithm = ENHANCED; -static int *algorithm = &global_algorithm; - -static int syntax = ENHANCED; - -static void init_viewport (void); +#include +#include +#include "data/case.h" +#include "data/format.h" +#include "data/value.h" +#include "libpspp/i18n.h" +#include "libpspp/integer-format.h" +#include "libpspp/message.h" + +#include "gl/minmax.h" +#include "gl/xalloc.h" + +#include "gettext.h" +#define _(msgid) gettext (msgid) + +struct settings +{ + /* Integer format used for IB and PIB input. */ + enum integer_format input_integer_format; + + /* Floating-point format used for RB and RBHEX input. */ + enum float_format input_float_format; + + /* Format of integers in output (SET WIB). */ + enum integer_format output_integer_format; + + /* Format of reals in output (SET WRB). */ + enum float_format output_float_format; + + /* MATRIX...END MATRIX settings. */ + enum settings_mdisplay mdisplay; + + int viewlength; + int viewwidth; + bool safer_mode; + bool include; + bool route_errors_to_terminal; + bool route_errors_to_listing; + bool scompress; + bool undefined; + double blanks; + int max_messages[MSG_N_SEVERITIES]; + bool printback; + + /* Macro settings. */ + bool mexpand; /* Expand macros? */ + bool mprint; /* Print macro expansions? */ + int miterate; /* Maximum iterations of !FOR. */ + int mnest; /* Maximum nested macro expansion levels. */ + + int mxloops; + size_t workspace; + struct fmt_spec default_format; + bool testing_mode; + int fuzzbits; + int scalemin; + + int cmd_algorithm; + int global_algorithm; + int syntax; + + struct fmt_settings styles; + double small; + + enum settings_output_devices output_routing[SETTINGS_N_OUTPUT_TYPES]; + + enum settings_value_show show_values; + enum settings_value_show show_variables; +}; + +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, + .mdisplay = SETTINGS_MDISPLAY_TEXT, + .viewlength = 24, + .viewwidth = 79, + .safer_mode = false, + .include = true, + .route_errors_to_terminal = true, + .route_errors_to_listing = true, + .scompress = true, + .undefined = true, + .blanks = SYSMIS, + + .max_messages = { + [MSG_S_ERROR] = 100, + [MSG_S_WARNING] = 100, + [MSG_S_NOTE] = 100 + }, + + .printback = true, + + .mexpand = true, + .mprint = false, + .miterate = 1000, + .mnest = 50, + + .mxloops = 40, + .workspace = 64L * 1024 * 1024, + .default_format = { .type = FMT_F, .w = 8, .d = 2 }, + .testing_mode = false, + .fuzzbits = 6, + .scalemin = 24, + .cmd_algorithm = ENHANCED, + .global_algorithm = ENHANCED, + .syntax = ENHANCED, + .styles = FMT_SETTINGS_INIT, + .small = .0001, + + /* output_routing */ + .output_routing = { +#define LT (SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL) + [SETTINGS_OUTPUT_ERROR] = LT, + [SETTINGS_OUTPUT_NOTE] = LT, + [SETTINGS_OUTPUT_SYNTAX] = 0, + [SETTINGS_OUTPUT_RESULT] = LT +#undef LT + }, + + .show_values = SETTINGS_VALUE_SHOW_LABEL, + .show_variables = SETTINGS_VALUE_SHOW_LABEL, +}; + +/* Initializes the settings module. */ void settings_init (void) { - init_viewport (); - i18n_init (); + settings_set_decimal_char (get_system_decimal ()); } +/* Cleans up the settings module. */ void settings_done (void) { - i18n_done (); + settings_destroy (&the_settings); } -/* Screen length in lines. */ -int -get_viewlength (void) +static void +settings_copy (struct settings *dst, const struct settings *src) { - return viewlength; + *dst = *src; + dst->styles = fmt_settings_copy (&src->styles); } -/* Sets the view length. */ +/* Returns a copy of the current settings. */ +struct settings * +settings_get (void) +{ + struct settings *s = xmalloc (sizeof *s); + settings_copy (s, &the_settings); + return s; +} + +/* Replaces the current settings by those in S. The caller retains ownership + of S. */ void -set_viewlength (int viewlength_) +settings_set (const struct settings *s) { - viewlength = viewlength_; + settings_destroy (&the_settings); + settings_copy (&the_settings, s); } -/* Set view width to a very long value, and prevent it from ever - changing. */ +/* Destroys S. */ void -force_long_view (void) +settings_destroy (struct settings *s) { - long_view = true; - viewwidth = 9999; + if (s != NULL) + { + fmt_settings_uninit (&s->styles); + if (s != &the_settings) + free (s); + } } -/* Screen width. */ -int -get_viewwidth(void) +/* Returns the floating-point format used for RB and RBHEX + input. */ +enum float_format +settings_get_input_float_format (void) { - return viewwidth; + return the_settings.input_float_format; } -/* Sets the screen width. */ +/* Sets the floating-point format used for RB and RBHEX input to + FORMAT. */ void -set_viewwidth (int viewwidth_) +settings_set_input_float_format (enum float_format format) { - viewwidth = viewwidth_; + the_settings.input_float_format = format; } -#if HAVE_LIBTERMCAP -static void -get_termcap_viewport (void) +/* Returns the integer format used for IB and PIB input. */ +enum integer_format +settings_get_input_integer_format (void) { - char term_buffer[16384]; - if (getenv ("TERM") == NULL) - return; - else if (tgetent (term_buffer, getenv ("TERM")) <= 0) - { - msg (IE, _("Could not access definition for terminal `%s'."), termtype); - return; - } - - if (tgetnum ("li") > 0) - viewlength = tgetnum ("li"); - - if (tgetnum ("co") > 1) - viewwidth = tgetnum ("co") - 1; + return the_settings.input_integer_format; } -#endif /* HAVE_LIBTERMCAP */ -static void -init_viewport (void) +/* Sets the integer format used for IB and PIB input to + FORMAT. */ +void +settings_set_input_integer_format (enum integer_format format) { - if (long_view) - return; - - viewwidth = viewlength = -1; - -#if HAVE_LIBTERMCAP - get_termcap_viewport (); -#endif /* HAVE_LIBTERMCAP */ - - if (viewwidth < 0 && getenv ("COLUMNS") != NULL) - viewwidth = atoi (getenv ("COLUMNS")); - if (viewlength < 0 && getenv ("LINES") != NULL) - viewlength = atoi (getenv ("LINES")); - - if (viewwidth < 0) - viewwidth = 79; - if (viewlength < 0) - viewlength = 24; + the_settings.input_integer_format = format; } -/* Whether PSPP can erase and overwrite files. */ -bool -get_safer_mode (void) +/* Returns the current output integer format. */ +enum integer_format +settings_get_output_integer_format (void) { - return safer_mode; + return the_settings.output_integer_format; } -/* Set safer mode. */ +/* Sets the output integer format to INTEGER_FORMAT. */ void -set_safer_mode (void) +settings_set_output_integer_format ( + enum integer_format integer_format) { - safer_mode = true; + the_settings.output_integer_format = integer_format; } -/* Echo commands to the listing file/printer? */ -bool -get_echo (void) +/* Returns the current output float format. */ +enum float_format +settings_get_output_float_format (void) { - return echo; + return the_settings.output_float_format; } -/* Set echo. */ +/* Sets the output float format to FLOAT_FORMAT. */ void -set_echo (bool echo_) +settings_set_output_float_format (enum float_format float_format) { - echo = echo_; + the_settings.output_float_format = float_format; } -/* If echo is on, whether commands from include files are echoed. */ -bool -get_include (void) +/* Screen length in lines. */ +int +settings_get_viewlength (void) { - return include; + return the_settings.viewlength; } -/* Set include file echo. */ +/* Sets the view length. */ void -set_include (bool include_) +settings_set_viewlength (int viewlength_) { - include = include_; + the_settings.viewlength = viewlength_; } -/* What year to use as the start of the epoch. */ +/* Screen width. */ int -get_epoch (void) +settings_get_viewwidth(void) { - if (epoch < 0) - { - time_t t = time (0); - struct tm *tm = localtime (&t); - epoch = (tm != NULL ? tm->tm_year + 1900 : 2000) - 69; - } - - return epoch; + return the_settings.viewwidth; } -/* Sets the year that starts the epoch. */ +/* Sets the screen width. */ void -set_epoch (int epoch_) +settings_set_viewwidth (int viewwidth_) { - epoch = epoch_; + the_settings.viewwidth = viewwidth_; } -/* Does an error stop execution? */ +/* Whether PSPP can erase and overwrite files. */ bool -get_errorbreak (void) +settings_get_safer_mode (void) { - return errorbreak; + return the_settings.safer_mode; } -/* Sets whether an error stops execution. */ +/* Set safer mode. */ void -set_errorbreak (bool errorbreak_) +settings_set_safer_mode (void) { - errorbreak = errorbreak_; + the_settings.safer_mode = true; } -/* Route error messages to terminal? */ +/* If echo is on, whether commands from include files are echoed. */ bool -get_error_routing_to_terminal (void) +settings_get_include (void) { - return route_errors_to_terminal; + return the_settings.include; } -/* Sets whether error messages should be routed to the - terminal. */ +/* Set include file echo. */ void -set_error_routing_to_terminal (bool route_to_terminal) +settings_set_include (bool include) { - route_errors_to_terminal = route_to_terminal; + the_settings.include = include; } -/* Route error messages to listing file? */ -bool -get_error_routing_to_listing (void) +/* Returns the year that starts the epoch. */ +int +settings_get_epoch (void) { - return route_errors_to_listing; + return the_settings.styles.epoch; } -/* Sets whether error messages should be routed to the - listing file. */ +/* Sets the year that starts the epoch. */ void -set_error_routing_to_listing (bool route_to_listing) +settings_set_epoch (int epoch) { - route_errors_to_listing = route_to_listing; + the_settings.styles.epoch = epoch; } /* Compress system files by default? */ bool -get_scompression (void) +settings_get_scompression (void) { - return scompress; + return the_settings.scompress; } /* Set system file default compression. */ void -set_scompression (bool scompress_) +settings_set_scompression (bool scompress) { - scompress = scompress_; + the_settings.scompress = scompress; } /* Whether to warn on undefined values in numeric data. */ bool -get_undefined (void) +settings_get_undefined (void) { - return undefined; + return the_settings.undefined; } /* Set whether to warn on undefined values. */ void -set_undefined (bool undefined_) +settings_set_undefined (bool undefined) { - undefined = undefined_; + the_settings.undefined = undefined; } /* The value that blank numeric fields are set to when read in. */ double -get_blanks (void) +settings_get_blanks (void) { - return blanks; + return the_settings.blanks; } /* Set the value that blank numeric fields are set to when read in. */ void -set_blanks (double blanks_) +settings_set_blanks (double blanks) { - blanks = blanks_; + 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 -get_mxwarns (void) +settings_get_max_messages (enum msg_severity severity) { - return 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 -set_mxwarns (int mxwarns_) +settings_set_max_messages (enum msg_severity severity, int max) { - mxwarns = mxwarns_; -} + assert (severity < MSG_N_SEVERITIES); -/* Maximum number of errors. */ -int -get_mxerrs (void) -{ - return mxerrs; -} + 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 maximum number of errors. */ -void -set_mxerrs (int mxerrs_) -{ - mxerrs = mxerrs_; + the_settings.max_messages[severity] = max; } -/* Whether commands are written to the display. */ +/* Returns whether to expand macro invocations. */ bool -get_printback (void) +settings_get_mexpand (void) { - return printback; + return the_settings.mexpand; } -/* Sets whether commands are written to the display. */ +/* Sets whether to expand macro invocations. */ void -set_printback (bool printback_) +settings_set_mexpand (bool mexpand) { - printback = printback_; + the_settings.mexpand = mexpand; } /* Independent of get_printback, controls whether the commands generated by macro invocations are displayed. */ bool -get_mprint (void) +settings_get_mprint (void) { - return mprint; + return the_settings.mprint; } /* Sets whether the commands generated by macro invocations are displayed. */ void -set_mprint (bool mprint_) +settings_set_mprint (bool mprint) { - mprint = mprint_; + the_settings.mprint = mprint; } -/* Implied limit of unbounded loop. */ +/* Returns the limit for loop iterations within a macro. */ int -get_mxloops (void) +settings_get_miterate (void) { - return mxloops; + return the_settings.miterate; } -/* Set implied limit of unbounded loop. */ +/* Sets the limit for loop iterations within a macro. */ void -set_mxloops (int mxloops_) +settings_set_miterate (int miterate) { - mxloops = mxloops_; + the_settings.miterate = miterate; } -/* Whether a blank line is a command terminator. */ -bool -get_nulline (void) +/* Returns the limit for recursion macro expansions. */ +int settings_get_mnest (void) { - return nulline; + return the_settings.mnest; } -/* Set whether a blank line is a command terminator. */ +/* Sets the limit for recursion macro expansions. */ void -set_nulline (bool nulline_) +settings_set_mnest (int mnest) { - nulline = nulline_; + the_settings.mnest = mnest; } -/* The character used to terminate commands. */ -char -get_endcmd (void) +int settings_get_mxloops (void); +void settings_set_mxloops (int); +/* Implied limit of unbounded loop. */ +int +settings_get_mxloops (void) { - return endcmd; + return the_settings.mxloops; } -/* Set the character used to terminate commands. */ +/* Set implied limit of unbounded loop. */ void -set_endcmd (char endcmd_) +settings_set_mxloops (int mxloops) { - endcmd = endcmd_; + the_settings.mxloops = mxloops; } /* Approximate maximum amount of memory to use for cases, in bytes. */ size_t -get_workspace (void) +settings_get_workspace (void) { - return workspace; + return the_settings.workspace; } /* 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 -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 (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 bytes. */ void -set_workspace (size_t workspace_) +settings_set_workspace (size_t workspace) { - workspace = workspace_; + the_settings.workspace = workspace; } /* Default format for variables created by transformations and by DATA LIST {FREE,LIST}. */ const struct fmt_spec * -get_format (void) +settings_get_format (void) { - return &default_format; + return &the_settings.default_format; } /* Set default format for variables created by transformations and by DATA LIST {FREE,LIST}. */ void -set_format (const struct fmt_spec *default_format_) +settings_set_format (const struct fmt_spec *default_format) { - default_format = *default_format_; + the_settings.default_format = *default_format; } /* Are we in testing mode? (e.g. --testing-mode command line option) */ bool -get_testing_mode (void) +settings_get_testing_mode (void) { - return testing_mode; + return the_settings.testing_mode; } /* Set testing mode. */ void -set_testing_mode (bool testing_mode_) +settings_set_testing_mode (bool testing_mode) { - testing_mode = testing_mode_; + the_settings.testing_mode = testing_mode; +} + +int +settings_get_fuzzbits (void) +{ + return the_settings.fuzzbits; +} + +void +settings_set_fuzzbits (int fuzzbits) +{ + the_settings.fuzzbits = fuzzbits; +} + +int +settings_get_scalemin (void) +{ + return the_settings.scalemin; +} + +void +settings_set_scalemin (int scalemin) +{ + the_settings.scalemin = scalemin; } /* Return the current algorithm setting */ enum behavior_mode -get_algorithm (void) +settings_get_algorithm (void) { - return *algorithm; + return the_settings.cmd_algorithm; } /* Set the algorithm option globally. */ void -set_algorithm (enum behavior_mode mode) +settings_set_algorithm (enum behavior_mode mode) { - global_algorithm = mode; + the_settings.global_algorithm = the_settings.cmd_algorithm = mode; } /* Set the algorithm option for this command only */ void -set_cmd_algorithm (enum behavior_mode mode) +settings_set_cmd_algorithm (enum behavior_mode mode) { - cmd_algorithm = mode; - algorithm = &cmd_algorithm; + the_settings.cmd_algorithm = mode; } /* Unset the algorithm option for this command */ void unset_cmd_algorithm (void) { - algorithm = &global_algorithm; + the_settings.cmd_algorithm = the_settings.global_algorithm; } /* Get the current syntax setting */ enum behavior_mode -get_syntax (void) +settings_get_syntax (void) { - return syntax; + return the_settings.syntax; } /* Set the syntax option */ void -set_syntax (enum behavior_mode mode) +settings_set_syntax (enum behavior_mode mode) +{ + the_settings.syntax = mode; +} + + +/* 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 *style = fmt_number_style_from_string (cc_string); + if (!style) + { + msg (SE, _("%s: Custom currency string `%s' does not contain " + "exactly three periods or commas (or it contains both)."), + fmt_name (type), cc_string); + return false; + } + + fmt_settings_set_cc (&the_settings.styles, type, style); + return true; +} + +void +settings_set_decimal_char (char decimal) +{ + the_settings.styles.decimal = decimal; +} + +void +settings_set_include_leading_zero (bool include_leading_zero) +{ + the_settings.styles.include_leading_zero = include_leading_zero; +} + +const struct fmt_settings * +settings_get_fmt_settings (void) +{ + return &the_settings.styles; +} + +double +settings_get_small (void) +{ + return the_settings.small; +} + +void +settings_set_small (double small) +{ + the_settings.small = small; +} + +/* 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) +{ + struct string str = DS_EMPTY_INITIALIZER; + int c; + const struct fmt_number_style *fns ; + + assert (fmt->type == FMT_DOLLAR); + + fns = fmt_settings_get_style (&the_settings.styles, fmt->type); + + ds_put_byte (&str, '$'); + for (c = MAX (fmt->w - fmt->d - 1, 0); c > 0;) + { + ds_put_byte (&str, '#'); + if (--c % 4 == 0 && c > 0) + { + ds_put_byte (&str, fns->grouping); + --c; + } + } + if (fmt->d > 0) + { + ds_put_byte (&str, fns->decimal); + ds_put_byte_multiple (&str, '#', fmt->d); + } + + 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; +} + +enum settings_value_show +settings_get_show_values (void) +{ + return the_settings.show_values; +} + +void +settings_set_show_values (enum settings_value_show s) +{ + the_settings.show_values = s; +} + + +enum settings_value_show +settings_get_show_variables (void) +{ + return the_settings.show_variables; +} + +void +settings_set_show_variables (enum settings_value_show s) +{ + the_settings.show_variables = s; +} + +enum settings_mdisplay +settings_get_mdisplay (void) +{ + return the_settings.mdisplay; +} + +void +settings_set_mdisplay (enum settings_mdisplay mdisplay) { - syntax = mode; + the_settings.mdisplay = mdisplay; }