texinfo-commits
[Top][All Lists]
Advanced

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

branch master updated: * tp/Texinfo/XS/convert/get_html_perl_info.c (fin


From: Patrice Dumas
Subject: branch master updated: * tp/Texinfo/XS/convert/get_html_perl_info.c (find_element_from_sv): use output_units_descriptor only if set.
Date: Mon, 25 Dec 2023 19:56:55 -0500

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 28dc2bb7a1 * tp/Texinfo/XS/convert/get_html_perl_info.c 
(find_element_from_sv): use output_units_descriptor only if set.
28dc2bb7a1 is described below

commit 28dc2bb7a1ee5a731935cb94dea0b53d9f95489d
Author: Patrice Dumas <pertusus@free.fr>
AuthorDate: Tue Dec 26 01:56:52 2023 +0100

    * tp/Texinfo/XS/convert/get_html_perl_info.c (find_element_from_sv):
    use output_units_descriptor only if set.
    
    * tp/Texinfo/XS/main/utils.c (expanded_formats_number): add.
    
    * tp/Texinfo/XS/main/utils.c (index_number_index_by_name): add.
    
    * tp/Texinfo/XS/convert/convert_html.c (prepare_index_entries_targets)
    (html_initialize_output_state, html_reset_converter),
    tp/Texinfo/XS/main/converter_types.h (CONVERTER, INDEX_NUMBER)
    (SORTED_INDEX_NAMES): sort index names
    and add a corresponding structure.
    
    * tp/Texinfo/XS/convert/convert_html.c (html_reset_converter),
    tp/Texinfo/XS/main/converter_types.h (HTML_SHARED_CONVERSION_STATE):
    add formatted_index_entries shared_conversion_state.
    
    * tp/Texinfo/XS/convert/convert_html.c (html_reset_converter),
    tp/Texinfo/XS/main/converter_types.h (HTML_SHARED_CONVERSION_STATE): add
    expanded_format_raw shared_conversion_state.
    
    * tp/Texinfo/XS/main/converter_types.h (HTML_TARGET): add
    formatted_nodedescription_nr for formatted_nodedescriptions
    shared_conversion_state.
    
    * tp/Texinfo/XS/convert/get_html_perl_info.c
    (find_index_entry_numbers_extra_index_entry_sv)
    (find_index_entry_extra_index_entry_sv): rename
    find_index_entry_element as find_element_extra_index_entry_sv, add
    find_index_entry_numbers_extra_index_entry_sv.
    
    * tp/Texinfo/Convert/HTML.pm (%default_shared_conversion_states)
    (define_shared_conversion_state, get_shared_conversion_state)
    (set_shared_conversion_state, register_footnote)
    (_convert_explained_command, _convert_footnote_command)
    (_convert_heading_command, _convert_menu_command)
    (_convert_printindex_command, _convert_menu_entry_type)
    (_initialize_XS_NonXS_output_state),
    tp/Texinfo/XS/convert/convert_html.c (html_register_footnote)
    (prepare_index_entries_targets, convert_heading_command),
    tp/init/book.pm b/tp/init/book.pm: change shared_conversion_state API,
    replace with define_shared_conversion_state, which sets the data
    specification, get_shared_conversion_state and
    set_shared_conversion_state.  Add %default_shared_conversion_states
    for the share_conversion_state data description used in default HTML
    conversion code.
    
    * tp/Texinfo/Convert/HTML.pm (%XS_conversion_overrides)
    (_XS_get_shared_conversion_state, get_shared_conversion_state)
    (_get_shared_conversion_state, _XS_set_shared_conversion_state)
    (get_shared_conversion_state, _initialize_output_state),
    tp/Texinfo/XS/convert/ConvertXS.xs (html_set_shared_conversion_state)
    (html_get_shared_conversion_state),
    tp/Texinfo/XS/convert/get_html_perl_info.c
    (find_index_entry_numbers_index_entry_sv)
    (find_node_target_info_nodedescription_sv)
    (html_set_shared_conversion_state, html_get_shared_conversion_state):
    XS override for get_shared_conversion_state and
    set_shared_conversion_state for the share_conversion_state data used
    in default HTML conversion code.
    
    * tp/Texinfo/XS/convert/build_html_perl_state.c
    (build_html_formatting_state),
    tp/Texinfo/XS/convert/call_html_perl_function.c,
    tp/Texinfo/XS/convert/convert_html.c (html_finalize_output_state)
    (html_free_converter), tp/Texinfo/XS/main/converter_types.h
    (CONVERTER): remove code for passing information to and from C and
    perl for previous shared_conversion_state.  Remove
    get_shared_conversion_state, get_shared_conversion_state_integer and
    register_modified_shared_conversion_state_integer.
    
    * tp/Texinfo/XS/*/*.*: add some const, with some minor code
    modification when needed.
---
 ChangeLog                                       |  76 +++++
 tp/Texinfo/Convert/HTML.pm                      | 360 ++++++++++++++++++------
 tp/Texinfo/XS/convert/ConvertXS.xs              |  55 +++-
 tp/Texinfo/XS/convert/build_html_perl_state.c   |  45 +--
 tp/Texinfo/XS/convert/call_html_perl_function.c | 117 +-------
 tp/Texinfo/XS/convert/convert_html.c            | 174 ++++++------
 tp/Texinfo/XS/convert/convert_html.h            |  12 +-
 tp/Texinfo/XS/convert/get_html_perl_info.c      | 320 +++++++++++++++++++--
 tp/Texinfo/XS/convert/get_html_perl_info.h      |   7 +
 tp/Texinfo/XS/main/builtin_commands.c           |   7 +-
 tp/Texinfo/XS/main/builtin_commands.h           |   4 +-
 tp/Texinfo/XS/main/convert_to_texinfo.c         |   2 +-
 tp/Texinfo/XS/main/converter_types.h            |  33 ++-
 tp/Texinfo/XS/main/debug.c                      |   2 +-
 tp/Texinfo/XS/main/extra.c                      |   8 +-
 tp/Texinfo/XS/main/extra.h                      |   8 +-
 tp/Texinfo/XS/main/utils.c                      |  25 +-
 tp/Texinfo/XS/main/utils.h                      |   7 +-
 tp/Texinfo/XS/parsetexi/debug_parser.c          |   2 +-
 tp/Texinfo/XS/parsetexi/debug_parser.h          |   2 +-
 tp/Texinfo/XS/parsetexi/end_line.c              |   2 +-
 tp/Texinfo/XS/parsetexi/handle_commands.c       |   7 +-
 tp/Texinfo/XS/parsetexi/handle_commands.h       |   2 +-
 tp/Texinfo/XS/parsetexi/input.c                 |  10 +-
 tp/Texinfo/XS/parsetexi/input.h                 |   6 +-
 tp/Texinfo/XS/parsetexi/parser.c                |   2 +-
 tp/Texinfo/XS/parsetexi/separator.c             |   2 +-
 tp/Texinfo/XS/structuring_transfo/structuring.c |   2 +-
 tp/init/book.pm                                 |  24 +-
 29 files changed, 906 insertions(+), 417 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 0e3d58ada7..e407cd1a17 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,79 @@
+2023-12-25  Patrice Dumas  <pertusus@free.fr>
+
+       * tp/Texinfo/XS/convert/get_html_perl_info.c (find_element_from_sv):
+       use output_units_descriptor only if set.
+
+       * tp/Texinfo/XS/main/utils.c (expanded_formats_number): add.
+
+       * tp/Texinfo/XS/main/utils.c (index_number_index_by_name): add.
+
+       * tp/Texinfo/XS/convert/convert_html.c (prepare_index_entries_targets)
+       (html_initialize_output_state, html_reset_converter),
+       tp/Texinfo/XS/main/converter_types.h (CONVERTER, INDEX_NUMBER)
+       (SORTED_INDEX_NAMES): sort index names
+       and add a corresponding structure.
+
+       * tp/Texinfo/XS/convert/convert_html.c (html_reset_converter),
+       tp/Texinfo/XS/main/converter_types.h (HTML_SHARED_CONVERSION_STATE):
+       add formatted_index_entries shared_conversion_state.
+
+       * tp/Texinfo/XS/convert/convert_html.c (html_reset_converter),
+       tp/Texinfo/XS/main/converter_types.h (HTML_SHARED_CONVERSION_STATE): add
+       expanded_format_raw shared_conversion_state.
+
+       * tp/Texinfo/XS/main/converter_types.h (HTML_TARGET): add
+       formatted_nodedescription_nr for formatted_nodedescriptions
+       shared_conversion_state.
+
+       * tp/Texinfo/XS/convert/get_html_perl_info.c
+       (find_index_entry_numbers_extra_index_entry_sv)
+       (find_index_entry_extra_index_entry_sv): rename
+       find_index_entry_element as find_element_extra_index_entry_sv, add
+       find_index_entry_numbers_extra_index_entry_sv.
+
+       * tp/Texinfo/Convert/HTML.pm (%default_shared_conversion_states)
+       (define_shared_conversion_state, get_shared_conversion_state)
+       (set_shared_conversion_state, register_footnote)
+       (_convert_explained_command, _convert_footnote_command)
+       (_convert_heading_command, _convert_menu_command)
+       (_convert_printindex_command, _convert_menu_entry_type)
+       (_initialize_XS_NonXS_output_state),
+       tp/Texinfo/XS/convert/convert_html.c (html_register_footnote)
+       (prepare_index_entries_targets, convert_heading_command),
+       tp/init/book.pm b/tp/init/book.pm: change shared_conversion_state API,
+       replace with define_shared_conversion_state, which sets the data
+       specification, get_shared_conversion_state and
+       set_shared_conversion_state.  Add %default_shared_conversion_states
+       for the share_conversion_state data description used in default HTML
+       conversion code.
+
+       * tp/Texinfo/Convert/HTML.pm (%XS_conversion_overrides)
+       (_XS_get_shared_conversion_state, get_shared_conversion_state)
+       (_get_shared_conversion_state, _XS_set_shared_conversion_state)
+       (get_shared_conversion_state, _initialize_output_state),
+       tp/Texinfo/XS/convert/ConvertXS.xs (html_set_shared_conversion_state)
+       (html_get_shared_conversion_state),
+       tp/Texinfo/XS/convert/get_html_perl_info.c
+       (find_index_entry_numbers_index_entry_sv)
+       (find_node_target_info_nodedescription_sv)
+       (html_set_shared_conversion_state, html_get_shared_conversion_state):
+       XS override for get_shared_conversion_state and
+       set_shared_conversion_state for the share_conversion_state data used
+       in default HTML conversion code.
+
+       * tp/Texinfo/XS/convert/build_html_perl_state.c
+       (build_html_formatting_state),
+       tp/Texinfo/XS/convert/call_html_perl_function.c,
+       tp/Texinfo/XS/convert/convert_html.c (html_finalize_output_state)
+       (html_free_converter), tp/Texinfo/XS/main/converter_types.h
+       (CONVERTER): remove code for passing information to and from C and
+       perl for previous shared_conversion_state.  Remove
+       get_shared_conversion_state, get_shared_conversion_state_integer and
+       register_modified_shared_conversion_state_integer.
+
+       * tp/Texinfo/XS/*/*.*: add some const, with some minor code
+       modification when needed.
+
 2023-12-24  Patrice Dumas  <pertusus@free.fr>
 
        * tp/Texinfo/Convert/HTML.pm (%default_commands_args)
diff --git a/tp/Texinfo/Convert/HTML.pm b/tp/Texinfo/Convert/HTML.pm
index e209346917..f2ec7623a9 100644
--- a/tp/Texinfo/Convert/HTML.pm
+++ b/tp/Texinfo/Convert/HTML.pm
@@ -151,6 +151,11 @@ my %XS_conversion_overrides = (
   "Texinfo::Convert::HTML::_internal_command_text"
    => "Texinfo::Convert::ConvertXS::html_internal_command_text",
 
+  "Texinfo::Convert::HTML::_XS_set_shared_conversion_state"
+   => "Texinfo::Convert::ConvertXS::html_set_shared_conversion_state",
+  "Texinfo::Convert::HTML::_XS_get_shared_conversion_state"
+   => "Texinfo::Convert::ConvertXS::html_get_shared_conversion_state",
+
   "Texinfo::Convert::HTML::_open_command_update_context"
    => "Texinfo::Convert::ConvertXS::html_open_command_update_context",
   "Texinfo::Convert::HTML::_convert_command_update_context",
@@ -1958,29 +1963,182 @@ sub get_value($$)
   }
 }
 
-# $INITIALIZATION_VALUE is only used for the initialization.
-# If it is not a reference, it is turned into a scalar reference.
-sub shared_conversion_state($$;$)
+my %default_shared_conversion_states = (
+  'top' => {'in_skipped_node_top' => ['integer'],
+            'expanded_format_raw' => ['string', 'integer']},
+  'abbr' => {'explained_commands' => ['string', 'string']},
+  'acronym' => {'explained_commands' => ['string', 'string']},
+  'footnote' => {'footnote_number' => ['integer'],
+                 'footnote_id_numbers' => ['string', 'integer']},
+  'menu' => {'html_menu_entry_index' => ['integer']},
+  'printindex' => {'formatted_index_entries' => ['index_entry', 'integer']},
+  'nodedescription' => {'formatted_nodedescriptions' => ['element', 
'integer']},
+);
+
+sub define_shared_conversion_state($$$$)
+{
+  my $self = shift;
+  my $cmdname = shift;
+  my $state_name = shift;
+  my $specification = shift;
+
+  if (not defined($self->{'shared_conversion_state'}->{$cmdname})) {
+    $self->{'shared_conversion_state'}->{$cmdname} = {};
+  }
+  if (not defined($self->{'shared_conversion_state'}
+                                      ->{$cmdname}->{$state_name})) {
+    $self->{'shared_conversion_state'}->{$cmdname}->{$state_name} = {};
+  }
+
+  my $state = $self->{'shared_conversion_state'}->{$cmdname}->{$state_name};
+
+  if ($state->{'spec'}) {
+    warn("BUG: redefining shared_conversion_state: $cmdname: $state_name");
+  }
+  $state->{'spec'} = $specification;
+}
+
+sub _get_shared_conversion_state($$$;@)
 {
   my $self = shift;
+  my $cmdname = shift;
   my $state_name = shift;
-  my $initialization_value = shift;
+  my @args = @_;
+
+  my $state = $self->{'shared_conversion_state'}->{$cmdname}->{$state_name};
 
-  if (not defined($self->{'shared_conversion_state'}->{$state_name})) {
-    if ($initialization_value =~ /^\d+$/) {
-      $self->{'shared_conversion_state_integers'}->{$state_name} = 1;
+  if (!defined($state)) {
+    #print STDERR "DEBUG: [".
+    #     
join('|',keys(%{$self->{'shared_conversion_state'}->{$cmdname}}))."]\n";
+    confess("BUG: $self: undef shared_conversion_state: $cmdname: 
$state_name\n");
+  }
+
+  my $spec_nr = scalar(@{$state->{'spec'}});
+
+  if ($spec_nr == 1) {
+    return $state->{'values'};
+  }
+
+  if (!defined($state->{'values'})) {
+    $state->{'values'} = {};
+  }
+  my $spec_idx = 1;
+  my $current = $state->{'values'};
+  foreach my $arg (@args) {
+    if (!defined($arg)) {
+      return $current;
     }
-    if (not ref($initialization_value)) {
-      $self->{'shared_conversion_state'}->{$state_name} = 
\$initialization_value;
-    } else {
-      $self->{'shared_conversion_state'}->{$state_name} = 
$initialization_value;
+    if ($spec_idx == $spec_nr - 1) {
+      return $current->{$arg};
+    }
+    if (!$current->{$arg}) {
+      $current->{$arg} = {};
     }
+    $current = $current->{$arg};
+    $spec_idx++;
   }
-  # set for XS code to notify that value may have changed
-  if ($self->{'shared_conversion_state_integers'}->{$state_name}) {
-    $self->{'shared_conversion_accessed_integers'}->{$state_name} = 1;
+  return $current;
+}
+
+sub _XS_get_shared_conversion_state($$$;@)
+{
+  my $self = shift;
+  my $cmdname = shift;
+  my $state_name = shift;
+  my @args = @_;
+
+  return _get_shared_conversion_state($self, $cmdname,
+                                      $state_name, @args);
+}
+
+sub get_shared_conversion_state($$$;@)
+{
+  my $self = shift;
+  my $cmdname = shift;
+  my $state_name = shift;
+  my @args = @_;
+
+  if ($default_shared_conversion_states{$cmdname}
+      and $default_shared_conversion_states{$cmdname}->{$state_name}) {
+    my $result = _XS_get_shared_conversion_state($self, $cmdname,
+                                           $state_name, @args);
+    return $result;
   }
-  return $self->{'shared_conversion_state'}->{$state_name};
+
+  return _get_shared_conversion_state($self, $cmdname,
+                                      $state_name, @args);
+}
+
+sub _set_shared_conversion_state($$$;@)
+{
+  my $self = shift;
+  my $cmdname = shift;
+  my $state_name = shift;
+  my @args = @_;
+
+  my $state = $self->{'shared_conversion_state'}->{$cmdname}->{$state_name};
+
+  my $spec_nr = scalar(@{$state->{'spec'}});
+  if (scalar(@args) != $spec_nr) {
+    return undef;
+  }
+
+  if ($spec_nr == 1) {
+    if (!defined($args[0])) {
+      return undef;
+    }
+    $state->{'values'} = $args[0];
+    return $args[0];
+  }
+
+  if (!defined($state->{'values'})) {
+    $state->{'values'} = {};
+  }
+  my $spec_idx = 1;
+  my $current = $state->{'values'};
+  foreach my $arg (@args) {
+    if (!defined($arg)) {
+      return undef;
+    }
+    if ($spec_idx == $spec_nr - 1) {
+      $current->{$arg} = $args[$spec_idx];
+      return $current->{$arg};
+    }
+    if (!defined($current->{$arg})) {
+      $current->{$arg} = {};
+    }
+    $current = $current->{$arg};
+    $spec_idx++;
+  }
+}
+
+sub _XS_set_shared_conversion_state($$$;@)
+{
+  my $self = shift;
+  my $cmdname = shift;
+  my $state_name = shift;
+  my @args = @_;
+
+  _set_shared_conversion_state($self, $cmdname,
+                               $state_name, @args);
+}
+
+sub set_shared_conversion_state($$$;@)
+{
+  my $self = shift;
+  my $cmdname = shift;
+  my $state_name = shift;
+  my @args = @_;
+
+  if ($default_shared_conversion_states{$cmdname}
+      and $default_shared_conversion_states{$cmdname}->{$state_name}) {
+    _XS_set_shared_conversion_state($self, $cmdname,
+                                    $state_name, @args);
+    return;
+  }
+
+  _set_shared_conversion_state($self, $cmdname,
+                                    $state_name, @args);
 }
 
 sub register_footnote($$$$$$$)
@@ -1988,8 +2146,8 @@ sub register_footnote($$$$$$$)
   my ($self, $command, $footid, $docid, $number_in_doc,
       $footnote_location_filename, $multi_expanded_region) = @_;
   my $in_skipped_node_top
-    = $self->shared_conversion_state('in_skipped_node_top', 0);
-  if ($$in_skipped_node_top != 1) {
+    = $self->get_shared_conversion_state('top', 'in_skipped_node_top');
+  if (!defined($in_skipped_node_top) or $in_skipped_node_top != 1) {
     push @{$self->{'pending_footnotes'}}, [$command, $footid, $docid,
       $number_in_doc, $footnote_location_filename, $multi_expanded_region];
   }
@@ -3377,16 +3535,15 @@ sub _convert_explained_command($$$$)
                                    $command->{'args'}->[0]);
   }
 
-  my $explained_commands
-    = $self->shared_conversion_state('explained_commands', {});
-  $explained_commands->{$cmdname} = {} if (!$explained_commands->{$cmdname});
-
   if ($args and $args->[1] and defined($args->[1]->{'string'})
                  and $args->[1]->{'string'} =~ /\S/) {
     $explanation_string = $args->[1]->{'string'};
-    $explained_commands->{$cmdname}->{$normalized_type} = $explanation_string;
-  } elsif ($explained_commands->{$cmdname}->{$normalized_type}) {
-    $explanation_string = $explained_commands->{$cmdname}->{$normalized_type};
+    $self->set_shared_conversion_state($cmdname, 'explained_commands',
+                                       $normalized_type, $explanation_string);
+  } else {
+    $explanation_string
+      = $self->get_shared_conversion_state($cmdname, 'explained_commands',
+                                           $normalized_type);
   }
 
   my $result = '';
@@ -3445,9 +3602,16 @@ sub _convert_footnote_command($$$$)
   my $command = shift;
   my $args = shift;
 
-  my $foot_num = $self->shared_conversion_state('footnote_number', 0);
-  ${$foot_num}++;
-  my $number_in_doc = $$foot_num;
+  my $foot_num
+    = $self->get_shared_conversion_state('footnote', 'footnote_number');
+  if (!defined($foot_num)) {
+    $foot_num = 0;
+  }
+
+  $foot_num++;
+  $self->set_shared_conversion_state('footnote', 'footnote_number',
+                                     $foot_num);
+  my $number_in_doc = $foot_num;
   my $footnote_mark;
   if ($self->get_conf('NUMBER_FOOTNOTES')) {
     $footnote_mark = $number_in_doc;
@@ -3477,14 +3641,16 @@ sub _convert_footnote_command($$$$)
     # to avoid duplicate names, use a prefix that cannot happen in anchors
     my $target_prefix = "t_f";
     $footid = $target_prefix.$multi_expanded_region.'_'
-                    .$footnote_id.'_'.$$foot_num;
+                    .$footnote_id.'_'.$foot_num;
     $docid = $target_prefix.$multi_expanded_region.'_'
-                     .$footnote_docid.'_'.$$foot_num;
+                     .$footnote_docid.'_'.$foot_num;
   } else {
-    my $footnote_id_numbers
-      = $self->shared_conversion_state('footnote_id_numbers', {});
-    if (!defined($footnote_id_numbers->{$footnote_id})) {
-      $footnote_id_numbers->{$footnote_id} = $$foot_num;
+    my $footnote_id_number
+      = $self->get_shared_conversion_state('footnote', 'footnote_id_numbers',
+                                           $footnote_id);
+    if (!defined($footnote_id_number)) {
+      $self->set_shared_conversion_state('footnote', 'footnote_id_numbers',
+                                         $footnote_id, $foot_num);
       $footid = $footnote_id;
       $docid = $footnote_docid;
     } else {
@@ -3493,8 +3659,8 @@ sub _convert_footnote_command($$$$)
       # Here it is not checked that there is no clash with another anchor.
       # However, unless there are more than 1000 footnotes this should not
       # happen at all, and even in that case it is very unlikely.
-      $footid = $footnote_id.'_'.$$foot_num;
-      $docid = $footnote_docid.'_'.$$foot_num;
+      $footid = $footnote_id.'_'.$foot_num;
+      $docid = $footnote_docid.'_'.$foot_num;
       $multiple_expanded_footnote = 1;
     }
   }
@@ -4523,7 +4689,8 @@ sub _convert_heading_command($$$$$)
   if ($self->get_conf('NO_TOP_NODE_OUTPUT')
       and $Texinfo::Commands::root_commands{$cmdname}) {
     my $in_skipped_node_top
-      = $self->shared_conversion_state('in_skipped_node_top', 0);
+      = $self->get_shared_conversion_state('top', 'in_skipped_node_top');
+    $in_skipped_node_top = 0 if (!defined($in_skipped_node_top));
     my $node_element;
     if ($cmdname eq 'node') {
       $node_element = $element;
@@ -4535,12 +4702,16 @@ sub _convert_heading_command($$$$$)
       if ($node_element and $node_element->{'extra'}
           and $node_element->{'extra'}->{'normalized'}
           and $node_element->{'extra'}->{'normalized'} eq 'Top') {
-        $$in_skipped_node_top = 1;
-      } elsif ($$in_skipped_node_top == 1) {
-        $$in_skipped_node_top = -1;
+        $in_skipped_node_top = 1;
+        $self->set_shared_conversion_state('top', 'in_skipped_node_top',
+                                           $in_skipped_node_top);
+      } elsif ($in_skipped_node_top == 1) {
+        $in_skipped_node_top = -1;
+        $self->set_shared_conversion_state('top', 'in_skipped_node_top',
+                                           $in_skipped_node_top);
       }
     }
-    if ($$in_skipped_node_top == 1) {
+    if ($in_skipped_node_top == 1) {
       my $id_class = $cmdname;
       $result .= &{$self->formatting_function('format_separate_anchor')}($self,
                                                         $element_id, 
$id_class);
@@ -4611,15 +4782,16 @@ sub _convert_heading_command($$$$$)
         my $use_next_heading = 0;
         if ($self->get_conf('USE_NEXT_HEADING_FOR_LONE_NODE')) {
           my $expanded_format_raw
-             = $self->shared_conversion_state('expanded_format_raw', {});
-
+             = $self->get_shared_conversion_state('top', 
'expanded_format_raw');
           # if no format is expanded, the formats will be checked each time
           # but this is very unlikely, as html is always expanded.
-          if (scalar(keys(%$expanded_format_raw)) == 0) {
+          if (!defined($expanded_format_raw)
+              or !scalar(keys(%$expanded_format_raw))) {
             foreach my $output_format_command
                 (keys(%Texinfo::Common::texinfo_output_formats)) {
               if ($self->is_format_expanded($output_format_command)) {
-                $expanded_format_raw->{$output_format_command} = 1;
+                $self->set_shared_conversion_state('top', 
'expanded_format_raw',
+                                                   $output_format_command, 1);
               }
             }
           }
@@ -5199,9 +5371,7 @@ sub _convert_menu_command($$$$$)
 
   return $content if ($cmdname eq 'detailmenu');
 
-  my $html_menu_entry_index
-    = $self->shared_conversion_state('html_menu_entry_index', 0);
-  $$html_menu_entry_index = 0;
+  $self->set_shared_conversion_state('menu', 'html_menu_entry_index', 0);
 
   if ($content !~ /\S/) {
     return '';
@@ -5983,8 +6153,6 @@ sub _convert_printindex_command($$$$)
   # Next do the entries to determine the letters that are not empty
   my @letter_entries;
   my $result_index_entries = '';
-  my $formatted_index_entries
-    = $self->shared_conversion_state('formatted_index_entries', {});
   foreach my $letter_entry (@{$index_entries_by_letter->{$index_name}}) {
     my $letter = $letter_entry->{'letter'};
     my $entries_text = '';
@@ -6007,11 +6175,15 @@ sub _convert_printindex_command($$$$)
       # to avoid double error messages, call 
convert_tree_new_formatting_context
       # below with a multiple_pass argument if an entry was already formatted 
once,
       # for example if there are multiple printindex.
-      if (!$formatted_index_entries->{$index_entry_ref}) {
-        $formatted_index_entries->{$index_entry_ref} = 1;
-      } else {
-        $formatted_index_entries->{$index_entry_ref}++;
-      }
+      my $formatted_index_entry_nr
+       = $self->get_shared_conversion_state('printindex',
+                                          'formatted_index_entries',
+                                           $index_entry_ref);
+      $formatted_index_entry_nr = 0 if (!defined($formatted_index_entry_nr));
+      $formatted_index_entry_nr++;
+      $self->set_shared_conversion_state('printindex',
+                                          'formatted_index_entries',
+                                $index_entry_ref, $formatted_index_entry_nr);
 
       my $entry_content_element
           = Texinfo::Common::index_content_element($main_entry_element);
@@ -6066,11 +6238,11 @@ sub _convert_printindex_command($$$$)
                                         {'main_index_entry' => $entry_ref_tree,
                                          'seenentry' => $referred_tree});
           }
-          if ($formatted_index_entries->{$index_entry_ref} > 1) {
+          if ($formatted_index_entry_nr > 1) {
             # call with multiple_pass argument
             $entry = $self->convert_tree_new_formatting_context($result_tree,
                  "index $index_name l $letter index entry $entry_nr seenentry",
-                 
"index-formatted-$formatted_index_entries->{$index_entry_ref}")
+                 "index-formatted-$formatted_index_entry_nr")
           } else {
             $entry = $self->convert_tree($result_tree,
                   "index $index_name l $letter index entry $entry_nr 
seenentry");
@@ -6081,15 +6253,15 @@ sub _convert_printindex_command($$$$)
           # TRANSLATORS: refer to another index entry
           my $reference_tree = $self->gdt('@emph{See also} {see_also_entry}',
                                        {'see_also_entry' => $referred_tree});
-          if ($formatted_index_entries->{$index_entry_ref} > 1) {
+          if ($formatted_index_entry_nr > 1) {
             # call with multiple_pass argument
             $entry = 
$self->convert_tree_new_formatting_context($entry_ref_tree,
                "index $index_name l $letter index entry $entry_nr (with 
seealso)",
-               "index-formatted-$formatted_index_entries->{$index_entry_ref}");
+               "index-formatted-$formatted_index_entry_nr");
             $reference
                = $self->convert_tree_new_formatting_context($reference_tree,
                 "index $index_name l $letter index entry $entry_nr seealso",
-                 
"index-formatted-$formatted_index_entries->{$index_entry_ref}");
+                 "index-formatted-$formatted_index_entry_nr");
           } else {
             $entry = $self->convert_tree($entry_ref_tree,
              "index $index_name l $letter index entry $entry_nr (with 
seealso)");
@@ -6177,11 +6349,11 @@ sub _convert_printindex_command($$$$)
         $entry_level = $starting_subentry_level;
         foreach my $level ($starting_subentry_level .. scalar(@entry_trees)-1) 
{
           my $entry;
-          if ($formatted_index_entries->{$index_entry_ref} > 1) {
+          if ($formatted_index_entry_nr > 1) {
             # call with multiple_pass argument
             $entry = 
$self->convert_tree_new_formatting_context($entry_trees[$level],
                    "index $index_name l $letter index entry $entry_nr subentry 
$level",
-                   
"index-formatted-$formatted_index_entries->{$index_entry_ref}")
+                   "index-formatted-$formatted_index_entry_nr")
           } else {
             $entry = $self->convert_tree($entry_trees[$level],
                   "index $index_name l $letter index entry $entry_nr subentry 
$level");
@@ -6205,11 +6377,11 @@ sub _convert_printindex_command($$$$)
       }
 
       my $entry;
-      if ($formatted_index_entries->{$index_entry_ref} > 1) {
+      if ($formatted_index_entry_nr > 1) {
         # call with multiple_pass argument
         $entry = $self->convert_tree_new_formatting_context($entry_tree,
                        "index $index_name l $letter index entry $entry_nr",
-                   
"index-formatted-$formatted_index_entries->{$index_entry_ref}")
+                   "index-formatted-$formatted_index_entry_nr")
       } else {
         $entry = $self->convert_tree($entry_tree,
                             "index $index_name l $letter index entry 
$entry_nr");
@@ -6240,7 +6412,7 @@ sub _convert_printindex_command($$$$)
         if (!defined($associated_command)
             # do not warn if the entry is in a special region, like titlepage
             and not $main_entry_element->{'extra'}->{'element_region'}
-            and $formatted_index_entries->{$index_entry_ref} == 1) {
+            and $formatted_index_entry_nr == 1) {
           # NOTE _noticed_line_warn is not used as printindex should not
           # happen in multiple tree parsing that lead to ignore_notice being 
set,
           # but the error message is printed only for the first entry 
formatting.
@@ -6270,7 +6442,7 @@ sub _convert_printindex_command($$$$)
               and not $self->get_conf('NODE_NAME_IN_INDEX')
               # do not warn if the entry is in a special region, like titlepage
               and not $main_entry_element->{'extra'}->{'element_region'}
-              and $formatted_index_entries->{$index_entry_ref} == 1) {
+              and $formatted_index_entry_nr == 1) {
             # NOTE _noticed_line_warn is not used as printindex should not
             # happen in multiple tree parsing that lead to ignore_notice being 
set,
             # but the error message is printed only for the first entry 
formatting.
@@ -6984,9 +7156,7 @@ sub _convert_menu_entry_type($$$)
   my $rel = '';
   my $section;
 
-  my $formatted_nodedescriptions
-    = $self->shared_conversion_state('formatted_nodedescriptions', {});
-  my $use_nodedescription;
+  my $formatted_nodedescription_nr;
   # external node
   my $external_node;
   if ($menu_entry_node->{'extra'}
@@ -7036,23 +7206,30 @@ sub _convert_menu_entry_type($$$)
             $menu_description = {'contents' => 
$node_description->{'contents'}};
           }
           # update the number of time the node description was formatted
-          if (!$formatted_nodedescriptions->{$node_description}) {
-            $formatted_nodedescriptions->{$node_description} = 1;
-          } else {
-            $formatted_nodedescriptions->{$node_description}++;
-          }
-          $use_nodedescription = 
$formatted_nodedescriptions->{$node_description};
+          $formatted_nodedescription_nr
+            = $self->get_shared_conversion_state('nodedescription',
+                                            'formatted_nodedescriptions',
+                                             $node_description);
+          $formatted_nodedescription_nr = 0
+             if (!defined($formatted_nodedescription_nr));
+          $formatted_nodedescription_nr++;
+          $self->set_shared_conversion_state('nodedescription',
+                                            'formatted_nodedescriptions',
+                            $node_description, $formatted_nodedescription_nr);
         }
       }
     }
   }
 
   my $html_menu_entry_index
-    = $self->shared_conversion_state('html_menu_entry_index', 0);
-  ${$html_menu_entry_index}++;
+    = $self->get_shared_conversion_state('menu', 'html_menu_entry_index');
+  $html_menu_entry_index = 0 if (!defined($html_menu_entry_index));
+  $html_menu_entry_index++;
+  $self->set_shared_conversion_state('menu', 'html_menu_entry_index',
+                                    $html_menu_entry_index);
   my $accesskey = '';
-  $accesskey = " accesskey=\"$$html_menu_entry_index\""
-    if ($self->get_conf('USE_ACCESSKEY') and $$html_menu_entry_index < 10);
+  $accesskey = " accesskey=\"$html_menu_entry_index\""
+    if ($self->get_conf('USE_ACCESSKEY') and $html_menu_entry_index < 10);
 
   my $MENU_SYMBOL = $self->get_conf('MENU_SYMBOL');
   my $MENU_ENTRY_COLON = $self->get_conf('MENU_ENTRY_COLON');
@@ -7102,11 +7279,11 @@ sub _convert_menu_entry_type($$$)
 
     my $description = '';
     if ($menu_description) {
-      if ($use_nodedescription) {
+      if ($formatted_nodedescription_nr) {
         my $multiple_formatted;
-        if ($use_nodedescription > 1) {
+        if ($formatted_nodedescription_nr > 1) {
           $multiple_formatted
-            = 'preformatted-node-description-'.$use_nodedescription;
+            = 'preformatted-node-description-'.$formatted_nodedescription_nr;
         }
         $description .= $self->convert_tree_new_formatting_context(
                                   $menu_description,
@@ -7156,11 +7333,11 @@ sub _convert_menu_entry_type($$$)
   }
   my $description = '';
   if ($menu_description) {
-    if ($use_nodedescription) {
+    if ($formatted_nodedescription_nr) {
       my $multiple_formatted;
-      if ($use_nodedescription > 1) {
+      if ($formatted_nodedescription_nr > 1) {
         $multiple_formatted
-          = 'node-description-'.$use_nodedescription;
+          = 'node-description-'.$formatted_nodedescription_nr;
       }
       $description = $self->convert_tree_new_formatting_context(
                               $menu_description, 'menu_arg node description',
@@ -11331,6 +11508,14 @@ sub _initialize_output_state($$)
 
   $self->{'associated_inline_content'} = {};
 
+  foreach my $cmdname (keys(%default_shared_conversion_states)) {
+    foreach my $state_name
+        (keys(%{$default_shared_conversion_states{$cmdname}})) {
+      $self->define_shared_conversion_state($cmdname, $state_name,
+          $default_shared_conversion_states{$cmdname}->{$state_name});
+    }
+  }
+
   # even if there is no actual file, this is needed if the API is used.
   $self->{'html_files_information'} = {};
 
@@ -11370,15 +11555,12 @@ sub _initialize_XS_NonXS_output_state($$)
   my $self = shift;
   my $context = shift;
 
+  $self->{'shared_conversion_state'} = {};
+
   $self->_initialize_output_state($context);
 
   $self->{'multiple_pass'} = [];
 
-  # for diverse API used in conversion
-  $self->{'shared_conversion_state'} = {};
-  $self->{'shared_conversion_state_integers'} = {};
-  $self->{'shared_conversion_accessed_integers'} = {};
-
   # direction strings
   foreach my $string_type (keys(%default_translated_directions_strings)) {
     # those will be determined from translatable strings
diff --git a/tp/Texinfo/XS/convert/ConvertXS.xs 
b/tp/Texinfo/XS/convert/ConvertXS.xs
index 9af1180525..d506ccc866 100644
--- a/tp/Texinfo/XS/convert/ConvertXS.xs
+++ b/tp/Texinfo/XS/convert/ConvertXS.xs
@@ -662,7 +662,7 @@ html_preformatted_number (SV *converter_in)
     OUTPUT:
          RETVAL
 
-char *
+const char *
 html_top_block_command (SV *converter_in)
      PREINIT:
          CONVERTER *self;
@@ -697,7 +697,7 @@ html_preformatted_classes_stack (SV *converter_in)
     OUTPUT:
          RETVAL
 
-char *
+const char *
 html_in_align (SV *converter_in)
      PREINIT:
          CONVERTER *self;
@@ -1123,6 +1123,57 @@ html_internal_command_text (SV *converter_in, SV 
*element_sv, char *type)
     OUTPUT:
          RETVAL
 
+void
+html_set_shared_conversion_state (SV *converter_in, cmdname, state_name, ...)
+         char *cmdname = (char *)SvPVutf8_nolen($arg);
+         char *state_name = (char *)SvPVutf8_nolen($arg);
+     PREINIT:
+         CONVERTER *self;
+         SV **args_sv = 0;
+         int args_nr = 0;
+     CODE:
+         self = get_sv_converter (converter_in,
+                                  "html_set_shared_conversion_state");
+         args_nr = items - 3;
+         if (args_nr > 0)
+           {
+             int i;
+             args_sv = (SV **) malloc (args_nr * sizeof (SV *));
+             for (i = 0; i < args_nr; i++)
+               {
+                 args_sv[i] = ST(i+3);
+               }
+           }
+         html_set_shared_conversion_state (self, converter_in,
+                                cmdname, state_name, args_nr, args_sv);
+         free (args_sv);
+
+SV *
+html_get_shared_conversion_state (SV *converter_in, cmdname, state_name, ...)
+         char *cmdname = (char *)SvPVutf8_nolen($arg);
+         char *state_name = (char *)SvPVutf8_nolen($arg);
+     PREINIT:
+         CONVERTER *self;
+         SV **args_sv = 0;
+         int args_nr = 0;
+     CODE:
+         self = get_sv_converter (converter_in,
+                                  "html_get_shared_conversion_state");
+         args_nr = items - 3;
+         if (args_nr > 0)
+           {
+             int i;
+             args_sv = (SV **) malloc (args_nr * sizeof (SV *));
+             for (i = 0; i < args_nr; i++)
+               {
+                 args_sv[i] = ST(i+3);
+               }
+           }
+         RETVAL = html_get_shared_conversion_state (self, converter_in,
+                                     cmdname, state_name, args_nr, args_sv);
+         free (args_sv);
+    OUTPUT:
+         RETVAL
 
 void
 html_register_opened_section_level (SV *converter_in, int level, close_string)
diff --git a/tp/Texinfo/XS/convert/build_html_perl_state.c 
b/tp/Texinfo/XS/convert/build_html_perl_state.c
index 83bef5bff4..4b1462c42e 100644
--- a/tp/Texinfo/XS/convert/build_html_perl_state.c
+++ b/tp/Texinfo/XS/convert/build_html_perl_state.c
@@ -312,7 +312,7 @@ build_html_translated_names (HV *hv, CONVERTER *converter)
             = converter->no_arg_formatted_cmd_translated.list[j];
           HTML_COMMAND_CONVERSION *conversion_contexts
                 = converter->html_command_conversion[cmd];
-          char *cmdname = builtin_command_data[cmd].cmdname;
+          const char *cmdname = builtin_command_data[cmd].cmdname;
           SV **no_arg_command_sv
              = hv_fetch (no_arg_commands_formatting_hv,
                          cmdname, strlen (cmdname), 0);
@@ -458,49 +458,6 @@ build_html_formatting_state (CONVERTER *converter, 
unsigned long flags)
         }
     }
 
-  if (flags & HMSF_shared_conversion_state_integer)
-    {
-      int j;
-      SV **shared_conversion_state_sv;
-      HV *shared_conversion_state_hv;
-
-      FETCH(shared_conversion_state)
-
-      if (!shared_conversion_state_sv)
-        {
-          shared_conversion_state_hv = newHV ();
-          STORE("shared_conversion_state",
-             newRV_noinc ((SV *) shared_conversion_state_hv));
-        }
-      else
-        shared_conversion_state_hv
-          = (HV *) SvRV (*shared_conversion_state_sv);
-
-      for (j = 0; j < converter->shared_conversion_state_integer.number; j++)
-        {
-          const char *key = converter->shared_conversion_state_integer.list[j];
-          KEY_PAIR *k
-            = lookup_associated_info (
-                 &converter->shared_conversion_state.integers, key);
-
-          SV **int_key_sv = hv_fetch (shared_conversion_state_hv,
-                                  key, strlen (key), 0);
-          if (!int_key_sv)
-            {
-              SV *int_value_sv = newSViv ((IV) k->integer);
-              SV *int_sv = newRV_noinc (int_value_sv);
-              hv_store (shared_conversion_state_hv, key,
-                        strlen (key), int_sv, 0);
-            }
-          else
-            {
-              SV *int_value_sv = SvRV (*int_key_sv);
-              sv_setiv (int_value_sv, (IV) k->integer);
-            }
-        }
-      clear_strings_list (&converter->shared_conversion_state_integer);
-    }
-
 #undef STORE
 
   if (flags & HMSF_translations)
diff --git a/tp/Texinfo/XS/convert/call_html_perl_function.c 
b/tp/Texinfo/XS/convert/call_html_perl_function.c
index 8c6657a553..720737dc5b 100644
--- a/tp/Texinfo/XS/convert/call_html_perl_function.c
+++ b/tp/Texinfo/XS/convert/call_html_perl_function.c
@@ -41,63 +41,6 @@
 #include "build_html_perl_state.h"
 #include "call_html_perl_function.h"
 
-/* in general we get information from perl by overriding functions setting
-   that information, but for shared_conversion the reference obtained
-   through a function call may be modified afterwards, so it is better to
-   set in perl information allowing to find which item may be modified and
-   get the information here when exiting from user-defined functions */
-void
-get_shared_conversion_state (CONVERTER *self)
-{
-  SV **shared_conversion_accessed_integers_sv;
-
-  dTHX;
-
-  shared_conversion_accessed_integers_sv = hv_fetch (self->hv,
-                       "shared_conversion_accessed_integers",
-                       strlen ("shared_conversion_accessed_integers"), 0);
-
-  if (shared_conversion_accessed_integers_sv)
-    {
-      SV **shared_conversion_state_sv;
-      I32 hv_number;
-      I32 i;
-
-      shared_conversion_state_sv = hv_fetch (self->hv,
-                       "shared_conversion_state",
-                       strlen ("shared_conversion_state"), 0);
-      HV *conversion_state_hv = (HV *) SvRV (*shared_conversion_state_sv);
-
-      HV *accessed_integers_v
-        = (HV *) SvRV (*shared_conversion_accessed_integers_sv);
-
-      hv_number = hv_iterinit (accessed_integers_v);
-
-      for (i = 0; i < hv_number; i++)
-        {
-          SV *ref_value_sv;
-          int value;
-          HE *next = hv_iternext (accessed_integers_v);
-          SV *selector_sv = hv_iterkeysv (next);
-          char *selector = (char *) SvPVutf8_nolen (selector_sv);
-          char *saved_selector;
-
-          HE *conversion_state_he = hv_fetch_ent (conversion_state_hv,
-                                                  selector_sv, 0, 0);
-          ref_value_sv = HeVAL (conversion_state_he);
-          value = SvIV (SvRV (ref_value_sv));
-
-          saved_selector
-             = add_string (selector,
-                           &self->shared_conversion_state.key_strings);
-          add_associated_info_integer (&self->shared_conversion_state.integers,
-                                       saved_selector, value);
-
-          hv_delete_ent (accessed_integers_v, selector_sv, 0, 0);
-        }
-    }
-}
-
 TARGET_FILENAME *
 call_file_id_setting_special_unit_target_file_name (CONVERTER *self,
                          const OUTPUT_UNIT *special_unit, const char *target,
@@ -741,8 +684,6 @@ call_formatting_function_format_comment (CONVERTER *self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -798,8 +739,6 @@ call_formatting_function_format_program_string (CONVERTER 
*self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -855,8 +794,6 @@ call_formatting_function_format_titlepage (CONVERTER *self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -912,8 +849,6 @@ call_formatting_function_format_title_titlepage (CONVERTER 
*self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -971,8 +906,6 @@ call_formatting_function_format_protect_text (CONVERTER 
*self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -1028,8 +961,6 @@ call_formatting_function_format_footnotes_segment 
(CONVERTER *self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -1085,8 +1016,6 @@ call_formatting_function_format_footnotes_sequence 
(CONVERTER *self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -1144,8 +1073,6 @@ call_formatting_function_format_css_lines (CONVERTER 
*self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -1210,8 +1137,6 @@ call_formatting_function_format_end_file (CONVERTER *self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -1277,8 +1202,6 @@ call_formatting_function_format_begin_file (CONVERTER 
*self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -1342,8 +1265,6 @@ call_formatting_function_format_translate_message 
(CONVERTER *self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -1414,8 +1335,6 @@ call_formatting_function_format_button_icon_img 
(CONVERTER *self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -1500,8 +1419,6 @@ call_formatting_function_format_button (CONVERTER *self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -1566,8 +1483,6 @@ call_formatting_function_format_navigation_panel 
(CONVERTER *self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -1631,8 +1546,6 @@ call_formatting_function_format_navigation_header 
(CONVERTER *self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -1724,8 +1637,6 @@ call_formatting_function_format_heading_text (CONVERTER 
*self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -1794,8 +1705,6 @@ call_formatting_function_format_contents (CONVERTER *self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -1856,8 +1765,6 @@ call_formatting_function_format_separate_anchor 
(CONVERTER *self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -1920,8 +1827,6 @@ call_formatting_function_format_element_header (CONVERTER 
*self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -1988,8 +1893,6 @@ call_formatting_function_format_element_footer (CONVERTER 
*self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -2067,8 +1970,6 @@ call_types_conversion (CONVERTER *self, const enum 
element_type type,
 
   FREETMPS;
   LEAVE;
-
-  get_shared_conversion_state (self);
 }
 
 void
@@ -2128,8 +2029,6 @@ call_types_open (CONVERTER *self, const enum element_type 
type,
 
   FREETMPS;
   LEAVE;
-
-  get_shared_conversion_state (self);
 }
 
 void
@@ -2145,7 +2044,7 @@ call_commands_conversion (CONVERTER *self, const enum 
command_id cmd,
   SV *result_sv;
   SV *formatting_reference_sv;
   SV *args_formatted_sv;
-  char *command_name;
+  const char *command_name;
 
   dTHX;
 
@@ -2203,8 +2102,6 @@ call_commands_conversion (CONVERTER *self, const enum 
command_id cmd,
 
   FREETMPS;
   LEAVE;
-
-  get_shared_conversion_state (self);
 }
 
 void
@@ -2216,7 +2113,7 @@ call_commands_open (CONVERTER *self, const enum 
command_id cmd,
   STRLEN len;
   SV *result_sv;
   SV *formatting_reference_sv;
-  char *command_name;
+  const char *command_name;
 
   dTHX;
 
@@ -2268,8 +2165,6 @@ call_commands_open (CONVERTER *self, const enum 
command_id cmd,
 
   FREETMPS;
   LEAVE;
-
-  get_shared_conversion_state (self);
 }
 
 void
@@ -2336,8 +2231,6 @@ call_output_units_conversion (CONVERTER *self,
 
   FREETMPS;
   LEAVE;
-
-  get_shared_conversion_state (self);
 }
 
 void
@@ -2402,8 +2295,6 @@ call_special_unit_body_formatting (CONVERTER *self,
 
   FREETMPS;
   LEAVE;
-
-  get_shared_conversion_state (self);
 }
 
 
@@ -2472,8 +2363,6 @@ call_button_simple_function (CONVERTER *self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
@@ -2546,8 +2435,6 @@ call_button_direction_function (CONVERTER *self,
   FREETMPS;
   LEAVE;
 
-  get_shared_conversion_state (self);
-
   return result;
 }
 
diff --git a/tp/Texinfo/XS/convert/convert_html.c 
b/tp/Texinfo/XS/convert/convert_html.c
index a65af0751e..f7b647bb4c 100644
--- a/tp/Texinfo/XS/convert/convert_html.c
+++ b/tp/Texinfo/XS/convert/convert_html.c
@@ -200,7 +200,7 @@ CMD_VARIETY command_special_unit_variety[] = {
 
 typedef struct HTML_COMMAND_STRUCT {
     unsigned long flags;
-    char *pre_class;
+    const char *pre_class;
 } HTML_COMMAND_STRUCT;
 
 static HTML_COMMAND_STRUCT html_commands_data[BUILTIN_CMD_NUMBER];
@@ -936,10 +936,7 @@ html_register_footnote (CONVERTER *self, const ELEMENT 
*command,
   HTML_PENDING_FOOTNOTE_STACK *stack;
   HTML_PENDING_FOOTNOTE *pending_footnote;
 
-  KEY_PAIR *k = lookup_associated_info 
(&self->shared_conversion_state.integers,
-                                        "in_skipped_node_top");
-
-  if (k && k->integer > 0)
+  if (self->shared_conversion_state.in_skipped_node_top == 1)
     return;
 
   stack = &self->pending_footnotes;
@@ -1509,7 +1506,7 @@ register_format_context_command (enum command_id cmd)
 
 void register_pre_class_command (enum command_id cmd, enum command_id main_cmd)
 {
-  char *pre_class_str;
+  const char *pre_class_str;
 
   if (main_cmd)
     pre_class_str = builtin_command_data[main_cmd].cmdname;
@@ -1914,7 +1911,7 @@ new_sectioning_command_target (CONVERTER *self, const 
ELEMENT *command)
 
   if (self->conf->DEBUG > 0)
     {
-      char *command_name = element_command_name (command);
+      const char *command_name = element_command_name (command);
       fprintf (stderr, "XS|Register %s %s\n", command_name, target);
     }
 
@@ -2020,7 +2017,7 @@ set_root_commands_targets_node_files (CONVERTER *self)
 
           if (self->conf->DEBUG > 0)
             {
-              char *command_name = element_command_name (target_element);
+              const char *command_name = element_command_name (target_element);
               fprintf (stderr, "Label @%s %s, %s\n", command_name, target,
                                node_filename);
             }
@@ -2601,7 +2598,7 @@ pop_html_formatting_context 
(HTML_FORMATTING_CONTEXT_STACK *stack)
 
 void
 html_new_document_context (CONVERTER *self,
-        char *context_name, char *document_global_context,
+        const char *context_name, const char *document_global_context,
         enum command_id block_command)
 {
   HTML_DOCUMENT_CONTEXT_STACK *stack = &self->html_document_context;
@@ -2617,7 +2614,8 @@ html_new_document_context (CONVERTER *self,
   doc_context = &stack->stack[stack->top];
   memset (doc_context, 0, sizeof (HTML_DOCUMENT_CONTEXT));
   doc_context->context = strdup (context_name);
-  doc_context->document_global_context = document_global_context;
+  if (document_global_context)
+    doc_context->document_global_context = strdup (document_global_context);
 
   push_integer_stack_integer (&doc_context->monospace, 0);
   push_integer_stack_integer (&doc_context->preformatted_context, 0);
@@ -2648,6 +2646,7 @@ html_pop_document_context (CONVERTER *self)
   document_ctx = &stack->stack[stack->top -1];
 
   free (document_ctx->context);
+  free (document_ctx->document_global_context);
   free (document_ctx->monospace.stack);
   free (document_ctx->preformatted_context.stack);
   free (document_ctx->composition_context.stack);
@@ -2681,8 +2680,8 @@ html_convert_tree (CONVERTER *self, const ELEMENT *tree, 
char *explanation)
    Texinfo tree need to be converted. */
 char *
 convert_tree_new_formatting_context (CONVERTER *self, const ELEMENT *tree,
-                              char *context_string, char *multiple_pass,
-                              char *document_global_context,
+                              const char *context_string, char *multiple_pass,
+                              const char *document_global_context,
                               enum command_id block_cmd)
 {
   char *result;
@@ -3693,31 +3692,6 @@ html_footnote_location_href (CONVERTER *self, const 
ELEMENT *command,
   return href.text;
 }
 
-int *
-get_shared_conversion_state_integer (CONVERTER *self, char *key,
-                                     int value)
-{
-  KEY_PAIR *k
-    = lookup_associated_info (&self->shared_conversion_state.integers, key);
-
-  if (!k)
-    {
-      add_associated_info_integer (&self->shared_conversion_state.integers,
-                                   key, value);
-      k = lookup_associated_info (&self->shared_conversion_state.integers, 
key);
-    }
-  return &k->integer;
-}
-
-static void
-register_modified_shared_conversion_state_integer (CONVERTER *self,
-                                                   const char *key)
-{
-  self->modified_state |= HMSF_shared_conversion_state_integer;
-  if (!find_string (&self->shared_conversion_state_integer, key))
-    add_string (key, &self->shared_conversion_state_integer);
-}
-
 TREE_ADDED_ELEMENTS *
 html_internal_command_tree (CONVERTER *self, const ELEMENT *command,
                             int no_number)
@@ -3884,7 +3858,7 @@ html_internal_command_text (CONVERTER *self, const 
ELEMENT *command,
           ELEMENT *tree_root;
           TREE_ADDED_ELEMENTS *string_tree = 0;
           char *explanation = 0;
-          char *context_name;
+          const char *context_name;
           ELEMENT *selected_tree;
           TREE_ADDED_ELEMENTS *command_tree
             = html_internal_command_tree (self, command, 0);
@@ -3894,7 +3868,7 @@ html_internal_command_text (CONVERTER *self, const 
ELEMENT *command,
 
           if (command->cmd)
             {
-              char *command_name = element_command_name(command);
+              const char *command_name = element_command_name(command);
               context_name = command_name;
               xasprintf (&explanation, "command_text:%s @%s",
                          html_command_text_type_name[type],
@@ -4491,28 +4465,19 @@ prepare_index_entries_targets (CONVERTER *self)
 {
   if (self->document->index_names)
     {
-      INDEX **i, *idx;
-      INDEX **index_names = self->document->index_names;
-      INDEX **sorted_index_names;
-      int index_nr = 0;
-
-      /* TODO sort indices by name before? when registering in document?
-         In parser?
-         Depending on size?  And use bsearch in some places?
-       */
-      for (i = index_names; (idx = *i); i++)
-        index_nr++;
-
-      sorted_index_names = (INDEX **) malloc ((index_nr+1) * sizeof (INDEX *));
-
-      memcpy (sorted_index_names, index_names, (index_nr+1) * sizeof (INDEX 
*));
-      qsort (sorted_index_names, index_nr, sizeof (INDEX *),
-             compare_index_name);
-
-      for (i = sorted_index_names; (idx = *i); i++)
+      size_t i;
+      self->shared_conversion_state.formatted_index_entries
+        = (int **) malloc (self->sorted_index_names.number * sizeof (int *));
+      for (i = 0; i < self->sorted_index_names.number; i++)
         {
+          INDEX *idx = self->sorted_index_names.list[i].index;
+          self->shared_conversion_state.formatted_index_entries[i] = 0;
           if (idx->entries_number > 0)
             {
+              self->shared_conversion_state.formatted_index_entries[i]
+                = (int *) malloc (idx->entries_number * sizeof (int));
+              memset (self->shared_conversion_state.formatted_index_entries[i],
+                      0, idx->entries_number * sizeof (int));
               int j;
               for (j = 0; j < idx->entries_number; j++)
                 {
@@ -4590,7 +4555,6 @@ prepare_index_entries_targets (CONVERTER *self)
                 }
             }
         }
-      free (sorted_index_names);
     }
 }
 
@@ -6242,7 +6206,7 @@ destroy_begin_file_information (BEGIN_FILE_INFORMATION 
*begin_info)
 static char *
 convert_string_tree_new_formatting_context (CONVERTER *self,
                                             ELEMENT *tree,
-                                   char *context_string, char *multiple_pass)
+                              const char *context_string, char *multiple_pass)
 {
   TREE_ADDED_ELEMENTS *string_tree = 0;
   ELEMENT *tree_root_string;
@@ -9512,8 +9476,8 @@ convert_itemize_command (CONVERTER *self, const enum 
command_id cmd,
                     const char *content, TEXT *result)
 {
   ELEMENT *command_as_argument;
-  char *command_as_argument_name = 0;
-  char *mark_class_name = 0;
+  const char *command_as_argument_name = 0;
+  const char *mark_class_name = 0;
   STRING_LIST *classes;
   char *attribute_class;
   CSS_SELECTOR_STYLE *selector_style = 0;
@@ -9791,8 +9755,8 @@ convert_heading_command (CONVERTER *self, const enum 
command_id cmd,
       && builtin_command_data[cmd].flags & CF_root)
     {
       const ELEMENT *node_element = 0;
-      int *in_skipped_node_top
-        = get_shared_conversion_state_integer (self, "in_skipped_node_top", 0);
+      int in_skipped_node_top
+        = self->shared_conversion_state.in_skipped_node_top;
 
       if (cmd == CM_node)
         node_element = element;
@@ -9813,19 +9777,19 @@ convert_heading_command (CONVERTER *self, const enum 
command_id cmd,
               if (normalized && !strcmp (normalized, "Top"))
                 {
                   node_is_top = 1;
-                  *in_skipped_node_top = 1;
-                  register_modified_shared_conversion_state_integer (self,
-                                                       "in_skipped_node_top");
+                  in_skipped_node_top = 1;
+                  self->shared_conversion_state.in_skipped_node_top
+                    = in_skipped_node_top;
                 }
             }
-          if (!node_is_top && *in_skipped_node_top == 1)
+          if (!node_is_top && in_skipped_node_top == 1)
             {
-              *in_skipped_node_top = -1;
-              register_modified_shared_conversion_state_integer (self,
-                                                     "in_skipped_node_top");
+              in_skipped_node_top = -1;
+              self->shared_conversion_state.in_skipped_node_top
+                = in_skipped_node_top;
             }
         }
-      if (*in_skipped_node_top == 1)
+      if (in_skipped_node_top == 1)
         {
           format_separate_anchor (self, element_id,
                                   builtin_command_name(cmd), result);
@@ -10000,12 +9964,11 @@ convert_heading_command (CONVERTER *self, const enum 
command_id cmd,
              xasprintf (&id_class, "%s-id", builtin_command_name (cmd));
            }
          else
-           id_class = builtin_command_name (cmd);
+           id_class = strdup (builtin_command_name (cmd));
 
          format_separate_anchor (self, element_id, id_class, result);
 
-         if (do_heading)
-           free (id_class);
+         free (id_class);
        }
      else
        heading_id = element_id;
@@ -10186,7 +10149,7 @@ void
 open_quotation_command (CONVERTER *self, const enum command_id cmd,
                         const ELEMENT *element, TEXT *result)
 {
-  char *cmdname = element_command_name (element);
+  const char *cmdname = element_command_name (element);
   char *formatted_quotation_arg_to_prepend = 0;
   if (element->args.number > 0 && element->args.list[0]->contents.number > 0)
     {
@@ -11133,7 +11096,8 @@ html_converter_initialize (CONVERTER *self)
          sizeof (HTMLXREF_MANUAL), compare_htmlxref_manual);
 }
 
-/* called in the end of html_converter_prepare_output_sv */
+/* called in the end of html_converter_prepare_output_sv, just before
+   html_prepare_title_titlepage and just before the start of conversion */
 void
 html_converter_prepare_output (CONVERTER* self)
 {
@@ -11173,6 +11137,8 @@ reset_html_targets (CONVERTER *self, HTML_TARGET_LIST 
*targets)
     }
 }
 
+/* called very early in conversion functions, before updating
+   customization, before calling user-defined functions...  */
 void
 html_initialize_output_state (CONVERTER *self, char *context)
 {
@@ -11204,6 +11170,37 @@ html_initialize_output_state (CONVERTER *self, char 
*context)
   self->current_format_protect_text = &html_default_format_protect_text;
 
   html_new_document_context (self, context, 0, 0);
+
+  if (self->document->index_names)
+    {
+      INDEX **i, *idx;
+      size_t j;
+      INDEX **index_names = self->document->index_names;
+      INDEX **sorted_index_names;
+      size_t index_nr = 0;
+
+      for (i = index_names; (idx = *i); i++)
+        index_nr++;
+
+      self->sorted_index_names.number = index_nr;
+
+      sorted_index_names = (INDEX **) malloc (index_nr * sizeof (INDEX *));
+
+      memcpy (sorted_index_names, index_names, index_nr * sizeof (INDEX *));
+      qsort (sorted_index_names, index_nr, sizeof (INDEX *),
+             compare_index_name);
+      self->sorted_index_names.list = (INDEX_NUMBER *)
+         malloc (index_nr * sizeof (INDEX_NUMBER));
+      for (j = 0; j < index_nr; j++)
+        {
+          self->sorted_index_names.list[j].index = sorted_index_names[j];
+          self->sorted_index_names.list[j].number = j+1;
+        }
+      free (sorted_index_names);
+    }
+
+  self->shared_conversion_state.expanded_format_raw
+    = new_expanded_formats ();
 }
 
 void
@@ -11269,9 +11266,6 @@ html_finalize_output_state (CONVERTER *self)
     }
   self->associated_inline_content.number = 0;
 
-  self->shared_conversion_state.integers.info_number = 0;
-  clear_strings_list (&self->shared_conversion_state.key_strings);
-
   html_pop_document_context (self);
 
   /* could change to 0 in releases? */
@@ -11307,6 +11301,19 @@ html_reset_converter (CONVERTER *self)
     }
 
   free (self->shared_conversion_state.footnote_id_numbers);
+  free (self->shared_conversion_state.expanded_format_raw);
+
+  if (self->document->index_names)
+    {
+      for (i = 0; i < self->sorted_index_names.number; i++)
+        {
+          free (self->shared_conversion_state.formatted_index_entries[i]);
+        }
+    free (self->shared_conversion_state.formatted_index_entries);
+  }
+
+  free (self->sorted_index_names.list);
+  memset (&self->sorted_index_names, 0, sizeof (SORTED_INDEX_NAMES));
 
   free (self->special_units_direction_name);
   self->special_units_direction_name = 0;
@@ -11589,11 +11596,6 @@ html_free_converter (CONVERTER *self)
 
   free (self->associated_inline_content.list);
 
-  free_strings_list (&self->shared_conversion_state_integer);
-
-  destroy_associated_info (&self->shared_conversion_state.integers);
-  free_strings_list (&self->shared_conversion_state.key_strings);
-
   free (self->no_arg_formatted_cmd_translated.list);
 
   free (self->referred_command_stack.stack);
@@ -12192,7 +12194,7 @@ convert_to_html_internal (CONVERTER *self, const 
ELEMENT *element,
   /* for debugging, for explanations */
   TEXT command_type;
   char *debug_str;
-  char *command_name = element_command_name (element);
+  const char *command_name = element_command_name (element);
   enum command_id cmd = element_builtin_cmd (element);
 
   text_init (&command_type);
diff --git a/tp/Texinfo/XS/convert/convert_html.h 
b/tp/Texinfo/XS/convert/convert_html.h
index c0a13aed38..d3c7bbe9ed 100644
--- a/tp/Texinfo/XS/convert/convert_html.h
+++ b/tp/Texinfo/XS/convert/convert_html.h
@@ -45,7 +45,7 @@ void html_open_type_update_context (CONVERTER *self,
                                     enum element_type type);
 void html_convert_type_update_context (CONVERTER *self, enum element_type 
type);
 void html_new_document_context (CONVERTER *self,
-        char *context_name, char *document_global_context,
+        const char *context_name, const char *document_global_context,
         enum command_id block_command);
 void html_pop_document_context (CONVERTER *self);
 void html_set_code_context (CONVERTER *self, int code);
@@ -110,6 +110,16 @@ TREE_ADDED_ELEMENTS *html_internal_command_tree (CONVERTER 
*self,
 char *html_internal_command_text (CONVERTER *self, const ELEMENT *command,
                                   const enum html_text_type type);
 
+EXPLAINED_COMMAND_TYPE *find_explained_command_string
+                           (EXPLAINED_COMMAND_TYPE_LIST *type_explanations,
+                               const enum command_id cmd, const char *type);
+void register_explained_command_string (
+               EXPLAINED_COMMAND_TYPE_LIST *type_explanations,
+                    const enum command_id cmd,
+                    const char *type, const char *explanation);
+FOOTNOTE_ID_NUMBER *find_footnote_id_number (CONVERTER *self,
+                                           const char *footnote_id);
+
 void html_register_opened_section_level (CONVERTER *self, int level,
                                          const char *close_string);
 STRING_LIST *html_close_registered_sections_level (CONVERTER *self,
diff --git a/tp/Texinfo/XS/convert/get_html_perl_info.c 
b/tp/Texinfo/XS/convert/get_html_perl_info.c
index 733ff0e829..fd5556797f 100644
--- a/tp/Texinfo/XS/convert/get_html_perl_info.c
+++ b/tp/Texinfo/XS/convert/get_html_perl_info.c
@@ -49,6 +49,8 @@ FIXME add an initialization of translations?
 #include "converter.h"
 #include "convert_html.h"
 #include "get_perl_info.h"
+/* for newSVpv_utf8 */
+#include "build_perl_info.h"
 #include "get_html_perl_info.h"
 
 /* Following is HTML specific */
@@ -307,7 +309,7 @@ html_converter_initialize_sv (SV *converter_sv,
 
   for (i = 0; i < BUILTIN_CMD_NUMBER; i++)
     {
-      char *ref_name;
+      const char *ref_name;
       if (i == 0)
         ref_name = "";
       else
@@ -336,7 +338,7 @@ html_converter_initialize_sv (SV *converter_sv,
 
   for (i = 0; i < BUILTIN_CMD_NUMBER; i++)
     {
-      char *ref_name;
+      const char *ref_name;
       if (i == 0)
         ref_name = "";
       else
@@ -361,7 +363,7 @@ html_converter_initialize_sv (SV *converter_sv,
 
   for (i = 0; i < TXI_TREE_TYPES_NUMBER; i++)
     {
-      char *ref_name;
+      const char *ref_name;
       if (i == 0)
         ref_name = "";
       else
@@ -1134,10 +1136,12 @@ html_converter_prepare_output_sv (SV *converter_sv, 
CONVERTER *converter)
 
 #undef FETCH
 
-ELEMENT *
-find_index_entry_element (CONVERTER *converter, SV *index_entry_sv)
+/* find from an extra element index entry */
+int
+find_index_entry_numbers_extra_index_entry_sv (CONVERTER *converter,
+                            SV *extra_index_entry_sv, size_t *index_nr)
 {
-  AV *index_entry_av;
+  AV *extra_index_entry_av;
   SV **index_name_sv;
   char *index_name = 0;
 
@@ -1146,9 +1150,9 @@ find_index_entry_element (CONVERTER *converter, SV 
*index_entry_sv)
   if (!converter->document->index_names)
     return 0;
 
-  index_entry_av = (AV *) SvRV (index_entry_sv);
+  extra_index_entry_av = (AV *) SvRV (extra_index_entry_sv);
 
-  index_name_sv = av_fetch (index_entry_av, 0, 0);
+  index_name_sv = av_fetch (extra_index_entry_av, 0, 0);
   if (index_name_sv)
     {
       index_name = SvPVutf8_nolen (*index_name_sv);
@@ -1156,26 +1160,55 @@ find_index_entry_element (CONVERTER *converter, SV 
*index_entry_sv)
 
   if (index_name)
     {
-      SV **number_sv = av_fetch (index_entry_av, 1, 0);
+      SV **number_sv = av_fetch (extra_index_entry_av, 1, 0);
       if (number_sv)
         {
           int entry_number = SvIV (*number_sv);
-          INDEX **index_names = converter->document->index_names;
-          INDEX *idx = indices_info_index_by_name (index_names, index_name);
 
-          if (idx)
-            {
-              INDEX_ENTRY *index_entry = &idx->index_entries[entry_number -1];
-              if (index_entry->entry_associated_element)
-                return index_entry->entry_associated_element;
-              else if (index_entry->entry_element)
-                return index_entry->entry_element;
-            }
+          *index_nr
+            = index_number_index_by_name (&converter->sorted_index_names,
+                                          index_name);
+          return entry_number;
         }
     }
   return 0;
 }
 
+INDEX_ENTRY *
+find_index_entry_extra_index_entry_sv (CONVERTER *converter,
+                                       SV *extra_index_entry_sv)
+{
+  size_t index_nr;
+
+  int entry_number
+    = find_index_entry_numbers_extra_index_entry_sv (converter,
+                                                     extra_index_entry_sv,
+                                                     &index_nr);
+
+  if (entry_number)
+    return &converter->sorted_index_names.list[index_nr -1].index
+              ->index_entries[entry_number -1];
+
+  return 0;
+}
+
+ELEMENT *
+find_element_extra_index_entry_sv (CONVERTER *converter,
+                                   SV *extra_index_entry_sv)
+{
+  INDEX_ENTRY *index_entry = find_index_entry_extra_index_entry_sv
+                                        (converter, extra_index_entry_sv);
+  if (index_entry)
+    {
+      if (index_entry->entry_associated_element)
+        return index_entry->entry_associated_element;
+      else if (index_entry->entry_element)
+        return index_entry->entry_element;
+    }
+  return 0;
+}
+
+
 #define FETCH(key) key##_sv = hv_fetch (element_hv, #key, strlen(#key), 0);
 /* find C tree root element corresponding to perl tree element element_hv */
 ELEMENT *find_root_command (CONVERTER *converter, HV *element_hv,
@@ -1228,6 +1261,9 @@ ELEMENT *find_root_command (CONVERTER *converter, HV 
*element_hv,
   return 0;
 }
 
+/* TODO nodedescription using the extra element_node and the
+ * node extra node_description? */
+
 /* find C Texinfo tree element based on element_sv perl tree element.
    Only for elements that can be targets of links. */
 ELEMENT *
@@ -1246,7 +1282,7 @@ find_element_from_sv (CONVERTER *converter, SV 
*element_sv,
 
   FETCH(cmdname)
 
-  if (cmdname_sv)
+  if (cmdname_sv && output_units_descriptor)
     {
       char *cmdname = SvPVutf8_nolen (*cmdname_sv);
       cmd = lookup_builtin_command (cmdname);
@@ -1303,7 +1339,7 @@ find_element_from_sv (CONVERTER *converter, SV 
*element_sv,
       EXTRA(associated_index_entry)
       if (associated_index_entry_sv)
         {
-          ELEMENT *index_element = find_index_entry_element (converter,
+          ELEMENT *index_element = find_element_extra_index_entry_sv 
(converter,
                                                *associated_index_entry_sv);
           /* there should be no ambiguity, but we check nevertheless */
           if (index_element && index_element->hv == element_hv)
@@ -1313,7 +1349,7 @@ find_element_from_sv (CONVERTER *converter, SV 
*element_sv,
       EXTRA(index_entry)
       if (index_entry_sv)
         {
-          ELEMENT *index_element = find_index_entry_element (converter,
+          ELEMENT *index_element = find_element_extra_index_entry_sv(converter,
                                                           *index_entry_sv);
           /* it is important to check if the index entry was reassociated */
           if (index_element && index_element->hv == element_hv)
@@ -1400,3 +1436,243 @@ element_converter_from_sv (SV *converter_in, SV 
*element_sv,
   return find_element_from_sv (*converter_out, element_sv,
                                output_units_descriptor);
 }
+
+/* find from an index entry in index data */
+int
+find_index_entry_numbers_index_entry_sv (CONVERTER *converter,
+                            SV *index_entry_sv, size_t *index_nr)
+{
+  HV *index_entry_hv;
+  SV **index_name_sv;
+  char *index_name = 0;
+
+  dTHX;
+
+  if (!converter->document->index_names)
+    return 0;
+
+  index_entry_hv = (HV *) SvRV (index_entry_sv);
+
+  index_name_sv = hv_fetch (index_entry_hv, "index_name",
+                            strlen("index_name") ,0);
+  if (index_name_sv)
+    {
+      index_name = SvPVutf8_nolen (*index_name_sv);
+    }
+
+  if (index_name)
+    {
+      SV **number_sv = hv_fetch (index_entry_hv, "entry_number",
+                                 strlen("entry_number") ,0);
+
+      if (number_sv)
+        {
+          int entry_number = SvIV (*number_sv);
+
+          *index_nr
+            = index_number_index_by_name (&converter->sorted_index_names,
+                                          index_name);
+          return entry_number;
+        }
+    }
+  return 0;
+}
+
+HTML_TARGET *
+find_node_target_info_nodedescription_sv (CONVERTER *converter,
+                                          SV *element_sv)
+{
+  HV *element_hv;
+  SV **extra_sv;
+
+  dTHX;
+
+  element_hv = (HV *)SvRV (element_sv);
+  extra_sv = hv_fetch (element_hv, "extra", strlen ("extra"), 0);
+  if (extra_sv)
+    {
+      HV *extra_hv = (HV *)SvRV (*extra_sv);
+      SV **element_node_sv = hv_fetch (extra_hv, "element_node",
+                                       strlen ("element_node"), 0);
+      if (element_node_sv)
+        {
+          ELEMENT *node = find_element_from_sv (converter,
+                                                *element_node_sv, 0);
+          if (node)
+            {
+              HTML_TARGET *target_info = html_get_target (converter, node);
+              return target_info;
+            }
+        }
+    }
+  return 0;
+}
+
+
+void
+html_set_shared_conversion_state (CONVERTER *converter, SV *converter_in,
+                               const char *cmdname, const char *state_name,
+                               const int args_nr, SV **args_sv)
+{
+  dTHX;
+
+  if (!strcmp (state_name, "formatted_index_entries"))
+    {
+      int formatted_nr = SvIV (args_sv[1]);
+      size_t index_nr;
+
+      int entry_number
+        = find_index_entry_numbers_index_entry_sv (converter,
+                                                args_sv[0], &index_nr);
+
+      converter->shared_conversion_state
+         .formatted_index_entries[index_nr-1][entry_number-1] = formatted_nr;
+    }
+  else if (!strcmp (state_name, "html_menu_entry_index"))
+    {
+      int html_menu_entry_index = SvIV (args_sv[0]);
+      converter->shared_conversion_state.html_menu_entry_index
+        = html_menu_entry_index;
+    }
+  else if (!strcmp (state_name, "footnote_number"))
+    {
+      int footnote_number = SvIV (args_sv[0]);
+      converter->shared_conversion_state.footnote_number
+        = footnote_number;
+    }
+  else if (!strcmp (state_name, "footnote_id_numbers"))
+    {
+      char *footnote_id = (char *)SvPVutf8_nolen(args_sv[0]);
+      int number = SvIV (args_sv[1]);
+      FOOTNOTE_ID_NUMBER *footnote_id_number
+       = find_footnote_id_number (converter, footnote_id);
+      if (footnote_id_number)
+        {
+          footnote_id_number->number = number;
+        }
+    }
+  else if (!strcmp (state_name, "explained_commands"))
+    {
+      EXPLAINED_COMMAND_TYPE_LIST *type_explanations
+       = &converter->shared_conversion_state.explained_commands;
+      enum command_id cmd = lookup_builtin_command (cmdname);
+      char *type = (char *)SvPVutf8_nolen(args_sv[0]);
+      char *explanation = (char *)SvPVutf8_nolen(args_sv[1]);
+      register_explained_command_string (type_explanations,
+                                         cmd, type, explanation);
+    }
+  else if (!strcmp (state_name, "formatted_nodedescriptions"))
+    {
+      HTML_TARGET *target_info
+        = find_node_target_info_nodedescription_sv (converter, args_sv[0]);
+      int number = SvIV (args_sv[1]);
+
+      if (target_info)
+        target_info->formatted_nodedescription_nr = number;
+    }
+  else if (!strcmp (state_name, "expanded_format_raw"))
+    {
+      char *format = (char *)SvPVutf8_nolen(args_sv[0]);
+      int expanded = SvIV (args_sv[1]);
+      if (expanded)
+        add_expanded_format
+            (converter->shared_conversion_state.expanded_format_raw,
+                             format);
+    }
+  else if (!strcmp (state_name, "in_skipped_node_top"))
+    {
+      int in_skipped_node_top = SvIV (args_sv[0]);
+      converter->shared_conversion_state.in_skipped_node_top
+        = in_skipped_node_top;
+    }
+}
+
+SV *
+html_get_shared_conversion_state (CONVERTER *converter, SV *converter_in,
+                               const char *cmdname, const char *state_name,
+                               const int args_nr, SV **args_sv)
+{
+  dTHX;
+
+  if (!strcmp (state_name, "formatted_index_entries"))
+    {
+      size_t index_nr;
+
+      int entry_number
+        = find_index_entry_numbers_index_entry_sv (converter,
+                                                args_sv[0], &index_nr);
+      if (entry_number <= 0)
+        fatal ("index entry not found");
+
+      return newSViv(converter->shared_conversion_state
+         .formatted_index_entries[index_nr-1][entry_number-1]);
+    }
+  else if (!strcmp (state_name, "html_menu_entry_index"))
+    return newSViv(converter->shared_conversion_state.html_menu_entry_index);
+  else if (!strcmp (state_name, "footnote_number"))
+    return newSViv(converter->shared_conversion_state.footnote_number);
+  else if (!strcmp (state_name, "footnote_id_numbers"))
+    {
+      char *footnote_id = (char *)SvPVutf8_nolen(args_sv[0]);
+      FOOTNOTE_ID_NUMBER *footnote_id_number
+       = find_footnote_id_number (converter, footnote_id);
+      if (footnote_id_number->number > 0)
+        return newSViv(footnote_id_number->number);
+    }
+  else if (!strcmp (state_name, "explained_commands"))
+    {
+      char *type = (char *)SvPVutf8_nolen(args_sv[0]);
+      enum command_id cmd = lookup_builtin_command (cmdname);
+      EXPLAINED_COMMAND_TYPE_LIST *type_explanations
+       = &converter->shared_conversion_state.explained_commands;
+      EXPLAINED_COMMAND_TYPE *type_explanation
+         = find_explained_command_string(type_explanations, cmd, type);
+      if (type_explanation)
+        {
+          char *explanation_string = type_explanation->explanation;
+          return newSVpv_utf8 (explanation_string, 0);
+        }
+    }
+  else if (!strcmp (state_name, "formatted_nodedescriptions"))
+    {
+      HTML_TARGET *target_info
+        = find_node_target_info_nodedescription_sv (converter, args_sv[0]);
+
+      if (target_info && target_info->formatted_nodedescription_nr > 0)
+        return newSViv (target_info->formatted_nodedescription_nr);
+    }
+  else if (!strcmp (state_name, "expanded_format_raw"))
+    {
+      char *format;
+
+      if (args_nr == 0)
+        {
+          int i;
+          HV *expanded_hv = newHV ();
+          for (i = 0; i < expanded_formats_number (); i++)
+            {
+              if (converter->shared_conversion_state
+                                    .expanded_format_raw[i].expandedp)
+                {
+                  char *format = converter->shared_conversion_state
+                                    .expanded_format_raw[i].format;
+                  hv_store (expanded_hv, format, strlen (format),
+                            newSViv (1), 0);
+                }
+            }
+          return newRV_noinc ((SV *)expanded_hv);
+        }
+      else if (args_nr > 0)
+        {
+          format = (char *)SvPVutf8_nolen(args_sv[0]);
+          int expanded
+            = format_expanded_p (
+                converter->shared_conversion_state.expanded_format_raw,
+                                 format);
+          return newSViv(expanded);
+        }
+    }
+  else if (!strcmp (state_name, "in_skipped_node_top"))
+    return newSViv(converter->shared_conversion_state.in_skipped_node_top);
+  return newSV (0);
+}
diff --git a/tp/Texinfo/XS/convert/get_html_perl_info.h 
b/tp/Texinfo/XS/convert/get_html_perl_info.h
index 284ec08a74..fcde7db85d 100644
--- a/tp/Texinfo/XS/convert/get_html_perl_info.h
+++ b/tp/Texinfo/XS/convert/get_html_perl_info.h
@@ -26,4 +26,11 @@ ELEMENT *find_element_from_sv (CONVERTER *converter, SV 
*element_sv,
 
 ELEMENT *element_converter_from_sv (SV *converter_in, SV *element_sv,
                        const char *warn_string, CONVERTER **converter_out);
+
+void html_set_shared_conversion_state (CONVERTER *converter, SV *converter_in,
+                               const char *cmdname, const char *state_name,
+                               const int args_nr, SV **args_sv);
+SV *html_get_shared_conversion_state (CONVERTER *converter, SV *converter_in,
+                               const char *cmdname, const char *state_name,
+                               const int args_nr, SV **args_sv);
 #endif
diff --git a/tp/Texinfo/XS/main/builtin_commands.c 
b/tp/Texinfo/XS/main/builtin_commands.c
index 96ace973b8..e85fe027a9 100644
--- a/tp/Texinfo/XS/main/builtin_commands.c
+++ b/tp/Texinfo/XS/main/builtin_commands.c
@@ -39,12 +39,13 @@ compare_command_fn (const void *a, const void *b)
 
 /* Return element number in command_data array.  Return 0 if not found. */
 enum command_id
-lookup_builtin_command (char *cmdname)
+lookup_builtin_command (const char *cmdname)
 {
   COMMAND *c;
   COMMAND target;
 
-  target.cmdname = cmdname;
+  /* cast as target.cmdname is not const, though we know we do not modify */
+  target.cmdname = (char *) cmdname;
 
   c = (COMMAND *) bsearch (&target, builtin_command_data + 1,
         /* number of elements */
@@ -63,7 +64,7 @@ lookup_builtin_command (char *cmdname)
 
 /* this should be used when the user-defined commands are not available,
    ie outside of the parser */
-char *
+const char *
 element_command_name (const ELEMENT *e)
 {
   if (e->cmd && e->cmd < BUILTIN_CMD_NUMBER)
diff --git a/tp/Texinfo/XS/main/builtin_commands.h 
b/tp/Texinfo/XS/main/builtin_commands.h
index 3f905b303f..16d9bdfc31 100644
--- a/tp/Texinfo/XS/main/builtin_commands.h
+++ b/tp/Texinfo/XS/main/builtin_commands.h
@@ -35,8 +35,8 @@ extern COMMAND builtin_command_data[];
 #define command_other_flags(e) \
    (!(e) ? 0 : (builtin_command_data[(e)->cmd].other_flags))
 
-enum command_id lookup_builtin_command (char *cmdname);
-char *element_command_name (const ELEMENT *e);
+enum command_id lookup_builtin_command (const char *cmdname);
+const char *element_command_name (const ELEMENT *e);
 enum command_id element_builtin_cmd (const ELEMENT *e);
 enum command_id element_builtin_data_cmd (const ELEMENT *e);
 
diff --git a/tp/Texinfo/XS/main/convert_to_texinfo.c 
b/tp/Texinfo/XS/main/convert_to_texinfo.c
index 351b9a3fd1..3fb46f6778 100644
--- a/tp/Texinfo/XS/main/convert_to_texinfo.c
+++ b/tp/Texinfo/XS/main/convert_to_texinfo.c
@@ -50,7 +50,7 @@ expand_cmd_args_to_texi (const ELEMENT *e, TEXT *result)
 
   if (cmd)
     {
-      char *cmdname = element_command_name (e);
+      const char *cmdname = element_command_name (e);
       ADD("@");  ADD(cmdname);
       elt = lookup_info_element (e, "spaces_after_cmd_before_arg");
       if (elt)
diff --git a/tp/Texinfo/XS/main/converter_types.h 
b/tp/Texinfo/XS/main/converter_types.h
index 0e6ec827bc..88d2ce65b6 100644
--- a/tp/Texinfo/XS/main/converter_types.h
+++ b/tp/Texinfo/XS/main/converter_types.h
@@ -273,6 +273,8 @@ typedef struct HTML_TARGET {
     int root_element_command_set;
     const ELEMENT *node_command;
     int node_command_set;
+
+    int formatted_nodedescription_nr;
 } HTML_TARGET;
 
 typedef struct HTML_TARGET_LIST {
@@ -299,22 +301,19 @@ typedef struct FOOTNOTE_ID_NUMBER {
 } FOOTNOTE_ID_NUMBER;
 
 typedef struct HTML_SHARED_CONVERSION_STATE {
+    int in_skipped_node_top;
+    /* not used in C, directly use expanded formats in the converter.
+      Needed in perl as expanded formats are accessed per format in the API */
+    EXPANDED_FORMAT *expanded_format_raw;
     EXPLAINED_COMMAND_TYPE_LIST explained_commands;
         /* explained_commands->{char $cmdname}->{char $normalized_type}
                                = explanation */
     int footnote_number;
     FOOTNOTE_ID_NUMBER *footnote_id_numbers; /* footnote_id_numbers->{char 
$footid} = int */
-    /* Not useful, directly use expanded formats in the converter.
-       Needed in perl as expanded formats are accessed per format in the API
-    int expanded_format_raw;
-     */
-    int formatted_index_entries; /* formatted_index_entries->{INDEX_ENTRY 
$index_entry_ref} = 1, ++ */
-    int formatted_nodedescriptions; /* formatted_nodedescriptions->{ELEMENT 
$node_description} = 1, ++ */
-    ASSOCIATED_INFO integers;
-    STRING_LIST key_strings; /* used to save the keys used in
-                                ASSOCIATED_INFO integers such that they can be
-                                free'd later.  In general constant strings are
-                                for keys, if not, key_strings should be used */
+    int html_menu_entry_index;
+    int **formatted_index_entries; /* formatted_index_entries->{INDEX_ENTRY 
$index_entry_ref} = 1, ++ */
+    /* stored in HTML_TARGET formatted_nodedescription_nr */
+    /* formatted_nodedescriptions */
 } HTML_SHARED_CONVERSION_STATE;
 
 typedef struct MERGED_INDEX {
@@ -656,6 +655,16 @@ typedef struct JSLICENSE_CATEGORY_LIST {
     JSLICENSE_FILE_INFO_LIST *list;
 } JSLICENSE_CATEGORY_LIST;
 
+typedef struct INDEX_NUMBER {
+    size_t number;
+    INDEX *index;
+} INDEX_NUMBER;
+
+typedef struct SORTED_INDEX_NAMES {
+    size_t number;
+    INDEX_NUMBER *list;
+} SORTED_INDEX_NAMES;
+
 typedef struct CONVERTER {
     int converter_descriptor;
   /* perl converter. This should be HV *hv,
@@ -728,6 +737,7 @@ typedef struct CONVERTER {
     const OUTPUT_UNIT **global_units_directions;
     SPECIAL_UNIT_DIRECTION *special_units_direction_name;
     ELEMENT **special_unit_info_tree[SUIT_type_heading+1];
+    SORTED_INDEX_NAMES sorted_index_names;
     STRING_LIST seen_ids;
     HTML_TARGET_LIST html_targets;
     HTML_TARGET_LIST html_special_targets[ST_footnote_location+1];
@@ -752,7 +762,6 @@ typedef struct CONVERTER {
                                before calling perl functions on it */
     COMMAND_ID_LIST no_arg_formatted_cmd_translated; /* list of commands that
                          were translated and need to be passed back to perl */
-    STRING_LIST shared_conversion_state_integer; /* modified */
     /* next 4 allow to switch from normal HTML formatting to css strings
        formatting */
     FORMATTING_REFERENCE *current_formatting_references;
diff --git a/tp/Texinfo/XS/main/debug.c b/tp/Texinfo/XS/main/debug.c
index 298cb40bc7..c925d44deb 100644
--- a/tp/Texinfo/XS/main/debug.c
+++ b/tp/Texinfo/XS/main/debug.c
@@ -26,7 +26,7 @@
 #include "extra.h"
 #include "debug.h"
 
-char *
+const char *
 debug_element_command_name (const ELEMENT *e)
 {
   if (e->cmd == CM_TAB)
diff --git a/tp/Texinfo/XS/main/extra.c b/tp/Texinfo/XS/main/extra.c
index 2cc4001184..0dbc3553c1 100644
--- a/tp/Texinfo/XS/main/extra.c
+++ b/tp/Texinfo/XS/main/extra.c
@@ -59,7 +59,7 @@ get_associated_info_key (ASSOCIATED_INFO *a, const char *key,
    'associated_section' on a node command element. */
 /* TODO would be good to have ELEMENT be const */
 void
-add_extra_element (ELEMENT *e, char *key, ELEMENT *value)
+add_extra_element (ELEMENT *e, const char *key, ELEMENT *value)
 {
   KEY_PAIR *k = get_associated_info_key (&e->extra_info, key,
                                          extra_element);
@@ -135,7 +135,7 @@ add_extra_misc_args (ELEMENT *e, char *key, ELEMENT *value)
 }
 
 void
-add_extra_string (ELEMENT *e, char *key, char *value)
+add_extra_string (ELEMENT *e, const char *key, char *value)
 {
   KEY_PAIR *k = get_associated_info_key (&e->extra_info, key, extra_string);
   k->string = value;
@@ -149,14 +149,14 @@ add_info_string (ELEMENT *e, char *key, char *value)
 }
 
 void
-add_extra_string_dup (ELEMENT *e, char *key, char *value)
+add_extra_string_dup (ELEMENT *e, const char *key, const char *value)
 {
   KEY_PAIR *k = get_associated_info_key (&e->extra_info, key, extra_string);
   k->string = strdup (value);
 }
 
 void
-add_info_string_dup (ELEMENT *e, char *key, char *value)
+add_info_string_dup (ELEMENT *e, const char *key, const char *value)
 {
   KEY_PAIR *k = get_associated_info_key (&e->info_info, key, extra_string);
   k->string = strdup (value);
diff --git a/tp/Texinfo/XS/main/extra.h b/tp/Texinfo/XS/main/extra.h
index 3480442b7e..5d3adcfce0 100644
--- a/tp/Texinfo/XS/main/extra.h
+++ b/tp/Texinfo/XS/main/extra.h
@@ -19,18 +19,18 @@
 
 #include "tree_types.h"
 
-void add_extra_element (ELEMENT *e, char *key, ELEMENT *value);
+void add_extra_element (ELEMENT *e, const char *key, ELEMENT *value);
 void add_extra_element_oot (ELEMENT *e, char *key, ELEMENT *value);
 void add_extra_contents (ELEMENT *e, const char *key, ELEMENT_LIST *value);
 void add_extra_container (ELEMENT *e, char *key, ELEMENT *value);
 void add_extra_directions (ELEMENT *e, const char *key, ELEMENT *value);
 void add_extra_text (ELEMENT *e, char *key, ELEMENT *value);
 void add_extra_misc_args (ELEMENT *e, char *key, ELEMENT *value);
-void add_extra_string (ELEMENT *e, char *key, char *value);
-void add_extra_string_dup (ELEMENT *e, char *key, char *value);
+void add_extra_string (ELEMENT *e, const char *key, char *value);
+void add_extra_string_dup (ELEMENT *e, const char *key, const char *value);
 void add_extra_integer (ELEMENT *e, char *key, long value);
 void add_info_string (ELEMENT *e, char *key, char *value);
-void add_info_string_dup (ELEMENT *e, char *key, char *value);
+void add_info_string_dup (ELEMENT *e, const char *key, const char *value);
 void add_info_element_oot (ELEMENT *e, char *key, ELEMENT *value);
 void add_associated_info_integer (ASSOCIATED_INFO *a,
                                   const char *key, int value);
diff --git a/tp/Texinfo/XS/main/utils.c b/tp/Texinfo/XS/main/utils.c
index dd3d053a24..a863e57f85 100644
--- a/tp/Texinfo/XS/main/utils.c
+++ b/tp/Texinfo/XS/main/utils.c
@@ -504,7 +504,7 @@ new_expanded_formats (void)
 }
 
 int
-format_expanded_p (EXPANDED_FORMAT *formats, char *format)
+format_expanded_p (EXPANDED_FORMAT *formats, const char *format)
 {
   int i;
   for (i = 0; i < sizeof (expanded_formats)/sizeof (*expanded_formats);
@@ -516,6 +516,12 @@ format_expanded_p (EXPANDED_FORMAT *formats, char *format)
   return 0;
 }
 
+int
+expanded_formats_number (void)
+{
+  return sizeof (expanded_formats)/sizeof (*expanded_formats);
+}
+
 
 /* Return the parent if in an item_line command, @*table */
 ELEMENT *
@@ -565,6 +571,23 @@ ultimate_index (INDEX *index)
   return index;
 }
 
+/* only used in conversion, on sorted indices names */
+/* TODO also a bsearch? */
+size_t
+index_number_index_by_name (const SORTED_INDEX_NAMES *sorted_indices,
+                            const char *name)
+{
+  size_t i;
+
+  for (i = 0; i < sorted_indices->number; i++)
+    {
+      if (!strcmp (sorted_indices->list[i].index->name, name))
+        return i+1;
+    }
+  return 0;
+}
+
+
 
 /* text parsing functions used in diverse situations */
 /* Read a name used for @set, @value and translations arguments. */
diff --git a/tp/Texinfo/XS/main/utils.h b/tp/Texinfo/XS/main/utils.h
index cad189a4a1..342cc1f57d 100644
--- a/tp/Texinfo/XS/main/utils.h
+++ b/tp/Texinfo/XS/main/utils.h
@@ -120,8 +120,8 @@ enum command_location {
 
 /* HTML modified state flags */
 #define HMSF_current_root            0x0001
-#define HMSF_shared_conversion_state_integer  0x0002
 /*
+#define HMSF_  0x0002
 #define HMSF_      0x0004
 #define HMSF_     0x0008
 #define HMSF_    0x0010
@@ -191,6 +191,8 @@ ELEMENT *item_line_parent (ELEMENT *current);
 ELEMENT *get_label_element (const ELEMENT *e);
 INDEX *indices_info_index_by_name (INDEX **indices_information, char *name);
 INDEX *ultimate_index (INDEX *index);
+size_t index_number_index_by_name (const SORTED_INDEX_NAMES *sorted_indices,
+                                   const char *name);
 char *read_flag_name (char **ptr);
 int section_level (const ELEMENT *section);
 enum command_id section_level_adjusted_command_name (const ELEMENT *element);
@@ -233,7 +235,8 @@ char *encode_string (char *input_string, char *encoding, 
int *status,
 EXPANDED_FORMAT *new_expanded_formats (void);
 void clear_expanded_formats (EXPANDED_FORMAT *formats);
 void add_expanded_format (EXPANDED_FORMAT *formats, char *format);
-int format_expanded_p (EXPANDED_FORMAT *formats, char *format);
+int format_expanded_p (EXPANDED_FORMAT *formats, const char *format);
+int expanded_formats_number (void);
 
 char *enumerate_item_representation (char *specification, int number);
 
diff --git a/tp/Texinfo/XS/parsetexi/debug_parser.c 
b/tp/Texinfo/XS/parsetexi/debug_parser.c
index 6f915aba1e..caaf3cf353 100644
--- a/tp/Texinfo/XS/parsetexi/debug_parser.c
+++ b/tp/Texinfo/XS/parsetexi/debug_parser.c
@@ -90,7 +90,7 @@ debug_print_protected_string (char *input_string)
    user-defined commands information.
 */
 
-char *
+const char *
 debug_parser_command_name (enum command_id cmd)
 {
   if (cmd == CM_TAB)
diff --git a/tp/Texinfo/XS/parsetexi/debug_parser.h 
b/tp/Texinfo/XS/parsetexi/debug_parser.h
index df26271d78..eac8d81773 100644
--- a/tp/Texinfo/XS/parsetexi/debug_parser.h
+++ b/tp/Texinfo/XS/parsetexi/debug_parser.h
@@ -13,7 +13,7 @@ void debug_print_element (const ELEMENT *e, int print_parent);
 void debug_print_protected_string (char *input_string);
 
 char *print_element_debug_parser (ELEMENT *e, int print_parent);
-char *debug_parser_command_name (enum command_id cmd);
+const char *debug_parser_command_name (enum command_id cmd);
 void debug_parser_print_element (ELEMENT *e, int print_parent);
 
 #endif
diff --git a/tp/Texinfo/XS/parsetexi/end_line.c 
b/tp/Texinfo/XS/parsetexi/end_line.c
index f496e5d37a..3662a4fd5d 100644
--- a/tp/Texinfo/XS/parsetexi/end_line.c
+++ b/tp/Texinfo/XS/parsetexi/end_line.c
@@ -1102,7 +1102,7 @@ end_line_starting_block (ELEMENT *current)
         }
       else if (!memcmp (command_name(command), "if", 2)) /* e.g. @ifhtml */
         {
-          char *p;
+          const char *p;
           /* Handle @if* and @ifnot* */
 
           p = command_name(command) + 2; /* After "if". */
diff --git a/tp/Texinfo/XS/parsetexi/handle_commands.c 
b/tp/Texinfo/XS/parsetexi/handle_commands.c
index c081d6b580..247aebfe4f 100644
--- a/tp/Texinfo/XS/parsetexi/handle_commands.c
+++ b/tp/Texinfo/XS/parsetexi/handle_commands.c
@@ -854,10 +854,9 @@ handle_line_command (ELEMENT *current, char **line_inout,
                   char *base_name;
                   int base_len;
 
-                  base_name = command_name(cmd);
                   add_extra_string_dup (command_e, "original_def_cmdname",
-                                        base_name);
-                  base_name = strdup (base_name);
+                                        command_name(cmd));
+                  base_name = strdup (command_name(cmd));
                   base_len = strlen (base_name);
                   if (base_name[base_len - 1] != 'x')
                     fatal ("no x at end of def command name");
@@ -998,7 +997,7 @@ add_parser_expanded_format (char *format)
 }
 
 int
-parser_format_expanded_p (char *format)
+parser_format_expanded_p (const char *format)
 {
   return format_expanded_p (parser_expanded_formats, format);
 }
diff --git a/tp/Texinfo/XS/parsetexi/handle_commands.h 
b/tp/Texinfo/XS/parsetexi/handle_commands.h
index f41929d130..c67d1f7c68 100644
--- a/tp/Texinfo/XS/parsetexi/handle_commands.h
+++ b/tp/Texinfo/XS/parsetexi/handle_commands.h
@@ -19,7 +19,7 @@ int check_no_text (ELEMENT *current);
 
 void clear_parser_expanded_formats (void);
 void add_parser_expanded_format (char *format);
-int parser_format_expanded_p (char *format);
+int parser_format_expanded_p (const char *format);
 
 extern struct expanded_format parser_expanded_formats[7];
 
diff --git a/tp/Texinfo/XS/parsetexi/input.c b/tp/Texinfo/XS/parsetexi/input.c
index f37e92ffe7..2199b0c2e5 100644
--- a/tp/Texinfo/XS/parsetexi/input.c
+++ b/tp/Texinfo/XS/parsetexi/input.c
@@ -251,7 +251,7 @@ save_line_directive (int line_nr, char *filename)
 
 
 int
-expanding_macro (char *macro)
+expanding_macro (const char *macro)
 {
   int i;
   for (i = 0; i < input_number; i++)
@@ -265,7 +265,7 @@ expanding_macro (char *macro)
   return 0;
 }
 
-char *save_string (char *string);
+char *save_string (const char *string);
 
 void
 input_pushback (char *string)
@@ -457,11 +457,11 @@ next_text (ELEMENT *current)
    VALUE_FLAG will be later free'd, but not MACRO_NAME.
  */
 void
-input_push_text (char *text, int line_number, char *macro_name,
+input_push_text (char *text, int line_number, const char *macro_name,
                  char *value_flag)
 {
   char *filename = 0;
-  char *in_macro = 0;
+  const char *in_macro = 0;
 
   if (!text)
     return;
@@ -515,7 +515,7 @@ size_t small_strings_num = 0;
 static size_t small_strings_space;
 
 char *
-save_string (char *string)
+save_string (const char *string)
 {
   char *ret = string ? strdup (string) : 0;
   if (ret)
diff --git a/tp/Texinfo/XS/parsetexi/input.h b/tp/Texinfo/XS/parsetexi/input.h
index 0c1fd8109f..08e72b4d19 100644
--- a/tp/Texinfo/XS/parsetexi/input.h
+++ b/tp/Texinfo/XS/parsetexi/input.h
@@ -11,14 +11,14 @@ char *next_text (ELEMENT *current);
 
 void save_line_directive (int line_nr, char *filename);
 
-void input_push_text (char *text, int line_number, char *macro_name,
+void input_push_text (char *text, int line_number, const char *macro_name,
                       char *value_flag);
 int input_push_file (char *filename);
 void input_pushback (char *line);
 void set_input_source_mark (SOURCE_MARK *source_mark);
 void input_reset_input_stack (void);
 void parser_reset_encoding_list (void);
-int expanding_macro (char *macro);
+int expanding_macro (const char *macro);
 int top_file_index (void);
 
 char *parser_locate_include_file (char *filename);
@@ -31,7 +31,7 @@ void parser_clear_include_directories (void);
 extern char **small_strings;
 extern size_t small_strings_num;
 
-char *save_string (char *string);
+char *save_string (const char *string);
 void free_small_strings (void);
 void forget_small_strings (void);
 
diff --git a/tp/Texinfo/XS/parsetexi/parser.c b/tp/Texinfo/XS/parsetexi/parser.c
index 0b15620a38..e62c218e68 100644
--- a/tp/Texinfo/XS/parsetexi/parser.c
+++ b/tp/Texinfo/XS/parsetexi/parser.c
@@ -1943,7 +1943,7 @@ process_remaining_on_line (ELEMENT **current_inout, char 
**line_inout)
            */
       || (command_data(cmd).flags & CF_ALIAS))
     {
-      char *unknown_cmd;
+      const char *unknown_cmd;
 
       if (cmd)
         {
diff --git a/tp/Texinfo/XS/parsetexi/separator.c 
b/tp/Texinfo/XS/parsetexi/separator.c
index 06cd9ca829..a7e3a1c529 100644
--- a/tp/Texinfo/XS/parsetexi/separator.c
+++ b/tp/Texinfo/XS/parsetexi/separator.c
@@ -101,7 +101,7 @@ handle_open_brace (ELEMENT *current, char **line_inout)
             {
 #define float floatxx
               ELEMENT *float;
-              char *caption_cmdname = command_name(command);
+              const char *caption_cmdname = command_name(command);
               nesting_context.caption++;
               if (!current->parent->parent
                   || current->parent->parent->cmd != CM_float)
diff --git a/tp/Texinfo/XS/structuring_transfo/structuring.c 
b/tp/Texinfo/XS/structuring_transfo/structuring.c
index e46979f4db..6bf36e4467 100644
--- a/tp/Texinfo/XS/structuring_transfo/structuring.c
+++ b/tp/Texinfo/XS/structuring_transfo/structuring.c
@@ -51,7 +51,7 @@ new_block_command (ELEMENT *element, enum command_id cmd)
   ELEMENT *end_spaces_before = new_element (ET_NONE);
   ELEMENT *end_spaces_after = new_element (ET_NONE);
   ELEMENT *command_name_text = new_element (ET_NONE);
-  char *command_name = builtin_command_name(cmd);
+  const char *command_name = builtin_command_name(cmd);
 
   element->cmd = cmd;
 
diff --git a/tp/init/book.pm b/tp/init/book.pm
index 4cac93eb81..55db5a1517 100644
--- a/tp/init/book.pm
+++ b/tp/init/book.pm
@@ -242,7 +242,7 @@ sub book_convert_heading_command($$$$$)
   if ($self->get_conf('NO_TOP_NODE_OUTPUT')
       and $Texinfo::Commands::root_commands{$cmdname}) {
     my $in_skipped_node_top
-      = $self->shared_conversion_state('in_skipped_node_top', 0);
+      = $self->get_shared_conversion_state('top', 'in_skipped_node_top');
     my $node_element;
     if ($cmdname eq 'node') {
       $node_element = $element;
@@ -254,12 +254,16 @@ sub book_convert_heading_command($$$$$)
       if ($node_element and $node_element->{'extra'}
           and $node_element->{'extra'}->{'normalized'}
           and $node_element->{'extra'}->{'normalized'} eq 'Top') {
-        $$in_skipped_node_top = 1;
-      } elsif ($$in_skipped_node_top == 1) {
-        $$in_skipped_node_top = -1;
+        $in_skipped_node_top = 1;
+        $self->set_shared_conversion_state('top', 'in_skipped_node_top',
+                                           $in_skipped_node_top);
+      } elsif ($in_skipped_node_top == 1) {
+        $in_skipped_node_top = -1;
+        $self->set_shared_conversion_state('top', 'in_skipped_node_top',
+                                           $in_skipped_node_top);
       }
     }
-    if ($$in_skipped_node_top == 1) {
+    if ($in_skipped_node_top == 1) {
       my $id_class = $cmdname;
       $result .= &{$self->formatting_function('format_separate_anchor')}($self,
                                                         $element_id, 
$id_class);
@@ -328,14 +332,16 @@ sub book_convert_heading_command($$$$$)
         my $use_next_heading = 0;
         if ($self->get_conf('USE_NEXT_HEADING_FOR_LONE_NODE')) {
           my $expanded_format_raw
-             = $self->shared_conversion_state('expanded_format_raw', {});
+             = $self->get_shared_conversion_state('top', 
'expanded_format_raw');
           # if no format is expanded, the formats will be checked each time
           # but this is very unlikely, as html is always expanded.
-          if (length(keys(%$expanded_format_raw)) == 0) {
+          if (!defined($expanded_format_raw)
+              or !scalar(keys(%$expanded_format_raw))) {
             foreach my $output_format_command
-                (keys(%Texinfo::Comon::texinfo_output_formats)) {
+                (keys(%Texinfo::Common::texinfo_output_formats)) {
               if ($self->is_format_expanded($output_format_command)) {
-                $expanded_format_raw->{$output_format_command} = 1;
+                $self->set_shared_conversion_state('top', 
'expanded_format_raw',
+                                                   $output_format_command, 1);
               }
             }
           }



reply via email to

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