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 ? xasprintf (_("%s and %s:"), x, b)
97 : xasprintf ("%s:", x ? x : b));
98 text_item_submit (text_item_create_nocopy (TEXT_ITEM_TITLE, s));
101 switch (spv_item_get_type (item))
103 case SPV_ITEM_HEADING:
107 spv_text_submit (item);
111 pivot_table_submit (pivot_table_ref (spv_item_get_table (item)));
120 case SPV_ITEM_OBJECT:
132 print_item_directory (const struct spv_item *item)
134 for (int i = 1; i < spv_item_get_level (item); i++)
137 enum spv_item_type type = spv_item_get_type (item);
138 printf ("- %s", spv_item_type_to_string (type));
140 const char *label = spv_item_get_label (item);
142 printf (" \"%s\"", label);
144 if (type == SPV_ITEM_TABLE)
146 const struct pivot_table *table = spv_item_get_table (item);
147 char *title = pivot_value_to_string (table->title,
148 SETTINGS_VALUE_SHOW_DEFAULT,
149 SETTINGS_VALUE_SHOW_DEFAULT);
150 if (!label || strcmp (title, label))
151 printf (" title \"%s\"", title);
155 const char *command_id = spv_item_get_command_id (item);
157 printf (" command \"%s\"", command_id);
159 const char *subtype = spv_item_get_subtype (item);
160 if (subtype && (!label || strcmp (label, subtype)))
161 printf (" subtype \"%s\"", subtype);
163 if (!spv_item_is_visible (item))
164 printf (" (hidden)");
165 if (show_member_names && (item->xml_member || item->bin_member))
167 if (item->xml_member && item->bin_member)
168 printf (" in %s and %s", item->xml_member, item->bin_member);
169 else if (item->xml_member)
170 printf (" in %s", item->xml_member);
171 else if (item->bin_member)
172 printf (" in %s", item->bin_member);
178 run_detect (int argc UNUSED, char **argv)
180 char *err = spv_detect (argv[1]);
182 error (1, 0, "%s", err);
186 run_directory (int argc UNUSED, char **argv)
188 struct spv_reader *spv;
189 char *err = spv_open (argv[1], &spv);
191 error (1, 0, "%s", err);
193 struct spv_item **items;
195 spv_select (spv, criteria, n_criteria, &items, &n_items);
196 for (size_t i = 0; i < n_items; i++)
197 print_item_directory (items[i]);
205 const struct spv_item **nodes;
209 const struct spv_item *stub[N_STUB];
213 swap_nodes (const struct spv_item **a, const struct spv_item **b)
215 const struct spv_item *tmp = *a;
221 get_path (const struct spv_item *item, struct item_path *path)
223 size_t allocated = 10;
224 path->nodes = path->stub;
229 if (path->n >= allocated)
231 if (path->nodes == path->stub)
232 path->nodes = xmemdup (path->stub, sizeof path->stub);
233 path->nodes = x2nrealloc (path->nodes, &allocated,
234 sizeof *path->nodes);
236 path->nodes[path->n++] = item;
240 for (size_t i = 0; i < path->n / 2; i++)
241 swap_nodes (&path->nodes[i], &path->nodes[path->n - i - 1]);
245 free_path (struct item_path *path)
247 if (path && path->nodes != path->stub)
252 dump_heading_transition (const struct spv_item *old,
253 const struct spv_item *new)
258 struct item_path old_path, new_path;
259 get_path (old, &old_path);
260 get_path (new, &new_path);
263 for (; common < old_path.n && common < new_path.n; common++)
264 if (old_path.nodes[common] != new_path.nodes[common])
267 for (size_t i = common; i < old_path.n; i++)
268 group_close_item_submit (group_close_item_create ());
269 for (size_t i = common; i < new_path.n; i++)
270 group_open_item_submit (group_open_item_create (
271 new_path.nodes[i]->command_id));
273 free_path (&old_path);
274 free_path (&new_path);
278 run_convert (int argc UNUSED, char **argv)
280 struct spv_reader *spv;
281 char *err = spv_open (argv[1], &spv);
283 error (1, 0, "%s", err);
286 spv_item_set_table_look (spv_get_root (spv), table_look);
288 output_engine_push ();
289 output_set_filename (argv[1]);
290 string_map_replace (&output_options, "output-file", argv[2]);
291 struct output_driver *driver = output_driver_create (&output_options);
294 output_driver_register (driver);
296 const struct page_setup *ps = spv_get_page_setup (spv);
298 page_setup_item_submit (page_setup_item_create (ps));
300 struct spv_item **items;
302 spv_select (spv, criteria, n_criteria, &items, &n_items);
303 struct spv_item *prev_heading = spv_get_root (spv);
304 for (size_t i = 0; i < n_items; i++)
306 struct spv_item *heading
307 = items[i]->type == SPV_ITEM_HEADING ? items[i] : items[i]->parent;
308 dump_heading_transition (prev_heading, heading);
309 dump_item (items[i]);
310 prev_heading = heading;
312 dump_heading_transition (prev_heading, spv_get_root (spv));
317 output_engine_pop ();
320 if (n_warnings && !force)
322 /* XXX There could be other files to unlink, e.g. the ascii driver can
323 produce additional files with the charts. */
328 static const struct pivot_table *
329 get_first_table (const struct spv_reader *spv)
331 struct spv_item **items;
333 spv_select (spv, criteria, n_criteria, &items, &n_items);
335 for (size_t i = 0; i < n_items; i++)
336 if (spv_item_is_table (items[i]))
339 return spv_item_get_table (items[i]);
347 run_get_table_look (int argc UNUSED, char **argv)
349 struct pivot_table_look *look;
350 if (strcmp (argv[1], "-"))
352 struct spv_reader *spv;
353 char *err = spv_open (argv[1], &spv);
355 error (1, 0, "%s", err);
357 const struct pivot_table *table = get_first_table (spv);
359 error (1, 0, "%s: no tables found", argv[1]);
361 look = pivot_table_look_ref (pivot_table_get_look (table));
366 look = pivot_table_look_ref (pivot_table_look_builtin_default ());
368 char *err = spv_table_look_write (argv[2], look);
370 error (1, 0, "%s", err);
372 pivot_table_look_unref (look);
376 run_convert_table_look (int argc UNUSED, char **argv)
378 struct pivot_table_look *look;
379 char *err = spv_table_look_read (argv[1], &look);
381 error (1, 0, "%s", err);
383 err = spv_table_look_write (argv[2], look);
385 error (1, 0, "%s", err);
387 pivot_table_look_unref (look);
392 run_dump (int argc UNUSED, char **argv)
394 struct spv_reader *spv;
395 char *err = spv_open (argv[1], &spv);
397 error (1, 0, "%s", err);
399 struct spv_item **items;
401 spv_select (spv, criteria, n_criteria, &items, &n_items);
402 for (size_t i = 0; i < n_items; i++)
403 if (items[i]->type == SPV_ITEM_TABLE)
405 pivot_table_dump (spv_item_get_table (items[i]), 0);
414 compare_borders (const void *a_, const void *b_)
416 const struct spvlb_border *const *ap = a_;
417 const struct spvlb_border *const *bp = b_;
418 uint32_t a = (*ap)->border_type;
419 uint32_t b = (*bp)->border_type;
421 return a < b ? -1 : a > b;
425 compare_cells (const void *a_, const void *b_)
427 const struct spvlb_cell *const *ap = a_;
428 const struct spvlb_cell *const *bp = b_;
429 uint64_t a = (*ap)->index;
430 uint64_t b = (*bp)->index;
432 return a < b ? -1 : a > b;
436 run_dump_light_table (int argc UNUSED, char **argv)
438 if (raw && isatty (STDOUT_FILENO))
439 error (1, 0, "not writing binary data to tty");
441 struct spv_reader *spv;
442 char *err = spv_open (argv[1], &spv);
444 error (1, 0, "%s", err);
446 struct spv_item **items;
448 spv_select (spv, criteria, n_criteria, &items, &n_items);
449 for (size_t i = 0; i < n_items; i++)
451 if (!spv_item_is_light_table (items[i]))
459 error = spv_item_get_raw_light_table (items[i], &data, &size);
462 fwrite (data, size, 1, stdout);
468 struct spvlb_table *table;
469 error = spv_item_get_light_table (items[i], &table);
474 qsort (table->borders->borders, table->borders->n_borders,
475 sizeof *table->borders->borders, compare_borders);
476 qsort (table->cells->cells, table->cells->n_cells,
477 sizeof *table->cells->cells, compare_cells);
479 spvlb_print_table (items[i]->bin_member, 0, table);
480 spvlb_free_table (table);
485 msg (ME, "%s", error);
496 run_dump_legacy_data (int argc UNUSED, char **argv)
498 struct spv_reader *spv;
499 char *err = spv_open (argv[1], &spv);
501 error (1, 0, "%s", err);
503 struct spv_item **items;
505 spv_select (spv, criteria, n_criteria, &items, &n_items);
506 for (size_t i = 0; i < n_items; i++)
507 if (spv_item_is_legacy_table (items[i]))
509 struct spv_data data;
515 error = spv_item_get_raw_legacy_data (items[i], &data, &size);
518 fwrite (data, size, 1, stdout);
524 error = spv_item_get_legacy_data (items[i], &data);
527 printf ("%s:\n", items[i]->bin_member);
528 spv_data_dump (&data, stdout);
529 spv_data_uninit (&data);
536 msg (ME, "%s", error);
545 /* This is really bogus.
547 XPath doesn't have any notion of a default XML namespace, but all of the
548 elements in the documents we're interested in have a namespace. Thus, we'd
549 need to require the XPath expressions to have a namespace on every single
550 element: vis:sourceVariable, vis:graph, and so on. That's a pain. So,
551 instead, we remove the default namespace from everyplace it occurs. XPath
552 does support the null namespace, so this allows sourceVariable, graph,
555 See http://plasmasturm.org/log/259/ and
556 https://mail.gnome.org/archives/xml/2003-April/msg00144.html for more
559 remove_default_xml_namespace (xmlNode *node)
561 if (node->ns && !node->ns->prefix)
564 for (xmlNode *child = node->children; child; child = child->next)
565 remove_default_xml_namespace (child);
569 register_ns (xmlXPathContext *ctx, const char *prefix, const char *uri)
571 xmlXPathRegisterNs (ctx, CHAR_CAST (xmlChar *, prefix),
572 CHAR_CAST (xmlChar *, uri));
575 static xmlXPathContext *
576 create_xpath_context (xmlDoc *doc)
578 xmlXPathContext *ctx = xmlXPathNewContext (doc);
579 register_ns (ctx, "vgr", "http://xml.spss.com/spss/viewer/viewer-graph");
580 register_ns (ctx, "vizml", "http://xml.spss.com/visualization");
581 register_ns (ctx, "vmd", "http://xml.spss.com/spss/viewer/viewer-model");
582 register_ns (ctx, "vps", "http://xml.spss.com/spss/viewer/viewer-pagesetup");
583 register_ns (ctx, "vst", "http://xml.spss.com/spss/viewer/viewer-style");
584 register_ns (ctx, "vtb", "http://xml.spss.com/spss/viewer/viewer-table");
585 register_ns (ctx, "vtl", "http://xml.spss.com/spss/viewer/table-looks");
586 register_ns (ctx, "vtt", "http://xml.spss.com/spss/viewer/viewer-treemodel");
587 register_ns (ctx, "vtx", "http://xml.spss.com/spss/viewer/viewer-text");
588 register_ns (ctx, "xsi", "http://www.w3.org/2001/XMLSchema-instance");
593 dump_xml (int argc, char **argv, const char *member_name,
594 char *error_s, xmlDoc *doc)
600 printf ("<!-- %s -->\n", member_name);
601 xmlElemDump (stdout, NULL, xmlDocGetRootElement (doc));
606 bool any_results = false;
608 remove_default_xml_namespace (xmlDocGetRootElement (doc));
609 for (int i = 2; i < argc; i++)
611 xmlXPathContext *xpath_ctx = create_xpath_context (doc);
612 xmlXPathSetContextNode (xmlDocGetRootElement (doc),
614 xmlXPathObject *xpath_obj = xmlXPathEvalExpression(
615 CHAR_CAST (xmlChar *, argv[i]), xpath_ctx);
617 error (1, 0, _("%s: invalid XPath expression"), argv[i]);
619 const xmlNodeSet *nodes = xpath_obj->nodesetval;
620 if (nodes && nodes->nodeNr > 0)
624 printf ("<!-- %s -->\n", member_name);
627 for (size_t j = 0; j < nodes->nodeNr; j++)
629 xmlElemDump (stdout, doc, nodes->nodeTab[j]);
634 xmlXPathFreeObject (xpath_obj);
635 xmlXPathFreeContext (xpath_ctx);
644 printf ("<!-- %s -->\n", member_name);
645 msg (ME, "%s", error_s);
651 run_dump_legacy_table (int argc, char **argv)
653 struct spv_reader *spv;
654 char *err = spv_open (argv[1], &spv);
656 error (1, 0, "%s", err);
658 struct spv_item **items;
660 spv_select (spv, criteria, n_criteria, &items, &n_items);
661 for (size_t i = 0; i < n_items; i++)
662 if (spv_item_is_legacy_table (items[i]))
665 char *error_s = spv_item_get_legacy_table (items[i], &doc);
666 dump_xml (argc, argv, items[i]->xml_member, error_s, doc);
674 run_dump_structure (int argc, char **argv)
676 struct spv_reader *spv;
677 char *err = spv_open (argv[1], &spv);
679 error (1, 0, "%s", err);
681 struct spv_item **items;
683 spv_select (spv, criteria, n_criteria, &items, &n_items);
684 const char *last_structure_member = NULL;
685 for (size_t i = 0; i < n_items; i++)
686 if (!last_structure_member || strcmp (items[i]->structure_member,
687 last_structure_member))
689 last_structure_member = items[i]->structure_member;
692 char *error_s = spv_item_get_structure (items[i], &doc);
693 dump_xml (argc, argv, items[i]->structure_member, error_s, doc);
701 run_is_legacy (int argc UNUSED, char **argv)
703 struct spv_reader *spv;
704 char *err = spv_open (argv[1], &spv);
706 error (1, 0, "%s", err);
708 bool is_legacy = false;
710 struct spv_item **items;
712 spv_select (spv, criteria, n_criteria, &items, &n_items);
713 for (size_t i = 0; i < n_items; i++)
714 if (spv_item_is_legacy_table (items[i]))
723 exit (is_legacy ? EXIT_SUCCESS : EXIT_FAILURE);
729 int min_args, max_args;
730 void (*run) (int argc, char **argv);
733 static const struct command commands[] =
735 { "detect", 1, 1, run_detect },
736 { "dir", 1, 1, run_directory },
737 { "convert", 2, 2, run_convert },
738 { "get-table-look", 2, 2, run_get_table_look },
739 { "convert-table-look", 2, 2, run_convert_table_look },
741 /* Undocumented commands. */
742 { "dump", 1, 1, run_dump },
743 { "dump-light-table", 1, 1, run_dump_light_table },
744 { "dump-legacy-data", 1, 1, run_dump_legacy_data },
745 { "dump-legacy-table", 1, INT_MAX, run_dump_legacy_table },
746 { "dump-structure", 1, INT_MAX, run_dump_structure },
747 { "is-legacy", 1, 1, run_is_legacy },
749 static const int n_commands = sizeof commands / sizeof *commands;
751 static const struct command *
752 find_command (const char *name)
754 for (size_t i = 0; i < n_commands; i++)
756 const struct command *c = &commands[i];
757 if (!strcmp (name, c->name))
764 emit_msg (const struct msg *m, void *aux UNUSED)
766 if (m->severity == MSG_S_ERROR || m->severity == MSG_S_WARNING)
769 char *s = msg_to_string (m);
770 fprintf (stderr, "%s\n", s);
775 main (int argc, char **argv)
777 set_program_name (argv[0]);
778 msg_set_handler (emit_msg, NULL);
782 parse_options (argc, argv);
788 error (1, 0, _("missing command name (use --help for help)"));
790 const struct command *c = find_command (argv[0]);
792 error (1, 0, _("unknown command \"%s\" (use --help for help)"), argv[0]);
794 int n_args = argc - 1;
795 if (n_args < c->min_args || n_args > c->max_args)
797 if (c->min_args == c->max_args)
800 ngettext ("\"%s\" command takes exactly %d argument",
801 "\"%s\" command takes exactly %d arguments",
802 c->min_args), c->name, c->min_args);
804 else if (c->max_args == INT_MAX)
807 ngettext ("\"%s\" command requires at least %d argument",
808 "\"%s\" command requires at least %d arguments",
809 c->min_args), c->name, c->min_args);
814 _("\"%s\" command requires between %d and %d arguments"),
815 c->name, c->min_args, c->max_args);
821 pivot_table_look_unref (table_look);
824 return n_warnings ? EXIT_FAILURE : EXIT_SUCCESS;
827 static struct spv_criteria *
830 if (!n_criteria || new_criteria)
832 new_criteria = false;
833 if (n_criteria >= allocated_criteria)
834 criteria = x2nrealloc (criteria, &allocated_criteria,
836 criteria[n_criteria++] = (struct spv_criteria) SPV_CRITERIA_INITIALIZER;
839 return &criteria[n_criteria - 1];
843 parse_select (char *arg)
845 bool invert = arg[0] == '^';
848 unsigned classes = 0;
849 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
851 if (!strcmp (arg, "all"))
852 classes = SPV_ALL_CLASSES;
853 else if (!strcmp (arg, "help"))
855 puts (_("The following object classes are supported:"));
856 for (int class = 0; class < SPV_N_CLASSES; class++)
857 printf ("- %s\n", spv_item_class_to_string (class));
862 int class = spv_item_class_from_string (token);
863 if (class == SPV_N_CLASSES)
864 error (1, 0, _("%s: unknown object class (use --select=help "
866 classes |= 1u << class;
870 struct spv_criteria *c = get_criteria ();
871 c->classes = invert ? classes ^ SPV_ALL_CLASSES : classes;
874 static struct spv_criteria_match *
875 get_criteria_match (const char **arg)
877 struct spv_criteria *c = get_criteria ();
878 if ((*arg)[0] == '^')
888 parse_commands (const char *arg)
890 struct spv_criteria_match *cm = get_criteria_match (&arg);
891 string_array_parse (&cm->commands, ss_cstr (arg), ss_cstr (","));
895 parse_subtypes (const char *arg)
897 struct spv_criteria_match *cm = get_criteria_match (&arg);
898 string_array_parse (&cm->subtypes, ss_cstr (arg), ss_cstr (","));
902 parse_labels (const char *arg)
904 struct spv_criteria_match *cm = get_criteria_match (&arg);
905 string_array_parse (&cm->labels, ss_cstr (arg), ss_cstr (","));
909 parse_instances (char *arg)
911 struct spv_criteria *c = get_criteria ();
912 size_t allocated_instances = c->n_instances;
914 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
916 if (c->n_instances >= allocated_instances)
917 c->instances = x2nrealloc (c->instances, &allocated_instances,
918 sizeof *c->instances);
920 c->instances[c->n_instances++] = (!strcmp (token, "last") ? -1
926 parse_nth_commands (char *arg)
928 struct spv_criteria *c = get_criteria ();
929 size_t allocated_commands = c->n_commands;
931 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
933 if (c->n_commands >= allocated_commands)
934 c->commands = x2nrealloc (c->commands, &allocated_commands,
935 sizeof *c->commands);
937 c->commands[c->n_commands++] = atoi (token);
942 parse_members (const char *arg)
944 struct spv_criteria *cm = get_criteria ();
945 string_array_parse (&cm->members, ss_cstr (arg), ss_cstr (","));
949 parse_table_look (const char *arg)
951 pivot_table_look_unref (table_look);
953 char *error_s = spv_table_look_read (arg, &table_look);
955 error (1, 0, "%s", error_s);
959 parse_options (int argc, char *argv[])
965 OPT_MEMBER_NAMES = UCHAR_MAX + 1,
980 static const struct option long_options[] =
982 /* Input selection options. */
983 { "show-hidden", no_argument, NULL, OPT_SHOW_HIDDEN },
984 { "select", required_argument, NULL, OPT_SELECT },
985 { "commands", required_argument, NULL, OPT_COMMANDS },
986 { "nth-commands", required_argument, NULL, OPT_NTH_COMMANDS },
987 { "subtypes", required_argument, NULL, OPT_SUBTYPES },
988 { "labels", required_argument, NULL, OPT_LABELS },
989 { "instances", required_argument, NULL, OPT_INSTANCES },
990 { "members", required_argument, NULL, OPT_MEMBERS },
991 { "errors", no_argument, NULL, OPT_ERRORS },
992 { "or", no_argument, NULL, OPT_OR },
994 /* "dir" command options. */
995 { "member-names", no_argument, NULL, OPT_MEMBER_NAMES },
997 /* "convert" command options. */
998 { "force", no_argument, NULL, 'f' },
999 { "table-look", required_argument, NULL, OPT_TABLE_LOOK },
1001 /* "dump-light-table" command options. */
1002 { "sort", no_argument, NULL, OPT_SORT },
1003 { "raw", no_argument, NULL, OPT_RAW },
1005 { "help", no_argument, NULL, 'h' },
1006 { "version", no_argument, NULL, 'v' },
1008 { NULL, 0, NULL, 0 },
1013 c = getopt_long (argc, argv, "O:hvf", long_options, NULL);
1020 output_driver_parse_option (optarg, &output_options);
1023 case OPT_MEMBER_NAMES:
1024 show_member_names = true;
1027 case OPT_SHOW_HIDDEN:
1028 get_criteria ()->include_hidden = true;
1032 parse_select (optarg);
1036 parse_commands (optarg);
1039 case OPT_NTH_COMMANDS:
1040 parse_nth_commands (optarg);
1044 parse_subtypes (optarg);
1048 parse_labels (optarg);
1052 parse_instances (optarg);
1056 parse_members (optarg);
1060 get_criteria ()->error = true;
1064 new_criteria = true;
1075 case OPT_TABLE_LOOK:
1076 parse_table_look (optarg);
1084 version_etc (stdout, "pspp-output", PACKAGE_NAME, PACKAGE_VERSION,
1085 "Ben Pfaff", "John Darrington", NULL_SENTINEL);
1086 exit (EXIT_SUCCESS);
1090 exit (EXIT_SUCCESS);
1093 exit (EXIT_FAILURE);
1101 struct string s = DS_EMPTY_INITIALIZER;
1102 struct string_set formats = STRING_SET_INITIALIZER(formats);
1103 output_get_supported_formats (&formats);
1105 const struct string_set_node *node;
1106 STRING_SET_FOR_EACH (format, node, &formats)
1108 if (!ds_is_empty (&s))
1109 ds_put_byte (&s, ' ');
1110 ds_put_cstr (&s, format);
1112 string_set_destroy (&formats);
1115 %s, a utility for working with SPSS viewer (.spv) files.\n\
1116 Usage: %s [OPTION]... COMMAND ARG...\n\
1118 The following commands are available:\n\
1119 detect FILE Detect whether FILE is an SPV file.\n\
1120 dir FILE List tables and other items in FILE.\n\
1121 convert SOURCE DEST Convert .spv SOURCE to DEST.\n\
1122 get-table-look SOURCE DEST Copies first selected TableLook into DEST\n\
1123 convert-table-look SOURCE DEST Copies .tlo or .stt SOURCE into DEST\n\
1125 Input selection options for \"dir\" and \"convert\":\n\
1126 --select=CLASS... include only some kinds of objects\n\
1127 --select=help print known object classes\n\
1128 --commands=COMMAND... include only specified COMMANDs\n\
1129 --nth-commands=N... include only the Nth instance of selected commands\n\
1130 --subtypes=SUBTYPE... include only specified SUBTYPEs of output\n\
1131 --labels=LABEL... include only output objects with the given LABELs\n\
1132 --instances=INSTANCE... include only the given object INSTANCEs\n\
1133 --show-hidden include hidden output objects\n\
1134 --or separate two sets of selection options\n\
1136 \"convert\" by default infers the destination's format from its extension.\n\
1137 The known extensions are: %s\n\
1138 The following options override \"convert\" behavior:\n\
1139 -O format=FORMAT set destination format to FORMAT\n\
1140 -O OPTION=VALUE set output option\n\
1141 -f, --force keep output file even given errors\n\
1142 --table-look=FILE override tables' style with TableLook from FILE\n\
1144 --help display this help and exit\n\
1145 --version output version information and exit\n",
1146 program_name, program_name, ds_cstr (&s));