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/>. */
24 #include "data/file-handle-def.h"
25 #include "data/settings.h"
26 #include "libpspp/i18n.h"
27 #include "libpspp/message.h"
28 #include "libpspp/string-map.h"
29 #include "libpspp/string-set.h"
30 #include "output/driver.h"
31 #include "output/group-item.h"
32 #include "output/page-setup-item.h"
33 #include "output/pivot-table.h"
34 #include "output/spv/light-binary-parser.h"
35 #include "output/spv/spv-legacy-data.h"
36 #include "output/spv/spv-output.h"
37 #include "output/spv/spv-select.h"
38 #include "output/spv/spv-table-look.h"
39 #include "output/spv/spv.h"
40 #include "output/table-item.h"
41 #include "output/text-item.h"
43 #include "gl/c-ctype.h"
45 #include "gl/progname.h"
46 #include "gl/version-etc.h"
47 #include "gl/xalloc.h"
49 #include <libxml/tree.h>
50 #include <libxml/xpath.h>
51 #include <libxml/xpathInternals.h>
54 #define _(msgid) gettext (msgid)
56 /* -O key=value: Output driver options. */
57 static struct string_map output_options
58 = STRING_MAP_INITIALIZER (output_options);
60 /* --member-name: Include .zip member name in "dir" output. */
61 static bool show_member_names;
63 /* --show-hidden, --select, --commands, ...: Selection criteria. */
64 static struct spv_criteria *criteria;
65 static size_t n_criteria, allocated_criteria;
67 /* --or: Add new element to 'criteria' array. */
68 static bool new_criteria;
70 /* --sort: Sort members under dump-light-table, to make comparisons easier. */
73 /* --raw: Dump raw binary data in dump-light-table. */
76 /* -f, --force: Keep output file even on error. */
79 /* --table-look: TableLook to replace table style for conversion. */
80 static struct pivot_table_look *table_look;
82 /* --set-label: New object label. */
83 static char *set_label;
85 /* Number of warnings issued. */
86 static size_t n_warnings;
88 static void 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 ? xasprintf (_("%s and %s:"), x, b)
100 : xasprintf ("%s:", x ? x : b));
101 text_item_submit (text_item_create_nocopy (TEXT_ITEM_TITLE, s));
104 switch (spv_item_get_type (item))
106 case SPV_ITEM_HEADING:
110 spv_text_submit (item);
114 pivot_table_submit (pivot_table_ref (spv_item_get_table (item)));
123 case SPV_ITEM_OBJECT:
135 print_item_directory (const struct spv_item *item)
137 for (int i = 1; i < spv_item_get_level (item); i++)
140 enum spv_item_type type = spv_item_get_type (item);
141 printf ("- %s", spv_item_type_to_string (type));
143 const char *label = spv_item_get_label (item);
145 printf (" \"%s\"", label);
147 if (type == SPV_ITEM_TABLE)
149 const struct pivot_table *table = spv_item_get_table (item);
150 char *title = pivot_value_to_string (table->title,
151 SETTINGS_VALUE_SHOW_DEFAULT,
152 SETTINGS_VALUE_SHOW_DEFAULT);
153 if (!label || strcmp (title, label))
154 printf (" title \"%s\"", title);
158 const char *command_id = spv_item_get_command_id (item);
160 printf (" command \"%s\"", command_id);
162 const char *subtype = spv_item_get_subtype (item);
163 if (subtype && (!label || strcmp (label, subtype)))
164 printf (" subtype \"%s\"", subtype);
166 if (!spv_item_is_visible (item))
167 printf (" (hidden)");
168 if (show_member_names && (item->xml_member || item->bin_member))
170 if (item->xml_member && item->bin_member)
171 printf (" in %s and %s", item->xml_member, item->bin_member);
172 else if (item->xml_member)
173 printf (" in %s", item->xml_member);
174 else if (item->bin_member)
175 printf (" in %s", item->bin_member);
181 run_detect (int argc UNUSED, char **argv)
183 char *err = spv_detect (argv[1]);
185 error (1, 0, "%s", err);
189 run_directory (int argc UNUSED, char **argv)
191 struct spv_reader *spv;
192 char *err = spv_open (argv[1], &spv);
194 error (1, 0, "%s", err);
196 struct spv_item **items;
198 spv_select (spv, criteria, n_criteria, &items, &n_items);
199 for (size_t i = 0; i < n_items; i++)
200 print_item_directory (items[i]);
208 const struct spv_item **nodes;
212 const struct spv_item *stub[N_STUB];
216 swap_nodes (const struct spv_item **a, const struct spv_item **b)
218 const struct spv_item *tmp = *a;
224 get_path (const struct spv_item *item, struct item_path *path)
226 size_t allocated = 10;
227 path->nodes = path->stub;
232 if (path->n >= allocated)
234 if (path->nodes == path->stub)
235 path->nodes = xmemdup (path->stub, sizeof path->stub);
236 path->nodes = x2nrealloc (path->nodes, &allocated,
237 sizeof *path->nodes);
239 path->nodes[path->n++] = item;
243 for (size_t i = 0; i < path->n / 2; i++)
244 swap_nodes (&path->nodes[i], &path->nodes[path->n - i - 1]);
248 free_path (struct item_path *path)
250 if (path && path->nodes != path->stub)
255 dump_heading_transition (const struct spv_item *old,
256 const struct spv_item *new)
261 struct item_path old_path, new_path;
262 get_path (old, &old_path);
263 get_path (new, &new_path);
266 for (; common < old_path.n && common < new_path.n; common++)
267 if (old_path.nodes[common] != new_path.nodes[common])
270 for (size_t i = common; i < old_path.n; i++)
271 group_close_item_submit (group_close_item_create ());
272 for (size_t i = common; i < new_path.n; i++)
273 group_open_item_submit (group_open_item_create (
274 new_path.nodes[i]->command_id));
276 free_path (&old_path);
277 free_path (&new_path);
281 run_convert (int argc UNUSED, char **argv)
283 struct spv_reader *spv;
284 char *err = spv_open (argv[1], &spv);
286 error (1, 0, "%s", err);
289 spv_item_set_table_look (spv_get_root (spv), table_look);
291 output_engine_push ();
292 output_set_filename (argv[1]);
293 string_map_replace (&output_options, "output-file", argv[2]);
294 struct output_driver *driver = output_driver_create (&output_options);
297 output_driver_register (driver);
299 const struct page_setup *ps = spv_get_page_setup (spv);
301 page_setup_item_submit (page_setup_item_create (ps));
303 struct spv_item **items;
305 spv_select (spv, criteria, n_criteria, &items, &n_items);
306 struct spv_item *prev_heading = spv_get_root (spv);
307 for (size_t i = 0; i < n_items; i++)
309 struct spv_item *heading
310 = items[i]->type == SPV_ITEM_HEADING ? items[i] : items[i]->parent;
311 dump_heading_transition (prev_heading, heading);
313 if (set_label && spv_item_is_table (items[i]))
315 printf ("set label to %s\n", set_label);
316 free (items[i]->label);
317 items[i]->label = xstrdup (set_label);
320 dump_item (items[i]);
321 prev_heading = heading;
323 dump_heading_transition (prev_heading, spv_get_root (spv));
328 output_engine_pop ();
331 if (n_warnings && !force)
333 /* XXX There could be other files to unlink, e.g. the ascii driver can
334 produce additional files with the charts. */
339 static const struct pivot_table *
340 get_first_table (const struct spv_reader *spv)
342 struct spv_item **items;
344 spv_select (spv, criteria, n_criteria, &items, &n_items);
346 for (size_t i = 0; i < n_items; i++)
347 if (spv_item_is_table (items[i]))
350 return spv_item_get_table (items[i]);
358 run_get_table_look (int argc UNUSED, char **argv)
360 struct spv_reader *spv;
361 char *err = spv_open (argv[1], &spv);
363 error (1, 0, "%s", err);
365 const struct pivot_table *table = get_first_table (spv);
367 error (1, 0, "%s: no tables found", argv[1]);
369 err = spv_table_look_write (argv[2], pivot_table_get_look (table));
371 error (1, 0, "%s", err);
377 run_convert_table_look (int argc UNUSED, char **argv)
379 struct pivot_table_look *look;
380 char *err = spv_table_look_read (argv[1], &look);
382 error (1, 0, "%s", err);
384 err = spv_table_look_write (argv[2], look);
386 error (1, 0, "%s", err);
388 pivot_table_look_unref (look);
393 run_dump (int argc UNUSED, char **argv)
395 struct spv_reader *spv;
396 char *err = spv_open (argv[1], &spv);
398 error (1, 0, "%s", err);
400 struct spv_item **items;
402 spv_select (spv, criteria, n_criteria, &items, &n_items);
403 for (size_t i = 0; i < n_items; i++)
404 if (items[i]->type == SPV_ITEM_TABLE)
406 pivot_table_dump (spv_item_get_table (items[i]), 0);
415 compare_borders (const void *a_, const void *b_)
417 const struct spvlb_border *const *ap = a_;
418 const struct spvlb_border *const *bp = b_;
419 uint32_t a = (*ap)->border_type;
420 uint32_t b = (*bp)->border_type;
422 return a < b ? -1 : a > b;
426 compare_cells (const void *a_, const void *b_)
428 const struct spvlb_cell *const *ap = a_;
429 const struct spvlb_cell *const *bp = b_;
430 uint64_t a = (*ap)->index;
431 uint64_t b = (*bp)->index;
433 return a < b ? -1 : a > b;
437 run_dump_light_table (int argc UNUSED, char **argv)
439 if (raw && isatty (STDOUT_FILENO))
440 error (1, 0, "not writing binary data to tty");
442 struct spv_reader *spv;
443 char *err = spv_open (argv[1], &spv);
445 error (1, 0, "%s", err);
447 struct spv_item **items;
449 spv_select (spv, criteria, n_criteria, &items, &n_items);
450 for (size_t i = 0; i < n_items; i++)
452 if (!spv_item_is_light_table (items[i]))
460 error = spv_item_get_raw_light_table (items[i], &data, &size);
463 fwrite (data, size, 1, stdout);
469 struct spvlb_table *table;
470 error = spv_item_get_light_table (items[i], &table);
475 qsort (table->borders->borders, table->borders->n_borders,
476 sizeof *table->borders->borders, compare_borders);
477 qsort (table->cells->cells, table->cells->n_cells,
478 sizeof *table->cells->cells, compare_cells);
480 spvlb_print_table (items[i]->bin_member, 0, table);
481 spvlb_free_table (table);
486 msg (ME, "%s", error);
497 run_dump_legacy_data (int argc UNUSED, char **argv)
499 struct spv_reader *spv;
500 char *err = spv_open (argv[1], &spv);
502 error (1, 0, "%s", err);
504 struct spv_item **items;
506 spv_select (spv, criteria, n_criteria, &items, &n_items);
507 for (size_t i = 0; i < n_items; i++)
508 if (spv_item_is_legacy_table (items[i]))
510 struct spv_data data;
516 error = spv_item_get_raw_legacy_data (items[i], &data, &size);
519 fwrite (data, size, 1, stdout);
525 error = spv_item_get_legacy_data (items[i], &data);
528 printf ("%s:\n", items[i]->bin_member);
529 spv_data_dump (&data, stdout);
530 spv_data_uninit (&data);
537 msg (ME, "%s", error);
546 /* This is really bogus.
548 XPath doesn't have any notion of a default XML namespace, but all of the
549 elements in the documents we're interested in have a namespace. Thus, we'd
550 need to require the XPath expressions to have a namespace on every single
551 element: vis:sourceVariable, vis:graph, and so on. That's a pain. So,
552 instead, we remove the default namespace from everyplace it occurs. XPath
553 does support the null namespace, so this allows sourceVariable, graph,
556 See http://plasmasturm.org/log/259/ and
557 https://mail.gnome.org/archives/xml/2003-April/msg00144.html for more
560 remove_default_xml_namespace (xmlNode *node)
562 if (node->ns && !node->ns->prefix)
565 for (xmlNode *child = node->children; child; child = child->next)
566 remove_default_xml_namespace (child);
570 register_ns (xmlXPathContext *ctx, const char *prefix, const char *uri)
572 xmlXPathRegisterNs (ctx, CHAR_CAST (xmlChar *, prefix),
573 CHAR_CAST (xmlChar *, uri));
576 static xmlXPathContext *
577 create_xpath_context (xmlDoc *doc)
579 xmlXPathContext *ctx = xmlXPathNewContext (doc);
580 register_ns (ctx, "vgr", "http://xml.spss.com/spss/viewer/viewer-graph");
581 register_ns (ctx, "vizml", "http://xml.spss.com/visualization");
582 register_ns (ctx, "vmd", "http://xml.spss.com/spss/viewer/viewer-model");
583 register_ns (ctx, "vps", "http://xml.spss.com/spss/viewer/viewer-pagesetup");
584 register_ns (ctx, "vst", "http://xml.spss.com/spss/viewer/viewer-style");
585 register_ns (ctx, "vtb", "http://xml.spss.com/spss/viewer/viewer-table");
586 register_ns (ctx, "vtl", "http://xml.spss.com/spss/viewer/table-looks");
587 register_ns (ctx, "vtt", "http://xml.spss.com/spss/viewer/viewer-treemodel");
588 register_ns (ctx, "vtx", "http://xml.spss.com/spss/viewer/viewer-text");
589 register_ns (ctx, "xsi", "http://www.w3.org/2001/XMLSchema-instance");
594 dump_xml (int argc, char **argv, const char *member_name,
595 char *error_s, xmlDoc *doc)
601 printf ("<!-- %s -->\n", member_name);
602 xmlElemDump (stdout, NULL, xmlDocGetRootElement (doc));
607 bool any_results = false;
609 remove_default_xml_namespace (xmlDocGetRootElement (doc));
610 for (int i = 2; i < argc; i++)
612 xmlXPathContext *xpath_ctx = create_xpath_context (doc);
613 xmlXPathSetContextNode (xmlDocGetRootElement (doc),
615 xmlXPathObject *xpath_obj = xmlXPathEvalExpression(
616 CHAR_CAST (xmlChar *, argv[i]), xpath_ctx);
618 error (1, 0, _("%s: invalid XPath expression"), argv[i]);
620 const xmlNodeSet *nodes = xpath_obj->nodesetval;
621 if (nodes && nodes->nodeNr > 0)
625 printf ("<!-- %s -->\n", member_name);
628 for (size_t j = 0; j < nodes->nodeNr; j++)
630 xmlElemDump (stdout, doc, nodes->nodeTab[j]);
635 xmlXPathFreeObject (xpath_obj);
636 xmlXPathFreeContext (xpath_ctx);
645 printf ("<!-- %s -->\n", member_name);
646 msg (ME, "%s", error_s);
652 run_dump_legacy_table (int argc, char **argv)
654 struct spv_reader *spv;
655 char *err = spv_open (argv[1], &spv);
657 error (1, 0, "%s", err);
659 struct spv_item **items;
661 spv_select (spv, criteria, n_criteria, &items, &n_items);
662 for (size_t i = 0; i < n_items; i++)
663 if (spv_item_is_legacy_table (items[i]))
666 char *error_s = spv_item_get_legacy_table (items[i], &doc);
667 dump_xml (argc, argv, items[i]->xml_member, error_s, doc);
675 run_dump_structure (int argc, char **argv)
677 struct spv_reader *spv;
678 char *err = spv_open (argv[1], &spv);
680 error (1, 0, "%s", err);
682 struct spv_item **items;
684 spv_select (spv, criteria, n_criteria, &items, &n_items);
685 const char *last_structure_member = NULL;
686 for (size_t i = 0; i < n_items; i++)
687 if (!last_structure_member || strcmp (items[i]->structure_member,
688 last_structure_member))
690 last_structure_member = items[i]->structure_member;
693 char *error_s = spv_item_get_structure (items[i], &doc);
694 dump_xml (argc, argv, items[i]->structure_member, error_s, doc);
702 run_is_legacy (int argc UNUSED, char **argv)
704 struct spv_reader *spv;
705 char *err = spv_open (argv[1], &spv);
707 error (1, 0, "%s", err);
709 bool is_legacy = false;
711 struct spv_item **items;
713 spv_select (spv, criteria, n_criteria, &items, &n_items);
714 for (size_t i = 0; i < n_items; i++)
715 if (spv_item_is_legacy_table (items[i]))
724 exit (is_legacy ? EXIT_SUCCESS : EXIT_FAILURE);
730 int min_args, max_args;
731 void (*run) (int argc, char **argv);
734 static const struct command commands[] =
736 { "detect", 1, 1, run_detect },
737 { "dir", 1, 1, run_directory },
738 { "convert", 2, 2, run_convert },
739 { "get-table-look", 2, 2, run_get_table_look },
740 { "convert-table-look", 2, 2, run_convert_table_look },
742 /* Undocumented commands. */
743 { "dump", 1, 1, run_dump },
744 { "dump-light-table", 1, 1, run_dump_light_table },
745 { "dump-legacy-data", 1, 1, run_dump_legacy_data },
746 { "dump-legacy-table", 1, INT_MAX, run_dump_legacy_table },
747 { "dump-structure", 1, INT_MAX, run_dump_structure },
748 { "is-legacy", 1, 1, run_is_legacy },
750 static const int n_commands = sizeof commands / sizeof *commands;
752 static const struct command *
753 find_command (const char *name)
755 for (size_t i = 0; i < n_commands; i++)
757 const struct command *c = &commands[i];
758 if (!strcmp (name, c->name))
765 emit_msg (const struct msg *m, void *aux UNUSED)
767 if (m->severity == MSG_S_ERROR || m->severity == MSG_S_WARNING)
770 char *s = msg_to_string (m);
771 fprintf (stderr, "%s\n", s);
776 main (int argc, char **argv)
778 set_program_name (argv[0]);
779 msg_set_handler (emit_msg, NULL);
783 parse_options (argc, argv);
789 error (1, 0, _("missing command name (use --help for help)"));
791 const struct command *c = find_command (argv[0]);
793 error (1, 0, _("unknown command \"%s\" (use --help for help)"), argv[0]);
795 int n_args = argc - 1;
796 if (n_args < c->min_args || n_args > c->max_args)
798 if (c->min_args == c->max_args)
801 ngettext ("\"%s\" command takes exactly %d argument",
802 "\"%s\" command takes exactly %d arguments",
803 c->min_args), c->name, c->min_args);
805 else if (c->max_args == INT_MAX)
808 ngettext ("\"%s\" command requires at least %d argument",
809 "\"%s\" command requires at least %d arguments",
810 c->min_args), c->name, c->min_args);
815 _("\"%s\" command requires between %d and %d arguments"),
816 c->name, c->min_args, c->max_args);
822 pivot_table_look_unref (table_look);
825 return n_warnings ? EXIT_FAILURE : EXIT_SUCCESS;
828 static struct spv_criteria *
831 if (!n_criteria || new_criteria)
833 new_criteria = false;
834 if (n_criteria >= allocated_criteria)
835 criteria = x2nrealloc (criteria, &allocated_criteria,
837 criteria[n_criteria++] = (struct spv_criteria) SPV_CRITERIA_INITIALIZER;
840 return &criteria[n_criteria - 1];
844 parse_select (char *arg)
846 bool invert = arg[0] == '^';
849 unsigned classes = 0;
850 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
852 if (!strcmp (arg, "all"))
853 classes = SPV_ALL_CLASSES;
854 else if (!strcmp (arg, "help"))
856 puts (_("The following object classes are supported:"));
857 for (int class = 0; class < SPV_N_CLASSES; class++)
858 printf ("- %s\n", spv_item_class_to_string (class));
863 int class = spv_item_class_from_string (token);
864 if (class == SPV_N_CLASSES)
865 error (1, 0, _("%s: unknown object class (use --select=help "
867 classes |= 1u << class;
871 struct spv_criteria *c = get_criteria ();
872 c->classes = invert ? classes ^ SPV_ALL_CLASSES : classes;
875 static struct spv_criteria_match *
876 get_criteria_match (const char **arg)
878 struct spv_criteria *c = get_criteria ();
879 if ((*arg)[0] == '^')
889 parse_commands (const char *arg)
891 struct spv_criteria_match *cm = get_criteria_match (&arg);
892 string_array_parse (&cm->commands, ss_cstr (arg), ss_cstr (","));
896 parse_subtypes (const char *arg)
898 struct spv_criteria_match *cm = get_criteria_match (&arg);
899 string_array_parse (&cm->subtypes, ss_cstr (arg), ss_cstr (","));
903 parse_labels (const char *arg)
905 struct spv_criteria_match *cm = get_criteria_match (&arg);
906 string_array_parse (&cm->labels, ss_cstr (arg), ss_cstr (","));
910 parse_instances (char *arg)
912 struct spv_criteria *c = get_criteria ();
913 size_t allocated_instances = c->n_instances;
915 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
917 if (c->n_instances >= allocated_instances)
918 c->instances = x2nrealloc (c->instances, &allocated_instances,
919 sizeof *c->instances);
921 c->instances[c->n_instances++] = (!strcmp (token, "last") ? -1
927 parse_nth_commands (char *arg)
929 struct spv_criteria *c = get_criteria ();
930 size_t allocated_commands = c->n_commands;
932 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
934 if (c->n_commands >= allocated_commands)
935 c->commands = x2nrealloc (c->commands, &allocated_commands,
936 sizeof *c->commands);
938 c->commands[c->n_commands++] = atoi (token);
943 parse_members (const char *arg)
945 struct spv_criteria *cm = get_criteria ();
946 string_array_parse (&cm->members, ss_cstr (arg), ss_cstr (","));
950 parse_table_look (const char *arg)
952 pivot_table_look_unref (table_look);
954 char *error_s = spv_table_look_read (arg, &table_look);
956 error (1, 0, "%s", error_s);
960 parse_options (int argc, char *argv[])
966 OPT_MEMBER_NAMES = UCHAR_MAX + 1,
982 static const struct option long_options[] =
984 /* Input selection options. */
985 { "show-hidden", no_argument, NULL, OPT_SHOW_HIDDEN },
986 { "select", required_argument, NULL, OPT_SELECT },
987 { "commands", required_argument, NULL, OPT_COMMANDS },
988 { "nth-commands", required_argument, NULL, OPT_NTH_COMMANDS },
989 { "subtypes", required_argument, NULL, OPT_SUBTYPES },
990 { "labels", required_argument, NULL, OPT_LABELS },
991 { "instances", required_argument, NULL, OPT_INSTANCES },
992 { "members", required_argument, NULL, OPT_MEMBERS },
993 { "errors", no_argument, NULL, OPT_ERRORS },
994 { "or", no_argument, NULL, OPT_OR },
996 /* "dir" command options. */
997 { "member-names", no_argument, NULL, OPT_MEMBER_NAMES },
999 /* "convert" command options. */
1000 { "force", no_argument, NULL, 'f' },
1001 { "table-look", required_argument, NULL, OPT_TABLE_LOOK },
1002 { "set-label", required_argument, NULL, OPT_SET_LABEL },
1004 /* "dump-light-table" command options. */
1005 { "sort", no_argument, NULL, OPT_SORT },
1006 { "raw", no_argument, NULL, OPT_RAW },
1008 { "help", no_argument, NULL, 'h' },
1009 { "version", no_argument, NULL, 'v' },
1011 { NULL, 0, NULL, 0 },
1016 c = getopt_long (argc, argv, "O:hvf", long_options, NULL);
1023 output_driver_parse_option (optarg, &output_options);
1026 case OPT_MEMBER_NAMES:
1027 show_member_names = true;
1030 case OPT_SHOW_HIDDEN:
1031 get_criteria ()->include_hidden = true;
1035 parse_select (optarg);
1039 parse_commands (optarg);
1042 case OPT_NTH_COMMANDS:
1043 parse_nth_commands (optarg);
1047 parse_subtypes (optarg);
1051 parse_labels (optarg);
1055 parse_instances (optarg);
1059 parse_members (optarg);
1063 get_criteria ()->error = true;
1067 new_criteria = true;
1078 case OPT_TABLE_LOOK:
1079 parse_table_look (optarg);
1091 version_etc (stdout, "pspp-output", PACKAGE_NAME, PACKAGE_VERSION,
1092 "Ben Pfaff", "John Darrington", NULL_SENTINEL);
1093 exit (EXIT_SUCCESS);
1097 exit (EXIT_SUCCESS);
1100 exit (EXIT_FAILURE);
1108 struct string s = DS_EMPTY_INITIALIZER;
1109 struct string_set formats = STRING_SET_INITIALIZER(formats);
1110 output_get_supported_formats (&formats);
1112 const struct string_set_node *node;
1113 STRING_SET_FOR_EACH (format, node, &formats)
1115 if (!ds_is_empty (&s))
1116 ds_put_byte (&s, ' ');
1117 ds_put_cstr (&s, format);
1119 string_set_destroy (&formats);
1122 %s, a utility for working with SPSS viewer (.spv) files.\n\
1123 Usage: %s [OPTION]... COMMAND ARG...\n\
1125 The following commands are available:\n\
1126 detect FILE Detect whether FILE is an SPV file.\n\
1127 dir FILE List tables and other items in FILE.\n\
1128 convert SOURCE DEST Convert .spv SOURCE to DEST.\n\
1129 get-table-look SOURCE DEST Copies first selected TableLook into DEST\n\
1130 convert-table-look SOURCE DEST Copies .tlo or .stt SOURCE into DEST\n\
1132 Input selection options for \"dir\" and \"convert\":\n\
1133 --select=CLASS... include only some kinds of objects\n\
1134 --select=help print known object classes\n\
1135 --commands=COMMAND... include only specified COMMANDs\n\
1136 --nth-commands=N... include only the Nth instance of selected commands\n\
1137 --subtypes=SUBTYPE... include only specified SUBTYPEs of output\n\
1138 --labels=LABEL... include only output objects with the given LABELs\n\
1139 --instances=INSTANCE... include only the given object INSTANCEs\n\
1140 --show-hidden include hidden output objects\n\
1141 --or separate two sets of selection options\n\
1143 \"convert\" by default infers the destination's format from its extension.\n\
1144 The known extensions are: %s\n\
1145 The following options override \"convert\" behavior:\n\
1146 -O format=FORMAT set destination format to FORMAT\n\
1147 -O OPTION=VALUE set output option\n\
1148 -f, --force keep output file even given errors\n\
1149 --table-look=FILE override tables' style with TableLook from FILE\n\
1151 --help display this help and exit\n\
1152 --version output version information and exit\n",
1153 program_name, program_name, ds_cstr (&s));