texinfo-commits
[Top][All Lists]
Advanced

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

[no subject]


From: Patrice Dumas
Date: Wed, 3 Jan 2024 15:51:42 -0500 (EST)

branch: master
commit bce2b9ba9216583a7847c6f169756e36d93c5287
Author: Patrice Dumas <pertusus@free.fr>
AuthorDate: Wed Jan 3 21:49:55 2024 +0100

    * tp/Texinfo/XS/main/build_perl_info.c (build_string_list)
    (html_build_direction_icons): add.
    
    * tp/Texinfo/XS/main/converter_types.h (enum sv_string_type):
    move to converter_types.h.
    
    * tp/Texinfo/XS/*/*.c, tp/Texinfo/XS/convert/converter.c
    (new_option_value, command_init, set_global_document_commands),
    tp/Texinfo/XS/main/converter_types.h (enum global_option_type)
    (OPTION), tp/Texinfo/XS/main/utils.c (set_informative_command_value)
    (new_options, free_option, initialize_option),
    tp/Texinfo/XS/main/utils.h, tp/Texinfo/options_data.txt,
    tp/maintain/regenerate_C_options_info.pl,
    tp/maintain/regenerate_perl_options_info.pl: modify OPTIONS structure
    to have an intermediate OPTION structure that is a union of the
    possible types instead of the value being directly in OPTIONS.  rename
    enum global_option_command_type as enum global_option_type and add all
    the possible types of global options.  Use the types of
    global_option_type in options_data.txt instead of C types.  Add
    free_option and initialize_option to handle all the possible types.
    
    * tp/Texinfo/Convert/Converter.pm (%XS_overrides, _XS_force_conf)
    (force_conf, _XS_get_conf, get_conf, converter),
    tp/Texinfo/XS/convert/ConvertXS.xs (force_conf, get_conf),
    tp/Texinfo/XS/main/build_perl_info.c (get_conf),
    tp/Texinfo/XS/main/get_perl_info.c (get_sv_options, copy_sv_options)
    (recopy_converter_conf_sv, set_conf, force_conf),
    tp/Texinfo/XS/main/utils.c (set_informative_command_value),
    tp/maintain/regenerate_C_options_info.pl: use XS to access
    customization variables preferrentially to make sure that perl and XS
    are synchronized.  Override get_conf, and use a specific override for
    force_conf.  Reorganize converter function code to use get_conf only
    when the XS converter has been initialized.  Generate build_sv_option
    for get_conf.  Add set field in OPTION to avoid overriding the value
    if not called as force_conf.  Set set field based on perl value in
    converter.
    
    * tp/Texinfo/XS/convert/convert_html.c (convert_informative_command)
    (commands_internal_conversion_table): implement
    convert_informative_command.
---
 ChangeLog                                       |  43 ++
 tp/Texinfo/Convert/Converter.pm                 |  43 +-
 tp/Texinfo/XS/convert/ConvertXS.xs              |  33 +-
 tp/Texinfo/XS/convert/convert_html.c            | 602 +++++++++++++-----------
 tp/Texinfo/XS/convert/converter.c               | 111 +++--
 tp/Texinfo/XS/main/DocumentXS.xs                |   4 +-
 tp/Texinfo/XS/main/build_perl_info.c            |  65 ++-
 tp/Texinfo/XS/main/build_perl_info.h            |  10 +
 tp/Texinfo/XS/main/call_perl_function.c         |   3 +-
 tp/Texinfo/XS/main/convert_to_text.c            |  15 +-
 tp/Texinfo/XS/main/convert_utils.c              |  20 +-
 tp/Texinfo/XS/main/converter_types.h            |  31 ++
 tp/Texinfo/XS/main/errors.c                     |  18 +-
 tp/Texinfo/XS/main/get_perl_info.c              |  59 ++-
 tp/Texinfo/XS/main/get_perl_info.h              |  11 +-
 tp/Texinfo/XS/main/output_unit.c                |   4 +-
 tp/Texinfo/XS/main/translations.c               |   8 +-
 tp/Texinfo/XS/main/utils.c                      |  98 +++-
 tp/Texinfo/XS/main/utils.h                      |  17 +-
 tp/Texinfo/XS/structuring_transfo/structuring.c |  20 +-
 tp/Texinfo/options_data.txt                     | 438 ++++++++---------
 tp/maintain/regenerate_C_options_info.pl        | 186 ++++----
 tp/maintain/regenerate_perl_options_info.pl     |   2 +-
 23 files changed, 1096 insertions(+), 745 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 48fc3652c2..73f6fe12f8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,46 @@
+2024-01-03  Patrice Dumas  <pertusus@free.fr>
+
+       * tp/Texinfo/XS/main/build_perl_info.c (build_string_list)
+       (html_build_direction_icons): add.
+
+       * tp/Texinfo/XS/main/converter_types.h (enum sv_string_type):
+       move to converter_types.h.
+
+       * tp/Texinfo/XS/*/*.c, tp/Texinfo/XS/convert/converter.c
+       (new_option_value, command_init, set_global_document_commands),
+       tp/Texinfo/XS/main/converter_types.h (enum global_option_type)
+       (OPTION), tp/Texinfo/XS/main/utils.c (set_informative_command_value)
+       (new_options, free_option, initialize_option),
+       tp/Texinfo/XS/main/utils.h, tp/Texinfo/options_data.txt,
+       tp/maintain/regenerate_C_options_info.pl,
+       tp/maintain/regenerate_perl_options_info.pl: modify OPTIONS structure
+       to have an intermediate OPTION structure that is a union of the
+       possible types instead of the value being directly in OPTIONS.  rename
+       enum global_option_command_type as enum global_option_type and add all
+       the possible types of global options.  Use the types of
+       global_option_type in options_data.txt instead of C types.  Add
+       free_option and initialize_option to handle all the possible types.
+
+       * tp/Texinfo/Convert/Converter.pm (%XS_overrides, _XS_force_conf)
+       (force_conf, _XS_get_conf, get_conf, converter),
+       tp/Texinfo/XS/convert/ConvertXS.xs (force_conf, get_conf),
+       tp/Texinfo/XS/main/build_perl_info.c (get_conf),
+       tp/Texinfo/XS/main/get_perl_info.c (get_sv_options, copy_sv_options)
+       (recopy_converter_conf_sv, set_conf, force_conf),
+       tp/Texinfo/XS/main/utils.c (set_informative_command_value),
+       tp/maintain/regenerate_C_options_info.pl: use XS to access
+       customization variables preferrentially to make sure that perl and XS
+       are synchronized.  Override get_conf, and use a specific override for
+       force_conf.  Reorganize converter function code to use get_conf only
+       when the XS converter has been initialized.  Generate build_sv_option
+       for get_conf.  Add set field in OPTION to avoid overriding the value
+       if not called as force_conf.  Set set field based on perl value in
+       converter.
+
+       * tp/Texinfo/XS/convert/convert_html.c (convert_informative_command)
+       (commands_internal_conversion_table): implement
+       convert_informative_command.
+
 2024-01-03  Patrice Dumas  <pertusus@free.fr>
 
        * tp/Texinfo/Convert/HTML.pm (convert, output): use get_conf instead
diff --git a/tp/Texinfo/Convert/Converter.pm b/tp/Texinfo/Convert/Converter.pm
index 3ddba215af..d444cb4490 100644
--- a/tp/Texinfo/Convert/Converter.pm
+++ b/tp/Texinfo/Convert/Converter.pm
@@ -85,15 +85,19 @@ $XS_convert = 1 if ($XS_structuring
 our $module_loaded = 0;
 
 my %XS_overrides = (
+  # XS only called if there is an associated XS converter
   "Texinfo::Convert::Converter::_XS_converter_initialize",
    => "Texinfo::Convert::ConvertXS::converter_initialize",
   "Texinfo::Convert::Converter::_XS_set_conf"
    => "Texinfo::Convert::ConvertXS::set_conf",
-  "Texinfo::Convert::Converter::_XS_get_unclosed_stream"
-   => "Texinfo::Convert::ConvertXS::get_unclosed_stream",
+  "Texinfo::Convert::Converter::_XS_force_conf"
+   => "Texinfo::Convert::ConvertXS::force_conf",
+  "Texinfo::Convert::Converter::_XS_get_conf"
+   => "Texinfo::Convert::ConvertXS::get_conf",
+
+  # fully overriden for all the converters
   "Texinfo::Convert::Converter::get_converter_errors"
    => "Texinfo::Convert::ConvertXS::get_converter_errors",
-
   "Texinfo::Convert::Converter::converter_line_error"
    => "Texinfo::Convert::ConvertXS::converter_line_error",
   "Texinfo::Convert::Converter::converter_line_warn"
@@ -103,11 +107,14 @@ my %XS_overrides = (
   "Texinfo::Convert::Converter::converter_document_warn"
    => "Texinfo::Convert::ConvertXS::converter_document_warn",
 
+  # XS only
   "Texinfo::Convert::Converter::reset_converter"
    => "Texinfo::Convert::ConvertXS::reset_converter",
   "Texinfo::Convert::Converter::destroy"
    => "Texinfo::Convert::ConvertXS::destroy",
 );
+  "Texinfo::Convert::Converter::_XS_get_unclosed_stream"
+   => "Texinfo::Convert::ConvertXS::get_unclosed_stream",
 
 sub import {
   if (!$module_loaded) {
@@ -294,14 +301,11 @@ sub converter($;$)
     }
   }
 
-  Texinfo::Common::set_output_encodings($converter,
-                                        $converter->{'document_info'});
-
   # turn the array to a hash.
-  my $expanded_formats = $converter->get_conf('EXPANDED_FORMATS');
+  my $expanded_formats = $converter->{'conf'}->{'EXPANDED_FORMATS'};
   $converter->{'expanded_formats'} = {};
   if (defined($expanded_formats)) {
-    foreach my $expanded_format (@{$converter->get_conf('EXPANDED_FORMATS')}) {
+    foreach my $expanded_format (@$expanded_formats) {
       $converter->{'expanded_formats'}->{$expanded_format} = 1;
     }
   }
@@ -313,8 +317,13 @@ sub converter($;$)
   $converter->{'error_warning_messages'} = [];
 
   # XS converter initialization
+  # get_conf should not be used before that point, such that the conf is
+  # initialized before it is called for the first time.
   _XS_converter_initialize($converter);
 
+  Texinfo::Common::set_output_encodings($converter,
+                                        $converter->{'document_info'});
+
   $converter->converter_initialize();
 
   return $converter;
@@ -581,6 +590,13 @@ sub get_converter_errors($)
 # Implementation of the customization API that is used in many
 # Texinfo modules
 
+# Those functions are not overriden when XS is used as it is possible
+# that some converters do not use XS.
+
+sub _XS_get_conf($$)
+{
+}
+
 sub get_conf($$)
 {
   my $self = shift;
@@ -589,6 +605,11 @@ sub get_conf($$)
     confess("CBUG: unknown option $conf\n");
     #return undef;
   }
+
+  if ($self->{'converter_descriptor'} and $XS_convert) {
+    return _XS_get_conf($self, $conf);
+  }
+
   return $self->{'conf'}->{$conf};
 }
 
@@ -616,6 +637,10 @@ sub set_conf($$$)
   }
 }
 
+sub _XS_force_conf($$$)
+{
+}
+
 sub force_conf($$$)
 {
   my $self = shift;
@@ -626,7 +651,7 @@ sub force_conf($$$)
     return undef;
   }
   if ($self->{'converter_descriptor'} and $XS_convert) {
-    _XS_set_conf($self, $conf, $value);
+    _XS_force_conf($self, $conf, $value);
   }
   $self->{'conf'}->{$conf} = $value;
   return 1;
diff --git a/tp/Texinfo/XS/convert/ConvertXS.xs 
b/tp/Texinfo/XS/convert/ConvertXS.xs
index 5ad6fc9b30..f5bbc53930 100644
--- a/tp/Texinfo/XS/convert/ConvertXS.xs
+++ b/tp/Texinfo/XS/convert/ConvertXS.xs
@@ -79,11 +79,36 @@ set_conf (SV *converter_in, conf, SV *value)
       PREINIT:
          CONVERTER *self;
       CODE:
-         /* Warn? Calling code checks 'converter_descriptor' is set */
+         /* Calling code checks 'converter_descriptor' is set */
          self = get_sv_converter (converter_in, 0);
          if (self)
            set_conf (self, conf, value);
 
+void
+force_conf (SV *converter_in, conf, SV *value)
+         char *conf = (char *)SvPVbyte_nolen($arg);
+      PREINIT:
+         CONVERTER *self;
+      CODE:
+         /* Calling code checks 'converter_descriptor' is set */
+         self = get_sv_converter (converter_in, 0);
+         if (self)
+           force_conf (self, conf, value);
+
+SV *
+get_conf (SV *converter_in, conf)
+         char *conf = (char *)SvPVbyte_nolen($arg);
+      PREINIT:
+         CONVERTER *self;
+      CODE:
+         self = get_sv_converter (converter_in, 0);
+         if (self)
+           RETVAL = get_conf (self, conf);
+         else
+           RETVAL = newSV (0);
+    OUTPUT:
+        RETVAL
+
 void
 converter_line_error (SV *converter_in, text, SV *error_location_info, ...)
           char *text = (char *)SvPVutf8_nolen($arg);
@@ -1613,10 +1638,10 @@ html_prepare_conversion_units (SV *converter_in, ...)
          self = set_output_converter_sv (converter_in,
                                          "html_prepare_conversion_units");
 
-         if (self->conf->OUTPUT_CHARACTERS > 0
-             && self->conf->OUTPUT_ENCODING_NAME
+         if (self->conf->OUTPUT_CHARACTERS.integer > 0
+             && self->conf->OUTPUT_ENCODING_NAME.string
              /* not sure if strcasecmp is needed or not */
-             && !strcasecmp (self->conf->OUTPUT_ENCODING_NAME, "utf-8"))
+             && !strcasecmp (self->conf->OUTPUT_ENCODING_NAME.string, "utf-8"))
            self->use_unicode_text = 1;
 
          html_prepare_conversion_units (self,
diff --git a/tp/Texinfo/XS/convert/convert_html.c 
b/tp/Texinfo/XS/convert/convert_html.c
index e89ff1da9c..8fdf9a3ada 100644
--- a/tp/Texinfo/XS/convert/convert_html.c
+++ b/tp/Texinfo/XS/convert/convert_html.c
@@ -367,8 +367,8 @@ html_get_tree_root_element (CONVERTER *self, const ELEMENT 
*command,
                 }
             }
           else if (data_cmd == CM_titlepage
-                   && self->conf->USE_TITLEPAGE_FOR_TITLE > 0
-                   && self->conf->SHOW_TITLE > 0
+                   && self->conf->USE_TITLEPAGE_FOR_TITLE.integer > 0
+                   && self->conf->SHOW_TITLE.integer > 0
                    && output_units->number > 0)
             {
               ROOT_AND_UNIT *result = malloc (sizeof (ROOT_AND_UNIT));
@@ -441,7 +441,7 @@ get_element_root_command_element (CONVERTER *self, const 
ELEMENT *command)
   if (root_unit && root_unit->root)
     {
       const ELEMENT *root_command = root_unit->root;
-      if (self->conf->USE_NODES > 0)
+      if (self->conf->USE_NODES.integer > 0)
         {
           if (root_command->cmd != CM_node)
             {
@@ -575,8 +575,8 @@ html_translate_string (CONVERTER *self, const char *string,
       const char *lang = in_lang;
       char *translated_string;
 
-      if (!lang && self->conf->documentlanguage)
-        lang = self->conf->documentlanguage;
+      if (!lang && self->conf->documentlanguage.string)
+        lang = self->conf->documentlanguage.string;
 
       translated_string
        = format_translate_message(self, string, lang, translation_context);
@@ -1450,16 +1450,15 @@ prepare_special_units (CONVERTER *self, int 
output_units_descriptor,
         {
           int contents_set = 0;
           enum command_id cmd = contents_cmds[i];
-          COMMAND_OPTION_REF *contents_option_ref
-             = get_command_option (self->conf, cmd);
-          if (*(contents_option_ref->int_ref) > 0)
+          OPTION *contents_option_ref = get_command_option (self->conf, cmd);
+          if (contents_option_ref->integer > 0)
             contents_set = 1;
-          free (contents_option_ref);
           if (contents_set)
             {
               int j;
               char *special_unit_variety = 0;
-              char *contents_location = self->conf->CONTENTS_OUTPUT_LOCATION;
+              char *contents_location
+                = self->conf->CONTENTS_OUTPUT_LOCATION.string;
 
               for (j = 0; command_special_unit_variety[j].cmd; j++)
                 {
@@ -1535,15 +1534,15 @@ prepare_special_units (CONVERTER *self, int 
output_units_descriptor,
     }
 
   if (self->document->global_commands->footnotes.number > 0
-      && !strcmp(self->conf->footnotestyle, "separate")
+      && !strcmp(self->conf->footnotestyle.string, "separate")
       && output_units && output_units->number > 1)
     add_string ("footnotes", do_special);
 
-  if ((self->conf->DO_ABOUT < 0
+  if ((self->conf->DO_ABOUT.integer < 0
        && output_units && output_units->number > 1
-       && ((self->conf->SPLIT && strlen (self->conf->SPLIT))
-           || self->conf->HEADERS > 0))
-      || self->conf->DO_ABOUT > 0)
+       && ((self->conf->SPLIT.string && strlen (self->conf->SPLIT.string))
+           || self->conf->HEADERS.integer > 0))
+      || self->conf->DO_ABOUT.integer > 0)
     add_string ("about", do_special);
 
   special_units_order = (SPECIAL_UNIT_ORDER *)
@@ -1681,7 +1680,7 @@ html_prepare_conversion_units (CONVERTER *self,
 {
   int output_units_descriptor;
 
-  if (self->conf->USE_NODES > 0)
+  if (self->conf->USE_NODES.integer > 0)
     output_units_descriptor = split_by_node (self->document->tree);
   else
     output_units_descriptor = split_by_section (self->document->tree);
@@ -1722,8 +1721,8 @@ set_special_units_targets_files (CONVERTER *self, int 
special_units_descriptor,
     = retrieve_output_units (special_units_descriptor);
 
   char *extension = "";
-  if (self->conf->EXTENSION)
-    extension = self->conf->EXTENSION;
+  if (self->conf->EXTENSION.string)
+    extension = self->conf->EXTENSION.string;
 
   for (i = 0; i < special_units->number; i++)
     {
@@ -1740,8 +1739,8 @@ set_special_units_targets_files (CONVERTER *self, int 
special_units_descriptor,
       if (!target)
         continue;
 
-      if (((self->conf->SPLIT && strlen (self->conf->SPLIT))
-           || self->conf->MONOLITHIC <= 0)
+      if (((self->conf->SPLIT.string && strlen (self->conf->SPLIT.string))
+           || self->conf->MONOLITHIC.string <= 0)
     /* in general document_name not defined means called through convert */
           && document_name)
         {
@@ -1779,7 +1778,7 @@ set_special_units_targets_files (CONVERTER *self, int 
special_units_descriptor,
       else
         filename = default_filename;
 
-      if (self->conf->DEBUG > 0)
+      if (self->conf->DEBUG.integer > 0)
         {
           char *fileout = filename;
           if (!fileout)
@@ -1835,7 +1834,7 @@ prepare_associated_special_units_targets (CONVERTER *self,
                 filename = target_filename->filename;
             }
 
-          if (self->conf->DEBUG > 0)
+          if (self->conf->DEBUG.integer > 0)
             {
               char *str_filename;
               char *str_target;
@@ -2020,7 +2019,7 @@ new_sectioning_command_target (CONVERTER *self, const 
ELEMENT *command)
       free (target_contents_filename);
     }
 
-  if (self->conf->DEBUG > 0)
+  if (self->conf->DEBUG.integer > 0)
     {
       const char *command_name = element_command_name (command);
       fprintf (stderr, "XS|Register %s %s\n", command_name, target);
@@ -2072,8 +2071,8 @@ set_root_commands_targets_node_files (CONVERTER *self)
     {
       char *extension = 0;
 
-      if (self->conf->EXTENSION)
-        extension = self->conf->EXTENSION;
+      if (self->conf->EXTENSION.string)
+        extension = self->conf->EXTENSION.string;
       LABEL_LIST *label_targets = self->document->identifiers_target;
       int i;
       for (i = 0; i < label_targets->number; i++)
@@ -2112,13 +2111,13 @@ set_root_commands_targets_node_files (CONVERTER *self)
             }
           else if (called)
             {
-              if (self->conf->VERBOSE > 0)
+              if (self->conf->VERBOSE.integer > 0)
                 {
                   message_list_document_warn (&self->error_messages, 
self->conf,
                              "user-defined node file name not set for `%s'",
                              node_filename);
                 }
-              else if (self->conf->DEBUG > 0)
+              else if (self->conf->DEBUG.integer > 0)
                 {
                   fprintf (stderr,
                      "user-defined node file name undef for `%s'\n",
@@ -2126,7 +2125,7 @@ set_root_commands_targets_node_files (CONVERTER *self)
                 }
             }
 
-          if (self->conf->DEBUG > 0)
+          if (self->conf->DEBUG.integer > 0)
             {
               const char *command_name = element_command_name (target_element);
               fprintf (stderr, "Label @%s %s, %s\n", command_name, target,
@@ -2469,11 +2468,11 @@ html_css_string_convert_text (CONVERTER *self, const 
enum element_type type,
         OTXI_CONVERT_TEXT("-`'" additional_delim, \
           OTXI_UNICODE_TEXT_CASES(p) \
           other_cases) \
-      else if (self->conf->USE_NUMERIC_ENTITY > 0) \
+      else if (self->conf->USE_NUMERIC_ENTITY.integer > 0) \
         OTXI_CONVERT_TEXT("-`'" additional_delim, \
           OTXI_NUMERIC_ENTITY_TEXT_CASES(p) \
           other_cases) \
-      else if (self->conf->USE_ISO > 0) \
+      else if (self->conf->USE_ISO.integer > 0) \
         OTXI_CONVERT_TEXT("-`'" additional_delim, \
           OTXI_ISO_ENTITY_TEXT_CASES(p) \
           other_cases) \
@@ -2792,7 +2791,7 @@ convert_tree_new_formatting_context (CONVERTER *self, 
const ELEMENT *tree,
       multiple_pass_str = "|M";
     }
 
-  if (self->conf->DEBUG > 0)
+  if (self->conf->DEBUG.integer > 0)
     fprintf (stderr, "XS|new_fmt_ctx %s%s\n", context_string_str.text,
                                            multiple_pass_str);
 
@@ -3051,15 +3050,15 @@ external_node_href (CONVERTER *self, const ELEMENT 
*external_node,
     normalized_label_id_file (self, normalized, node_contents);
 
   /* undef if conversion is called through convert() */
-  if (self->conf->EXTERNAL_CROSSREF_SPLIT
-      && strlen (self->conf->EXTERNAL_CROSSREF_SPLIT))
+  if (self->conf->EXTERNAL_CROSSREF_SPLIT.string
+      && strlen (self->conf->EXTERNAL_CROSSREF_SPLIT.string))
     /* initialize to EXTERNAL_CROSSREF_SPLIT */
     target_split = 1;
 
-  if (self->conf->EXTERNAL_CROSSREF_EXTENSION)
-    extension = self->conf->EXTERNAL_CROSSREF_EXTENSION;
-  else if (self->conf->EXTENSION)
-    extension = self->conf->EXTENSION;
+  if (self->conf->EXTERNAL_CROSSREF_EXTENSION.string)
+    extension = self->conf->EXTERNAL_CROSSREF_EXTENSION.string;
+  else if (self->conf->EXTENSION.string)
+    extension = self->conf->EXTENSION.string;
 
   /* both to be freed before return */
   target = target_filename->target;
@@ -3084,9 +3083,9 @@ external_node_href (CONVERTER *self, const ELEMENT 
*external_node,
 
       free (text_conv_options);
 
-      if (self->conf->IGNORE_REF_TO_TOP_NODE_UP > 0 && !strlen (target))
+      if (self->conf->IGNORE_REF_TO_TOP_NODE_UP.integer > 0 && !strlen 
(target))
         {
-          char *top_node_up = self->conf->TOP_NODE_UP;
+          char *top_node_up = self->conf->TOP_NODE_UP.string;
           if (top_node_up)
             {
               char *parentheses_manual_name;
@@ -3151,7 +3150,7 @@ external_node_href (CONVERTER *self, const ELEMENT 
*external_node,
         }
       else
         { /* nothing specified for that manual, use default */
-          if (self->conf->CHECK_HTMLXREF > 0)
+          if (self->conf->CHECK_HTMLXREF.integer > 0)
             {
               if ((source_command != 0) &&
                   (source_command->source_info.line_nr != 0))
@@ -3193,12 +3192,13 @@ external_node_href (CONVERTER *self, const ELEMENT 
*external_node,
               char *url_encoded_path;
               text_init (&dir_path);
 
-              if (self->conf->EXTERNAL_DIR)
+              if (self->conf->EXTERNAL_DIR.string)
                 {
-                  text_printf (&dir_path, "%s/%s", self->conf->EXTERNAL_DIR,
-                                           manual_base);
+                  text_printf (&dir_path, "%s/%s",
+                               self->conf->EXTERNAL_DIR.string, manual_base);
                 }
-              else if (self->conf->SPLIT && strlen (self->conf->SPLIT))
+              else if (self->conf->SPLIT.string
+                       && strlen (self->conf->SPLIT.string))
                 {
                   text_append_n (&dir_path, "../", 3);
                   text_append (&dir_path, manual_base);
@@ -3226,12 +3226,13 @@ external_node_href (CONVERTER *self, const ELEMENT 
*external_node,
               TEXT file_path;
               text_init (&file_path);
 
-              if (self->conf->EXTERNAL_DIR)
+              if (self->conf->EXTERNAL_DIR.string)
                 {
-                  text_printf (&file_path, "%s/%s", self->conf->EXTERNAL_DIR,
-                                           manual_base);
+                  text_printf (&file_path, "%s/%s",
+                               self->conf->EXTERNAL_DIR.string, manual_base);
                 }
-              else if (self->conf->SPLIT && strlen (self->conf->SPLIT))
+              else if (self->conf->SPLIT.string
+                       && strlen (self->conf->SPLIT.string))
                 {
                   text_append_n (&file_path, "../", 3);
                   text_append (&file_path, manual_base);
@@ -3257,9 +3258,9 @@ external_node_href (CONVERTER *self, const ELEMENT 
*external_node,
       TARGET_DIRECTORY_FILENAME *target_dir_filename;
 
       if ((!strcmp (target, "Top") || !strlen (target))
-          && self->conf->TOP_NODE_FILE_TARGET)
+          && self->conf->TOP_NODE_FILE_TARGET.string)
         {
-          file_name = strdup (self->conf->TOP_NODE_FILE_TARGET);
+          file_name = strdup (self->conf->TOP_NODE_FILE_TARGET.string);
         }
       else
         {
@@ -3809,7 +3810,7 @@ html_internal_command_tree (CONVERTER *self, const 
ELEMENT *command,
             {
               char *section_number
                 = lookup_extra_string (command, "section_number");
-              if (section_number && !self->conf->NUMBER_SECTIONS == 0)
+              if (section_number && !self->conf->NUMBER_SECTIONS.integer == 0)
                 {
                   NAMED_STRING_ELEMENT_LIST *replaced_substrings
                     = new_named_string_element_list ();
@@ -4074,14 +4075,14 @@ from_element_direction (CONVERTER *self, int direction,
        = self->global_units_directions
            [D_direction_Last + direction - NON_SPECIAL_DIRECTIONS_NR +1];
   else if ((!source_unit || unit_is_top_output_unit (self, source_unit))
-           && self->conf->TOP_NODE_UP_URL
+           && self->conf->TOP_NODE_UP_URL.string
            && (direction == D_direction_Up || direction == D_direction_NodeUp))
     {
       if (type == HTT_href)
-        return strdup (self->conf->TOP_NODE_UP_URL);
+        return strdup (self->conf->TOP_NODE_UP_URL.string);
       else if (type == HTT_text || type == HTT_node
                || type == HTT_string || type == HTT_section)
-        return strdup (self->conf->TOP_NODE_UP);
+        return strdup (self->conf->TOP_NODE_UP.string);
       else
         {
           char *msg;
@@ -4345,7 +4346,7 @@ html_get_css_elements_classes (CONVERTER *self, const 
char *filename)
 void
 close_html_lone_element (CONVERTER *self, TEXT *result)
 {
-  if (self->conf->USE_XML_SYNTAX > 0)
+  if (self->conf->USE_XML_SYNTAX.integer > 0)
     text_append_n (result, "/>", 2);
   else
     text_append_n (result, ">", 1);
@@ -4395,7 +4396,7 @@ html_attribute_class (CONVERTER *self, const char 
*element,
   int i;
   int class_nr = 0;
   if (!classes  || classes->number <= 0
-      || self->conf->NO_CSS > 0)
+      || self->conf->NO_CSS.integer > 0)
     {
       if (!strcmp (element, "span"))
         return strdup ("");
@@ -4407,7 +4408,7 @@ html_attribute_class (CONVERTER *self, const char 
*element,
         }
     }
 
-  if (self->conf->INLINE_CSS_STYLE > 0)
+  if (self->conf->INLINE_CSS_STYLE.integer > 0)
     {
       int i;
       TEXT inline_styles;
@@ -4480,7 +4481,7 @@ static const STRING_LIST copiable_link_classes = 
{copiable_link_array, 1, 1};
 static char *
 get_copiable_anchor (CONVERTER *self, const char *id)
 {
-  if (id && strlen (id) && self->conf->COPIABLE_LINKS > 0)
+  if (id && strlen (id) && self->conf->COPIABLE_LINKS.integer > 0)
     {
       TEXT result;
       char *attribute_class = html_attribute_class (self, "a",
@@ -4581,7 +4582,7 @@ prepare_index_entries_targets (CONVERTER *self)
                     }
                   normalized_index
                     = normalize_transliterate_texinfo (normalize_index_element,
-                                                       (self->conf->TEST > 0));
+                                                (self->conf->TEST.integer > 
0));
 
                   destroy_element (normalize_index_element);
                   if (subentries_tree)
@@ -4696,7 +4697,7 @@ prepare_footnotes_targets (CONVERTER *self)
           add_special_target (self, ST_footnote_location, footnote,
                               docid.text);
 
-          if (self->conf->DEBUG > 0)
+          if (self->conf->DEBUG.integer > 0)
             {
               char *footnote_txi = convert_to_texinfo (footnote);
               fprintf (stderr, "Enter footnote: target %s, nr %d\n%s\n",
@@ -4884,7 +4885,7 @@ html_prepare_output_units_global_targets (CONVERTER *self,
       free (root_unit);
     }
 
-  if (self->conf->DEBUG > 0)
+  if (self->conf->DEBUG.integer > 0)
     {
       int i;
       fprintf (stderr, "GLOBAL DIRECTIONS:\n");
@@ -5050,7 +5051,7 @@ html_set_pages_files (CONVERTER *self, OUTPUT_UNIT_LIST 
*output_units,
   memset (unit_file_name_paths, 0,
           output_units->number * sizeof (char *));
 
-  if (!self->conf->SPLIT || !strlen (self->conf->SPLIT))
+  if (!self->conf->SPLIT.string || !strlen (self->conf->SPLIT.string))
     {
       int i;
       add_to_files_source_info (files_source_info, output_filename,
@@ -5093,8 +5094,8 @@ html_set_pages_files (CONVERTER *self, OUTPUT_UNIT_LIST 
*output_units,
                                        node_top_output_unit);
         }
 
-      if (self->conf->EXTENSION && strlen (self->conf->EXTENSION))
-        extension = self->conf->EXTENSION;
+      if (self->conf->EXTENSION.string && strlen 
(self->conf->EXTENSION.string))
+        extension = self->conf->EXTENSION.string;
 
       for (i = 0; i < output_units->number; i++)
         {
@@ -5367,7 +5368,7 @@ html_set_pages_files (CONVERTER *self, OUTPUT_UNIT_LIST 
*output_units,
         = set_output_unit_file (self, output_unit, filename, 1);
       self->output_unit_file_indices[i] = output_unit_file_idx;
       output_unit_file = &self->output_unit_files.list[output_unit_file_idx];
-      if (self->conf->DEBUG > 0)
+      if (self->conf->DEBUG.integer > 0)
         fprintf (stderr, "Page %s: %s(%d)\n",
                  output_unit_texi (output_unit),
                  output_unit->unit_filename, output_unit_file->counter);
@@ -5422,7 +5423,7 @@ html_set_pages_files (CONVERTER *self, OUTPUT_UNIT_LIST 
*output_units,
           self->special_unit_file_indices[i] = special_unit_file_idx;
           special_unit_file
              = &self->output_unit_files.list[special_unit_file_idx];
-          if (self->conf->DEBUG > 0)
+          if (self->conf->DEBUG.integer > 0)
             fprintf (stderr, "Special page: %s(%d)\n", filename,
                              special_unit_file->counter);
         }
@@ -5550,7 +5551,7 @@ html_prepare_units_directions_files (CONVERTER *self,
                                              special_units_descriptor,
                                        associated_special_units_descriptor);
 
-  split_pages (output_units, self->conf->SPLIT);
+  split_pages (output_units, self->conf->SPLIT.string);
 
   if (strlen (output_file))
     {
@@ -5695,7 +5696,7 @@ format_separate_anchor (CONVERTER *self, const char *id,
 static void
 direction_href_attributes (CONVERTER *self, int direction, TEXT *result)
 {
-  if (self->conf->USE_ACCESSKEY > 0)
+  if (self->conf->USE_ACCESSKEY.integer > 0)
     {
       char *accesskey
         = direction_string (self, direction, TDS_type_accesskey,
@@ -5704,7 +5705,7 @@ direction_href_attributes (CONVERTER *self, int 
direction, TEXT *result)
         text_printf (result, " accesskey=\"%s\"", accesskey);
     }
 
-  if (self->conf->USE_REL_REV)
+  if (self->conf->USE_REL_REV.integer)
     {
       char *button_rel
         = direction_string (self, direction, TDS_type_rel,
@@ -5754,8 +5755,8 @@ html_default_format_heading_text (CONVERTER *self, const 
enum command_id cmd,
 
   if (level < 1)
     heading_level = 1;
-  else if (level > self->conf->MAX_HEADER_LEVEL)
-    heading_level = self->conf->MAX_HEADER_LEVEL;
+  else if (level > self->conf->MAX_HEADER_LEVEL.integer)
+    heading_level = self->conf->MAX_HEADER_LEVEL.integer;
 
   xasprintf (&heading_html_element, "h%d", heading_level);
 
@@ -5797,10 +5798,10 @@ html_default_format_heading_text (CONVERTER *self, 
const enum command_id cmd,
   text_printf (result, "</h%d>", heading_level);
   if (cmd != CM_titlefont)
     text_append_n (result, "\n", 1);
-  if (cmd == CM_part && self->conf->DEFAULT_RULE
-      && strlen (self->conf->DEFAULT_RULE))
+  if (cmd == CM_part && self->conf->DEFAULT_RULE.string
+      && strlen (self->conf->DEFAULT_RULE.string))
     {
-      text_append (result, self->conf->DEFAULT_RULE);
+      text_append (result, self->conf->DEFAULT_RULE.string);
       text_append_n (result, "\n", 1);
     }
 }
@@ -5865,8 +5866,8 @@ html_default_format_contents (CONVERTER *self, const enum 
command_id cmd,
    fprintf(stderr, "ROOT_LEVEL Max: %d, Min: %d\n", max_root_level, 
min_root_level);
    */
 
-  if ((is_contents && !self->conf->BEFORE_TOC_LINES)
-      || (!is_contents && !self->conf->BEFORE_SHORT_TOC_LINES))
+  if ((is_contents && !self->conf->BEFORE_TOC_LINES.string)
+      || (!is_contents && !self->conf->BEFORE_SHORT_TOC_LINES.string))
     {
       STRING_LIST *classes;
       char *attribute_class;
@@ -5881,11 +5882,11 @@ html_default_format_contents (CONVERTER *self, const 
enum command_id cmd,
       text_append_n (&result, ">\n", 2);
     }
   else if (is_contents)
-    text_append (&result, self->conf->BEFORE_TOC_LINES);
+    text_append (&result, self->conf->BEFORE_TOC_LINES.string);
   else
-    text_append (&result, self->conf->BEFORE_SHORT_TOC_LINES);
+    text_append (&result, self->conf->BEFORE_SHORT_TOC_LINES.string);
 
-  if (self->conf->NUMBER_SECTIONS > 0)
+  if (self->conf->NUMBER_SECTIONS.integer > 0)
     toc_ul_classes = &toc_numbered_mark_classes;
   if (root_children->number > 1)
     {
@@ -5897,9 +5898,10 @@ html_default_format_contents (CONVERTER *self, const 
enum command_id cmd,
       has_toplevel_contents = 1;
     }
 
-  link_to_toc = (!is_contents && self->conf->SHORT_TOC_LINK_TO_TOC > 0
-                 && self->conf->contents > 0
-                 && (strcmp (self->conf->CONTENTS_OUTPUT_LOCATION, "inline")
+  link_to_toc = (!is_contents && self->conf->SHORT_TOC_LINK_TO_TOC.integer > 0
+                 && self->conf->contents.integer > 0
+                 && (strcmp
+                    (self->conf->CONTENTS_OUTPUT_LOCATION.string, "inline")
                || self->document->global_commands->contents.number > 0
                || self->document->global_commands->shortcontents.number > 0));
 
@@ -6058,13 +6060,13 @@ html_default_format_contents (CONVERTER *self, const 
enum command_id cmd,
   if (root_children->number > 1)
     text_append_n (&result, "\n</ul>", 6);
 
-  if ((is_contents && !self->conf->AFTER_TOC_LINES)
-      || (!is_contents && !self->conf->AFTER_SHORT_TOC_LINES))
+  if ((is_contents && !self->conf->AFTER_TOC_LINES.string)
+      || (!is_contents && !self->conf->AFTER_SHORT_TOC_LINES.string))
     text_append_n (&result, "\n</div>\n", 8);
   else if (is_contents)
-    text_append (&result, self->conf->AFTER_TOC_LINES);
+    text_append (&result, self->conf->AFTER_TOC_LINES.string);
   else
-    text_append (&result, self->conf->AFTER_SHORT_TOC_LINES);
+    text_append (&result, self->conf->AFTER_SHORT_TOC_LINES.string);
 
   return result.text;
 }
@@ -6147,16 +6149,16 @@ void
 html_default_format_program_string (CONVERTER *self, TEXT *result)
 {
   ELEMENT *tree;
-  if (self->conf->PROGRAM && strlen (self->conf->PROGRAM)
-      && self->conf->PACKAGE_URL_OPTION)
+  if (self->conf->PROGRAM.string && strlen (self->conf->PROGRAM.string)
+      && self->conf->PACKAGE_URL_OPTION.string)
     {
       ELEMENT *program_homepage = new_element (ET_NONE);
       ELEMENT *program = new_element (ET_NONE);
       NAMED_STRING_ELEMENT_LIST *substrings
                                    = new_named_string_element_list ();
 
-      text_append (&program_homepage->text, self->conf->PACKAGE_URL_OPTION);
-      text_append (&program->text, self->conf->PROGRAM);
+      text_append (&program_homepage->text, 
self->conf->PACKAGE_URL_OPTION.string);
+      text_append (&program->text, self->conf->PROGRAM.string);
 
       add_element_to_named_string_element_list (substrings,
                                     "program_homepage", program_homepage);
@@ -6216,7 +6218,7 @@ html_default_format_end_file (CONVERTER *self, const char 
*filename,
   text_init (&result);
   text_append (&result, "");
 
-  if (self->conf->PROGRAM_NAME_IN_FOOTER > 0)
+  if (self->conf->PROGRAM_NAME_IN_FOOTER.integer > 0)
     {
       char *open;
       size_t open_len;
@@ -6238,8 +6240,8 @@ html_default_format_end_file (CONVERTER *self, const char 
*filename,
     }
   text_append_n (&result, "\n\n", 2);
 
-  if (self->conf->PRE_BODY_CLOSE)
-    text_append (&result, self->conf->PRE_BODY_CLOSE);
+  if (self->conf->PRE_BODY_CLOSE.string)
+    text_append (&result, self->conf->PRE_BODY_CLOSE.string);
 
   if (self->jslicenses.number)
     {
@@ -6259,17 +6261,19 @@ html_default_format_end_file (CONVERTER *self, const 
char *filename,
       if (infojs_jslicenses_file_nr > 0
           || ((html_get_file_information (self, "mathjax",
                                           filename, &status) > 0
-               || (!self->conf->SPLIT || !strlen (self->conf->SPLIT)))
+               || (!self->conf->SPLIT.string
+                   || !strlen (self->conf->SPLIT.string)))
               && mathjax_jslicenses_file_nr > 0))
         {
-          if (self->conf->JS_WEBLABELS_FILE
-              && (self->conf->JS_WEBLABELS
-                  && (!strcmp (self->conf->JS_WEBLABELS, "generate")
-                      || !strcmp (self->conf->JS_WEBLABELS, "reference"))))
+          if (self->conf->JS_WEBLABELS_FILE.string
+              && (self->conf->JS_WEBLABELS.string
+                  && (!strcmp (self->conf->JS_WEBLABELS.string, "generate")
+                      || !strcmp (self->conf->JS_WEBLABELS.string,
+                                  "reference"))))
             {
               ELEMENT *tree;
               char *js_path = url_protect_url_text (self,
-                                          self->conf->JS_WEBLABELS_FILE);
+                                          
self->conf->JS_WEBLABELS_FILE.string);
               text_append_n (&result, "<a href=\"", 9);
               text_append (&result, js_path);
               free (js_path);
@@ -6379,11 +6383,12 @@ format_css_lines (CONVERTER *self, const char 
*filename, TEXT *result)
 
 static char *root_html_element_attributes_string (CONVERTER *self)
 {
-  if (self->conf->HTML_ROOT_ELEMENT_ATTRIBUTES
-      && strlen (self->conf->HTML_ROOT_ELEMENT_ATTRIBUTES))
+  if (self->conf->HTML_ROOT_ELEMENT_ATTRIBUTES.string
+      && strlen (self->conf->HTML_ROOT_ELEMENT_ATTRIBUTES.string))
     {
       char *result;
-      xasprintf (&result, " %s", self->conf->HTML_ROOT_ELEMENT_ATTRIBUTES);
+      xasprintf (&result, " %s",
+                 self->conf->HTML_ROOT_ELEMENT_ATTRIBUTES.string);
       return result;
     }
   return 0;
@@ -6421,7 +6426,7 @@ file_header_information (CONVERTER *self, ELEMENT 
*command,
           ELEMENT *title_tree;
           ELEMENT *command_tree = 0;
 
-          if (self->conf->SECTION_NAME_IN_TITLE > 0)
+          if (self->conf->SECTION_NAME_IN_TITLE.integer > 0)
             {
               ELEMENT *associated_section
                 = lookup_extra_element (command, "associated_section");
@@ -6479,12 +6484,12 @@ file_header_information (CONVERTER *self, ELEMENT 
*command,
     }
 
   text_reset (&text);
-  if (self->conf->OUTPUT_ENCODING_NAME
-      && strlen (self->conf->OUTPUT_ENCODING_NAME))
+  if (self->conf->OUTPUT_ENCODING_NAME.string
+      && strlen (self->conf->OUTPUT_ENCODING_NAME.string))
     {
       text_printf (&text,
         "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\"",
-                   self->conf->OUTPUT_ENCODING_NAME);
+                   self->conf->OUTPUT_ENCODING_NAME.string);
       close_html_lone_element (self, &text);
       begin_info->encoding = strdup (text.text);
     }
@@ -6503,8 +6508,9 @@ file_header_information (CONVERTER *self, ELEMENT 
*command,
     begin_info->root_html_element_attributes = strdup ("");
 
   text_reset (&text);
-  text_append (&text, self->conf->BODYTEXT);
-  if (self->conf->HTML_MATH && !strcmp (self->conf->HTML_MATH, "mathjax")
+  text_append (&text, self->conf->BODYTEXT.string);
+  if (self->conf->HTML_MATH.string
+      && !strcmp (self->conf->HTML_MATH.string, "mathjax")
       && html_get_file_information (self, "mathjax", filename, &status) > 0)
     {
       text_append_n (&text, " class=\"tex2jax_ignore\"", 23);
@@ -6513,21 +6519,21 @@ file_header_information (CONVERTER *self, ELEMENT 
*command,
   begin_info->bodytext = strdup (text.text);
 
   text_reset (&text);
-  if (self->conf->PROGRAM && strlen (self->conf->PROGRAM))
+  if (self->conf->PROGRAM.string && strlen (self->conf->PROGRAM.string))
     {
       text_printf (&text, "<meta name=\"Generator\" content=\"%s\"",
-                   self->conf->PROGRAM);
+                   self->conf->PROGRAM.string);
       close_html_lone_element (self, &text);
       text_append_n (&text, "\n", 1);
       begin_info->generator = strdup (text.text);
       text_reset (&text);
     }
 
-  if (self->conf->EXTRA_HEAD)
-    text_append (&text, self->conf->EXTRA_HEAD);
-  if (self->conf->INFO_JS_DIR)
+  if (self->conf->EXTRA_HEAD.string)
+    text_append (&text, self->conf->EXTRA_HEAD.string);
+  if (self->conf->INFO_JS_DIR.string)
     {
-      if (!self->conf->SPLIT || !strlen (self->conf->SPLIT))
+      if (!self->conf->SPLIT.string || !strlen (self->conf->SPLIT.string))
         {
           message_list_document_error (&self->error_messages, self->conf,
                      "%s not meaningful for non-split output", "INFO_JS_DIR");
@@ -6536,12 +6542,12 @@ file_header_information (CONVERTER *self, ELEMENT 
*command,
         {
           char *jsdir;
           char *protected_jsdir;
-          if (!strcmp (self->conf->INFO_JS_DIR, "."))
+          if (!strcmp (self->conf->INFO_JS_DIR.string, "."))
             jsdir = strdup ("");
           else
             {
               size_t len;
-              jsdir = strdup (self->conf->INFO_JS_DIR);
+              jsdir = strdup (self->conf->INFO_JS_DIR.string);
               len = strlen (jsdir);
               if (len > 0)
                 {
@@ -6576,12 +6582,13 @@ file_header_information (CONVERTER *self, ELEMENT 
*command,
           free (protected_jsdir);
         }
     }
-  if (self->conf->HTML_MATH && !strcmp (self->conf->HTML_MATH, "mathjax")
+  if (self->conf->HTML_MATH.string
+      && !strcmp (self->conf->HTML_MATH.string, "mathjax")
       && (html_get_file_information (self, "mathjax", filename, &status) > 0
-          || (self->conf->SPLIT && strlen (self->conf->SPLIT))))
+          || (self->conf->SPLIT.string && strlen (self->conf->SPLIT.string))))
     {
       char *mathjax_script = url_protect_url_text (self,
-                                    self->conf->MATHJAX_SCRIPT);
+                                self->conf->MATHJAX_SCRIPT.string);
       text_printf (&text, "<script type='text/javascript'>\n"
 "MathJax = {\n"
 "  options: {\n"
@@ -6604,10 +6611,11 @@ get_links (CONVERTER* self, const char *filename,
            const OUTPUT_UNIT *output_unit,
            const ELEMENT *node_command, TEXT *result)
 {
-  if (self->conf->USE_LINKS > 0)
+  if (self->conf->USE_LINKS.integer > 0)
     {
       int i;
-      BUTTON_SPECIFICATION_LIST *link_buttons = self->conf->LINKS_BUTTONS;
+      BUTTON_SPECIFICATION_LIST *link_buttons
+          = self->conf->LINKS_BUTTONS.buttons;
       for (i = 0; i < link_buttons->number; i++)
         {
           const BUTTON_SPECIFICATION *link = &link_buttons->list[i];
@@ -6664,7 +6672,8 @@ html_default_format_begin_file (CONVERTER *self, const 
char *filename,
       if (!node_command)
         node_command = element_command;
 
-      if (self->conf->SPLIT && strlen (self->conf->SPLIT) && element_command)
+      if (self->conf->SPLIT.string && strlen (self->conf->SPLIT.string)
+          && element_command)
         command_for_title = element_command;
     }
 
@@ -6672,12 +6681,12 @@ html_default_format_begin_file (CONVERTER *self, const 
char *filename,
 
   text_init (&result);
 
-  text_append (&result, self->conf->DOCTYPE);
+  text_append (&result, self->conf->DOCTYPE.string);
   text_append_n (&result, "\n", 1);
   text_printf (&result, "<html%s>\n", 
begin_info->root_html_element_attributes);
   text_printf (&result, "<!-- Created by %s, %s -->\n<head>\n",
-                        self->conf->PACKAGE_AND_VERSION_OPTION,
-                        self->conf->PACKAGE_URL_OPTION);
+                        self->conf->PACKAGE_AND_VERSION_OPTION.string,
+                        self->conf->PACKAGE_URL_OPTION.string);
   if (begin_info->encoding)
     text_append (&result, begin_info->encoding);
   text_append_n (&result, "\n", 1);
@@ -6714,8 +6723,8 @@ html_default_format_begin_file (CONVERTER *self, const 
char *filename,
     text_append (&result, begin_info->extra_head);
   text_append_n (&result, "\n</head>\n\n", 10);
   text_printf (&result, "<body %s>\n", begin_info->bodytext);
-  if (self->conf->AFTER_BODY_OPEN)
-    text_append (&result, self->conf->AFTER_BODY_OPEN);
+  if (self->conf->AFTER_BODY_OPEN.string)
+    text_append (&result, self->conf->AFTER_BODY_OPEN.string);
 
   destroy_begin_file_information (begin_info);
 
@@ -6812,9 +6821,9 @@ default_panel_button_dynamic_direction_internal 
(CONVERTER *self,
 
   formatted_button->need_delimiter = 1;
 
-  if (self->conf->USE_NODE_DIRECTIONS > 0
-      || (self->conf->USE_NODE_DIRECTIONS < 0
-          && self->conf->USE_NODES > 0))
+  if (self->conf->USE_NODE_DIRECTIONS.integer > 0
+      || (self->conf->USE_NODE_DIRECTIONS.integer < 0
+          && self->conf->USE_NODES.integer > 0))
     direction += NODE_DIRECTIONS_OFFSET;
 
   if (use_first_element_in_file_directions)
@@ -6822,7 +6831,7 @@ default_panel_button_dynamic_direction_internal 
(CONVERTER *self,
 
   href = from_element_direction (self, direction, HTT_href, 0, 0, element);
 
-  if (!strcmp (self->conf->xrefautomaticsectiontitle, "on"))
+  if (!strcmp (self->conf->xrefautomaticsectiontitle.string, "on"))
     node = from_element_direction (self, direction, HTT_section, 0, 0, 0);
 
   if (!node)
@@ -6986,16 +6995,18 @@ html_default_format_button (CONVERTER *self,
       else if (button->direction == D_direction_Space)
         {
           /* handle space button */
-          if (self->conf->ICONS > 0 && self->conf->ACTIVE_ICONS.number > 0
-              && self->conf->ACTIVE_ICONS.list[button->direction]
-              && strlen (self->conf->ACTIVE_ICONS.list[button->direction]))
+          if (self->conf->ICONS.integer > 0
+              && self->conf->ACTIVE_ICONS.icons->number > 0
+              && self->conf->ACTIVE_ICONS.icons->list[button->direction]
+              && strlen
+                  (self->conf->ACTIVE_ICONS.icons->list[button->direction]))
             {
               char *button_name_string = direction_string (self,
                                      button->direction, TDS_type_button,
                                                       TDS_context_string);
               formatted_button->active
                 = format_button_icon_img (self, button_name_string,
-                       self->conf->ACTIVE_ICONS.list[button->direction], 0);
+                   self->conf->ACTIVE_ICONS.icons->list[button->direction], 0);
             }
           else
             {
@@ -7016,10 +7027,13 @@ html_default_format_button (CONVERTER *self,
               char *description = direction_string (self, button->direction,
                                    TDS_type_description, TDS_context_string);
 
-              if (self->conf->ICONS > 0 && self->conf->ACTIVE_ICONS.number > 0
-                  && self->conf->ACTIVE_ICONS.list[button->direction]
-                  && strlen (self->conf->ACTIVE_ICONS.list[button->direction]))
-                active_icon = self->conf->ACTIVE_ICONS.list[button->direction];
+              if (self->conf->ICONS.integer > 0
+                  && self->conf->ACTIVE_ICONS.icons->number > 0
+                  && self->conf->ACTIVE_ICONS.icons->list[button->direction]
+                  && strlen (self->conf->ACTIVE_ICONS.icons
+                                                ->list[button->direction]))
+                active_icon = self->conf->ACTIVE_ICONS.icons
+                                                  ->list[button->direction];
 
               text_init (&active_text);
               if (!active_icon)
@@ -7027,14 +7041,14 @@ html_default_format_button (CONVERTER *self,
               text_printf (&active_text, "<a href=\"%s\"", href);
               if (description)
                 text_printf (&active_text, " title=\"%s\"", description);
-              if (self->conf->USE_ACCESSKEY > 0)
+              if (self->conf->USE_ACCESSKEY.integer > 0)
                 {
                   char *accesskey = direction_string (self, button->direction,
                                       TDS_type_accesskey, TDS_context_string);
                   if (accesskey && strlen (accesskey))
                     text_printf (&active_text, " accesskey=\"%s\"", accesskey);
                 }
-              if (self->conf->USE_REL_REV > 0)
+              if (self->conf->USE_REL_REV.integer > 0)
                 {
                   char *button_rel = direction_string (self, button->direction,
                                      TDS_type_rel, TDS_context_string);
@@ -7079,12 +7093,14 @@ html_default_format_button (CONVERTER *self,
 
               text_init (&passive_text);
 
-              if (self->conf->ICONS > 0 && self->conf->PASSIVE_ICONS.number > 0
-                  && self->conf->PASSIVE_ICONS.list[button->direction]
-                  && strlen 
(self->conf->PASSIVE_ICONS.list[button->direction]))
+              if (self->conf->ICONS.integer > 0
+                  && self->conf->PASSIVE_ICONS.icons->number > 0
+                  && self->conf->PASSIVE_ICONS.icons->list[button->direction]
+                  && strlen (self->conf->PASSIVE_ICONS.icons
+                                              ->list[button->direction]))
                 {
                   passive_icon
-                    = self->conf->PASSIVE_ICONS.list[button->direction];
+                    = self->conf->PASSIVE_ICONS.icons->list[button->direction];
                 }
               if (passive_icon)
                 {
@@ -7184,7 +7200,7 @@ html_default_format_navigation_panel (CONVERTER *self,
           free (button_info);
         }
 
-      if (self->conf->HEADER_IN_TABLE > 0)
+      if (self->conf->HEADER_IN_TABLE.integer > 0)
         {
           if (vertical)
             text_append_n (&result_buttons, "<tr>\n", 5);
@@ -7215,7 +7231,7 @@ html_default_format_navigation_panel (CONVERTER *self,
       free (passive);
     }
 
-  if (self->conf->HEADER_IN_TABLE > 0)
+  if (self->conf->HEADER_IN_TABLE.integer > 0)
     {
       attribute_class = html_attribute_class (self, "table",
                                               &nav_panel_classes);
@@ -7240,7 +7256,7 @@ html_default_format_navigation_panel (CONVERTER *self,
 
   text_append (result, result_buttons.text);
 
-  if (self->conf->HEADER_IN_TABLE > 0)
+  if (self->conf->HEADER_IN_TABLE.integer > 0)
     {
       if (!vertical)
         text_append_n (result, "</tr>", 5);
@@ -7287,7 +7303,7 @@ html_default_format_navigation_header (CONVERTER *self,
                           const ELEMENT *element, TEXT *result)
 {
   int vertical = 0;
-  if (self->conf->VERTICAL_HEAD_NAVIGATION > 0)
+  if (self->conf->VERTICAL_HEAD_NAVIGATION.integer > 0)
     vertical = 1;
   if (vertical)
     text_append (result,
@@ -7298,9 +7314,9 @@ html_default_format_navigation_header (CONVERTER *self,
 
   if (vertical)
     text_append (result, "</td>\n<td>\n");
-  else if (!strcmp (self->conf->SPLIT, "node"))
+  else if (!strcmp (self->conf->SPLIT.string, "node"))
     {
-      text_append (result, self->conf->DEFAULT_RULE);
+      text_append (result, self->conf->DEFAULT_RULE.string);
       text_append_n (result, "\n", 1);
     }
 }
@@ -7334,7 +7350,7 @@ html_default_format_element_header (CONVERTER *self,
                                const char *cmdname, const ELEMENT *command,
                                const OUTPUT_UNIT *output_unit, TEXT *result)
 {
-  if (self->conf->DEBUG > 0)
+  if (self->conf->DEBUG.integer > 0)
     {
       int i;
       TEXT debug_txt;
@@ -7380,7 +7396,7 @@ html_default_format_element_header (CONVERTER *self,
                                output_unit->tree_unit_directions[D_prev]))
         previous_is_top = 1;
 
-      if (self->conf->DEBUG > 0)
+      if (self->conf->DEBUG.integer > 0)
         fprintf (stderr, "Header (%d, %d, %d): %s\n", previous_is_top, is_top,
                          first_in_page,
                          root_heading_command_to_texinfo (command));
@@ -7388,47 +7404,47 @@ html_default_format_element_header (CONVERTER *self,
       if (is_top)
        /* use TOP_BUTTONS for top. */
         {
-          if ((self->conf->SPLIT && strlen (self->conf->SPLIT))
-              || self->conf->HEADERS > 0)
-            format_navigation_header (self, self->conf->TOP_BUTTONS, cmdname,
-                                      command, result);
+          if ((self->conf->SPLIT.string && strlen (self->conf->SPLIT.string))
+              || self->conf->HEADERS.integer > 0)
+            format_navigation_header (self, self->conf->TOP_BUTTONS.buttons,
+                                      cmdname, command, result);
         }
       else
         {
-          if (first_in_page && self->conf->HEADERS <= 0)
+          if (first_in_page && self->conf->HEADERS.integer <= 0)
             {
-              if (!strcmp (self->conf->SPLIT, "chapter"))
+              if (!strcmp (self->conf->SPLIT.string, "chapter"))
                 {
                   format_navigation_header (self,
-                     self->conf->CHAPTER_BUTTONS, cmdname, command,
+                     self->conf->CHAPTER_BUTTONS.buttons, cmdname, command,
                      result);
-                  if (self->conf->DEFAULT_RULE
-                      && self->conf->VERTICAL_HEAD_NAVIGATION <= 0)
+                  if (self->conf->DEFAULT_RULE.string
+                      && self->conf->VERTICAL_HEAD_NAVIGATION.integer <= 0)
                     {
-                      text_append (result, self->conf->DEFAULT_RULE);
+                      text_append (result, self->conf->DEFAULT_RULE.string);
                       text_append_n (result, "\n", 1);
                     }
                 }
-              else if (!strcmp (self->conf->SPLIT, "section"))
+              else if (!strcmp (self->conf->SPLIT.string, "section"))
                 {
                   format_navigation_header (self,
-                     self->conf->SECTION_BUTTONS, cmdname, command,
+                     self->conf->SECTION_BUTTONS.buttons, cmdname, command,
                      result);
                 }
             }
           if ((first_in_page || previous_is_top)
-              && self->conf->HEADERS > 0)
+              && self->conf->HEADERS.integer > 0)
             {
               format_navigation_header (self,
-                 self->conf->SECTION_BUTTONS, cmdname, command,
+                 self->conf->SECTION_BUTTONS.buttons, cmdname, command,
                  result);
             }
-          else if (self->conf->HEADERS > 0
-                   || !strcmp (self->conf->SPLIT, "node"))
+          else if (self->conf->HEADERS.integer > 0
+                   || !strcmp (self->conf->SPLIT.string, "node"))
             {
           /* got to do this here, as it isn't done otherwise since
              navigation_header is not called */
-               format_navigation_panel (self, self->conf->SECTION_BUTTONS,
+               format_navigation_panel (self, 
self->conf->SECTION_BUTTONS.buttons,
                                         cmdname, command, 0, result);
             }
         }
@@ -7517,10 +7533,11 @@ html_default_format_footnotes_sequence (CONVERTER 
*self, TEXT *result)
           else
             footnote_text_with_eol = footnote_text;
 
-          if (self->conf->NUMBER_FOOTNOTES > 0)
+          if (self->conf->NUMBER_FOOTNOTES.integer > 0)
             xasprintf (&footnote_mark, "%d", number_in_doc);
           else
-            footnote_mark = strdup (self->conf->NO_NUMBER_FOOTNOTE_SYMBOL);
+            footnote_mark
+              = strdup (self->conf->NO_NUMBER_FOOTNOTE_SYMBOL.string);
 
           attribute_class = html_attribute_class (self, "h5",
                             &foot_body_heading_classes);
@@ -7597,9 +7614,10 @@ default_format_footnotes_segment (CONVERTER *self, TEXT 
*result)
 
   text_append_n (result, ">\n", 2);
 
-  if (self->conf->DEFAULT_RULE && strlen (self->conf->DEFAULT_RULE))
+  if (self->conf->DEFAULT_RULE.string
+      && strlen (self->conf->DEFAULT_RULE.string))
     {
-      text_append (result, self->conf->DEFAULT_RULE);
+      text_append (result, self->conf->DEFAULT_RULE.string);
       text_append_n (result, "\n", 1);
     }
 
@@ -7615,7 +7633,7 @@ default_format_footnotes_segment (CONVERTER *self, TEXT 
*result)
       footnote_heading = "";
     }
 
-  level = self->conf->FOOTNOTE_END_HEADER_LEVEL;
+  level = self->conf->FOOTNOTE_END_HEADER_LEVEL.integer;
 
   xasprintf (&class, "%s-heading", class_base);
 
@@ -7793,7 +7811,7 @@ convert_def_line_type (CONVERTER *self, const enum 
element_type type,
           text_append_n (&def_call, "</code>", 7);
         }
       if ((base_cmd == CM_deftypefn || base_cmd == CM_deftypeop)
-          && !strcmp (self->conf->deftypefnnewline, "on"))
+          && !strcmp (self->conf->deftypefnnewline.string, "on"))
         {
           text_append_n (&def_call, self->line_break_element.string,
                                     self->line_break_element.len);
@@ -7886,7 +7904,7 @@ convert_def_line_type (CONVERTER *self, const enum 
element_type type,
       free (args_formatted);
     }
 
-  if (self->conf->DEF_TABLE > 0)
+  if (self->conf->DEF_TABLE.integer > 0)
     {
       ELEMENT *category_tree
          = definition_category_tree (self->conf, element);
@@ -7949,7 +7967,7 @@ convert_def_line_type (CONVERTER *self, const enum 
element_type type,
                                             "class", class_copy);
 
           if (base_cmd == CM_deftypeop && parsed_def->type
-              && !strcmp (self->conf->deftypefnnewline, "on"))
+              && !strcmp (self->conf->deftypefnnewline.string, "on"))
             {
                category_tree
                   = html_gdt_tree ("{category} on @code{{class}}:@* ",
@@ -7972,7 +7990,7 @@ convert_def_line_type (CONVERTER *self, const enum 
element_type type,
         {
           if ((base_cmd == CM_deftypefn || base_cmd == CM_deftypeop)
               && parsed_def->type
-              && !strcmp (self->conf->deftypefnnewline, "on"))
+              && !strcmp (self->conf->deftypefnnewline.string, "on"))
             {
               category_tree
                   = html_gdt_tree ("{category}:@* ",
@@ -8281,7 +8299,7 @@ convert_style_command (CONVERTER *self, const enum 
command_id cmd,
         }
 
       if (formatting_spec->quote)
-        text_append (result, self->conf->OPEN_QUOTE_SYMBOL);
+        text_append (result, self->conf->OPEN_QUOTE_SYMBOL.string);
 
       open
         = html_attribute_class (self, formatting_spec->element, classes);
@@ -8305,7 +8323,7 @@ convert_style_command (CONVERTER *self, const enum 
command_id cmd,
         }
 
       if (formatting_spec->quote)
-        text_append (result, self->conf->CLOSE_QUOTE_SYMBOL);
+        text_append (result, self->conf->CLOSE_QUOTE_SYMBOL.string);
     }
   else
     text_append (result, args_formatted->args[0].formatted[AFT_type_normal]);
@@ -8623,10 +8641,10 @@ convert_footnote_command (CONVERTER *self, const enum 
command_id cmd,
   self->shared_conversion_state.footnote_number++;
   foot_num = self->shared_conversion_state.footnote_number;
 
-  if (self->conf->NUMBER_FOOTNOTES > 0)
+  if (self->conf->NUMBER_FOOTNOTES.integer > 0)
     xasprintf (&footnote_mark, "%d", foot_num);
   else
-    footnote_mark = strdup (self->conf->NO_NUMBER_FOOTNOTE_SYMBOL);
+    footnote_mark = strdup (self->conf->NO_NUMBER_FOOTNOTE_SYMBOL.string);
 
   if (html_in_string (self))
     {
@@ -8682,7 +8700,7 @@ convert_footnote_command (CONVERTER *self, const enum 
command_id cmd,
       footnote_id_number->number++;
     }
 
-  if (!strcmp (self->conf->footnotestyle, "end")
+  if (!strcmp (self->conf->footnotestyle.string, "end")
       && (multi_expanded_region || multiple_expanded_footnote))
     {
    /* if the footnote appears multiple times, command_href() will select
@@ -8808,7 +8826,7 @@ find_image_extension_file (CONVERTER *self, const ELEMENT 
*element,
                    image_file, 0, &input_file_encoding, &element->source_info);
 
   located_image_path = locate_include_file (file_name,
-                                            &self->conf->INCLUDE_DIRECTORIES);
+                                      self->conf->INCLUDE_DIRECTORIES.strlist);
   free (file_name);
 
   if (located_image_path)
@@ -8961,10 +8979,10 @@ convert_image_command (CONVERTER *self, const enum 
command_id cmd,
       free_image_file_location_info (image_path_info);
       free (image_path_info);
 
-      if (self->conf->IMAGE_LINK_PREFIX)
+      if (self->conf->IMAGE_LINK_PREFIX.string)
         {
           char *tmp;
-          xasprintf (&tmp, "%s%s", self->conf->IMAGE_LINK_PREFIX,
+          xasprintf (&tmp, "%s%s", self->conf->IMAGE_LINK_PREFIX.string,
                                    image_file);
           free (image_file);
           image_file = tmp;
@@ -9019,7 +9037,8 @@ convert_math_command (CONVERTER *self, const enum 
command_id cmd,
   memset (classes, 0, sizeof (STRING_LIST));
   add_string (builtin_command_name (cmd), classes);
 
-  if (self->conf->HTML_MATH && !strcmp (self->conf->HTML_MATH, "mathjax"))
+  if (self->conf->HTML_MATH.string
+      && !strcmp (self->conf->HTML_MATH.string, "mathjax"))
     {
       html_register_file_information (self, "mathjax", 1);
       add_string ("tex2jax_process", classes);
@@ -9140,9 +9159,9 @@ convert_accent_command (CONVERTER *self, const enum 
command_id cmd,
   char *(*format_accents)(CONVERTER *self, const char *text,
                          const ELEMENT *element, int set_case);
 
-  int output_encoded_characters = (self->conf->OUTPUT_CHARACTERS > 0);
+  int output_encoded_characters = (self->conf->OUTPUT_CHARACTERS.integer > 0);
 
-  if (self->conf->USE_NUMERIC_ENTITY > 0)
+  if (self->conf->USE_NUMERIC_ENTITY.integer > 0)
     format_accents = &html_accent_entities_numeric_entities_accent;
   else
     format_accents = &html_accent_entities_html_accent;
@@ -9166,7 +9185,7 @@ convert_indicateurl_command (CONVERTER *self, const enum 
command_id cmd,
       || !args_formatted->args[0].formatted[AFT_type_normal])
     return;
 
-  text_append (result, self->conf->OPEN_QUOTE_SYMBOL);
+  text_append (result, self->conf->OPEN_QUOTE_SYMBOL.string);
 
   if (!html_in_string (self))
     {
@@ -9189,7 +9208,7 @@ convert_indicateurl_command (CONVERTER *self, const enum 
command_id cmd,
   else
     text_append (result, args_formatted->args[0].formatted[AFT_type_normal]);
 
-  text_append (result, self->conf->CLOSE_QUOTE_SYMBOL);
+  text_append (result, self->conf->CLOSE_QUOTE_SYMBOL.string);
 }
 
 void
@@ -9235,7 +9254,7 @@ contents_inline_element (CONVERTER *self, const enum 
command_id cmd,
 {
   char *table_of_contents;
 
-  if (self->conf->DEBUG > 0)
+  if (self->conf->DEBUG.integer > 0)
     fprintf (stderr, "CONTENTS_INLINE %s\n", builtin_command_name (cmd));
 
   table_of_contents = format_contents (self, cmd, element, 0);
@@ -9312,7 +9331,7 @@ contents_inline_element (CONVERTER *self, const enum 
command_id cmd,
               if (!heading)
                 heading = strdup ("");
               format_heading_text (self, 0, classes, heading,
-                                   self->conf->CHAPTER_HEADER_LEVEL,
+                                   self->conf->CHAPTER_HEADER_LEVEL.integer,
                                    0, 0, 0, &result);
               destroy_strings_list (classes);
 
@@ -9378,7 +9397,7 @@ mini_toc_internal (CONVERTER *self, const ELEMENT 
*element, TEXT *result)
 
           entry_index++;
 
-          if (self->conf->USE_ACCESSKEY > 0 && entry_index < 10)
+          if (self->conf->USE_ACCESSKEY.integer > 0 && entry_index < 10)
             {
               xasprintf (&accesskey, " accesskey=\"%d\"", entry_index);
             }
@@ -9448,7 +9467,7 @@ convert_heading_command (CONVERTER *self, const enum 
command_id cmd,
 
   element_id = html_command_id (self, element);
 
-  if (self->conf->DEBUG > 0)
+  if (self->conf->DEBUG.integer > 0)
     fprintf (stderr, "CONVERT elt heading %s\n",
                      root_heading_command_to_texinfo (element));
 
@@ -9464,7 +9483,7 @@ convert_heading_command (CONVERTER *self, const enum 
command_id cmd,
   text_init (&tables_of_contents);
   text_append (&tables_of_contents, "");
   if (element->cmd == CM_top
-      && !strcmp (self->conf->CONTENTS_OUTPUT_LOCATION, "after_top")
+      && !strcmp (self->conf->CONTENTS_OUTPUT_LOCATION.string, "after_top")
       && self->document->sections_list
       && self->document->sections_list->number > 1)
     {
@@ -9474,11 +9493,9 @@ convert_heading_command (CONVERTER *self, const enum 
command_id cmd,
         {
           int contents_set = 0;
           enum command_id cmd = contents_cmds[i];
-          COMMAND_OPTION_REF *contents_option_ref
-             = get_command_option (self->conf, cmd);
-          if (*(contents_option_ref->int_ref) > 0)
+          OPTION *contents_option_ref = get_command_option (self->conf, cmd);
+          if (contents_option_ref->integer > 0)
             contents_set = 1;
-          free (contents_option_ref);
           if (contents_set)
             {
               char *contents_text
@@ -9497,11 +9514,11 @@ convert_heading_command (CONVERTER *self, const enum 
command_id cmd,
   if (tables_of_contents.end <= 0
       && (flags & CF_sectioning_heading))
     {
-      if (!strcmp (self->conf->FORMAT_MENU, "sectiontoc"))
+      if (!strcmp (self->conf->FORMAT_MENU.string, "sectiontoc"))
         {
           mini_toc_internal (self, element, &mini_toc_or_auto_menu);
         }
-      else if (!strcmp (self->conf->FORMAT_MENU, "menu"))
+      else if (!strcmp (self->conf->FORMAT_MENU.string, "menu"))
         {
           ELEMENT *node
             = lookup_extra_element (element, "associated_node");
@@ -9530,7 +9547,7 @@ convert_heading_command (CONVERTER *self, const enum 
command_id cmd,
         }
     }
 
-  if (self->conf->NO_TOP_NODE_OUTPUT > 0
+  if (self->conf->NO_TOP_NODE_OUTPUT.integer > 0
       && builtin_command_data[cmd].flags & CF_root)
     {
       const ELEMENT *node_element = 0;
@@ -9649,12 +9666,13 @@ convert_heading_command (CONVERTER *self, const enum 
command_id cmd,
           else
             {
               int use_next_heading = 0;
-              if (self->conf->USE_NEXT_HEADING_FOR_LONE_NODE > 0)
+              if (self->conf->USE_NEXT_HEADING_FOR_LONE_NODE.integer > 0)
                 {
                   ELEMENT *next_heading
                     = find_root_command_next_heading_command (element,
                                                         self->expanded_formats,
-                    (!strcmp (self->conf->CONTENTS_OUTPUT_LOCATION, "inline")),
+                    (!strcmp (
+                        self->conf->CONTENTS_OUTPUT_LOCATION.string, 
"inline")),
                             0);
                   if (next_heading)
                     use_next_heading = 1;
@@ -9759,7 +9777,7 @@ convert_heading_command (CONVERTER *self, const enum 
command_id cmd,
   if (do_heading)
     {
       STRING_LIST *heading_classes;
-      if (self->conf->TOC_LINKS > 0
+      if (self->conf->TOC_LINKS.integer > 0
           && (builtin_command_data[cmd].flags & CF_root)
           && (builtin_command_data[cmd].flags & CF_sectioning_heading))
         {
@@ -9804,7 +9822,7 @@ convert_heading_command (CONVERTER *self, const enum 
command_id cmd,
         {
           format_heading_text (self, level_corrected_cmd,
                     heading_classes, heading,
-                    heading_level + self->conf->CHAPTER_HEADER_LEVEL -1,
+                    heading_level + self->conf->CHAPTER_HEADER_LEVEL.integer 
-1,
                     heading_id, element, element_id, result);
         }
       destroy_strings_list (heading_classes);
@@ -9991,7 +10009,7 @@ convert_preformatted_command (CONVERTER *self, const 
enum command_id cmd,
       main_cmd = CM_example;
     }
 
-  if (self->conf->COMPLEX_FORMAT_IN_TABLE > 0
+  if (self->conf->COMPLEX_FORMAT_IN_TABLE.integer > 0
       && html_commands_data[cmd].flags & HF_indented_preformatted)
     {
       indent_with_table (self, cmd, content,
@@ -10053,7 +10071,7 @@ convert_indented_command (CONVERTER *self, const enum 
command_id cmd,
   else
     main_cmd = cmd;
 
-  if (self->conf->COMPLEX_FORMAT_IN_TABLE > 0)
+  if (self->conf->COMPLEX_FORMAT_IN_TABLE.integer > 0)
     {
       indent_with_table (self, main_cmd, content,
                          additional_classes, result);
@@ -10129,7 +10147,8 @@ convert_displaymath_command (CONVERTER *self, const 
enum command_id cmd,
 
   clear_strings_list (classes);
 
-  if (self->conf->HTML_MATH && !strcmp (self->conf->HTML_MATH, "mathjax"))
+  if (self->conf->HTML_MATH.string
+      && !strcmp (self->conf->HTML_MATH.string, "mathjax"))
     {
       html_register_file_information (self, "mathjax", 1);
       add_string ("tex2jax_process", classes);
@@ -11062,7 +11081,7 @@ convert_itemize_command (CONVERTER *self, const enum 
command_id cmd,
   text_append (result, attribute_class);
   free (attribute_class);
 
-  if (!selector_style && self->conf->NO_CSS <= 0)
+  if (!selector_style && self->conf->NO_CSS.integer <= 0)
     {
       char *css_string
         = html_convert_css_string_for_list_mark (self, element->args.list[0],
@@ -11518,7 +11537,7 @@ convert_xref_commands (CONVERTER *self, const enum 
command_id cmd,
 
       if (!name)
         {
-          if (!strcmp (self->conf->xrefautomaticsectiontitle, "on")
+          if (!strcmp (self->conf->xrefautomaticsectiontitle.string, "on")
               && associated_section
         /* this condition avoids infinite recursions, indeed in that case
            the node will be used and not the section.  There should not be
@@ -11535,7 +11554,7 @@ convert_xref_commands (CONVERTER *self, const enum 
command_id cmd,
             }
           else if (target_node->cmd == CM_float)
             {
-              if (self->conf->XREF_USE_FLOAT_LABEL <= 0)
+              if (self->conf->XREF_USE_FLOAT_LABEL.integer <= 0)
                 {
                   name = html_command_text (self, target_root, 0);
                 }
@@ -11552,8 +11571,8 @@ convert_xref_commands (CONVERTER *self, const enum 
command_id cmd,
                     name = strdup ("");
                 }
             }
-          else if (self->conf->XREF_USE_NODE_NAME_ARG <= 0
-                   && (self->conf->XREF_USE_NODE_NAME_ARG == 0
+          else if (self->conf->XREF_USE_NODE_NAME_ARG.integer <= 0
+                   && (self->conf->XREF_USE_NODE_NAME_ARG.integer == 0
                        || !html_in_preformatted_context (self)))
             {
               name = html_command_text (self, target_root, HTT_text_nonumber);
@@ -11720,7 +11739,7 @@ convert_xref_commands (CONVERTER *self, const enum 
command_id cmd,
           TEXT manual_name_attribute;
           text_init (&manual_name_attribute);
           text_append (&manual_name_attribute, "");
-          if (file && self->conf->NO_CUSTOM_HTML_ATTRIBUTE <= 0)
+          if (file && self->conf->NO_CUSTOM_HTML_ATTRIBUTE.integer <= 0)
             {
               text_append_n (&manual_name_attribute, "data-manual=\"", 13);
               format_protect_text (self, file, &manual_name_attribute);
@@ -12156,7 +12175,7 @@ convert_printindex_command (CONVERTER *self, const enum 
command_id cmd,
                                      "integer", &status);
           entry_nr++;
 
-          if (self->conf->NO_TOP_NODE_OUTPUT > 0)
+          if (self->conf->NO_TOP_NODE_OUTPUT.integer > 0)
             {
               const ELEMENT *element_node
                 = lookup_extra_element (main_entry_element, "element_node");
@@ -12342,7 +12361,8 @@ convert_printindex_command (CONVERTER *self, const enum 
command_id cmd,
                 {
                   if (in_code)
                     text_append_n (&entries_text, "</code>", 7);
-                  text_append (&entries_text, self->conf->INDEX_ENTRY_COLON);
+                  text_append (&entries_text,
+                               self->conf->INDEX_ENTRY_COLON.string);
                 }
               text_append_n (&entries_text, "</td>", 5);
 
@@ -12573,10 +12593,10 @@ convert_printindex_command (CONVERTER *self, const 
enum command_id cmd,
           if (in_code)
             text_append_n (&entries_text, "</code>", 7);
           text_append_n (&entries_text, "</a>", 4);
-          text_append (&entries_text, self->conf->INDEX_ENTRY_COLON);
+          text_append (&entries_text, self->conf->INDEX_ENTRY_COLON.string);
           text_append_n (&entries_text, "</td>", 5);
 
-          if (self->conf->NODE_NAME_IN_INDEX > 0)
+          if (self->conf->NODE_NAME_IN_INDEX.integer > 0)
             {
               associated_command = lookup_extra_element (main_entry_element,
                                                         "element_node");
@@ -12620,7 +12640,7 @@ convert_printindex_command (CONVERTER *self, const enum 
command_id cmd,
             NODE_NAME_IN_INDEX may be undef even with USE_NODES set if the
             converter is called as convert() as in the test suite */
 
-                  if (self->conf->NODE_NAME_IN_INDEX == 0
+                  if (self->conf->NODE_NAME_IN_INDEX.integer == 0
                       && *formatted_index_entry_nr == 1)
                     {
                       char *element_region
@@ -12683,7 +12703,7 @@ convert_printindex_command (CONVERTER *self, const enum 
command_id cmd,
           text_append_n (&result_index_entries, "</th></tr>\n", 11);
           text_append (&result_index_entries, entries_text.text);
           text_append_n (&result_index_entries, "<tr><td colspan=\"3\">", 20);
-          text_append (&result_index_entries, self->conf->DEFAULT_RULE);
+          text_append (&result_index_entries, self->conf->DEFAULT_RULE.string);
           text_append_n (&result_index_entries, "</td></tr>\n", 11);
           letter_has_entries[i] = 1;
         }
@@ -12857,7 +12877,7 @@ convert_printindex_command (CONVERTER *self, const enum 
command_id cmd,
                                       0, 0, result, 0);
   text_append_n (result, "</th></tr>\n", 11);
   text_append_n (result, "<tr><td colspan=\"3\">", 20);
-  text_append (result, self->conf->DEFAULT_RULE);
+  text_append (result, self->conf->DEFAULT_RULE.string);
   text_append_n (result, "</td></tr>\n", 11);
   text_append (result, result_index_entries.text);
   text_append_n (result, "</table>\n", 9);
@@ -12885,12 +12905,24 @@ convert_printindex_command (CONVERTER *self, const 
enum command_id cmd,
   destroy_strings_list (entry_classes);
 }
 
+void
+convert_informative_command (CONVERTER *self, const enum command_id cmd,
+                    const ELEMENT *element,
+                    const HTML_ARGS_FORMATTED *args_formatted,
+                    const char *content, TEXT *result)
+{
+  if (html_in_string (self))
+    return;
+
+  set_informative_command_value (self->conf, element);
+}
+
 void
 contents_shortcontents_in_title (CONVERTER *self, TEXT *result)
 {
   if (self->document->sections_list
       && self->document->sections_list->number > 0
-      && !strcmp (self->conf->CONTENTS_OUTPUT_LOCATION, "after_title"))
+      && !strcmp (self->conf->CONTENTS_OUTPUT_LOCATION.string, "after_title"))
     {
       enum command_id contents_cmds[2] = {CM_shortcontents, CM_contents};
       int i;
@@ -12898,11 +12930,9 @@ contents_shortcontents_in_title (CONVERTER *self, TEXT 
*result)
         {
           int contents_set = 0;
           enum command_id cmd = contents_cmds[i];
-          COMMAND_OPTION_REF *contents_option_ref
-             = get_command_option (self->conf, cmd);
-          if (*(contents_option_ref->int_ref) > 0)
+          OPTION *contents_option_ref = get_command_option (self->conf, cmd);
+          if (contents_option_ref->integer > 0)
             contents_set = 1;
-          free (contents_option_ref);
           if (contents_set)
             {
               char *contents_text
@@ -12910,7 +12940,7 @@ contents_shortcontents_in_title (CONVERTER *self, TEXT 
*result)
               if (contents_text)
                 {
                   text_append (result, contents_text);
-                  text_append (result, self->conf->DEFAULT_RULE);
+                  text_append (result, self->conf->DEFAULT_RULE.string);
                   text_append_n (result, "\n", 1);
                   free (contents_text);
                 }
@@ -12965,7 +12995,7 @@ html_default_format_titlepage (CONVERTER *self)
     }
   if (titlepage_text)
     {
-      text_append (&result, self->conf->DEFAULT_RULE);
+      text_append (&result, self->conf->DEFAULT_RULE.string);
       text_append_n (&result, "\n", 1);
     }
   contents_shortcontents_in_title (self, &result);
@@ -12991,9 +13021,9 @@ format_titlepage (CONVERTER *self)
 char *
 html_default_format_title_titlepage (CONVERTER *self)
 {
-  if (self->conf->SHOW_TITLE > 0)
+  if (self->conf->SHOW_TITLE.integer > 0)
     {
-      if (self->conf->USE_TITLEPAGE_FOR_TITLE)
+      if (self->conf->USE_TITLEPAGE_FOR_TITLE.integer)
         {
           return format_titlepage (self);
         }
@@ -13047,9 +13077,10 @@ convert_contents_command (CONVERTER *self, const enum 
command_id cmd,
 
   set_informative_command_value (self->conf, element);
 
-  if (!strcmp (self->conf->CONTENTS_OUTPUT_LOCATION, "inline")
-      && ((used_cmd == CM_contents && self->conf->contents > 0)
-          || (used_cmd == CM_shortcontents && self->conf->shortcontents > 0))
+  if (!strcmp (self->conf->CONTENTS_OUTPUT_LOCATION.string, "inline")
+      && ((used_cmd == CM_contents && self->conf->contents.integer > 0)
+          || (used_cmd == CM_shortcontents
+              && self->conf->shortcontents.integer > 0))
       && self->document->sections_list
       && self->document->sections_list->number > 1)
     {
@@ -13126,6 +13157,11 @@ static COMMAND_INTERNAL_CONVERSION 
commands_internal_conversion_table[] = {
   {CM_insertcopying, &convert_insertcopying_command},
   {CM_listoffloats, &convert_listoffloats_command},
   {CM_printindex, &convert_printindex_command},
+  /* @informative_global_commands in perl */
+  {CM_documentlanguage, &convert_informative_command},
+  {CM_footnotestyle, &convert_informative_command},
+  {CM_xrefautomaticsectiontitle, &convert_informative_command},
+  {CM_deftypefnnewline, &convert_informative_command},
 
   {CM_contents, &convert_contents_command},
   {CM_shortcontents, &convert_contents_command},
@@ -13259,10 +13295,10 @@ convert_unit_type (CONVERTER *self, const enum 
output_unit_type unit_type,
        of footnotes in a separate unit.  And if footnotestyle is end
        the footnotes won't be done in format_element_footer either. */
           format_footnotes_segment (self, result);
-          if (self->conf->DEFAULT_RULE
-              && self->conf->PROGRAM_NAME_IN_FOOTER > 0)
+          if (self->conf->DEFAULT_RULE.string
+              && self->conf->PROGRAM_NAME_IN_FOOTER.integer > 0)
             {
-              text_append (result, self->conf->DEFAULT_RULE);
+              text_append (result, self->conf->DEFAULT_RULE.string);
               text_append_n (result, "\n", 1);
             }
 
@@ -13378,18 +13414,18 @@ convert_special_unit_type (CONVERTER *self,
         = count_elements_in_file_number (self, CEFT_current, file_index +1);
     }
 
-  if (self->conf->HEADERS > 0
+  if (self->conf->HEADERS.integer > 0
       /* first in page */
       || count_in_file == 1)
     {
-      format_navigation_header (self, self->conf->MISC_BUTTONS, 0,
+      format_navigation_header (self, self->conf->MISC_BUTTONS.buttons, 0,
                                 unit_command, result);
     }
 
   heading = html_command_text (self, unit_command, 0);
-  level = self->conf->CHAPTER_HEADER_LEVEL;
+  level = self->conf->CHAPTER_HEADER_LEVEL.integer;
   if (!strcmp (special_unit_variety, "footnotes"))
-    level = self->conf->FOOTNOTE_SEPARATE_HEADER_LEVEL;
+    level = self->conf->FOOTNOTE_SEPARATE_HEADER_LEVEL.integer;
 
   xasprintf (&class, "%s-heading", class_base);
 
@@ -13465,9 +13501,10 @@ default_format_special_body_about (CONVERTER *self,
                                TEXT *result)
 {
   int i;
-  const BUTTON_SPECIFICATION_LIST *buttons = self->conf->SECTION_BUTTONS;
+  const BUTTON_SPECIFICATION_LIST *buttons
+           = self->conf->SECTION_BUTTONS.buttons;
 
-  if (self->conf->PROGRAM_NAME_IN_ABOUT > 0)
+  if (self->conf->PROGRAM_NAME_IN_ABOUT.integer > 0)
     {
       text_append_n (result, "<p>\n  ", 6);
       format_program_string (self, result);
@@ -13519,15 +13556,15 @@ default_format_special_body_about (CONVERTER *self,
       if (button->type == BST_direction)
         {
          /* FIXME strip FirstInFile from $button to get active icon file? */
-          if (self->conf->ICONS > 0
-              && self->conf->ACTIVE_ICONS.number > 0
-              && self->conf->ACTIVE_ICONS.list[direction]
-              && strlen (self->conf->ACTIVE_ICONS.list[direction]))
+          if (self->conf->ICONS.integer > 0
+              && self->conf->ACTIVE_ICONS.icons->number > 0
+              && self->conf->ACTIVE_ICONS.icons->list[direction]
+              && strlen (self->conf->ACTIVE_ICONS.icons->list[direction]))
             {
               char *button_name_string = direction_string (self, direction,
                                        TDS_type_button, TDS_context_string);
               char *button = format_button_icon_img (self, button_name_string,
-                        self->conf->ACTIVE_ICONS.list[direction], 0);
+                        self->conf->ACTIVE_ICONS.icons->list[direction], 0);
               text_append (result, button);
               free (button);
             }
@@ -13627,7 +13664,7 @@ command_conversion_external (CONVERTER *self, const 
enum command_id cmd,
 {
   /* XS specific debug message */
   /*
-  if (self->conf->DEBUG > 0)
+  if (self->conf->DEBUG.integer > 0)
     fprintf (stderr, "DEBUG: command conversion %s '%s'\n",
              builtin_command_data[cmd].cmdname, content);
    */
@@ -13818,9 +13855,9 @@ html_prepare_converted_output_info (CONVERTER *self)
     }
 
   /* documentdescription */
-  if (self->conf->documentdescription)
+  if (self->conf->documentdescription.string)
     self->documentdescription_string
-     = strdup (self->conf->documentdescription);
+     = strdup (self->conf->documentdescription.string);
   else if (self->document->global_commands->documentdescription)
     {
       ELEMENT *tmp = new_element (ET_NONE);
@@ -14077,7 +14114,7 @@ html_converter_initialize (CONVERTER *self)
   char *line_break_element;
   /* initialization needing some information from perl */
 
-  output_encoding = self->conf->OUTPUT_ENCODING_NAME;
+  output_encoding = self->conf->OUTPUT_ENCODING_NAME.string;
 
   for (i = 0; i < SC_non_breaking_space+1; i++)
     {
@@ -14087,11 +14124,11 @@ html_converter_initialize (CONVERTER *self)
       char *numeric_entity = special_characters_formatting[i][3];
       char *special_character_string;
 
-      if (self->conf->OUTPUT_CHARACTERS > 0
+      if (self->conf->OUTPUT_CHARACTERS.integer > 0
           && unicode_point_decoded_in_encoding (output_encoding,
                                                 unicode_point))
         special_character_string = encoded_string;
-      else if (self->conf->USE_NUMERIC_ENTITY > 0)
+      else if (self->conf->USE_NUMERIC_ENTITY.integer > 0)
         special_character_string = numeric_entity;
       else
         special_character_string = entity;
@@ -14100,7 +14137,7 @@ html_converter_initialize (CONVERTER *self)
       self->special_character[i].len = strlen (special_character_string);
     }
 
-  if (self->conf->USE_XML_SYNTAX > 0)
+  if (self->conf->USE_XML_SYNTAX.integer > 0)
     {
       /* here in perl something for rules but we already get that from perl */
       line_break_element = "<br/>";
@@ -14487,12 +14524,12 @@ html_initialize_output_state (CONVERTER *self, char 
*context)
   /* set the htmlxref type split of the document */
   self->document_htmlxref_split_type = htmlxref_split_type_mono;
 
-  if (self->conf->SPLIT && strlen (self->conf->SPLIT))
+  if (self->conf->SPLIT.string && strlen (self->conf->SPLIT.string))
     {
       int i;
       for (i = 1; i < htmlxref_split_type_chapter+1; i++)
         {
-          if (!strcmp (self->conf->SPLIT, htmlxref_split_type_names[i]))
+          if (!strcmp (self->conf->SPLIT.string, htmlxref_split_type_names[i]))
             {
               self->document_htmlxref_split_type = i;
               break;
@@ -14743,7 +14780,7 @@ html_reset_converter (CONVERTER *self)
         {
           fprintf (stderr, "BUG: tree_to_build: %zu\n",
                            self->tree_to_build.number);
-          if (self->conf->DEBUG > 0)
+          if (self->conf->DEBUG.integer > 0)
             {
               for (i = 0; i < self->tree_to_build.number; i++)
                 {
@@ -15101,11 +15138,12 @@ html_translate_names (CONVERTER *self)
   int j;
   STRING_LIST *special_unit_varieties = &self->special_unit_varieties;
 
-  if (self->conf->DEBUG > 0)
+  if (self->conf->DEBUG.integer > 0)
     {
       fprintf (stderr, "\nXS|TRANSLATE_NAMES encoding_name: %s"
                " documentlanguage: %s\n",
-               self->conf->OUTPUT_ENCODING_NAME, self->conf->documentlanguage);
+               self->conf->OUTPUT_ENCODING_NAME.string,
+               self->conf->documentlanguage.string);
     }
 
   /* reset strings such that they are translated when needed. */
@@ -15222,7 +15260,7 @@ html_translate_names (CONVERTER *self)
         }
     }
 
-  if (self->conf->DEBUG > 0)
+  if (self->conf->DEBUG.integer > 0)
     fprintf (stderr, "END TRANSLATE_NAMES\n\n");
 
   self->modified_state |= HMSF_translations;
@@ -15336,7 +15374,7 @@ html_open_command_update_context (CONVERTER *self, enum 
command_id data_cmd)
   else if (builtin_command_data[data_cmd].flags & CF_math)
     {
       top_document_ctx->math_ctx++;
-      if (self->conf->CONVERT_TO_LATEX_IN_MATH > 0)
+      if (self->conf->CONVERT_TO_LATEX_IN_MATH.integer > 0)
         convert_to_latex = 1;
     }
   if (data_cmd == CM_verb)
@@ -15557,7 +15595,7 @@ convert_to_html_internal (CONVERTER *self, const 
ELEMENT *element,
   if (element->type)
     text_append (&command_type, element_type_names[element->type]);
 
-  if (self->conf->DEBUG > 0)
+  if (self->conf->DEBUG.integer > 0)
     {
       TEXT debug_str;
       char *contexts_str = debug_print_html_contexts (self);
@@ -15590,7 +15628,7 @@ convert_to_html_internal (CONVERTER *self, const 
ELEMENT *element,
           && self->current_commands_conversion_function[cmd].status
                                                          == 
FRS_status_ignored))
     {
-      if (self->conf->DEBUG > 0)
+      if (self->conf->DEBUG.integer > 0)
         {
           fprintf (stderr, "IGNORED %s\n", command_type.text);
         }
@@ -15630,7 +15668,7 @@ convert_to_html_internal (CONVERTER *self, const 
ELEMENT *element,
                     (self, ET_text, element, element->text.text, &text_result);
         }
 
-      if (self->conf->DEBUG > 0)
+      if (self->conf->DEBUG.integer > 0)
         {
           fprintf (stderr, "XS|DO TEXT => `%s'\n", text_result.text);
         }
@@ -15648,7 +15686,7 @@ convert_to_html_internal (CONVERTER *self, const 
ELEMENT *element,
       enum command_id data_cmd = element_builtin_data_cmd (element);
       /* XS only debug message */
       /*
-      if (self->conf->DEBUG > 0)
+      if (self->conf->DEBUG.integer > 0)
         fprintf (stderr, "COMMAND: %s %s\n",
                  builtin_command_data[data_cmd].cmdname,
                  builtin_command_data[cmd].cmdname);
@@ -15953,7 +15991,7 @@ convert_to_html_internal (CONVERTER *self, const 
ELEMENT *element,
         }
       else
         {
-          if (self->conf->DEBUG > 0 || self->conf->VERBOSE > 0)
+          if (self->conf->DEBUG.integer > 0 || self->conf->VERBOSE.integer > 0)
             fprintf (stderr, "Command not converted: %s\n", command_name);
           if (builtin_command_data[data_cmd].flags & CF_root)
             {
@@ -16024,7 +16062,7 @@ convert_to_html_internal (CONVERTER *self, const 
ELEMENT *element,
         }
       free (content_formatted.text);
 
-      if (self->conf->DEBUG > 0)
+      if (self->conf->DEBUG.integer > 0)
         {
           fprintf (stderr, "XS|DO type (%s) => `%s'\n", 
element_type_names[type],
                            type_result.text);
@@ -16056,7 +16094,7 @@ convert_to_html_internal (CONVERTER *self, const 
ELEMENT *element,
           free (explanation);
         }
 
-      if (self->conf->DEBUG > 0)
+      if (self->conf->DEBUG.integer > 0)
         fprintf (stderr, "UNNAMED HOLDER => `%s'\n", content_formatted.text);
       ADD(content_formatted.text);
       free (content_formatted.text);
@@ -16064,7 +16102,7 @@ convert_to_html_internal (CONVERTER *self, const 
ELEMENT *element,
     }
   else
     {
-      if (self->conf->DEBUG > 0)
+      if (self->conf->DEBUG.integer > 0)
         fprintf (stderr, "UNNAMED empty\n");
       if (self->current_types_conversion_function[0].type_conversion)
         {
@@ -16094,7 +16132,7 @@ convert_output_unit (CONVERTER *self, const OUTPUT_UNIT 
*output_unit,
 
   if (self->output_units_conversion[unit_type].status == FRS_status_ignored)
     {
-      if (self->conf->DEBUG > 0)
+      if (self->conf->DEBUG.integer > 0)
         {
           fprintf (stderr, "IGNORED OU %s\n",
                            output_unit_type_names[unit_type]);
@@ -16102,7 +16140,7 @@ convert_output_unit (CONVERTER *self, const OUTPUT_UNIT 
*output_unit,
       return;
     }
 
-  if (self->conf->DEBUG > 0)
+  if (self->conf->DEBUG.integer > 0)
     {
       char *output_unit_txi = output_unit_texi (output_unit);
       fprintf (stderr, "XS|UNIT(%s) -> ou: %s '%s'\n", explanation,
@@ -16149,7 +16187,7 @@ convert_output_unit (CONVERTER *self, const OUTPUT_UNIT 
*output_unit,
   self->current_output_unit = 0;
   self->modified_state |= HMSF_current_output_unit;
 
-  if (self->conf->DEBUG > 0)
+  if (self->conf->DEBUG.integer > 0)
     fprintf (stderr, "DOUNIT (%s) => `%s'\n", 
output_unit_type_names[unit_type],
                      result->text + input_result_end);
 }
@@ -16162,7 +16200,7 @@ convert_convert_output_unit_internal (CONVERTER *self, 
TEXT *result,
 {
   char *explanation;
 
-  if (self->conf->DEBUG > 0)
+  if (self->conf->DEBUG.integer > 0)
     fprintf (stderr, "\n%s %d\n", debug_str, unit_nr);
 
   xasprintf (&explanation, "%s %d", explanation_str, unit_nr);
@@ -16190,7 +16228,7 @@ html_convert_convert (CONVERTER *self, const ELEMENT 
*root,
 
   if (!output_units || !output_units->number)
     {
-      if (self->conf->DEBUG > 0)
+      if (self->conf->DEBUG.integer > 0)
         fprintf (stderr, "\nC NO UNIT\n");
 
       convert_to_html_internal (self, root, &result,
@@ -16432,7 +16470,7 @@ html_convert_output (CONVERTER *self, const ELEMENT 
*root,
   text_init (&result);
   text_init (&text);
 
-  if (self->conf->DATE_IN_HEADER > 0)
+  if (self->conf->DATE_IN_HEADER.integer > 0)
     {
       ELEMENT *today_element = new_element (ET_NONE);
       char *today;
@@ -16497,7 +16535,7 @@ html_convert_output (CONVERTER *self, const ELEMENT 
*root,
         }
       else
         {
-          if (self->conf->DEBUG > 0)
+          if (self->conf->DEBUG.integer > 0)
             fprintf (stderr, "\nNO UNIT NO PAGE\n");
 
           text_append (&text, self->title_titlepage);
@@ -16529,14 +16567,14 @@ html_convert_output (CONVERTER *self, const ELEMENT 
*root,
       int i;
       ENCODING_CONVERSION *conversion = 0;
 
-      if (self->conf->OUTPUT_ENCODING_NAME)
+      if (self->conf->OUTPUT_ENCODING_NAME.string)
         {
           conversion
-             = get_encoding_conversion (self->conf->OUTPUT_ENCODING_NAME,
+             = get_encoding_conversion 
(self->conf->OUTPUT_ENCODING_NAME.string,
                                               &output_conversions);
         }
 
-      if (self->conf->DEBUG > 0)
+      if (self->conf->DEBUG.integer > 0)
         fprintf (stderr, "DO Units with filenames\n");
 
       for (i = 0; i < output_units->number; i++)
diff --git a/tp/Texinfo/XS/convert/converter.c 
b/tp/Texinfo/XS/convert/converter.c
index 321991626f..afa5718a94 100644
--- a/tp/Texinfo/XS/convert/converter.c
+++ b/tp/Texinfo/XS/convert/converter.c
@@ -106,59 +106,58 @@ unregister_converter_descriptor (int converter_descriptor)
 }
 
 /* freed by caller */
-static COMMAND_OPTION_VALUE *
-new_option_value (int type, int int_value, char *char_value)
+static OPTION *
+new_option_value (enum global_option_type type, int int_value, char 
*char_value)
 {
-  COMMAND_OPTION_VALUE *result
-    = (COMMAND_OPTION_VALUE *) malloc (sizeof (COMMAND_OPTION_VALUE));
+  OPTION *result
+    = (OPTION *) malloc (sizeof (OPTION));
   result->type = type;
-  if (type == GO_int)
-    result->int_value = int_value;
+  if (type == GO_integer)
+    result->integer = int_value;
   else
-    result->char_value = char_value;
+    result->string = char_value;
   return result;
 }
 
 /* freed by caller */
-static COMMAND_OPTION_VALUE *
+static OPTION *
 command_init (enum command_id cmd, OPTIONS *init_conf)
 {
-  COMMAND_OPTION_REF *init_conf_ref;
+  OPTION *init_conf_ref;
   COMMAND_OPTION_DEFAULT *option_default;
-  COMMAND_OPTION_VALUE *option_value = 0;
+  OPTION *option_value = 0;
   if (init_conf)
     {
       init_conf_ref = get_command_option (init_conf, cmd);
       if (init_conf_ref)
         {
-          if (init_conf_ref->type == GO_int)
+          if (init_conf_ref->type == GO_integer)
             {
-              if (*(init_conf_ref->int_ref) >= 0)
+              if (init_conf_ref->integer >= 0)
                 {
                   option_value
-                    = new_option_value (GO_int, *(init_conf_ref->int_ref), 0);
-                  free (init_conf_ref);
+                    = new_option_value (GO_integer, init_conf_ref->integer, 0);
                   return option_value;
                 }
             }
           else
             {
-              if (*(init_conf_ref->char_ref))
+              if (init_conf_ref->type == GO_char
+                  || init_conf_ref->type == GO_bytes)
                 {
                   option_value
-                    = new_option_value (GO_char, -1, 
*(init_conf_ref->char_ref));
-                  free (init_conf_ref);
+                    = new_option_value (init_conf_ref->type, -1,
+                                        init_conf_ref->string);
                   return option_value;
                 }
             }
         }
-      free (init_conf_ref);
     }
   option_default = &command_option_default_table[cmd];
-  if (option_default->type == GO_int)
+  if (option_default->type == GO_integer)
     {
       if (option_default->value >= 0)
-        option_value = new_option_value (GO_int, option_default->value, 0);
+        option_value = new_option_value (GO_integer, option_default->value, 0);
     }
   else if (option_default->type == GO_char)
     {
@@ -179,20 +178,19 @@ set_global_document_commands (CONVERTER *converter,
       for (i = 0; cmd_list[i] > 0; i++)
         {
           enum command_id cmd = cmd_list[i];
-          COMMAND_OPTION_VALUE *option_value = command_init (cmd,
-                                                converter->init_conf);
+          OPTION *option_value = command_init (cmd,
+                                               converter->init_conf);
           if (option_value)
             {
-              COMMAND_OPTION_REF *option_ref
+              OPTION *option_ref
                = get_command_option (converter->conf, cmd);
-              if (option_value->type == GO_int)
-                *(option_ref->int_ref) = option_value->int_value;
+              if (option_value->type == GO_integer)
+                option_ref->integer = option_value->integer;
               else
                 {
-                  free (*(option_ref->char_ref));
-                  *(option_ref->char_ref) = strdup (option_value->char_value);
+                  free (option_ref->string);
+                  option_ref->string = strdup (option_value->string);
                 }
-              free (option_ref);
               free (option_value);
             }
         }
@@ -204,7 +202,7 @@ set_global_document_commands (CONVERTER *converter,
         {
           ELEMENT *element;
           enum command_id cmd = cmd_list[i];
-          if (converter->conf->DEBUG > 0)
+          if (converter->conf->DEBUG.integer > 0)
             {
               fprintf (stderr, "XS|SET_global(%s) %s\n",
                        command_location_names[location],
@@ -216,22 +214,21 @@ set_global_document_commands (CONVERTER *converter,
                                            cmd, location);
           if (!element)
             {
-              COMMAND_OPTION_VALUE *option_value = command_init (cmd,
-                                                      converter->init_conf);
+              OPTION *option_value = command_init (cmd,
+                                                   converter->init_conf);
               if (option_value)
                 {
-                  COMMAND_OPTION_REF *option_ref
+                  OPTION *option_ref
                     = get_command_option (converter->conf, cmd);
-                  if (option_value->type == GO_int)
-                    *(option_ref->int_ref) = option_value->int_value;
+                  if (option_value->type == GO_integer)
+                    option_ref->integer = option_value->integer;
                   else
                     {
-                      free (*(option_ref->char_ref));
-                      *(option_ref->char_ref)
-                        = strdup (option_value->char_value);
+                      free (option_ref->string);
+                      option_ref->string
+                        = strdup (option_value->string);
                     }
 
-                  free (option_ref);
                   free (option_value);
                 }
             }
@@ -242,12 +239,12 @@ set_global_document_commands (CONVERTER *converter,
 static void
 id_to_filename (CONVERTER *self, char **id_ref)
 {
-  if (self->conf->BASEFILENAME_LENGTH < 0)
+  if (self->conf->BASEFILENAME_LENGTH.integer < 0)
     return;
   char *id = *id_ref;
-  if (strlen (id) > self->conf->BASEFILENAME_LENGTH)
+  if (strlen (id) > self->conf->BASEFILENAME_LENGTH.integer)
     {
-      id[self->conf->BASEFILENAME_LENGTH] = '\0';
+      id[self->conf->BASEFILENAME_LENGTH.integer] = '\0';
     }
 }
 
@@ -260,16 +257,16 @@ normalized_sectioning_command_filename (CONVERTER *self, 
const ELEMENT *command)
   char *normalized_file_name;
   char *normalized_name
     = normalize_transliterate_texinfo_contents (command->args.list[0],
-                                                (self->conf->TEST > 0));
+                                                (self->conf->TEST.integer > 
0));
   normalized_file_name = strdup (normalized_name);
   id_to_filename (self, &normalized_file_name);
 
   text_init (&filename);
   text_append (&filename, normalized_file_name);
-  if (self->conf->EXTENSION && strlen (self->conf->EXTENSION))
+  if (self->conf->EXTENSION.string && strlen (self->conf->EXTENSION.string))
     {
       text_append (&filename, ".");
-      text_append (&filename, self->conf->EXTENSION);
+      text_append (&filename, self->conf->EXTENSION.string);
     }
 
   free (normalized_file_name);
@@ -288,10 +285,10 @@ node_information_filename (CONVERTER *self, char 
*normalized,
 
   if (normalized)
     {
-      if (self->conf->TRANSLITERATE_FILE_NAMES > 0)
+      if (self->conf->TRANSLITERATE_FILE_NAMES.integer > 0)
         {
           filename = normalize_transliterate_texinfo_contents (label_element,
-                                                       (self->conf->TEST > 0));
+                                                       
(self->conf->TEST.integer > 0));
         }
       else
         filename = strdup (normalized);
@@ -561,8 +558,8 @@ convert_accents (CONVERTER *self, const ELEMENT *accent,
   if (output_encoded_characters)
     {
       char *encoded = encoded_accents (self, arg_text, &accent_stack->stack,
-                                 self->conf->OUTPUT_ENCODING_NAME, 
format_accent,
-                                 set_case);
+                                 self->conf->OUTPUT_ENCODING_NAME.string,
+                                 format_accent, set_case);
       if (encoded)
         {
           free (arg_text);
@@ -638,19 +635,19 @@ top_node_filename (CONVERTER *self, char *document_name)
 {
   TEXT top_node_filename;
 
-  if (self->conf->TOP_FILE && strlen (self->conf->TOP_FILE))
+  if (self->conf->TOP_FILE.string && strlen (self->conf->TOP_FILE.string))
     {
-      return strdup (self->conf->TOP_FILE);
+      return strdup (self->conf->TOP_FILE.string);
     }
 
   if (document_name)
     {
       text_init (&top_node_filename);
       text_append (&top_node_filename, document_name);
-      if (self->conf->EXTENSION && strlen (self->conf->EXTENSION))
+      if (self->conf->EXTENSION.string && strlen 
(self->conf->EXTENSION.string))
         {
           text_append (&top_node_filename, ".");
-          text_append (&top_node_filename, self->conf->EXTENSION);
+          text_append (&top_node_filename, self->conf->EXTENSION.string);
         }
       return top_node_filename.text;
     }
@@ -722,14 +719,14 @@ static size_t
 register_normalize_case_filename (CONVERTER *self, char *filename)
 {
   size_t output_unit_file_idx;
-  if (self->conf->CASE_INSENSITIVE_FILENAMES > 0)
+  if (self->conf->CASE_INSENSITIVE_FILENAMES.integer > 0)
     {
       char *lc_filename = to_upper_or_lower_multibyte (filename, -1);
       int status;
       output_unit_file_idx = find_output_unit_file (self, lc_filename, 
&status);
       if (status)
         {
-          if (self->conf->DEBUG > 0)
+          if (self->conf->DEBUG.integer > 0)
             {
               FILE_NAME_PATH_COUNTER *output_unit_file
                 = &self->output_unit_files.list[output_unit_file_idx];
@@ -752,7 +749,7 @@ register_normalize_case_filename (CONVERTER *self, char 
*filename)
       output_unit_file_idx = find_output_unit_file (self, filename, &status);
       if (status)
         {
-          if (self->conf->DEBUG > 0)
+          if (self->conf->DEBUG.integer > 0)
             {
               FILE_NAME_PATH_COUNTER *output_unit_file
                 = &self->output_unit_files.list[output_unit_file_idx];
@@ -808,13 +805,13 @@ set_file_path (CONVERTER *self, char *filename, char 
*filepath,
     {
       if (!strcmp (output_unit_file->filepath, filepath_str))
         {
-          if (self->conf->DEBUG > 0)
+          if (self->conf->DEBUG.integer > 0)
             fprintf (stderr, "set_file_path: filepath set: %s\n",
                              filepath_str);
         }
       else
         {
-          if (self->conf->DEBUG > 0)
+          if (self->conf->DEBUG.integer > 0)
             fprintf (stderr, "set_file_path: filepath reset: %s, %s\n",
                              output_unit_file->filepath, filepath_str);
           free (output_unit_file->filepath);
diff --git a/tp/Texinfo/XS/main/DocumentXS.xs b/tp/Texinfo/XS/main/DocumentXS.xs
index 61cea0bfe2..5cbb2858ff 100644
--- a/tp/Texinfo/XS/main/DocumentXS.xs
+++ b/tp/Texinfo/XS/main/DocumentXS.xs
@@ -165,7 +165,7 @@ set_document_options (SV *sv_options_in, SV *document_in)
                                              "set_document_options");
         if (document)
           {
-            OPTIONS *options = copy_sv_options (sv_options_in, 0);
+            OPTIONS *options = copy_sv_options (sv_options_in, 0, 0);
             register_document_options (document, options);
           }
 
@@ -201,7 +201,7 @@ gdt (SV *options_in, string, ...)
       CODE:
          if (SvOK(options_in))
            {
-             options = copy_sv_options (options_in, 0);
+             options = copy_sv_options (options_in, 0, 0);
            }
         if (items > 4 && SvOK(ST(4)))
            in_lang = (char *)SvPVutf8_nolen(ST(4));
diff --git a/tp/Texinfo/XS/main/build_perl_info.c 
b/tp/Texinfo/XS/main/build_perl_info.c
index 78e43f7400..d9abbbe725 100644
--- a/tp/Texinfo/XS/main/build_perl_info.c
+++ b/tp/Texinfo/XS/main/build_perl_info.c
@@ -38,7 +38,7 @@
 #include "tree_types.h"
 #include "command_ids.h"
 #include "element_types.h"
-/* for GLOBAL_INFO ERROR_MESSAGE CONVERTER */
+/* for GLOBAL_INFO ERROR_MESSAGE CONVERTER sv_string_type */
 #include "converter_types.h"
 #include "tree.h"
 /* for output_conversions fatal output_unit_type_names */
@@ -1605,6 +1605,29 @@ build_integer_stack (INTEGER_STACK *integer_stack)
   return av;
 }
 
+AV *
+build_string_list (STRING_LIST *strings_list, enum sv_string_type type)
+{
+  AV *av;
+  int i;
+
+  dTHX;
+
+  av = newAV ();
+
+  for (i = 0; i < strings_list->number; i++)
+    {
+      char *value = strings_list->list[i];
+      if (!value)
+        av_push (av, newSV (0));
+      else if (type == svt_char)
+        av_push (av, newSVpv_utf8 (value, 0));
+      else
+        av_push (av, newSVpv_byte (value, 0));
+    }
+  return av;
+}
+
 SV *
 build_filenames (FILE_NAME_PATH_COUNTER_LIST *output_unit_files)
 {
@@ -1865,3 +1888,43 @@ build_expanded_formats (EXPANDED_FORMAT 
*expanded_formats)
     }
   return newRV_noinc ((SV *)expanded_hv);
 }
+
+SV *
+get_conf (CONVERTER *converter, const char *conf)
+{
+  dTHX;
+
+  if (converter->conf)
+    return build_sv_option (converter->conf, conf, converter);
+  return newSV (0);
+}
+
+SV *
+html_build_direction_icons (CONVERTER *converter,
+                            DIRECTION_ICON_LIST *direction_icons)
+{
+  HV *icons_hv;
+  int i;
+
+  dTHX;
+
+  if (!direction_icons)
+    return newSV (0);
+
+  if (!converter || !converter->direction_unit_direction_name)
+    return newSV (0);
+
+  icons_hv = newHV ();
+
+  for (i = 0; converter->direction_unit_direction_name[i]; i++)
+    {
+      if (direction_icons->list[i])
+        {
+          const char *direction_name
+            = converter->direction_unit_direction_name[i];
+          hv_store (icons_hv, direction_name, strlen (direction_name),
+                    newSVpv_utf8 (direction_name, 0), 0);
+        }
+    }
+  return newRV_noinc ((SV *)icons_hv);
+}
diff --git a/tp/Texinfo/XS/main/build_perl_info.h 
b/tp/Texinfo/XS/main/build_perl_info.h
index 50f0da3293..007acd80ba 100644
--- a/tp/Texinfo/XS/main/build_perl_info.h
+++ b/tp/Texinfo/XS/main/build_perl_info.h
@@ -11,11 +11,16 @@
 #include "tree_types.h"
 #include "document_types.h"
 #include "converter_types.h"
+#include "options_types.h"
 
 int init (int texinfo_uninstalled, char *srcdir_in);
 
+/* in options_get_perl.c */
+SV *build_sv_option (OPTIONS *options, const char *key, CONVERTER *converter);
+
 /* does not exist as perl macro */
 SV *newSVpv_utf8 (const char *str, STRLEN len);
+SV *newSVpv_byte (const char *str, STRLEN len);
 
 void element_to_perl_hash (ELEMENT *e, int avoid_recursion);
 
@@ -40,6 +45,7 @@ void rebuild_output_units_list (SV *output_units_sv,
                                 size_t output_units_descriptor);
 
 AV *build_integer_stack (INTEGER_STACK *integer_stack);
+AV *build_string_list (STRING_LIST *strings_list, enum sv_string_type);
 
 void pass_output_unit_files (SV *converter_sv,
                         FILE_NAME_PATH_COUNTER_LIST *output_unit_files);
@@ -47,4 +53,8 @@ void pass_output_unit_files (SV *converter_sv,
 void build_output_files_information (SV *converter_sv,
                    OUTPUT_FILES_INFORMATION *output_files_information);
 
+SV *html_build_direction_icons (CONVERTER *converter,
+                            DIRECTION_ICON_LIST *direction_icons);
+SV *get_conf (CONVERTER *converter, const char *conf);
+
 #endif
diff --git a/tp/Texinfo/XS/main/call_perl_function.c 
b/tp/Texinfo/XS/main/call_perl_function.c
index fb13e69d27..3b41785aff 100644
--- a/tp/Texinfo/XS/main/call_perl_function.c
+++ b/tp/Texinfo/XS/main/call_perl_function.c
@@ -141,8 +141,7 @@ call_latex_convert_to_latex_math (CONVERTER *self, ELEMENT 
*element)
     croak("convert_to_latex_math should return 1 item\n");
 
   result_sv = POPs;
-  /* FIXME encoding */
-  result_ret = SvPV (result_sv, len);
+  result_ret = SvPVutf8 (result_sv, len);
   result = strdup (result_ret);
 
   PUTBACK;
diff --git a/tp/Texinfo/XS/main/convert_to_text.c 
b/tp/Texinfo/XS/main/convert_to_text.c
index fa71a6b677..46004fc579 100644
--- a/tp/Texinfo/XS/main/convert_to_text.c
+++ b/tp/Texinfo/XS/main/convert_to_text.c
@@ -152,17 +152,17 @@ copy_options_for_convert_text (CONVERTER *self,
   TEXT_OPTIONS *options = new_text_options ();
   int text_indicator_option;
 
-  if ((self->conf->ENABLE_ENCODING > 0
-       && self->conf->OUTPUT_ENCODING_NAME)
+  if ((self->conf->ENABLE_ENCODING.integer > 0
+       && self->conf->OUTPUT_ENCODING_NAME.string)
       || (enable_encoding_if_not_ascii
-          && self->conf->OUTPUT_ENCODING_NAME
-          && strcmp (self->conf->OUTPUT_ENCODING_NAME, "us-ascii")))
+          && self->conf->OUTPUT_ENCODING_NAME.string
+          && strcmp (self->conf->OUTPUT_ENCODING_NAME.string, "us-ascii")))
     {
-      options->encoding = self->conf->OUTPUT_ENCODING_NAME;
+      options->encoding = self->conf->OUTPUT_ENCODING_NAME.string;
     }
 
   #define tico_option_name(name) \
-  text_indicator_option = self->conf->name; \
+  text_indicator_option = self->conf->name.integer; \
   if (text_indicator_option > 0) { options->name = 1; } \
   else if (text_indicator_option >= 0) { options->name = 0; }
    TEXT_INDICATOR_CONVERTER_OPTIONS
@@ -171,7 +171,8 @@ copy_options_for_convert_text (CONVERTER *self,
   free (options->expanded_formats);
   options->expanded_formats = self->expanded_formats;
 
-  memcpy (&options->include_directories, &self->conf->INCLUDE_DIRECTORIES,
+  memcpy (&options->include_directories,
+          &self->conf->INCLUDE_DIRECTORIES.strlist,
           sizeof (STRING_LIST));
 
   options->other_converter_options = self->conf;
diff --git a/tp/Texinfo/XS/main/convert_utils.c 
b/tp/Texinfo/XS/main/convert_utils.c
index 6abf1c2eb1..3fc8b948e0 100644
--- a/tp/Texinfo/XS/main/convert_utils.c
+++ b/tp/Texinfo/XS/main/convert_utils.c
@@ -66,7 +66,7 @@ expand_today (OPTIONS *options)
   ELEMENT *year_element;
   ELEMENT *result;
 
-  if (options->TEST > 0)
+  if (options->TEST.integer > 0)
     {
       result = new_element (ET_NONE);
       text_append (&result->text, "a sunny day");
@@ -272,9 +272,9 @@ encoded_input_file_name (OPTIONS *options,
   char *encoding = 0;
   int status;
 
-  if (options && options->INPUT_FILE_NAME_ENCODING)
-    encoding = options->INPUT_FILE_NAME_ENCODING;
-  else if (options && options->DOC_ENCODING_FOR_INPUT_FILE_NAME != 0
+  if (options && options->INPUT_FILE_NAME_ENCODING.string)
+    encoding = options->INPUT_FILE_NAME_ENCODING.string;
+  else if (options && options->DOC_ENCODING_FOR_INPUT_FILE_NAME.integer != 0
            || (!options))
     {
       if (input_file_encoding)
@@ -283,7 +283,7 @@ encoded_input_file_name (OPTIONS *options,
         encoding = global_information->input_encoding_name;
     }
   else if (options)
-    encoding = options->LOCALE_ENCODING;
+    encoding = options->LOCALE_ENCODING.string;
 
   result = encode_string (file_name, encoding, &status, source_info);
 
@@ -303,16 +303,16 @@ encoded_output_file_name (OPTIONS *options, GLOBAL_INFO 
*global_information,
   char *encoding = 0;
   int status;
 
-  if (options && options->OUTPUT_FILE_NAME_ENCODING)
-    encoding = options->OUTPUT_FILE_NAME_ENCODING;
-  else if (options && options->DOC_ENCODING_FOR_OUTPUT_FILE_NAME != 0
+  if (options && options->OUTPUT_FILE_NAME_ENCODING.string)
+    encoding = options->OUTPUT_FILE_NAME_ENCODING.string;
+  else if (options && options->DOC_ENCODING_FOR_OUTPUT_FILE_NAME.integer != 0
            || (!options))
     {
       if (global_information && global_information->input_encoding_name)
         encoding = global_information->input_encoding_name;
     }
   else if (options)
-    encoding = options->LOCALE_ENCODING;
+    encoding = options->LOCALE_ENCODING.string;
 
   result = encode_string (file_name, encoding, &status, source_info);
 
@@ -346,7 +346,7 @@ expand_verbatiminclude (ERROR_MESSAGE_LIST *error_messages,
                                        &current->source_info);
 
   if (options)
-    include_directories = &options->INCLUDE_DIRECTORIES;
+    include_directories = options->INCLUDE_DIRECTORIES.strlist;
 
   file = locate_include_file (file_name, include_directories);
 
diff --git a/tp/Texinfo/XS/main/converter_types.h 
b/tp/Texinfo/XS/main/converter_types.h
index 629abd67b1..9e455f2b22 100644
--- a/tp/Texinfo/XS/main/converter_types.h
+++ b/tp/Texinfo/XS/main/converter_types.h
@@ -30,6 +30,13 @@
 /* for interdependency with options_types.h */
 struct OPTIONS;
 
+/* for string information passing to/from perl */
+enum sv_string_type {
+  svt_byte,
+  svt_dir,
+  svt_char,
+};
+
 enum formatting_reference_status {
    FRS_status_none,
    FRS_status_default_set,        /* default is set, no customization (or
@@ -191,6 +198,18 @@ enum htmlxref_split_type {
    htmlxref_split_type_chapter,
 };
 
+enum global_option_type {
+   GO_NONE,
+   GO_integer,
+   GO_char,
+   GO_bytes,
+   GO_icons,
+   GO_buttons,
+   GO_bytes_string_list,
+   GO_file_string_list,
+   GO_char_string_list,
+};
+
 typedef struct {
     enum command_id *stack;
     size_t top;   /* One above last pushed command. */
@@ -917,4 +936,16 @@ typedef struct DIRECTION_ICON_LIST {
     char **list;
 } DIRECTION_ICON_LIST;
 
+typedef struct OPTION {
+    enum global_option_type type;
+    int set;
+    union {
+      int integer;
+      char *string;
+      STRING_LIST *strlist;
+      BUTTON_SPECIFICATION_LIST *buttons;
+      DIRECTION_ICON_LIST *icons;
+    };
+} OPTION;
+
 #endif
diff --git a/tp/Texinfo/XS/main/errors.c b/tp/Texinfo/XS/main/errors.c
index 6876717295..a7c019630f 100644
--- a/tp/Texinfo/XS/main/errors.c
+++ b/tp/Texinfo/XS/main/errors.c
@@ -165,7 +165,7 @@ message_list_document_formatted_message (ERROR_MESSAGE_LIST 
*error_messages,
   text_init (&error_line);
   text_append (&error_line, "");
 
-  if (conf && conf->PROGRAM && strlen (conf->PROGRAM))
+  if (conf && conf->PROGRAM.string && strlen (conf->PROGRAM.string))
     {
       if (type == MSG_document_warning)
         {
@@ -173,16 +173,16 @@ message_list_document_formatted_message 
(ERROR_MESSAGE_LIST *error_messages,
           text_printf (&error_line,
                        pgettext ("whole document warning",
                                  "%s: warning: %s"),
-                       conf->PROGRAM, error_message->message);
+                       conf->PROGRAM.string, error_message->message);
 #else
           text_printf (&error_line, "%s: warning: %s",
-                       conf->PROGRAM, error_message->message);
+                       conf->PROGRAM.string, error_message->message);
 #endif
         }
       else
         {
           text_printf (&error_line, "%s: %s",
-                       conf->PROGRAM, error_message->message);
+                       conf->PROGRAM.string, error_message->message);
         }
     }
   else
@@ -208,7 +208,7 @@ message_list_document_formatted_message (ERROR_MESSAGE_LIST 
*error_messages,
 
   error_message->error_line = error_line.text;
 
-  if (conf && conf->DEBUG > 0)
+  if (conf && conf->DEBUG.integer > 0)
     fprintf (stderr, "%s", error_message->error_line);
 }
 
@@ -241,7 +241,7 @@ message_list_line_error_ext (ERROR_MESSAGE_LIST 
*error_messages,
 
   va_start (v, format);
   vmessage_list_line_error (error_messages, type, continuation,
-                            (conf && conf->DEBUG > 0),
+                            (conf && conf->DEBUG.integer > 0),
                             cmd_source_info, format, v);
 }
 
@@ -254,7 +254,7 @@ message_list_command_warn (ERROR_MESSAGE_LIST 
*error_messages,
 
   va_start (v, format);
   vmessage_list_line_error (error_messages, MSG_warning, 0,
-                            (conf && conf->DEBUG > 0),
+                            (conf && conf->DEBUG.integer > 0),
                              &e->source_info, format, v);
 }
 
@@ -266,7 +266,7 @@ vmessage_list_command_warn (ERROR_MESSAGE_LIST 
*error_messages,
                             const ELEMENT *e, const char *format, va_list v)
 {
   vmessage_list_line_error (error_messages, MSG_warning, 0,
-                            (conf && conf->DEBUG > 0),
+                            (conf && conf->DEBUG.integer > 0),
                             &e->source_info, format, v);
 }
 
@@ -279,7 +279,7 @@ message_list_command_error (ERROR_MESSAGE_LIST 
*error_messages,
 
   va_start (v, format);
   vmessage_list_line_error (error_messages, MSG_error, 0,
-                           (conf && conf->DEBUG > 0),
+                           (conf && conf->DEBUG.integer > 0),
                            &e->source_info, format, v);
 }
 
diff --git a/tp/Texinfo/XS/main/get_perl_info.c 
b/tp/Texinfo/XS/main/get_perl_info.c
index 7a2504400c..961e838cae 100644
--- a/tp/Texinfo/XS/main/get_perl_info.c
+++ b/tp/Texinfo/XS/main/get_perl_info.c
@@ -242,7 +242,7 @@ void
 get_line_message (CONVERTER *self, enum error_type type, int continuation,
                   SV *error_location_info, char *message)
 {
-  int do_warn = (self->conf->DEBUG > 1);
+  int do_warn = (self->conf->DEBUG.integer > 1);
   SOURCE_INFO *source_info = get_source_info (error_location_info);
   if (source_info->file_name)
     {
@@ -268,34 +268,47 @@ get_line_message (CONVERTER *self, enum error_type type, 
int continuation,
 }
 
 void
-get_sv_options (SV *sv, OPTIONS *options, CONVERTER *converter)
+get_sv_options (SV *sv, OPTIONS *options, CONVERTER *converter, SV *set_sv_in)
 {
   I32 hv_number;
   I32 i;
   HV *hv;
+  HV *set_hv = 0;
 
   dTHX;
 
   hv = (HV *)SvRV (sv);
+
+  if (set_sv_in)
+    set_hv = (HV *)SvRV (set_sv_in);
+
   hv_number = hv_iterinit (hv);
   for (i = 0; i < hv_number; i++)
     {
+      int set = 0;
       char *key;
       I32 retlen;
       SV *value = hv_iternextsv(hv, &key, &retlen);
       if (value && SvOK (value))
         {
-          get_sv_option (options, key, value, converter);
+          if (set_hv)
+            {
+              SV **value_set_sv = hv_fetch (set_hv, key, strlen (key), 0);
+              if (value_set_sv && SvOK (*value_set_sv)
+                  && SvIV (*value_set_sv))
+                set = 1;
+            }
+          get_sv_option (options, key, value, set, converter);
         }
     }
 }
 
 
 OPTIONS *
-copy_sv_options (SV *sv_in, CONVERTER *converter)
+copy_sv_options (SV *sv_in, CONVERTER *converter, SV *set_sv_in)
 {
   OPTIONS *options = new_options ();
-  get_sv_options (sv_in, options, converter);
+  get_sv_options (sv_in, options, converter, set_sv_in);
   return options;
 }
 
@@ -476,8 +489,15 @@ converter_initialize (SV *converter_sv)
 
   if (conf_sv && SvOK (*conf_sv))
     {
+      SV **set_sv;
+      SV *set_arg = 0;
+
+      FETCH(set);
+
+      if (set_sv && SvOK (*set_sv))
+        set_arg = *set_sv;
       converter->conf
-         = copy_sv_options (*conf_sv, converter);
+         = copy_sv_options (*conf_sv, converter, set_arg);
     }
 
   FETCH(converter_init_conf)
@@ -485,7 +505,7 @@ converter_initialize (SV *converter_sv)
   if (converter_init_conf_sv && SvOK (*converter_init_conf_sv))
     {
       converter->init_conf
-         = copy_sv_options (*converter_init_conf_sv, converter);
+         = copy_sv_options (*converter_init_conf_sv, converter, 0);
     }
 
 #undef FETCH
@@ -515,11 +535,19 @@ recopy_converter_conf_sv (HV *hv, CONVERTER *converter,
 
   if (conf_sv && SvOK(*conf_sv))
     {
+      SV **set_sv;
+      SV *set_arg = 0;
+
       if (*conf)
         free_options (*conf);
       free (*conf);
 
-      *conf = copy_sv_options (*conf_sv, converter);
+      set_sv = hv_fetch (hv, "set", strlen ("set"), 0);
+
+      if (set_sv && SvOK (*set_sv))
+        set_arg = *set_sv;
+
+      *conf = copy_sv_options (*conf_sv, converter, set_arg);
     }
 }
 
@@ -777,13 +805,20 @@ void
 set_conf (CONVERTER *converter, const char *conf, SV *value)
 {
   if (converter->conf)
-    get_sv_option (converter->conf, conf, value, converter);
+    get_sv_option (converter->conf, conf, value, -1, converter);
    /* Too early to have options set
   else
     fprintf (stderr, "HHH no converter conf %s\n", conf);
     */
 }
 
+void
+force_conf (CONVERTER *converter, const char *conf, SV *value)
+{
+  if (converter->conf)
+    get_sv_option (converter->conf, conf, value, 0, converter);
+}
+
 /* output format specific */
 
 /* map hash reference of Convert::Text options to TEXT_OPTIONS */
@@ -833,7 +868,7 @@ copy_sv_options_for_convert_text (SV *sv_in)
   if (other_converter_options_sv)
     {
       text_options->other_converter_options
-         = copy_sv_options (*other_converter_options_sv, 0);
+         = copy_sv_options (*other_converter_options_sv, 0, 0);
     }
 
   self_converter_options_sv = hv_fetch (hv_in, "self_converter_options",
@@ -842,7 +877,7 @@ copy_sv_options_for_convert_text (SV *sv_in)
   if (self_converter_options_sv)
     {
       text_options->self_converter_options
-         = copy_sv_options (*self_converter_options_sv, 0);
+         = copy_sv_options (*self_converter_options_sv, 0, 0);
     }
 
   return text_options;
@@ -1048,7 +1083,7 @@ html_get_direction_icons_sv (CONVERTER *converter,
 
   icons_hv = (HV *)SvRV (icons_sv);
 
-  for (i = 0; converter->direction_unit_direction_name[i] ; i++)
+  for (i = 0; converter->direction_unit_direction_name[i]; i++)
     {
       const char *direction_name
         = converter->direction_unit_direction_name[i];
diff --git a/tp/Texinfo/XS/main/get_perl_info.h 
b/tp/Texinfo/XS/main/get_perl_info.h
index cb72e37d2d..50aa4faca7 100644
--- a/tp/Texinfo/XS/main/get_perl_info.h
+++ b/tp/Texinfo/XS/main/get_perl_info.h
@@ -11,15 +11,9 @@
 #include "converter_types.h"
 #include "convert_to_text.h"
 
-enum sv_string_type {
-  svt_byte,
-  svt_dir,
-  svt_char,
-};
-
 /* in options_get_perl.c */
 void get_sv_option (OPTIONS *options, const char *key, SV *value,
-                    CONVERTER *converter);
+                    int set, CONVERTER *converter);
 
 DOCUMENT *get_sv_tree_document (SV *tree_in, char *warn_string);
 DOCUMENT *get_sv_document_document (SV *document_in, char *warn_string);
@@ -33,10 +27,11 @@ void add_svav_to_string_list (SV *sv, STRING_LIST 
*string_list,
 SOURCE_INFO *get_source_info (SV *source_info_sv);
 void get_line_message (CONVERTER *self, enum error_type type, int continuation,
                        SV *error_location_info, char *message);
-OPTIONS *copy_sv_options (SV *sv_in, CONVERTER *converter);
+OPTIONS *copy_sv_options (SV *sv_in, CONVERTER *converter, SV *set_sv_in);
 void recopy_converter_conf_sv (HV *hv, CONVERTER *converter,
                                OPTIONS **conf, const char *conf_key);
 void set_conf (CONVERTER *converter, const char *conf, SV *value);
+void force_conf (CONVERTER *converter, const char *conf, SV *value);
 
 CONVERTER *set_output_converter_sv (SV *sv_in, const char *warn_string);
 CONVERTER *get_sv_converter (SV *sv_in, const char *warn_string);
diff --git a/tp/Texinfo/XS/main/output_unit.c b/tp/Texinfo/XS/main/output_unit.c
index f0a089c3f4..a8e34ed837 100644
--- a/tp/Texinfo/XS/main/output_unit.c
+++ b/tp/Texinfo/XS/main/output_unit.c
@@ -747,7 +747,7 @@ units_directions (OPTIONS *customization_information,
 
       /* Use node up for Up if there is no section up.
          Not done in the default case. */
-      if (customization_information->USE_UP_NODE_FOR_ELEMENT_UP > 0
+      if (customization_information->USE_UP_NODE_FOR_ELEMENT_UP.integer > 0
           && !directions[RUD_type_Up] && node
           && node_directions && node_directions->contents.list[D_up]
           && (!node_top || node != node_top))
@@ -758,7 +758,7 @@ units_directions (OPTIONS *customization_information,
             directions[RUD_type_Up] = up_node_unit_element;
         }
     }
-  if (customization_information->DEBUG > 0)
+  if (customization_information->DEBUG.integer > 0)
     {
       int i;
       for (i = 0; i < output_units->number; i++)
diff --git a/tp/Texinfo/XS/main/translations.c 
b/tp/Texinfo/XS/main/translations.c
index 8f5448263f..4b626fb637 100644
--- a/tp/Texinfo/XS/main/translations.c
+++ b/tp/Texinfo/XS/main/translations.c
@@ -162,8 +162,8 @@ translate_string (OPTIONS *options, const char * string,
   static TEXT language_locales;
   int i;
 
-  if ((!lang) && options && options->documentlanguage)
-    lang = options->documentlanguage;
+  if ((!lang) && options && options->documentlanguage.string)
+    lang = options->documentlanguage.string;
   if (!lang)
     lang = "en";
 
@@ -512,7 +512,7 @@ replace_convert_substrings (OPTIONS *options, char 
*translated_string,
   /*
   debug ("IN TR PARSER '%s'", texinfo_line);
    */
-  if (options && options->DEBUG > 0)
+  if (options && options->DEBUG.integer > 0)
     fprintf (stderr, "XS|IN TR PARSER '%s'\n", texinfo_line);
 
   document = retrieve_document (document_descriptor);
@@ -540,7 +540,7 @@ replace_convert_substrings (OPTIONS *options, char 
*translated_string,
 /*
   {
     char *result_texi = convert_to_texinfo (document->tree);
-    if (options && options->DEBUG > 0)
+    if (options && options->DEBUG.integer > 0)
       fprintf (stderr, "XS|RESULT GDT %d: '%s'\n", document_descriptor,
                result_texi);
     free (result_texi);
diff --git a/tp/Texinfo/XS/main/utils.c b/tp/Texinfo/XS/main/utils.c
index 31e167acf1..bc01f086e8 100644
--- a/tp/Texinfo/XS/main/utils.c
+++ b/tp/Texinfo/XS/main/utils.c
@@ -1075,17 +1075,16 @@ set_informative_command_value (OPTIONS *options, const 
ELEMENT *element)
 
   if (value)
     {
-      COMMAND_OPTION_REF *option_ref = get_command_option (options, cmd);
-      if (option_ref)
+      OPTION *option = get_command_option (options, cmd);
+      if (option && option->set <= 0)
         {
-          if (option_ref->type == GO_int)
-            *(option_ref->int_ref) = strtoul (value, NULL, 10);
+          if (option->type == GO_integer)
+            option->integer = strtoul (value, NULL, 10);
           else
             {
-              free (*(option_ref->char_ref));
-              *(option_ref->char_ref) = strdup (value);
+              free (option->string);
+              option->string = strdup (value);
             }
-          free (option_ref);
         }
     }
 }
@@ -1187,16 +1186,6 @@ set_global_document_command (GLOBAL_COMMANDS 
*global_commands, OPTIONS *options,
 }
 
 
-/* options and converters */
-OPTIONS *
-new_options (void)
-{
-  OPTIONS *options = (OPTIONS *) malloc (sizeof (OPTIONS));
-  initialize_options (options);
-  return options;
-}
-
-
 void
 destroy_accent_stack (ACCENTS_STACK *accent_stack)
 {
@@ -1425,4 +1414,79 @@ html_free_direction_icons (DIRECTION_ICON_LIST 
*direction_icons)
   free (direction_icons->list);
 }
 
+
+/* options and converters */
+OPTIONS *
+new_options (void)
+{
+  OPTIONS *options = (OPTIONS *) malloc (sizeof (OPTIONS));
+  memset (options, 0, sizeof (OPTIONS));
+  initialize_options (options);
+  return options;
+}
+
+void
+free_option (OPTION *option)
+{
+  switch (option->type)
+    {
+      case GO_char:
+      case GO_bytes:
+        free (option->string);
+        break;
+
+      case GO_bytes_string_list:
+      case GO_file_string_list:
+      case GO_char_string_list:
+        free_strings_list (option->strlist);
+        break;
+
+      case GO_buttons:
+        html_free_button_specification_list (option->buttons);
+        break;
+
+      case GO_icons:
+        html_free_direction_icons (option->icons);
+        break;
+
+      case GO_integer:
+      default:
+    }
+}
+
+void
+initialize_option (OPTION *option, enum global_option_type type)
+{
+  option->type = type;
+  switch (type)
+    {
+      case GO_integer:
+        option->integer = -1;
+        break;
+
+      case GO_bytes_string_list:
+      case GO_file_string_list:
+      case GO_char_string_list:
+        option->strlist = (STRING_LIST *) malloc (sizeof (STRING_LIST));
+        memset (option->strlist, 0, sizeof (STRING_LIST));
+        break;
+
+      case GO_char:
+      case GO_bytes:
+        option->string = 0;
+        break;
+
+      case GO_buttons:
+        option->buttons = 0;
+        break;
+
+      case GO_icons:
+        option->icons = (DIRECTION_ICON_LIST *)
+                          malloc (sizeof (DIRECTION_ICON_LIST));
+        memset (option->icons, 0, sizeof (DIRECTION_ICON_LIST));
+        break;
+
+      default:
+    }
+}
 
diff --git a/tp/Texinfo/XS/main/utils.h b/tp/Texinfo/XS/main/utils.h
index 795ca1ebc9..9d44bc04b4 100644
--- a/tp/Texinfo/XS/main/utils.h
+++ b/tp/Texinfo/XS/main/utils.h
@@ -67,15 +67,9 @@ typedef struct {
 
 extern DEF_ALIAS def_aliases[];
 
-enum global_option_command_type {
-   GO_NONE,
-   GO_int,
-   GO_char,
-};
-
 /* definitions for table of defaults for options corresponding to commands */
 typedef struct COMMAND_OPTION_DEFAULT {
-    enum global_option_command_type type;
+    enum global_option_type type;
     int value;
     char *string;
 } COMMAND_OPTION_DEFAULT;
@@ -84,7 +78,7 @@ extern COMMAND_OPTION_DEFAULT command_option_default_table[];
 
 /* return type of get_command_option */
 typedef struct COMMAND_OPTION_REF {
-    enum global_option_command_type type;
+    enum global_option_type type;
     union {
       int *int_ref;
       char **char_ref;
@@ -93,7 +87,7 @@ typedef struct COMMAND_OPTION_REF {
 
 /* similar to COMMAND_OPTION_REF but for values only */
 typedef struct COMMAND_OPTION_VALUE {
-    enum global_option_command_type type;
+    enum global_option_type type;
     union {
       int int_value;
       char *char_value;
@@ -218,7 +212,7 @@ void initialize_options (OPTIONS *options);
 void free_options (OPTIONS *options);
 
 OPTIONS *new_options (void);
-COMMAND_OPTION_REF *get_command_option (OPTIONS *options, enum command_id cmd);
+OPTION *get_command_option (OPTIONS *options, enum command_id cmd);
 
 void add_include_directory (char *filename, STRING_LIST *include_dirs_list);
 char *locate_include_file (char *filename, STRING_LIST *include_dirs_list);
@@ -257,4 +251,7 @@ ELEMENT *get_cmd_global_uniq_command (GLOBAL_COMMANDS 
*global_commands_ref,
 void html_free_button_specification_list (BUTTON_SPECIFICATION_LIST *buttons);
 void html_free_direction_icons (DIRECTION_ICON_LIST *direction_icons);
 
+void free_option (OPTION *option);
+void initialize_option (OPTION *option, enum global_option_type type);
+
 #endif
diff --git a/tp/Texinfo/XS/structuring_transfo/structuring.c 
b/tp/Texinfo/XS/structuring_transfo/structuring.c
index 6bf36e4467..da5aeb9f0b 100644
--- a/tp/Texinfo/XS/structuring_transfo/structuring.c
+++ b/tp/Texinfo/XS/structuring_transfo/structuring.c
@@ -810,8 +810,8 @@ set_menus_node_directions (DOCUMENT *document)
   if (!nodes_list || nodes_list->number <= 0)
     return;
 
-  if (options && (options->novalidate > 0
-                  || strcmp (options->FORMAT_MENU, "menu")))
+  if (options && (options->novalidate.integer > 0
+                  || strcmp (options->FORMAT_MENU.string, "menu")))
     check_menu_entries = 0;
 
   /*
@@ -1038,7 +1038,7 @@ complete_node_tree_with_menus (DOCUMENT *document)
                   section = lookup_extra_element (node, "associated_section");
                   if (section
                       && ((!options)
-                          || options->CHECK_NORMAL_MENU_STRUCTURE > 0))
+                          || options->CHECK_NORMAL_MENU_STRUCTURE.integer > 0))
                     {
                       ELEMENT *node_direction_section = section;
                       ELEMENT *part_section;
@@ -1107,7 +1107,7 @@ complete_node_tree_with_menus (DOCUMENT *document)
                       if (!menu_direction_manual_content)
                         {
                           if (((!options)
-                               || options->CHECK_NORMAL_MENU_STRUCTURE > 0)
+                           || options->CHECK_NORMAL_MENU_STRUCTURE.integer > 0)
                               && section)
                             {
                               char *node_texi
@@ -1184,7 +1184,7 @@ complete_node_tree_with_menus (DOCUMENT *document)
         }
   /* check consistency between node pointer and node entries menu order */
       if (((!options)
-           || options->CHECK_NORMAL_MENU_STRUCTURE > 0)
+           || options->CHECK_NORMAL_MENU_STRUCTURE.integer > 0)
           && strcmp (normalized, "Top"))
         {
           ELEMENT *node_directions = lookup_extra_element (node,
@@ -1226,7 +1226,7 @@ complete_node_tree_with_menus (DOCUMENT *document)
         }
       /* check for node up / menu up mismatch */
       if ((!options)
-          || options->CHECK_MISSING_MENU_ENTRY > 0)
+          || options->CHECK_MISSING_MENU_ENTRY.integer > 0)
         {
           ELEMENT *node_directions = lookup_extra_element (node,
                                                            "node_directions");
@@ -1436,7 +1436,7 @@ nodes_tree (DOCUMENT *document)
                           node_directions->contents.list[direction]
                             = node_target;
                           if ((!options)
-                               || options->novalidate <= 0)
+                               || options->novalidate.integer <= 0)
                             {
                               ELEMENT *direction_node_content
                                 = lookup_extra_element (direction_element,
@@ -1466,7 +1466,7 @@ nodes_tree (DOCUMENT *document)
                       else
                         {
                           if ((!options)
-                               || options->novalidate <= 0)
+                               || options->novalidate.integer <= 0)
                             {
                               char *direction_texi
                                  = link_element_to_texi(direction_element);
@@ -1545,7 +1545,7 @@ associate_internal_references (DOCUMENT *document)
           if (!node_target)
             {
               if ((!options)
-                  || options->novalidate <= 0)
+                  || options->novalidate.integer <= 0)
                 {
                   char *label_texi = link_element_to_texi (label_element);
                   message_list_command_error (error_messages, options,
@@ -1559,7 +1559,7 @@ associate_internal_references (DOCUMENT *document)
               label_node_content = lookup_extra_element (label_element,
                                                          "node_content");
               if ((!options)
-                  || options->novalidate <= 0)
+                  || options->novalidate.integer <= 0)
                 {
                   if (!check_node_same_texinfo_code (node_target,
                                                      label_node_content))
diff --git a/tp/Texinfo/options_data.txt b/tp/Texinfo/options_data.txt
index f238b1f5a0..249af3932b 100644
--- a/tp/Texinfo/options_data.txt
+++ b/tp/Texinfo/options_data.txt
@@ -29,153 +29,153 @@
 # values.
 # also used in util/txicustomvars
 
-allowcodebreaks            multiple_at_command true     char *
-clickstyle                 multiple_at_command @arrow   char *
-codequotebacktick          multiple_at_command off      char *
-codequoteundirected        multiple_at_command off      char *
-contents                   multiple_at_command 0        int
-deftypefnnewline           multiple_at_command off      char *
-documentencoding           multiple_at_command utf-8    char *
+allowcodebreaks            multiple_at_command true     char
+clickstyle                 multiple_at_command @arrow   char
+codequotebacktick          multiple_at_command off      char
+codequoteundirected        multiple_at_command off      char
+contents                   multiple_at_command 0        integer
+deftypefnnewline           multiple_at_command off      char
+documentencoding           multiple_at_command utf-8    char
 
 # Documented as en, but no @documentlanguage
 # really means that the language is not set.
 # --document-language
-documentlanguage           multiple_at_command undef    char *
+documentlanguage           multiple_at_command undef    char
 
-evenfooting                multiple_at_command undef    char *
-evenheading                multiple_at_command undef    char *
-everyfooting               multiple_at_command undef    char *
-everyheading               multiple_at_command undef    char *
+evenfooting                multiple_at_command undef    char
+evenheading                multiple_at_command undef    char
+everyfooting               multiple_at_command undef    char
+everyheading               multiple_at_command undef    char
 # is N ems in TeX, 0.4 in.  Can be asis or a number
-exampleindent              multiple_at_command 5        char *
-firstparagraphindent       multiple_at_command none     char *
-frenchspacing              multiple_at_command off      char *
-headings                   multiple_at_command on       char *
-kbdinputstyle              multiple_at_command distinct char *
-microtype                  multiple_at_command undef    char *
-oddheading                 multiple_at_command undef    char *
-oddfooting                 multiple_at_command undef    char *
-paragraphindent            multiple_at_command 3        char *
-shortcontents              multiple_at_command 0        int
-summarycontents            multiple_at_command 0        int
-urefbreakstyle             multiple_at_command after    char *
-xrefautomaticsectiontitle  multiple_at_command off      char *
+exampleindent              multiple_at_command 5        char
+firstparagraphindent       multiple_at_command none     char
+frenchspacing              multiple_at_command off      char
+headings                   multiple_at_command on       char
+kbdinputstyle              multiple_at_command distinct char
+microtype                  multiple_at_command undef    char
+oddheading                 multiple_at_command undef    char
+oddfooting                 multiple_at_command undef    char
+paragraphindent            multiple_at_command 3        char
+shortcontents              multiple_at_command 0        integer
+summarycontents            multiple_at_command 0        integer
+urefbreakstyle             multiple_at_command after    char
+xrefautomaticsectiontitle  multiple_at_command off      char
 
 
 # @-commands that should be unique.
 # also used in util/txicustomvars
-afivepaper           unique_at_command undef   char *
-afourpaper           unique_at_command undef   char *
-afourlatex           unique_at_command undef   char *
-afourwide            unique_at_command undef   char *
-bsixpaper            unique_at_command undef   char *
+afivepaper           unique_at_command undef   char
+afourpaper           unique_at_command undef   char
+afourlatex           unique_at_command undef   char
+afourwide            unique_at_command undef   char
+bsixpaper            unique_at_command undef   char
 # when passed through a customization variable, documentdescription
 # should be already formatted for HTML.  There is no default,
 # what is determined to be the title is used if not set.
-documentdescription  unique_at_command undef   char *
-evenfootingmarks     unique_at_command undef   char *
-evenheadingmarks     unique_at_command undef   char *
-everyfootingmarks    unique_at_command bottom  char *
-everyheadingmarks    unique_at_command bottom  char *
-fonttextsize         unique_at_command 11      int
+documentdescription  unique_at_command undef   char
+evenfootingmarks     unique_at_command undef   char
+evenheadingmarks     unique_at_command undef   char
+everyfootingmarks    unique_at_command bottom  char
+everyheadingmarks    unique_at_command bottom  char
+fonttextsize         unique_at_command 11      integer
 # --footnote-style
-footnotestyle        unique_at_command end     char *
+footnotestyle        unique_at_command end     char
 # --no-validate
-novalidate           unique_at_command 0       int
-oddfootingmarks      unique_at_command undef   char *
-oddheadingmarks      unique_at_command undef   char *
-pagesizes            unique_at_command undef   char *
-setchapternewpage    unique_at_command on      char *
-setfilename          unique_at_command undef   char *
-smallbook            unique_at_command undef   char *
+novalidate           unique_at_command 0       integer
+oddfootingmarks      unique_at_command undef   char
+oddheadingmarks      unique_at_command undef   char
+pagesizes            unique_at_command undef   char
+setchapternewpage    unique_at_command on      char
+setfilename          unique_at_command undef   char
+smallbook            unique_at_command undef   char
 
 
 # comand-line options that are primarily used to control conversion.
 # a value corresponds to defaults that are the same for every output format
 # otherwise undef is used
 # --split-size
-SPLIT_SIZE                converter_cmdline 300000  int
+SPLIT_SIZE                converter_cmdline 300000  integer
 # --fill-column
-FILLCOLUMN                converter_cmdline 72      int
+FILLCOLUMN                converter_cmdline 72      integer
 # --number-sections
-NUMBER_SECTIONS           converter_cmdline 1       int
+NUMBER_SECTIONS           converter_cmdline 1       integer
 # --number-footnotes
-NUMBER_FOOTNOTES          converter_cmdline 1       int
+NUMBER_FOOTNOTES          converter_cmdline 1       integer
 # only in HTML
 # --transliterate-file-names
-TRANSLITERATE_FILE_NAMES  converter_cmdline 1       int
+TRANSLITERATE_FILE_NAMES  converter_cmdline 1       integer
 # --split
-SPLIT                     converter_cmdline undef   char *
+SPLIT                     converter_cmdline undef   char
 # --headers.  Used to set diverse
 # customization options in main program.
 # Only directly used in HTML converter
-HEADERS                   converter_cmdline 1       int
+HEADERS                   converter_cmdline 1       integer
 # --node-files.  Default depends on SPLIT;  Used in HTML only.
-NODE_FILES                converter_cmdline undef   int
+NODE_FILES                converter_cmdline undef   integer
 # --verbose
-VERBOSE                   converter_cmdline undef   int
+VERBOSE                   converter_cmdline undef   integer
 # --output    Sets OUTPUT if non split and not ending by /.
 # Setting can be format dependent
-OUTFILE                   converter_cmdline undef   char *
+OUTFILE                   converter_cmdline undef   char
 # --output    Sets SUBDIR if split or ending by /.
 # Setting can be format dependent
-SUBDIR                    converter_cmdline undef   char *
+SUBDIR                    converter_cmdline undef   char
 # --disable-encoding/--enable-encoding.
 # The option is directly used in
 # Info/Plaintext, and used in diverse formats
 # for index sorting and plain text output.
-ENABLE_ENCODING           converter_cmdline 1       int
+ENABLE_ENCODING           converter_cmdline 1       integer
 
 
 # used in main program, defaults documented in manual
 # --macro-expand.  Only for main program
-MACRO_EXPAND    program_cmdline undef  char *
+MACRO_EXPAND    program_cmdline undef  bytes
 # used in HTML only, called from main program
 # --internal-links
-INTERNAL_LINKS  program_cmdline undef  char *
+INTERNAL_LINKS  program_cmdline undef  bytes
 # --error-limit
-ERROR_LIMIT     program_cmdline 100    int
+ERROR_LIMIT     program_cmdline 100    integer
 # --force
-FORCE           program_cmdline undef  int
+FORCE           program_cmdline undef  integer
 # --no-warn
-NO_WARN         program_cmdline undef  int
+NO_WARN         program_cmdline undef  integer
 # --silent.  Not used.  For completeness
-SILENT          program_cmdline undef  char *
+SILENT          program_cmdline undef  char
 
 # following also set in converters
 # --headers.  Modified by the format.
-FORMAT_MENU     program_cmdline menu   char *
+FORMAT_MENU     program_cmdline menu   char
 
 
 # output warnings when node with
 # automatic direction and directions in menu are not consistent
 # with sectionning, and when node directions are not consistent
 # with menu directions.
-CHECK_NORMAL_MENU_STRUCTURE  program_customization 0         int
-CHECK_MISSING_MENU_ENTRY     program_customization 1         int
-DUMP_TREE                    program_customization undef     int
-DUMP_TEXI                    program_customization undef     int
-SHOW_BUILTIN_CSS_RULES       program_customization 0         int
-SORT_ELEMENT_COUNT           program_customization undef     char *
-SORT_ELEMENT_COUNT_WORDS     program_customization undef     int
-TEXI2DVI                     program_customization texi2dvi  char *
-TREE_TRANSFORMATIONS         program_customization undef     char *
+CHECK_NORMAL_MENU_STRUCTURE  program_customization 0         integer
+CHECK_MISSING_MENU_ENTRY     program_customization 1         integer
+DUMP_TREE                    program_customization undef     integer
+DUMP_TEXI                    program_customization undef     integer
+SHOW_BUILTIN_CSS_RULES       program_customization 0         integer
+SORT_ELEMENT_COUNT           program_customization undef     char
+SORT_ELEMENT_COUNT_WORDS     program_customization undef     integer
+TEXI2DVI                     program_customization texi2dvi  char
+TREE_TRANSFORMATIONS         program_customization undef     char
 
 
 # up node of Top node default value
-TOP_NODE_UP                        converter_customization (dir)   char *
-BASEFILENAME_LENGTH                converter_customization 255-10  int
-DOC_ENCODING_FOR_INPUT_FILE_NAME   converter_customization 1       int
-DOC_ENCODING_FOR_OUTPUT_FILE_NAME  converter_customization 0       int
+TOP_NODE_UP                        converter_customization (dir)   char
+BASEFILENAME_LENGTH                converter_customization 255-10  integer
+DOC_ENCODING_FOR_INPUT_FILE_NAME   converter_customization 1       integer
+DOC_ENCODING_FOR_OUTPUT_FILE_NAME  converter_customization 0       integer
 # only used in HTML
-IMAGE_LINK_PREFIX                  converter_customization undef   char *
-CASE_INSENSITIVE_FILENAMES         converter_customization 0       int
-DEBUG                              converter_customization 0       int
+IMAGE_LINK_PREFIX                  converter_customization undef   char
+CASE_INSENSITIVE_FILENAMES         converter_customization 0       integer
+DEBUG                              converter_customization 0       integer
 # only used in HTML
-HANDLER_FATAL_ERROR_LEVEL          converter_customization 100     int
-TEST                               converter_customization 0       int
+HANDLER_FATAL_ERROR_LEVEL          converter_customization 100     integer
+TEST                               converter_customization 0       integer
 # for textcontent format
-TEXTCONTENT_COMMENT                converter_customization undef   int
+TEXTCONTENT_COMMENT                converter_customization undef   integer
 # used in TexinfoXML/SXML
 # Reset by the main program, therefore this value is only used in converter
 # tests that use the perl modules directly.  Does not need to match with the
@@ -183,164 +183,164 @@ TEXTCONTENT_COMMENT                
converter_customization undef   int
 # DTD is released, to have a fixed value for the tests.  However, it should
 # be good to update from time to time to avoid test results that are not
 # valid against their reported DTD.
-TEXINFO_DTD_VERSION                converter_customization 7.1     char *
+TEXINFO_DTD_VERSION                converter_customization 7.1     char
 
 # Some are for all converters, EXTENSION for instance, some for
 # some converters, for example CLOSE_QUOTE_SYMBOL and many
 # for HTML.
 # Defaults are documented in manual and set in the various converters.
 # used in util/txicustomvars
-AFTER_BODY_OPEN                    converter_customization undef   char *
-AFTER_SHORT_TOC_LINES              converter_customization undef   char *
-AFTER_TOC_LINES                    converter_customization undef   char *
-ASCII_DASHES_AND_QUOTES            converter_customization undef   int
-ASCII_GLYPH                        converter_customization undef   int
-ASCII_PUNCTUATION                  converter_customization undef   int
-AUTO_MENU_DESCRIPTION_ALIGN_COLUMN converter_customization undef   int
-AUTO_MENU_MAX_WIDTH                converter_customization undef   int
-AVOID_MENU_REDUNDANCY              converter_customization undef   int
-BEFORE_SHORT_TOC_LINES             converter_customization undef   char *
-BEFORE_TOC_LINES                   converter_customization undef   char *
-BIG_RULE                           converter_customization undef   char *
-BODYTEXT                           converter_customization undef   char *
+AFTER_BODY_OPEN                    converter_customization undef   char
+AFTER_SHORT_TOC_LINES              converter_customization undef   char
+AFTER_TOC_LINES                    converter_customization undef   char
+ASCII_DASHES_AND_QUOTES            converter_customization undef   integer
+ASCII_GLYPH                        converter_customization undef   integer
+ASCII_PUNCTUATION                  converter_customization undef   integer
+AUTO_MENU_DESCRIPTION_ALIGN_COLUMN converter_customization undef   integer
+AUTO_MENU_MAX_WIDTH                converter_customization undef   integer
+AVOID_MENU_REDUNDANCY              converter_customization undef   integer
+BEFORE_SHORT_TOC_LINES             converter_customization undef   char
+BEFORE_TOC_LINES                   converter_customization undef   char
+BIG_RULE                           converter_customization undef   char
+BODYTEXT                           converter_customization undef   char
 # for LaTeX
-CLASS_BEGIN_USEPACKAGE             converter_customization undef   char *
-COPIABLE_LINKS                     converter_customization undef   int
-CHAPTER_HEADER_LEVEL               converter_customization undef   int
-CHECK_HTMLXREF                     converter_customization undef   int
-CLOSE_DOUBLE_QUOTE_SYMBOL          converter_customization undef   char *
-CLOSE_QUOTE_SYMBOL                 converter_customization undef   char *
-COMMAND_LINE_ENCODING              converter_customization undef   char *
-COMPLEX_FORMAT_IN_TABLE            converter_customization undef   int
-CONTENTS_OUTPUT_LOCATION           converter_customization undef   char *
-CONVERT_TO_LATEX_IN_MATH           converter_customization undef   int
-DATE_IN_HEADER                     converter_customization undef   int
-DEFAULT_RULE                       converter_customization undef   char *
-DEF_TABLE                          converter_customization undef   int
-DO_ABOUT                           converter_customization undef   int
-DOCTYPE                            converter_customization undef   char *
+CLASS_BEGIN_USEPACKAGE             converter_customization undef   char
+COPIABLE_LINKS                     converter_customization undef   integer
+CHAPTER_HEADER_LEVEL               converter_customization undef   integer
+CHECK_HTMLXREF                     converter_customization undef   integer
+CLOSE_DOUBLE_QUOTE_SYMBOL          converter_customization undef   char
+CLOSE_QUOTE_SYMBOL                 converter_customization undef   char
+COMMAND_LINE_ENCODING              converter_customization undef   char
+COMPLEX_FORMAT_IN_TABLE            converter_customization undef   integer
+CONTENTS_OUTPUT_LOCATION           converter_customization undef   char
+CONVERT_TO_LATEX_IN_MATH           converter_customization undef   integer
+DATE_IN_HEADER                     converter_customization undef   integer
+DEFAULT_RULE                       converter_customization undef   char
+DEF_TABLE                          converter_customization undef   integer
+DO_ABOUT                           converter_customization undef   integer
+DOCTYPE                            converter_customization undef   char
 # for LaTeX
-END_USEPACKAGE                     converter_customization undef   char *
+END_USEPACKAGE                     converter_customization undef   char
 # for ext/epub3.pm
-EPUB_CREATE_CONTAINER_FILE         converter_customization undef   int
+EPUB_CREATE_CONTAINER_FILE         converter_customization undef   integer
 # for ext/epub3.pm
-EPUB_KEEP_CONTAINER_FOLDER         converter_customization undef   int
-EXTENSION                          converter_customization undef   char *
-EXTERNAL_CROSSREF_EXTENSION        converter_customization undef   char *
-EXTERNAL_CROSSREF_SPLIT            converter_customization undef   char *
-EXTERNAL_DIR                       converter_customization undef   char *
-EXTRA_HEAD                         converter_customization undef   char *
-FOOTNOTE_END_HEADER_LEVEL          converter_customization undef   int
-FOOTNOTE_SEPARATE_HEADER_LEVEL     converter_customization undef   int
-HEADER_IN_TABLE                    converter_customization undef   int
+EPUB_KEEP_CONTAINER_FOLDER         converter_customization undef   integer
+EXTENSION                          converter_customization undef   char
+EXTERNAL_CROSSREF_EXTENSION        converter_customization undef   char
+EXTERNAL_CROSSREF_SPLIT            converter_customization undef   char
+EXTERNAL_DIR                       converter_customization undef   char
+EXTRA_HEAD                         converter_customization undef   char
+FOOTNOTE_END_HEADER_LEVEL          converter_customization undef   integer
+FOOTNOTE_SEPARATE_HEADER_LEVEL     converter_customization undef   integer
+HEADER_IN_TABLE                    converter_customization undef   integer
 # for ext/highlight_syntax.pm
-HIGHLIGHT_SYNTAX                   converter_customization undef   char *
+HIGHLIGHT_SYNTAX                   converter_customization undef   char
 # for ext/highlight_syntax.pm
-HIGHLIGHT_SYNTAX_DEFAULT_LANGUAGE  converter_customization undef   char *
-HTML_MATH                          converter_customization undef   char *
-HTML_ROOT_ELEMENT_ATTRIBUTES       converter_customization undef   char *
-HTMLXREF_FILE                      converter_customization undef   char *
-HTMLXREF_MODE                      converter_customization undef   char *
-ICONS                              converter_customization undef   int
-INDEX_ENTRY_COLON                  converter_customization undef   char *
-INDEX_SPECIAL_CHARS_WARNING        converter_customization undef   int
-INFO_JS_DIR                        converter_customization undef   char *
-INFO_SPECIAL_CHARS_QUOTE           converter_customization undef   char *
-INFO_SPECIAL_CHARS_WARNING         converter_customization undef   int
-IGNORE_REF_TO_TOP_NODE_UP          converter_customization undef   int
-INLINE_CSS_STYLE                   converter_customization undef   int
-INPUT_FILE_NAME_ENCODING           converter_customization undef   char *
-JS_WEBLABELS                       converter_customization undef   char *
-JS_WEBLABELS_FILE                  converter_customization undef   char *
-LOCALE_ENCODING                    converter_customization undef   char *
-L2H_CLEAN                          converter_customization undef   int
-L2H_FILE                           converter_customization undef   char *
-L2H_HTML_VERSION                   converter_customization undef   char *
-L2H_L2H                            converter_customization undef   char *
-L2H_SKIP                           converter_customization undef   int
-L2H_TMP                            converter_customization undef   char *
-MATHJAX_SCRIPT                     converter_customization undef   char *
-MATHJAX_SOURCE                     converter_customization undef   char *
-MAX_HEADER_LEVEL                   converter_customization undef   int
-MENU_ENTRY_COLON                   converter_customization undef   char *
-MENU_SYMBOL                        converter_customization undef   char *
-MESSAGE_ENCODING                   converter_customization undef   char *
-MONOLITHIC                         converter_customization undef   int
-NO_CSS                             converter_customization undef   int
-NO_NUMBER_FOOTNOTE_SYMBOL          converter_customization undef   char *
-NO_CUSTOM_HTML_ATTRIBUTE           converter_customization undef   int
-NODE_NAME_IN_INDEX                 converter_customization undef   int
-NODE_NAME_IN_MENU                  converter_customization undef   int
-NO_TOP_NODE_OUTPUT                 converter_customization undef   int
-NO_USE_SETFILENAME                 converter_customization undef   int
-OPEN_DOUBLE_QUOTE_SYMBOL           converter_customization undef   char *
-OPEN_QUOTE_SYMBOL                  converter_customization undef   char *
-OUTPUT_CHARACTERS                  converter_customization undef   int
-OUTPUT_ENCODING_NAME               converter_customization undef   char *
-OUTPUT_FILE_NAME_ENCODING          converter_customization undef   char *
-OUTPUT_PERL_ENCODING               converter_customization undef   char *
-PACKAGE_OPTION                     converter_customization undef   char *
-PACKAGE_AND_VERSION_OPTION         converter_customization undef   char *
-PACKAGE_NAME_OPTION                converter_customization undef   char *
-PACKAGE_URL_OPTION                 converter_customization undef   char *
-PACKAGE_VERSION_OPTION             converter_customization undef   char *
-PRE_BODY_CLOSE                     converter_customization undef   char *
-PREFIX                             converter_customization undef   char *
-PROGRAM                            converter_customization undef   char *
-PROGRAM_NAME_IN_ABOUT              converter_customization undef   char *
-PROGRAM_NAME_IN_FOOTER             converter_customization undef   int
-SECTION_NAME_IN_TITLE              converter_customization undef   int
-SHORT_TOC_LINK_TO_TOC              converter_customization undef   int
-SHOW_TITLE                         converter_customization undef   int
-T4H_LATEX_CONVERSION               converter_customization undef   char *
-T4H_MATH_CONVERSION                converter_customization undef   char *
-T4H_TEX_CONVERSION                 converter_customization undef   char *
-TEXI2HTML                          converter_customization undef   int
-TEXINFO_OUTPUT_FORMAT              converter_customization undef   char *
-TOC_LINKS                          converter_customization undef   int
-TOP_FILE                           converter_customization undef   char *
-TOP_NODE_FILE_TARGET               converter_customization undef   char *
-TOP_NODE_UP_URL                    converter_customization undef   char *
-USE_ACCESSKEY                      converter_customization undef   int
-USE_ISO                            converter_customization undef   int
-USE_LINKS                          converter_customization undef   int
-USE_NEXT_HEADING_FOR_LONE_NODE     converter_customization undef   int
-USE_NODES                          converter_customization undef   int
-USE_NODE_DIRECTIONS                converter_customization undef   int
-USE_NUMERIC_ENTITY                 converter_customization undef   int
-USE_REL_REV                        converter_customization undef   int
-USE_SETFILENAME_EXTENSION          converter_customization undef   int
-USE_TITLEPAGE_FOR_TITLE            converter_customization undef   int
-USE_UNIDECODE                      converter_customization undef   int
-USE_UP_NODE_FOR_ELEMENT_UP         converter_customization undef   int
-USE_XML_SYNTAX                     converter_customization undef   int
-VERTICAL_HEAD_NAVIGATION           converter_customization undef   int
-WORDS_IN_PAGE                      converter_customization undef   int
-XREF_USE_FLOAT_LABEL               converter_customization undef   int
-XREF_USE_NODE_NAME_ARG             converter_customization undef   int
+HIGHLIGHT_SYNTAX_DEFAULT_LANGUAGE  converter_customization undef   char
+HTML_MATH                          converter_customization undef   char
+HTML_ROOT_ELEMENT_ATTRIBUTES       converter_customization undef   char
+HTMLXREF_FILE                      converter_customization undef   char
+HTMLXREF_MODE                      converter_customization undef   char
+ICONS                              converter_customization undef   integer
+INDEX_ENTRY_COLON                  converter_customization undef   char
+INDEX_SPECIAL_CHARS_WARNING        converter_customization undef   integer
+INFO_JS_DIR                        converter_customization undef   char
+INFO_SPECIAL_CHARS_QUOTE           converter_customization undef   char
+INFO_SPECIAL_CHARS_WARNING         converter_customization undef   integer
+IGNORE_REF_TO_TOP_NODE_UP          converter_customization undef   integer
+INLINE_CSS_STYLE                   converter_customization undef   integer
+INPUT_FILE_NAME_ENCODING           converter_customization undef   char
+JS_WEBLABELS                       converter_customization undef   char
+JS_WEBLABELS_FILE                  converter_customization undef   char
+LOCALE_ENCODING                    converter_customization undef   char
+L2H_CLEAN                          converter_customization undef   integer
+L2H_FILE                           converter_customization undef   char
+L2H_HTML_VERSION                   converter_customization undef   char
+L2H_L2H                            converter_customization undef   char
+L2H_SKIP                           converter_customization undef   integer
+L2H_TMP                            converter_customization undef   char
+MATHJAX_SCRIPT                     converter_customization undef   char
+MATHJAX_SOURCE                     converter_customization undef   char
+MAX_HEADER_LEVEL                   converter_customization undef   integer
+MENU_ENTRY_COLON                   converter_customization undef   char
+MENU_SYMBOL                        converter_customization undef   char
+MESSAGE_ENCODING                   converter_customization undef   char
+MONOLITHIC                         converter_customization undef   integer
+NO_CSS                             converter_customization undef   integer
+NO_NUMBER_FOOTNOTE_SYMBOL          converter_customization undef   char
+NO_CUSTOM_HTML_ATTRIBUTE           converter_customization undef   integer
+NODE_NAME_IN_INDEX                 converter_customization undef   integer
+NODE_NAME_IN_MENU                  converter_customization undef   integer
+NO_TOP_NODE_OUTPUT                 converter_customization undef   integer
+NO_USE_SETFILENAME                 converter_customization undef   integer
+OPEN_DOUBLE_QUOTE_SYMBOL           converter_customization undef   char
+OPEN_QUOTE_SYMBOL                  converter_customization undef   char
+OUTPUT_CHARACTERS                  converter_customization undef   integer
+OUTPUT_ENCODING_NAME               converter_customization undef   char
+OUTPUT_FILE_NAME_ENCODING          converter_customization undef   char
+OUTPUT_PERL_ENCODING               converter_customization undef   char
+PACKAGE_OPTION                     converter_customization undef   char
+PACKAGE_AND_VERSION_OPTION         converter_customization undef   char
+PACKAGE_NAME_OPTION                converter_customization undef   char
+PACKAGE_URL_OPTION                 converter_customization undef   char
+PACKAGE_VERSION_OPTION             converter_customization undef   char
+PRE_BODY_CLOSE                     converter_customization undef   char
+PREFIX                             converter_customization undef   char
+PROGRAM                            converter_customization undef   char
+PROGRAM_NAME_IN_ABOUT              converter_customization undef   integer
+PROGRAM_NAME_IN_FOOTER             converter_customization undef   integer
+SECTION_NAME_IN_TITLE              converter_customization undef   integer
+SHORT_TOC_LINK_TO_TOC              converter_customization undef   integer
+SHOW_TITLE                         converter_customization undef   integer
+T4H_LATEX_CONVERSION               converter_customization undef   char
+T4H_MATH_CONVERSION                converter_customization undef   char
+T4H_TEX_CONVERSION                 converter_customization undef   char
+TEXI2HTML                          converter_customization undef   integer
+TEXINFO_OUTPUT_FORMAT              converter_customization undef   char
+TOC_LINKS                          converter_customization undef   integer
+TOP_FILE                           converter_customization undef   char
+TOP_NODE_FILE_TARGET               converter_customization undef   char
+TOP_NODE_UP_URL                    converter_customization undef   char
+USE_ACCESSKEY                      converter_customization undef   integer
+USE_ISO                            converter_customization undef   integer
+USE_LINKS                          converter_customization undef   integer
+USE_NEXT_HEADING_FOR_LONE_NODE     converter_customization undef   integer
+USE_NODES                          converter_customization undef   integer
+USE_NODE_DIRECTIONS                converter_customization undef   integer
+USE_NUMERIC_ENTITY                 converter_customization undef   integer
+USE_REL_REV                        converter_customization undef   integer
+USE_SETFILENAME_EXTENSION          converter_customization undef   integer
+USE_TITLEPAGE_FOR_TITLE            converter_customization undef   integer
+USE_UNIDECODE                      converter_customization undef   integer
+USE_UP_NODE_FOR_ELEMENT_UP         converter_customization undef   integer
+USE_XML_SYNTAX                     converter_customization undef   integer
+VERTICAL_HEAD_NAVIGATION           converter_customization undef   integer
+WORDS_IN_PAGE                      converter_customization undef   integer
+XREF_USE_FLOAT_LABEL               converter_customization undef   integer
+XREF_USE_NODE_NAME_ARG             converter_customization undef   integer
 
 
 # Not strings
-LINKS_BUTTONS                      converter_other undef   
BUTTON_SPECIFICATION_LIST *
-TOP_BUTTONS                        converter_other undef   
BUTTON_SPECIFICATION_LIST *
-SECTION_BUTTONS                    converter_other undef   
BUTTON_SPECIFICATION_LIST *
-CHAPTER_FOOTER_BUTTONS             converter_other undef   
BUTTON_SPECIFICATION_LIST *
-SECTION_FOOTER_BUTTONS             converter_other undef   
BUTTON_SPECIFICATION_LIST *
-NODE_FOOTER_BUTTONS                converter_other undef   
BUTTON_SPECIFICATION_LIST *
-MISC_BUTTONS                       converter_other undef   
BUTTON_SPECIFICATION_LIST *
-CHAPTER_BUTTONS                    converter_other undef   
BUTTON_SPECIFICATION_LIST *
-ACTIVE_ICONS                       converter_other undef   DIRECTION_ICON_LIST
-PASSIVE_ICONS                      converter_other undef   DIRECTION_ICON_LIST
+LINKS_BUTTONS                      converter_other undef   buttons
+TOP_BUTTONS                        converter_other undef   buttons
+SECTION_BUTTONS                    converter_other undef   buttons
+CHAPTER_FOOTER_BUTTONS             converter_other undef   buttons
+SECTION_FOOTER_BUTTONS             converter_other undef   buttons
+NODE_FOOTER_BUTTONS                converter_other undef   buttons
+MISC_BUTTONS                       converter_other undef   buttons
+CHAPTER_BUTTONS                    converter_other undef   buttons
+ACTIVE_ICONS                       converter_other undef   icons
+PASSIVE_ICONS                      converter_other undef   icons
 
 
 # set from command line.
 # --css-include
-CSS_FILES            array_cmdline  undef   STRING_LIST
+CSS_FILES            array_cmdline  undef   bytes_string_list
 # --css-ref
-CSS_REFS             array_cmdline  undef   STRING_LIST
+CSS_REFS             array_cmdline  undef   bytes_string_list
 # --if*
-EXPANDED_FORMATS     array_cmdline  undef   STRING_LIST
+EXPANDED_FORMATS     array_cmdline  undef   bytes_string_list
 # -I
-INCLUDE_DIRECTORIES  array_cmdline  undef   STRING_LIST
+INCLUDE_DIRECTORIES  array_cmdline  undef   file_string_list
 
 
diff --git a/tp/maintain/regenerate_C_options_info.pl 
b/tp/maintain/regenerate_C_options_info.pl
index cb4000a870..7aa5885eb0 100755
--- a/tp/maintain/regenerate_C_options_info.pl
+++ b/tp/maintain/regenerate_C_options_info.pl
@@ -110,7 +110,7 @@ foreach my $category (sort(keys(%option_categories))) {
   print HEADER "\n/* ${category} */\n\n";
   foreach my $option_info (@{$option_categories{$category}}) {
     my ($option, $value, $type) = @$option_info;
-    print HEADER "    $type $option;\n";
+    print HEADER "    OPTION $option;\n";
   }
 }
 print HEADER "} OPTIONS;\n\n";
@@ -138,15 +138,7 @@ foreach my $category (sort(keys(%option_categories))) {
   print CODE "\n/* ${category} */\n\n";
   foreach my $option_info (@{$option_categories{$category}}) {
     my ($option, $value, $type) = @$option_info;
-    if ($type eq 'STRING_LIST' or $type eq 'DIRECTION_ICON_LIST') {
-      print CODE "  memset (&options->$option, 0, sizeof ($type));\n";
-    } else {
-      my $init_value = 0;
-      if ($type eq 'int') {
-        $init_value = -1;
-      }
-      print CODE " options->$option = $init_value;\n";
-    }
+    print CODE " initialize_option (&options->$option, GO_$type);\n";
   }
 }
 print CODE "};\n\n";
@@ -156,28 +148,17 @@ foreach my $category (sort(keys(%option_categories))) {
   print CODE "\n/* ${category} */\n\n";
   foreach my $option_info (@{$option_categories{$category}}) {
     my ($option, $value, $type) = @$option_info;
-    if ($type eq 'STRING_LIST') {
-      print CODE "  free_strings_list (&options->$option);\n";
-    } elsif ($type eq 'char *') {
-      print CODE " free (options->$option);\n";
-    } elsif ($type eq 'BUTTON_SPECIFICATION_LIST *') {
-      print CODE "  html_free_button_specification_list (options->$option);\n";
-    } elsif ($type eq 'DIRECTION_ICON_LIST') {
-      print CODE "  html_free_direction_icons (&options->$option);\n";
-    }
+    print CODE "  free_option (&options->$option);\n";
   }
 }
 print CODE "};\n\n";
 
 # associate commands to options
 print CODE "#include \"command_ids.h\"\n\n";
-print CODE 'COMMAND_OPTION_REF *
+print CODE 'OPTION *
 get_command_option (OPTIONS *options,
                     enum command_id cmd)
 {
-  int type = 0;
-  char **char_ref = 0;
-  int *int_ref = 0;
   switch (cmd)
     {
 ';
@@ -190,15 +171,10 @@ foreach my $command_name (@commands_order) {
   if ($commands_options{$command}) {
     my ($category, $value, $type) = @{$commands_options{$command}};
     print CODE "    case CM_${command}:
-    {\n";
-    my $str_type = 'char';
-    if ($type eq 'int') {
-      $str_type = 'int';
-    }
-    print CODE "      type = GO_${str_type};\n";
-    print CODE "      ${str_type}_ref = &options->${command};\n";
-    print CODE "      break;\n";
-    print CODE "    }\n";
+    {
+      return &options->${command};
+      break;
+    }\n";
   }
 }
 
@@ -206,16 +182,6 @@ print CODE "
     default:
       return 0;
     }
-
-  COMMAND_OPTION_REF *result
-    = (COMMAND_OPTION_REF *)malloc (sizeof (COMMAND_OPTION_REF));
-  result->type = type;
-  if (type == GO_int)
-    result->int_ref = int_ref;
-  else
-    result->char_ref = char_ref;
-
-  return result;
 };\n\n";
 
 # table of defaults for options corresponding to commands
@@ -231,19 +197,17 @@ foreach my $command_name (@commands_order) {
     #print STDERR "$command $category, $value, $type\n";
     my $char_value = 0;
     my $int_value = '-2';
-    my $GO_type = 'GO_char';
-    if ($type eq 'int') {
-      $GO_type = 'GO_int';
+    if ($type eq 'integer') {
       $int_value = -1;
     }
     if ($value ne 'undef') {
-      if ($type eq 'int') {
+      if ($type eq 'integer') {
         $int_value = $value;
       } else {
         $char_value = '"'.$value.'"';
       }
     }
-    print CODE "{$GO_type, $int_value, $char_value},   /* $command ($category) 
*/\n";
+    print CODE "{GO_$type, $int_value, $char_value},   /* $command ($category) 
*/\n";
   } else {
     print CODE "{GO_NONE, -2, 0},\n";
   }
@@ -282,10 +246,11 @@ print GET '#include <stdlib.h>'."\n\n";
 print GET '#include "options_types.h"'."\n";
 print GET '#include "converter_types.h"'."\n";
 print GET '#include "utils.h"'."\n";
-print GET '#include "get_perl_info.h"'."\n\n";
+print GET '#include "get_perl_info.h"'."\n";
+print GET '#include "build_perl_info.h"'."\n\n";
 
 print GET 'void
-get_sv_option (OPTIONS *options, const char *key, SV *value, CONVERTER 
*converter)
+get_sv_option (OPTIONS *options, const char *key, SV *value, int set, 
CONVERTER *converter)
 {
   dTHX;
 
@@ -305,45 +270,47 @@ foreach my $category (sort(keys(%option_categories))) {
   print GET "\n/* ${category} */\n\n";
   foreach my $option_info (@{$option_categories{$category}}) {
     my ($option, $value, $type) = @$option_info;
-    print GET "  else if (!strcmp (key, \"$option\"))\n";
-    if ($type eq 'char *') {
+    print GET "  else if (!strcmp (key, \"$option\"))
+    {
+      if (set > 0)
+        options->$option.set = set;
+      else if (set < 0 && options->$option.set > 0)
+        return;\n\n";
+    if ($type eq 'char' or $type eq 'bytes') {
       my $SV_function_type = 'utf8';
-      if ($non_decoded_customization_variables{$option}) {
+      if ($type eq 'bytes') {
         $SV_function_type = 'byte';
       }
-      print GET "    {
-      free (options->$option);
+      print GET "      free (options->$option.string);
       if (SvOK (value))
-        options->$option = strdup (SvPV${SV_function_type}_nolen (value));
+        options->$option.string = strdup (SvPV${SV_function_type}_nolen 
(value));
       else
-        options->$option = 0;
+        options->$option.string = 0;
     }\n";
-    } elsif ($type eq 'int') {
-      print GET "    {
-      if (SvOK (value))
-        options->$option = SvIV (value);
+    } elsif ($type eq 'integer') {
+      print GET "      if (SvOK (value))
+        options->$option.integer = SvIV (value);
       else
-        options->$option = -1;
+        options->$option.integer = -1;
     }\n";
-    } elsif ($type eq 'STRING_LIST') {
+    } elsif ($type =~ /_string_list$/) {
       my $dir_string_arg = 'svt_byte';
-      $dir_string_arg = 'svt_dir'
-        if ($option eq 'INCLUDE_DIRECTORIES');
-      print GET "    {\n";
-      print GET "      clear_strings_list (&options->$option);\n";
-      print GET "      add_svav_to_string_list (value, &options->$option, 
$dir_string_arg);\n";
-      print GET "    }\n";
-    } elsif ($type eq 'BUTTON_SPECIFICATION_LIST *') {
-      print GET "    {\n";
-      print GET "      html_free_button_specification_list 
(options->$option);\n";
-      print GET "      options->$option = "
-                        ."html_get_button_specification_list (converter, 
value);\n";
-      print GET "    }\n";
-    } elsif ($type eq 'DIRECTION_ICON_LIST') {
-      print GET "    {\n";
-      print GET "      html_free_direction_icons (&options->$option);\n";
-      print GET "      html_get_direction_icons_sv (converter, 
&options->$option, value);\n";
-      print GET "    }\n";
+      if ($type eq 'file_string_list') {
+        $dir_string_arg = 'svt_dir';
+      } elsif ($type eq 'file_string_char') {
+        $dir_string_arg = 'svt_char';
+      }
+      print GET "      clear_strings_list (options->$option.strlist);
+      add_svav_to_string_list (value, options->$option.strlist, 
$dir_string_arg);
+    }\n";
+    } elsif ($type eq 'buttons') {
+      print GET "      html_free_button_specification_list 
(options->$option.buttons);
+      options->$option.buttons = html_get_button_specification_list 
(converter, value);
+    }\n";
+    } elsif ($type eq 'icons') {
+      print GET "      html_free_direction_icons (options->$option.icons);
+      html_get_direction_icons_sv (converter, options->$option.icons, value);
+    }\n";
     } else {
       print GET "    {}\n";
     }
@@ -351,6 +318,67 @@ foreach my $category (sort(keys(%option_categories))) {
 }
 
 print GET '}
+
+';
+
+print GET 'SV *
+build_sv_option (OPTIONS *options, const char *key, CONVERTER *converter)
+{
+  dTHX;
+
+  if (0) {return newSV (0);}
+';
+
+foreach my $category (sort(keys(%option_categories))) {
+  print GET "\n/* ${category} */\n\n";
+  foreach my $option_info (@{$option_categories{$category}}) {
+    my ($option, $value, $type) = @$option_info;
+    print GET "  else if (!strcmp (key, \"$option\"))\n";
+    if ($type eq 'char' or $type eq 'bytes') {
+      my $SV_function_type = 'utf8';
+      if ($type eq 'bytes') {
+        $SV_function_type = 'byte';
+      }
+      print GET "    {
+      if (!options->$option.string)
+        return newSV (0);
+      return newSVpv_${SV_function_type} (options->$option.string, 0);
+    }\n";
+    } elsif ($type eq 'integer') {
+      print GET "    {
+      if (options->$option.integer == -1)
+        return newSV (0);
+      return newSViv (options->$option.integer);
+    }\n";
+    } elsif ($type =~ /_string_list$/) {
+      my $dir_string_arg = 'svt_byte';
+      if ($type eq 'file_string_list') {
+        $dir_string_arg = 'svt_dir';
+      } elsif ($type eq 'file_string_char') {
+        $dir_string_arg = 'svt_char';
+      }
+      print GET "    {
+      return newRV_noinc ((SV *) build_string_list(options->$option.strlist, 
$dir_string_arg));
+    }\n";
+    } elsif ($type eq 'buttons') {
+      print GET "    {
+      if (!options->$option.buttons) return newSV (0);
+      return newRV_inc ((SV *) options->$option.buttons->av);
+    }\n";
+    } elsif ($type eq 'icons') {
+      print GET "    {
+      html_build_direction_icons (converter, options->$option.icons);
+    }\n";
+    } else {
+      print GET "    {return newSV (0);}\n";
+    }
+  }
+}
+
+print GET '
+  return newSV (0);
+}
+
 ';
 
 close(GET);
diff --git a/tp/maintain/regenerate_perl_options_info.pl 
b/tp/maintain/regenerate_perl_options_info.pl
index 210993006b..8b12349d11 100755
--- a/tp/maintain/regenerate_perl_options_info.pl
+++ b/tp/maintain/regenerate_perl_options_info.pl
@@ -36,7 +36,7 @@ while (<STDIN>) {
       my $value = $3;
       my $type = $4;
 
-      if ($type eq 'char *' and $value ne 'undef') {
+      if (($type eq 'char' or $type eq 'bytes') and $value ne 'undef') {
         $value = "'".$value."'";
       }
 



reply via email to

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