[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
branch master updated: * tp/Texinfo/Convert/HTML.pm (_html_convert_outpu
From: |
Patrice Dumas |
Subject: |
branch master updated: * tp/Texinfo/Convert/HTML.pm (_html_convert_output): if a special element body is empty, do not return immediately but check if there is already a body registered with the file, as in that case, the body would need to be output. |
Date: |
Wed, 01 Nov 2023 16:17:10 -0400 |
This is an automated email from the git hooks/post-receive script.
pertusus pushed a commit to branch master
in repository texinfo.
The following commit(s) were added to refs/heads/master by this push:
new f796367e02 * tp/Texinfo/Convert/HTML.pm (_html_convert_output): if a
special element body is empty, do not return immediately but check if there is
already a body registered with the file, as in that case, the body would need
to be output.
f796367e02 is described below
commit f796367e025a859b6b1dff8ae401f4f72b03a66e
Author: Patrice Dumas <pertusus@free.fr>
AuthorDate: Wed Nov 1 21:15:29 2023 +0100
* tp/Texinfo/Convert/HTML.pm (_html_convert_output): if a special
element body is empty, do not return immediately but check if there is
already a body registered with the file, as in that case, the body
would need to be output.
* tp/Texinfo/Common.pm (output_files_open_out): warn if an unclosed
file has already been registered.
* tp/Texinfo/XS/main/utils.c (add_include_directory): simplify, set
string argument const.
* tp/Texinfo/Convert/HTML.pm (_html_convert_output),
tp/Texinfo/XS/convert/convert_html.c (html_convert_output): rename $footer
as $file_end and $header as $file_beginning.
* tp/Texinfo/XS/convert/ConvertXS.xs
(html_prepare_units_directions_files),
tp/Texinfo/XS/convert/convert_html.c
(html_prepare_units_directions_files),
tp/Texinfo/XS/convert/converter.c (initialize_output_units_files),
tp/Texinfo/XS/convert/convert_html.c (html_set_pages_files),
tp/Texinfo/XS/convert/converter.c (find_output_unit_file)
(add_output_units_file, set_output_unit_file)
(register_normalize_case_filename, set_file_path),
tp/Texinfo/XS/main/converter_types.h (CONVERTER): put
output_unit_files directly in CONVERTER. Start indices of found files
in output_unit_files list at 0. have set_output_unit_file and
functions called by set_output_unit_file return indices in
output_unit_files list. Setup converter output_unit_file_indices and
special_unit_file_indices with each output unit output_unit_files file
index.
* tp/Texinfo/XS/convert/convert_html.c (unique_target),
tp/Texinfo/XS/main/utils.c (find_string): add
find_string function.
* tp/Texinfo/XS/main/build_perl_info.c (newSVpv_byte): add
newSVpv_byte.
* tp/Texinfo/Convert/HTML.pm (_html_convert_output),
tp/Texinfo/XS/convert/convert_html.c
(convert_output_output_unit_internal, html_convert_output),
tp/Texinfo/XS/main/build_perl_info.c (build_html_formatting_state),
tp/Texinfo/XS/main/convert_utils.c (encoded_output_file_name),
(register_unclosed_file, output_files_open_out)
(output_files_register_closed), tp/Texinfo/XS/main/converter_types.h
(ARRAY_INDEX_LIST, FILE_NAME_PATH_COUNTER, FILE_STREAM)
(FILE_STREAM_LIST, OUTPUT_FILES_INFORMATION):
finish C html_convert_output output implementation. Pass file counters
back to perl. Add Texinfo::Common output_files_information API to C to
open and register files.
* tp/Texinfo/XS/convert/ConvertXS.xs (html_convert_output),
tp/Texinfo/XS/convert/convert_html.c (html_converter_initialize),
tp/Texinfo/XS/main/build_perl_info.c
(build_output_files_unclosed_files, build_output_files_opened_files)
(build_output_files_information): build perl converter
output_files_information.
* tp/texi2any.pl (%main_unclosed_files): rename %unclosed_files as
%main_unclosed_files.
---
ChangeLog | 64 +++++++++
tp/Texinfo/Common.pm | 14 +-
tp/Texinfo/Convert/HTML.pm | 33 +++--
tp/Texinfo/XS/convert/ConvertXS.xs | 10 +-
tp/Texinfo/XS/convert/convert_html.c | 248 +++++++++++++++++++++++++++--------
tp/Texinfo/XS/convert/converter.c | 77 ++++++-----
tp/Texinfo/XS/convert/converter.h | 3 +-
tp/Texinfo/XS/main/build_perl_info.c | 167 ++++++++++++++++++++++-
tp/Texinfo/XS/main/build_perl_info.h | 2 +
tp/Texinfo/XS/main/convert_utils.c | 156 ++++++++++++++++++++++
tp/Texinfo/XS/main/convert_utils.h | 13 ++
tp/Texinfo/XS/main/converter_types.h | 60 ++++++++-
tp/Texinfo/XS/main/utils.c | 20 ++-
tp/Texinfo/XS/main/utils.h | 3 +-
tp/texi2any.pl | 8 +-
15 files changed, 750 insertions(+), 128 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index cd0d8caccb..88ff669eb1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,67 @@
+2023-11-01 Patrice Dumas <pertusus@free.fr>
+
+ * tp/Texinfo/Convert/HTML.pm (_html_convert_output): if a special
+ element body is empty, do not return immediately but check if there is
+ already a body registered with the file, as in that case, the body
+ would need to be output.
+
+ * tp/Texinfo/Common.pm (output_files_open_out): warn if an unclosed
+ file has already been registered.
+
+ * tp/Texinfo/XS/main/utils.c (add_include_directory): simplify, set
+ string argument const.
+
+ * tp/Texinfo/Convert/HTML.pm (_html_convert_output),
+ tp/Texinfo/XS/convert/convert_html.c (html_convert_output): rename
$footer
+ as $file_end and $header as $file_beginning.
+
+ * tp/Texinfo/XS/convert/ConvertXS.xs
+ (html_prepare_units_directions_files),
+ tp/Texinfo/XS/convert/convert_html.c
+ (html_prepare_units_directions_files),
+ tp/Texinfo/XS/convert/converter.c (initialize_output_units_files),
+ tp/Texinfo/XS/convert/convert_html.c (html_set_pages_files),
+ tp/Texinfo/XS/convert/converter.c (find_output_unit_file)
+ (add_output_units_file, set_output_unit_file)
+ (register_normalize_case_filename, set_file_path),
+ tp/Texinfo/XS/main/converter_types.h (CONVERTER): put
+ output_unit_files directly in CONVERTER. Start indices of found files
+ in output_unit_files list at 0. have set_output_unit_file and
+ functions called by set_output_unit_file return indices in
+ output_unit_files list. Setup converter output_unit_file_indices and
+ special_unit_file_indices with each output unit output_unit_files file
+ index.
+
+ * tp/Texinfo/XS/convert/convert_html.c (unique_target),
+ tp/Texinfo/XS/main/utils.c (find_string): add
+ find_string function.
+
+ * tp/Texinfo/XS/main/build_perl_info.c (newSVpv_byte): add
+ newSVpv_byte.
+
+ * tp/Texinfo/Convert/HTML.pm (_html_convert_output),
+ tp/Texinfo/XS/convert/convert_html.c
+ (convert_output_output_unit_internal, html_convert_output),
+ tp/Texinfo/XS/main/build_perl_info.c (build_html_formatting_state),
+ tp/Texinfo/XS/main/convert_utils.c (encoded_output_file_name),
+ (register_unclosed_file, output_files_open_out)
+ (output_files_register_closed), tp/Texinfo/XS/main/converter_types.h
+ (ARRAY_INDEX_LIST, FILE_NAME_PATH_COUNTER, FILE_STREAM)
+ (FILE_STREAM_LIST, OUTPUT_FILES_INFORMATION):
+ finish C html_convert_output output implementation. Pass file counters
+ back to perl. Add Texinfo::Common output_files_information API to C to
+ open and register files.
+
+ * tp/Texinfo/XS/convert/ConvertXS.xs (html_convert_output),
+ tp/Texinfo/XS/convert/convert_html.c (html_converter_initialize),
+ tp/Texinfo/XS/main/build_perl_info.c
+ (build_output_files_unclosed_files, build_output_files_opened_files)
+ (build_output_files_information): build perl converter
+ output_files_information.
+
+ * tp/texi2any.pl (%main_unclosed_files): rename %unclosed_files as
+ %main_unclosed_files.
+
2023-10-31 Patrice Dumas <pertusus@free.fr>
* tp/Texinfo/XS/main/call_perl_function.h (FILE_NAME_PATH)
diff --git a/tp/Texinfo/Common.pm b/tp/Texinfo/Common.pm
index bc2c9e9d2d..69f3569831 100644
--- a/tp/Texinfo/Common.pm
+++ b/tp/Texinfo/Common.pm
@@ -609,7 +609,17 @@ sub output_files_open_out($$$;$$)
binmode($filehandle, ":encoding($encoding)");
}
if ($self) {
- push @{$self->{'opened_files'}}, $file_path;
+ if ($self->{'unclosed_files'}->{$file_path}) {
+ warn "BUG: already open: $file_path\n";
+ } else {
+ # FIXME check that this file has not already been registered
+ # as opened_file? If not, it will be unlink'ed twice if the
+ # main program aborts. It is not possible to use the file name
+ # twice except with user customization file name set to a file
+ # name also used for a specific purpose such as MACRO_EXPAND
+ # or the like, as output units files are never opened twice.
+ push @{$self->{'opened_files'}}, $file_path;
+ }
$self->{'unclosed_files'}->{$file_path} = $filehandle;
}
return $filehandle, undef;
@@ -625,7 +635,7 @@ sub output_files_register_closed($$)
if ($self->{'unclosed_files'}->{$file_path}) {
delete $self->{'unclosed_files'}->{$file_path};
} else {
- cluck "$file_path not opened\n";
+ cluck "BUG: $file_path not opened\n";
}
}
diff --git a/tp/Texinfo/Convert/HTML.pm b/tp/Texinfo/Convert/HTML.pm
index 6fcffa1491..8859416628 100644
--- a/tp/Texinfo/Convert/HTML.pm
+++ b/tp/Texinfo/Convert/HTML.pm
@@ -11429,7 +11429,7 @@ sub _html_convert_output($$$$$$$$)
my ($self, $root, $output_units, $special_units, $output_file,
$destination_directory, $output_filename, $document_name) = @_;
- if (0 and $self->{'converter_descriptor'} and $XS_convert) {
+ if ($self->{'converter_descriptor'} and $XS_convert) {
my $encoded_converter = $self->encode_converter_for_output();
my $encoded_document_name = Encode::encode('UTF-8', $document_name);
my $encoded_output_file = Encode::encode('UTF-8', $output_file);
@@ -11437,7 +11437,8 @@ sub _html_convert_output($$$$$$$$)
= Encode::encode('UTF-8', $destination_directory);
my $encoded_output_filename = Encode::encode('UTF-8', $output_filename);
- my $XS_result = _XS_html_convert_output ($encoded_converter,
+ my $XS_result
+ = _XS_html_convert_output ($encoded_converter,
$root, $output_units, $special_units,
$encoded_output_file,
$encoded_destination_directory, $encoded_output_filename,
$encoded_document_name);
@@ -11527,13 +11528,14 @@ sub _html_convert_output($$$$$$$$)
}
# do end file first, in case it needs some CSS
- my $footer = &{$self->formatting_function('format_end_file')}($self,
+ my $file_end = &{$self->formatting_function('format_end_file')}($self,
$output_filename, undef);
- my $header = &{$self->formatting_function('format_begin_file')}($self,
+ my $file_beginning
+ = &{$self->formatting_function('format_begin_file')}($self,
$output_filename, undef);
- $text_output .= $self->write_or_return($header, $fh);
+ $text_output .= $self->write_or_return($file_beginning, $fh);
$text_output .= $self->write_or_return($body, $fh);
- $text_output .= $self->write_or_return($footer, $fh);
+ $text_output .= $self->write_or_return($file_end, $fh);
# NOTE do not close STDOUT now to avoid a perl warning.
if ($fh and $no_page_out_filepath ne '-') {
@@ -11572,8 +11574,7 @@ sub _html_convert_output($$$$$$$$)
$body = $self->convert_output_unit($output_unit,
"output s-unit $unit_nr");
if ($body eq '') {
- $self->{'file_counters'}->{$output_unit_filename}--;
- next;
+ $body = undef;
}
} else {
print STDERR "\nUNIT $unit_nr\n" if ($self->get_conf('DEBUG'));
@@ -11581,15 +11582,21 @@ sub _html_convert_output($$$$$$$$)
"output unit $unit_nr");
}
+ $self->{'file_counters'}->{$output_unit_filename}--;
+
# register the output but do not print anything. Printing
# only when file_counters reach 0, to be sure that all the
# elements have been converted before headers are done.
- if (!exists($files{$output_unit_filename})) {
- $files{$output_unit_filename} = {'first_unit' => $output_unit,
- 'body' => ''};
+ if (defined($body)) {
+ if (!exists($files{$output_unit_filename})) {
+ $files{$output_unit_filename} = {'first_unit' => $output_unit,
+ 'body' => ''};
+ }
+ $files{$output_unit_filename}->{'body'} .= $body;
+ } else {
+ next if (!exists($files{$output_unit_filename})
+ or $files{$output_unit_filename}->{'body'} eq '');
}
- $files{$output_unit_filename}->{'body'} .= $body;
- $self->{'file_counters'}->{$output_unit_filename}--;
if ($self->{'file_counters'}->{$output_unit_filename} == 0) {
my $out_filepath = $self->{'out_filepaths'}->{$output_unit_filename};
diff --git a/tp/Texinfo/XS/convert/ConvertXS.xs
b/tp/Texinfo/XS/convert/ConvertXS.xs
index c992c6ee87..ca5dcd3788 100644
--- a/tp/Texinfo/XS/convert/ConvertXS.xs
+++ b/tp/Texinfo/XS/convert/ConvertXS.xs
@@ -233,12 +233,12 @@ html_prepare_units_directions_files (SV *converter_in, SV
*output_units_in, SV *
= build_html_global_units_directions (self->global_units_directions,
self->special_units_direction_name);
elements_in_file_count_sv
- = build_html_elements_in_file_count (self->output_unit_files);
+ = build_html_elements_in_file_count (&self->output_unit_files);
/* file names API */
- filenames_sv = build_filenames (self->output_unit_files);
- file_counters_sv = build_file_counters (self->output_unit_files);
- out_filepaths_sv = build_out_filepaths (self->output_unit_files);
+ filenames_sv = build_filenames (&self->output_unit_files);
+ file_counters_sv = build_file_counters (&self->output_unit_files);
+ out_filepaths_sv = build_out_filepaths (&self->output_unit_files);
EXTEND(SP, 6);
PUSHs(sv_2mortal(files_source_info_sv));
@@ -442,6 +442,8 @@ html_convert_output (SV *converter_in, SV *tree_in, SV
*output_units_in, SV *spe
result_sv = newSVpv_utf8 (result, 0);
free (result);
}
+
+ build_output_files_information (self);
}
if (result_sv)
diff --git a/tp/Texinfo/XS/convert/convert_html.c
b/tp/Texinfo/XS/convert/convert_html.c
index 9d73189b6e..2d00429795 100644
--- a/tp/Texinfo/XS/convert/convert_html.c
+++ b/tp/Texinfo/XS/convert/convert_html.c
@@ -17,6 +17,7 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
+#include <errno.h>
#include "global_commands_types.h"
#include "tree_types.h"
@@ -879,17 +880,7 @@ unique_target (CONVERTER *self, char *target_base)
char *target = strdup (target_base);
while (1)
{
- int j;
- int non_unique = 0;
- for (j = 0; j < self->seen_ids->number; j++)
- {
- if (!strcmp (target, self->seen_ids->list[j]))
- {
- non_unique = 1;
- break;
- }
- }
- if (non_unique)
+ if (find_string (self->seen_ids, target))
{
free (target);
xasprintf (&target, "%s-%d", target_base, nr);
@@ -1802,8 +1793,13 @@ html_set_pages_files (CONVERTER *self, OUTPUT_UNIT_LIST
*output_units,
}
}
+ self->output_unit_file_indices = (size_t *)
+ malloc (output_units->number * sizeof (size_t));
+
+ memset (self->output_unit_file_indices, 0, output_units->number);
for (i = 0; i < output_units->number; i++)
{
+ size_t output_unit_file_idx = 0;
FILE_NAME_PATH_COUNTER *output_unit_file;
OUTPUT_UNIT *output_unit = output_units->list[i];
char *output_unit_file_name = unit_file_name_paths[i];
@@ -1847,7 +1843,10 @@ html_set_pages_files (CONVERTER *self, OUTPUT_UNIT_LIST
*output_units,
}
free (file_name_path);
}
- output_unit_file = set_output_unit_file (self, output_unit, filename, 1);
+ output_unit_file_idx
+ = set_output_unit_file (self, output_unit, filename, 1);
+ self->output_unit_file_indices[i] = output_unit_file_idx;
+ output_unit_file = &self->output_unit_files.list[output_unit_file_idx];
if (self->conf->DEBUG > 0)
fprintf (stderr, "Page %s: %s(%d)\n",
output_unit_texi (output_unit),
@@ -1857,9 +1856,14 @@ html_set_pages_files (CONVERTER *self, OUTPUT_UNIT_LIST
*output_units,
if (special_units && special_units->number)
{
+ self->special_unit_file_indices = (size_t *)
+ malloc (special_units->number * sizeof (size_t));
+ memset (self->special_unit_file_indices, 0,
+ special_units->number);
int i;
for (i = 0; i < special_units->number; i++)
{
+ size_t special_unit_file_idx = 0;
FILE_NAME_PATH_COUNTER *special_unit_file;
OUTPUT_UNIT *special_unit = special_units->list[i];
ELEMENT *unit_command = special_unit->unit_command;
@@ -1892,8 +1896,11 @@ html_set_pages_files (CONVERTER *self, OUTPUT_UNIT_LIST
*output_units,
add_to_files_source_info (files_source_info, filename,
"special_unit", 0, unit_command, 0);
}
- special_unit_file
+ special_unit_file_idx
= set_output_unit_file (self, special_unit, filename, 1);
+ self->special_unit_file_indices[i] = special_unit_file_idx;
+ special_unit_file
+ = &self->output_unit_files.list[special_unit_file_idx];
if (self->conf->DEBUG > 0)
fprintf (stderr, "Special page: %s(%d)\n", filename,
special_unit_file->counter);
@@ -2000,12 +2007,12 @@ html_prepare_units_directions_files (CONVERTER *self,
/* elements_in_file_count is only set in HTML, not in
Texinfo::Convert::Converter */
- if (self->output_unit_files)
+ if (self->output_unit_files.number)
{
- for (i = 0; i < self->output_unit_files->number; i++)
+ for (i = 0; i < self->output_unit_files.number; i++)
{
FILE_NAME_PATH_COUNTER *file_counter
- = &self->output_unit_files->list[i];
+ = &self->output_unit_files.list[i];
/* counter is dynamic, decreased when the element is encountered
elements_in_file_count is not modified afterwards */
@@ -2265,6 +2272,11 @@ html_converter_initialize (CONVERTER *self)
memset (self->no_arg_formatted_cmd_translated.list, 0,
self->no_arg_formatted_cmd.number * sizeof (enum command_id));
}
+
+ self->file_changed_counter.list = (size_t *)
+ malloc (self->output_unit_files.number * sizeof (size_t));
+ memset (self->file_changed_counter.list, 0,
+ self->output_unit_files.number * sizeof (size_t));
}
void
@@ -3588,51 +3600,150 @@ html_convert_convert (CONVERTER *self, ELEMENT *root,
return result.text;
}
-void
-convert_output_output_unit_internal (CONVERTER *self, TEXT *result,
+int
+convert_output_output_unit_internal (CONVERTER *self,
+ ENCODING_CONVERSION *conversion,
+ TEXT *text,
OUTPUT_UNIT *output_unit, int unit_nr)
{
- TEXT body;
+ FILE_NAME_PATH_COUNTER *unit_file = 0;
+ size_t file_index;
+ int empty_body = 0; /* set if body is empty and it is a special unit */
char *output_unit_filename = output_unit->unit_filename;
self->current_filename = output_unit_filename;
self->modified_state |= HMSF_current_filename;
- text_init (&body);
- text_append (&body, "");
+ text_reset (text);
+ text_append (text, "");
if (output_unit->unit_type == OU_special_unit)
{
char *debug_str;
char *special_unit_variety = output_unit->special_unit_variety;
+
+ file_index = self->special_unit_file_indices[output_unit->index];
+ unit_file = &self->output_unit_files.list[file_index];
+
xasprintf (&debug_str, "UNIT SPECIAL %s", special_unit_variety);
- convert_convert_output_unit_internal (self, &body,
+ convert_convert_output_unit_internal (self, text,
output_unit, unit_nr, debug_str, "output s-unit");
free (debug_str);
- if (!strcmp (body.text, ""))
- {
- /*
- $self->{'file_counters'}->{$output_unit_filename}--;
- */
- return;
- }
+ if (!strcmp (text->text, ""))
+ empty_body = 1;
}
else
{
- convert_convert_output_unit_internal (self, &body, output_unit,
+ file_index = self->output_unit_file_indices[output_unit->index];
+ unit_file = &self->output_unit_files.list[file_index];
+
+ convert_convert_output_unit_internal (self, text, output_unit,
unit_nr, "UNIT", "output unit");
}
+ unit_file->counter--;
+ if (!unit_file->counter_changed)
+ {
+ self->file_changed_counter.list[self->file_changed_counter.number]
+ = file_index;
+ self->file_changed_counter.number++;
+ unit_file->counter_changed = 1;
+ }
+
/* register the output but do not print anything. Printing
only when file_counters reach 0, to be sure that all the
elements have been converted before headers are done. */
- /* */
+ if (!empty_body)
+ {
+ if (!unit_file->first_unit)
+ {
+ unit_file->first_unit = output_unit;
+ text_init (&unit_file->body);
+ }
+ text_append (&unit_file->body, text->text);
+ }
+ else
+ {
+ if (!unit_file->first_unit
+ || unit_file->body.end == 0)
+ {
+ return 1;
+ }
+ }
+
+ if (unit_file->counter == 0)
+ {
+ OUTPUT_UNIT *file_output_unit = unit_file->first_unit;
+ char *file_end;
+ char *file_beginning;
+ char *out_filepath = unit_file->filepath;
+ char *path_encoding;
+ char *open_error_message;
+ char *encoded_out_filepath = encoded_output_file_name (self->conf,
+ self->document->global_info, out_filepath,
+ &path_encoding, 0);
+ FILE *file_fh = output_files_open_out (&self->output_files_information,
+ encoded_out_filepath, &open_error_message, 0);
+ if (!file_fh)
+ {
+ message_list_document_error (self->error_messages, self->conf,
+ "could not open %s for writing: %s",
+ out_filepath, open_error_message);
+ return 0;
+ }
- self->current_filename = 0;
- self->modified_state |= HMSF_current_filename;
+ /* do end file first in case it requires some CSS */
+ file_end = call_formatting_function_format_end_file (self,
+ out_filepath, output_unit);
+ file_beginning = call_formatting_function_format_begin_file (self,
+ out_filepath, file_output_unit);
+ text_reset (text);
+ if (file_beginning)
+ {
+ text_append (text, file_beginning);
+ free (file_beginning);
+ }
+ if (unit_file->body.end)
+ {
+ text_append (text, unit_file->body.text);
+ }
+ if (file_end)
+ {
+ text_append (text, file_end);
+ free (file_end);
+ }
+ if (text->end)
+ {
+ char *result = encode_with_iconv (conversion->iconv, text->text, 0);
+ size_t res_len = strlen (result)+1;
+ size_t write_len = fwrite (result, sizeof (char), res_len,
+ file_fh);
+ free (result);
+ if (write_len != res_len)
+ { /* register error message instead? */
+ fprintf (stderr, "write to %s failed (%zu/%zu)\n",
+ encoded_out_filepath, write_len, res_len);
+ return 0;
+ }
+ }
+ /* NOTE do not close STDOUT here to be in line with perl code */
+ if (strcmp (out_filepath, "-"))
+ {
+ output_files_register_closed (&self->output_files_information,
+ encoded_out_filepath);
+ if (!fclose (file_fh))
+ {
+ message_list_document_error (self->error_messages, self->conf,
+ "error on closing %s: %s",
+ out_filepath, strerror (errno));
+ return 0;
+ }
+ }
+ }
+ return 1;
}
char *
@@ -3642,7 +3753,9 @@ html_convert_output (CONVERTER *self, ELEMENT *root,
char *output_file, char *destination_directory,
char *output_filename, char *document_name)
{
+ int status = 1;
TEXT result;
+ TEXT text; /* reused for all the output units */
char *title_titlepage;
OUTPUT_UNIT_LIST *output_units
@@ -3651,6 +3764,7 @@ html_convert_output (CONVERTER *self, ELEMENT *root,
= retrieve_output_units (special_units_descriptor);
text_init (&result);
+ text_init (&text);
text_append (&result, "");
@@ -3700,12 +3814,10 @@ html_convert_output (CONVERTER *self, ELEMENT *root,
if (!output_units || !output_units->number
|| !output_units->list[0]->unit_filename)
{
- TEXT body;
- char *footer;
- char *header;
+ char *file_end;
+ char *file_beginning;
- text_init (&body);
- text_append (&body, "");
+ text_append (&text, "");
/* in perl there is code for a case that should not be possible,
with current_filename ne '' here. This code is no present here */
@@ -3716,7 +3828,7 @@ html_convert_output (CONVERTER *self, ELEMENT *root,
for (i = 0; i < output_units->number; i++)
{
OUTPUT_UNIT *output_unit = output_units->list[i];
- convert_convert_output_unit_internal (self, &body, output_unit,
+ convert_convert_output_unit_internal (self, &text, output_unit,
unit_nr, "UNIT NO-PAGE", "no-page output unit");
unit_nr++;
}
@@ -3728,7 +3840,7 @@ html_convert_output (CONVERTER *self, ELEMENT *root,
for (i = 0; i < special_units->number; i++)
{
OUTPUT_UNIT *special_unit = special_units->list[i];
- convert_convert_output_unit_internal (self, &body,
+ convert_convert_output_unit_internal (self, &text,
special_unit, unit_nr, "UNIT NO-PAGE",
"no-page output unit");
unit_nr++;
@@ -3741,34 +3853,33 @@ html_convert_output (CONVERTER *self, ELEMENT *root,
if (self->conf->DEBUG > 0)
fprintf (stderr, "\nNO UNIT NO PAGE\n");
- text_append (&body, self->title_titlepage);
- convert_to_html_internal (self, root, &body,
+ text_append (&text, self->title_titlepage);
+ convert_to_html_internal (self, root, &text,
"no-page output no unit");
footnotes_segment
= call_formatting_function_format_footnotes_segment (self);
if (footnotes_segment)
{
- text_append (&body, footnotes_segment);
+ text_append (&text, footnotes_segment);
free (footnotes_segment);
}
}
/* do end file first, in case it needs some CSS */
- footer = call_formatting_function_format_end_file (self,
+ file_end = call_formatting_function_format_end_file (self,
output_filename, 0);
- header = call_formatting_function_format_begin_file (self,
+ file_beginning = call_formatting_function_format_begin_file (self,
output_filename, 0);
- if (footer)
+ if (file_beginning)
{
- text_append (&result, footer);
- free (footer);
+ text_append (&result, file_beginning);
+ free (file_beginning);
}
- text_append (&result, body.text);
- free (body.text);
- if (header)
+ text_append (&result, text.text);
+ if (file_end)
{
- text_append (&result, header);
- free (header);
+ text_append (&result, file_end);
+ free (file_end);
}
self->current_filename = 0;
self->modified_state |= HMSF_current_filename;
@@ -3777,6 +3888,11 @@ html_convert_output (CONVERTER *self, ELEMENT *root,
{
int unit_nr = 0;
int i;
+ ENCODING_CONVERSION *conversion = 0;
+
+ if (self->conf->OUTPUT_ENCODING_NAME)
+ conversion = get_encoding_conversion (self->conf->OUTPUT_ENCODING_NAME,
+ &output_conversions);
if (self->conf->DEBUG > 0)
fprintf (stderr, "DO Units with filenames\n");
@@ -3784,8 +3900,10 @@ html_convert_output (CONVERTER *self, ELEMENT *root,
for (i = 0; i < output_units->number; i++)
{
OUTPUT_UNIT *output_unit = output_units->list[i];
- convert_output_output_unit_internal (self, &result, output_unit,
- unit_nr);
+ status = convert_output_output_unit_internal (self, conversion,
+ &text, output_unit, unit_nr);
+ if (!status)
+ goto out;
unit_nr++;
}
if (special_units && special_units->number)
@@ -3793,11 +3911,25 @@ html_convert_output (CONVERTER *self, ELEMENT *root,
for (i = 0; i < special_units->number; i++)
{
OUTPUT_UNIT *special_unit = special_units->list[i];
- convert_output_output_unit_internal (self, &result, special_unit,
- unit_nr);
+ status = convert_output_output_unit_internal (self, conversion,
+ &text, special_unit, unit_nr);
+ if (!status)
+ goto out;
unit_nr++;
}
}
+ self->current_filename = 0;
+ self->modified_state |= HMSF_current_filename;
+ }
+
+ out:
+ free (text.text);
+
+ if (status)
+ return result.text;
+ else
+ {
+ free (result.text);
+ return 0;
}
- return result.text;
}
diff --git a/tp/Texinfo/XS/convert/converter.c
b/tp/Texinfo/XS/convert/converter.c
index 49934d339f..ae45a554a9 100644
--- a/tp/Texinfo/XS/convert/converter.c
+++ b/tp/Texinfo/XS/convert/converter.c
@@ -360,33 +360,37 @@ top_node_filename (CONVERTER *self, char *document_name)
void
initialize_output_units_files (CONVERTER *self)
{
- self->output_unit_files = (FILE_NAME_PATH_COUNTER_LIST *)
- malloc (sizeof (FILE_NAME_PATH_COUNTER_LIST));
- memset (self->output_unit_files, 0,
- sizeof (FILE_NAME_PATH_COUNTER_LIST));
+ /* nothing to do, should have been initialized during converter
+ initialization */
}
-static FILE_NAME_PATH_COUNTER *
-find_output_unit_file (CONVERTER *self, char *filename)
+static size_t
+find_output_unit_file (CONVERTER *self, char *filename, int *status)
{
FILE_NAME_PATH_COUNTER_LIST *output_unit_files
- = self->output_unit_files;
+ = &self->output_unit_files;
int i;
+ *status = 0;
+
for (i = 0; i < output_unit_files->number; i++)
{
if (!strcmp (output_unit_files->list[i].normalized_filename, filename))
- return &output_unit_files->list[i];
+ {
+ *status = 1;
+ return i;
+ }
}
return 0;
}
-static FILE_NAME_PATH_COUNTER *
+static size_t
add_output_units_file (CONVERTER *self, char *filename,
char *normalized_filename)
{
+ size_t file_index;
FILE_NAME_PATH_COUNTER *new_output_unit_file;
FILE_NAME_PATH_COUNTER_LIST *output_unit_files
- = self->output_unit_files;
+ = &self->output_unit_files;
if (output_unit_files->number == output_unit_files->space)
{
@@ -396,7 +400,8 @@ add_output_units_file (CONVERTER *self, char *filename,
fatal ("realloc failed");
}
- new_output_unit_file = &output_unit_files->list[output_unit_files->number];
+ file_index = output_unit_files->number;
+ new_output_unit_file = &output_unit_files->list[file_index];
memset (new_output_unit_file, 0, sizeof (FILE_NAME_PATH_COUNTER));
new_output_unit_file->filename = strdup (filename);
if (normalized_filename)
@@ -406,72 +411,84 @@ add_output_units_file (CONVERTER *self, char *filename,
output_unit_files->number++;
- return new_output_unit_file;
+ return file_index;
}
/*
If CASE_INSENSITIVE_FILENAMES is set, reuse the first
filename with the same name insensitive to the case.
*/
-static FILE_NAME_PATH_COUNTER *
+static size_t
register_normalize_case_filename (CONVERTER *self, char *filename)
{
- FILE_NAME_PATH_COUNTER *output_unit_file;
+ size_t output_unit_file_idx;
if (self->conf->CASE_INSENSITIVE_FILENAMES > 0)
{
char *lc_filename = to_upper_or_lower_multibyte (filename, -1);
- output_unit_file = find_output_unit_file (self, lc_filename);
- if (output_unit_file)
+ int status;
+ output_unit_file_idx = find_output_unit_file (self, lc_filename,
&status);
+ if (status)
{
if (self->conf->DEBUG > 0)
{
- fprintf (stderr, "Reusing case-insensitive %s for %s\n",
- output_unit_file->filename, filename);
+ FILE_NAME_PATH_COUNTER *output_unit_file
+ = &self->output_unit_files.list[output_unit_file_idx];
+ fprintf (stderr, "Reusing case-insensitive %s(%zu) for %s\n",
+ output_unit_file->filename, output_unit_file_idx,
+ filename);
}
free (lc_filename);
}
else
{
- output_unit_file = add_output_units_file (self, filename,
- lc_filename);
+ output_unit_file_idx = add_output_units_file (self, filename,
+ lc_filename);
free (lc_filename);
}
}
else
{
- output_unit_file = find_output_unit_file (self, filename);
- if (output_unit_file)
+ int status;
+ output_unit_file_idx = find_output_unit_file (self, filename, &status);
+ if (status)
{
if (self->conf->DEBUG > 0)
{
- fprintf (stderr, "Reusing %s for %s\n",
- output_unit_file->filename, filename);
+ FILE_NAME_PATH_COUNTER *output_unit_file
+ = &self->output_unit_files.list[output_unit_file_idx];
+ fprintf (stderr, "Reusing %s(%zu) for %s\n",
+ output_unit_file->filename, output_unit_file_idx,
+ filename);
}
}
else
- output_unit_file = add_output_units_file (self, filename, 0);
+ output_unit_file_idx = add_output_units_file (self, filename, 0);
}
- return output_unit_file;
+ return output_unit_file_idx;
}
-FILE_NAME_PATH_COUNTER *
+size_t
set_output_unit_file (CONVERTER *self, OUTPUT_UNIT *output_unit,
char *filename, int set_counter)
{
+ size_t output_unit_file_idx
+ = register_normalize_case_filename (self, filename);
FILE_NAME_PATH_COUNTER *output_unit_file
- = register_normalize_case_filename (self, filename);
+ = &self->output_unit_files.list[output_unit_file_idx];
if (set_counter)
output_unit_file->counter++;
output_unit->unit_filename = output_unit_file->filename;
- return output_unit_file;
+ return output_unit_file_idx;
}
void
set_file_path (CONVERTER *self, char *filename, char *filepath,
char *destination_directory)
{
+ size_t output_unit_file_idx
+ = register_normalize_case_filename (self, filename);
FILE_NAME_PATH_COUNTER *output_unit_file
- = register_normalize_case_filename (self, filename);
+ = &self->output_unit_files.list[output_unit_file_idx];
char *filepath_str;
int free_filepath = 0;
diff --git a/tp/Texinfo/XS/convert/converter.h
b/tp/Texinfo/XS/convert/converter.h
index e7e8c087f8..9fab969d77 100644
--- a/tp/Texinfo/XS/convert/converter.h
+++ b/tp/Texinfo/XS/convert/converter.h
@@ -31,8 +31,7 @@ char *top_node_filename (CONVERTER *self, char
*document_name);
void initialize_output_units_files (CONVERTER *self);
-FILE_NAME_PATH_COUNTER *set_output_unit_file (CONVERTER *self,
- OUTPUT_UNIT *output_unit,
+size_t set_output_unit_file (CONVERTER *self, OUTPUT_UNIT *output_unit,
char *filename, int set_counter);
void set_file_path (CONVERTER *self, char *filename, char *filepath,
char *destination_directory);
diff --git a/tp/Texinfo/XS/main/build_perl_info.c
b/tp/Texinfo/XS/main/build_perl_info.c
index 232b8b4bc3..96c8f1cd1b 100644
--- a/tp/Texinfo/XS/main/build_perl_info.c
+++ b/tp/Texinfo/XS/main/build_perl_info.c
@@ -211,6 +211,18 @@ newSVpv_utf8 (const char *str, STRLEN len)
return sv;
}
+/* Used to create a string considered as bytes by perl */
+SV *
+newSVpv_byte (const char *str, STRLEN len)
+{
+ SV *sv;
+ dTHX;
+
+ sv = newSVpv (str, len);
+ SvUTF8_off (sv);
+ return sv;
+}
+
static void
store_additional_info (ELEMENT *e, ASSOCIATED_INFO* a, char *key)
{
@@ -2191,6 +2203,8 @@ build_html_formatting_state (CONVERTER *converter,
unsigned long flags)
AV *document_context_av;
SV **multiple_pass_sv;
AV *multiple_pass_av;
+ SV **file_counters_sv;
+ HV *file_counters_hv;
/*
SV **files_information_sv;
HV *files_information_hv;
@@ -2204,6 +2218,7 @@ build_html_formatting_state (CONVERTER *converter,
unsigned long flags)
hv = converter->hv;
+#define FETCH(key) key##_sv = hv_fetch (hv, #key, strlen (#key), 0);
#define STORE(key, value) hv_store (hv, key, strlen (key), value, 0)
if (flags & HMSF_converter_state)
@@ -2251,8 +2266,7 @@ build_html_formatting_state (CONVERTER *converter,
unsigned long flags)
if (flags & HMSF_document_context)
{
- document_context_sv = hv_fetch (hv, "document_context",
- strlen ("document_context"), 0);
+ FETCH(document_context);
if (!document_context_sv)
{
@@ -2341,8 +2355,7 @@ build_html_formatting_state (CONVERTER *converter,
unsigned long flags)
if (flags & HMSF_multiple_pass)
{
- multiple_pass_sv = hv_fetch (hv, "multiple_pass",
- strlen ("multiple_pass"), 0);
+ FETCH(multiple_pass);
if (!multiple_pass_sv)
{
@@ -2362,6 +2375,31 @@ build_html_formatting_state (CONVERTER *converter,
unsigned long flags)
}
}
+ if (converter->file_changed_counter.number)
+ {
+ FETCH(file_counters);
+ file_counters_hv = (HV *) SvRV (*file_counters_sv);
+
+ int j;
+ for (j = 0; j < converter->file_changed_counter.number; j++)
+ {
+ size_t file_idx = converter->file_changed_counter.list[j];
+ FILE_NAME_PATH_COUNTER *output_unit_file
+ = &converter->output_unit_files.list[file_idx];
+ char *filename = output_unit_file->filename;
+
+ SV *filename_sv = newSVpv_utf8 (filename, 0);
+
+ hv_store_ent (file_counters_hv, filename_sv,
+ newSViv (output_unit_file->counter), 0);
+
+ output_unit_file->counter_changed = 0;
+ }
+ memset (converter->file_changed_counter.list, 0,
+ converter->file_changed_counter.number * sizeof (size_t));
+ converter->file_changed_counter.number = 0;
+ }
+
/*
files_information_sv = hv_fetch (hv, "files_information",
strlen ("files_information"), 0);
@@ -2386,6 +2424,127 @@ build_html_formatting_state (CONVERTER *converter,
unsigned long flags)
return newRV_noinc ((SV *) hv);
}
+/* Texinfo::Common output_files_information API */
+void
+build_output_files_unclosed_files (HV *hv,
+ OUTPUT_FILES_INFORMATION *output_files_information)
+{
+ SV **unclosed_files_sv;
+ HV *unclosed_files_hv;
+
+ FILE_STREAM_LIST *unclosed_files;
+ int i;
+
+ dTHX;
+
+ unclosed_files_sv = hv_fetch (hv, "unclosed_files",
+ strlen ("unclosed_files"), 0);
+
+ if (!unclosed_files_sv)
+ {
+ unclosed_files_hv = newHV ();
+ hv_store (hv, "unclosed_files", strlen ("unclosed_files"),
+ newRV_noinc ((SV *) unclosed_files_hv), 0);
+ }
+ else
+ {
+ unclosed_files_hv = (HV *)SvRV (*unclosed_files_sv);
+ }
+
+ unclosed_files = &output_files_information->unclosed_files;
+ if (unclosed_files->number > 0)
+ {
+ for (i = 0; i < unclosed_files->number; i++)
+ {
+ FILE_STREAM *file_stream = &unclosed_files->list[i];
+ char *file_path = file_stream->file_path;
+ /* FIXME no way to pass back the FILE *stream see comments in
+ converter_types.h. So for now we close here.
+ SV *file_path_sv = newSVpv_byte (file_path, 0);
+ hv_store_ent (unclosed_files_hv, file_path_sv, newSV (0), 0);
+ */
+ if (strcmp (file_path, "-"))
+ {
+ fclose (file_stream->stream);
+ }
+ }
+ }
+}
+
+/* input hv should be an output_files hv, in general setup by
+ $converter->{'output_files'} = Texinfo::Common::output_files_initialize(); */
+void
+build_output_files_opened_files (HV *hv,
+ OUTPUT_FILES_INFORMATION *output_files_information)
+{
+ SV **opened_files_sv;
+ AV *opened_files_av;
+
+ STRING_LIST *opened_files;
+ int i;
+
+ dTHX;
+
+ opened_files_sv = hv_fetch (hv, "opened_files", strlen ("opened_files"), 0);
+
+ if (!opened_files_sv)
+ {
+ opened_files_av = newAV ();
+ hv_store (hv, "opened_files", strlen ("opened_files"),
+ newRV_noinc ((SV *) opened_files_av), 0);
+ }
+ else
+ {
+ opened_files_av = (AV *)SvRV (*opened_files_sv);
+ }
+
+ opened_files = &output_files_information->opened_files;
+ if (opened_files->number > 0)
+ {
+ for (i = 0; i < opened_files->number; i++)
+ {
+ char *file_path = opened_files->list[i];
+ SV *file_path_sv = newSVpv_byte (file_path, 0);
+ av_push (opened_files_av, file_path_sv);
+ }
+ }
+}
+
+/* for the perl converter associated to CONVERTER */
+void
+build_output_files_information (CONVERTER *converter)
+{
+ HV *hv;
+ SV **output_files_sv;
+ HV *output_files_hv;
+
+ dTHX;
+
+ if (!converter->hv)
+ return;
+
+ hv = converter->hv;
+
+ output_files_sv = hv_fetch (hv, "output_files",
+ strlen ("output_files"), 0);
+
+ if (!output_files_sv)
+ {
+ output_files_hv = newHV ();
+ hv_store (hv, "output_files", strlen ("output_files"),
+ newRV_noinc ((SV *) output_files_hv), 0);
+ }
+ else
+ {
+ output_files_hv = (HV *)SvRV (*output_files_sv);
+ }
+
+ build_output_files_opened_files (output_files_hv,
+ &converter->output_files_information);
+ build_output_files_unclosed_files (output_files_hv,
+ &converter->output_files_information);
+}
+
SV *
build_html_command_formatted_args (HTML_ARGS_FORMATTED *args_formatted)
{
diff --git a/tp/Texinfo/XS/main/build_perl_info.h
b/tp/Texinfo/XS/main/build_perl_info.h
index b790c175ed..3638e76962 100644
--- a/tp/Texinfo/XS/main/build_perl_info.h
+++ b/tp/Texinfo/XS/main/build_perl_info.h
@@ -54,5 +54,7 @@ SV *build_out_filepaths (FILE_NAME_PATH_COUNTER_LIST
*output_unit_files);
SV *build_html_formatting_state (CONVERTER *converter, unsigned long flags);
+void build_output_files_information (CONVERTER *converter);
+
SV *build_html_command_formatted_args (HTML_ARGS_FORMATTED *args_formatted);
#endif
diff --git a/tp/Texinfo/XS/main/convert_utils.c
b/tp/Texinfo/XS/main/convert_utils.c
index 6df76949e5..43101d9077 100644
--- a/tp/Texinfo/XS/main/convert_utils.c
+++ b/tp/Texinfo/XS/main/convert_utils.c
@@ -220,6 +220,35 @@ encoded_input_file_name (OPTIONS *options,
return result;
}
+char *
+encoded_output_file_name (OPTIONS *options, GLOBAL_INFO *global_information,
+ char *file_name, char **file_name_encoding,
+ SOURCE_INFO *source_info)
+{
+ char *result;
+ char *encoding = 0;
+ int status;
+
+ if (options && options->OUTPUT_FILE_NAME_ENCODING)
+ encoding = options->OUTPUT_FILE_NAME_ENCODING;
+ else if (options && options->DOC_ENCODING_FOR_OUTPUT_FILE_NAME != 0
+ || (!options))
+ {
+ if (global_information && global_information->input_encoding_name)
+ encoding = global_information->input_encoding_name;
+ }
+ else if (options)
+ encoding = options->LOCALE_ENCODING;
+
+ result = encode_string (file_name, encoding, &status, source_info);
+
+ if (status)
+ *file_name_encoding = strdup(encoding);
+ else
+ *file_name_encoding = 0;
+ return result;
+}
+
ELEMENT *
expand_verbatiminclude (ERROR_MESSAGE_LIST *error_messages,
OPTIONS *options, GLOBAL_INFO *global_information,
@@ -526,3 +555,130 @@ translated_command_tree (CONVERTER *self, enum command_id
cmd)
}
return 0;
}
+
+/*
+ API to open, set encoding and register files.
+*/
+
+/* in Texinfo::Common (because it is also used by main program) */
+
+/* in contrast with perl, we do not handle conversion to output encoding
+ in output_files_open_out, but in the caller program */
+
+static void
+register_unclosed_file (OUTPUT_FILES_INFORMATION *self, const char *file_path,
+ FILE *stream)
+{
+ FILE_STREAM *file_stream;
+ int slot_found = 0;
+ size_t file_stream_index;
+ if (self->unclosed_files.number)
+ {
+ size_t i;
+ for (i = 0; i < self->unclosed_files.number; i++)
+ {
+ file_stream = &self->unclosed_files.list[i];
+ if (file_stream->file_path)
+ {
+ fprintf (stderr, "RUF:%zu: %s\n", i, file_stream->file_path);
+ if (!strcmp (file_path, file_stream->file_path))
+ {
+ fprintf (stderr, "BUG: RUF: already open %zu: %s\n",
+ i, file_path);
+ file_stream->stream = stream;
+ return;
+ }
+ }
+ else if (!slot_found)
+ {
+ file_stream_index = i;
+ slot_found = 1;
+ }
+ }
+ }
+
+ if (!slot_found)
+ {
+ if (self->unclosed_files.number == self->unclosed_files.space)
+ {
+ self->unclosed_files.list = realloc (self->unclosed_files.list,
+ (self->unclosed_files.space += 5) * sizeof (FILE_STREAM));
+ }
+ file_stream_index = self->unclosed_files.number;
+ self->unclosed_files.number++;
+ }
+
+ file_stream = &self->unclosed_files.list[file_stream_index];
+
+ file_stream->file_path = strdup (file_path);
+ file_stream->stream = stream;
+
+ return;
+}
+
+
+/*
+ FILE_PATH is the file path, it should be a binary string.
+ If BINARY is set, set binary mode.
+ Returns
+ - as return value, the opened filehandle, or 0 if opening failed,
+ - in *error_message, the errno message or 0 if opening succeeded.
+*/
+FILE *
+output_files_open_out (OUTPUT_FILES_INFORMATION *self, const char *file_path,
+ char **error_message, int binary)
+{
+ FILE *stream_handle;
+ *error_message = 0;
+ if (!strcmp (file_path, "-"))
+ {
+ register_unclosed_file (self, file_path, stdout);
+ return stdout;
+ }
+ if (binary)
+ stream_handle = fopen (file_path, "wb");
+ else
+ stream_handle = fopen (file_path, "w");
+ if (!stream_handle)
+ {
+ *error_message = strdup (strerror (errno));
+ return 0;
+ }
+ else
+ {
+ register_unclosed_file (self, file_path, stream_handle);
+ add_string (file_path, &self->opened_files);
+ }
+ return stream_handle;
+}
+
+void
+output_files_register_closed (OUTPUT_FILES_INFORMATION *self,
+ const char *file_path)
+{
+ size_t unclosed_files_nr = self->unclosed_files.number;
+ if (unclosed_files_nr)
+ {
+ size_t j;
+ for (j = unclosed_files_nr -1; j >= 0; j--)
+ {
+ FILE_STREAM *file_stream = &self->unclosed_files.list[j];
+ if (file_stream->file_path)
+ {
+ if (!strcmp (file_path, file_stream->file_path))
+ {
+ free (file_stream->file_path);
+ file_stream->file_path = 0;
+ if (j == unclosed_files_nr -1)
+ {
+ self->unclosed_files.number--;
+ }
+ return;
+ }
+ }
+ else
+ fprintf (stderr, "REMARK: no unclosed file at %zu\n", j);
+ }
+ }
+ fprintf (stderr, "BUG: %s not opened\n", file_path);
+}
diff --git a/tp/Texinfo/XS/main/convert_utils.h
b/tp/Texinfo/XS/main/convert_utils.h
index 64bcd1d443..658764f17b 100644
--- a/tp/Texinfo/XS/main/convert_utils.h
+++ b/tp/Texinfo/XS/main/convert_utils.h
@@ -2,6 +2,8 @@
#ifndef CONVERT_UTILS_H
#define CONVERT_UTILS_H
+#include <stdio.h>
+
#include "options_types.h"
#include "tree_types.h"
#include "converter_types.h"
@@ -38,4 +40,15 @@ void destroy_parsed_def (PARSED_DEF *parsed_def);
ELEMENT *definition_category_tree (OPTIONS *options, ELEMENT *current);
ELEMENT *translated_command_tree (CONVERTER *self, enum command_id cmd);
+
+char *encoded_output_file_name (OPTIONS *options,
+ GLOBAL_INFO *global_information,
+ char *file_name, char **file_name_encoding,
+ SOURCE_INFO *source_info);
+
+FILE *output_files_open_out (OUTPUT_FILES_INFORMATION *self,
+ const char *file_path,
+ char **error_message, int binary);
+void output_files_register_closed (OUTPUT_FILES_INFORMATION *self,
+ const char *file_path);
#endif
diff --git a/tp/Texinfo/XS/main/converter_types.h
b/tp/Texinfo/XS/main/converter_types.h
index 4d7e4ba42c..a1d538d2b7 100644
--- a/tp/Texinfo/XS/main/converter_types.h
+++ b/tp/Texinfo/XS/main/converter_types.h
@@ -18,6 +18,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <stddef.h>
+#include <stdio.h>
#include "tree_types.h"
#include "element_types.h"
@@ -270,6 +271,11 @@ typedef struct COMMAND_ID_LIST {
enum command_id *list;
} COMMAND_ID_LIST;
+typedef struct ARRAY_INDEX_LIST {
+ size_t number;
+ size_t *list;
+} ARRAY_INDEX_LIST;
+
typedef struct TRANSLATED_COMMAND {
enum command_id cmd;
char *translation;
@@ -282,6 +288,10 @@ typedef struct FILE_NAME_PATH_COUNTER {
int counter;
int elements_in_file_count; /* only used in HTML, corresponds to
'elements_in_file_count' */
+ TEXT body; /* file body output, used for HTML */
+ OUTPUT_UNIT *first_unit;
+ int counter_changed; /* indicator to determine if the file has already
+ been setup for change in counter passed to perl */
} FILE_NAME_PATH_COUNTER;
typedef struct FILE_NAME_PATH_COUNTER_LIST {
@@ -290,6 +300,34 @@ typedef struct FILE_NAME_PATH_COUNTER_LIST {
FILE_NAME_PATH_COUNTER *list;
} FILE_NAME_PATH_COUNTER_LIST;
+typedef struct FILE_STREAM {
+ char *file_path;
+ /* TODO see https://perldoc.perl.org/perlapio to pass to perl
+ PerlIO_importFILE. This creates a perl io object.
+ PerlIO * PerlIO_importFILE (FILE *stdio, const char *mode)
+ A SV is IO *, created by newIO
+ IO * newIO()
+ the output perolIO of an IO is obtained by:
+ PerlIO *IoOFP(IO *io);
+ FIXME no way to set the PerlIO associated to an IO corresponding
+ to IoOFP?
+ From perlguts
+ All of these accessors macros are lvalues, there are no distinct _set()
macros to modify the members of the IO object.
+ */
+ FILE *stream;
+} FILE_STREAM;
+
+typedef struct FILE_STREAM_LIST {
+ size_t number;
+ size_t space;
+ FILE_STREAM *list;
+} FILE_STREAM_LIST;
+
+typedef struct OUTPUT_FILES_INFORMATION {
+ STRING_LIST opened_files;
+ FILE_STREAM_LIST unclosed_files;
+} OUTPUT_FILES_INFORMATION;
+
typedef struct SPECIAL_UNIT_DIRECTION {
OUTPUT_UNIT *output_unit;
char *direction;
@@ -352,7 +390,10 @@ typedef struct CONVERTER {
EXPANDED_FORMAT *expanded_formats;
/* output unit files API */
- FILE_NAME_PATH_COUNTER_LIST *output_unit_files;
+ FILE_NAME_PATH_COUNTER_LIST output_unit_files;
+
+ /* API to open, set encoding and register files */
+ OUTPUT_FILES_INFORMATION output_files_information;
/* perl converter. This should be HV *hv,
but we don't want to include the Perl headers everywhere; */
@@ -387,14 +428,19 @@ typedef struct CONVERTER {
FORMATTING_REFERENCE output_units_conversion[OU_special_unit+1];
/* state only in C converter */
- unsigned long modified_state; /* to determine if perl data should be
rebuilt */
+ unsigned long modified_state; /* specifies which perl state to rebuild */
ELEMENT *tree_to_build; /* C tree that needs to be built to perl before
calling perl functions on it */
- COMMAND_ID_LIST no_arg_formatted_cmd_translated; /* list of commands that
were
- translated that need to be passed back to perl
*/
- ELEMENT_LIST reset_target_commands; /* element targets that should have
their texts
- reset after language change */
-
+ COMMAND_ID_LIST no_arg_formatted_cmd_translated; /* list of commands that
+ were translated and need to be passed back to perl */
+ ELEMENT_LIST reset_target_commands; /* element targets that should have
+ their texts reset after language
+ change */
+ ARRAY_INDEX_LIST file_changed_counter; /* index of files in
+ output_unit_files with changed counter */
+ size_t *output_unit_file_indices; /* array of indices in
output_unit_files
+ each position corresponding to an output unit. */
+ size_t *special_unit_file_indices; /* same for special output units */
/* state common with perl converter */
int document_global_context;
diff --git a/tp/Texinfo/XS/main/utils.c b/tp/Texinfo/XS/main/utils.c
index 5b462bf921..1ee53f6402 100644
--- a/tp/Texinfo/XS/main/utils.c
+++ b/tp/Texinfo/XS/main/utils.c
@@ -755,15 +755,14 @@ add_include_directory (char *input_filename, STRING_LIST
*include_dirs_list)
}
void
-add_string (char *string, STRING_LIST *strings_list)
+add_string (const char *string, STRING_LIST *strings_list)
{
if (strings_list->number == strings_list->space)
{
strings_list->list = realloc (strings_list->list,
sizeof (char *) * (strings_list->space += 5));
}
- string = strdup (string);
- strings_list->list[strings_list->number++] = string;
+ strings_list->list[strings_list->number++] = strdup (string);
}
void
@@ -783,6 +782,21 @@ merge_strings (STRING_LIST *strings_list, STRING_LIST
*merged_strings)
strings_list->number += merged_strings->number;
}
+/* return the index +1, to return 0 if not found */
+size_t
+find_string (STRING_LIST *strings_list, const char *target)
+{
+ size_t j;
+ for (j = 0; j < strings_list->number; j++)
+ {
+ if (!strcmp (target, strings_list->list[j]))
+ {
+ return j+1;
+ }
+ }
+ return 0;
+}
+
/* Return value to be freed by caller. */
/* try to locate a file called FILENAME, looking for it in the list of include
directories. */
diff --git a/tp/Texinfo/XS/main/utils.h b/tp/Texinfo/XS/main/utils.h
index 3fd9949407..ca9c1ced69 100644
--- a/tp/Texinfo/XS/main/utils.h
+++ b/tp/Texinfo/XS/main/utils.h
@@ -276,8 +276,9 @@ int is_content_empty (ELEMENT *tree, int
do_not_ignore_index_entries);
void clear_strings_list (STRING_LIST *include_dirs_list);
void free_strings_list (STRING_LIST *strings);
void destroy_strings_list (STRING_LIST *strings);
-void add_string (char *string, STRING_LIST *strings_list);
+void add_string (const char *string, STRING_LIST *strings_list);
void merge_strings (STRING_LIST *strings_list, STRING_LIST *merged_strings);
+size_t find_string (STRING_LIST *strings_list, const char *string);
void wipe_index (INDEX *idx);
void wipe_index_names (INDEX **index_names);
diff --git a/tp/texi2any.pl b/tp/texi2any.pl
index f1f7eecff7..de51d7b96a 100755
--- a/tp/texi2any.pl
+++ b/tp/texi2any.pl
@@ -1400,7 +1400,7 @@ my $with_XS = ((not defined($ENV{TEXINFO_XS})
my $file_number = -1;
my @opened_files = ();
-my %unclosed_files;
+my %main_unclosed_files;
my $error_count = 0;
# main processing
while(@input_files) {
@@ -1697,7 +1697,7 @@ while(@input_files) {
if ($converter_unclosed_files) {
foreach my $unclosed_file (keys(%$converter_unclosed_files)) {
if ($unclosed_file eq '-') {
- $unclosed_files{$unclosed_file}
+ $main_unclosed_files{$unclosed_file}
= $converter_unclosed_files->{$unclosed_file};
} else {
if (!close($converter_unclosed_files->{$unclosed_file})) {
@@ -1827,8 +1827,8 @@ while(@input_files) {
Texinfo::Document::remove_document($document);
}
-foreach my $unclosed_file (keys(%unclosed_files)) {
- if (!close($unclosed_files{$unclosed_file})) {
+foreach my $unclosed_file (keys(%main_unclosed_files)) {
+ if (!close($main_unclosed_files{$unclosed_file})) {
warn(sprintf(__("%s: error on closing %s: %s\n"),
$real_command_name, $unclosed_file, $!));
$error_count++;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- branch master updated: * tp/Texinfo/Convert/HTML.pm (_html_convert_output): if a special element body is empty, do not return immediately but check if there is already a body registered with the file, as in that case, the body would need to be output.,
Patrice Dumas <=