1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
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.
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.
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/>. */
26 #include "data/file-handle-def.h"
27 #include "language/lexer/lexer.h"
28 #include "libpspp/assertion.h"
29 #include "libpspp/compiler.h"
30 #include "libpspp/i18n.h"
31 #include "libpspp/string-map.h"
32 #include "output/driver.h"
33 #include "output/pivot-table.h"
34 #include "output/table-item.h"
37 #include "gl/progname.h"
38 #include "gl/xalloc.h"
39 #include "gl/xvasprintf.h"
41 /* --emphasis: Enable emphasis in ASCII driver? */
44 /* --box: ASCII driver box option. */
47 /* -o, --output: Base name for output files. */
48 static const char *output_base = "render";
50 static const char *parse_options (int argc, char **argv);
51 static void usage (void) NO_RETURN;
52 static struct pivot_table *read_table (struct lexer *);
55 main (int argc, char **argv)
57 const char *input_file_name;
59 set_program_name (argv[0]);
61 output_engine_push ();
62 input_file_name = parse_options (argc, argv);
66 struct lex_reader *reader = lex_reader_for_file (input_file_name, NULL,
72 struct lexer *lexer = lex_create ();
73 lex_include (lexer, reader);
78 while (lex_match (lexer, T_ENDCMD))
80 if (lex_match (lexer, T_STOP))
83 struct pivot_table *pt = read_table (lexer);
84 pivot_table_dump (pt, 0);
85 pivot_table_submit (pt);
95 static void PRINTF_FORMAT (2, 3)
96 register_driver (struct string_map *options,
97 const char *output_file, ...)
100 va_start (args, output_file);
101 string_map_insert_nocopy (options, xstrdup ("output-file"),
102 xvasprintf (output_file, args));
105 struct output_driver *driver = output_driver_create (options);
108 output_driver_register (driver);
112 configure_drivers (int width, int length, int min_break)
114 /* Render to stdout. */
115 struct string_map options = STRING_MAP_INITIALIZER (options);
116 string_map_insert (&options, "format", "txt");
117 string_map_insert_nocopy (&options, xstrdup ("width"),
118 xasprintf ("%d", width));
120 string_map_insert_nocopy (&options, xstrdup ("min-hbreak"),
121 xasprintf ("%d", min_break));
122 string_map_insert (&options, "emphasis", emphasis ? "true" : "false");
124 string_map_insert (&options, "box", box);
125 register_driver (&options, "-");
127 /* Render to <base>.txt. */
128 register_driver (&options, "%s.txt", output_base);
131 /* Render to <base>.pdf. */
132 string_map_insert (&options, "top-margin", "0");
133 string_map_insert (&options, "bottom-margin", "0");
134 string_map_insert (&options, "left-margin", "0");
135 string_map_insert (&options, "right-margin", "0");
136 string_map_insert_nocopy (&options, xstrdup ("paper-size"),
137 xasprintf ("%dx%dpt", width * 5, length * 8));
140 string_map_insert_nocopy (&options, xstrdup ("min-hbreak"),
141 xasprintf ("%d", min_break * 5));
142 string_map_insert_nocopy (&options, xstrdup ("min-vbreak"),
143 xasprintf ("%d", min_break * 8));
145 register_driver (&options, "%s.pdf", output_base);
148 /* Render to <base>.csv. */
149 register_driver (&options, "%s.csv", output_base);
151 /* Render to <base>.odt. */
152 register_driver (&options, "%s.odt", output_base);
154 string_map_destroy (&options);
158 parse_options (int argc, char **argv)
167 OPT_WIDTH = UCHAR_MAX + 1,
174 static const struct option options[] =
176 {"width", required_argument, NULL, OPT_WIDTH},
177 {"length", required_argument, NULL, OPT_LENGTH},
178 {"min-break", required_argument, NULL, OPT_MIN_BREAK},
179 {"emphasis", no_argument, NULL, OPT_EMPHASIS},
180 {"box", required_argument, NULL, OPT_BOX},
181 {"output", required_argument, NULL, 'o'},
182 {"help", no_argument, NULL, OPT_HELP},
186 int c = getopt_long (argc, argv, "o:", options, NULL);
193 width = atoi (optarg);
197 length = atoi (optarg);
201 min_break = atoi (optarg);
213 output_base = optarg;
232 configure_drivers (width, length, min_break);
234 if (optind + 1 != argc)
235 error (1, 0, "exactly one non-option argument required; "
236 "use --help for help");
243 printf ("%s, to test rendering of PSPP tables\n"
244 "usage: %s [OPTIONS] INPUT\n"
246 " --width=WIDTH set page width in characters\n"
247 " --length=LINE set page length in lines\n",
248 program_name, program_name);
252 static struct pivot_value *
253 read_value (struct lexer *lexer)
255 struct pivot_value *value;
256 if (lex_is_number (lexer))
258 value = pivot_value_new_number (lex_number (lexer));
261 else if (lex_is_string (lexer))
263 value = pivot_value_new_user_text (lex_tokcstr (lexer), SIZE_MAX);
268 msg (SE, "Expecting pivot_value");
272 if (!lex_match (lexer, T_LBRACK))
276 msg (SE, "Options not yet supported");
279 while (lex_match (lexer, T_COMMA));
280 if (!lex_force_match (lexer, T_RBRACK))
285 read_group (struct lexer *lexer, struct pivot_table *pt,
286 struct pivot_category *group)
288 if (lex_match (lexer, T_ASTERISK))
289 group->show_label = true;
291 if (!lex_force_match (lexer, T_LPAREN))
294 if (lex_match (lexer, T_RPAREN))
299 struct pivot_value *name = read_value (lexer);
300 if (lex_token (lexer) == T_ASTERISK
301 || lex_token (lexer) == T_LPAREN)
302 read_group (lexer, pt, pivot_category_create_group__ (group, name));
306 if (lex_token (lexer) == T_ID
307 && is_pivot_result_class (lex_tokcstr (lexer)))
309 rc = xstrdup (lex_tokcstr (lexer));
315 pivot_category_create_leaf_rc (group, name, rc);
320 while (lex_match (lexer, T_COMMA));
321 if (!lex_force_match (lexer, T_RPAREN))
326 read_dimension (struct lexer *lexer, struct pivot_table *pt,
327 enum pivot_axis_type a)
329 lex_match (lexer, T_EQUALS);
331 struct pivot_value *name = read_value (lexer);
332 struct pivot_dimension *dim = pivot_dimension_create__ (pt, a, name);
333 read_group (lexer, pt, dim->root);
337 read_look (struct lexer *lexer, struct pivot_table *pt)
339 lex_match (lexer, T_EQUALS);
341 if (lex_is_string (lexer))
343 struct pivot_table_look *look;
344 char *error = pivot_table_look_read (lex_tokcstr (lexer), &look);
347 msg (SE, "%s", error);
351 pivot_table_set_look (pt, look);
352 pivot_table_look_unref (look);
356 static struct pivot_table *
357 read_table (struct lexer *lexer)
359 struct pivot_table *pt = pivot_table_create__ (NULL, NULL);
360 while (lex_match (lexer, T_SLASH))
362 if (lex_match_id (lexer, "ROW"))
363 read_dimension (lexer, pt, PIVOT_AXIS_ROW);
364 else if (lex_match_id (lexer, "COLUMN"))
365 read_dimension (lexer, pt, PIVOT_AXIS_COLUMN);
366 else if (lex_match_id (lexer, "LAYER"))
367 read_dimension (lexer, pt, PIVOT_AXIS_LAYER);
368 else if (lex_match_id (lexer, "LOOK"))
369 read_look (lexer, pt);
372 msg (SE, "Expecting keyword");
377 if (!lex_force_match (lexer, T_ENDCMD))