texinfo-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[no subject]


From: Patrice Dumas
Date: Thu, 21 Dec 2023 16:36:59 -0500 (EST)

branch: master
commit 133bd0b7a6c265236e09d2af63c165ec24c73c0f
Author: Patrice Dumas <pertusus@free.fr>
AuthorDate: Wed Dec 20 14:39:21 2023 +0100

    * tp/Texinfo/Convert/HTML.pm (%XS_conversion_overrides)
    (_push_referred_command_stack_command, _pop_referred_command_stack)
    (_command_is_in_referred_command_stack, command_text)
    (_convert_xref_commands), tp/Texinfo/XS/convert/ConvertXS.xs
    (html_push_referred_command_stack_command)
    (html_pop_referred_command_stack)
    (html_command_is_in_referred_command_stack),
    tp/Texinfo/XS/convert/convert_html.c (html_command_text),
    tp/Texinfo/XS/main/command_stack.c
    (push_element_reference_stack_element)
    (pop_element_reference_stack, command_is_in_referred_command_stack),
    tp/Texinfo/XS/main/converter_types.h (ELEMENT_REFERENCE)
    (ELEMENT_REFERENCE_STACK, CONVERTER): add accessors around
    referred_command_stack state and override them to make sure that the
    state viewed from perl and C is the same, both from C to perl and perl
    to C.
    
    * tp/Texinfo/XS/convert/build_html_perl_state.c
    (build_html_formatting_state): remove the previous way to synchronize
    referred_command_stack from C to perl.
    
    * tp/Texinfo/Convert/HTML.pm (_initialize_output_state)
    (_initialize_XS_NonXS_output_state): move
    check_htmlxref_already_warned and referred_command_stack
    initialization to _initialize_output_state.
---
 ChangeLog                                     | 28 +++++++++++++++
 tp/TODO                                       | 15 ++++++++
 tp/Texinfo/Convert/HTML.pm                    | 50 +++++++++++++++++++++------
 tp/Texinfo/XS/convert/ConvertXS.xs            | 48 +++++++++++++++++++++++++
 tp/Texinfo/XS/convert/build_html_perl_state.c | 27 ---------------
 tp/Texinfo/XS/convert/convert_html.c          | 11 +++---
 tp/Texinfo/XS/main/command_stack.c            | 50 +++++++++++++++++++++++++++
 tp/Texinfo/XS/main/command_stack.h            |  6 ++++
 tp/Texinfo/XS/main/converter_types.h          | 17 ++++++++-
 tp/Texinfo/XS/main/utils.h                    |  2 +-
 10 files changed, 208 insertions(+), 46 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 0c0c479efd..e40d190ac5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -29,6 +29,34 @@
        Eliminate use of Texinfo::Convert::Unicode::string_width on
        converted output.
 
+2023-12-19  Patrice Dumas  <pertusus@free.fr>
+
+       * tp/Texinfo/Convert/HTML.pm (%XS_conversion_overrides)
+       (_push_referred_command_stack_command, _pop_referred_command_stack)
+       (_command_is_in_referred_command_stack, command_text)
+       (_convert_xref_commands), tp/Texinfo/XS/convert/ConvertXS.xs
+       (html_push_referred_command_stack_command)
+       (html_pop_referred_command_stack)
+       (html_command_is_in_referred_command_stack),
+       tp/Texinfo/XS/convert/convert_html.c (html_command_text),
+       tp/Texinfo/XS/main/command_stack.c
+       (push_element_reference_stack_element)
+       (pop_element_reference_stack, command_is_in_referred_command_stack),
+       tp/Texinfo/XS/main/converter_types.h (ELEMENT_REFERENCE)
+       (ELEMENT_REFERENCE_STACK, CONVERTER): add accessors around
+       referred_command_stack state and override them to make sure that the
+       state viewed from perl and C is the same, both from C to perl and perl
+       to C.
+
+       * tp/Texinfo/XS/convert/build_html_perl_state.c
+       (build_html_formatting_state): remove the previous way to synchronize
+       referred_command_stack from C to perl.
+
+       * tp/Texinfo/Convert/HTML.pm (_initialize_output_state)
+       (_initialize_XS_NonXS_output_state): move
+       check_htmlxref_already_warned and referred_command_stack
+       initialization to _initialize_output_state.
+
 2023-12-19  Patrice Dumas  <pertusus@free.fr>
 
        * tp/Texinfo/Convert/HTML.pm
diff --git a/tp/TODO b/tp/TODO
index c1b797ba16..56460d3fed 100644
--- a/tp/TODO
+++ b/tp/TODO
@@ -103,6 +103,21 @@ the context command stack.
  @end defun
 
 
+For HTML conversion it is possible that the conversion and caching of
+element text (in general for directions href) is done at different
+moments with conversion in perl only and conversion with a mix of perl
+code and C code.  Indeed, if an element text is formatted in C and
+will be needed later on in perl it will be formatted later on in perl
+in that setup compared to the pure perl case.  In general the moment
+of first conversion of element text does not matter much, but it does
+in specific cases, for instance with recursive definitions of sectioning
+commands (with a @ref in sectioning command).  This is tested in test
+30sectioning.t double_recursive_self_section_reference.
+With @ref converted in perl and other parts of the conversions
+in C, an href for a direction differs for this test.  If @ref is also
+converted in C, this issue is invisible.
+
+
 Modules included in tp/maintain/lib/ need to be updated from time to
 time.
 
diff --git a/tp/Texinfo/Convert/HTML.pm b/tp/Texinfo/Convert/HTML.pm
index ef0f3ae46f..089dfb82c1 100644
--- a/tp/Texinfo/Convert/HTML.pm
+++ b/tp/Texinfo/Convert/HTML.pm
@@ -215,6 +215,12 @@ my %XS_conversion_overrides = (
    => 
"Texinfo::Convert::ConvertXS::html_associate_pending_formatted_inline_content",
   "Texinfo::Convert::HTML::get_associated_formatted_inline_content",
    => 
"Texinfo::Convert::ConvertXS::html_get_associated_formatted_inline_content",
+  "Texinfo::Convert::HTML::_push_referred_command_stack_command"
+   => "Texinfo::Convert::ConvertXS::html_push_referred_command_stack_command",
+  "Texinfo::Convert::HTML::_pop_referred_command_stack"
+   => "Texinfo::Convert::ConvertXS::html_pop_referred_command_stack",
+  "Texinfo::Convert::HTML::_command_is_in_referred_command_stack"
+   => "Texinfo::Convert::ConvertXS::html_command_is_in_referred_command_stack",
   "Texinfo::Convert::HTML::_check_htmlxref_already_warned"
    => "Texinfo::Convert::ConvertXS::html_check_htmlxref_already_warned",
 
@@ -1261,6 +1267,27 @@ sub command_tree($$;$)
   return undef;
 }
 
+sub _push_referred_command_stack_command($$)
+{
+  my $self = shift;
+  my $command = shift;
+  push @{$self->{'referred_command_stack'}}, $command;
+}
+
+sub _pop_referred_command_stack($)
+{
+  my $self = shift;
+  pop @{$self->{'referred_command_stack'}};
+}
+
+sub _command_is_in_referred_command_stack($$)
+{
+  my $self = shift;
+  my $command = shift;
+
+  return grep {$_ eq $command} @{$self->{'referred_command_stack'}};
+}
+
 # Return text to be used for a hyperlink to $COMMAND.
 # $TYPE refers to the type of value returned from this function:
 #  'text' - return text
@@ -1335,9 +1362,10 @@ sub command_text($$;$)
     }
 
     $self->{'ignore_notice'}++;
-    push @{$self->{'referred_command_stack'}}, $command;
+
+    _push_referred_command_stack_command($self, $command);
     $target->{$type} = $self->_convert($tree_root, $explanation);
-    pop @{$self->{'referred_command_stack'}};
+    _pop_referred_command_stack($self);
     $self->{'ignore_notice'}--;
 
     $self->_pop_document_context();
@@ -5643,8 +5671,8 @@ sub _convert_xref_commands($$$$)
          # possible to construct an infinite recursion with nodes only
          # as the node must both be a reference target and refer to a specific
          # target at the same time, which is not possible.
-         and not grep {$_ eq $target_node->{'extra'}->{'associated_section'}}
-                     @{$self->{'referred_command_stack'}}) {
+         and not _command_is_in_referred_command_stack($self,
+                          $target_node->{'extra'}->{'associated_section'})) {
         $target_root = $target_node->{'extra'}->{'associated_section'};
         $name = $self->command_text($target_root, 'text_nonumber');
       } elsif ($target_node->{'cmdname'} eq 'float') {
@@ -11267,6 +11295,13 @@ sub _initialize_output_state($$)
   $self->{'pending_footnotes'} = [];
   $self->{'pending_closes'} = [];
 
+  # to avoid infinite recursions when a section refers to itself, possibly
+  # indirectly
+  $self->{'referred_command_stack'} = [];
+
+  $self->{'check_htmlxref_already_warned'} = {}
+    if ($self->get_conf('CHECK_HTMLXREF'));
+
   $self->_new_document_context($context);
 }
 
@@ -11304,13 +11339,6 @@ sub _initialize_XS_NonXS_output_state($$)
 
   # for footnotes
   $self->{'special_targets'} = {'footnote_location' => {}};
-
-  # to avoid infinite recursions when a section refers to itself, possibly
-  # indirectly
-  $self->{'referred_command_stack'} = [];
-
-  $self->{'check_htmlxref_already_warned'} = {}
-    if ($self->get_conf('CHECK_HTMLXREF'));
 }
 
 sub _finalize_output_state($)
diff --git a/tp/Texinfo/XS/convert/ConvertXS.xs 
b/tp/Texinfo/XS/convert/ConvertXS.xs
index 767d32e64c..b1096017c7 100644
--- a/tp/Texinfo/XS/convert/ConvertXS.xs
+++ b/tp/Texinfo/XS/convert/ConvertXS.xs
@@ -1098,6 +1098,54 @@ html_get_associated_formatted_inline_content (SV 
*converter_in, SV *element_sv)
     OUTPUT:
          RETVAL
 
+# we do not increase here and decrease in pop the element_hv refcount, under
+# the assumption that there is already a reference held by the C tree on
+# the element.
+void
+html_push_referred_command_stack_command (SV *converter_in, SV *element_sv)
+      PREINIT:
+         CONVERTER *self;
+     CODE:
+         self = get_sv_converter (converter_in,
+                                  "html_push_referred_command_stack_command");
+         if (self)
+           {
+             const HV *element_hv = (HV *) SvRV (element_sv);
+             push_element_reference_stack_element (
+              &self->referred_command_stack, 0, (const void *)element_hv);
+           }
+
+void
+html_pop_referred_command_stack (SV *converter_in)
+      PREINIT:
+         CONVERTER *self;
+     CODE:
+         self = get_sv_converter (converter_in,
+                                  "html_pop_referred_command_stack");
+         if (self)
+           {
+             pop_element_reference_stack (&self->referred_command_stack);
+           }
+
+int
+html_command_is_in_referred_command_stack (SV *converter_in, SV *element_sv)
+      PREINIT:
+         CONVERTER *self;
+         int found = 0;
+     CODE:
+         self = get_sv_converter (converter_in,
+                               "html_command_is_in_referred_command_stack");
+         if (self)
+           {
+             const HV *element_hv = (HV *) SvRV (element_sv);
+             found = command_is_in_referred_command_stack (
+                      &self->referred_command_stack, 0,
+                      (const void *)element_hv);
+           }
+         RETVAL = found;
+    OUTPUT:
+         RETVAL
+
 int
 html_check_htmlxref_already_warned (SV *converter_in, manual_name, SV 
*source_info_sv)
          char *manual_name = (char *)SvPVutf8_nolen($arg);
diff --git a/tp/Texinfo/XS/convert/build_html_perl_state.c 
b/tp/Texinfo/XS/convert/build_html_perl_state.c
index 12af08aa19..bdde83acf4 100644
--- a/tp/Texinfo/XS/convert/build_html_perl_state.c
+++ b/tp/Texinfo/XS/convert/build_html_perl_state.c
@@ -755,33 +755,6 @@ build_html_formatting_state (CONVERTER *converter, 
unsigned long flags)
         }
     }
 
-  if (flags & HMSF_referred_command_stack)
-    {
-      SV **referred_command_stack_sv;
-      AV *referred_command_stack_av;
-
-      FETCH(referred_command_stack);
-
-      if (!referred_command_stack_sv)
-        {
-          referred_command_stack_av = newAV ();
-          STORE("referred_command_stack",
-                newRV_noinc ((SV *) referred_command_stack_av));
-        }
-      else
-        {
-          referred_command_stack_av = (AV *) SvRV (*referred_command_stack_sv);
-          av_clear (referred_command_stack_av);
-        }
-
-      for (i = 0; i < converter->referred_command_stack.top; i++)
-        {
-          const ELEMENT *referred_e = 
converter->referred_command_stack.stack[i];
-          av_push (referred_command_stack_av,
-                   newRV_inc ((SV *) referred_e->hv));
-        }
-    }
-
   if (converter->added_targets.number)
     {
       SV **targets_sv;
diff --git a/tp/Texinfo/XS/convert/convert_html.c 
b/tp/Texinfo/XS/convert/convert_html.c
index 16acf4e016..1f87491aae 100644
--- a/tp/Texinfo/XS/convert/convert_html.c
+++ b/tp/Texinfo/XS/convert/convert_html.c
@@ -3884,16 +3884,15 @@ html_command_text (CONVERTER *self, const ELEMENT 
*command,
             tree_root = selected_tree;
 
           self->ignore_notice++;
-          push_stack_element (&self->referred_command_stack, command);
-          self->modified_state |= HMSF_referred_command_stack
-                                   | HMSF_converter_state;
+          push_element_reference_stack_element (&self->referred_command_stack,
+                                                command, command->hv);
+          self->modified_state |= HMSF_converter_state;
           target_info->command_text[type]
             = html_convert_tree (self, tree_root, explanation);
           free (explanation);
-          pop_stack_element (&self->referred_command_stack);
+          pop_element_reference_stack (&self->referred_command_stack);
           self->ignore_notice--;
-          self->modified_state |= HMSF_referred_command_stack
-                                   | HMSF_converter_state;
+          self->modified_state |= HMSF_converter_state;
 
           html_pop_document_context (self);
 
diff --git a/tp/Texinfo/XS/main/command_stack.c 
b/tp/Texinfo/XS/main/command_stack.c
index 150c667631..322fd6caf8 100644
--- a/tp/Texinfo/XS/main/command_stack.c
+++ b/tp/Texinfo/XS/main/command_stack.c
@@ -219,6 +219,56 @@ pop_stack_element (ELEMENT_STACK *stack)
 }
 
 
+/* elements stack that can also be called from an external language (perl)
+   where there is no reference to C elements */
+void
+push_element_reference_stack_element (ELEMENT_REFERENCE_STACK *stack,
+                                      const ELEMENT *e, const void *hv)
+{
+  if (stack->top >= stack->space)
+  {
+    stack->stack
+      = realloc (stack->stack,
+                 (stack->space += 5) * sizeof (ELEMENT_STACK));
+  }
+
+  memset (&stack->stack[stack->top], 0, sizeof (ELEMENT_STACK));
+
+  if (e)
+    stack->stack[stack->top].element = e;
+  if (hv)
+    stack->stack[stack->top].hv = hv;
+
+  stack->top++;
+}
+
+void
+pop_element_reference_stack (ELEMENT_REFERENCE_STACK *stack)
+{
+  if (stack->top == 0)
+    fatal ("element reference stack empty for top");
+
+  stack->top--;
+}
+
+int
+command_is_in_referred_command_stack (ELEMENT_REFERENCE_STACK *stack,
+                                      const ELEMENT *e, const void *hv)
+{
+  size_t i;
+  for (i = 0; i < stack->top; i++)
+    {
+      ELEMENT_REFERENCE *element_reference = &stack->stack[i];
+      if (e && element_reference->element == e
+          || hv && element_reference->hv == hv)
+        {
+          return 1;
+        }
+    }
+  return 0;
+}
+
+
 /* HTML specific but also used to build perl */
 HTML_DOCUMENT_CONTEXT *
 html_top_document_context (CONVERTER *self)
diff --git a/tp/Texinfo/XS/main/command_stack.h 
b/tp/Texinfo/XS/main/command_stack.h
index 18c7f6c30a..dd1d7de618 100644
--- a/tp/Texinfo/XS/main/command_stack.h
+++ b/tp/Texinfo/XS/main/command_stack.h
@@ -44,6 +44,12 @@ int top_integer_stack (INTEGER_STACK *stack);
 void push_stack_element (ELEMENT_STACK *stack, const ELEMENT *e);
 const ELEMENT *pop_stack_element (ELEMENT_STACK *stack);
 
+void push_element_reference_stack_element (ELEMENT_REFERENCE_STACK *stack,
+                                      const ELEMENT *e, const void *hv);
+void pop_element_reference_stack (ELEMENT_REFERENCE_STACK *stack);
+int command_is_in_referred_command_stack (ELEMENT_REFERENCE_STACK *stack,
+                                      const ELEMENT *e, const void *hv);
+
 HTML_DOCUMENT_CONTEXT *html_top_document_context (CONVERTER *self);
 
 HTML_FORMATTING_CONTEXT *html_top_formatting_context
diff --git a/tp/Texinfo/XS/main/converter_types.h 
b/tp/Texinfo/XS/main/converter_types.h
index 350030843b..05afce8d97 100644
--- a/tp/Texinfo/XS/main/converter_types.h
+++ b/tp/Texinfo/XS/main/converter_types.h
@@ -230,6 +230,21 @@ typedef struct ELEMENT_STACK {
     size_t space;
 } ELEMENT_STACK;
 
+/* an element in C, and/or a reference to an external language (perl)
+   for stack functions called from outside of the C converter */
+typedef struct ELEMENT_REFERENCE {
+    const ELEMENT *element;
+  /* perl element. This should be HV *hv,
+     but we don't want to include the Perl headers everywhere; */
+    const void *hv;
+} ELEMENT_REFERENCE;
+
+typedef struct ELEMENT_REFERENCE_STACK {
+    ELEMENT_REFERENCE *stack;
+    size_t top;
+    size_t space;
+} ELEMENT_REFERENCE_STACK;
+
 typedef struct FILE_NUMBER_NAME {
     size_t file_number;
     char *filename;
@@ -750,7 +765,7 @@ typedef struct CONVERTER {
     STRING_STACK multiple_pass;
     STRING_STACK pending_closes;
     FILE_NUMBER_NAME current_filename;
-    ELEMENT_STACK referred_command_stack;
+    ELEMENT_REFERENCE_STACK referred_command_stack;
     HTML_SHARED_CONVERSION_STATE shared_conversion_state;
     HTML_INLINE_CONTENT_STACK pending_inline_content;
     HTML_PENDING_FOOTNOTE_STACK pending_footnotes;
diff --git a/tp/Texinfo/XS/main/utils.h b/tp/Texinfo/XS/main/utils.h
index d66707167e..66cfea6b9d 100644
--- a/tp/Texinfo/XS/main/utils.h
+++ b/tp/Texinfo/XS/main/utils.h
@@ -138,7 +138,7 @@ enum command_location {
 #define HMSF_translations            0x4000
 #define HMSF_            0x8000
 #define HMSF_added_target            0x00010000
-#define HMSF_referred_command_stack  0x00020000
+#define HMSF_  0x00020000
 
 typedef struct TARGET_FILENAME {
     char *target;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]