The new interface provides the user with a preview of the data to be imported
and interactive methods to select the desired ranges.
+ * The pspp-output utility has a new --nth-commands option.
+
Changes from 1.4.0 to 1.4.1:
* Bug fixes.
is, the table titles). Labels are affected by the output language,
variable names and labels, split file settings, and other factors.
+@item --nth-commands=@var{n}@dots{}
+Include only objects from the @var{n}th command that matches
+@option{--command} (or the @var{n}th command overall if
+@option{--command} is not specified), where @var{n} is 1 for the first
+command, 2 for the second, and so on.
+
@item --instances=@var{instance}@dots{}
Include the specified @var{instance} of an object that matches the
other criteria within a single command. The @var{instance} may be a
#include "gl/c-ctype.h"
#include "gl/xalloc.h"
+static bool
+is_command_item (const struct spv_item *item)
+{
+ return !item->parent || !item->parent->parent;
+}
+
static struct spv_item *
find_command_item (struct spv_item *item)
{
- /* A command item itself does not have a command item. */
- if (!item->parent || !item->parent->parent)
- return NULL;
-
- do
- {
- item = item->parent;
- }
- while (item->parent && item->parent->parent);
+ while (!is_command_item (item))
+ item = item->parent;
return item;
}
return retval;
}
+static bool
+match_command (size_t nth_command, size_t *commands, size_t n_commands)
+{
+ for (size_t i = 0; i < n_commands; i++)
+ if (nth_command == commands[i])
+ return true;
+ return false;
+}
+
static void
select_matches (const struct spv_reader *spv, const struct spv_criteria *c,
unsigned long int *include)
{
- struct spv_item *item;
- struct spv_item *command_item = NULL;
+ /* Counting instances within a command. */
+ struct spv_item *instance_command_item = NULL;
int instance_within_command = 0;
int last_instance = -1;
+
+ /* Counting commands. */
+ struct spv_item *command_command_item = NULL;
+ size_t nth_command = 0;
+
+ struct spv_item *item;
ssize_t index = -1;
SPV_ITEM_FOR_EACH_SKIP_ROOT (item, spv_get_root (spv))
{
index++;
struct spv_item *new_command_item = find_command_item (item);
- if (new_command_item != command_item)
+ if (new_command_item != instance_command_item)
{
if (last_instance >= 0)
{
last_instance = -1;
}
- command_item = new_command_item;
+ instance_command_item = new_command_item;
instance_within_command = 0;
}
&c->include.commands, &c->exclude.commands))
continue;
+ if (c->n_commands)
+ {
+ if (new_command_item != command_command_item)
+ {
+ command_command_item = new_command_item;
+ nth_command++;
+ }
+
+ if (!match_command (nth_command, c->commands, c->n_commands))
+ continue;
+ }
+
if (!match (spv_item_get_subtype (item),
&c->include.subtypes, &c->exclude.subtypes))
continue;
if (c->n_instances)
{
- if (!command_item)
+ if (is_command_item (item))
continue;
instance_within_command++;
struct spv_criteria_match include;
struct spv_criteria_match exclude;
+ /* Include objects under commands with indexes listed in COMMANDS. Indexes
+ are 1-based. Everything is included if N_COMMANDS is 0. */
+ size_t *commands;
+ size_t n_commands;
+
/* Include XML and binary member names that match (except that everything
is included by default if empty). */
struct string_array members;
const struct spv_criteria[], size_t n_criteria,
struct spv_item ***items, size_t *n_items);
-
#endif /* output/spv/spv-select.h */
])
AT_CLEANUP
+AT_SETUP([pspp-output --nth-commands])
+AT_CHECK([pspp-output dir $srcdir/utilities/regress.spv --nth-commands=2,4,6],
+ [0], [dnl
+- heading "Title" command "Title"
+ - text "Page Title" command "Title"
+- heading "Begin Data" command "Begin Data"
+- heading "Frequencies" command "Frequencies"
+ - table "Statistics" command "Frequencies"
+ - table "v0" command "Frequencies" subtype "Frequencies"
+ - table "v1" command "Frequencies" subtype "Frequencies"
+ - table "v2" command "Frequencies" subtype "Frequencies"
+])
+AT_CLEANUP
+
AT_SETUP([pspp-output --subtypes equal])
AT_CHECK([pspp-output dir $srcdir/utilities/regress.spv --subtypes='freq*'],
[0], [dnl
The \fB\-\-labels\fR option matches the labels in table output (that
is, the table titles). Labels are affected by the output language,
variable names and labels, split file settings, and other factors.
+.IP "\-\-nth-commands=\fIn\fR..."
+Include only objects from the \fIn\fRth command that matches
+\fB\-\-commands\fR (or the \fIn\fRth command overall if
+\fB\-\-commands\fR is not specified), where \fIn\fR is 1 for the first
+command, 2 for the second, and so on.
.IP "\fB\-\-instances=\fIinstance\fR..."
Include the specified \fIinstance\fR of an object that matches the
other criteria within a single command. The \fIinstance\fR may be a
}
}
+static void
+parse_nth_commands (char *arg)
+{
+ struct spv_criteria *c = get_criteria ();
+ size_t allocated_commands = c->n_commands;
+
+ for (char *token = strtok (arg, ","); token; token = strtok (NULL, ","))
+ {
+ if (c->n_commands >= allocated_commands)
+ c->commands = x2nrealloc (c->commands, &allocated_commands,
+ sizeof *c->commands);
+
+ c->commands[c->n_commands++] = atoi (token);
+ }
+}
+
static void
parse_members (const char *arg)
{
OPT_SHOW_HIDDEN,
OPT_SELECT,
OPT_COMMANDS,
+ OPT_NTH_COMMANDS,
OPT_SUBTYPES,
OPT_LABELS,
OPT_INSTANCES,
{ "show-hidden", no_argument, NULL, OPT_SHOW_HIDDEN },
{ "select", required_argument, NULL, OPT_SELECT },
{ "commands", required_argument, NULL, OPT_COMMANDS },
+ { "nth-commands", required_argument, NULL, OPT_NTH_COMMANDS },
{ "subtypes", required_argument, NULL, OPT_SUBTYPES },
{ "labels", required_argument, NULL, OPT_LABELS },
{ "instances", required_argument, NULL, OPT_INSTANCES },
parse_commands (optarg);
break;
+ case OPT_NTH_COMMANDS:
+ parse_nth_commands (optarg);
+ break;
+
case OPT_SUBTYPES:
parse_subtypes (optarg);
break;
--select=CLASS... include only some kinds of objects\n\
--select=help print known object classes\n\
--commands=COMMAND... include only specified COMMANDs\n\
+ --nth-commands=N... include only the Nth instance of selected commands\n\
--subtypes=SUBTYPE... include only specified SUBTYPEs of output\n\
--labels=LABEL... include only output objects with the given LABELs\n\
--instances=INSTANCE... include only the given object INSTANCEs\n\