texinfo-commits
[Top][All Lists]
Advanced

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

branch master updated: * tp/Texinfo/Convert/HTML.pm (_convert_def_line_t


From: Patrice Dumas
Subject: branch master updated: * tp/Texinfo/Convert/HTML.pm (_convert_def_line_type): fix call of Texinfo::Convert::Text::convert_to_text (in a code that is never run in normal circumstances).
Date: Sat, 28 Oct 2023 08:56:08 -0400

This is an automated email from the git hooks/post-receive script.

pertusus pushed a commit to branch master
in repository texinfo.

The following commit(s) were added to refs/heads/master by this push:
     new 659e828bb4 * tp/Texinfo/Convert/HTML.pm (_convert_def_line_type): fix 
call of Texinfo::Convert::Text::convert_to_text (in a code that is never run in 
normal circumstances).
659e828bb4 is described below

commit 659e828bb4c44910f8cdfa083242ccea8c8d2531
Author: Patrice Dumas <pertusus@free.fr>
AuthorDate: Sat Oct 28 14:54:47 2023 +0200

    * tp/Texinfo/Convert/HTML.pm (_convert_def_line_type): fix call of
    Texinfo::Convert::Text::convert_to_text (in a code that is never run
    in normal circumstances).
    
    * tp/Texinfo/Convert/HTML.pm (converter_initialize): set non expanded
    raw format commands to undef in 'commands_conversion' rather than not
    setting the key in the hash, as the meaning is different, it means
    ignoring the command, not that the command is not formatted.  For the
    XS code it makes a difference.
    
    * tp/Texinfo/Convert/HTML.pm (_translate_names, output): do not run
    both perl and XS code as it will mess up the converter state.  Do not
    call the XS code for now in output.
    
    * tp/Texinfo/Convert/HTML.pm (_convert): unset
    $self->{'current_root_command'} also when the command is not
    converted.
    
    * tp/Texinfo/Convert/Converter.pm (encode_converter_document)
    tp/Texinfo/Convert/HTML.pm (converter_initialize),
    tp/Texinfo/XS/convert/ConvertXS.xs (html_converter_initialize_sv),
    tp/Texinfo/XS/main/get_perl_info.c (html_converter_initialize_sv),
    tp/Texinfo/XS/main/utils.h (CONVERTER): pass output_units_conversion
    to XS.
    
    * tp/Texinfo/Convert/Text.pm (convert_to_text): confess if $options is
    not a ref.
    
    * tp/Texinfo/XS/main/utils.h (HTML_ARG_FORMATTED)
    (HTML_ARGS_FORMATTED, enum argument_formatting_type)
    (HTML_ARGUMENTS_FORMATTED_FORMAT_TYPE):
    rename from ARG_FORMATTED and ARGS_FORMATTED, move from
    tp/Texinfo/XS/convert/convert_html.c and add
    HTML_ARGUMENTS_FORMATTED_FORMAT_TYPE.
    
    * tp/Texinfo/XS/convert/convert_html.c (command_conversion)
    (command_open, convert_tree, convert_tree_new_formatting_context)
    (reset_unset_no_arg_commands_formatting_context)
    (destroy_args_formatted, convert_to_html_internal)
    (output_unit_conversion, convert_output_unit),
    tp/Texinfo/XS/main/build_perl_info.c (build_html_formatting_state)
    (build_html_command_formatted_args),
    tp/Texinfo/XS/main/call_perl_function.c (call_commands_conversion)
    (call_commands_open, call_output_units_conversion)
    (call_types_conversion, call_types_open), tp/Texinfo/XS/main/utils.h
    (CONVERTER), tp/Texinfo/XS/main/utils.c
    (html_argument_formatting_type_names): call output units conversion,
    command opening and conversion.  Progress in completeness of
    conversion.  Add self->modified_state to mark that the formatting
    state has to be rebuilt and self->tree_to_build if a tree need to be
    built as perl, in general when it comes from a translated string.
    Pass formatted_args to perl, pass multiple_pass formatting state.
---
 ChangeLog                               |   55 ++
 tp/TODO                                 |    5 +
 tp/Texinfo/Convert/Converter.pm         |    2 +-
 tp/Texinfo/Convert/HTML.pm              |   24 +-
 tp/Texinfo/Convert/Text.pm              |    3 +
 tp/Texinfo/XS/convert/ConvertXS.xs      |    2 +-
 tp/Texinfo/XS/convert/convert_html.c    | 1123 ++++++++++++++++++-------------
 tp/Texinfo/XS/main/build_perl_info.c    |   72 +-
 tp/Texinfo/XS/main/build_perl_info.h    |    4 +-
 tp/Texinfo/XS/main/call_perl_function.c |  248 ++++++-
 tp/Texinfo/XS/main/get_perl_info.c      |   25 +-
 tp/Texinfo/XS/main/get_perl_info.h      |    3 +-
 tp/Texinfo/XS/main/tree_perl_api.h      |    8 +
 tp/Texinfo/XS/main/utils.c              |   10 +-
 tp/Texinfo/XS/main/utils.h              |   45 +-
 15 files changed, 1125 insertions(+), 504 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 2ba7aad2d8..a334127f59 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,58 @@
+2023-10-28  Patrice Dumas  <pertusus@free.fr>
+
+       * tp/Texinfo/Convert/HTML.pm (_convert_def_line_type): fix call of
+       Texinfo::Convert::Text::convert_to_text (in a code that is never run
+       in normal circumstances).
+
+       * tp/Texinfo/Convert/HTML.pm (converter_initialize): set non expanded
+       raw format commands to undef in 'commands_conversion' rather than not
+       setting the key in the hash, as the meaning is different, it means
+       ignoring the command, not that the command is not formatted.  For the
+       XS code it makes a difference.
+
+       * tp/Texinfo/Convert/HTML.pm (_translate_names, output): do not run
+       both perl and XS code as it will mess up the converter state.  Do not
+       call the XS code for now in output.
+
+       * tp/Texinfo/Convert/HTML.pm (_convert): unset
+       $self->{'current_root_command'} also when the command is not
+       converted.
+
+       * tp/Texinfo/Convert/Converter.pm (encode_converter_document)
+       tp/Texinfo/Convert/HTML.pm (converter_initialize),
+       tp/Texinfo/XS/convert/ConvertXS.xs (html_converter_initialize_sv),
+       tp/Texinfo/XS/main/get_perl_info.c (html_converter_initialize_sv),
+       tp/Texinfo/XS/main/utils.h (CONVERTER): pass output_units_conversion
+       to XS.
+
+       * tp/Texinfo/Convert/Text.pm (convert_to_text): confess if $options is
+       not a ref.
+
+       * tp/Texinfo/XS/main/utils.h (HTML_ARG_FORMATTED)
+       (HTML_ARGS_FORMATTED, enum argument_formatting_type)
+       (HTML_ARGUMENTS_FORMATTED_FORMAT_TYPE):
+       rename from ARG_FORMATTED and ARGS_FORMATTED, move from
+       tp/Texinfo/XS/convert/convert_html.c and add
+       HTML_ARGUMENTS_FORMATTED_FORMAT_TYPE.
+
+       * tp/Texinfo/XS/convert/convert_html.c (command_conversion)
+       (command_open, convert_tree, convert_tree_new_formatting_context)
+       (reset_unset_no_arg_commands_formatting_context)
+       (destroy_args_formatted, convert_to_html_internal)
+       (output_unit_conversion, convert_output_unit),
+       tp/Texinfo/XS/main/build_perl_info.c (build_html_formatting_state)
+       (build_html_command_formatted_args),
+       tp/Texinfo/XS/main/call_perl_function.c (call_commands_conversion)
+       (call_commands_open, call_output_units_conversion)
+       (call_types_conversion, call_types_open), tp/Texinfo/XS/main/utils.h
+       (CONVERTER), tp/Texinfo/XS/main/utils.c
+       (html_argument_formatting_type_names): call output units conversion,
+       command opening and conversion.  Progress in completeness of
+       conversion.  Add self->modified_state to mark that the formatting
+       state has to be rebuilt and self->tree_to_build if a tree need to be
+       built as perl, in general when it comes from a translated string.
+       Pass formatted_args to perl, pass multiple_pass formatting state.
+
 2023-10-27  Gavin Smith <gavinsmith0123@gmail.com>
 
        * tp/Texinfo/XS/main/build_perl_info.c (build_perl_array):
diff --git a/tp/TODO b/tp/TODO
index 972e417914..50e4332a9a 100644
--- a/tp/TODO
+++ b/tp/TODO
@@ -31,6 +31,11 @@ Document that Texinfo::Structuring::rebuild_document or
 Texinfo::Structuring::rebuild_tree should be called after tree modifications
 if the parser is XS but converters are perl.
 
+More fine grained determination of what needs to be rebuilt in converter,
+mostly for document and formatting state instead of one indicator
+self->modified_state, could imagine giving the index of the document context
+that needs to be redone or done, or even more fine grained.
+
 the code in _parsed_manual_tree in Pod-Simple-Texinfo/pod2texi.pl
 does not work perfectly with XS.  See FIXME in the code.  Tested in
 ./manual_tests/manual_sectioning_gap_test.sh
diff --git a/tp/Texinfo/Convert/Converter.pm b/tp/Texinfo/Convert/Converter.pm
index 7991632f4f..59e53a960e 100644
--- a/tp/Texinfo/Convert/Converter.pm
+++ b/tp/Texinfo/Convert/Converter.pm
@@ -444,7 +444,7 @@ sub encode_converter_document($)
 
   foreach my $variable ('style_commands_formatting', 'formatting_function',
      'types_open', 'types_conversion', 'commands_open', 'commands_conversion',
-     'code_types', 'pre_class_types') {
+     'output_units_conversion', 'code_types', 'pre_class_types') {
     if ($self->{$variable}) {
       $result->{$variable} = $self->{$variable};
     }
diff --git a/tp/Texinfo/Convert/HTML.pm b/tp/Texinfo/Convert/HTML.pm
index bdd495e48d..47ea8158a6 100644
--- a/tp/Texinfo/Convert/HTML.pm
+++ b/tp/Texinfo/Convert/HTML.pm
@@ -2332,6 +2332,7 @@ sub _translate_names($;$)
                 'conf' => $encoded_conf,
                };
     _XS_translate_names($encoded_converter);
+    return;
   }
 
   print STDERR "\nTRANSLATE_NAMES encoding_name: "
@@ -6983,7 +6984,7 @@ sub _convert_def_line_type($$$$)
     # should probably never happen
     return &{$self->formatting_function('format_protect_text')}($self,
      Texinfo::Convert::Text::convert_to_text(
-      $element, Texinfo::Convert::Text::copy_options_for_convert_text($self)));
+      $element, 
{Texinfo::Convert::Text::copy_options_for_convert_text($self)}));
   }
 
   my $index_label = '';
@@ -7528,7 +7529,7 @@ sub _default_format_element_footer($$$$;$)
 # is not done within the document formatting flow, but the formatted
 # output may still end up in the document.  In particular for
 # command_text() which caches its computations.
-sub _new_document_context($;$$)
+sub _new_document_context($;$$$)
 {
   my $self = shift;
   my $context = shift;
@@ -7648,7 +7649,7 @@ sub 
_reset_unset_no_arg_commands_formatting_context($$$$;$)
     } elsif ($reset_context eq 'preformatted') {
       # there does not seems to be anything simpler...
       my $preformatted_command_name = 'example';
-      $self->_new_document_context();
+      $self->_new_document_context("Translate $cmdname");
       push @{$self->{'document_context'}->[-1]->{'composition_context'}},
           $preformatted_command_name;
       # should not be needed for at commands no brace translation strings
@@ -7967,7 +7968,7 @@ my %special_characters = (
   'non_breaking_space' => [undef, '00A0'],
 );
 
-sub _XS_converter_initialize($$$$$$$)
+sub _XS_converter_initialize($$$$$$$$)
 {
 }
 
@@ -8188,6 +8189,7 @@ sub converter_initialize($)
         $self->{'commands_conversion'}->{$command} = undef;
       } elsif ($format_raw_commands{$command}
                and !$self->{'expanded_formats_hash'}->{$command}) {
+        $self->{'commands_conversion'}->{$command} = undef;
       } elsif (exists($default_commands_conversion{$command})) {
         $self->{'commands_conversion'}->{$command}
            = $default_commands_conversion{$command};
@@ -8423,7 +8425,8 @@ sub converter_initialize($)
                              \%default_commands_open,
                              \%default_commands_conversion,
                              \%default_types_open,
-                             \%default_types_conversion);
+                             \%default_types_conversion,
+                             \%default_output_units_conversion);
   }
 
   return $self;
@@ -11158,9 +11161,7 @@ sub convert_output_unit($$;$)
   if (exists ($self->{'output_units_conversion'}->{$unit_type_name})
       and !defined($self->{'output_units_conversion'}->{$unit_type_name})) {
     if ($debug) {
-      my $string = 'IGNORED';
-      $string .= " $unit_type_name" if ($unit_type_name);
-      print STDERR "$string\n";
+      print STDERR "IGNORED OU $unit_type_name\n";
     }
     return '';
   }
@@ -11468,7 +11469,7 @@ sub output($$)
     = $self->_prepare_conversion_units($root, $document_name);
 
   # setup untranslated strings
-  $self->_translate_names(1);
+  $self->_translate_names();
 
   my %files_source_info
     = $self->_prepare_units_directions_files($output_units, $special_units,
@@ -11491,7 +11492,7 @@ sub output($$)
   my $preamble_document_language = $self->get_conf('documentlanguage');
 
   if ($default_document_language ne $preamble_document_language) {
-    $self->_translate_names(1);
+    $self->_translate_names();
   }
 
   # prepare title.  fulltitle uses more possibility than simpletitle for
@@ -12328,6 +12329,9 @@ sub _convert($$;$)
     } else {
       print STDERR "Command not converted: $command_name\n"
        if ($self->get_conf('VERBOSE') or $self->get_conf('DEBUG'));
+      if ($root_commands{$command_name}) {
+        delete $self->{'current_root_command'};
+      }
       return '';
     }
     if ($root_commands{$command_name}) {
diff --git a/tp/Texinfo/Convert/Text.pm b/tp/Texinfo/Convert/Text.pm
index 7ebdadfb0a..47cadc141a 100644
--- a/tp/Texinfo/Convert/Text.pm
+++ b/tp/Texinfo/Convert/Text.pm
@@ -480,6 +480,9 @@ sub convert_to_text($;$)
   # reference.
   $options = {} if (!defined($options));
   if (defined($options)) {
+    if (!ref($options)) {
+      confess("convert_to_text options not a ref\n");
+    }
     bless $options;
     if ($options->{'code'}) {
       $options->{'_code_state'} = 1;
diff --git a/tp/Texinfo/XS/convert/ConvertXS.xs 
b/tp/Texinfo/XS/convert/ConvertXS.xs
index 4e48266050..9bd182c8b5 100644
--- a/tp/Texinfo/XS/convert/ConvertXS.xs
+++ b/tp/Texinfo/XS/convert/ConvertXS.xs
@@ -94,7 +94,7 @@ text_convert_tree (text_options_in, tree_in, unused=0)
         RETVAL
 
 int
-html_converter_initialize_sv (SV *converter_in, SV 
*default_formatting_references, SV *default_css_string_formatting_references, 
SV *default_commands_open, SV *default_commands_conversion, SV 
*default_types_open, SV *default_types_conversion)
+html_converter_initialize_sv (SV *converter_in, SV 
*default_formatting_references, SV *default_css_string_formatting_references, 
SV *default_commands_open, SV *default_commands_conversion, SV 
*default_types_open, SV *default_types_conversion, SV* 
default_output_units_conversion)
 
 void
 html_initialize_output_state (SV *converter_in)
diff --git a/tp/Texinfo/XS/convert/convert_html.c 
b/tp/Texinfo/XS/convert/convert_html.c
index b2d0e4876f..868d4f8996 100644
--- a/tp/Texinfo/XS/convert/convert_html.c
+++ b/tp/Texinfo/XS/convert/convert_html.c
@@ -43,28 +43,6 @@ typedef struct ROOT_AND_UNIT {
     ELEMENT *root;
 } ROOT_AND_UNIT;
 
-enum argument_formatting_type {
-  AFT_type_none,
-  AFT_type_normal,
-  AFT_type_string,
-  AFT_type_monospace,
-  AFT_type_monospacetext,
-  AFT_type_monospacestring,
-  AFT_type_filenametext,
-  AFT_type_url,
-  AFT_type_raw,
-};
-
-typedef struct ARG_FORMATTED {
-    ELEMENT *tree;
-    char *formatted[AFT_type_raw+1];
-} ARG_FORMATTED;
-
-typedef struct ARGS_FORMATTED {
-    size_t number;
-    ARG_FORMATTED *args;
-} ARGS_FORMATTED;
-
 /* unused */
 #define F_AFT_none              0x0001
 
@@ -303,240 +281,6 @@ special_unit_variety_direction_index (CONVERTER *self,
   return -1;
 }
 
-/* FIXME conversion need to be added */
-static void
-reset_unset_no_arg_commands_formatting_context (CONVERTER *self,
-                   enum command_id cmd, int reset_context, int ref_context,
-                   int translate)
-{
-  HTML_COMMAND_CONVERSION *no_arg_command_context;
-  HTML_COMMAND_CONVERSION **conversion_contexts
-    = self->html_command_conversion[cmd];
-  /* should never happen as unset is set at configuration */
-  if (!conversion_contexts[reset_context])
-    {
-      conversion_contexts[reset_context] =
-        (HTML_COMMAND_CONVERSION *) malloc (sizeof (HTML_COMMAND_CONVERSION));
-      memset (conversion_contexts[reset_context], 0,
-              sizeof (HTML_COMMAND_CONVERSION));
-
-      conversion_contexts[reset_context]->unset = 1;
-    }
-  no_arg_command_context = conversion_contexts[reset_context];
-  if (ref_context >= 0)
-    {
-      if (no_arg_command_context->unset)
-        {
-          HTML_COMMAND_CONVERSION *no_arg_ref
-            = conversion_contexts[ref_context];
-
-          /* TODO memory leaks possible for the other char * fields */
-
-          if (no_arg_ref->text)
-            no_arg_command_context->text = no_arg_ref->text;
-          if (no_arg_ref->tree)
-            no_arg_command_context->tree = no_arg_ref->tree;
-          if (no_arg_ref->translated_converted)
-            {
-              free (no_arg_command_context->translated_converted);
-              no_arg_command_context->translated_converted
-                = strdup (no_arg_ref->translated_converted);
-            }
-          if (no_arg_ref->translated_to_convert)
-            no_arg_command_context->translated_to_convert
-              = no_arg_ref->translated_to_convert;
-        }
-    }
-
-  if (translate
-      && no_arg_command_context->tree
-      && !no_arg_command_context->translated_converted)
-    {
-      char *translation_result = 0;
-      ELEMENT *translated_tree = no_arg_command_context->tree;
-      if (reset_context == HCC_type_normal)
-        {
-          char *explanation;
-          xasprintf (&explanation, "no arg %s translated",
-                     builtin_command_data[cmd].cmdname);
-           /*
-          translation_result = convert_tree (self, explanation);
-            */
-          free (explanation);
-        }
-      else if (reset_context == HCC_type_preformatted)
-        {
-          /*
-      # there does not seems to be anything simpler...
-      my $preformatted_command_name = 'example';
-      $self->_new_document_context();
-      push @{$self->{'document_context'}->[-1]->{'composition_context'}},
-          $preformatted_command_name;
-      # should not be needed for at commands no brace translation strings
-      push @{$self->{'document_context'}->[-1]->{'preformatted_classes'}},
-          $pre_class_commands{$preformatted_command_name};
-      $translation_result
-        = $self->convert_tree($translated_tree, "no arg $cmdname translated");
-      # only pop the main context
-      $self->_pop_document_context();
-           */
-        }
-      else if (reset_context == HCC_type_string)
-        {
-          /*
-      $translation_result
-        = $self->convert_tree_new_formatting_context({'type' => '_string',
-                                          'contents' => [$translated_tree]},
-                     'translated_string', "string no arg $cmdname translated");
-           */
-        }
-      else if (reset_context == HCC_type_css_string)
-        {
-           /*
-          translation_result = html_convert_css_string (self, translated_tree);
-            */
-        }
-      if (no_arg_command_context->text)
-        free (no_arg_command_context->text);
-      no_arg_command_context->text = translation_result;
-    }
-}
-
-static void
-complete_no_arg_commands_formatting (CONVERTER *self, enum command_id cmd,
-                                     int translate)
-{
-  reset_unset_no_arg_commands_formatting_context (self, cmd, HCC_type_normal,
-                                                  -1, translate);
-  reset_unset_no_arg_commands_formatting_context (self, cmd,
-                                                  HCC_type_preformatted,
-                                                  HCC_type_normal, translate);
-  reset_unset_no_arg_commands_formatting_context (self, cmd, HCC_type_string,
-                                                  HCC_type_preformatted, 
translate);
-  reset_unset_no_arg_commands_formatting_context (self, cmd, 
HCC_type_css_string,
-                                                  HCC_type_string, translate);
-}
-
-void
-html_translate_names (CONVERTER *self)
-{
-  int j;
-  STRING_LIST *special_unit_varieties = self->special_unit_varieties;
-  if (self->conf->DEBUG > 0)
-    {
-      fprintf (stderr, "\nTRANSLATE_NAMES encoding_name: "
-               " documentlanguage: %s\n", self->conf->documentlanguage);
-    }
-
-  /* reset strings such that they are translated when needed. */
-  #define tds_type(name) self->directions_strings[TDS_type_ ## name] = 0;
-   TDS_TRANSLATED_TYPES_LIST
-  #undef tds_type
-
-  for (j = 0; translated_special_unit_info[j].tree_type >= 0; j++)
-    {
-      int i;
-      int tree_type = translated_special_unit_info[j].tree_type;
-      for (i = 0; i < special_unit_varieties->number; i++)
-        self->special_unit_info_tree[tree_type][i] = 0;
-    }
-
-  /* delete the tree and formatted results for special elements
-     such that they are redone with the new tree when needed. */
-  for (j = 0; j < special_unit_varieties->number; j++)
-    {
-      char *special_unit_variety = special_unit_varieties->list[j];
-      int special_unit_direction_index
-       = special_unit_variety_direction_index (self, special_unit_variety);
-      if (special_unit_direction_index >= 0)
-        {
-          OUTPUT_UNIT *special_unit
-           = self->global_units_directions[special_unit_direction_index];
-          if (special_unit)
-             {
-               ELEMENT *command = special_unit->unit_command;
-               if (command)
-                 {
-                   HTML_TARGET *target
-                     = find_element_target (self->html_targets, command);
-                   if (target)
-                     {
-                       target->tree = 0;
-                       target->string = 0;
-                       target->text = 0;
-                     }
-                 }
-             }
-        }
-    }
-
-  if (self->no_arg_formatted_cmd)
-    {
-      int translated_nr = 0;
-      /* this is overkill, but simpler */
-      enum command_id *translated_cmds = (enum command_id *)
-        malloc ((self->no_arg_formatted_cmd->number +1)
-                * sizeof (enum command_id));
-      memset (translated_cmds, 0, (self->no_arg_formatted_cmd->number +1)
-                * sizeof (enum command_id));
-
-      for (j = 0; j < self->no_arg_formatted_cmd->number; j++)
-        {
-          enum command_id cmd = self->no_arg_formatted_cmd->list[j];
-          int i;
-          int add_cmd = 0;
-          for (i = 0; i < HCC_type_css_string+1; i++)
-            {
-              HTML_COMMAND_CONVERSION *format_spec
-                = self->html_command_conversion[cmd][i];
-              if (format_spec->translated_converted
-                  && !format_spec->unset)
-                {
-                  add_cmd = 1;
-                  format_spec->text
-                   = gdt_string (format_spec->translated_converted, self->conf,
-                                 0, 0, 0);
-                }
-              else if (i == HCC_type_normal)
-                {
-                  ELEMENT *translated_tree = 0;
-                  if (format_spec->translated_to_convert)
-                    {/* FIXME use document associated to converter? */
-                      translated_tree =
-                         gdt_tree (format_spec->translated_to_convert,
-                                   0, self->conf, 0, 0, 0);
-                    }
-                  else
-                    translated_tree = translated_command_tree (self, cmd);
-
-                  if (translated_tree)
-                    {
-                      add_cmd = 1;
-
-                      format_spec->tree = translated_tree;
-                    }
-                }
-            }
-          if (add_cmd)
-            {
-              translated_cmds[translated_nr] = cmd;
-              translated_nr++;
-            }
-        }
-
-      for (j = 0; j < translated_nr; j++)
-        {
-          enum command_id cmd = translated_cmds[j];
-          complete_no_arg_commands_formatting (self, cmd, 1);
-        }
-
-      free (translated_cmds);
-    }
-
-  if (self->conf->DEBUG > 0)
-    fprintf (stderr, "END TRANSLATE_NAMES\n\n");
-}
-
 typedef struct CMD_VARIETY {
     enum command_id cmd;
     char *variety;
@@ -853,107 +597,21 @@ void register_pre_class_command (enum command_id cmd, 
enum command_id main_cmd)
   html_commands_data[cmd].flags |= HF_pre_class;
 }
 
-/* most of the initialization is done by html_converter_initialize_sv
-   in get_perl_info, the initialization that sdo not require information
-   from perl is done here */
-void
-html_converter_initialize (CONVERTER *self)
+static HTML_TARGET *
+add_element_target_to_list (HTML_TARGET_LIST *targets,
+                            ELEMENT *element, char *target)
 {
-  int i;
-  int nr_default_commands
-    = sizeof (default_commands_args) / sizeof (default_commands_args[0]);
-  int max_args = MAX_COMMAND_ARGS_NR;
-  for (i = 0; i < nr_default_commands; i++)
-    {
-      /* we file the status for specified commands, to distinguish them
-         but it is not actually used in the code, as we default to
-         normal for unspecified commands too */
-      enum command_id cmd = default_commands_args[i].cmd;
-      command_args_flags[cmd].status = 1;
-      memcpy (&command_args_flags[cmd].flags, &default_commands_args[i].flags,
-              max_args);
-    }
+  HTML_TARGET *element_target;
 
-  for (i = 0; small_block_associated_command[i][0]; i++)
+  if (targets->number == targets->space)
     {
-      enum command_id small_cmd = small_block_associated_command[i][0];
-      enum command_id cmd = small_block_associated_command[i][1];
-      register_pre_class_command (small_cmd, cmd);
+      targets->list = realloc (targets->list,
+                   sizeof (HTML_TARGET) * (targets->space += 5));
     }
-
-  for (i = 1; i < BUILTIN_CMD_NUMBER; i++)
-    {
-      if (builtin_command_data[i].flags & CF_block
-          || builtin_command_data[i].flags & CF_root)
-        register_format_context_command (i);
-
-      if (builtin_command_data[i].flags & CF_preformatted
-          || builtin_command_data[i].flags & CF_root)
-        html_commands_data[i].flags |= HF_composition_context;
-
-      if (builtin_command_data[i].flags & CF_block)
-        {
-          if (builtin_command_data[i].data == BLOCK_menu)
-            html_commands_data[i].flags |= HF_composition_context;
-          else if (builtin_command_data[i].data == BLOCK_format_raw)
-            html_commands_data[i].flags |= HF_format_raw;
-        }
-
-      if (builtin_command_data[i].flags & CF_preformatted)
-        {
-          if (!(html_commands_data[i].flags & HF_pre_class))
-            register_pre_class_command (i, 0);
-        }
-    }
-  register_pre_class_command (CM_verbatim, 0);
-  register_pre_class_command (CM_menu, 0);
-  for (i = 0; additional_format_context_cmd[i]; i++)
-    register_format_context_command (additional_format_context_cmd[i]);
-
-  for (i = 0; HTML_align_cmd[i]; i++)
-    html_commands_data[i].flags |= HF_HTML_align | HF_composition_context;
-
-  html_commands_data[CM_float].flags |= HF_composition_context;
-
-  html_commands_data[CM_sc].flags |= HF_upper_case;
-}
-
-void
-html_initialize_output_state (CONVERTER *self)
-{
-  int i;
-  /* targets and directions */
-
-  /* used for diverse elements: tree units, indices, footnotes, special
-    elements, contents elements... */
-  self->html_targets = (HTML_TARGET_LIST *) malloc (sizeof (HTML_TARGET_LIST));
-  self->seen_ids = (STRING_LIST *) malloc (sizeof (STRING_LIST));
-  memset (self->html_targets, 0, sizeof (HTML_TARGET_LIST));
-  memset (self->seen_ids, 0, sizeof (STRING_LIST));
-  for (i = 0; i < ST_footnote_location+1; i++)
-    {
-      self->html_special_targets[i]
-        = (HTML_TARGET_LIST *) malloc (sizeof (HTML_TARGET_LIST));
-      memset (self->html_special_targets[i], 0, sizeof (HTML_TARGET_LIST));
-    }
-
-}
-
-static HTML_TARGET *
-add_element_target_to_list (HTML_TARGET_LIST *targets,
-                            ELEMENT *element, char *target)
-{
-  HTML_TARGET *element_target;
-
-  if (targets->number == targets->space)
-    {
-      targets->list = realloc (targets->list,
-                   sizeof (HTML_TARGET) * (targets->space += 5));
-    }
-  element_target = &targets->list[targets->number];
-  memset (element_target, 0, sizeof (HTML_TARGET));
-  element_target->element = element;
-  element_target->target = target;
+  element_target = &targets->list[targets->number];
+  memset (element_target, 0, sizeof (HTML_TARGET));
+  element_target->element = element;
+  element_target->target = target;
 
   targets->number++;
   return element_target;
@@ -2372,6 +2030,33 @@ html_convert_init (CONVERTER *self)
   self->title_titlepage = title_titlepage;
 }
 
+static char *
+command_conversion (CONVERTER *self, enum command_id cmd,
+                    ELEMENT *element, HTML_ARGS_FORMATTED *args_formatted,
+                    char *content)
+{
+  /* TODO call a C function if status is FRS_status_default_set
+     maybe putting function references in an array */
+  /* FIXME XS specific debug message */
+  if (self->conf->DEBUG > 0)
+    fprintf (stderr, "DEBUG: command conversion %s '%s'\n",
+             builtin_command_data[cmd].cmdname, content);
+  if (self->commands_conversion[cmd].status > 0)
+    return call_commands_conversion (self, cmd, element,
+                                     args_formatted, content);
+  return 0;
+}
+
+static char *
+command_open (CONVERTER *self, enum command_id cmd, ELEMENT *element)
+{
+  /* TODO call a C function if status is FRS_status_default_set
+     maybe putting function references in an array */
+  if (self->commands_open[cmd].status > 0)
+    return call_commands_open (self, cmd, element);
+  return 0;
+}
+
 static char *
 type_conversion (CONVERTER *self, enum element_type type,
                  ELEMENT *element, char *content)
@@ -2409,104 +2094,539 @@ push_html_formatting_context 
(HTML_FORMATTING_CONTEXT_STACK *stack,
 
   stack->stack[stack->top].context_name = strdup (context_name);
 
-  stack->top++;
-}
+  stack->top++;
+}
+
+static HTML_FORMATTING_CONTEXT *
+top_html_formatting_context (HTML_FORMATTING_CONTEXT_STACK *stack)
+{
+  if (stack->top == 0)
+    fatal ("HTML formatting context stack empty for top");
+
+  return &stack->stack[stack->top - 1];
+}
+
+static void
+pop_html_formatting_context (HTML_FORMATTING_CONTEXT_STACK *stack)
+{
+  if (stack->top == 0)
+    fatal ("HTML formatting context stack empty");
+
+  free (stack->stack[stack->top - 1].context_name);
+  stack->top--;
+}
+
+static void
+html_new_document_context (CONVERTER *self,
+        char *context_name, char *document_global_context,
+        enum command_id block_command)
+{
+  HTML_DOCUMENT_CONTEXT_STACK *stack = &self->html_document_context;
+  if (stack->top >= stack->space)
+    {
+      stack->stack
+        = realloc (stack->stack,
+                   (stack->space += 5) * sizeof (HTML_DOCUMENT_CONTEXT));
+    }
+
+  memset (&stack->stack[stack->top], 0, sizeof (HTML_DOCUMENT_CONTEXT));
+  stack->stack[stack->top].context = strdup (context_name);
+  stack->stack[stack->top].document_global_context = document_global_context;
+
+  push_style_no_code (&stack->stack[stack->top].monospace_context);
+  push_command_or_type (&stack->stack[stack->top].composition_context,
+                        0, 0);
+  if (block_command)
+    push_command (&stack->stack[stack->top].block_commands, block_command);
+
+  if (document_global_context)
+    {
+      self->document_global_context++;
+      self->modified_state++;
+    }
+
+  push_html_formatting_context (&stack->stack[stack->top].formatting_context,
+                                context_name);
+
+  stack->top++;
+}
+
+static void
+html_pop_document_context (CONVERTER *self)
+{
+  HTML_DOCUMENT_CONTEXT_STACK *stack = &self->html_document_context;
+  HTML_DOCUMENT_CONTEXT *document_ctx;
+
+  if (stack->top == 0)
+    fatal ("HTML document context stack empty for pop");
+
+  document_ctx = &stack->stack[stack->top -1];
+
+  free (document_ctx->context);
+  free (document_ctx->monospace_context.stack);
+  free (document_ctx->composition_context.stack);
+  if (document_ctx->block_commands.top > 0)
+    pop_command (&document_ctx->block_commands);
+  free (document_ctx->block_commands.stack);
+  pop_html_formatting_context (&document_ctx->formatting_context);
+  free (document_ctx->formatting_context.stack);
+
+  if (document_ctx->document_global_context)
+    {
+      self->document_global_context--;
+      self->modified_state++;
+    }
+
+  stack->top--;
+}
+
+static HTML_DOCUMENT_CONTEXT *
+top_document_context (CONVERTER *self)
+{
+  HTML_DOCUMENT_CONTEXT_STACK *stack = &self->html_document_context;
+
+  if (stack->top == 0)
+    fatal ("HTML document context stack empty for top");
+
+  return &stack->stack[stack->top - 1];
+}
+
+/* most of the initialization is done by html_converter_initialize_sv
+   in get_perl_info, the initialization that do not require information
+   from perl is done here */
+void
+html_converter_initialize (CONVERTER *self)
+{
+  int i;
+  int nr_default_commands
+    = sizeof (default_commands_args) / sizeof (default_commands_args[0]);
+  int max_args = MAX_COMMAND_ARGS_NR;
+  for (i = 0; i < nr_default_commands; i++)
+    {
+      /* we file the status for specified commands, to distinguish them
+         but it is not actually used in the code, as we default to
+         normal for unspecified commands too */
+      enum command_id cmd = default_commands_args[i].cmd;
+      command_args_flags[cmd].status = 1;
+      memcpy (&command_args_flags[cmd].flags, &default_commands_args[i].flags,
+              max_args);
+    }
+
+  for (i = 0; small_block_associated_command[i][0]; i++)
+    {
+      enum command_id small_cmd = small_block_associated_command[i][0];
+      enum command_id cmd = small_block_associated_command[i][1];
+      register_pre_class_command (small_cmd, cmd);
+    }
+
+  for (i = 1; i < BUILTIN_CMD_NUMBER; i++)
+    {
+      if (builtin_command_data[i].flags & CF_block
+          || builtin_command_data[i].flags & CF_root)
+        register_format_context_command (i);
+
+      if (builtin_command_data[i].flags & CF_preformatted
+          || builtin_command_data[i].flags & CF_root)
+        html_commands_data[i].flags |= HF_composition_context;
+
+      if (builtin_command_data[i].flags & CF_block)
+        {
+          if (builtin_command_data[i].data == BLOCK_menu)
+            html_commands_data[i].flags |= HF_composition_context;
+          else if (builtin_command_data[i].data == BLOCK_format_raw)
+            html_commands_data[i].flags |= HF_format_raw;
+        }
+
+      if (builtin_command_data[i].flags & CF_preformatted)
+        {
+          if (!(html_commands_data[i].flags & HF_pre_class))
+            register_pre_class_command (i, 0);
+        }
+    }
+  register_pre_class_command (CM_verbatim, 0);
+  register_pre_class_command (CM_menu, 0);
+  for (i = 0; additional_format_context_cmd[i]; i++)
+    register_format_context_command (additional_format_context_cmd[i]);
+
+  for (i = 0; HTML_align_cmd[i]; i++)
+    html_commands_data[i].flags |= HF_HTML_align | HF_composition_context;
+
+  html_commands_data[CM_float].flags |= HF_composition_context;
+
+  html_commands_data[CM_sc].flags |= HF_upper_case;
+
+  html_new_document_context (self, "_toplevel_context", 0, 0);
+}
+
+void
+html_initialize_output_state (CONVERTER *self)
+{
+  int i;
+  /* targets and directions */
+
+  /* used for diverse elements: tree units, indices, footnotes, special
+    elements, contents elements... */
+  self->html_targets = (HTML_TARGET_LIST *) malloc (sizeof (HTML_TARGET_LIST));
+  self->seen_ids = (STRING_LIST *) malloc (sizeof (STRING_LIST));
+  memset (self->html_targets, 0, sizeof (HTML_TARGET_LIST));
+  memset (self->seen_ids, 0, sizeof (STRING_LIST));
+  for (i = 0; i < ST_footnote_location+1; i++)
+    {
+      self->html_special_targets[i]
+        = (HTML_TARGET_LIST *) malloc (sizeof (HTML_TARGET_LIST));
+      memset (self->html_special_targets[i], 0, sizeof (HTML_TARGET_LIST));
+    }
+}
+
+char *
+convert_tree (CONVERTER *self, ELEMENT *tree, char *explanation)
+{
+  TEXT result;
+  text_init (&result);
+
+  convert_to_html_internal (self, tree, &result, explanation);
+
+  return result.text;
+}
+
+/* This function should be used in formatting functions when some
+   Texinfo tree need to be converted. */
+char *
+convert_tree_new_formatting_context (CONVERTER *self, ELEMENT *tree,
+                              char *context_string, char *multiple_pass,
+                              char *document_global_context,
+                              enum command_id block_cmd)
+{
+  char *result;
+  char *multiple_pass_str = "";
+  char *explanation;
+  TEXT context_string_str;
+  text_init (&context_string_str);
+  text_append (&context_string_str, "");
+
+  if (context_string)
+    {
+      html_new_document_context (self, context_string,
+                                 document_global_context, block_cmd);
+      text_printf (&context_string_str, "C(%s)", context_string);
+    }
+
+  if (multiple_pass)
+    {
+      self->ignore_notice++;
+      push_string_stack_string (&self->multiple_pass, multiple_pass);
+      multiple_pass_str = "|M";
+    }
+
+  if (self->conf->DEBUG > 0)
+    fprintf (stderr, "new_fmt_ctx %s%s\n", context_string_str.text,
+                                           multiple_pass_str);
+
+  self->modified_state++;
+  xasprintf (&explanation, "new_fmt_ctx %s", context_string_str.text);
+  result = convert_tree (self, tree, explanation);
+
+  free (explanation);
+  free (context_string_str.text);
+
+  if (context_string)
+    html_pop_document_context (self);
+
+  if (multiple_pass)
+    {
+      self->ignore_notice++;
+      pop_string_stack (&self->multiple_pass);
+    }
+
+  self->modified_state++;
+
+  return result;
+}
+
+
+static void
+reset_unset_no_arg_commands_formatting_context (CONVERTER *self,
+                   enum command_id cmd, int reset_context, int ref_context,
+                   int translate)
+{
+  HTML_COMMAND_CONVERSION *no_arg_command_context;
+  HTML_COMMAND_CONVERSION **conversion_contexts
+    = self->html_command_conversion[cmd];
+  /* should never happen as unset is set at configuration */
+  if (!conversion_contexts[reset_context])
+    {
+      conversion_contexts[reset_context] =
+        (HTML_COMMAND_CONVERSION *) malloc (sizeof (HTML_COMMAND_CONVERSION));
+      memset (conversion_contexts[reset_context], 0,
+              sizeof (HTML_COMMAND_CONVERSION));
+
+      conversion_contexts[reset_context]->unset = 1;
+    }
+  no_arg_command_context = conversion_contexts[reset_context];
+  if (ref_context >= 0)
+    {
+      if (no_arg_command_context->unset)
+        {
+          HTML_COMMAND_CONVERSION *no_arg_ref
+            = conversion_contexts[ref_context];
+
+          /* TODO memory leaks possible for the other char * fields */
+
+          if (no_arg_ref->text)
+            no_arg_command_context->text = no_arg_ref->text;
+          if (no_arg_ref->tree)
+            no_arg_command_context->tree = no_arg_ref->tree;
+          if (no_arg_ref->translated_converted)
+            {
+              free (no_arg_command_context->translated_converted);
+              no_arg_command_context->translated_converted
+                = strdup (no_arg_ref->translated_converted);
+            }
+          if (no_arg_ref->translated_to_convert)
+            no_arg_command_context->translated_to_convert
+              = no_arg_ref->translated_to_convert;
+        }
+    }
+
+  if (translate
+      && no_arg_command_context->tree
+      && !no_arg_command_context->translated_converted)
+    {
+      char *translation_result = 0;
+      ELEMENT *translated_tree = no_arg_command_context->tree;
+      if (!translated_tree->hv)
+        {/* FIXME Should be done differently if it is possible
+           it be possible to recursively call html_translate_names. */
+          self->tree_to_build = translated_tree;
+        }
+      if (reset_context == HCC_type_normal)
+        {
+          char *explanation;
+          xasprintf (&explanation, "no arg %s translated",
+                     builtin_command_data[cmd].cmdname);
+          translation_result = convert_tree (self, translated_tree, 
explanation);
+          free (explanation);
+        }
+      else if (reset_context == HCC_type_preformatted)
+        {
+          char *context_name;
+          enum command_id preformated_cmd = CM_example;
+          HTML_DOCUMENT_CONTEXT *top_document_ctx;
+          char *explanation;
+          xasprintf (&context_name, "Translate %s",
+                     builtin_command_data[cmd].cmdname);
+          html_new_document_context (self, context_name, 0, 0);
+          free (context_name);
+
+          top_document_ctx = top_document_context (self);
+
+          /* there does not seems to be anything simpler... */
+          push_command_or_type (&top_document_ctx->composition_context,
+                                preformated_cmd, 0);
+      /* should not be needed for at commands no brace translation strings */
+          push_string_stack_string (&top_document_ctx->preformatted_classes,
+                              html_commands_data[preformated_cmd].pre_class);
+          self->modified_state++;
+
+          xasprintf (&explanation, "no arg %s translated",
+                     builtin_command_data[cmd].cmdname);
+          translation_result = convert_tree (self, translated_tree,
+                                             explanation);
+          free (explanation);
+          pop_command_or_type (&top_document_ctx->composition_context);
+          pop_string_stack (&top_document_ctx->preformatted_classes);
+          html_pop_document_context (self);
+          self->modified_state++;
+        }
+      else if (reset_context == HCC_type_string)
+        {
+          char *context_name;
+          HTML_DOCUMENT_CONTEXT *top_document_ctx;
+
+          xasprintf (&context_name, "string no arg %s translated",
+                     builtin_command_data[cmd].cmdname);
+          html_new_document_context (self, context_name, 0, 0);
 
-static HTML_FORMATTING_CONTEXT *
-top_html_formatting_context (HTML_FORMATTING_CONTEXT_STACK *stack)
-{
-  if (stack->top == 0)
-    fatal ("HTML formatting context stack empty for top");
+          top_document_ctx = top_document_context (self);
+          top_document_ctx->string_ctx++;
 
-  return &stack->stack[stack->top - 1];
+          self->modified_state++;
+          translation_result = convert_tree (self, translated_tree,
+                                             context_name);
+          free (context_name);
+          html_pop_document_context (self);
+          self->modified_state++;
+        }
+      else if (reset_context == HCC_type_css_string)
+        {
+           /*
+          translation_result = html_convert_css_string (self, translated_tree);
+            */
+        }
+      if (no_arg_command_context->text)
+        free (no_arg_command_context->text);
+      no_arg_command_context->text = translation_result;
+      self->tree_to_build = 0;
+    }
 }
 
 static void
-pop_html_formatting_context (HTML_FORMATTING_CONTEXT_STACK *stack)
+complete_no_arg_commands_formatting (CONVERTER *self, enum command_id cmd,
+                                     int translate)
 {
-  if (stack->top == 0)
-    fatal ("HTML formatting context stack empty");
-
-  free (stack->stack[stack->top - 1].context_name);
-  stack->top--;
+  reset_unset_no_arg_commands_formatting_context (self, cmd, HCC_type_normal,
+                                                  -1, translate);
+  reset_unset_no_arg_commands_formatting_context (self, cmd,
+                                                  HCC_type_preformatted,
+                                                  HCC_type_normal, translate);
+  reset_unset_no_arg_commands_formatting_context (self, cmd, HCC_type_string,
+                                                  HCC_type_preformatted, 
translate);
+  reset_unset_no_arg_commands_formatting_context (self, cmd, 
HCC_type_css_string,
+                                                  HCC_type_string, translate);
 }
 
-static void
-html_new_document_context (CONVERTER *self,
-        char *context_name, int document_global_context,
-        enum command_id block_command)
+void
+html_translate_names (CONVERTER *self)
 {
-  HTML_DOCUMENT_CONTEXT_STACK *stack = &self->html_document_context;
-  if (stack->top >= stack->space)
+  int j;
+  STRING_LIST *special_unit_varieties = self->special_unit_varieties;
+  if (self->conf->DEBUG > 0)
     {
-      stack->stack
-        = realloc (stack->stack,
-                   (stack->space += 5) * sizeof (HTML_DOCUMENT_CONTEXT));
+      fprintf (stderr, "\nTRANSLATE_NAMES encoding_name: "
+               " documentlanguage: %s\n", self->conf->documentlanguage);
     }
 
-  memset (&stack->stack[stack->top], 0, sizeof (HTML_DOCUMENT_CONTEXT));
-  stack->stack[stack->top].context = strdup (context_name);
-  stack->stack[stack->top].document_global_context = document_global_context;
-
-  push_style_no_code (&stack->stack[stack->top].monospace_context);
-  push_command_or_type (&stack->stack[stack->top].composition_context,
-                        0, 0);
-  if (block_command)
-    push_command (&stack->stack[stack->top].block_commands, block_command);
+  /* reset strings such that they are translated when needed. */
+  #define tds_type(name) self->directions_strings[TDS_type_ ## name] = 0;
+   TDS_TRANSLATED_TYPES_LIST
+  #undef tds_type
 
-  if (document_global_context)
+  for (j = 0; translated_special_unit_info[j].tree_type >= 0; j++)
     {
-      self->document_global_context++;
-      self->modified_state++;
+      int i;
+      int tree_type = translated_special_unit_info[j].tree_type;
+      for (i = 0; i < special_unit_varieties->number; i++)
+        self->special_unit_info_tree[tree_type][i] = 0;
     }
 
-  push_html_formatting_context (&stack->stack[stack->top].formatting_context,
-                                context_name);
+  /* delete the tree and formatted results for special elements
+     such that they are redone with the new tree when needed. */
+  for (j = 0; j < special_unit_varieties->number; j++)
+    {
+      char *special_unit_variety = special_unit_varieties->list[j];
+      int special_unit_direction_index
+       = special_unit_variety_direction_index (self, special_unit_variety);
+      if (special_unit_direction_index >= 0)
+        {
+          OUTPUT_UNIT *special_unit
+           = self->global_units_directions[special_unit_direction_index];
+          if (special_unit)
+             {
+               ELEMENT *command = special_unit->unit_command;
+               if (command)
+                 {
+                   HTML_TARGET *target
+                     = find_element_target (self->html_targets, command);
+                   if (target)
+                     {
+                       target->tree = 0;
+                       target->string = 0;
+                       target->text = 0;
+                     }
+                 }
+             }
+        }
+    }
 
-  stack->top++;
-}
+  if (self->no_arg_formatted_cmd)
+    {
+      int translated_nr = 0;
+      /* this is overkill, but simpler */
+      enum command_id *translated_cmds = (enum command_id *)
+        malloc ((self->no_arg_formatted_cmd->number +1)
+                * sizeof (enum command_id));
+      memset (translated_cmds, 0, (self->no_arg_formatted_cmd->number +1)
+                * sizeof (enum command_id));
 
-static void
-html_pop_document_context (CONVERTER *self)
-{
-  HTML_DOCUMENT_CONTEXT_STACK *stack = &self->html_document_context;
-  HTML_DOCUMENT_CONTEXT *document_ctx;
+      for (j = 0; j < self->no_arg_formatted_cmd->number; j++)
+        {
+          enum command_id cmd = self->no_arg_formatted_cmd->list[j];
+          int i;
+          int add_cmd = 0;
+          for (i = 0; i < HCC_type_css_string+1; i++)
+            {
+              HTML_COMMAND_CONVERSION *format_spec
+                = self->html_command_conversion[cmd][i];
+              if (format_spec->translated_converted
+                  && !format_spec->unset)
+                {
+                  add_cmd = 1;
+                  format_spec->text
+                   = gdt_string (format_spec->translated_converted, self->conf,
+                                 0, 0, 0);
+                }
+              else if (i == HCC_type_normal)
+                {
+                  ELEMENT *translated_tree = 0;
+                  if (format_spec->translated_to_convert)
+                    {/* FIXME use document associated to converter? */
+                      translated_tree =
+                         gdt_tree (format_spec->translated_to_convert,
+                                   0, self->conf, 0, 0, 0);
+                    }
+                  else
+                    translated_tree = translated_command_tree (self, cmd);
 
-  if (stack->top == 0)
-    fatal ("HTML document context stack empty for pop");
+                  if (translated_tree)
+                    {
+                      add_cmd = 1;
 
-  document_ctx = &stack->stack[stack->top -1];
+                      format_spec->tree = translated_tree;
+                    }
+                }
+            }
+          if (add_cmd)
+            {
+              translated_cmds[translated_nr] = cmd;
+              translated_nr++;
+            }
+        }
 
-  free (document_ctx->context);
-  free (document_ctx->monospace_context.stack);
-  free (document_ctx->composition_context.stack);
-  if (document_ctx->block_commands.top > 0)
-    pop_command (&document_ctx->block_commands);
-  free (document_ctx->block_commands.stack);
-  pop_html_formatting_context (&document_ctx->formatting_context);
-  free (document_ctx->formatting_context.stack);
+      for (j = 0; j < translated_nr; j++)
+        {
+          enum command_id cmd = translated_cmds[j];
+          complete_no_arg_commands_formatting (self, cmd, 1);
+        }
 
-  if (document_ctx->document_global_context)
-    {
-      self->document_global_context--;
-      self->modified_state++;
+      free (translated_cmds);
     }
 
-  stack->top--;
+  if (self->conf->DEBUG > 0)
+    fprintf (stderr, "END TRANSLATE_NAMES\n\n");
 }
 
-static HTML_DOCUMENT_CONTEXT *
-top_document_context (CONVERTER *self)
-{
-  HTML_DOCUMENT_CONTEXT_STACK *stack = &self->html_document_context;
-
-  if (stack->top == 0)
-    fatal ("HTML document context stack empty for top");
 
-  return &stack->stack[stack->top - 1];
+void
+destroy_args_formatted (HTML_ARGS_FORMATTED *args_formatted)
+{
+  if (args_formatted)
+    {
+      int i;
+      for (i = 0; i < args_formatted->number; i++)
+        {
+          int j;
+          HTML_ARG_FORMATTED *arg_formatted = &args_formatted->args[i];
+          if (arg_formatted->tree)
+            {
+              for (j = 0; j < AFT_type_raw+1; j++)
+                free (arg_formatted->formatted[j]);
+            }
+        }
+      free (args_formatted->args);
+    }
+  free (args_formatted);
 }
 
-
 #define ADD(x) text_append (result, x)
 
 /* EXPLANATION is used for debugging */
@@ -2529,15 +2649,31 @@ convert_to_html_internal (CONVERTER *self, ELEMENT 
*element,
 
   if (self->conf->DEBUG > 0)
     {
+      int i;
       TEXT debug_str;
+      TEXT contexts_str;
       text_init (&debug_str);
-     /* TODO
-         my @contexts_names = map {defined($_->{'context_name'})
-                                 ? $_->{'context_name'}: 'UNDEF'}
-         @{$self->{'document_context'}->[-1]->{'formatting_context'}};
-    print STDERR "ELEMENT($explanation) (".join('|',@contexts_names)."), ->";
-       */
-      text_printf (&debug_str, "ELEMENT(%s) (), ->", explanation);
+      text_init (&contexts_str);
+      HTML_DOCUMENT_CONTEXT *top_document_ctx = top_document_context (self);
+      HTML_FORMATTING_CONTEXT_STACK *formatting_context_stack
+        = &top_document_ctx->formatting_context;
+
+      for (i = 0; i < formatting_context_stack->top; i++)
+        {
+          HTML_FORMATTING_CONTEXT *formatting_context
+           = &formatting_context_stack->stack[i];
+          if (i != 0)
+            text_append (&contexts_str, "|");
+          if (formatting_context->context_name)
+            text_append (&contexts_str, formatting_context->context_name);
+          else
+            text_append (&contexts_str, "UNDEF");
+
+        }
+      text_printf (&debug_str, "XS|ELEMENT(%s) %p (%s), ->", explanation,
+                                        &self->commands_conversion,
+                                                       contexts_str.text);
+      free (contexts_str.text);
       if (command_name)
         text_printf (&debug_str, " cmd: %s,", command_name);
       if (element->type)
@@ -2575,6 +2711,7 @@ convert_to_html_internal (CONVERTER *self, ELEMENT 
*element,
       TEXT text_result;
       text_init (&text_result);
       text_append (&text_result, "");
+
       /* already converted to html, keep it as is, assume it cannot be NULL */
       if (element->type == ET__converted)
         text_append (&text_result, element->text.text);
@@ -2615,6 +2752,11 @@ convert_to_html_internal (CONVERTER *self, ELEMENT 
*element,
           && element->type != ET_index_entry_command))
     {
       enum command_id data_cmd = element_builtin_data_cmd (element);
+      /* FIXME XS only debug message */
+      if (self->conf->DEBUG > 0)
+        fprintf (stderr, "COMMAND: %s %s\n",
+                 builtin_command_data[data_cmd].cmdname,
+                 builtin_command_data[cmd].cmdname);
 
       if (builtin_command_data[data_cmd].flags & CF_root)
         {
@@ -2625,7 +2767,7 @@ convert_to_html_internal (CONVERTER *self, ELEMENT 
*element,
       if (self->commands_conversion[cmd].status)
         {
           int convert_to_latex = 0;
-          ARGS_FORMATTED *args_formatted = 0;
+          HTML_ARGS_FORMATTED *args_formatted = 0;
           TEXT content_formatted;
 
           HTML_DOCUMENT_CONTEXT *top_document_ctx;
@@ -2719,17 +2861,21 @@ convert_to_html_internal (CONVERTER *self, ELEMENT 
*element,
               self->modified_state++;
             }
 
-          /*
-      my $result = '';
-      if (defined($self->{'commands_open'}->{$command_name})) {
-        $result .= &{$self->{'commands_open'}->{$command_name}}($self,
-                                                 $command_name, $element);
-      }
-           */
+          if (self->commands_open[cmd].status)
+            {
+              char *cmd_open_str = command_open (self, data_cmd, element);
+              if (cmd_open_str)
+                {
+                  ADD(cmd_open_str);
+                  free (cmd_open_str);
+                }
+            }
+
+          text_init (&content_formatted);
+          text_append (&content_formatted, "");
 
           if (element->contents.number > 0)
             {
-              text_init (&content_formatted);
 
               if (convert_to_latex)
                 {
@@ -2758,6 +2904,9 @@ convert_to_html_internal (CONVERTER *self, ELEMENT 
*element,
                     }
                 }
             }
+          /* FIXME XS only debug message */
+          if (self->conf->DEBUG > 0)
+            fprintf (stderr, "CM CONTENTS: '%s'\n", content_formatted.text);
 
           if ((builtin_command_data[data_cmd].flags & CF_brace)
               || (builtin_command_data[data_cmd].flags & CF_line
@@ -2775,25 +2924,27 @@ convert_to_html_internal (CONVERTER *self, ELEMENT 
*element,
 
                   text_init (&formatted_arg);
 
-                  args_formatted = (ARGS_FORMATTED *)
-                    malloc (sizeof (ARGS_FORMATTED));
+                  args_formatted = (HTML_ARGS_FORMATTED *)
+                    malloc (sizeof (HTML_ARGS_FORMATTED));
                   args_formatted->number = element->args.number;
-                  args_formatted->args = (ARG_FORMATTED *)
-                    malloc (args_formatted->number * sizeof (ARG_FORMATTED));
+                  args_formatted->args = (HTML_ARG_FORMATTED *)
+                 malloc (args_formatted->number * sizeof (HTML_ARG_FORMATTED));
+                  memset (args_formatted->args, 0,
+                        args_formatted->number * sizeof (HTML_ARG_FORMATTED));
 
-                  /* */
                   for (arg_idx = 0; arg_idx < element->args.number; arg_idx++)
                     {
-                      ELEMENT *arg = element->args.list[arg_idx];
                       char *explanation;
-                      /* */
+                      ELEMENT *arg = element->args.list[arg_idx];
+                      HTML_ARG_FORMATTED *arg_formatted
+                         = &args_formatted->args[arg_idx];
+
                       if (arg->contents.number <= 0)
                         /*
                  # special case for @value argument
                 and !defined($arg->{'text'}))
                          */
                         {
-                          /* */
                           continue;
                         }
                       int arg_flags = 0;
@@ -2805,9 +2956,6 @@ convert_to_html_internal (CONVERTER *self, ELEMENT 
*element,
                       else
                         arg_flags = F_AFT_normal;
 
-                      ARG_FORMATTED *arg_formatted
-                         = &args_formatted->args[arg_idx];
-
                       arg_formatted->tree = arg;
 
                       if (arg_flags & F_AFT_normal)
@@ -2898,6 +3046,8 @@ convert_to_html_internal (CONVERTER *self, ELEMENT 
*element,
                          {'code' => 1,
                  
Texinfo::Convert::Text::copy_options_for_convert_text($self)});
                         */
+                          arg_formatted->formatted[AFT_type_monospacetext]
+                            = strdup ("");
                         }
                       if (arg_flags & F_AFT_filenametext)
                         {
@@ -2908,8 +3058,10 @@ convert_to_html_internal (CONVERTER *self, ELEMENT 
*element,
                          {'code' => 1,
                Texinfo::Convert::Text::copy_options_for_convert_text($self, 
1)});
                         */
+                          arg_formatted->formatted[AFT_type_filenametext]
+                            = strdup ("");
                         }
-                      if (arg_flags & F_AFT_filenametext)
+                      if (arg_flags & F_AFT_url)
                         {
                          /*
                 # set the encoding to UTF-8 to always have a string that is 
suitable
@@ -2921,9 +3073,12 @@ convert_to_html_internal (CONVERTER *self, ELEMENT 
*element,
                    = Texinfo::Convert::Text::convert_to_text($arg,
                                                    $text_conversion_options);
                          */
+                          arg_formatted->formatted[AFT_type_url]
+                            = strdup ("");
                         }
                       if (arg_flags & F_AFT_raw)
                         {
+                          text_reset (&formatted_arg);
                           top_document_ctx->raw_ctx++;
                           self->modified_state++;
                           xasprintf (&explanation, "%s A[%d]raw",
@@ -3025,10 +3180,14 @@ convert_to_html_internal (CONVERTER *self, ELEMENT 
*element,
           /* args are formatted, now format the command itself */
           if (self->commands_conversion[cmd].status)
             {
-              /*
-          $result .= &{$self->{'commands_conversion'}->{$command_name}}($self,
-                  $command_name, $element, $args_formatted, 
$content_formatted);
-               */
+              char *conv_str = command_conversion (self, cmd,
+                                                   element, args_formatted,
+                                                   content_formatted.text);
+              if (conv_str)
+                {
+                  ADD(conv_str);
+                  free (conv_str);
+                }
             }
           else if (args_formatted)
             fprintf (stderr, "No command_conversion for %s\n",
@@ -3037,12 +3196,19 @@ convert_to_html_internal (CONVERTER *self, ELEMENT 
*element,
           if (cmd == CM_documentlanguage)
             html_translate_names (self);
 
+          free (content_formatted.text);
+
           return;
         }
       else
         {
           if (self->conf->DEBUG > 0 || self->conf->VERBOSE > 0)
             fprintf (stderr, "Command not converted: %s\n", command_name);
+          if (builtin_command_data[data_cmd].flags & CF_root)
+            {
+              self->current_root_command = 0;
+              self->modified_state++;
+            }
           return;
         }
 
@@ -3222,25 +3388,33 @@ convert_to_html_internal (CONVERTER *self, ELEMENT 
*element,
   free (debug_str);
 }
 
+static char *
+output_unit_conversion (CONVERTER *self, enum output_unit_type unit_type,
+                        OUTPUT_UNIT *output_unit, const char *content)
+{
+  /* TODO call a C function if status is FRS_status_default_set
+     maybe putting function references in an array */
+  if (self->output_units_conversion[unit_type].status > 0)
+    return call_output_units_conversion (self, unit_type, output_unit, 
content);
+  return 0;
+}
+
 char *
 convert_output_unit (CONVERTER *self, OUTPUT_UNIT *output_unit,
                      char *explanation)
 {
-  char *result;
+  char *result = 0;
   TEXT content_formatted;
   enum output_unit_type unit_type = output_unit->unit_type;
 
-/*
-  if (exists ($self->{'output_units_conversion'}->{$unit_type_name})
-      and !defined($self->{'output_units_conversion'}->{$unit_type_name})) {
-    if ($debug) {
-      my $string = 'IGNORED';
-      $string .= " $unit_type_name" if ($unit_type_name);
-      print STDERR "$string\n";
-    }
-    return '';
-  }
- */
+  if (self->output_units_conversion[unit_type].status == FRS_status_ignored)
+    {
+      if (self->conf->DEBUG > 0)
+        {
+          fprintf (stderr, "IGNORED OU %s\n", 
output_unit_type_names[unit_type]);
+        }
+      return strdup ("");
+    }
 
   self->current_output_unit = output_unit;
   self->modified_state++;
@@ -3264,22 +3438,20 @@ convert_output_unit (CONVERTER *self, OUTPUT_UNIT 
*output_unit,
        }
     }
 
-  if (0)
+  if (self->output_units_conversion[unit_type].status)
     {
-    /*
-   if (exists($self->{'output_units_conversion'}->{$unit_type_name}))
-   $result
-     .= &{$self->{'output_units_conversion'}->{$unit_type_name}} ($self,
-                                               $unit_type_name,
-                                               $output_unit,
-                                               $content_formatted);
-     */
+      result = output_unit_conversion (self, unit_type, output_unit,
+                                             content_formatted.text);
+      if (! result)
+        result = strdup ("");
     }
    else
     {
       result = strdup (content_formatted.text);
     }
 
+  free (content_formatted.text);
+
   self->current_output_unit = 0;
   self->modified_state++;
 
@@ -3321,7 +3493,6 @@ html_convert_convert (CONVERTER *self, ELEMENT *root,
   OUTPUT_UNIT_LIST *special_units
     = retrieve_output_units (special_units_descriptor);
 
-  html_new_document_context (self, "_toplevel_context", 0, 0);
   text_init (&result);
 
   if (!output_units || !output_units->number)
diff --git a/tp/Texinfo/XS/main/build_perl_info.c 
b/tp/Texinfo/XS/main/build_perl_info.c
index 4fabb66d68..3bdf4ceab9 100644
--- a/tp/Texinfo/XS/main/build_perl_info.c
+++ b/tp/Texinfo/XS/main/build_perl_info.c
@@ -206,7 +206,7 @@ build_perl_directions (ELEMENT_LIST *e)
 /* Used to create a "Perl-internal" string that represents a sequence
    of Unicode codepoints with no specific encoding. */
 SV *
-newSVpv_utf8 (char *str, STRLEN len)
+newSVpv_utf8 (const char *str, STRLEN len)
 {
   SV *sv;
   dTHX;
@@ -1836,7 +1836,7 @@ build_html_document_context (HTML_DOCUMENT_CONTEXT 
*document_context)
   STORE_CTX(math);
 #undef STORE_CTX
   STORE ("document_global_context",
-         newSViv (document_context->document_global_context));
+         newSVpv_utf8 (document_context->document_global_context, 0));
 
   for (i = 0; i < document_context->monospace_context.top; i++)
     {
@@ -1897,6 +1897,8 @@ build_html_formatting_state (CONVERTER *converter)
   HV *hv;
   SV **document_context_sv;
   AV *document_context_av;
+  SV **multiple_pass_sv;
+  AV *multiple_pass_av;
   SV **files_information_sv;
   HV *files_information_hv;
   int i;
@@ -1912,6 +1914,9 @@ build_html_formatting_state (CONVERTER *converter)
   STORE("document_global_context",
         newSViv (converter->document_global_context));
 
+  STORE("ignore_notice",
+        newSViv (converter->ignore_notice));
+
   if (!converter->current_root_command)
     STORE("current_root_command", newSV (0));
   else
@@ -1957,6 +1962,26 @@ build_html_formatting_state (CONVERTER *converter)
       av_push (document_context_av, newRV_noinc ((SV *) document_context_hv));
     }
 
+  multiple_pass_sv = hv_fetch (hv, "multiple_pass",
+                                  strlen ("multiple_pass"), 0);
+
+  if (!multiple_pass_sv)
+    {
+      multiple_pass_av = newAV ();
+      STORE("multiple_pass", newRV_noinc ((SV *) multiple_pass_av));
+    }
+  else
+    {
+      multiple_pass_av = (AV *) SvRV (*multiple_pass_sv);
+      av_clear (multiple_pass_av);
+    }
+
+  for (i = 0; i < converter->multiple_pass.top; i++)
+    {
+      char *multiple_pass_str = converter->multiple_pass.stack[i];
+      av_push (multiple_pass_av, newSVpv_utf8(multiple_pass_str, 0));
+    }
+
   files_information_sv = hv_fetch (hv, "files_information",
                                   strlen ("files_information"), 0);
 
@@ -1978,3 +2003,46 @@ build_html_formatting_state (CONVERTER *converter)
 
   return newRV_noinc ((SV *) hv);
 }
+
+SV *
+build_html_command_formatted_args (HTML_ARGS_FORMATTED *args_formatted)
+{
+  AV *av;
+  int i;
+
+  dTHX;
+
+  if (!args_formatted)
+    return newSV (0);
+
+  av = newAV ();
+
+  for (i = 0; i < args_formatted->number; i++)
+    {
+      HTML_ARG_FORMATTED *arg_formatted = &args_formatted->args[i];
+      if (arg_formatted->tree)
+        {
+          int j;
+          HV *arg_formated_hv = newHV ();
+          av_push (av, newRV_noinc ((SV *) arg_formated_hv));
+
+          hv_store (arg_formated_hv, "tree", strlen ("tree"),
+                    newRV_inc ((SV *) arg_formatted->tree->hv), 0);
+
+          for (j = 0; j < AFT_type_raw+1; j++)
+            {
+              if (arg_formatted->formatted[j])
+                {
+                  const char *format_name
+                     = html_argument_formatting_type_names[j];
+                  hv_store (arg_formated_hv, format_name, strlen (format_name),
+                            newSVpv_utf8 (arg_formatted->formatted[j], 0), 0);
+                }
+            }
+        }
+      else
+        av_push (av, newSV(0));
+    }
+
+  return newRV_noinc ((SV *) av);
+}
diff --git a/tp/Texinfo/XS/main/build_perl_info.h 
b/tp/Texinfo/XS/main/build_perl_info.h
index 421aa65d40..6a6a72bd15 100644
--- a/tp/Texinfo/XS/main/build_perl_info.h
+++ b/tp/Texinfo/XS/main/build_perl_info.h
@@ -11,7 +11,7 @@
 int init (int texinfo_uninstalled, char *srcdir_in);
 
 /* does not exist as perl macro */
-SV *newSVpv_utf8 (char *str, STRLEN len);
+SV *newSVpv_utf8 (const char *str, STRLEN len);
 
 SV *build_document (size_t document_descriptor, int no_store);
 
@@ -49,4 +49,6 @@ SV *build_file_counters (FILE_NAME_PATH_COUNTER_LIST 
*output_unit_files);
 SV *build_out_filepaths (FILE_NAME_PATH_COUNTER_LIST *output_unit_files);
 
 SV *build_html_formatting_state (CONVERTER *converter);
+
+SV *build_html_command_formatted_args (HTML_ARGS_FORMATTED *args_formatted);
 #endif
diff --git a/tp/Texinfo/XS/main/call_perl_function.c 
b/tp/Texinfo/XS/main/call_perl_function.c
index 9c661a4422..a3da5bfab5 100644
--- a/tp/Texinfo/XS/main/call_perl_function.c
+++ b/tp/Texinfo/XS/main/call_perl_function.c
@@ -488,14 +488,16 @@ call_formatting_function_format_title_titlepage 
(CONVERTER *self)
   char *result_ret;
   STRLEN len;
   SV *result_sv;
-  SV *formatting_reference
-    = self->formatting_references[FR_format_title_titlepage].sv_reference;
+  SV *formatting_reference;
 
   dTHX;
 
   if (!self->hv)
     return 0;
 
+  formatting_reference
+    = self->formatting_references[FR_format_title_titlepage].sv_reference;
+
   dSP;
 
   ENTER;
@@ -537,13 +539,21 @@ call_types_conversion (CONVERTER *self, enum element_type 
type,
   char *result_ret;
   STRLEN len;
   SV *result_sv;
-  SV *formatting_reference = self->types_conversion[type].sv_reference;
+  SV *formatting_reference;
 
   dTHX;
 
   if (!self->hv)
     return 0;
 
+  if (self->tree_to_build)
+    {
+      build_texinfo_tree (self->tree_to_build);
+      self->tree_to_build = 0;
+    }
+
+  formatting_reference = self->types_conversion[type].sv_reference;
+
   if (self->modified_state)
     {
       build_html_formatting_state (self);
@@ -598,13 +608,21 @@ call_types_open (CONVERTER *self, enum element_type type,
   char *result_ret;
   STRLEN len;
   SV *result_sv;
-  SV *formatting_reference = self->types_open[type].sv_reference;
+  SV *formatting_reference;
 
   dTHX;
 
+  if (self->tree_to_build)
+    {
+      build_texinfo_tree (self->tree_to_build);
+      self->tree_to_build = 0;
+    }
+
   if (!self->hv)
     return 0;
 
+  formatting_reference = self->types_open[type].sv_reference;
+
   if (self->modified_state)
     {
       build_html_formatting_state (self);
@@ -646,3 +664,225 @@ call_types_open (CONVERTER *self, enum element_type type,
 
   return result;
 }
+
+char *
+call_commands_conversion (CONVERTER *self, enum command_id cmd,
+                          ELEMENT *element, HTML_ARGS_FORMATTED 
*args_formatted,
+                          const char *content)
+{
+  int count;
+  char *result;
+  char *result_ret;
+  STRLEN len;
+  SV *result_sv;
+  SV *formatting_reference;
+  SV *args_formatted_sv;
+  char *command_name;
+
+  dTHX;
+
+  if (!self->hv)
+    return 0;
+
+  if (self->tree_to_build)
+    {
+      build_texinfo_tree (self->tree_to_build);
+      self->tree_to_build = 0;
+    }
+
+  /* could also be builtin_command_data[cmd].cmdname) */
+  command_name = element_command_name (element);
+
+  formatting_reference = self->commands_conversion[cmd].sv_reference;
+
+  if (self->modified_state)
+    {
+      build_html_formatting_state (self);
+      self->modified_state = 0;
+    }
+
+  args_formatted_sv = build_html_command_formatted_args (args_formatted);
+
+  dSP;
+
+  ENTER;
+  SAVETMPS;
+
+  PUSHMARK(SP);
+  EXTEND(SP, 5);
+
+  PUSHs(sv_2mortal (newRV_inc (self->hv)));
+  PUSHs(sv_2mortal (newSVpv (command_name, 0)));
+  PUSHs(sv_2mortal (newRV_inc (element->hv)));
+  PUSHs(sv_2mortal (args_formatted_sv));
+  /* content == 0 is possible, hope that newSVpv result corresponds to
+     undef in that case, but could also need to explicitely use newSV(0) */
+  PUSHs(sv_2mortal (newSVpv_utf8 (content, 0)));
+  PUTBACK;
+
+  count = call_sv (formatting_reference,
+                   G_SCALAR);
+
+  SPAGAIN;
+
+  if (count != 1)
+    croak("commands_conversion should return 1 item\n");
+
+  result_sv = POPs;
+  /* it is encoded using non strict encoding, so the UTF-8 could be invalid.
+     It could be possible to add a wrapper in perl that encode to UTF-8,
+     but probably not worth it */
+  result_ret = SvPVutf8 (result_sv, len);
+  result = strdup (result_ret);
+
+  PUTBACK;
+
+  FREETMPS;
+  LEAVE;
+
+  return result;
+}
+
+char *
+call_commands_open (CONVERTER *self, enum command_id cmd,
+                    ELEMENT *element)
+{
+  int count;
+  char *result;
+  char *result_ret;
+  STRLEN len;
+  SV *result_sv;
+  SV *formatting_reference;
+  char *command_name;
+
+  dTHX;
+
+  if (!self->hv)
+    return 0;
+
+  if (self->tree_to_build)
+    {
+      build_texinfo_tree (self->tree_to_build);
+      self->tree_to_build = 0;
+    }
+
+  formatting_reference = self->commands_open[cmd].sv_reference;
+
+  /* could also be builtin_command_data[cmd].cmdname) */
+  command_name = element_command_name (element);
+
+  if (self->modified_state)
+    {
+      build_html_formatting_state (self);
+      self->modified_state = 0;
+    }
+
+  dSP;
+
+  ENTER;
+  SAVETMPS;
+
+  PUSHMARK(SP);
+  EXTEND(SP, 3);
+
+  PUSHs(sv_2mortal (newRV_inc (self->hv)));
+  PUSHs(sv_2mortal (newSVpv (command_name, 0)));
+  PUSHs(sv_2mortal (newRV_inc (element->hv)));
+  PUTBACK;
+
+  count = call_sv (formatting_reference,
+                   G_SCALAR);
+
+  SPAGAIN;
+
+  if (count != 1)
+    croak("commands_open should return 1 item\n");
+
+  result_sv = POPs;
+  /* it is encoded using non strict encoding, so the UTF-8 could be invalid.
+     It could be possible to add a wrapper in perl that encode to UTF-8,
+     but probably not worth it */
+  result_ret = SvPVutf8 (result_sv, len);
+  result = strdup (result_ret);
+
+  PUTBACK;
+
+  FREETMPS;
+  LEAVE;
+
+  return result;
+}
+
+char *
+call_output_units_conversion (CONVERTER *self,
+                               enum output_unit_type unit_type,
+                               OUTPUT_UNIT *output_unit, const char *content)
+{
+  int count;
+  char *result;
+  char *result_ret;
+  STRLEN len;
+  SV *result_sv;
+  SV *formatting_reference;
+
+  dTHX;
+
+  if (!self->hv)
+    return 0;
+
+  if (self->tree_to_build)
+    {
+      build_texinfo_tree (self->tree_to_build);
+      self->tree_to_build = 0;
+    }
+
+  formatting_reference
+     = self->output_units_conversion[unit_type].sv_reference;
+
+  if (self->modified_state)
+    {
+      build_html_formatting_state (self);
+      self->modified_state = 0;
+    }
+
+  dSP;
+
+  ENTER;
+  SAVETMPS;
+
+  PUSHMARK(SP);
+  EXTEND(SP, 4);
+
+  PUSHs(sv_2mortal (newRV_inc (self->hv)));
+  PUSHs(sv_2mortal (newSVpv (output_unit_type_names[unit_type], 0)));
+  PUSHs(sv_2mortal (newRV_inc (output_unit->hv)));
+  /* content == 0 is possible, hope that newSVpv result corresponds to
+     undef in that case, but could also need to explicitely use newSV(0) */
+  PUSHs(sv_2mortal (newSVpv_utf8 (content, 0)));
+  PUTBACK;
+
+  count = call_sv (formatting_reference,
+                   G_SCALAR);
+
+  SPAGAIN;
+
+  if (count != 1)
+    croak("output_units_conversion should return 1 item\n");
+
+
+  result_sv = POPs;
+  /* it is encoded using non strict encoding, so the UTF-8 could be invalid.
+     It could be possible to add a wrapper in perl that encode to UTF-8,
+     but probably not worth it */
+  result_ret = SvPVutf8 (result_sv, len);
+  result = strdup (result_ret);
+
+  PUTBACK;
+
+  FREETMPS;
+  LEAVE;
+
+  return result;
+}
+
+
diff --git a/tp/Texinfo/XS/main/get_perl_info.c 
b/tp/Texinfo/XS/main/get_perl_info.c
index bdcbf18dcc..36ed271594 100644
--- a/tp/Texinfo/XS/main/get_perl_info.c
+++ b/tp/Texinfo/XS/main/get_perl_info.c
@@ -388,7 +388,7 @@ set_translated_commands (CONVERTER *converter, HV *hv_in)
 static void
 register_formatting_reference_with_default (char *type_string,
                 FORMATTING_REFERENCE *formatting_reference,
-                char *ref_name, HV *default_hv, HV *customized_hv)
+                const char *ref_name, HV *default_hv, HV *customized_hv)
 {
   SV **default_formatting_reference_sv;
   SV **formatting_reference_sv;
@@ -434,7 +434,8 @@ html_converter_initialize_sv (SV *sv_in, SV 
*default_formatting_references,
                               SV *default_commands_open,
                               SV *default_commands_conversion,
                               SV *default_types_open,
-                              SV *default_types_conversion)
+                              SV *default_types_conversion,
+                              SV *default_output_units_conversion)
 {
   int i;
   HV *hv_in;
@@ -444,6 +445,7 @@ html_converter_initialize_sv (SV *sv_in, SV 
*default_formatting_references,
   HV *default_commands_conversion_hv;
   HV *default_types_open_hv;
   HV *default_types_conversion_hv;
+  HV *default_output_units_conversion_hv;
   SV **converter_init_conf_sv;
   SV **converter_sv;
   SV **formatting_function_sv;
@@ -454,6 +456,7 @@ html_converter_initialize_sv (SV *sv_in, SV 
*default_formatting_references,
   SV **types_conversion_sv;
   SV **commands_open_sv;
   SV **commands_conversion_sv;
+  SV **output_units_conversion_sv;
   SV **code_types_sv;
   SV **pre_class_types_sv;
   HV *formatting_function_hv;
@@ -461,6 +464,7 @@ html_converter_initialize_sv (SV *sv_in, SV 
*default_formatting_references,
   HV *commands_conversion_hv;
   HV *types_open_hv;
   HV *types_conversion_hv;
+  HV *output_units_conversion_hv;
   CONVERTER *converter = new_converter ();
   int converter_descriptor = 0;
   DOCUMENT *document;
@@ -614,6 +618,23 @@ html_converter_initialize_sv (SV *sv_in, SV 
*default_formatting_references,
         types_conversion_hv);
     }
 
+  FETCH(output_units_conversion)
+  output_units_conversion_hv = (HV *)SvRV (*output_units_conversion_sv);
+  default_output_units_conversion_hv
+    = (HV *)SvRV (default_output_units_conversion);
+
+  for (i = 0; i < OU_special_unit+1; i++)
+    {
+      const char *ref_name = output_unit_type_names[i];
+      FORMATTING_REFERENCE *conversion_formatting_reference
+       = &converter->output_units_conversion[i];
+
+      register_formatting_reference_with_default ("output_unit_conversion",
+        conversion_formatting_reference, ref_name,
+        default_output_units_conversion_hv,
+        output_units_conversion_hv);
+    }
+
   FETCH(sorted_special_unit_varieties)
 
   if (sorted_special_unit_varieties_sv)
diff --git a/tp/Texinfo/XS/main/get_perl_info.h 
b/tp/Texinfo/XS/main/get_perl_info.h
index 42e85e6a2a..dcb4ff50e4 100644
--- a/tp/Texinfo/XS/main/get_perl_info.h
+++ b/tp/Texinfo/XS/main/get_perl_info.h
@@ -22,7 +22,8 @@ int html_converter_initialize_sv (SV *sv_in, SV 
*default_formatting_references,
                                   SV *default_commands_open,
                                   SV *default_commands_conversion,
                                   SV *default_types_open,
-                                  SV *default_types_conversion);
+                                  SV *default_types_conversion,
+                                  SV *default_output_units_conversion);
 CONVERTER *set_output_converter_sv (SV *sv_in, char *warn_string);
 CONVERTER *get_sv_converter (SV *sv_in, char *warn_string);
 
diff --git a/tp/Texinfo/XS/main/tree_perl_api.h 
b/tp/Texinfo/XS/main/tree_perl_api.h
index 4e6bf3e878..501076f132 100644
--- a/tp/Texinfo/XS/main/tree_perl_api.h
+++ b/tp/Texinfo/XS/main/tree_perl_api.h
@@ -33,5 +33,13 @@ char *call_types_conversion (CONVERTER *self, enum 
element_type type,
                              ELEMENT *element, char *content);
 char *call_types_open (CONVERTER *self, enum element_type type,
                        ELEMENT *element);
+char *call_commands_conversion (CONVERTER *self, enum command_id cmd,
+                          ELEMENT *element, HTML_ARGS_FORMATTED 
*args_formatted,
+                          const char *content);
+char *call_commands_open (CONVERTER *self, enum command_id cmd,
+                          ELEMENT *element);
+char *call_output_units_conversion (CONVERTER *self,
+                                    enum output_unit_type unit_type,
+                                OUTPUT_UNIT *output_unit, const char *content);
 
 #endif
diff --git a/tp/Texinfo/XS/main/utils.c b/tp/Texinfo/XS/main/utils.c
index e50c5cf498..d79174f3f1 100644
--- a/tp/Texinfo/XS/main/utils.c
+++ b/tp/Texinfo/XS/main/utils.c
@@ -65,8 +65,8 @@ const enum command_id small_block_associated_command[][2] = {
 
 /* to keep synchronized with enum output_unit_type in tree_types.h */
 const char *output_unit_type_names[] = {"unit",
-                                        "external_node_unit",
-                                        "special_unit"};
+                                  "external_node_unit",
+                                  "special_unit"};
 
 char *html_global_unit_direction_names[] = {
   #define hgdt_name(name) #name,
@@ -92,6 +92,12 @@ char *html_css_string_formatting_reference_names[] = {
   #undef html_fr_reference
 };
 
+const char *html_argument_formatting_type_names[] = {
+   #define html_aft_type(name) #name,
+    HTML_ARGUMENTS_FORMATTED_FORMAT_TYPE
+   #undef html_aft_type
+};
+
 ENCODING_CONVERSION_LIST output_conversions = {0, 0, 0, -1};
 ENCODING_CONVERSION_LIST input_conversions = {0, 0, 0, 1};
 
diff --git a/tp/Texinfo/XS/main/utils.h b/tp/Texinfo/XS/main/utils.h
index 730598f22e..4af980ca5a 100644
--- a/tp/Texinfo/XS/main/utils.h
+++ b/tp/Texinfo/XS/main/utils.h
@@ -395,7 +395,7 @@ typedef struct HTML_DOCUMENT_CONTEXT {
     int raw_ctx;
     int verbatim_ctx;
     int math_ctx;
-    int document_global_context;
+    char *document_global_context;
     MONOSPACE_CONTEXT_STACK monospace_context;
     COMMAND_OR_TYPE_STACK composition_context;
     COMMAND_STACK block_commands;
@@ -424,8 +424,6 @@ typedef struct CONVERTER {
   /* output unit files API */
     FILE_NAME_PATH_COUNTER_LIST *output_unit_files;
 
-    int modified_state; /* to determine if perl data should be rebuilt */
-
   /* perl converter. This should be HV *hv,
      but we don't want to include the Perl headers everywhere; */
     void *hv;
@@ -456,13 +454,22 @@ typedef struct CONVERTER {
     FORMATTING_REFERENCE commands_conversion[BUILTIN_CMD_NUMBER];
     FORMATTING_REFERENCE types_open[ET_special_unit_element+1];
     FORMATTING_REFERENCE types_conversion[ET_special_unit_element+1];
+    FORMATTING_REFERENCE output_units_conversion[OU_special_unit+1];
 
-    /* state */
+    /* state only in C converter */
+    int modified_state; /* to determine if perl data should be rebuilt */
+    ELEMENT *tree_to_build; /* C tree that needs to be built to perl before
+                               calling perl functions on it */
+
+
+    /* state common with perl converter */
     int document_global_context;
+    int ignore_notice;
     ELEMENT *current_root_command;
     ELEMENT *current_node;
     OUTPUT_UNIT *current_output_unit;
     HTML_DOCUMENT_CONTEXT_STACK html_document_context;
+    STRING_STACK multiple_pass;
     char *current_filename;
 } CONVERTER;
 
@@ -513,6 +520,36 @@ typedef struct INDEX_SORTABLE_ENTRIES {
     SORTABLE_ENTRY *sortable_entries;
 } INDEX_SORTABLE_ENTRIES;
 
+#define HTML_ARGUMENTS_FORMATTED_FORMAT_TYPE \
+  html_aft_type(none) \
+  html_aft_type(normal) \
+  html_aft_type(string) \
+  html_aft_type(monospace) \
+  html_aft_type(monospacetext) \
+  html_aft_type(monospacestring) \
+  html_aft_type(filenametext) \
+  html_aft_type(url) \
+  html_aft_type(raw)
+
+enum html_argument_formatting_type {
+   #define html_aft_type(name) AFT_type_##name,
+    HTML_ARGUMENTS_FORMATTED_FORMAT_TYPE
+   #undef html_aft_type
+};
+
+extern const char *html_argument_formatting_type_names[];
+
+typedef struct HTML_ARG_FORMATTED {
+    ELEMENT *tree;
+    char *formatted[AFT_type_raw+1];
+} HTML_ARG_FORMATTED;
+
+typedef struct HTML_ARGS_FORMATTED {
+    size_t number;
+    HTML_ARG_FORMATTED *args;
+} HTML_ARGS_FORMATTED;
+
+
 int xasprintf (char **ptr, const char *template, ...);
 
 void fatal (char *);



reply via email to

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