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 spv_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. */
329 run_dump (int argc UNUSED, char **argv)
331 struct spv_reader *spv;
332 char *err = spv_open (argv[1], &spv);
334 error (1, 0, "%s", err);
336 struct spv_item **items;
338 spv_select (spv, criteria, n_criteria, &items, &n_items);
339 for (size_t i = 0; i < n_items; i++)
340 if (items[i]->type == SPV_ITEM_TABLE)
342 pivot_table_dump (spv_item_get_table (items[i]), 0);
351 compare_borders (const void *a_, const void *b_)
353 const struct spvlb_border *const *ap = a_;
354 const struct spvlb_border *const *bp = b_;
355 uint32_t a = (*ap)->border_type;
356 uint32_t b = (*bp)->border_type;
358 return a < b ? -1 : a > b;
362 compare_cells (const void *a_, const void *b_)
364 const struct spvlb_cell *const *ap = a_;
365 const struct spvlb_cell *const *bp = b_;
366 uint64_t a = (*ap)->index;
367 uint64_t b = (*bp)->index;
369 return a < b ? -1 : a > b;
373 run_dump_light_table (int argc UNUSED, char **argv)
375 if (raw && isatty (STDOUT_FILENO))
376 error (1, 0, "not writing binary data to tty");
378 struct spv_reader *spv;
379 char *err = spv_open (argv[1], &spv);
381 error (1, 0, "%s", err);
383 struct spv_item **items;
385 spv_select (spv, criteria, n_criteria, &items, &n_items);
386 for (size_t i = 0; i < n_items; i++)
388 if (!spv_item_is_light_table (items[i]))
396 error = spv_item_get_raw_light_table (items[i], &data, &size);
399 fwrite (data, size, 1, stdout);
405 struct spvlb_table *table;
406 error = spv_item_get_light_table (items[i], &table);
411 qsort (table->borders->borders, table->borders->n_borders,
412 sizeof *table->borders->borders, compare_borders);
413 qsort (table->cells->cells, table->cells->n_cells,
414 sizeof *table->cells->cells, compare_cells);
416 spvlb_print_table (items[i]->bin_member, 0, table);
417 spvlb_free_table (table);
422 msg (ME, "%s", error);
433 run_dump_legacy_data (int argc UNUSED, char **argv)
435 struct spv_reader *spv;
436 char *err = spv_open (argv[1], &spv);
438 error (1, 0, "%s", err);
440 struct spv_item **items;
442 spv_select (spv, criteria, n_criteria, &items, &n_items);
443 for (size_t i = 0; i < n_items; i++)
444 if (spv_item_is_legacy_table (items[i]))
446 struct spv_data data;
452 error = spv_item_get_raw_legacy_data (items[i], &data, &size);
455 fwrite (data, size, 1, stdout);
461 error = spv_item_get_legacy_data (items[i], &data);
464 printf ("%s:\n", items[i]->bin_member);
465 spv_data_dump (&data, stdout);
466 spv_data_uninit (&data);
473 msg (ME, "%s", error);
482 /* This is really bogus.
484 XPath doesn't have any notion of a default XML namespace, but all of the
485 elements in the documents we're interested in have a namespace. Thus, we'd
486 need to require the XPath expressions to have a namespace on every single
487 element: vis:sourceVariable, vis:graph, and so on. That's a pain. So,
488 instead, we remove the default namespace from everyplace it occurs. XPath
489 does support the null namespace, so this allows sourceVariable, graph,
492 See http://plasmasturm.org/log/259/ and
493 https://mail.gnome.org/archives/xml/2003-April/msg00144.html for more
496 remove_default_xml_namespace (xmlNode *node)
498 if (node->ns && !node->ns->prefix)
501 for (xmlNode *child = node->children; child; child = child->next)
502 remove_default_xml_namespace (child);
506 register_ns (xmlXPathContext *ctx, const char *prefix, const char *uri)
508 xmlXPathRegisterNs (ctx, CHAR_CAST (xmlChar *, prefix),
509 CHAR_CAST (xmlChar *, uri));
512 static xmlXPathContext *
513 create_xpath_context (xmlDoc *doc)
515 xmlXPathContext *ctx = xmlXPathNewContext (doc);
516 register_ns (ctx, "vgr", "http://xml.spss.com/spss/viewer/viewer-graph");
517 register_ns (ctx, "vizml", "http://xml.spss.com/visualization");
518 register_ns (ctx, "vmd", "http://xml.spss.com/spss/viewer/viewer-model");
519 register_ns (ctx, "vps", "http://xml.spss.com/spss/viewer/viewer-pagesetup");
520 register_ns (ctx, "vst", "http://xml.spss.com/spss/viewer/viewer-style");
521 register_ns (ctx, "vtb", "http://xml.spss.com/spss/viewer/viewer-table");
522 register_ns (ctx, "vtl", "http://xml.spss.com/spss/viewer/table-looks");
523 register_ns (ctx, "vtt", "http://xml.spss.com/spss/viewer/viewer-treemodel");
524 register_ns (ctx, "vtx", "http://xml.spss.com/spss/viewer/viewer-text");
525 register_ns (ctx, "xsi", "http://www.w3.org/2001/XMLSchema-instance");
530 dump_xml (int argc, char **argv, const char *member_name,
531 char *error_s, xmlDoc *doc)
537 printf ("<!-- %s -->\n", member_name);
538 xmlElemDump (stdout, NULL, xmlDocGetRootElement (doc));
543 bool any_results = false;
545 remove_default_xml_namespace (xmlDocGetRootElement (doc));
546 for (int i = 2; i < argc; i++)
548 xmlXPathContext *xpath_ctx = create_xpath_context (doc);
549 xmlXPathSetContextNode (xmlDocGetRootElement (doc),
551 xmlXPathObject *xpath_obj = xmlXPathEvalExpression(
552 CHAR_CAST (xmlChar *, argv[i]), xpath_ctx);
554 error (1, 0, _("%s: invalid XPath expression"), argv[i]);
556 const xmlNodeSet *nodes = xpath_obj->nodesetval;
557 if (nodes && nodes->nodeNr > 0)
561 printf ("<!-- %s -->\n", member_name);
564 for (size_t j = 0; j < nodes->nodeNr; j++)
566 xmlElemDump (stdout, doc, nodes->nodeTab[j]);
571 xmlXPathFreeObject (xpath_obj);
572 xmlXPathFreeContext (xpath_ctx);
581 printf ("<!-- %s -->\n", member_name);
582 msg (ME, "%s", error_s);
588 run_dump_legacy_table (int argc, char **argv)
590 struct spv_reader *spv;
591 char *err = spv_open (argv[1], &spv);
593 error (1, 0, "%s", err);
595 struct spv_item **items;
597 spv_select (spv, criteria, n_criteria, &items, &n_items);
598 for (size_t i = 0; i < n_items; i++)
599 if (spv_item_is_legacy_table (items[i]))
602 char *error_s = spv_item_get_legacy_table (items[i], &doc);
603 dump_xml (argc, argv, items[i]->xml_member, error_s, doc);
611 run_dump_structure (int argc, char **argv)
613 struct spv_reader *spv;
614 char *err = spv_open (argv[1], &spv);
616 error (1, 0, "%s", err);
618 struct spv_item **items;
620 spv_select (spv, criteria, n_criteria, &items, &n_items);
621 const char *last_structure_member = NULL;
622 for (size_t i = 0; i < n_items; i++)
623 if (!last_structure_member || strcmp (items[i]->structure_member,
624 last_structure_member))
626 last_structure_member = items[i]->structure_member;
629 char *error_s = spv_item_get_structure (items[i], &doc);
630 dump_xml (argc, argv, items[i]->structure_member, error_s, doc);
638 run_is_legacy (int argc UNUSED, char **argv)
640 struct spv_reader *spv;
641 char *err = spv_open (argv[1], &spv);
643 error (1, 0, "%s", err);
645 bool is_legacy = false;
647 struct spv_item **items;
649 spv_select (spv, criteria, n_criteria, &items, &n_items);
650 for (size_t i = 0; i < n_items; i++)
651 if (spv_item_is_legacy_table (items[i]))
660 exit (is_legacy ? EXIT_SUCCESS : EXIT_FAILURE);
666 int min_args, max_args;
667 void (*run) (int argc, char **argv);
670 static const struct command commands[] =
672 { "detect", 1, 1, run_detect },
673 { "dir", 1, 1, run_directory },
674 { "convert", 2, 2, run_convert },
676 /* Undocumented commands. */
677 { "dump", 1, 1, run_dump },
678 { "dump-light-table", 1, 1, run_dump_light_table },
679 { "dump-legacy-data", 1, 1, run_dump_legacy_data },
680 { "dump-legacy-table", 1, INT_MAX, run_dump_legacy_table },
681 { "dump-structure", 1, INT_MAX, run_dump_structure },
682 { "is-legacy", 1, 1, run_is_legacy },
684 static const int n_commands = sizeof commands / sizeof *commands;
686 static const struct command *
687 find_command (const char *name)
689 for (size_t i = 0; i < n_commands; i++)
691 const struct command *c = &commands[i];
692 if (!strcmp (name, c->name))
699 emit_msg (const struct msg *m, void *aux UNUSED)
701 if (m->severity == MSG_S_ERROR || m->severity == MSG_S_WARNING)
704 char *s = msg_to_string (m);
705 fprintf (stderr, "%s\n", s);
710 main (int argc, char **argv)
712 set_program_name (argv[0]);
713 msg_set_handler (emit_msg, NULL);
717 parse_options (argc, argv);
723 error (1, 0, _("missing command name (use --help for help)"));
725 const struct command *c = find_command (argv[0]);
727 error (1, 0, _("unknown command \"%s\" (use --help for help)"), argv[0]);
729 int n_args = argc - 1;
730 if (n_args < c->min_args || n_args > c->max_args)
732 if (c->min_args == c->max_args)
735 ngettext ("\"%s\" command takes exactly %d argument",
736 "\"%s\" command takes exactly %d arguments",
737 c->min_args), c->name, c->min_args);
739 else if (c->max_args == INT_MAX)
742 ngettext ("\"%s\" command requires at least %d argument",
743 "\"%s\" command requires at least %d arguments",
744 c->min_args), c->name, c->min_args);
749 _("\"%s\" command requires between %d and %d arguments"),
750 c->name, c->min_args, c->max_args);
756 spv_table_look_destroy (table_look);
759 return n_warnings ? EXIT_FAILURE : EXIT_SUCCESS;
762 static struct spv_criteria *
765 if (!n_criteria || new_criteria)
767 new_criteria = false;
768 if (n_criteria >= allocated_criteria)
769 criteria = x2nrealloc (criteria, &allocated_criteria,
771 criteria[n_criteria++] = (struct spv_criteria) SPV_CRITERIA_INITIALIZER;
774 return &criteria[n_criteria - 1];
778 parse_select (char *arg)
780 bool invert = arg[0] == '^';
783 unsigned classes = 0;
784 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
786 if (!strcmp (arg, "all"))
787 classes = SPV_ALL_CLASSES;
788 else if (!strcmp (arg, "help"))
790 puts (_("The following object classes are supported:"));
791 for (int class = 0; class < SPV_N_CLASSES; class++)
792 printf ("- %s\n", spv_item_class_to_string (class));
797 int class = spv_item_class_from_string (token);
798 if (class == SPV_N_CLASSES)
799 error (1, 0, _("%s: unknown object class (use --select=help "
801 classes |= 1u << class;
805 struct spv_criteria *c = get_criteria ();
806 c->classes = invert ? classes ^ SPV_ALL_CLASSES : classes;
809 static struct spv_criteria_match *
810 get_criteria_match (const char **arg)
812 struct spv_criteria *c = get_criteria ();
813 if ((*arg)[0] == '^')
823 parse_commands (const char *arg)
825 struct spv_criteria_match *cm = get_criteria_match (&arg);
826 string_array_parse (&cm->commands, ss_cstr (arg), ss_cstr (","));
830 parse_subtypes (const char *arg)
832 struct spv_criteria_match *cm = get_criteria_match (&arg);
833 string_array_parse (&cm->subtypes, ss_cstr (arg), ss_cstr (","));
837 parse_labels (const char *arg)
839 struct spv_criteria_match *cm = get_criteria_match (&arg);
840 string_array_parse (&cm->labels, ss_cstr (arg), ss_cstr (","));
844 parse_instances (char *arg)
846 struct spv_criteria *c = get_criteria ();
847 size_t allocated_instances = c->n_instances;
849 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
851 if (c->n_instances >= allocated_instances)
852 c->instances = x2nrealloc (c->instances, &allocated_instances,
853 sizeof *c->instances);
855 c->instances[c->n_instances++] = (!strcmp (token, "last") ? -1
861 parse_nth_commands (char *arg)
863 struct spv_criteria *c = get_criteria ();
864 size_t allocated_commands = c->n_commands;
866 for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
868 if (c->n_commands >= allocated_commands)
869 c->commands = x2nrealloc (c->commands, &allocated_commands,
870 sizeof *c->commands);
872 c->commands[c->n_commands++] = atoi (token);
877 parse_members (const char *arg)
879 struct spv_criteria *cm = get_criteria ();
880 string_array_parse (&cm->members, ss_cstr (arg), ss_cstr (","));
884 parse_table_look (const char *arg)
886 spv_table_look_destroy (table_look);
887 char *error_s = spv_table_look_read (arg, &table_look);
889 error (1, 0, "%s", error_s);
893 parse_options (int argc, char *argv[])
899 OPT_MEMBER_NAMES = UCHAR_MAX + 1,
914 static const struct option long_options[] =
916 /* Input selection options. */
917 { "show-hidden", no_argument, NULL, OPT_SHOW_HIDDEN },
918 { "select", required_argument, NULL, OPT_SELECT },
919 { "commands", required_argument, NULL, OPT_COMMANDS },
920 { "nth-commands", required_argument, NULL, OPT_NTH_COMMANDS },
921 { "subtypes", required_argument, NULL, OPT_SUBTYPES },
922 { "labels", required_argument, NULL, OPT_LABELS },
923 { "instances", required_argument, NULL, OPT_INSTANCES },
924 { "members", required_argument, NULL, OPT_MEMBERS },
925 { "errors", no_argument, NULL, OPT_ERRORS },
926 { "or", no_argument, NULL, OPT_OR },
928 /* "dir" command options. */
929 { "member-names", no_argument, NULL, OPT_MEMBER_NAMES },
931 /* "convert" command options. */
932 { "force", no_argument, NULL, 'f' },
933 { "table-look", required_argument, NULL, OPT_TABLE_LOOK },
935 /* "dump-light-table" command options. */
936 { "sort", no_argument, NULL, OPT_SORT },
937 { "raw", no_argument, NULL, OPT_RAW },
939 { "help", no_argument, NULL, 'h' },
940 { "version", no_argument, NULL, 'v' },
942 { NULL, 0, NULL, 0 },
947 c = getopt_long (argc, argv, "O:hvf", long_options, NULL);
954 output_driver_parse_option (optarg, &output_options);
957 case OPT_MEMBER_NAMES:
958 show_member_names = true;
961 case OPT_SHOW_HIDDEN:
962 get_criteria ()->include_hidden = true;
966 parse_select (optarg);
970 parse_commands (optarg);
973 case OPT_NTH_COMMANDS:
974 parse_nth_commands (optarg);
978 parse_subtypes (optarg);
982 parse_labels (optarg);
986 parse_instances (optarg);
990 parse_members (optarg);
994 get_criteria ()->error = true;
1009 case OPT_TABLE_LOOK:
1010 parse_table_look (optarg);
1018 version_etc (stdout, "pspp-output", PACKAGE_NAME, PACKAGE_VERSION,
1019 "Ben Pfaff", "John Darrington", NULL_SENTINEL);
1020 exit (EXIT_SUCCESS);
1024 exit (EXIT_SUCCESS);
1027 exit (EXIT_FAILURE);
1035 struct string s = DS_EMPTY_INITIALIZER;
1036 struct string_set formats = STRING_SET_INITIALIZER(formats);
1037 output_get_supported_formats (&formats);
1039 const struct string_set_node *node;
1040 STRING_SET_FOR_EACH (format, node, &formats)
1042 if (!ds_is_empty (&s))
1043 ds_put_byte (&s, ' ');
1044 ds_put_cstr (&s, format);
1046 string_set_destroy (&formats);
1049 %s, a utility for working with SPSS viewer (.spv) files.\n\
1050 Usage: %s [OPTION]... COMMAND ARG...\n\
1052 The following commands are available:\n\
1053 detect FILE Detect whether FILE is an SPV file.\n\
1054 dir FILE List tables and other items in FILE.\n\
1055 convert SOURCE DEST Convert .spv SOURCE to DEST.\n\
1057 Input selection options for \"dir\" and \"convert\":\n\
1058 --select=CLASS... include only some kinds of objects\n\
1059 --select=help print known object classes\n\
1060 --commands=COMMAND... include only specified COMMANDs\n\
1061 --nth-commands=N... include only the Nth instance of selected commands\n\
1062 --subtypes=SUBTYPE... include only specified SUBTYPEs of output\n\
1063 --labels=LABEL... include only output objects with the given LABELs\n\
1064 --instances=INSTANCE... include only the given object INSTANCEs\n\
1065 --show-hidden include hidden output objects\n\
1066 --or separate two sets of selection options\n\
1068 \"convert\" by default infers the destination's format from its extension.\n\
1069 The known extensions are: %s\n\
1070 The following options override \"convert\" behavior:\n\
1071 -O format=FORMAT set destination format to FORMAT\n\
1072 -O OPTION=VALUE set output option\n\
1073 -f, --force keep output file even given errors\n\
1074 --table-look=FILE override tables' style with TableLook from FILE\n\
1076 --help display this help and exit\n\
1077 --version output version information and exit\n",
1078 program_name, program_name, ds_cstr (&s));