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 /* Number of warnings issued. */
83 static size_t n_warnings;
85 static void usage (void);
86 static void parse_options (int argc, char **argv);
89 dump_item (const struct spv_item *item)
91 if (show_member_names && (item->xml_member || item->bin_member))
93 const char *x = item->xml_member;
94 const char *b = item->bin_member;
96 /* The strings below are not marked for translation because they are only
97 useful to developers. */
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,
102 xstrdup ("Member Names")));
105 switch (spv_item_get_type (item))
107 case SPV_ITEM_HEADING:
111 spv_text_submit (item);
115 pivot_table_submit (pivot_table_ref (spv_item_get_table (item)));
124 case SPV_ITEM_OBJECT:
136 print_item_directory (const struct spv_item *item)
138 for (int i = 1; i < spv_item_get_level (item); i++)
141 enum spv_item_type type = spv_item_get_type (item);
142 printf ("- %s", spv_item_type_to_string (type));
144 const char *label = spv_item_get_label (item);
146 printf (" \"%s\"", label);
148 if (type == SPV_ITEM_TABLE)
150 const struct pivot_table *table = spv_item_get_table (item);
151 char *title = pivot_value_to_string (table->title,
152 SETTINGS_VALUE_SHOW_DEFAULT,
153 SETTINGS_VALUE_SHOW_DEFAULT);
154 if (!label || strcmp (title, label))
155 printf (" title \"%s\"", title);
159 const char *command_id = spv_item_get_command_id (item);
161 printf (" command \"%s\"", command_id);
163 const char *subtype = spv_item_get_subtype (item);
164 if (subtype && (!label || strcmp (label, subtype)))
165 printf (" subtype \"%s\"", subtype);
167 if (!spv_item_is_visible (item))
168 printf (" (hidden)");
169 if (show_member_names && (item->xml_member || item->bin_member))
171 if (item->xml_member && item->bin_member)
172 printf (" in %s and %s", item->xml_member, item->bin_member);
173 else if (item->xml_member)
174 printf (" in %s", item->xml_member);
175 else if (item->bin_member)
176 printf (" in %s", item->bin_member);
182 run_detect (int argc UNUSED, char **argv)
184 char *err = spv_detect (argv[1]);
186 error (1, 0, "%s", err);
190 run_directory (int argc UNUSED, char **argv)
192 struct spv_reader *spv;
193 char *err = spv_open (argv[1], &spv);
195 error (1, 0, "%s", err);
197 struct spv_item **items;
199 spv_select (spv, criteria, n_criteria, &items, &n_items);
200 for (size_t i = 0; i < n_items; i++)
201 print_item_directory (items[i]);
209 const struct spv_item **nodes;
213 const struct spv_item *stub[N_STUB];
217 swap_nodes (const struct spv_item **a, const struct spv_item **b)
219 const struct spv_item *tmp = *a;
225 get_path (const struct spv_item *item, struct item_path *path)
227 size_t allocated = 10;
228 path->nodes = path->stub;
233 if (path->n >= allocated)
235 if (path->nodes == path->stub)
236 path->nodes = xmemdup (path->stub, sizeof path->stub);
237 path->nodes = x2nrealloc (path->nodes, &allocated,
238 sizeof *path->nodes);
240 path->nodes[path->n++] = item;
244 for (size_t i = 0; i < path->n / 2; i++)
245 swap_nodes (&path->nodes[i], &path->nodes[path->n - i - 1]);
249 free_path (struct item_path *path)
251 if (path && path->nodes != path->stub)
256 dump_heading_transition (const struct spv_item *old,
257 const struct spv_item *new)
262 struct item_path old_path, new_path;
263 get_path (old, &old_path);
264 get_path (new, &new_path);
267 for (; common < old_path.n && common < new_path.n; common++)
268 if (old_path.nodes[common] != new_path.nodes[common])
271 for (size_t i = common; i < old_path.n; i++)
272 group_close_item_submit (group_close_item_create ());
273 for (size_t i = common; i < new_path.n; i++)
274 group_open_item_submit (group_open_item_create (
275 new_path.nodes[i]->command_id,
276 new_path.nodes[i]->label));
278 free_path (&old_path);
279 free_path (&new_path);
283 run_convert (int argc UNUSED, char **argv)
285 struct spv_reader *spv;
286 char *err = spv_open (argv[1], &spv);
288 error (1, 0, "%s", err);
291 spv_item_set_table_look (spv_get_root (spv), table_look);
293 output_engine_push ();
294 output_set_filename (argv[1]);
295 string_map_replace (&output_options, "output-file", argv[2]);
296 struct output_driver *driver = output_driver_create (&output_options);
299 output_driver_register (driver);
301 const struct page_setup *ps = spv_get_page_setup (spv);
303 page_setup_item_submit (page_setup_item_create (ps));
305 struct spv_item **items;
307 spv_select (spv, criteria, n_criteria, &items, &n_items);
308 struct spv_item *prev_heading = spv_get_root (spv);
309 for (size_t i = 0; i < n_items; i++)
311 struct spv_item *heading
312 = items[i]->type == SPV_ITEM_HEADING ? items[i] : items[i]->parent;
313 dump_heading_transition (prev_heading, heading);
314 dump_item (items[i]);
315 prev_heading = heading;
317 dump_heading_transition (prev_heading, spv_get_root (spv));
322 output_engine_pop ();
325 if (n_warnings && !force)
327 /* XXX There could be other files to unlink, e.g. the ascii driver can
328 produce additional files with the charts. */
333 static const struct pivot_table *
334 get_first_table (const struct spv_reader *spv)
336 struct spv_item **items;
338 spv_select (spv, criteria, n_criteria, &items, &n_items);
340 for (size_t i = 0; i < n_items; i++)
341 if (spv_item_is_table (items[i]))
344 return spv_item_get_table (items[i]);
352 run_get_table_look (int argc UNUSED, char **argv)
354 struct pivot_table_look *look;
355 if (strcmp (argv[1], "-"))
357 struct spv_reader *spv;
358 char *err = spv_open (argv[1], &spv);
360 error (1, 0, "%s", err);
362 const struct pivot_table *table = get_first_table (spv);
364 error (1, 0, "%s: no tables found", argv[1]);
366 look = pivot_table_look_ref (pivot_table_get_look (table));
371 look = pivot_table_look_ref (pivot_table_look_builtin_default ());
373 char *err = spv_table_look_write (argv[2], look);
375 error (1, 0, "%s", err);
377 pivot_table_look_unref (look);
381 run_convert_table_look (int argc UNUSED, char **argv)
383 struct pivot_table_look *look;
384 char *err = spv_table_look_read (argv[1], &look);
386 error (1, 0, "%s", err);
388 err = spv_table_look_write (argv[2], look);
390 error (1, 0, "%s", err);
392 pivot_table_look_unref (look);
397 run_dump (int argc UNUSED, char **argv)
399 struct spv_reader *spv;
400 char *err = spv_open (argv[1], &spv);
402 error (1, 0, "%s", err);
404 struct spv_item **items;
406 spv_select (spv, criteria, n_criteria, &items, &n_items);
407 for (size_t i = 0; i < n_items; i++)
408 if (items[i]->type == SPV_ITEM_TABLE)
410 pivot_table_dump (spv_item_get_table (items[i]), 0);
419 compare_borders (const void *a_, const void *b_)
421 const struct spvlb_border *const *ap = a_;
422 const struct spvlb_border *const *bp = b_;
423 uint32_t a = (*ap)->border_type;
424 uint32_t b = (*bp)->border_type;
426 return a < b ? -1 : a > b;
430 compare_cells (const void *a_, const void *b_)
432 const struct spvlb_cell *const *ap = a_;
433 const struct spvlb_cell *const *bp = b_;
434 uint64_t a = (*ap)->index;
435 uint64_t b = (*bp)->index;
437 return a < b ? -1 : a > b;
441 run_dump_light_table (int argc UNUSED, char **argv)
443 if (raw && isatty (STDOUT_FILENO))
444 error (1, 0, "not writing binary data to tty");
446 struct spv_reader *spv;
447 char *err = spv_open (argv[1], &spv);
449 error (1, 0, "%s", err);
451 struct spv_item **items;
453 spv_select (spv, criteria, n_criteria, &items, &n_items);
454 for (size_t i = 0; i < n_items; i++)
456 if (!spv_item_is_light_table (items[i]))
464 error = spv_item_get_raw_light_table (items[i], &data, &size);
467 fwrite (data, size, 1, stdout);
473 struct spvlb_table *table;
474 error = spv_item_get_light_table (items[i], &table);
479 qsort (table->borders->borders, table->borders->n_borders,
480 sizeof *table->borders->borders, compare_borders);
481 qsort (table->cells->cells, table->cells->n_cells,
482 sizeof *table->cells->cells, compare_cells);
484 spvlb_print_table (items[i]->bin_member, 0, table);
485 spvlb_free_table (table);
490 msg (ME, "%s", error);
501 run_dump_legacy_data (int argc UNUSED, char **argv)
503 struct spv_reader *spv;
504 char *err = spv_open (argv[1], &spv);
506 error (1, 0, "%s", err);
508 struct spv_item **items;
510 spv_select (spv, criteria, n_criteria, &items, &n_items);
511 for (size_t i = 0; i < n_items; i++)
512 if (spv_item_is_legacy_table (items[i]))
514 struct spv_data data;
520 error = spv_item_get_raw_legacy_data (items[i], &data, &size);
523 fwrite (data, size, 1, stdout);
529 error = spv_item_get_legacy_data (items[i], &data);
532 printf ("%s:\n", items[i]->bin_member);
533 spv_data_dump (&data, stdout);
534 spv_data_uninit (&data);
541 msg (ME, "%s", error);
550 /* This is really bogus.
552 XPath doesn't have any notion of a default XML namespace, but all of the
553 elements in the documents we're interested in have a namespace. Thus, we'd
554 need to require the XPath expressions to have a namespace on every single
555 element: vis:sourceVariable, vis:graph, and so on. That's a pain. So,
556 instead, we remove the default namespace from everyplace it occurs. XPath
557 does support the null namespace, so this allows sourceVariable, graph,
560 See http://plasmasturm.org/log/259/ and
561 https://mail.gnome.org/archives/xml/2003-April/msg00144.html for more
564 remove_default_xml_namespace (xmlNode *node)
566 if (node->ns && !node->ns->prefix)
569 for (xmlNode *child = node->children; child; child = child->next)
570 remove_default_xml_namespace (child);
574 register_ns (xmlXPathContext *ctx, const char *prefix, const char *uri)
576 xmlXPathRegisterNs (ctx, CHAR_CAST (xmlChar *, prefix),
577 CHAR_CAST (xmlChar *, uri));
580 static xmlXPathContext *
581 create_xpath_context (xmlDoc *doc)
583 xmlXPathContext *ctx = xmlXPathNewContext (doc);
584 register_ns (ctx, "vgr", "http://xml.spss.com/spss/viewer/viewer-graph");
585 register_ns (ctx, "vizml", "http://xml.spss.com/visualization");
586 register_ns (ctx, "vmd", "http://xml.spss.com/spss/viewer/viewer-model");
587 register_ns (ctx, "vps", "http://xml.spss.com/spss/viewer/viewer-pagesetup");
588 register_ns (ctx, "vst", "http://xml.spss.com/spss/viewer/viewer-style");
589 register_ns (ctx, "vtb", "http://xml.spss.com/spss/viewer/viewer-table");
590 register_ns (ctx, "vtl", "http://xml.spss.com/spss/viewer/table-looks");
591 register_ns (ctx, "vtt", "http://xml.spss.com/spss/viewer/viewer-treemodel");
592 register_ns (ctx, "vtx", "http://xml.spss.com/spss/viewer/viewer-text");
593 register_ns (ctx, "xsi", "http://www.w3.org/2001/XMLSchema-instance");
598 dump_xml (int argc, char **argv, const char *member_name,
599 char *error_s, xmlDoc *doc)
605 printf ("<!-- %s -->\n", member_name);
606 xmlElemDump (stdout, NULL, xmlDocGetRootElement (doc));
611 bool any_results = false;
613 remove_default_xml_namespace (xmlDocGetRootElement (doc));
614 for (int i = 2; i < argc; i++)
616 xmlXPathContext *xpath_ctx = create_xpath_context (doc);
617 xmlXPathSetContextNode (xmlDocGetRootElement (doc),
619 xmlXPathObject *xpath_obj = xmlXPathEvalExpression(
620 CHAR_CAST (xmlChar *, argv[i]), xpath_ctx);
622 error (1, 0, _("%s: invalid XPath expression"), argv[i]);
624 const xmlNodeSet *nodes = xpath_obj->nodesetval;
625 if (nodes && nodes->nodeNr > 0)
629 printf ("<!-- %s -->\n", member_name);
632 for (size_t j = 0; j < nodes->nodeNr; j++)
634 xmlElemDump (stdout, doc, nodes->nodeTab[j]);
639 xmlXPathFreeObject (xpath_obj);
640 xmlXPathFreeContext (xpath_ctx);
649 printf ("<!-- %s -->\n", member_name);
650 msg (ME, "%s", error_s);
656 run_dump_legacy_table (int argc, char **argv)
658 struct spv_reader *spv;
659 char *err = spv_open (argv[1], &spv);
661 error (1, 0, "%s", err);
663 struct spv_item **items;
665 spv_select (spv, criteria, n_criteria, &items, &n_items);
666 for (size_t i = 0; i < n_items; i++)
667 if (spv_item_is_legacy_table (items[i]))
670 char *error_s = spv_item_get_legacy_table (items[i], &doc);
671 dump_xml (argc, argv, items[i]->xml_member, error_s, doc);
679 run_dump_structure (int argc, char **argv)
681 struct spv_reader *spv;
682 char *err = spv_open (argv[1], &spv);
684 error (1, 0, "%s", err);
686 struct spv_item **items;
688 spv_select (spv, criteria, n_criteria, &items, &n_items);
689 const char *last_structure_member = NULL;
690 for (size_t i = 0; i < n_items; i++)
691 if (!last_structure_member || strcmp (items[i]->structure_member,
692 last_structure_member))
694 last_structure_member = items[i]->structure_member;
697 char *error_s = spv_item_get_structure (items[i], &doc);
698 dump_xml (argc, argv, items[i]->structure_member, error_s, doc);
706 run_is_legacy (int argc UNUSED, char **argv)
708 struct spv_reader *spv;
709 char *err = spv_open (argv[1], &spv);
711 error (1, 0, "%s", err);
713 bool is_legacy = false;
715 struct spv_item **items;
717 spv_select (spv, criteria, n_criteria, &items, &n_items);
718 for (size_t i = 0; i < n_items; i++)
719 if (spv_item_is_legacy_table (items[i]))
728 exit (is_legacy ? EXIT_SUCCESS : EXIT_FAILURE);
734 int min_args, max_args;
735 void (*run) (int argc, char **argv);
738 static const struct command commands[] =
740 { "detect", 1, 1, run_detect },
741 { "dir", 1, 1, run_directory },
742 { "convert", 2, 2, run_convert },
743 { "get-table-look", 2, 2, run_get_table_look },
744 { "convert-table-look", 2, 2, run_convert_table_look },
746 /* Undocumented commands. */
747 { "dump", 1, 1, run_dump },
748 { "dump-light-table", 1, 1, run_dump_light_table },
749 { "dump-legacy-data", 1, 1, run_dump_legacy_data },
750 { "dump-legacy-table", 1, INT_MAX, run_dump_legacy_table },
751 { "dump-structure", 1, INT_MAX, run_dump_structure },
752 { "is-legacy", 1, 1, run_is_legacy },
754 static const int n_commands = sizeof commands / sizeof *commands;
756 static const struct command *
757 find_command (const char *name)
759 for (size_t i = 0; i < n_commands; i++)
761 const struct command *c = &commands[i];
762 if (!strcmp (name, c->name))
769 emit_msg (const struct msg *m, void *aux UNUSED)
771 if (m->severity == MSG_S_ERROR || m->severity == MSG_S_WARNING)
774 char *s = msg_to_string (m);
775 fprintf (stderr, "%s\n", s);
780 main (int argc, char **argv)
782 set_program_name (argv[0]);
783 msg_set_handler (emit_msg, NULL);
787 parse_options (argc, argv);
793 error (1, 0, _("missing command name (use --help for help)"));
795 const struct command *c = find_command (argv[0]);
797 error (1, 0, _("unknown command \"%s\" (use --help for help)"), argv[0]);
799 int n_args = argc - 1;
800 if (n_args < c->min_args || n_args > c->max_args)
802 if (c->min_args == c->max_args)
805 ngettext ("\"%s\" command takes exactly %d argument",
806 "\"%s\" command takes exactly %d arguments",
807 c->min_args), c->name, c->min_args);
809 else if (c->max_args == INT_MAX)
812 ngettext ("\"%s\" command requires at least %d argument",
813 "\"%s\" command requires at least %d arguments",
814 c->min_args), c->name, c->min_args);
819 _("\"%s\" command requires between %d and %d arguments"),
820 c->name, c->min_args, c->max_args);
826 pivot_table_look_unref (table_look);
829 return n_warnings ? EXIT_FAILURE : EXIT_SUCCESS;
832 static struct spv_criteria *
835 if (!n_criteria || new_criteria)
837 new_criteria = false;
838 if (n_criteria >= allocated_criteria)
839 criteria = x2nrealloc (criteria, &allocated_criteria,
841 criteria[n_criteria++] = (struct spv_criteria) SPV_CRITERIA_INITIALIZER;
844 return &criteria[n_criteria - 1];
848 parse_select (char *arg)
850 bool invert = arg[0] == '^';
853 unsigned classes = 0;
854 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
856 if (!strcmp (arg, "all"))
857 classes = SPV_ALL_CLASSES;
858 else if (!strcmp (arg, "help"))
860 puts (_("The following object classes are supported:"));
861 for (int class = 0; class < SPV_N_CLASSES; class++)
862 printf ("- %s\n", spv_item_class_to_string (class));
867 int class = spv_item_class_from_string (token);
868 if (class == SPV_N_CLASSES)
869 error (1, 0, _("%s: unknown object class (use --select=help "
871 classes |= 1u << class;
875 struct spv_criteria *c = get_criteria ();
876 c->classes = invert ? classes ^ SPV_ALL_CLASSES : classes;
879 static struct spv_criteria_match *
880 get_criteria_match (const char **arg)
882 struct spv_criteria *c = get_criteria ();
883 if ((*arg)[0] == '^')
893 parse_commands (const char *arg)
895 struct spv_criteria_match *cm = get_criteria_match (&arg);
896 string_array_parse (&cm->commands, ss_cstr (arg), ss_cstr (","));
900 parse_subtypes (const char *arg)
902 struct spv_criteria_match *cm = get_criteria_match (&arg);
903 string_array_parse (&cm->subtypes, ss_cstr (arg), ss_cstr (","));
907 parse_labels (const char *arg)
909 struct spv_criteria_match *cm = get_criteria_match (&arg);
910 string_array_parse (&cm->labels, ss_cstr (arg), ss_cstr (","));
914 parse_instances (char *arg)
916 struct spv_criteria *c = get_criteria ();
917 size_t allocated_instances = c->n_instances;
919 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
921 if (c->n_instances >= allocated_instances)
922 c->instances = x2nrealloc (c->instances, &allocated_instances,
923 sizeof *c->instances);
925 c->instances[c->n_instances++] = (!strcmp (token, "last") ? -1
931 parse_nth_commands (char *arg)
933 struct spv_criteria *c = get_criteria ();
934 size_t allocated_commands = c->n_commands;
936 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
938 if (c->n_commands >= allocated_commands)
939 c->commands = x2nrealloc (c->commands, &allocated_commands,
940 sizeof *c->commands);
942 c->commands[c->n_commands++] = atoi (token);
947 parse_members (const char *arg)
949 struct spv_criteria *cm = get_criteria ();
950 string_array_parse (&cm->members, ss_cstr (arg), ss_cstr (","));
954 parse_table_look (const char *arg)
956 pivot_table_look_unref (table_look);
958 char *error_s = spv_table_look_read (arg, &table_look);
960 error (1, 0, "%s", error_s);
964 parse_options (int argc, char *argv[])
970 OPT_MEMBER_NAMES = UCHAR_MAX + 1,
985 static const struct option long_options[] =
987 /* Input selection options. */
988 { "show-hidden", no_argument, NULL, OPT_SHOW_HIDDEN },
989 { "select", required_argument, NULL, OPT_SELECT },
990 { "commands", required_argument, NULL, OPT_COMMANDS },
991 { "nth-commands", required_argument, NULL, OPT_NTH_COMMANDS },
992 { "subtypes", required_argument, NULL, OPT_SUBTYPES },
993 { "labels", required_argument, NULL, OPT_LABELS },
994 { "instances", required_argument, NULL, OPT_INSTANCES },
995 { "members", required_argument, NULL, OPT_MEMBERS },
996 { "errors", no_argument, NULL, OPT_ERRORS },
997 { "or", no_argument, NULL, OPT_OR },
999 /* "dir" command options. */
1000 { "member-names", no_argument, NULL, OPT_MEMBER_NAMES },
1002 /* "convert" command options. */
1003 { "force", no_argument, NULL, 'f' },
1004 { "table-look", required_argument, NULL, OPT_TABLE_LOOK },
1006 /* "dump-light-table" command options. */
1007 { "sort", no_argument, NULL, OPT_SORT },
1008 { "raw", no_argument, NULL, OPT_RAW },
1010 { "help", no_argument, NULL, 'h' },
1011 { "version", no_argument, NULL, 'v' },
1013 { NULL, 0, NULL, 0 },
1018 c = getopt_long (argc, argv, "O:hvf", long_options, NULL);
1025 output_driver_parse_option (optarg, &output_options);
1028 case OPT_MEMBER_NAMES:
1029 show_member_names = true;
1032 case OPT_SHOW_HIDDEN:
1033 get_criteria ()->include_hidden = true;
1037 parse_select (optarg);
1041 parse_commands (optarg);
1044 case OPT_NTH_COMMANDS:
1045 parse_nth_commands (optarg);
1049 parse_subtypes (optarg);
1053 parse_labels (optarg);
1057 parse_instances (optarg);
1061 parse_members (optarg);
1065 get_criteria ()->error = true;
1069 new_criteria = true;
1080 case OPT_TABLE_LOOK:
1081 parse_table_look (optarg);
1089 version_etc (stdout, "pspp-output", PACKAGE_NAME, PACKAGE_VERSION,
1090 "Ben Pfaff", "John Darrington", NULL_SENTINEL);
1091 exit (EXIT_SUCCESS);
1095 exit (EXIT_SUCCESS);
1098 exit (EXIT_FAILURE);
1106 struct string s = DS_EMPTY_INITIALIZER;
1107 struct string_set formats = STRING_SET_INITIALIZER(formats);
1108 output_get_supported_formats (&formats);
1110 const struct string_set_node *node;
1111 STRING_SET_FOR_EACH (format, node, &formats)
1113 if (!ds_is_empty (&s))
1114 ds_put_byte (&s, ' ');
1115 ds_put_cstr (&s, format);
1117 string_set_destroy (&formats);
1120 %s, a utility for working with SPSS viewer (.spv) files.\n\
1121 Usage: %s [OPTION]... COMMAND ARG...\n\
1123 The following commands are available:\n\
1124 detect FILE Detect whether FILE is an SPV file.\n\
1125 dir FILE List tables and other items in FILE.\n\
1126 convert SOURCE DEST Convert .spv SOURCE to DEST.\n\
1127 get-table-look SOURCE DEST Copies first selected TableLook into DEST\n\
1128 convert-table-look SOURCE DEST Copies .tlo or .stt SOURCE into DEST\n\
1130 Input selection options for \"dir\" and \"convert\":\n\
1131 --select=CLASS... include only some kinds of objects\n\
1132 --select=help print known object classes\n\
1133 --commands=COMMAND... include only specified COMMANDs\n\
1134 --nth-commands=N... include only the Nth instance of selected commands\n\
1135 --subtypes=SUBTYPE... include only specified SUBTYPEs of output\n\
1136 --labels=LABEL... include only output objects with the given LABELs\n\
1137 --instances=INSTANCE... include only the given object INSTANCEs\n\
1138 --show-hidden include hidden output objects\n\
1139 --or separate two sets of selection options\n\
1141 \"convert\" by default infers the destination's format from its extension.\n\
1142 The known extensions are: %s\n\
1143 The following options override \"convert\" behavior:\n\
1144 -O format=FORMAT set destination format to FORMAT\n\
1145 -O OPTION=VALUE set output option\n\
1146 -f, --force keep output file even given errors\n\
1147 --table-look=FILE override tables' style with TableLook from FILE\n\
1149 --help display this help and exit\n\
1150 --version output version information and exit\n",
1151 program_name, program_name, ds_cstr (&s));