+ if ($ret)
+ {
+ post_line ($ret, $index + 1);
+ }
+}} # handle_line_dsmap
+
+#
+# The _step_ handler
+#
+{
+my $step_factor_up;
+my $step_factor_down;
+sub handle_line_step
+{
+ my $line = shift;
+ my $index = shift;
+
+ if (!$Step)
+ {
+ post_line ($line, $index + 1);
+ return;
+ }
+
+ $step_factor_up ||= 0;
+ $step_factor_down ||= 0;
+
+ if (($step_factor_up == 0) && ($step_factor_down == 0))
+ {
+ if ($line =~ m#<step>\s*(\d+)\s*</step>#i)
+ {
+ my $old_step = 0 + $1;
+ if ($Step < $old_step)
+ {
+ $step_factor_down = int ($old_step / $Step);
+ if (($step_factor_down * $Step) != $old_step)
+ {
+ print STDERR "The old step ($old_step seconds) "
+ . "is not a multiple of the new step "
+ . "($Step seconds).\n";
+ exit (1);
+ }
+ $line = "<step> $Step </step>\n";
+ }
+ elsif ($Step > $old_step)
+ {
+ $step_factor_up = int ($Step / $old_step);
+ if (($step_factor_up * $old_step) != $Step)
+ {
+ print STDERR "The new step ($Step seconds) "
+ . "is not a multiple of the old step "
+ . "($old_step seconds).\n";
+ exit (1);
+ }
+ $line = "<step> $Step </step>\n";
+ }
+ else
+ {
+ $Step = 0;
+ }
+ }
+ }
+ elsif ($line =~ m#<pdp_per_row>\s*(\d+)\s*</pdp_per_row>#i)
+ {
+ my $old_val = 0 + $1;
+ my $new_val;
+ if ($step_factor_up)
+ {
+ $new_val = int ($old_val / $step_factor_up);
+ if (($new_val * $step_factor_up) != $old_val)
+ {
+ print STDERR "Can't divide number of PDPs per row ($old_val) by step-factor ($step_factor_up).\n";
+ exit (1);
+ }
+ }
+ else
+ {
+ $new_val = $step_factor_down * $old_val;
+ }
+ $line = "<pdp_per_row> $new_val </pdp_per_row>\n";
+ }
+
+ post_line ($line, $index + 1);
+}} # handle_line_step
+
+#
+# The _add RRA_ handler
+#
+{
+my $add_rra_done;
+my $num_ds;
+sub handle_line_add_rra
+{
+ my $line = shift;
+ my $index = shift;
+
+ my $post = sub { for (@_) { post_line ($_, $index + 1); } };
+
+ $num_ds ||= 0;
+
+ if (!@$NewRRAs || $add_rra_done)
+ {
+ $post->($line);
+ return;
+ }
+
+ if ($line =~ m#<ds>#i)
+ {
+ $num_ds++;
+ }
+ elsif ($line =~ m#<rra>#i)
+ {
+ for (my $i = 0; $i < @$NewRRAs; $i++)
+ {
+ my $rra = $NewRRAs->[$i];
+ my $temp;
+ $post->("\t<rra>\n",
+ "\t\t<cf> $rra->{'cf'} </cf>\n",
+ "\t\t<pdp_per_row> $rra->{'steps'} </pdp_per_row>\n",
+ "\t\t<params>\n",
+ "\t\t\t<xff> $rra->{'xff'} </xff>\n",
+ "\t\t</params>\n",
+ "\t\t<cdp_prep>\n");
+
+ for (my $j = 0; $j < $num_ds; $j++)
+ {
+ $post->("\t\t\t<ds>\n",
+ "\t\t\t\t<primary_value> NaN </primary_value>\n",
+ "\t\t\t\t<secondary_value> NaN </secondary_value>\n",
+ "\t\t\t\t<value> NaN </value>\n",
+ "\t\t\t\t<unknown_datapoints> 0 </unknown_datapoints>\n",
+ "\t\t\t</ds>\n");
+ }
+
+ $post->("\t\t</cdp_prep>\n", "\t\t<database>\n");
+ $temp = "\t\t\t<row>" . join ('', map { "<v> NaN </v>" } (1 .. $num_ds)) . "</row>\n";
+ for (my $j = 0; $j < $rra->{'rows'}; $j++)
+ {
+ $post->($temp);
+ }
+ $post->("\t\t</database>\n");
+ }
+ }
+
+ $post->($line);
+}} # handle_line_add_rra
+
+#
+# The _output_ handler
+#
+{
+my $fh;
+sub set_output
+{
+ $fh = shift;
+}
+
+sub handle_line_output
+{
+ my $line = shift;
+ my $index = shift;
+
+ if (!defined ($fh))
+ {
+ post_line ($line, $index + 1);
+ return;
+ }
+
+ print $fh $line;
+}} # handle_line_output
+
+#
+# Dispatching logic
+#
+{
+my @handlers = ();
+sub add_handler
+{
+ my $handler = shift;
+
+ die unless (ref ($handler) eq 'CODE');
+ push (@handlers, $handler);
+} # add_handler
+
+sub post_line
+{
+ my $line = shift;
+ my $index = shift;
+
+ if (0)
+ {
+ my $copy = $line;
+ chomp ($copy);
+ print "DEBUG: post_line ($copy, $index);\n";
+ }
+
+ if ($index > $#handlers)
+ {
+ return;
+ }
+ $handlers[$index]->($line, $index);
+}} # post_line
+
+sub handle_fh
+{
+ my $in_fh = shift;
+ my $out_fh = shift;
+
+ set_output ($out_fh);
+
+ if (@$InDS)
+ {
+ add_handler (\&handle_line_dsmap);
+ }
+
+ if ($Step)
+ {
+ add_handler (\&handle_line_step);
+ }
+
+ if (@$NewRRAs)
+ {
+ add_handler (\&handle_line_add_rra);
+ }
+
+ add_handler (\&handle_line_output);
+
+ while (my $line = <$in_fh>)
+ {
+ post_line ($line, 0);
+ }
+} # handle_fh
+
+sub main