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 parse_options (int argc, char **argv);
91 dump_item (const struct spv_item *item)
93 if (show_member_names && (item->xml_member || item->bin_member))
95 const char *x = item->xml_member;
96 const char *b = item->bin_member;
98 /* The strings below are not marked for translation because they are only
99 useful to developers. */
101 ? xasprintf ("%s and %s:", x, b)
102 : xasprintf ("%s:", x ? x : b));
103 text_item_submit (text_item_create_nocopy (TEXT_ITEM_TITLE, s,
104 xstrdup ("Member Names")));
107 switch (spv_item_get_type (item))
109 case SPV_ITEM_HEADING:
113 spv_text_submit (item);
117 pivot_table_submit (pivot_table_ref (spv_item_get_table (item)));
127 image_item_submit (image_item_create (cairo_surface_reference (
128 spv_item_get_image (item))));
140 print_item_directory (const struct spv_item *item)
142 for (int i = 1; i < spv_item_get_level (item); i++)
145 enum spv_item_type type = spv_item_get_type (item);
146 printf ("- %s", spv_item_type_to_string (type));
148 const char *label = spv_item_get_label (item);
150 printf (" \"%s\"", label);
152 if (type == SPV_ITEM_TABLE)
154 const struct pivot_table *table = spv_item_get_table (item);
155 char *title = pivot_value_to_string (table->title, table);
156 if (!label || strcmp (title, label))
157 printf (" title \"%s\"", title);
161 const char *command_id = spv_item_get_command_id (item);
163 printf (" command \"%s\"", command_id);
165 const char *subtype = spv_item_get_subtype (item);
166 if (subtype && (!label || strcmp (label, subtype)))
167 printf (" subtype \"%s\"", subtype);
169 if (!spv_item_is_visible (item))
170 printf (" (hidden)");
172 if (show_member_names)
174 const char *members[] = {
181 for (size_t i = 0; i < sizeof members / sizeof *members; i++)
183 printf (" %s %s", n++ == 0 ? "in" : "and", members[i]);
189 run_detect (int argc UNUSED, char **argv)
191 char *err = spv_detect (argv[1]);
193 error (1, 0, "%s", err);
197 run_directory (int argc UNUSED, char **argv)
199 struct spv_reader *spv;
200 char *err = spv_open (argv[1], &spv);
202 error (1, 0, "%s", err);
204 struct spv_item **items;
206 spv_select (spv, criteria, n_criteria, &items, &n_items);
207 for (size_t i = 0; i < n_items; i++)
208 print_item_directory (items[i]);
216 const struct spv_item **nodes;
220 const struct spv_item *stub[N_STUB];
224 swap_nodes (const struct spv_item **a, const struct spv_item **b)
226 const struct spv_item *tmp = *a;
232 get_path (const struct spv_item *item, struct item_path *path)
234 size_t allocated = 10;
235 path->nodes = path->stub;
240 if (path->n >= allocated)
242 if (path->nodes == path->stub)
243 path->nodes = xmemdup (path->stub, sizeof path->stub);
244 path->nodes = x2nrealloc (path->nodes, &allocated,
245 sizeof *path->nodes);
247 path->nodes[path->n++] = item;
251 for (size_t i = 0; i < path->n / 2; i++)
252 swap_nodes (&path->nodes[i], &path->nodes[path->n - i - 1]);
256 free_path (struct item_path *path)
258 if (path && path->nodes != path->stub)
263 dump_heading_transition (const struct spv_item *old,
264 const struct spv_item *new)
269 struct item_path old_path, new_path;
270 get_path (old, &old_path);
271 get_path (new, &new_path);
274 for (; common < old_path.n && common < new_path.n; common++)
275 if (old_path.nodes[common] != new_path.nodes[common])
278 for (size_t i = common; i < old_path.n; i++)
279 group_close_item_submit (group_close_item_create ());
280 for (size_t i = common; i < new_path.n; i++)
281 group_open_item_submit (group_open_item_create (
282 new_path.nodes[i]->command_id,
283 new_path.nodes[i]->label));
285 free_path (&old_path);
286 free_path (&new_path);
290 run_convert (int argc UNUSED, char **argv)
292 struct spv_reader *spv;
293 char *err = spv_open (argv[1], &spv);
295 error (1, 0, "%s", err);
298 spv_item_set_table_look (spv_get_root (spv), table_look);
300 output_engine_push ();
301 output_set_filename (argv[1]);
302 string_map_replace (&output_options, "output-file", argv[2]);
303 struct output_driver *driver = output_driver_create (&output_options);
306 output_driver_register (driver);
308 const struct page_setup *ps = spv_get_page_setup (spv);
310 page_setup_item_submit (page_setup_item_create (ps));
312 struct spv_item **items;
314 spv_select (spv, criteria, n_criteria, &items, &n_items);
315 struct spv_item *prev_heading = spv_get_root (spv);
316 for (size_t i = 0; i < n_items; i++)
318 struct spv_item *heading
319 = items[i]->type == SPV_ITEM_HEADING ? items[i] : items[i]->parent;
320 dump_heading_transition (prev_heading, heading);
321 dump_item (items[i]);
322 prev_heading = heading;
324 dump_heading_transition (prev_heading, spv_get_root (spv));
329 output_engine_pop ();
332 if (n_warnings && !force)
334 /* XXX There could be other files to unlink, e.g. the ascii driver can
335 produce additional files with the charts. */
340 static const struct pivot_table *
341 get_first_table (const struct spv_reader *spv)
343 struct spv_item **items;
345 spv_select (spv, criteria, n_criteria, &items, &n_items);
347 for (size_t i = 0; i < n_items; i++)
348 if (spv_item_is_table (items[i]))
351 return spv_item_get_table (items[i]);
359 run_get_table_look (int argc UNUSED, char **argv)
361 struct pivot_table_look *look;
362 if (strcmp (argv[1], "-"))
364 struct spv_reader *spv;
365 char *err = spv_open (argv[1], &spv);
367 error (1, 0, "%s", err);
369 const struct pivot_table *table = get_first_table (spv);
371 error (1, 0, "%s: no tables found", argv[1]);
373 look = pivot_table_look_ref (pivot_table_get_look (table));
378 look = pivot_table_look_ref (pivot_table_look_builtin_default ());
380 char *err = spv_table_look_write (argv[2], look);
382 error (1, 0, "%s", err);
384 pivot_table_look_unref (look);
388 run_convert_table_look (int argc UNUSED, char **argv)
390 struct pivot_table_look *look;
391 char *err = spv_table_look_read (argv[1], &look);
393 error (1, 0, "%s", err);
395 err = spv_table_look_write (argv[2], look);
397 error (1, 0, "%s", err);
399 pivot_table_look_unref (look);
404 run_dump (int argc UNUSED, char **argv)
406 struct spv_reader *spv;
407 char *err = spv_open (argv[1], &spv);
409 error (1, 0, "%s", err);
411 struct spv_item **items;
413 spv_select (spv, criteria, n_criteria, &items, &n_items);
414 for (size_t i = 0; i < n_items; i++)
415 if (items[i]->type == SPV_ITEM_TABLE)
417 pivot_table_dump (spv_item_get_table (items[i]), 0);
426 compare_borders (const void *a_, const void *b_)
428 const struct spvlb_border *const *ap = a_;
429 const struct spvlb_border *const *bp = b_;
430 uint32_t a = (*ap)->border_type;
431 uint32_t b = (*bp)->border_type;
433 return a < b ? -1 : a > b;
437 compare_cells (const void *a_, const void *b_)
439 const struct spvlb_cell *const *ap = a_;
440 const struct spvlb_cell *const *bp = b_;
441 uint64_t a = (*ap)->index;
442 uint64_t b = (*bp)->index;
444 return a < b ? -1 : a > b;
448 run_dump_light_table (int argc UNUSED, char **argv)
450 if (raw && isatty (STDOUT_FILENO))
451 error (1, 0, "not writing binary data to tty");
453 struct spv_reader *spv;
454 char *err = spv_open (argv[1], &spv);
456 error (1, 0, "%s", err);
458 struct spv_item **items;
460 spv_select (spv, criteria, n_criteria, &items, &n_items);
461 for (size_t i = 0; i < n_items; i++)
463 if (!spv_item_is_light_table (items[i]))
471 error = spv_item_get_raw_light_table (items[i], &data, &size);
474 fwrite (data, size, 1, stdout);
480 struct spvlb_table *table;
481 error = spv_item_get_light_table (items[i], &table);
486 qsort (table->borders->borders, table->borders->n_borders,
487 sizeof *table->borders->borders, compare_borders);
488 qsort (table->cells->cells, table->cells->n_cells,
489 sizeof *table->cells->cells, compare_cells);
491 spvlb_print_table (items[i]->bin_member, 0, table);
492 spvlb_free_table (table);
497 msg (ME, "%s", error);
508 run_dump_legacy_data (int argc UNUSED, char **argv)
510 struct spv_reader *spv;
511 char *err = spv_open (argv[1], &spv);
513 error (1, 0, "%s", err);
515 struct spv_item **items;
517 spv_select (spv, criteria, n_criteria, &items, &n_items);
518 for (size_t i = 0; i < n_items; i++)
519 if (spv_item_is_legacy_table (items[i]))
521 struct spv_data data;
527 error = spv_item_get_raw_legacy_data (items[i], &data, &size);
530 fwrite (data, size, 1, stdout);
536 error = spv_item_get_legacy_data (items[i], &data);
539 printf ("%s:\n", items[i]->bin_member);
540 spv_data_dump (&data, stdout);
541 spv_data_uninit (&data);
548 msg (ME, "%s", error);
557 /* This is really bogus.
559 XPath doesn't have any notion of a default XML namespace, but all of the
560 elements in the documents we're interested in have a namespace. Thus, we'd
561 need to require the XPath expressions to have a namespace on every single
562 element: vis:sourceVariable, vis:graph, and so on. That's a pain. So,
563 instead, we remove the default namespace from everyplace it occurs. XPath
564 does support the null namespace, so this allows sourceVariable, graph,
567 See http://plasmasturm.org/log/259/ and
568 https://mail.gnome.org/archives/xml/2003-April/msg00144.html for more
571 remove_default_xml_namespace (xmlNode *node)
573 if (node->ns && !node->ns->prefix)
576 for (xmlNode *child = node->children; child; child = child->next)
577 remove_default_xml_namespace (child);
581 register_ns (xmlXPathContext *ctx, const char *prefix, const char *uri)
583 xmlXPathRegisterNs (ctx, CHAR_CAST (xmlChar *, prefix),
584 CHAR_CAST (xmlChar *, uri));
587 static xmlXPathContext *
588 create_xpath_context (xmlDoc *doc)
590 xmlXPathContext *ctx = xmlXPathNewContext (doc);
591 register_ns (ctx, "vgr", "http://xml.spss.com/spss/viewer/viewer-graph");
592 register_ns (ctx, "vizml", "http://xml.spss.com/visualization");
593 register_ns (ctx, "vmd", "http://xml.spss.com/spss/viewer/viewer-model");
594 register_ns (ctx, "vps", "http://xml.spss.com/spss/viewer/viewer-pagesetup");
595 register_ns (ctx, "vst", "http://xml.spss.com/spss/viewer/viewer-style");
596 register_ns (ctx, "vtb", "http://xml.spss.com/spss/viewer/viewer-table");
597 register_ns (ctx, "vtl", "http://xml.spss.com/spss/viewer/table-looks");
598 register_ns (ctx, "vtt", "http://xml.spss.com/spss/viewer/viewer-treemodel");
599 register_ns (ctx, "vtx", "http://xml.spss.com/spss/viewer/viewer-text");
600 register_ns (ctx, "xsi", "http://www.w3.org/2001/XMLSchema-instance");
605 dump_xml (int argc, char **argv, const char *member_name,
606 char *error_s, xmlDoc *doc)
612 printf ("<!-- %s -->\n", member_name);
613 xmlElemDump (stdout, NULL, xmlDocGetRootElement (doc));
618 bool any_results = false;
620 remove_default_xml_namespace (xmlDocGetRootElement (doc));
621 for (int i = 2; i < argc; i++)
623 xmlXPathContext *xpath_ctx = create_xpath_context (doc);
624 xmlXPathSetContextNode (xmlDocGetRootElement (doc),
626 xmlXPathObject *xpath_obj = xmlXPathEvalExpression(
627 CHAR_CAST (xmlChar *, argv[i]), xpath_ctx);
629 error (1, 0, _("%s: invalid XPath expression"), argv[i]);
631 const xmlNodeSet *nodes = xpath_obj->nodesetval;
632 if (nodes && nodes->nodeNr > 0)
636 printf ("<!-- %s -->\n", member_name);
639 for (size_t j = 0; j < nodes->nodeNr; j++)
641 xmlElemDump (stdout, doc, nodes->nodeTab[j]);
646 xmlXPathFreeObject (xpath_obj);
647 xmlXPathFreeContext (xpath_ctx);
656 printf ("<!-- %s -->\n", member_name);
657 msg (ME, "%s", error_s);
663 run_dump_legacy_table (int argc, char **argv)
665 struct spv_reader *spv;
666 char *err = spv_open (argv[1], &spv);
668 error (1, 0, "%s", err);
670 struct spv_item **items;
672 spv_select (spv, criteria, n_criteria, &items, &n_items);
673 for (size_t i = 0; i < n_items; i++)
674 if (spv_item_is_legacy_table (items[i]))
677 char *error_s = spv_item_get_legacy_table (items[i], &doc);
678 dump_xml (argc, argv, items[i]->xml_member, error_s, doc);
686 run_dump_structure (int argc, char **argv)
688 struct spv_reader *spv;
689 char *err = spv_open (argv[1], &spv);
691 error (1, 0, "%s", err);
693 struct spv_item **items;
695 spv_select (spv, criteria, n_criteria, &items, &n_items);
696 const char *last_structure_member = NULL;
697 for (size_t i = 0; i < n_items; i++)
698 if (!last_structure_member || strcmp (items[i]->structure_member,
699 last_structure_member))
701 last_structure_member = items[i]->structure_member;
704 char *error_s = spv_item_get_structure (items[i], &doc);
705 dump_xml (argc, argv, items[i]->structure_member, error_s, doc);
713 run_is_legacy (int argc UNUSED, char **argv)
715 struct spv_reader *spv;
716 char *err = spv_open (argv[1], &spv);
718 error (1, 0, "%s", err);
720 bool is_legacy = false;
722 struct spv_item **items;
724 spv_select (spv, criteria, n_criteria, &items, &n_items);
725 for (size_t i = 0; i < n_items; i++)
726 if (spv_item_is_legacy_table (items[i]))
735 exit (is_legacy ? EXIT_SUCCESS : EXIT_FAILURE);
741 int min_args, max_args;
742 void (*run) (int argc, char **argv);
745 static const struct command commands[] =
747 { "detect", 1, 1, run_detect },
748 { "dir", 1, 1, run_directory },
749 { "convert", 2, 2, run_convert },
750 { "get-table-look", 2, 2, run_get_table_look },
751 { "convert-table-look", 2, 2, run_convert_table_look },
753 /* Undocumented commands. */
754 { "dump", 1, 1, run_dump },
755 { "dump-light-table", 1, 1, run_dump_light_table },
756 { "dump-legacy-data", 1, 1, run_dump_legacy_data },
757 { "dump-legacy-table", 1, INT_MAX, run_dump_legacy_table },
758 { "dump-structure", 1, INT_MAX, run_dump_structure },
759 { "is-legacy", 1, 1, run_is_legacy },
761 static const int n_commands = sizeof commands / sizeof *commands;
763 static const struct command *
764 find_command (const char *name)
766 for (size_t i = 0; i < n_commands; i++)
768 const struct command *c = &commands[i];
769 if (!strcmp (name, c->name))
776 emit_msg (const struct msg *m, void *aux UNUSED)
778 if (m->severity == MSG_S_ERROR || m->severity == MSG_S_WARNING)
781 char *s = msg_to_string (m);
782 fprintf (stderr, "%s\n", s);
787 main (int argc, char **argv)
789 set_program_name (argv[0]);
790 msg_set_handler (emit_msg, NULL);
794 parse_options (argc, argv);
800 error (1, 0, _("missing command name (use --help for help)"));
802 const struct command *c = find_command (argv[0]);
804 error (1, 0, _("unknown command \"%s\" (use --help for help)"), argv[0]);
806 int n_args = argc - 1;
807 if (n_args < c->min_args || n_args > c->max_args)
809 if (c->min_args == c->max_args)
812 ngettext ("\"%s\" command takes exactly %d argument",
813 "\"%s\" command takes exactly %d arguments",
814 c->min_args), c->name, c->min_args);
816 else if (c->max_args == INT_MAX)
819 ngettext ("\"%s\" command requires at least %d argument",
820 "\"%s\" command requires at least %d arguments",
821 c->min_args), c->name, c->min_args);
826 _("\"%s\" command requires between %d and %d arguments"),
827 c->name, c->min_args, c->max_args);
833 pivot_table_look_unref (table_look);
836 return n_warnings ? EXIT_FAILURE : EXIT_SUCCESS;
839 static struct spv_criteria *
842 if (!n_criteria || new_criteria)
844 new_criteria = false;
845 if (n_criteria >= allocated_criteria)
846 criteria = x2nrealloc (criteria, &allocated_criteria,
848 criteria[n_criteria++] = (struct spv_criteria) SPV_CRITERIA_INITIALIZER;
851 return &criteria[n_criteria - 1];
855 parse_select (char *arg)
857 bool invert = arg[0] == '^';
860 unsigned classes = 0;
861 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
863 if (!strcmp (arg, "all"))
864 classes = SPV_ALL_CLASSES;
865 else if (!strcmp (arg, "help"))
867 puts (_("The following object classes are supported:"));
868 for (int class = 0; class < SPV_N_CLASSES; class++)
869 printf ("- %s\n", spv_item_class_to_string (class));
874 int class = spv_item_class_from_string (token);
875 if (class == SPV_N_CLASSES)
876 error (1, 0, _("%s: unknown object class (use --select=help "
878 classes |= 1u << class;
882 struct spv_criteria *c = get_criteria ();
883 c->classes = invert ? classes ^ SPV_ALL_CLASSES : classes;
886 static struct spv_criteria_match *
887 get_criteria_match (const char **arg)
889 struct spv_criteria *c = get_criteria ();
890 if ((*arg)[0] == '^')
900 parse_commands (const char *arg)
902 struct spv_criteria_match *cm = get_criteria_match (&arg);
903 string_array_parse (&cm->commands, ss_cstr (arg), ss_cstr (","));
907 parse_subtypes (const char *arg)
909 struct spv_criteria_match *cm = get_criteria_match (&arg);
910 string_array_parse (&cm->subtypes, ss_cstr (arg), ss_cstr (","));
914 parse_labels (const char *arg)
916 struct spv_criteria_match *cm = get_criteria_match (&arg);
917 string_array_parse (&cm->labels, ss_cstr (arg), ss_cstr (","));
921 parse_instances (char *arg)
923 struct spv_criteria *c = get_criteria ();
924 size_t allocated_instances = c->n_instances;
926 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
928 if (c->n_instances >= allocated_instances)
929 c->instances = x2nrealloc (c->instances, &allocated_instances,
930 sizeof *c->instances);
932 c->instances[c->n_instances++] = (!strcmp (token, "last") ? -1
938 parse_nth_commands (char *arg)
940 struct spv_criteria *c = get_criteria ();
941 size_t allocated_commands = c->n_commands;
943 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
945 if (c->n_commands >= allocated_commands)
946 c->commands = x2nrealloc (c->commands, &allocated_commands,
947 sizeof *c->commands);
949 c->commands[c->n_commands++] = atoi (token);
954 parse_members (const char *arg)
956 struct spv_criteria *cm = get_criteria ();
957 string_array_parse (&cm->members, ss_cstr (arg), ss_cstr (","));
961 parse_table_look (const char *arg)
963 pivot_table_look_unref (table_look);
965 char *error_s = spv_table_look_read (arg, &table_look);
967 error (1, 0, "%s", error_s);
971 parse_options (int argc, char *argv[])
977 OPT_MEMBER_NAMES = UCHAR_MAX + 1,
992 static const struct option long_options[] =
994 /* Input selection options. */
995 { "show-hidden", no_argument, NULL, OPT_SHOW_HIDDEN },
996 { "select", required_argument, NULL, OPT_SELECT },
997 { "commands", required_argument, NULL, OPT_COMMANDS },
998 { "nth-commands", required_argument, NULL, OPT_NTH_COMMANDS },
999 { "subtypes", required_argument, NULL, OPT_SUBTYPES },
1000 { "labels", required_argument, NULL, OPT_LABELS },
1001 { "instances", required_argument, NULL, OPT_INSTANCES },
1002 { "members", required_argument, NULL, OPT_MEMBERS },
1003 { "errors", no_argument, NULL, OPT_ERRORS },
1004 { "or", no_argument, NULL, OPT_OR },
1006 /* "dir" command options. */
1007 { "member-names", no_argument, NULL, OPT_MEMBER_NAMES },
1009 /* "convert" command options. */
1010 { "force", no_argument, NULL, 'f' },
1011 { "table-look", required_argument, NULL, OPT_TABLE_LOOK },
1013 /* "dump-light-table" command options. */
1014 { "sort", no_argument, NULL, OPT_SORT },
1015 { "raw", no_argument, NULL, OPT_RAW },
1017 { "help", no_argument, NULL, 'h' },
1018 { "version", no_argument, NULL, 'v' },
1020 { NULL, 0, NULL, 0 },
1025 c = getopt_long (argc, argv, "O:hvf", long_options, NULL);
1032 output_driver_parse_option (optarg, &output_options);
1035 case OPT_MEMBER_NAMES:
1036 show_member_names = true;
1039 case OPT_SHOW_HIDDEN:
1040 get_criteria ()->include_hidden = true;
1044 parse_select (optarg);
1048 parse_commands (optarg);
1051 case OPT_NTH_COMMANDS:
1052 parse_nth_commands (optarg);
1056 parse_subtypes (optarg);
1060 parse_labels (optarg);
1064 parse_instances (optarg);
1068 parse_members (optarg);
1072 get_criteria ()->error = true;
1076 new_criteria = true;
1087 case OPT_TABLE_LOOK:
1088 parse_table_look (optarg);
1096 version_etc (stdout, "pspp-output", PACKAGE_NAME, PACKAGE_VERSION,
1097 "Ben Pfaff", "John Darrington", NULL_SENTINEL);
1098 exit (EXIT_SUCCESS);
1102 exit (EXIT_SUCCESS);
1105 exit (EXIT_FAILURE);
1113 struct string s = DS_EMPTY_INITIALIZER;
1114 struct string_set formats = STRING_SET_INITIALIZER(formats);
1115 output_get_supported_formats (&formats);
1117 const struct string_set_node *node;
1118 STRING_SET_FOR_EACH (format, node, &formats)
1120 if (!ds_is_empty (&s))
1121 ds_put_byte (&s, ' ');
1122 ds_put_cstr (&s, format);
1124 string_set_destroy (&formats);
1127 %s, a utility for working with SPSS viewer (.spv) files.\n\
1128 Usage: %s [OPTION]... COMMAND ARG...\n\
1130 The following commands are available:\n\
1131 detect FILE Detect whether FILE is an SPV file.\n\
1132 dir FILE List tables and other items in FILE.\n\
1133 convert SOURCE DEST Convert .spv SOURCE to DEST.\n\
1134 get-table-look SOURCE DEST Copies first selected TableLook into DEST\n\
1135 convert-table-look SOURCE DEST Copies .tlo or .stt SOURCE into DEST\n\
1137 Input selection options for \"dir\" and \"convert\":\n\
1138 --select=CLASS... include only some kinds of objects\n\
1139 --select=help print known object classes\n\
1140 --commands=COMMAND... include only specified COMMANDs\n\
1141 --nth-commands=N... include only the Nth instance of selected commands\n\
1142 --subtypes=SUBTYPE... include only specified SUBTYPEs of output\n\
1143 --labels=LABEL... include only output objects with the given LABELs\n\
1144 --instances=INSTANCE... include only the given object INSTANCEs\n\
1145 --show-hidden include hidden output objects\n\
1146 --or separate two sets of selection options\n\
1148 \"convert\" by default infers the destination's format from its extension.\n\
1149 The known extensions are: %s\n\
1150 The following options override \"convert\" behavior:\n\
1151 -O format=FORMAT set destination format to FORMAT\n\
1152 -O OPTION=VALUE set output option\n\
1153 -f, --force keep output file even given errors\n\
1154 --table-look=FILE override tables' style with TableLook from FILE\n\
1156 --help display this help and exit\n\
1157 --version output version information and exit\n",
1158 program_name, program_name, ds_cstr (&s));