From: Ben Pfaff Date: Wed, 30 Dec 2020 20:29:13 +0000 (-0800) Subject: work X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e8ee60e6a2fe7cef633c28cda312852e2a7d8087;p=pspp work --- diff --git a/src/output/pivot-table.c b/src/output/pivot-table.c index d0588365a1..561e45657d 100644 --- a/src/output/pivot-table.c +++ b/src/output/pivot-table.c @@ -396,6 +396,10 @@ pivot_category_set_rc (struct pivot_category *category, const char *s) category->dimension->table, s); if (format) category->format = *format; + + struct pivot_value *name = category->name; + if (name->type == PIVOT_VALUE_NUMERIC && !name->numeric.format.w) + name->numeric.format = format ? *format : *settings_get_format (); } static void @@ -789,6 +793,12 @@ pivot_result_class_change (const char *s_, const struct fmt_spec *format) return rc != NULL; } + +bool +is_pivot_result_class (const char *s) +{ + return pivot_result_class_find (s) != NULL; +} /* Pivot tables. */ @@ -1368,8 +1378,8 @@ pivot_category_assign_label_depth (struct pivot_category *category, static bool pivot_axis_assign_label_depth (struct pivot_table *table, - enum pivot_axis_type axis_type, - bool dimension_labels_in_corner) + enum pivot_axis_type axis_type, + bool dimension_labels_in_corner) { struct pivot_axis *axis = &table->axes[axis_type]; bool any_label_shown_in_corner = false; @@ -1401,10 +1411,6 @@ pivot_table_assign_label_depth (struct pivot_table *table) pivot_axis_assign_label_depth (table, PIVOT_AXIS_LAYER, false); } -/* Footnotes. */ - - - static void indent (int indentation) { diff --git a/src/output/pivot-table.h b/src/output/pivot-table.h index 7c36c43b2d..22995da74c 100644 --- a/src/output/pivot-table.h +++ b/src/output/pivot-table.h @@ -365,6 +365,7 @@ void pivot_category_destroy (struct pivot_category *); #define PIVOT_RC_COUNT ("RC_COUNT") bool pivot_result_class_change (const char *, const struct fmt_spec *); +bool is_pivot_result_class (const char *); /* Styling for a pivot table. diff --git a/tests/automake.mk b/tests/automake.mk index c90565c124..e87363e4bb 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -239,9 +239,10 @@ tests_math_chart_get_ticks_format_test_LDADD = \ check_PROGRAMS += tests/output/pivot-table-test tests_output_pivot_table_test_SOURCES = tests/output/pivot-table-test.c tests_output_pivot_table_test_LDADD = \ - src/libpspp/liblibpspp.la \ + src/libpspp.la \ src/libpspp-core.la \ - gl/libgl.la + gl/libgl.la \ + $(CAIRO_LIBS) EXTRA_DIST += tests/output/render-test.c diff --git a/tests/output/pivot-table-test.c b/tests/output/pivot-table-test.c new file mode 100644 index 0000000000..8200c18737 --- /dev/null +++ b/tests/output/pivot-table-test.c @@ -0,0 +1,380 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "data/file-handle-def.h" +#include "language/lexer/lexer.h" +#include "libpspp/assertion.h" +#include "libpspp/compiler.h" +#include "libpspp/i18n.h" +#include "libpspp/string-map.h" +#include "output/driver.h" +#include "output/pivot-table.h" +#include "output/table-item.h" + +#include "gl/error.h" +#include "gl/progname.h" +#include "gl/xalloc.h" +#include "gl/xvasprintf.h" + +/* --emphasis: Enable emphasis in ASCII driver? */ +static bool emphasis; + +/* --box: ASCII driver box option. */ +static char *box; + +/* -o, --output: Base name for output files. */ +static const char *output_base = "render"; + +static const char *parse_options (int argc, char **argv); +static void usage (void) NO_RETURN; +static struct pivot_table *read_table (struct lexer *); + +int +main (int argc, char **argv) +{ + const char *input_file_name; + + set_program_name (argv[0]); + i18n_init (); + output_engine_push (); + input_file_name = parse_options (argc, argv); + + settings_init (); + + struct lex_reader *reader = lex_reader_for_file (input_file_name, NULL, + LEX_SYNTAX_AUTO, + LEX_ERROR_CONTINUE); + if (!reader) + exit (1); + + struct lexer *lexer = lex_create (); + lex_include (lexer, reader); + lex_get (lexer); + + for (;;) + { + while (lex_match (lexer, T_ENDCMD)) + continue; + if (lex_match (lexer, T_STOP)) + break; + + struct pivot_table *pt = read_table (lexer); + pivot_table_dump (pt, 0); + pivot_table_submit (pt); + } + + lex_destroy (lexer); + output_engine_pop (); + fh_done (); + + return 0; +} + +static void PRINTF_FORMAT (2, 3) +register_driver (struct string_map *options, + const char *output_file, ...) +{ + va_list args; + va_start (args, output_file); + string_map_insert_nocopy (options, xstrdup ("output-file"), + xvasprintf (output_file, args)); + va_end (args); + + struct output_driver *driver = output_driver_create (options); + if (driver == NULL) + exit (EXIT_FAILURE); + output_driver_register (driver); +} + +static void +configure_drivers (int width, int length, int min_break) +{ + /* Render to stdout. */ + struct string_map options = STRING_MAP_INITIALIZER (options); + string_map_insert (&options, "format", "txt"); + string_map_insert_nocopy (&options, xstrdup ("width"), + xasprintf ("%d", width)); + if (min_break >= 0) + string_map_insert_nocopy (&options, xstrdup ("min-hbreak"), + xasprintf ("%d", min_break)); + string_map_insert (&options, "emphasis", emphasis ? "true" : "false"); + if (box != NULL) + string_map_insert (&options, "box", box); + register_driver (&options, "-"); + + /* Render to .txt. */ + register_driver (&options, "%s.txt", output_base); + +#ifdef HAVE_CAIRO + /* Render to .pdf. */ + string_map_insert (&options, "top-margin", "0"); + string_map_insert (&options, "bottom-margin", "0"); + string_map_insert (&options, "left-margin", "0"); + string_map_insert (&options, "right-margin", "0"); + string_map_insert_nocopy (&options, xstrdup ("paper-size"), + xasprintf ("%dx%dpt", width * 5, length * 8)); + if (min_break >= 0) + { + string_map_insert_nocopy (&options, xstrdup ("min-hbreak"), + xasprintf ("%d", min_break * 5)); + string_map_insert_nocopy (&options, xstrdup ("min-vbreak"), + xasprintf ("%d", min_break * 8)); + } + register_driver (&options, "%s.pdf", output_base); +#endif + + /* Render to .csv. */ + register_driver (&options, "%s.csv", output_base); + + /* Render to .odt. */ + register_driver (&options, "%s.odt", output_base); + + string_map_destroy (&options); +} + +static const char * +parse_options (int argc, char **argv) +{ + int width = 79; + int length = 66; + int min_break = -1; + + for (;;) + { + enum { + OPT_WIDTH = UCHAR_MAX + 1, + OPT_LENGTH, + OPT_MIN_BREAK, + OPT_EMPHASIS, + OPT_BOX, + OPT_HELP + }; + static const struct option options[] = + { + {"width", required_argument, NULL, OPT_WIDTH}, + {"length", required_argument, NULL, OPT_LENGTH}, + {"min-break", required_argument, NULL, OPT_MIN_BREAK}, + {"emphasis", no_argument, NULL, OPT_EMPHASIS}, + {"box", required_argument, NULL, OPT_BOX}, + {"output", required_argument, NULL, 'o'}, + {"help", no_argument, NULL, OPT_HELP}, + {NULL, 0, NULL, 0}, + }; + + int c = getopt_long (argc, argv, "o:", options, NULL); + if (c == -1) + break; + + switch (c) + { + case OPT_WIDTH: + width = atoi (optarg); + break; + + case OPT_LENGTH: + length = atoi (optarg); + break; + + case OPT_MIN_BREAK: + min_break = atoi (optarg); + break; + + case OPT_EMPHASIS: + emphasis = true; + break; + + case OPT_BOX: + box = optarg; + break; + + case 'o': + output_base = optarg; + break; + + case OPT_HELP: + usage (); + + case 0: + break; + + case '?': + exit(EXIT_FAILURE); + break; + + default: + NOT_REACHED (); + } + + } + + configure_drivers (width, length, min_break); + + if (optind + 1 != argc) + error (1, 0, "exactly one non-option argument required; " + "use --help for help"); + return argv[optind]; +} + +static void +usage (void) +{ + printf ("%s, to test rendering of PSPP tables\n" + "usage: %s [OPTIONS] INPUT\n" + "\nOptions:\n" + " --width=WIDTH set page width in characters\n" + " --length=LINE set page length in lines\n", + program_name, program_name); + exit (EXIT_SUCCESS); +} + +static struct pivot_value * +read_value (struct lexer *lexer) +{ + struct pivot_value *value; + if (lex_is_number (lexer)) + { + value = pivot_value_new_number (lex_number (lexer)); + lex_get (lexer); + } + else if (lex_is_string (lexer)) + { + value = pivot_value_new_user_text (lex_tokcstr (lexer), SIZE_MAX); + lex_get (lexer); + } + else + { + msg (SE, "Expecting pivot_value"); + exit (1); + } + + if (!lex_match (lexer, T_LBRACK)) + return value; + do + { + msg (SE, "Options not yet supported"); + exit (1); + } + while (lex_match (lexer, T_COMMA)); + if (!lex_force_match (lexer, T_RBRACK)) + exit (1); +} + +static void +read_group (struct lexer *lexer, struct pivot_table *pt, + struct pivot_category *group) +{ + if (lex_match (lexer, T_ASTERISK)) + group->show_label = true; + + if (!lex_force_match (lexer, T_LPAREN)) + exit (1); + + if (lex_match (lexer, T_RPAREN)) + return; + + do + { + struct pivot_value *name = read_value (lexer); + if (lex_token (lexer) == T_ASTERISK + || lex_token (lexer) == T_LPAREN) + read_group (lexer, pt, pivot_category_create_group__ (group, name)); + else + { + char *rc; + if (lex_token (lexer) == T_ID + && is_pivot_result_class (lex_tokcstr (lexer))) + { + rc = xstrdup (lex_tokcstr (lexer)); + lex_get (lexer); + } + else + rc = NULL; + + pivot_category_create_leaf_rc (group, name, rc); + + free (rc); + } + } + while (lex_match (lexer, T_COMMA)); + if (!lex_force_match (lexer, T_RPAREN)) + exit (1); +} + +static void +read_dimension (struct lexer *lexer, struct pivot_table *pt, + enum pivot_axis_type a) +{ + lex_match (lexer, T_EQUALS); + + struct pivot_value *name = read_value (lexer); + struct pivot_dimension *dim = pivot_dimension_create__ (pt, a, name); + read_group (lexer, pt, dim->root); +} + +static void +read_look (struct lexer *lexer, struct pivot_table *pt) +{ + lex_match (lexer, T_EQUALS); + + if (lex_is_string (lexer)) + { + struct pivot_table_look *look; + char *error = pivot_table_look_read (lex_tokcstr (lexer), &look); + if (error) + { + msg (SE, "%s", error); + exit (1); + } + + pivot_table_set_look (pt, look); + pivot_table_look_unref (look); + } +} + +static struct pivot_table * +read_table (struct lexer *lexer) +{ + struct pivot_table *pt = pivot_table_create__ (NULL, NULL); + while (lex_match (lexer, T_SLASH)) + { + if (lex_match_id (lexer, "ROW")) + read_dimension (lexer, pt, PIVOT_AXIS_ROW); + else if (lex_match_id (lexer, "COLUMN")) + read_dimension (lexer, pt, PIVOT_AXIS_COLUMN); + else if (lex_match_id (lexer, "LAYER")) + read_dimension (lexer, pt, PIVOT_AXIS_LAYER); + else if (lex_match_id (lexer, "LOOK")) + read_look (lexer, pt); + else + { + msg (SE, "Expecting keyword"); + exit (1); + } + } + + if (!lex_force_match (lexer, T_ENDCMD)) + exit (1); + return pt; +}