1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2017, 2018 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/>. */
25 #include "data/file-handle-def.h"
26 #include "data/settings.h"
27 #include "libpspp/i18n.h"
28 #include "libpspp/message.h"
29 #include "libpspp/string-map.h"
30 #include "libpspp/string-set.h"
31 #include "output/driver.h"
32 #include "output/group-item.h"
33 #include "output/image-item.h"
34 #include "output/page-setup-item.h"
35 #include "output/pivot-table.h"
36 #include "output/spv/light-binary-parser.h"
37 #include "output/spv/spv-legacy-data.h"
38 #include "output/spv/spv-output.h"
39 #include "output/spv/spv-select.h"
40 #include "output/spv/spv-table-look.h"
41 #include "output/spv/spv.h"
42 #include "output/table-item.h"
43 #include "output/text-item.h"
45 #include "gl/c-ctype.h"
47 #include "gl/progname.h"
48 #include "gl/version-etc.h"
49 #include "gl/xalloc.h"
51 #include <libxml/tree.h>
52 #include <libxml/xpath.h>
53 #include <libxml/xpathInternals.h>
56 #define _(msgid) gettext (msgid)
58 /* -O key=value: Output driver options. */
59 static struct string_map output_options
60 = STRING_MAP_INITIALIZER (output_options);
62 /* --member-name: Include .zip member name in "dir" output. */
63 static bool show_member_names;
65 /* --show-hidden, --select, --commands, ...: Selection criteria. */
66 static struct spv_criteria *criteria;
67 static size_t n_criteria, allocated_criteria;
69 /* --or: Add new element to 'criteria' array. */
70 static bool new_criteria;
72 /* --sort: Sort members under dump-light-table, to make comparisons easier. */
75 /* --raw: Dump raw binary data in dump-light-table. */
78 /* -f, --force: Keep output file even on error. */
81 /* --table-look: TableLook to replace table style for conversion. */
82 static struct pivot_table_look *table_look;
84 /* Number of warnings issued. */
85 static size_t n_warnings;
87 static void usage (void);
88 static void developer_usage (void);
89 static void parse_options (int argc, char **argv);
92 dump_item (const struct spv_item *item)
94 if (show_member_names && (item->xml_member || item->bin_member))
96 const char *x = item->xml_member;
97 const char *b = item->bin_member;
99 /* The strings below are not marked for translation because they are only
100 useful to developers. */
102 ? xasprintf ("%s and %s:", x, b)
103 : xasprintf ("%s:", x ? x : b));
104 text_item_submit (text_item_create_nocopy (TEXT_ITEM_TITLE, s,
105 xstrdup ("Member Names")));
108 switch (spv_item_get_type (item))
110 case SPV_ITEM_HEADING:
114 spv_text_submit (item);
118 pivot_table_submit (pivot_table_ref (spv_item_get_table (item)));
128 image_item_submit (image_item_create (cairo_surface_reference (
129 spv_item_get_image (item))));
141 print_item_directory (const struct spv_item *item)
143 for (int i = 1; i < spv_item_get_level (item); i++)
146 enum spv_item_type type = spv_item_get_type (item);
147 printf ("- %s", spv_item_type_to_string (type));
149 const char *label = spv_item_get_label (item);
151 printf (" \"%s\"", label);
153 if (type == SPV_ITEM_TABLE)
155 const struct pivot_table *table = spv_item_get_table (item);
156 char *title = pivot_value_to_string (table->title, table);
157 if (!label || strcmp (title, label))
158 printf (" title \"%s\"", title);
162 const char *command_id = spv_item_get_command_id (item);
164 printf (" command \"%s\"", command_id);
166 const char *subtype = spv_item_get_subtype (item);
167 if (subtype && (!label || strcmp (label, subtype)))
168 printf (" subtype \"%s\"", subtype);
170 if (!spv_item_is_visible (item))
171 printf (" (hidden)");
173 if (show_member_names)
175 const char *members[] = {
182 for (size_t i = 0; i < sizeof members / sizeof *members; i++)
184 printf (" %s %s", n++ == 0 ? "in" : "and", members[i]);
190 run_detect (int argc UNUSED, char **argv)
192 char *err = spv_detect (argv[1]);
194 error (1, 0, "%s", err);
198 run_directory (int argc UNUSED, char **argv)
200 struct spv_reader *spv;
201 char *err = spv_open (argv[1], &spv);
203 error (1, 0, "%s", err);
205 struct spv_item **items;
207 spv_select (spv, criteria, n_criteria, &items, &n_items);
208 for (size_t i = 0; i < n_items; i++)
209 print_item_directory (items[i]);
217 const struct spv_item **nodes;
221 const struct spv_item *stub[N_STUB];
225 swap_nodes (const struct spv_item **a, const struct spv_item **b)
227 const struct spv_item *tmp = *a;
233 get_path (const struct spv_item *item, struct item_path *path)
235 size_t allocated = 10;
236 path->nodes = path->stub;
241 if (path->n >= allocated)
243 if (path->nodes == path->stub)
244 path->nodes = xmemdup (path->stub, sizeof path->stub);
245 path->nodes = x2nrealloc (path->nodes, &allocated,
246 sizeof *path->nodes);
248 path->nodes[path->n++] = item;
252 for (size_t i = 0; i < path->n / 2; i++)
253 swap_nodes (&path->nodes[i], &path->nodes[path->n - i - 1]);
257 free_path (struct item_path *path)
259 if (path && path->nodes != path->stub)
264 dump_heading_transition (const struct spv_item *old,
265 const struct spv_item *new)
270 struct item_path old_path, new_path;
271 get_path (old, &old_path);
272 get_path (new, &new_path);
275 for (; common < old_path.n && common < new_path.n; common++)
276 if (old_path.nodes[common] != new_path.nodes[common])
279 for (size_t i = common; i < old_path.n; i++)
280 group_close_item_submit (group_close_item_create ());
281 for (size_t i = common; i < new_path.n; i++)
282 group_open_item_submit (group_open_item_create (
283 new_path.nodes[i]->command_id,
284 new_path.nodes[i]->label));
286 free_path (&old_path);
287 free_path (&new_path);
291 run_convert (int argc UNUSED, char **argv)
293 struct spv_reader *spv;
294 char *err = spv_open (argv[1], &spv);
296 error (1, 0, "%s", err);
299 spv_item_set_table_look (spv_get_root (spv), table_look);
301 output_engine_push ();
302 output_set_filename (argv[1]);
303 string_map_replace (&output_options, "output-file", argv[2]);
304 struct output_driver *driver = output_driver_create (&output_options);
307 output_driver_register (driver);
309 const struct page_setup *ps = spv_get_page_setup (spv);
311 page_setup_item_submit (page_setup_item_create (ps));
313 struct spv_item **items;
315 spv_select (spv, criteria, n_criteria, &items, &n_items);
316 struct spv_item *prev_heading = spv_get_root (spv);
317 for (size_t i = 0; i < n_items; i++)
319 struct spv_item *heading
320 = items[i]->type == SPV_ITEM_HEADING ? items[i] : items[i]->parent;
321 dump_heading_transition (prev_heading, heading);
322 dump_item (items[i]);
323 prev_heading = heading;
325 dump_heading_transition (prev_heading, spv_get_root (spv));
330 output_engine_pop ();
333 if (n_warnings && !force)
335 /* XXX There could be other files to unlink, e.g. the ascii driver can
336 produce additional files with the charts. */
341 static const struct pivot_table *
342 get_first_table (const struct spv_reader *spv)
344 struct spv_item **items;
346 spv_select (spv, criteria, n_criteria, &items, &n_items);
348 for (size_t i = 0; i < n_items; i++)
349 if (spv_item_is_table (items[i]))
352 return spv_item_get_table (items[i]);
360 run_get_table_look (int argc UNUSED, char **argv)
362 struct pivot_table_look *look;
363 if (strcmp (argv[1], "-"))
365 struct spv_reader *spv;
366 char *err = spv_open (argv[1], &spv);
368 error (1, 0, "%s", err);
370 const struct pivot_table *table = get_first_table (spv);
372 error (1, 0, "%s: no tables found", argv[1]);
374 look = pivot_table_look_ref (pivot_table_get_look (table));
379 look = pivot_table_look_ref (pivot_table_look_builtin_default ());
381 char *err = spv_table_look_write (argv[2], look);
383 error (1, 0, "%s", err);
385 pivot_table_look_unref (look);
389 run_convert_table_look (int argc UNUSED, char **argv)
391 struct pivot_table_look *look;
392 char *err = spv_table_look_read (argv[1], &look);
394 error (1, 0, "%s", err);
396 err = spv_table_look_write (argv[2], look);
398 error (1, 0, "%s", err);
400 pivot_table_look_unref (look);
405 run_dump (int argc UNUSED, char **argv)
407 struct spv_reader *spv;
408 char *err = spv_open (argv[1], &spv);
410 error (1, 0, "%s", err);
412 struct spv_item **items;
414 spv_select (spv, criteria, n_criteria, &items, &n_items);
415 for (size_t i = 0; i < n_items; i++)
416 if (items[i]->type == SPV_ITEM_TABLE)
418 pivot_table_dump (spv_item_get_table (items[i]), 0);
427 compare_borders (const void *a_, const void *b_)
429 const struct spvlb_border *const *ap = a_;
430 const struct spvlb_border *const *bp = b_;
431 uint32_t a = (*ap)->border_type;
432 uint32_t b = (*bp)->border_type;
434 return a < b ? -1 : a > b;
438 compare_cells (const void *a_, const void *b_)
440 const struct spvlb_cell *const *ap = a_;
441 const struct spvlb_cell *const *bp = b_;
442 uint64_t a = (*ap)->index;
443 uint64_t b = (*bp)->index;
445 return a < b ? -1 : a > b;
449 run_dump_light_table (int argc UNUSED, char **argv)
451 if (raw && isatty (STDOUT_FILENO))
452 error (1, 0, "not writing binary data to tty");
454 struct spv_reader *spv;
455 char *err = spv_open (argv[1], &spv);
457 error (1, 0, "%s", err);
459 struct spv_item **items;
461 spv_select (spv, criteria, n_criteria, &items, &n_items);
462 for (size_t i = 0; i < n_items; i++)
464 if (!spv_item_is_light_table (items[i]))
472 error = spv_item_get_raw_light_table (items[i], &data, &size);
475 fwrite (data, size, 1, stdout);
481 struct spvlb_table *table;
482 error = spv_item_get_light_table (items[i], &table);
487 qsort (table->borders->borders, table->borders->n_borders,
488 sizeof *table->borders->borders, compare_borders);
489 qsort (table->cells->cells, table->cells->n_cells,
490 sizeof *table->cells->cells, compare_cells);
492 spvlb_print_table (items[i]->bin_member, 0, table);
493 spvlb_free_table (table);
498 msg (ME, "%s", error);
509 run_dump_legacy_data (int argc UNUSED, char **argv)
511 struct spv_reader *spv;
512 char *err = spv_open (argv[1], &spv);
514 error (1, 0, "%s", err);
516 struct spv_item **items;
518 spv_select (spv, criteria, n_criteria, &items, &n_items);
519 for (size_t i = 0; i < n_items; i++)
520 if (spv_item_is_legacy_table (items[i]))
522 struct spv_data data;
528 error = spv_item_get_raw_legacy_data (items[i], &data, &size);
531 fwrite (data, size, 1, stdout);
537 error = spv_item_get_legacy_data (items[i], &data);
540 printf ("%s:\n", items[i]->bin_member);
541 spv_data_dump (&data, stdout);
542 spv_data_uninit (&data);
549 msg (ME, "%s", error);
558 /* This is really bogus.
560 XPath doesn't have any notion of a default XML namespace, but all of the
561 elements in the documents we're interested in have a namespace. Thus, we'd
562 need to require the XPath expressions to have a namespace on every single
563 element: vis:sourceVariable, vis:graph, and so on. That's a pain. So,
564 instead, we remove the default namespace from everyplace it occurs. XPath
565 does support the null namespace, so this allows sourceVariable, graph,
568 See http://plasmasturm.org/log/259/ and
569 https://mail.gnome.org/archives/xml/2003-April/msg00144.html for more
572 remove_default_xml_namespace (xmlNode *node)
574 if (node->ns && !node->ns->prefix)
577 for (xmlNode *child = node->children; child; child = child->next)
578 remove_default_xml_namespace (child);
582 register_ns (xmlXPathContext *ctx, const char *prefix, const char *uri)
584 xmlXPathRegisterNs (ctx, CHAR_CAST (xmlChar *, prefix),
585 CHAR_CAST (xmlChar *, uri));
588 static xmlXPathContext *
589 create_xpath_context (xmlDoc *doc)
591 xmlXPathContext *ctx = xmlXPathNewContext (doc);
592 register_ns (ctx, "vgr", "http://xml.spss.com/spss/viewer/viewer-graph");
593 register_ns (ctx, "vizml", "http://xml.spss.com/visualization");
594 register_ns (ctx, "vmd", "http://xml.spss.com/spss/viewer/viewer-model");
595 register_ns (ctx, "vps", "http://xml.spss.com/spss/viewer/viewer-pagesetup");
596 register_ns (ctx, "vst", "http://xml.spss.com/spss/viewer/viewer-style");
597 register_ns (ctx, "vtb", "http://xml.spss.com/spss/viewer/viewer-table");
598 register_ns (ctx, "vtl", "http://xml.spss.com/spss/viewer/table-looks");
599 register_ns (ctx, "vtt", "http://xml.spss.com/spss/viewer/viewer-treemodel");
600 register_ns (ctx, "vtx", "http://xml.spss.com/spss/viewer/viewer-text");
601 register_ns (ctx, "xsi", "http://www.w3.org/2001/XMLSchema-instance");
606 dump_xml (int argc, char **argv, const char *member_name,
607 char *error_s, xmlDoc *doc)
613 printf ("<!-- %s -->\n", member_name);
614 xmlElemDump (stdout, NULL, xmlDocGetRootElement (doc));
619 bool any_results = false;
621 remove_default_xml_namespace (xmlDocGetRootElement (doc));
622 for (int i = 2; i < argc; i++)
624 xmlXPathContext *xpath_ctx = create_xpath_context (doc);
625 xmlXPathSetContextNode (xmlDocGetRootElement (doc),
627 xmlXPathObject *xpath_obj = xmlXPathEvalExpression(
628 CHAR_CAST (xmlChar *, argv[i]), xpath_ctx);
630 error (1, 0, _("%s: invalid XPath expression"), argv[i]);
632 const xmlNodeSet *nodes = xpath_obj->nodesetval;
633 if (nodes && nodes->nodeNr > 0)
637 printf ("<!-- %s -->\n", member_name);
640 for (size_t j = 0; j < nodes->nodeNr; j++)
642 xmlElemDump (stdout, doc, nodes->nodeTab[j]);
647 xmlXPathFreeObject (xpath_obj);
648 xmlXPathFreeContext (xpath_ctx);
657 printf ("<!-- %s -->\n", member_name);
658 msg (ME, "%s", error_s);
664 run_dump_legacy_table (int argc, char **argv)
666 struct spv_reader *spv;
667 char *err = spv_open (argv[1], &spv);
669 error (1, 0, "%s", err);
671 struct spv_item **items;
673 spv_select (spv, criteria, n_criteria, &items, &n_items);
674 for (size_t i = 0; i < n_items; i++)
675 if (spv_item_is_legacy_table (items[i]))
678 char *error_s = spv_item_get_legacy_table (items[i], &doc);
679 dump_xml (argc, argv, items[i]->xml_member, error_s, doc);
687 run_dump_structure (int argc, char **argv)
689 struct spv_reader *spv;
690 char *err = spv_open (argv[1], &spv);
692 error (1, 0, "%s", err);
694 struct spv_item **items;
696 spv_select (spv, criteria, n_criteria, &items, &n_items);
697 const char *last_structure_member = NULL;
698 for (size_t i = 0; i < n_items; i++)
699 if (!last_structure_member || strcmp (items[i]->structure_member,
700 last_structure_member))
702 last_structure_member = items[i]->structure_member;
705 char *error_s = spv_item_get_structure (items[i], &doc);
706 dump_xml (argc, argv, items[i]->structure_member, error_s, doc);
714 run_is_legacy (int argc UNUSED, char **argv)
716 struct spv_reader *spv;
717 char *err = spv_open (argv[1], &spv);
719 error (1, 0, "%s", err);
721 bool is_legacy = false;
723 struct spv_item **items;
725 spv_select (spv, criteria, n_criteria, &items, &n_items);
726 for (size_t i = 0; i < n_items; i++)
727 if (spv_item_is_legacy_table (items[i]))
736 exit (is_legacy ? EXIT_SUCCESS : EXIT_FAILURE);
742 int min_args, max_args;
743 void (*run) (int argc, char **argv);
746 static const struct command commands[] =
748 { "detect", 1, 1, run_detect },
749 { "dir", 1, 1, run_directory },
750 { "convert", 2, 2, run_convert },
751 { "get-table-look", 2, 2, run_get_table_look },
752 { "convert-table-look", 2, 2, run_convert_table_look },
754 /* Undocumented commands. */
755 { "dump", 1, 1, run_dump },
756 { "dump-light-table", 1, 1, run_dump_light_table },
757 { "dump-legacy-data", 1, 1, run_dump_legacy_data },
758 { "dump-legacy-table", 1, INT_MAX, run_dump_legacy_table },
759 { "dump-structure", 1, INT_MAX, run_dump_structure },
760 { "is-legacy", 1, 1, run_is_legacy },
762 static const int n_commands = sizeof commands / sizeof *commands;
764 static const struct command *
765 find_command (const char *name)
767 for (size_t i = 0; i < n_commands; i++)
769 const struct command *c = &commands[i];
770 if (!strcmp (name, c->name))
777 emit_msg (const struct msg *m, void *aux UNUSED)
779 if (m->severity == MSG_S_ERROR || m->severity == MSG_S_WARNING)
782 char *s = msg_to_string (m);
783 fprintf (stderr, "%s\n", s);
788 main (int argc, char **argv)
790 set_program_name (argv[0]);
791 msg_set_handler (emit_msg, NULL);
795 parse_options (argc, argv);
801 error (1, 0, _("missing command name (use --help for help)"));
803 const struct command *c = find_command (argv[0]);
805 error (1, 0, _("unknown command \"%s\" (use --help for help)"), argv[0]);
807 int n_args = argc - 1;
808 if (n_args < c->min_args || n_args > c->max_args)
810 if (c->min_args == c->max_args)
813 ngettext ("\"%s\" command takes exactly %d argument",
814 "\"%s\" command takes exactly %d arguments",
815 c->min_args), c->name, c->min_args);
817 else if (c->max_args == INT_MAX)
820 ngettext ("\"%s\" command requires at least %d argument",
821 "\"%s\" command requires at least %d arguments",
822 c->min_args), c->name, c->min_args);
827 _("\"%s\" command requires between %d and %d arguments"),
828 c->name, c->min_args, c->max_args);
834 pivot_table_look_unref (table_look);
837 return n_warnings ? EXIT_FAILURE : EXIT_SUCCESS;
840 static struct spv_criteria *
843 if (!n_criteria || new_criteria)
845 new_criteria = false;
846 if (n_criteria >= allocated_criteria)
847 criteria = x2nrealloc (criteria, &allocated_criteria,
849 criteria[n_criteria++] = (struct spv_criteria) SPV_CRITERIA_INITIALIZER;
852 return &criteria[n_criteria - 1];
856 parse_select (char *arg)
858 bool invert = arg[0] == '^';
861 unsigned classes = 0;
862 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
864 if (!strcmp (arg, "all"))
865 classes = SPV_ALL_CLASSES;
866 else if (!strcmp (arg, "help"))
868 puts (_("The following object classes are supported:"));
869 for (int class = 0; class < SPV_N_CLASSES; class++)
870 printf ("- %s\n", spv_item_class_to_string (class));
875 int class = spv_item_class_from_string (token);
876 if (class == SPV_N_CLASSES)
877 error (1, 0, _("%s: unknown object class (use --select=help "
879 classes |= 1u << class;
883 struct spv_criteria *c = get_criteria ();
884 c->classes = invert ? classes ^ SPV_ALL_CLASSES : classes;
887 static struct spv_criteria_match *
888 get_criteria_match (const char **arg)
890 struct spv_criteria *c = get_criteria ();
891 if ((*arg)[0] == '^')
901 parse_commands (const char *arg)
903 struct spv_criteria_match *cm = get_criteria_match (&arg);
904 string_array_parse (&cm->commands, ss_cstr (arg), ss_cstr (","));
908 parse_subtypes (const char *arg)
910 struct spv_criteria_match *cm = get_criteria_match (&arg);
911 string_array_parse (&cm->subtypes, ss_cstr (arg), ss_cstr (","));
915 parse_labels (const char *arg)
917 struct spv_criteria_match *cm = get_criteria_match (&arg);
918 string_array_parse (&cm->labels, ss_cstr (arg), ss_cstr (","));
922 parse_instances (char *arg)
924 struct spv_criteria *c = get_criteria ();
925 size_t allocated_instances = c->n_instances;
927 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
929 if (c->n_instances >= allocated_instances)
930 c->instances = x2nrealloc (c->instances, &allocated_instances,
931 sizeof *c->instances);
933 c->instances[c->n_instances++] = (!strcmp (token, "last") ? -1
939 parse_nth_commands (char *arg)
941 struct spv_criteria *c = get_criteria ();
942 size_t allocated_commands = c->n_commands;
944 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
946 if (c->n_commands >= allocated_commands)
947 c->commands = x2nrealloc (c->commands, &allocated_commands,
948 sizeof *c->commands);
950 c->commands[c->n_commands++] = atoi (token);
955 parse_members (const char *arg)
957 struct spv_criteria *cm = get_criteria ();
958 string_array_parse (&cm->members, ss_cstr (arg), ss_cstr (","));
962 parse_table_look (const char *arg)
964 pivot_table_look_unref (table_look);
966 char *error_s = spv_table_look_read (arg, &table_look);
968 error (1, 0, "%s", error_s);
972 parse_options (int argc, char *argv[])
978 OPT_MEMBER_NAMES = UCHAR_MAX + 1,
994 static const struct option long_options[] =
996 /* Input selection options. */
997 { "show-hidden", no_argument, NULL, OPT_SHOW_HIDDEN },
998 { "select", required_argument, NULL, OPT_SELECT },
999 { "commands", required_argument, NULL, OPT_COMMANDS },
1000 { "nth-commands", required_argument, NULL, OPT_NTH_COMMANDS },
1001 { "subtypes", required_argument, NULL, OPT_SUBTYPES },
1002 { "labels", required_argument, NULL, OPT_LABELS },
1003 { "instances", required_argument, NULL, OPT_INSTANCES },
1004 { "members", required_argument, NULL, OPT_MEMBERS },
1005 { "errors", no_argument, NULL, OPT_ERRORS },
1006 { "or", no_argument, NULL, OPT_OR },
1008 /* "dir" command options. */
1009 { "member-names", no_argument, NULL, OPT_MEMBER_NAMES },
1011 /* "convert" command options. */
1012 { "force", no_argument, NULL, 'f' },
1013 { "table-look", required_argument, NULL, OPT_TABLE_LOOK },
1015 /* "dump-light-table" command options. */
1016 { "sort", no_argument, NULL, OPT_SORT },
1017 { "raw", no_argument, NULL, OPT_RAW },
1019 { "help", no_argument, NULL, 'h' },
1020 { "help-developer", no_argument, NULL, OPT_HELP_DEVELOPER },
1021 { "version", no_argument, NULL, 'v' },
1023 { NULL, 0, NULL, 0 },
1028 c = getopt_long (argc, argv, "O:hvf", long_options, NULL);
1035 output_driver_parse_option (optarg, &output_options);
1038 case OPT_MEMBER_NAMES:
1039 show_member_names = true;
1042 case OPT_SHOW_HIDDEN:
1043 get_criteria ()->include_hidden = true;
1047 parse_select (optarg);
1051 parse_commands (optarg);
1054 case OPT_NTH_COMMANDS:
1055 parse_nth_commands (optarg);
1059 parse_subtypes (optarg);
1063 parse_labels (optarg);
1067 parse_instances (optarg);
1071 parse_members (optarg);
1075 get_criteria ()->error = true;
1079 new_criteria = true;
1090 case OPT_TABLE_LOOK:
1091 parse_table_look (optarg);
1099 version_etc (stdout, "pspp-output", PACKAGE_NAME, PACKAGE_VERSION,
1100 "Ben Pfaff", "John Darrington", NULL_SENTINEL);
1101 exit (EXIT_SUCCESS);
1105 exit (EXIT_SUCCESS);
1107 case OPT_HELP_DEVELOPER:
1109 exit (EXIT_SUCCESS);
1112 exit (EXIT_FAILURE);
1120 struct string s = DS_EMPTY_INITIALIZER;
1121 struct string_set formats = STRING_SET_INITIALIZER(formats);
1122 output_get_supported_formats (&formats);
1124 const struct string_set_node *node;
1125 STRING_SET_FOR_EACH (format, node, &formats)
1127 if (!ds_is_empty (&s))
1128 ds_put_byte (&s, ' ');
1129 ds_put_cstr (&s, format);
1131 string_set_destroy (&formats);
1134 %s, a utility for working with SPSS viewer (.spv) files.\n\
1135 Usage: %s [OPTION]... COMMAND ARG...\n\
1137 The following commands are available:\n\
1138 detect FILE Detect whether FILE is an SPV file.\n\
1139 dir FILE List tables and other items in FILE.\n\
1140 convert SOURCE DEST Convert .spv SOURCE to DEST.\n\
1141 get-table-look SOURCE DEST Copies first selected TableLook into DEST\n\
1142 convert-table-look SOURCE DEST Copies .tlo or .stt SOURCE into DEST\n\
1144 Input selection options for \"dir\" and \"convert\":\n\
1145 --select=CLASS... include only some kinds of objects\n\
1146 --select=help print known object classes\n\
1147 --commands=COMMAND... include only specified COMMANDs\n\
1148 --nth-commands=N... include only the Nth instance of selected commands\n\
1149 --subtypes=SUBTYPE... include only specified SUBTYPEs of output\n\
1150 --labels=LABEL... include only output objects with the given LABELs\n\
1151 --instances=INSTANCE... include only the given object INSTANCEs\n\
1152 --show-hidden include hidden output objects\n\
1153 --or separate two sets of selection options\n\
1155 \"convert\" by default infers the destination's format from its extension.\n\
1156 The known extensions are: %s\n\
1157 The following options override \"convert\" behavior:\n\
1158 -O format=FORMAT set destination format to FORMAT\n\
1159 -O OPTION=VALUE set output option\n\
1160 -f, --force keep output file even given errors\n\
1161 --table-look=FILE override tables' style with TableLook from FILE\n\
1163 --help display this help and exit\n\
1164 --help-developer display help for developer commands and exit\n\
1165 --version output version information and exit\n",
1166 program_name, program_name, ds_cstr (&s));
1171 developer_usage (void)
1174 The following developer commands are available:\n\
1175 dump FILE Dump pivot table structure\n\
1176 [--raw | --sort] dump-light-table FILE Dump light tables\n\
1177 [--raw] dump-legacy-data FILE Dump legacy table data\n\
1178 dump-legacy-table FILE [XPATH]... Dump legacy table XML\n\
1179 dump-structure FILE [XPATH]... Dump structure XML\n\
1180 is-legacy FILE Exit with status 0 if any legacy table selected\n\
1182 Additional input selection options:\n\
1183 --members=MEMBER... include only objects with these Zip member names\n\
1184 --errors include only objects that cannot be loaded\n\
1186 Additional options for \"dir\" command:\n\
1187 --member-names show Zip member names with objects\n\
1190 --raw print raw binary data instead of a parsed version\n\
1191 --sort sort borders and areas for shorter \"diff\" output\n");