p_node_filename } return undef; } sub initialize_output_units_files($) { my $self = shift; $self->{'out_filepaths'} = {}; $self->{'file_counters'} = {}; $self->{'filenames'} = {}; } # If CASE_INSENSITIVE_FILENAMES is set, reuse the first # filename with the same name insensitive to the case. sub register_normalize_case_filename($$) { my $self = shift; my $filename = shift; if ($self->get_conf('CASE_INSENSITIVE_FILENAMES')) { if (exists($self->{'filenames'}->{lc($filename)})) { if ($self->get_conf('DEBUG')) { print STDERR "Reusing case-insensitive ". $self->{'filenames'}->{lc($filename)}." for $filename\n"; } $filename = $self->{'filenames'}->{lc($filename)}; } else { $self->{'filenames'}->{lc($filename)} = $filename; } } else { if (exists($self->{'filenames'}->{$filename})) { if ($self->get_conf('DEBUG')) { print STDERR "Reusing ".$self->{'filenames'}->{$filename} ." for $filename\n"; } } else { $self->{'filenames'}->{$filename} = $filename; } } return $filename; } # return the registered filename if there is one, else return undef. # Note that it only tells that a file name has been its name considered, # not that the corresponding file is created. # currently unused. sub registered_filename($$) { my $self = shift; my $filename = shift; if ($self->get_conf('CASE_INSENSITIVE_FILENAMES')) { if (exists($self->{'filenames'}->{lc($filename)})) { return $self->{'filenames'}->{lc($filename)}; } } elsif (exists($self->{'filenames'}->{$filename})) { return $self->{'filenames'}->{$filename}; } return undef; } # Sets $output_unit->{'unit_filename'}. sub set_output_unit_file($$$) { my $self = shift; my $output_unit = shift; my $filename = shift; if (!defined($filename)) { cluck("set_output_unit_file: filename not defined\n"); } if (!defined($output_unit)) { cluck("set_output_unit_file: output_unit not defined\n"); } $filename = $self->register_normalize_case_filename($filename); # This should never happen, set_output_unit_file is called once per # tree unit. if (exists($output_unit->{'unit_filename'})) { if ($output_unit->{'unit_filename'} eq $filename) { print STDERR "set_output_unit_file: already set: $filename\n" if ($self->get_conf('DEBUG')); } else { print STDERR "set_output_unit_file: unit_filename reset: " .$output_unit->{'unit_filename'}.", $filename\n" if ($self->get_conf('DEBUG')); } } $output_unit->{'unit_filename'} = $filename; } # sets out_filepaths converter state, associating a file name # to a file path. # $FILEPATH can be given explicitly, otherwise it is based on $FILENAME # and $DESTINATION_DIRECTORY sub set_file_path($$$;$) { my $self = shift; my $filename = shift; my $destination_directory = shift; my $filepath = shift; if (!defined($filename)) { cluck("set_file_path: filename not defined\n"); } $filename = $self->register_normalize_case_filename($filename); if (not defined($filepath)) { if (defined($destination_directory) and $destination_directory ne '') { $filepath = join('/', ($destination_directory, $filename)); } else { $filepath = $filename; } } # the file path should be set only once per file name. With # CASE_INSENSITIVE_FILENAMES the same file path can appear more # than once when files differ in case. if (defined($self->{'out_filepaths'}->{$filename})) { if ($self->{'out_filepaths'}->{$filename} eq $filepath) { print STDERR "set_file_path: filepath set: $filepath\n" if ($self->get_conf('DEBUG')); } else { print STDERR "set_file_path: filepath reset: " .$self->{'out_filepaths'}->{$filename}.", $filepath\n" if ($self->get_conf('DEBUG')); } } $self->{'out_filepaths'}->{$filename} = $filepath; } sub _get_root_element($$) { my $self = shift; my $command = shift; my $current = $command; while (1) { if ($current->{'associated_unit'}) { return $current->{'associated_unit'}; } if ($current->{'parent'}) { $current = $current->{'parent'}; } else { return undef; } } } # TODO document # set file_counters converter state sub set_output_units_files($$$$$$) { my $self = shift; my $output_units = shift; my $output_file = shift; my $destination_directory = shift; my $output_filename = shift; my $document_name = shift; # Ensure that the document has pages return undef if (!defined($output_units) or !@$output_units); $self->initialize_output_units_files(); my $extension = ''; $extension = '.'.$self->get_conf('EXTENSION') if (defined($self->get_conf('EXTENSION')) and $self->get_conf('EXTENSION') ne ''); if (!$self->get_conf('SPLIT')) { $self->set_file_path($output_filename, undef, $output_file); foreach my $output_unit (@$output_units) { $self->set_output_unit_file($output_unit, $output_filename); } } else { my $node_top; my $identifiers_target; if ($self->{'document'}) { $identifiers_target = $self->{'document'}->labels_information(); } $node_top = $identifiers_target->{'Top'} if ($identifiers_target); my $top_node_filename = $self->top_node_filename($document_name); # first determine the top node file name. if ($node_top and defined($top_node_filename)) { my ($node_top_unit) = $self->_get_root_element($node_top); if (!defined($node_top_unit)) { print STDERR "No element for top node (".scalar(@$output_units)." units)\n" if ($self->get_conf('DEBUG')); } else { $self->set_file_path($top_node_filename, $destination_directory); $self->set_output_unit_file($node_top_unit, $top_node_filename); } } my $file_nr = 0; my $previous_page; foreach my $output_unit (@$output_units) { # For Top node. next if (defined($output_unit->{'unit_filename'})); my $file_output_unit = $output_unit->{'first_in_page'}; if (!$file_output_unit) { cluck ("No first_in_page for $output_unit\n"); } if (!defined($file_output_unit->{'unit_filename'})) { foreach my $root_command (@{$file_output_unit->{'unit_contents'}}) { if ($root_command->{'cmdname'} and $root_command->{'cmdname'} eq 'node') { my $node_filename; # double node are not normalized, they are handled here if (!defined($root_command->{'extra'}->{'normalized'}) or !defined($identifiers_target->{ $root_command->{'extra'}->{'normalized'}})) { $node_filename = 'unknown_node'; } else { $node_filename = $self->node_information_filename( $root_command->{'extra'}->{'normalized'}, $root_command->{'args'}->[0]); } $node_filename .= $extension; $self->set_file_path($node_filename,$destination_directory); $self->set_output_unit_file($file_output_unit, $node_filename); last; } } if (!defined($file_output_unit->{'unit_filename'})) { # use section to do the file name if there is no node my $command = $file_output_unit->{'unit_command'}; if ($command) { if ($command->{'cmdname'} eq 'top' and !$node_top and defined($top_node_filename)) { $self->set_file_path($top_node_filename, $destination_directory); $self->set_output_unit_file($file_output_unit, $top_node_filename); } else { my ($normalized_name, $filename) = $self->normalized_sectioning_command_filename($command); $self->set_file_path($filename, $destination_directory); $self->set_output_unit_file($file_output_unit, $filename); } } else { # when everything else has failed if ($file_nr == 0 and !$node_top and defined($top_node_filename)) { $self->set_file_path($top_node_filename, $destination_directory); $self->set_output_unit_file($file_output_unit, $top_node_filename); } else { my $filename = $document_name . "_$file_nr"; $filename .= $extension; $self->set_file_path($filename, $destination_directory); $self->set_output_unit_file($output_unit, $filename); } $file_nr++; } } } $self->set_output_unit_file($output_unit, $file_output_unit->{'unit_filename'}); } } foreach my $output_unit (@$output_units) { my $output_unit_filename = $output_unit->{'unit_filename'}; $self->{'file_counters'}->{$output_unit_filename} = 0 if (!exists($self->{'file_counters'}->{$output_unit_filename})); $self->{'file_counters'}->{$output_unit_filename}++; print STDERR 'Page ' # uncomment for Perl object name #."$output_unit " .Texinfo::OutputUnits::output_unit_texi($output_unit) .": $output_unit_filename($self->{'file_counters'}->{$output_unit_filename})\n" if ($self->get_conf('DEBUG')); } }