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/>. */
27 #include "data/file-handle-def.h"
28 #include "data/settings.h"
29 #include "libpspp/i18n.h"
30 #include "libpspp/message.h"
31 #include "libpspp/string-map.h"
32 #include "libpspp/string-set.h"
33 #include "output/driver.h"
34 #include "output/group-item.h"
35 #include "output/image-item.h"
36 #include "output/page-setup-item.h"
37 #include "output/pivot-table.h"
38 #include "output/spv/light-binary-parser.h"
39 #include "output/spv/spv-legacy-data.h"
40 #include "output/spv/spv-output.h"
41 #include "output/spv/spv-select.h"
42 #include "output/spv/spv-table-look.h"
43 #include "output/spv/spv.h"
44 #include "output/table-item.h"
45 #include "output/text-item.h"
47 #include "gl/c-ctype.h"
49 #include "gl/progname.h"
50 #include "gl/version-etc.h"
51 #include "gl/xalloc.h"
53 #include <libxml/tree.h>
54 #include <libxml/xpath.h>
55 #include <libxml/xpathInternals.h>
58 #define _(msgid) gettext (msgid)
60 /* -O key=value: Output driver options. */
61 static struct string_map output_options
62 = STRING_MAP_INITIALIZER (output_options);
64 /* --member-name: Include .zip member name in "dir" output. */
65 static bool show_member_names;
67 /* --show-hidden, --select, --commands, ...: Selection criteria. */
68 static struct spv_criteria *criteria;
69 static size_t n_criteria, allocated_criteria;
71 /* --or: Add new element to 'criteria' array. */
72 static bool new_criteria;
74 /* --sort: Sort members under dump-light-table, to make comparisons easier. */
77 /* --raw: Dump raw binary data in dump-light-table. */
80 /* -f, --force: Keep output file even on error. */
83 /* --table-look: TableLook to replace table style for conversion. */
84 static struct pivot_table_look *table_look;
86 /* Number of warnings issued. */
87 static size_t n_warnings;
89 static void usage (void);
90 static void parse_options (int argc, char **argv);
93 dump_item (const struct spv_item *item)
95 if (show_member_names && (item->xml_member || item->bin_member))
97 const char *x = item->xml_member;
98 const char *b = item->bin_member;
100 /* The strings below are not marked for translation because they are only
101 useful to developers. */
103 ? xasprintf ("%s and %s:", x, b)
104 : xasprintf ("%s:", x ? x : b));
105 text_item_submit (text_item_create_nocopy (TEXT_ITEM_TITLE, s,
106 xstrdup ("Member Names")));
109 switch (spv_item_get_type (item))
111 case SPV_ITEM_HEADING:
115 spv_text_submit (item);
119 pivot_table_submit (pivot_table_ref (spv_item_get_table (item)));
130 image_item_submit (image_item_create (cairo_surface_reference (
131 spv_item_get_image (item))));
144 print_item_directory (const struct spv_item *item)
146 for (int i = 1; i < spv_item_get_level (item); i++)
149 enum spv_item_type type = spv_item_get_type (item);
150 printf ("- %s", spv_item_type_to_string (type));
152 const char *label = spv_item_get_label (item);
154 printf (" \"%s\"", label);
156 if (type == SPV_ITEM_TABLE)
158 const struct pivot_table *table = spv_item_get_table (item);
159 char *title = pivot_value_to_string (table->title, table);
160 if (!label || strcmp (title, label))
161 printf (" title \"%s\"", title);
165 const char *command_id = spv_item_get_command_id (item);
167 printf (" command \"%s\"", command_id);
169 const char *subtype = spv_item_get_subtype (item);
170 if (subtype && (!label || strcmp (label, subtype)))
171 printf (" subtype \"%s\"", subtype);
173 if (!spv_item_is_visible (item))
174 printf (" (hidden)");
176 if (show_member_names)
178 const char *members[] = {
185 for (size_t i = 0; i < sizeof members / sizeof *members; i++)
187 printf (" %s %s", n++ == 0 ? "in" : "and", members[i]);
193 run_detect (int argc UNUSED, char **argv)
195 char *err = spv_detect (argv[1]);
197 error (1, 0, "%s", err);
201 run_directory (int argc UNUSED, char **argv)
203 struct spv_reader *spv;
204 char *err = spv_open (argv[1], &spv);
206 error (1, 0, "%s", err);
208 struct spv_item **items;
210 spv_select (spv, criteria, n_criteria, &items, &n_items);
211 for (size_t i = 0; i < n_items; i++)
212 print_item_directory (items[i]);
220 const struct spv_item **nodes;
224 const struct spv_item *stub[N_STUB];
228 swap_nodes (const struct spv_item **a, const struct spv_item **b)
230 const struct spv_item *tmp = *a;
236 get_path (const struct spv_item *item, struct item_path *path)
238 size_t allocated = 10;
239 path->nodes = path->stub;
244 if (path->n >= allocated)
246 if (path->nodes == path->stub)
247 path->nodes = xmemdup (path->stub, sizeof path->stub);
248 path->nodes = x2nrealloc (path->nodes, &allocated,
249 sizeof *path->nodes);
251 path->nodes[path->n++] = item;
255 for (size_t i = 0; i < path->n / 2; i++)
256 swap_nodes (&path->nodes[i], &path->nodes[path->n - i - 1]);
260 free_path (struct item_path *path)
262 if (path && path->nodes != path->stub)
267 dump_heading_transition (const struct spv_item *old,
268 const struct spv_item *new)
273 struct item_path old_path, new_path;
274 get_path (old, &old_path);
275 get_path (new, &new_path);
278 for (; common < old_path.n && common < new_path.n; common++)
279 if (old_path.nodes[common] != new_path.nodes[common])
282 for (size_t i = common; i < old_path.n; i++)
283 group_close_item_submit (group_close_item_create ());
284 for (size_t i = common; i < new_path.n; i++)
285 group_open_item_submit (group_open_item_create (
286 new_path.nodes[i]->command_id,
287 new_path.nodes[i]->label));
289 free_path (&old_path);
290 free_path (&new_path);
294 run_convert (int argc UNUSED, char **argv)
296 struct spv_reader *spv;
297 char *err = spv_open (argv[1], &spv);
299 error (1, 0, "%s", err);
302 spv_item_set_table_look (spv_get_root (spv), table_look);
304 output_engine_push ();
305 output_set_filename (argv[1]);
306 string_map_replace (&output_options, "output-file", argv[2]);
307 struct output_driver *driver = output_driver_create (&output_options);
310 output_driver_register (driver);
312 const struct page_setup *ps = spv_get_page_setup (spv);
314 page_setup_item_submit (page_setup_item_create (ps));
316 struct spv_item **items;
318 spv_select (spv, criteria, n_criteria, &items, &n_items);
319 struct spv_item *prev_heading = spv_get_root (spv);
320 for (size_t i = 0; i < n_items; i++)
322 struct spv_item *heading
323 = items[i]->type == SPV_ITEM_HEADING ? items[i] : items[i]->parent;
324 dump_heading_transition (prev_heading, heading);
325 dump_item (items[i]);
326 prev_heading = heading;
328 dump_heading_transition (prev_heading, spv_get_root (spv));
333 output_engine_pop ();
336 if (n_warnings && !force)
338 /* XXX There could be other files to unlink, e.g. the ascii driver can
339 produce additional files with the charts. */
344 static const struct pivot_table *
345 get_first_table (const struct spv_reader *spv)
347 struct spv_item **items;
349 spv_select (spv, criteria, n_criteria, &items, &n_items);
351 for (size_t i = 0; i < n_items; i++)
352 if (spv_item_is_table (items[i]))
355 return spv_item_get_table (items[i]);
363 run_get_table_look (int argc UNUSED, char **argv)
365 struct pivot_table_look *look;
366 if (strcmp (argv[1], "-"))
368 struct spv_reader *spv;
369 char *err = spv_open (argv[1], &spv);
371 error (1, 0, "%s", err);
373 const struct pivot_table *table = get_first_table (spv);
375 error (1, 0, "%s: no tables found", argv[1]);
377 look = pivot_table_look_ref (pivot_table_get_look (table));
382 look = pivot_table_look_ref (pivot_table_look_builtin_default ());
384 char *err = spv_table_look_write (argv[2], look);
386 error (1, 0, "%s", err);
388 pivot_table_look_unref (look);
392 run_convert_table_look (int argc UNUSED, char **argv)
394 struct pivot_table_look *look;
395 char *err = spv_table_look_read (argv[1], &look);
397 error (1, 0, "%s", err);
399 err = spv_table_look_write (argv[2], look);
401 error (1, 0, "%s", err);
403 pivot_table_look_unref (look);
408 run_dump (int argc UNUSED, char **argv)
410 struct spv_reader *spv;
411 char *err = spv_open (argv[1], &spv);
413 error (1, 0, "%s", err);
415 struct spv_item **items;
417 spv_select (spv, criteria, n_criteria, &items, &n_items);
418 for (size_t i = 0; i < n_items; i++)
419 if (items[i]->type == SPV_ITEM_TABLE)
421 pivot_table_dump (spv_item_get_table (items[i]), 0);
430 compare_borders (const void *a_, const void *b_)
432 const struct spvlb_border *const *ap = a_;
433 const struct spvlb_border *const *bp = b_;
434 uint32_t a = (*ap)->border_type;
435 uint32_t b = (*bp)->border_type;
437 return a < b ? -1 : a > b;
441 compare_cells (const void *a_, const void *b_)
443 const struct spvlb_cell *const *ap = a_;
444 const struct spvlb_cell *const *bp = b_;
445 uint64_t a = (*ap)->index;
446 uint64_t b = (*bp)->index;
448 return a < b ? -1 : a > b;
452 run_dump_light_table (int argc UNUSED, char **argv)
454 if (raw && isatty (STDOUT_FILENO))
455 error (1, 0, "not writing binary data to tty");
457 struct spv_reader *spv;
458 char *err = spv_open (argv[1], &spv);
460 error (1, 0, "%s", err);
462 struct spv_item **items;
464 spv_select (spv, criteria, n_criteria, &items, &n_items);
465 for (size_t i = 0; i < n_items; i++)
467 if (!spv_item_is_light_table (items[i]))
475 error = spv_item_get_raw_light_table (items[i], &data, &size);
478 fwrite (data, size, 1, stdout);
484 struct spvlb_table *table;
485 error = spv_item_get_light_table (items[i], &table);
490 qsort (table->borders->borders, table->borders->n_borders,
491 sizeof *table->borders->borders, compare_borders);
492 qsort (table->cells->cells, table->cells->n_cells,
493 sizeof *table->cells->cells, compare_cells);
495 spvlb_print_table (items[i]->bin_member, 0, table);
496 spvlb_free_table (table);
501 msg (ME, "%s", error);
512 run_dump_legacy_data (int argc UNUSED, char **argv)
514 struct spv_reader *spv;
515 char *err = spv_open (argv[1], &spv);
517 error (1, 0, "%s", err);
519 struct spv_item **items;
521 spv_select (spv, criteria, n_criteria, &items, &n_items);
522 for (size_t i = 0; i < n_items; i++)
523 if (spv_item_is_legacy_table (items[i]))
525 struct spv_data data;
531 error = spv_item_get_raw_legacy_data (items[i], &data, &size);
534 fwrite (data, size, 1, stdout);
540 error = spv_item_get_legacy_data (items[i], &data);
543 printf ("%s:\n", items[i]->bin_member);
544 spv_data_dump (&data, stdout);
545 spv_data_uninit (&data);
552 msg (ME, "%s", error);
561 /* This is really bogus.
563 XPath doesn't have any notion of a default XML namespace, but all of the
564 elements in the documents we're interested in have a namespace. Thus, we'd
565 need to require the XPath expressions to have a namespace on every single
566 element: vis:sourceVariable, vis:graph, and so on. That's a pain. So,
567 instead, we remove the default namespace from everyplace it occurs. XPath
568 does support the null namespace, so this allows sourceVariable, graph,
571 See http://plasmasturm.org/log/259/ and
572 https://mail.gnome.org/archives/xml/2003-April/msg00144.html for more
575 remove_default_xml_namespace (xmlNode *node)
577 if (node->ns && !node->ns->prefix)
580 for (xmlNode *child = node->children; child; child = child->next)
581 remove_default_xml_namespace (child);
585 register_ns (xmlXPathContext *ctx, const char *prefix, const char *uri)
587 xmlXPathRegisterNs (ctx, CHAR_CAST (xmlChar *, prefix),
588 CHAR_CAST (xmlChar *, uri));
591 static xmlXPathContext *
592 create_xpath_context (xmlDoc *doc)
594 xmlXPathContext *ctx = xmlXPathNewContext (doc);
595 register_ns (ctx, "vgr", "http://xml.spss.com/spss/viewer/viewer-graph");
596 register_ns (ctx, "vizml", "http://xml.spss.com/visualization");
597 register_ns (ctx, "vmd", "http://xml.spss.com/spss/viewer/viewer-model");
598 register_ns (ctx, "vps", "http://xml.spss.com/spss/viewer/viewer-pagesetup");
599 register_ns (ctx, "vst", "http://xml.spss.com/spss/viewer/viewer-style");
600 register_ns (ctx, "vtb", "http://xml.spss.com/spss/viewer/viewer-table");
601 register_ns (ctx, "vtl", "http://xml.spss.com/spss/viewer/table-looks");
602 register_ns (ctx, "vtt", "http://xml.spss.com/spss/viewer/viewer-treemodel");
603 register_ns (ctx, "vtx", "http://xml.spss.com/spss/viewer/viewer-text");
604 register_ns (ctx, "xsi", "http://www.w3.org/2001/XMLSchema-instance");
609 dump_xml (int argc, char **argv, const char *member_name,
610 char *error_s, xmlDoc *doc)
616 printf ("<!-- %s -->\n", member_name);
617 xmlElemDump (stdout, NULL, xmlDocGetRootElement (doc));
622 bool any_results = false;
624 remove_default_xml_namespace (xmlDocGetRootElement (doc));
625 for (int i = 2; i < argc; i++)
627 xmlXPathContext *xpath_ctx = create_xpath_context (doc);
628 xmlXPathSetContextNode (xmlDocGetRootElement (doc),
630 xmlXPathObject *xpath_obj = xmlXPathEvalExpression(
631 CHAR_CAST (xmlChar *, argv[i]), xpath_ctx);
633 error (1, 0, _("%s: invalid XPath expression"), argv[i]);
635 const xmlNodeSet *nodes = xpath_obj->nodesetval;
636 if (nodes && nodes->nodeNr > 0)
640 printf ("<!-- %s -->\n", member_name);
643 for (size_t j = 0; j < nodes->nodeNr; j++)
645 xmlElemDump (stdout, doc, nodes->nodeTab[j]);
650 xmlXPathFreeObject (xpath_obj);
651 xmlXPathFreeContext (xpath_ctx);
660 printf ("<!-- %s -->\n", member_name);
661 msg (ME, "%s", error_s);
667 run_dump_legacy_table (int argc, char **argv)
669 struct spv_reader *spv;
670 char *err = spv_open (argv[1], &spv);
672 error (1, 0, "%s", err);
674 struct spv_item **items;
676 spv_select (spv, criteria, n_criteria, &items, &n_items);
677 for (size_t i = 0; i < n_items; i++)
678 if (spv_item_is_legacy_table (items[i]))
681 char *error_s = spv_item_get_legacy_table (items[i], &doc);
682 dump_xml (argc, argv, items[i]->xml_member, error_s, doc);
690 run_dump_structure (int argc, char **argv)
692 struct spv_reader *spv;
693 char *err = spv_open (argv[1], &spv);
695 error (1, 0, "%s", err);
697 struct spv_item **items;
699 spv_select (spv, criteria, n_criteria, &items, &n_items);
700 const char *last_structure_member = NULL;
701 for (size_t i = 0; i < n_items; i++)
702 if (!last_structure_member || strcmp (items[i]->structure_member,
703 last_structure_member))
705 last_structure_member = items[i]->structure_member;
708 char *error_s = spv_item_get_structure (items[i], &doc);
709 dump_xml (argc, argv, items[i]->structure_member, error_s, doc);
717 run_is_legacy (int argc UNUSED, char **argv)
719 struct spv_reader *spv;
720 char *err = spv_open (argv[1], &spv);
722 error (1, 0, "%s", err);
724 bool is_legacy = false;
726 struct spv_item **items;
728 spv_select (spv, criteria, n_criteria, &items, &n_items);
729 for (size_t i = 0; i < n_items; i++)
730 if (spv_item_is_legacy_table (items[i]))
739 exit (is_legacy ? EXIT_SUCCESS : EXIT_FAILURE);
745 int min_args, max_args;
746 void (*run) (int argc, char **argv);
749 static const struct command commands[] =
751 { "detect", 1, 1, run_detect },
752 { "dir", 1, 1, run_directory },
753 { "convert", 2, 2, run_convert },
754 { "get-table-look", 2, 2, run_get_table_look },
755 { "convert-table-look", 2, 2, run_convert_table_look },
757 /* Undocumented commands. */
758 { "dump", 1, 1, run_dump },
759 { "dump-light-table", 1, 1, run_dump_light_table },
760 { "dump-legacy-data", 1, 1, run_dump_legacy_data },
761 { "dump-legacy-table", 1, INT_MAX, run_dump_legacy_table },
762 { "dump-structure", 1, INT_MAX, run_dump_structure },
763 { "is-legacy", 1, 1, run_is_legacy },
765 static const int n_commands = sizeof commands / sizeof *commands;
767 static const struct command *
768 find_command (const char *name)
770 for (size_t i = 0; i < n_commands; i++)
772 const struct command *c = &commands[i];
773 if (!strcmp (name, c->name))
780 emit_msg (const struct msg *m, void *aux UNUSED)
782 if (m->severity == MSG_S_ERROR || m->severity == MSG_S_WARNING)
785 char *s = msg_to_string (m);
786 fprintf (stderr, "%s\n", s);
791 main (int argc, char **argv)
793 set_program_name (argv[0]);
794 msg_set_handler (emit_msg, NULL);
798 parse_options (argc, argv);
804 error (1, 0, _("missing command name (use --help for help)"));
806 const struct command *c = find_command (argv[0]);
808 error (1, 0, _("unknown command \"%s\" (use --help for help)"), argv[0]);
810 int n_args = argc - 1;
811 if (n_args < c->min_args || n_args > c->max_args)
813 if (c->min_args == c->max_args)
816 ngettext ("\"%s\" command takes exactly %d argument",
817 "\"%s\" command takes exactly %d arguments",
818 c->min_args), c->name, c->min_args);
820 else if (c->max_args == INT_MAX)
823 ngettext ("\"%s\" command requires at least %d argument",
824 "\"%s\" command requires at least %d arguments",
825 c->min_args), c->name, c->min_args);
830 _("\"%s\" command requires between %d and %d arguments"),
831 c->name, c->min_args, c->max_args);
837 pivot_table_look_unref (table_look);
840 return n_warnings ? EXIT_FAILURE : EXIT_SUCCESS;
843 static struct spv_criteria *
846 if (!n_criteria || new_criteria)
848 new_criteria = false;
849 if (n_criteria >= allocated_criteria)
850 criteria = x2nrealloc (criteria, &allocated_criteria,
852 criteria[n_criteria++] = (struct spv_criteria) SPV_CRITERIA_INITIALIZER;
855 return &criteria[n_criteria - 1];
859 parse_select (char *arg)
861 bool invert = arg[0] == '^';
864 unsigned classes = 0;
865 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
867 if (!strcmp (arg, "all"))
868 classes = SPV_ALL_CLASSES;
869 else if (!strcmp (arg, "help"))
871 puts (_("The following object classes are supported:"));
872 for (int class = 0; class < SPV_N_CLASSES; class++)
873 printf ("- %s\n", spv_item_class_to_string (class));
878 int class = spv_item_class_from_string (token);
879 if (class == SPV_N_CLASSES)
880 error (1, 0, _("%s: unknown object class (use --select=help "
882 classes |= 1u << class;
886 struct spv_criteria *c = get_criteria ();
887 c->classes = invert ? classes ^ SPV_ALL_CLASSES : classes;
890 static struct spv_criteria_match *
891 get_criteria_match (const char **arg)
893 struct spv_criteria *c = get_criteria ();
894 if ((*arg)[0] == '^')
904 parse_commands (const char *arg)
906 struct spv_criteria_match *cm = get_criteria_match (&arg);
907 string_array_parse (&cm->commands, ss_cstr (arg), ss_cstr (","));
911 parse_subtypes (const char *arg)
913 struct spv_criteria_match *cm = get_criteria_match (&arg);
914 string_array_parse (&cm->subtypes, ss_cstr (arg), ss_cstr (","));
918 parse_labels (const char *arg)
920 struct spv_criteria_match *cm = get_criteria_match (&arg);
921 string_array_parse (&cm->labels, ss_cstr (arg), ss_cstr (","));
925 parse_instances (char *arg)
927 struct spv_criteria *c = get_criteria ();
928 size_t allocated_instances = c->n_instances;
930 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
932 if (c->n_instances >= allocated_instances)
933 c->instances = x2nrealloc (c->instances, &allocated_instances,
934 sizeof *c->instances);
936 c->instances[c->n_instances++] = (!strcmp (token, "last") ? -1
942 parse_nth_commands (char *arg)
944 struct spv_criteria *c = get_criteria ();
945 size_t allocated_commands = c->n_commands;
947 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
949 if (c->n_commands >= allocated_commands)
950 c->commands = x2nrealloc (c->commands, &allocated_commands,
951 sizeof *c->commands);
953 c->commands[c->n_commands++] = atoi (token);
958 parse_members (const char *arg)
960 struct spv_criteria *cm = get_criteria ();
961 string_array_parse (&cm->members, ss_cstr (arg), ss_cstr (","));
965 parse_table_look (const char *arg)
967 pivot_table_look_unref (table_look);
969 char *error_s = spv_table_look_read (arg, &table_look);
971 error (1, 0, "%s", error_s);
975 parse_options (int argc, char *argv[])
981 OPT_MEMBER_NAMES = UCHAR_MAX + 1,
996 static const struct option long_options[] =
998 /* Input selection options. */
999 { "show-hidden", no_argument, NULL, OPT_SHOW_HIDDEN },
1000 { "select", required_argument, NULL, OPT_SELECT },
1001 { "commands", required_argument, NULL, OPT_COMMANDS },
1002 { "nth-commands", required_argument, NULL, OPT_NTH_COMMANDS },
1003 { "subtypes", required_argument, NULL, OPT_SUBTYPES },
1004 { "labels", required_argument, NULL, OPT_LABELS },
1005 { "instances", required_argument, NULL, OPT_INSTANCES },
1006 { "members", required_argument, NULL, OPT_MEMBERS },
1007 { "errors", no_argument, NULL, OPT_ERRORS },
1008 { "or", no_argument, NULL, OPT_OR },
1010 /* "dir" command options. */
1011 { "member-names", no_argument, NULL, OPT_MEMBER_NAMES },
1013 /* "convert" command options. */
1014 { "force", no_argument, NULL, 'f' },
1015 { "table-look", required_argument, NULL, OPT_TABLE_LOOK },
1017 /* "dump-light-table" command options. */
1018 { "sort", no_argument, NULL, OPT_SORT },
1019 { "raw", no_argument, NULL, OPT_RAW },
1021 { "help", no_argument, NULL, 'h' },
1022 { "version", no_argument, NULL, 'v' },
1024 { NULL, 0, NULL, 0 },
1029 c = getopt_long (argc, argv, "O:hvf", long_options, NULL);
1036 output_driver_parse_option (optarg, &output_options);
1039 case OPT_MEMBER_NAMES:
1040 show_member_names = true;
1043 case OPT_SHOW_HIDDEN:
1044 get_criteria ()->include_hidden = true;
1048 parse_select (optarg);
1052 parse_commands (optarg);
1055 case OPT_NTH_COMMANDS:
1056 parse_nth_commands (optarg);
1060 parse_subtypes (optarg);
1064 parse_labels (optarg);
1068 parse_instances (optarg);
1072 parse_members (optarg);
1076 get_criteria ()->error = true;
1080 new_criteria = true;
1091 case OPT_TABLE_LOOK:
1092 parse_table_look (optarg);
1100 version_etc (stdout, "pspp-output", PACKAGE_NAME, PACKAGE_VERSION,
1101 "Ben Pfaff", "John Darrington", NULL_SENTINEL);
1102 exit (EXIT_SUCCESS);
1106 exit (EXIT_SUCCESS);
1109 exit (EXIT_FAILURE);
1117 struct string s = DS_EMPTY_INITIALIZER;
1118 struct string_set formats = STRING_SET_INITIALIZER(formats);
1119 output_get_supported_formats (&formats);
1121 const struct string_set_node *node;
1122 STRING_SET_FOR_EACH (format, node, &formats)
1124 if (!ds_is_empty (&s))
1125 ds_put_byte (&s, ' ');
1126 ds_put_cstr (&s, format);
1128 string_set_destroy (&formats);
1131 %s, a utility for working with SPSS viewer (.spv) files.\n\
1132 Usage: %s [OPTION]... COMMAND ARG...\n\
1134 The following commands are available:\n\
1135 detect FILE Detect whether FILE is an SPV file.\n\
1136 dir FILE List tables and other items in FILE.\n\
1137 convert SOURCE DEST Convert .spv SOURCE to DEST.\n\
1138 get-table-look SOURCE DEST Copies first selected TableLook into DEST\n\
1139 convert-table-look SOURCE DEST Copies .tlo or .stt SOURCE into DEST\n\
1141 Input selection options for \"dir\" and \"convert\":\n\
1142 --select=CLASS... include only some kinds of objects\n\
1143 --select=help print known object classes\n\
1144 --commands=COMMAND... include only specified COMMANDs\n\
1145 --nth-commands=N... include only the Nth instance of selected commands\n\
1146 --subtypes=SUBTYPE... include only specified SUBTYPEs of output\n\
1147 --labels=LABEL... include only output objects with the given LABELs\n\
1148 --instances=INSTANCE... include only the given object INSTANCEs\n\
1149 --show-hidden include hidden output objects\n\
1150 --or separate two sets of selection options\n\
1152 \"convert\" by default infers the destination's format from its extension.\n\
1153 The known extensions are: %s\n\
1154 The following options override \"convert\" behavior:\n\
1155 -O format=FORMAT set destination format to FORMAT\n\
1156 -O OPTION=VALUE set output option\n\
1157 -f, --force keep output file even given errors\n\
1158 --table-look=FILE override tables' style with TableLook from FILE\n\
1160 --help display this help and exit\n\
1161 --version output version information and exit\n",
1162 program_name, program_name, ds_cstr (&s));