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 if (raw && isatty (STDOUT_FILENO))
517 error (1, 0, "not writing binary data to tty");
519 struct spv_item **items;
521 spv_select (spv, criteria, n_criteria, &items, &n_items);
522 for (size_t i = 0; i < n_items; i++)
523 if (spv_item_is_legacy_table (items[i]))
525 struct spv_data data;
531 error = spv_item_get_raw_legacy_data (items[i], &data, &size);
534 fwrite (data, size, 1, stdout);
540 error = spv_item_get_legacy_data (items[i], &data);
543 printf ("%s:\n", items[i]->bin_member);
544 spv_data_dump (&data, stdout);
545 spv_data_uninit (&data);
552 msg (ME, "%s", error);
561 /* This is really bogus.
563 XPath doesn't have any notion of a default XML namespace, but all of the
564 elements in the documents we're interested in have a namespace. Thus, we'd
565 need to require the XPath expressions to have a namespace on every single
566 element: vis:sourceVariable, vis:graph, and so on. That's a pain. So,
567 instead, we remove the default namespace from everyplace it occurs. XPath
568 does support the null namespace, so this allows sourceVariable, graph,
571 See http://plasmasturm.org/log/259/ and
572 https://mail.gnome.org/archives/xml/2003-April/msg00144.html for more
575 remove_default_xml_namespace (xmlNode *node)
577 if (node->ns && !node->ns->prefix)
580 for (xmlNode *child = node->children; child; child = child->next)
581 remove_default_xml_namespace (child);
585 register_ns (xmlXPathContext *ctx, const char *prefix, const char *uri)
587 xmlXPathRegisterNs (ctx, CHAR_CAST (xmlChar *, prefix),
588 CHAR_CAST (xmlChar *, uri));
591 static xmlXPathContext *
592 create_xpath_context (xmlDoc *doc)
594 xmlXPathContext *ctx = xmlXPathNewContext (doc);
595 register_ns (ctx, "vgr", "http://xml.spss.com/spss/viewer/viewer-graph");
596 register_ns (ctx, "vizml", "http://xml.spss.com/visualization");
597 register_ns (ctx, "vmd", "http://xml.spss.com/spss/viewer/viewer-model");
598 register_ns (ctx, "vps", "http://xml.spss.com/spss/viewer/viewer-pagesetup");
599 register_ns (ctx, "vst", "http://xml.spss.com/spss/viewer/viewer-style");
600 register_ns (ctx, "vtb", "http://xml.spss.com/spss/viewer/viewer-table");
601 register_ns (ctx, "vtl", "http://xml.spss.com/spss/viewer/table-looks");
602 register_ns (ctx, "vtt", "http://xml.spss.com/spss/viewer/viewer-treemodel");
603 register_ns (ctx, "vtx", "http://xml.spss.com/spss/viewer/viewer-text");
604 register_ns (ctx, "xsi", "http://www.w3.org/2001/XMLSchema-instance");
609 dump_xml (int argc, char **argv, const char *member_name,
610 char *error_s, xmlDoc *doc)
616 printf ("<!-- %s -->\n", member_name);
617 xmlElemDump (stdout, NULL, xmlDocGetRootElement (doc));
622 bool any_results = false;
624 remove_default_xml_namespace (xmlDocGetRootElement (doc));
625 for (int i = 2; i < argc; i++)
627 xmlXPathContext *xpath_ctx = create_xpath_context (doc);
628 xmlXPathSetContextNode (xmlDocGetRootElement (doc),
630 xmlXPathObject *xpath_obj = xmlXPathEvalExpression(
631 CHAR_CAST (xmlChar *, argv[i]), xpath_ctx);
633 error (1, 0, _("%s: invalid XPath expression"), argv[i]);
635 const xmlNodeSet *nodes = xpath_obj->nodesetval;
636 if (nodes && nodes->nodeNr > 0)
640 printf ("<!-- %s -->\n", member_name);
643 for (size_t j = 0; j < nodes->nodeNr; j++)
645 xmlElemDump (stdout, doc, nodes->nodeTab[j]);
650 xmlXPathFreeObject (xpath_obj);
651 xmlXPathFreeContext (xpath_ctx);
660 printf ("<!-- %s -->\n", member_name);
661 msg (ME, "%s", error_s);
667 run_dump_legacy_table (int argc, char **argv)
669 struct spv_reader *spv;
670 char *err = spv_open (argv[1], &spv);
672 error (1, 0, "%s", err);
674 struct spv_item **items;
676 spv_select (spv, criteria, n_criteria, &items, &n_items);
677 for (size_t i = 0; i < n_items; i++)
678 if (spv_item_is_legacy_table (items[i]))
681 char *error_s = spv_item_get_legacy_table (items[i], &doc);
682 dump_xml (argc, argv, items[i]->xml_member, error_s, doc);
690 run_dump_structure (int argc, char **argv)
692 struct spv_reader *spv;
693 char *err = spv_open (argv[1], &spv);
695 error (1, 0, "%s", err);
697 struct spv_item **items;
699 spv_select (spv, criteria, n_criteria, &items, &n_items);
700 const char *last_structure_member = NULL;
701 for (size_t i = 0; i < n_items; i++)
702 if (!last_structure_member || strcmp (items[i]->structure_member,
703 last_structure_member))
705 last_structure_member = items[i]->structure_member;
708 char *error_s = spv_item_get_structure (items[i], &doc);
709 dump_xml (argc, argv, items[i]->structure_member, error_s, doc);
717 run_is_legacy (int argc UNUSED, char **argv)
719 struct spv_reader *spv;
720 char *err = spv_open (argv[1], &spv);
722 error (1, 0, "%s", err);
724 bool is_legacy = false;
726 struct spv_item **items;
728 spv_select (spv, criteria, n_criteria, &items, &n_items);
729 for (size_t i = 0; i < n_items; i++)
730 if (spv_item_is_legacy_table (items[i]))
739 exit (is_legacy ? EXIT_SUCCESS : EXIT_FAILURE);
745 int min_args, max_args;
746 void (*run) (int argc, char **argv);
749 static const struct command commands[] =
751 { "detect", 1, 1, run_detect },
752 { "dir", 1, 1, run_directory },
753 { "convert", 2, 2, run_convert },
754 { "get-table-look", 2, 2, run_get_table_look },
755 { "convert-table-look", 2, 2, run_convert_table_look },
757 /* Undocumented commands. */
758 { "dump", 1, 1, run_dump },
759 { "dump-light-table", 1, 1, run_dump_light_table },
760 { "dump-legacy-data", 1, 1, run_dump_legacy_data },
761 { "dump-legacy-table", 1, INT_MAX, run_dump_legacy_table },
762 { "dump-structure", 1, INT_MAX, run_dump_structure },
763 { "is-legacy", 1, 1, run_is_legacy },
765 static const int n_commands = sizeof commands / sizeof *commands;
767 static const struct command *
768 find_command (const char *name)
770 for (size_t i = 0; i < n_commands; i++)
772 const struct command *c = &commands[i];
773 if (!strcmp (name, c->name))
780 emit_msg (const struct msg *m, void *aux UNUSED)
782 if (m->severity == MSG_S_ERROR || m->severity == MSG_S_WARNING)
785 char *s = msg_to_string (m);
786 fprintf (stderr, "%s\n", s);
791 main (int argc, char **argv)
793 set_program_name (argv[0]);
794 msg_set_handler (emit_msg, NULL);
798 parse_options (argc, argv);
804 error (1, 0, _("missing command name (use --help for help)"));
806 const struct command *c = find_command (argv[0]);
808 error (1, 0, _("unknown command \"%s\" (use --help for help)"), argv[0]);
810 int n_args = argc - 1;
811 if (n_args < c->min_args || n_args > c->max_args)
813 if (c->min_args == c->max_args)
816 ngettext ("\"%s\" command takes exactly %d argument",
817 "\"%s\" command takes exactly %d arguments",
818 c->min_args), c->name, c->min_args);
820 else if (c->max_args == INT_MAX)
823 ngettext ("\"%s\" command requires at least %d argument",
824 "\"%s\" command requires at least %d arguments",
825 c->min_args), c->name, c->min_args);
830 _("\"%s\" command requires between %d and %d arguments"),
831 c->name, c->min_args, c->max_args);
837 pivot_table_look_unref (table_look);
840 return n_warnings ? EXIT_FAILURE : EXIT_SUCCESS;
843 static struct spv_criteria *
846 if (!n_criteria || new_criteria)
848 new_criteria = false;
849 if (n_criteria >= allocated_criteria)
850 criteria = x2nrealloc (criteria, &allocated_criteria,
852 criteria[n_criteria++] = (struct spv_criteria) SPV_CRITERIA_INITIALIZER;
855 return &criteria[n_criteria - 1];
859 parse_select (char *arg)
861 bool invert = arg[0] == '^';
864 unsigned classes = 0;
865 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
867 if (!strcmp (arg, "all"))
868 classes = SPV_ALL_CLASSES;
869 else if (!strcmp (arg, "help"))
871 puts (_("The following object classes are supported:"));
872 for (int class = 0; class < SPV_N_CLASSES; class++)
873 printf ("- %s\n", spv_item_class_to_string (class));
878 int class = spv_item_class_from_string (token);
879 if (class == SPV_N_CLASSES)
880 error (1, 0, _("%s: unknown object class (use --select=help "
882 classes |= 1u << class;
886 struct spv_criteria *c = get_criteria ();
887 c->classes = invert ? classes ^ SPV_ALL_CLASSES : classes;
890 static struct spv_criteria_match *
891 get_criteria_match (const char **arg)
893 struct spv_criteria *c = get_criteria ();
894 if ((*arg)[0] == '^')
904 parse_commands (const char *arg)
906 struct spv_criteria_match *cm = get_criteria_match (&arg);
907 string_array_parse (&cm->commands, ss_cstr (arg), ss_cstr (","));
911 parse_subtypes (const char *arg)
913 struct spv_criteria_match *cm = get_criteria_match (&arg);
914 string_array_parse (&cm->subtypes, ss_cstr (arg), ss_cstr (","));
918 parse_labels (const char *arg)
920 struct spv_criteria_match *cm = get_criteria_match (&arg);
921 string_array_parse (&cm->labels, ss_cstr (arg), ss_cstr (","));
925 parse_instances (char *arg)
927 struct spv_criteria *c = get_criteria ();
928 size_t allocated_instances = c->n_instances;
930 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
932 if (c->n_instances >= allocated_instances)
933 c->instances = x2nrealloc (c->instances, &allocated_instances,
934 sizeof *c->instances);
936 c->instances[c->n_instances++] = (!strcmp (token, "last") ? -1
942 parse_nth_commands (char *arg)
944 struct spv_criteria *c = get_criteria ();
945 size_t allocated_commands = c->n_commands;
947 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
949 if (c->n_commands >= allocated_commands)
950 c->commands = x2nrealloc (c->commands, &allocated_commands,
951 sizeof *c->commands);
953 c->commands[c->n_commands++] = atoi (token);
958 parse_members (const char *arg)
960 struct spv_criteria *cm = get_criteria ();
961 string_array_parse (&cm->members, ss_cstr (arg), ss_cstr (","));
965 parse_table_look (const char *arg)
967 pivot_table_look_unref (table_look);
969 char *error_s = spv_table_look_read (arg, &table_look);
971 error (1, 0, "%s", error_s);
975 parse_options (int argc, char *argv[])
981 OPT_MEMBER_NAMES = UCHAR_MAX + 1,
997 static const struct option long_options[] =
999 /* Input selection options. */
1000 { "show-hidden", no_argument, NULL, OPT_SHOW_HIDDEN },
1001 { "select", required_argument, NULL, OPT_SELECT },
1002 { "commands", required_argument, NULL, OPT_COMMANDS },
1003 { "nth-commands", required_argument, NULL, OPT_NTH_COMMANDS },
1004 { "subtypes", required_argument, NULL, OPT_SUBTYPES },
1005 { "labels", required_argument, NULL, OPT_LABELS },
1006 { "instances", required_argument, NULL, OPT_INSTANCES },
1007 { "members", required_argument, NULL, OPT_MEMBERS },
1008 { "errors", no_argument, NULL, OPT_ERRORS },
1009 { "or", no_argument, NULL, OPT_OR },
1011 /* "dir" command options. */
1012 { "member-names", no_argument, NULL, OPT_MEMBER_NAMES },
1014 /* "convert" command options. */
1015 { "force", no_argument, NULL, 'f' },
1016 { "table-look", required_argument, NULL, OPT_TABLE_LOOK },
1018 /* "dump-light-table" command options. */
1019 { "sort", no_argument, NULL, OPT_SORT },
1020 { "raw", no_argument, NULL, OPT_RAW },
1022 { "help", no_argument, NULL, 'h' },
1023 { "help-developer", no_argument, NULL, OPT_HELP_DEVELOPER },
1024 { "version", no_argument, NULL, 'v' },
1026 { NULL, 0, NULL, 0 },
1031 c = getopt_long (argc, argv, "O:hvf", long_options, NULL);
1038 output_driver_parse_option (optarg, &output_options);
1041 case OPT_MEMBER_NAMES:
1042 show_member_names = true;
1045 case OPT_SHOW_HIDDEN:
1046 get_criteria ()->include_hidden = true;
1050 parse_select (optarg);
1054 parse_commands (optarg);
1057 case OPT_NTH_COMMANDS:
1058 parse_nth_commands (optarg);
1062 parse_subtypes (optarg);
1066 parse_labels (optarg);
1070 parse_instances (optarg);
1074 parse_members (optarg);
1078 get_criteria ()->error = true;
1082 new_criteria = true;
1093 case OPT_TABLE_LOOK:
1094 parse_table_look (optarg);
1102 version_etc (stdout, "pspp-output", PACKAGE_NAME, PACKAGE_VERSION,
1103 "Ben Pfaff", "John Darrington", NULL_SENTINEL);
1104 exit (EXIT_SUCCESS);
1108 exit (EXIT_SUCCESS);
1110 case OPT_HELP_DEVELOPER:
1112 exit (EXIT_SUCCESS);
1115 exit (EXIT_FAILURE);
1123 struct string s = DS_EMPTY_INITIALIZER;
1124 struct string_set formats = STRING_SET_INITIALIZER(formats);
1125 output_get_supported_formats (&formats);
1127 const struct string_set_node *node;
1128 STRING_SET_FOR_EACH (format, node, &formats)
1130 if (!ds_is_empty (&s))
1131 ds_put_byte (&s, ' ');
1132 ds_put_cstr (&s, format);
1134 string_set_destroy (&formats);
1137 %s, a utility for working with SPSS viewer (.spv) files.\n\
1138 Usage: %s [OPTION]... COMMAND ARG...\n\
1140 The following commands are available:\n\
1141 detect FILE Detect whether FILE is an SPV file.\n\
1142 dir FILE List tables and other items in FILE.\n\
1143 convert SOURCE DEST Convert .spv SOURCE to DEST.\n\
1144 get-table-look SOURCE DEST Copies first selected TableLook into DEST\n\
1145 convert-table-look SOURCE DEST Copies .tlo or .stt SOURCE into DEST\n\
1147 Input selection options for \"dir\" and \"convert\":\n\
1148 --select=CLASS... include only some kinds of objects\n\
1149 --select=help print known object classes\n\
1150 --commands=COMMAND... include only specified COMMANDs\n\
1151 --nth-commands=N... include only the Nth instance of selected commands\n\
1152 --subtypes=SUBTYPE... include only specified SUBTYPEs of output\n\
1153 --labels=LABEL... include only output objects with the given LABELs\n\
1154 --instances=INSTANCE... include only the given object INSTANCEs\n\
1155 --show-hidden include hidden output objects\n\
1156 --or separate two sets of selection options\n\
1158 \"convert\" by default infers the destination's format from its extension.\n\
1159 The known extensions are: %s\n\
1160 The following options override \"convert\" behavior:\n\
1161 -O format=FORMAT set destination format to FORMAT\n\
1162 -O OPTION=VALUE set output option\n\
1163 -f, --force keep output file even given errors\n\
1164 --table-look=FILE override tables' style with TableLook from FILE\n\
1166 --help display this help and exit\n\
1167 --help-developer display help for developer commands and exit\n\
1168 --version output version information and exit\n",
1169 program_name, program_name, ds_cstr (&s));
1174 developer_usage (void)
1177 The following developer commands are available:\n\
1178 dump FILE Dump pivot table structure\n\
1179 [--raw | --sort] dump-light-table FILE Dump light tables\n\
1180 [--raw] dump-legacy-data FILE Dump legacy table data\n\
1181 dump-legacy-table FILE [XPATH]... Dump legacy table XML\n\
1182 dump-structure FILE [XPATH]... Dump structure XML\n\
1183 is-legacy FILE Exit with status 0 if any legacy table selected\n\
1185 Additional input selection options:\n\
1186 --members=MEMBER... include only objects with these Zip member names\n\
1187 --errors include only objects that cannot be loaded\n\
1189 Additional options for \"dir\" command:\n\
1190 --member-names show Zip member names with objects\n\
1193 --raw print raw binary data instead of a parsed version\n\
1194 --sort sort borders and areas for shorter \"diff\" output\n");