texinfo-commits
[Top][All Lists]
Advanced

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

[no subject]


From: Patrice Dumas
Date: Sat, 5 Oct 2024 03:34:12 -0400 (EDT)

branch: master
commit c60007f14ae8fba08e4a6f3c90ed5d066407aed3
Author: Patrice Dumas <pertusus@free.fr>
AuthorDate: Wed Aug 21 09:07:32 2024 +0200

    Implement reading xhtmlxref in C and XS
    
    * tp/Texinfo/Convert/HTML.pm (_parse_htmlxref_files): encode file name
    for error message if close failed.
    
    * tp/Texinfo/XS/convert/converter.c (apply_converter_info)
    (destroy_converter_initialization_info)
    (copy_converter_initialization_info),
    tp/Texinfo/XS/convert/get_converter_perl_info.c
    (get_converter_info_from_sv), tp/Texinfo/XS/main/converter_types.h
    (CONVERTER_INITIALIZATION_INFO, CONVERTER): add
    texinfo_language_config_dirs field in CONVERTER and in
    texinfo_language_config_dirs in CONVERTER_INITIALIZATION_INFO,
    pass information in apply_converter_info and get from Perl.
    
    * tp/Texinfo/XS/main/utils.c (locate_file_in_dirs): add.
    
    * tp/Texinfo/XS/convert/html_prepare_converter.c
    (STRING_VARIABLE_INFO, STRING_VARIABLES_LIST, set_variable_value)
    (read_var_len, substitute_variables, get_create_htmlxref_manual)
    (fill_source_info_file, parse_htmlxref_files, load_htmlxref_files),
    tp/Texinfo/XS/main/converter_types.h (HTMLXREF_MANUAL_LIST):
    implement reading xhtmlxref files in C.
    
    * tp/Texinfo/XS/convert/ConvertXS.xs
    (html_converter_initialize_beginning),
    tp/Texinfo/XS/convert/build_html_perl_state.c (build_htmlxref)
    (html_pass_xtmlxref), tp/Texinfo/XS/convert/get_html_perl_info.c
    (html_converter_get_customization_sv): XS interface to build xhtmlxref
    information to Perl.  Do not get xhtmlxref information from Perl
    anymore.
    
    * tp/Texinfo/XS/Makefile.am (AM_CPPFLAGS),
    tp/Texinfo/XS/convert/texinfo.c (txi_converter_setup),
    tp/Texinfo/XS/teximakehtml.c (main): pass sysconfidir in AM_CPPFLAGS.
    Add texinfo_language_config_dirs argument to txi_converter_setup to
    setup texinfo_language_config_dirs, and set the list of
    texinfo_language_config_dirs in teximakehtml.c main.
---
 ChangeLog                                       |  41 ++
 tp/Texinfo/Convert/HTML.pm                      |  11 +-
 tp/Texinfo/XS/Makefile.am                       |   2 +-
 tp/Texinfo/XS/convert/ConvertXS.xs              |   5 +-
 tp/Texinfo/XS/convert/build_html_perl_state.c   |  54 +++
 tp/Texinfo/XS/convert/build_html_perl_state.h   |   2 +
 tp/Texinfo/XS/convert/converter.c               |   8 +
 tp/Texinfo/XS/convert/get_converter_perl_info.c |   5 +-
 tp/Texinfo/XS/convert/get_html_perl_info.c      |   9 +-
 tp/Texinfo/XS/convert/html_prepare_converter.c  | 500 +++++++++++++++++++++++-
 tp/Texinfo/XS/convert/texinfo.c                 |  14 +-
 tp/Texinfo/XS/convert/texinfo.h                 |   7 +-
 tp/Texinfo/XS/main/converter_types.h            |   3 +
 tp/Texinfo/XS/main/utils.c                      | 105 +++--
 tp/Texinfo/XS/main/utils.h                      |   3 +
 tp/Texinfo/XS/teximakehtml.c                    |  38 +-
 16 files changed, 760 insertions(+), 47 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 18c71c35f3..3c49a51359 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,44 @@
+2024-08-21  Patrice Dumas  <pertusus@free.fr>
+
+       Implement reading xhtmlxref in C and XS
+
+       * tp/Texinfo/Convert/HTML.pm (_parse_htmlxref_files): encode file name
+       for error message if close failed.
+
+       * tp/Texinfo/XS/convert/converter.c (apply_converter_info)
+       (destroy_converter_initialization_info)
+       (copy_converter_initialization_info),
+       tp/Texinfo/XS/convert/get_converter_perl_info.c
+       (get_converter_info_from_sv), tp/Texinfo/XS/main/converter_types.h
+       (CONVERTER_INITIALIZATION_INFO, CONVERTER): add
+       texinfo_language_config_dirs field in CONVERTER and in
+       texinfo_language_config_dirs in CONVERTER_INITIALIZATION_INFO,
+       pass information in apply_converter_info and get from Perl.
+
+       * tp/Texinfo/XS/main/utils.c (locate_file_in_dirs): add.
+
+       * tp/Texinfo/XS/convert/html_prepare_converter.c
+       (STRING_VARIABLE_INFO, STRING_VARIABLES_LIST, set_variable_value)
+       (read_var_len, substitute_variables, get_create_htmlxref_manual)
+       (fill_source_info_file, parse_htmlxref_files, load_htmlxref_files),
+       tp/Texinfo/XS/main/converter_types.h (HTMLXREF_MANUAL_LIST):
+       implement reading xhtmlxref files in C.
+
+       * tp/Texinfo/XS/convert/ConvertXS.xs
+       (html_converter_initialize_beginning),
+       tp/Texinfo/XS/convert/build_html_perl_state.c (build_htmlxref)
+       (html_pass_xtmlxref), tp/Texinfo/XS/convert/get_html_perl_info.c
+       (html_converter_get_customization_sv): XS interface to build xhtmlxref
+       information to Perl.  Do not get xhtmlxref information from Perl
+       anymore.
+
+       * tp/Texinfo/XS/Makefile.am (AM_CPPFLAGS),
+       tp/Texinfo/XS/convert/texinfo.c (txi_converter_setup),
+       tp/Texinfo/XS/teximakehtml.c (main): pass sysconfidir in AM_CPPFLAGS.
+       Add texinfo_language_config_dirs argument to txi_converter_setup to
+       setup texinfo_language_config_dirs, and set the list of
+       texinfo_language_config_dirs in teximakehtml.c main.
+
 2024-08-18  Patrice Dumas  <pertusus@free.fr>
 
        * tp/Texinfo/XS: run
diff --git a/tp/Texinfo/Convert/HTML.pm b/tp/Texinfo/Convert/HTML.pm
index a70cd89c02..b0a04b13b1 100644
--- a/tp/Texinfo/Convert/HTML.pm
+++ b/tp/Texinfo/Convert/HTML.pm
@@ -8478,9 +8478,14 @@ sub _parse_htmlxref_files($$)
       $htmlxref->{$manual}->{$split_or_mono} = $href;
     }
     if (!close (HTMLXREF)) {
+      my $htmlxref_file_name = $file;
+      my $encoding = $self->get_conf('COMMAND_LINE_ENCODING');
+      if (defined($encoding)) {
+        $htmlxref_file_name = decode($encoding, $htmlxref_file_name);
+      }
       $self->converter_document_warn(sprintf(__(
                        "error on closing html refs config file %s: %s"),
-                             $file, $!));
+                             $htmlxref_file_name, $!));
     }
   }
   return $htmlxref;
@@ -8745,9 +8750,9 @@ sub converter_initialize($)
         $self->force_conf($conf, '');
       }
     }
-  }
 
-  _load_htmlxref_files($self);
+    _load_htmlxref_files($self);
+  }
 
   $self->{'output_units_conversion'} = {};
   my $customized_output_units_conversion
diff --git a/tp/Texinfo/XS/Makefile.am b/tp/Texinfo/XS/Makefile.am
index fa39738a4f..abeb53e5e5 100644
--- a/tp/Texinfo/XS/Makefile.am
+++ b/tp/Texinfo/XS/Makefile.am
@@ -33,7 +33,7 @@ EXTRA_DIST+=gnulib/m4/gnulib-cache.m4
 
 ################### End Gnulib section #########################
 
-AM_CPPFLAGS += -DDATADIR=\"$(datadir)\"
+AM_CPPFLAGS += -DDATADIR=\"$(datadir)\" -DSYSCONFDIR=\"$(sysconfdir)\"
 
 ######################## Perl ################################
 
diff --git a/tp/Texinfo/XS/convert/ConvertXS.xs 
b/tp/Texinfo/XS/convert/ConvertXS.xs
index 686a70dda8..cc90d9e2f4 100644
--- a/tp/Texinfo/XS/convert/ConvertXS.xs
+++ b/tp/Texinfo/XS/convert/ConvertXS.xs
@@ -701,7 +701,10 @@ html_converter_initialize_beginning (SV *converter_in)
         self = get_sv_converter (converter_in,
                                  "html_converter_initialize_beginning");
         if (self)
-          html_converter_initialize_beginning (self);
+          {
+            html_converter_initialize_beginning (self);
+            html_pass_xtmlxref (&self->htmlxref, converter_in);
+          }
 
 void
 html_converter_get_customization_sv (SV *converter_in, SV 
*default_formatting_references, SV *default_css_string_formatting_references, 
SV *default_commands_open, SV *default_commands_conversion, SV 
*default_css_string_commands_conversion, SV *default_types_open, SV 
*default_types_conversion, SV *default_css_string_types_conversion, SV 
*default_output_units_conversion, SV *default_special_unit_body, SV 
*customized_upper_case_commands, SV *customized_type_formatting, SV 
*customized_accent [...]
diff --git a/tp/Texinfo/XS/convert/build_html_perl_state.c 
b/tp/Texinfo/XS/convert/build_html_perl_state.c
index e067d49191..c97885a2fd 100644
--- a/tp/Texinfo/XS/convert/build_html_perl_state.c
+++ b/tp/Texinfo/XS/convert/build_html_perl_state.c
@@ -62,6 +62,60 @@
  /* See the NOTE in build_perl_info.c on use of functions related to
     memory allocation */
 
+static HV *
+build_htmlxref (HTMLXREF_MANUAL_LIST *htmlxref_list)
+{
+  HV *htmlxref_hv;
+  size_t i;
+
+  dTHX;
+
+  htmlxref_hv = newHV ();
+
+  for (i = 0; i < htmlxref_list->number; i++)
+    {
+      HTMLXREF_MANUAL *htmlxref_manual = &htmlxref_list->list[i];
+      const char *manual_name = htmlxref_manual->manual;
+      SV *manual_name_sv = newSVpv_utf8 (manual_name, 0);
+      HV *htmlxref_manual_hv = newHV ();
+      SV *htmlxref_manual_sv = newRV_noinc ((SV *) htmlxref_manual_hv);
+      enum htmlxref_split_type j;
+
+      hv_store_ent (htmlxref_hv, manual_name_sv, htmlxref_manual_sv, 0);
+
+      for (j = 0; j < htmlxref_split_type_chapter+1; j++)
+        {
+          if (htmlxref_manual->urlprefix[j])
+            {
+              const char *split_type_name = htmlxref_split_type_names[j];
+              const char *href = htmlxref_manual->urlprefix[j];
+
+              hv_store (htmlxref_manual_hv, split_type_name,
+                        strlen (split_type_name),
+                        newSVpv_utf8 (href, 0), 0);
+            }
+        }
+    }
+
+  return htmlxref_hv;
+}
+
+void
+html_pass_xtmlxref (HTMLXREF_MANUAL_LIST *htmlxref_list, SV *converter_sv)
+{
+  HV *converter_hv;
+  HV *htmlxref_hv;
+
+  dTHX;
+
+  converter_hv = (HV *) SvRV (converter_sv);
+
+  htmlxref_hv = build_htmlxref (htmlxref_list);
+
+  hv_store (converter_hv, "htmlxref", strlen ("htmlxref"),
+            newRV_noinc ((SV *) htmlxref_hv), 0);
+}
+
 #define STORE(key, sv) hv_store (html_target_hv, key, strlen (key), sv, 0)
 HV *
 build_html_target (const HTML_TARGET *html_target)
diff --git a/tp/Texinfo/XS/convert/build_html_perl_state.h 
b/tp/Texinfo/XS/convert/build_html_perl_state.h
index c6c40e713d..6e5a5ecdce 100644
--- a/tp/Texinfo/XS/convert/build_html_perl_state.h
+++ b/tp/Texinfo/XS/convert/build_html_perl_state.h
@@ -10,6 +10,8 @@
 /* for NAMED_STRING_ELEMENT_LIST */
 #include "translations.h"
 
+void html_pass_xtmlxref (HTMLXREF_MANUAL_LIST *htmlxref_list, SV 
*converter_sv);
+
 HV *build_html_target (const HTML_TARGET *html_target);
 void build_html_translated_names (HV *hv, CONVERTER *converter);
 
diff --git a/tp/Texinfo/XS/convert/converter.c 
b/tp/Texinfo/XS/convert/converter.c
index 2444684fec..0d515b1c30 100644
--- a/tp/Texinfo/XS/convert/converter.c
+++ b/tp/Texinfo/XS/convert/converter.c
@@ -334,6 +334,9 @@ apply_converter_info (CONVERTER *converter,
       converter->translated_commands = init_info->translated_commands;
       init_info->translated_commands = 0;
     }
+
+  copy_strings (&converter->texinfo_language_config_dirs,
+                &init_info->texinfo_language_config_dirs);
 }
 
 /* apply format_defaults and user_conf initialization information.
@@ -397,6 +400,8 @@ destroy_converter_initialization_info 
(CONVERTER_INITIALIZATION_INFO *init_info)
   free (init_info->converted_format);
   free (init_info->output_format);
 
+  free_strings_list (&init_info->texinfo_language_config_dirs);
+
   free_options_list (&init_info->conf);
 
   free_strings_list (&init_info->non_valid_customization);
@@ -418,6 +423,9 @@ copy_converter_initialization_info 
(CONVERTER_INITIALIZATION_INFO *dst_info,
       dst_info->output_format = strdup (src_info->output_format);
     }
 
+  copy_strings (&dst_info->texinfo_language_config_dirs,
+                &src_info->texinfo_language_config_dirs);
+
   copy_strings (&dst_info->non_valid_customization,
                 &src_info->non_valid_customization);
 
diff --git a/tp/Texinfo/XS/convert/get_converter_perl_info.c 
b/tp/Texinfo/XS/convert/get_converter_perl_info.c
index c6ed81e1c1..1921056dd2 100644
--- a/tp/Texinfo/XS/convert/get_converter_perl_info.c
+++ b/tp/Texinfo/XS/convert/get_converter_perl_info.c
@@ -302,8 +302,9 @@ get_converter_info_from_sv (SV *conf_sv, const char 
*class_name,
                           = set_translated_commands (value);
                       else if (!strcmp (key, "texinfo_language_config_dirs"))
                         {
-                          /* TODO add to converter and set.  Only used for
-                             htmlxref, so should wait for that to implement */
+                          add_svav_to_string_list (value,
+                            &initialization_info->texinfo_language_config_dirs,
+                            svt_dir);
                         }
                       else if (class_name)
                         {
diff --git a/tp/Texinfo/XS/convert/get_html_perl_info.c 
b/tp/Texinfo/XS/convert/get_html_perl_info.c
index f9a5cbcc55..534f7798c9 100644
--- a/tp/Texinfo/XS/convert/get_html_perl_info.c
+++ b/tp/Texinfo/XS/convert/get_html_perl_info.c
@@ -258,7 +258,7 @@ html_converter_get_customization_sv (SV *converter_sv,
   HV *default_types_conversion_hv;
   HV *default_css_string_types_conversion_hv;
   HV *default_output_units_conversion_hv;
-  SV **htmlxref_sv;
+  SV **htmlxref_sv = 0;
   SV **formatting_function_sv;
   SV **stage_handlers_sv;
   SV **special_unit_body_sv;
@@ -892,8 +892,14 @@ html_converter_get_customization_sv (SV *converter_sv,
     }
 
 #define FETCH(key) key##_sv = hv_fetch (converter_hv, #key, strlen (#key), 0);
+   /*
   FETCH(htmlxref)
+    */
 
+  /* Get htmlxref from Perl.
+     this is always 0 as it is not fetch so this code is never run, htmlxref
+     information is setup in C.
+   */
   if (htmlxref_sv)
     {
       I32 hv_number;
@@ -906,6 +912,7 @@ html_converter_get_customization_sv (SV *converter_sv,
 
       if (hv_number > 0)
         {
+          converter->htmlxref.space = hv_number;
           converter->htmlxref.list = new_htmlxref_manual_list (hv_number);
 
           for (i = 0; i < hv_number; i++)
diff --git a/tp/Texinfo/XS/convert/html_prepare_converter.c 
b/tp/Texinfo/XS/convert/html_prepare_converter.c
index 4c4c053b71..4817a5a7e6 100644
--- a/tp/Texinfo/XS/convert/html_prepare_converter.c
+++ b/tp/Texinfo/XS/convert/html_prepare_converter.c
@@ -93,6 +93,7 @@ static CSS_SELECTOR_STYLE_LIST 
default_css_element_class_styles;
 
 COMMAND_ARGS_SPECIFICATION html_command_args_flags[BUILTIN_CMD_NUMBER];
 
+/* should match enum htmlxref_split_type */
 const char *htmlxref_split_type_names[htmlxref_split_type_chapter + 1] =
 {
   "mono", "node", "section", "chapter"
@@ -618,9 +619,434 @@ html_format_setup (void)
    defaults based on customization variables.
    Apply specific customizations (from Perl) */
 
+/* Also used to get htmlxref info from Perl.  Initialize in C */
+HTMLXREF_MANUAL *
+new_htmlxref_manual_list (size_t size)
+{
+  HTMLXREF_MANUAL *result = (HTMLXREF_MANUAL *)
+        malloc (size * sizeof (HTMLXREF_MANUAL));
+  memset (result, 0, size * sizeof (HTMLXREF_MANUAL));
+
+  return result;
+}
 
+/* This variable setting/substitution is quite generic and could be used
+   in other codes, but it is only needed here for now */
+typedef struct STRING_VARIABLE_INFO {
+    char *name;
+    char *string;
+} STRING_VARIABLE_INFO;
 
-void
+typedef struct STRING_VARIABLES_LIST {
+    size_t number;
+    size_t space;
+    STRING_VARIABLE_INFO *list;
+} STRING_VARIABLES_LIST;
+
+static void
+set_variable_value (STRING_VARIABLES_LIST *variables,
+                    const char *name, const char *value)
+{
+  size_t i;
+
+  for (i = 0; i < variables->number; i++)
+    {
+      STRING_VARIABLE_INFO *variable = &variables->list[i];
+      if (!strcmp (variable->name, name))
+        {
+          free (variable->string);
+          variable->string = strdup (value);
+          return;
+        }
+    }
+
+  if (variables->number == variables->space)
+    {
+      variables->list = (STRING_VARIABLE_INFO *) realloc
+        (variables->list,
+                   sizeof (STRING_VARIABLE_INFO) * (variables->space += 5));
+    }
+
+  variables->list[variables->number].name = strdup (name);
+  variables->list[variables->number].string = strdup (value);
+
+  variables->number++;
+}
+
+/* generic, similar to Perl re (\w+) with /a modifier */
+static size_t
+read_var_len (const char *text)
+{
+  const char *q = text;
+
+  while (*q && (isascii_alnum (*q) || *q == '_'))
+    q++;
+
+  return q - text;
+}
+
+static char *
+substitute_variables (const char *input_text,
+                      const STRING_VARIABLES_LIST *variables)
+{
+  TEXT substituted;
+  const char *p = input_text;
+
+  text_init (&substituted);
+  text_append (&substituted, "");
+
+  while (*p)
+    {
+      const char *q = strchr (p, '$');
+      if (q)
+        {
+          int found = 0;
+          size_t var_len;
+
+          if (q - p)
+            text_append_n (&substituted, p, q - p);
+          p = q;
+          q++; /* past $ */
+          if (*q == '{')
+            {
+              /* past { */
+              q++;
+              var_len = read_var_len (q);
+              if (var_len)
+                {
+                  if (*(q + var_len) == '}')
+                    {
+                      size_t i;
+                      char *flag = strndup (q, var_len);
+
+                      /* past } */
+                      q += var_len +1;
+                      for (i = 0; i < variables->number; i++)
+                        {
+                          if (!strcmp (variables->list[i].name, flag))
+                            {
+                              text_append (&substituted,
+                                           variables->list[i].string);
+                              found = 1;
+                              break;
+                            }
+                        }
+                      free (flag);
+                    }
+                }
+            }
+
+          if (!found)
+            text_append_n (&substituted, p, q - p);
+          p = q;
+        }
+      else
+        {
+          text_append (&substituted, p);
+          break;
+        }
+    }
+
+  return substituted.text;
+}
+
+static HTMLXREF_MANUAL *
+get_create_htmlxref_manual (HTMLXREF_MANUAL_LIST *htmlxref_list,
+                            const char *manual_name)
+{
+  size_t i;
+  HTMLXREF_MANUAL *htmlxref_manual;
+
+  for (i = 0; i < htmlxref_list->number; i++)
+    {
+      htmlxref_manual = &htmlxref_list->list[i];
+      if (!strcmp (htmlxref_manual->manual, manual_name))
+        return htmlxref_manual;
+    }
+
+  if (htmlxref_list->number == htmlxref_list->space)
+    {
+      htmlxref_list->list = (HTMLXREF_MANUAL *) realloc
+        (htmlxref_list->list,
+                   sizeof (HTMLXREF_MANUAL) * (htmlxref_list->space += 5));
+    }
+
+  htmlxref_manual = &htmlxref_list->list[htmlxref_list->number];
+  memset (htmlxref_manual, 0, sizeof (HTMLXREF_MANUAL));
+  htmlxref_manual->manual = strdup (manual_name);
+
+  htmlxref_list->number++;
+
+  return htmlxref_manual;
+}
+
+static void
+fill_source_info_file (SOURCE_INFO *source_info, CONVERTER *self,
+                       size_t line_nr, const char *file)
+{
+  source_info->macro = 0;
+  source_info->line_nr = line_nr;
+
+  if (self->conf->TEST.o.integer > 0)
+    {
+      char *filename_and_directory[2];
+     /* strip directories for out-of-source builds reproducible file names */
+      parse_file_path (file, filename_and_directory);
+      free (filename_and_directory[1]);
+      source_info->file_name = add_string (filename_and_directory[0],
+                                           &self->small_strings);
+      free (filename_and_directory[0]);
+    }
+  else
+    source_info->file_name = add_string (file, &self->small_strings);
+}
+
+static void
+parse_htmlxref_files (CONVERTER *self, HTMLXREF_MANUAL_LIST *htmlxref_list,
+                      STRING_LIST *htmlxref_files)
+{
+  size_t i;
+  int line_nr = 0;
+
+  STRING_VARIABLES_LIST variables;
+  memset (&variables, 0, sizeof (STRING_VARIABLES_LIST));
+
+  for (i = 0; i < htmlxref_files->number; i++)
+    {
+      const char *file = htmlxref_files->list[i];
+      FILE *stream = 0;
+
+      if (self->conf->DEBUG.o.integer > 0)
+        fprintf (stderr, "html refs config file: %s\n", file);
+
+      stream = fopen (file, "r");
+      if (!stream)
+        {
+          char *decoded_file;
+          const char *encoding = self->conf->COMMAND_LINE_ENCODING.o.string;
+
+          if (encoding)
+            {
+              int status;
+              /* cast to remove const */
+              decoded_file = decode_string ((char *)file,
+                                            encoding, &status, 0);
+            }
+          else
+            decoded_file = strdup (file);
+
+          message_list_document_warn (&self->error_messages,
+                 self->conf, 0, "could not open html refs config file %s: %s",
+                                      decoded_file, strerror (errno));
+
+          free (decoded_file);
+
+          continue;
+        }
+
+      while (1)
+        {
+          const char *p;
+          size_t n;
+          char *line = 0;
+          ssize_t status = getline (&line, &n, stream);
+          size_t len;
+          char *split_or_mono = 0;
+          char *manual;
+          char *href = 0;
+          enum htmlxref_split_type htmlxref_type = htmlxref_split_type_none;
+          const char *q;
+          size_t spaces_len;
+          char *subst_href;
+          HTMLXREF_MANUAL *htmlxref_manual;
+
+          if (status == -1)
+            {
+              free (line);
+              break;
+            }
+          line_nr++;
+
+                    /*
+          fprintf (stderr, "LLL %s:%d: %s", file, line_nr, line);
+                    */
+
+          p = line;
+
+          p += strspn (p, whitespace_chars);
+          if (*p == '#' || *p == '\0')
+            continue;
+
+          len = read_var_len (p);
+          if (len)
+            {
+              q = p;
+              q += len;
+              q += strspn (q, whitespace_chars);
+              if (*q == '=')
+                {
+                  char *name = strndup (p, len);
+                  char *definition;
+                  char *end_line;
+                  q++;
+                  q += strspn (q, whitespace_chars);
+                  definition = substitute_variables (q, &variables);
+                  end_line = strchr (definition, '\n');
+                  if (end_line)
+                    *end_line = '\0';
+                  set_variable_value (&variables, name, definition);
+                    /*
+                  fprintf (stderr, "VVV %s='%s'\n", name, definition);
+                     */
+                  free (definition);
+                  free (name);
+                  continue;
+                }
+            }
+          len = strcspn (p, whitespace_chars);
+          /* should always be true as we already handled a spaces only line */
+          if (len)
+            {
+              q = p + len;
+              spaces_len = strspn (q, whitespace_chars);
+
+              if (spaces_len && *q)
+                {
+                  size_t spec_len;
+
+                  q += spaces_len;
+                  spec_len = strcspn (q, whitespace_chars);
+
+                  if (spec_len)
+                    {
+                      split_or_mono = strndup (q, spec_len);
+                      q += spec_len;
+
+                      enum htmlxref_split_type i;
+
+                      for (i = 0; i < htmlxref_split_type_chapter+1; i++)
+                        {
+                          if (!strcmp (split_or_mono,
+                                       htmlxref_split_type_names[i]))
+                            {
+                              htmlxref_type = i;
+                              break;
+                            }
+                        }
+                    }
+                }
+            }
+            /*
+          fprintf (stderr, "SOM %s %d\n", split_or_mono, htmlxref_type);
+             */
+          if (!split_or_mono)
+            {
+              SOURCE_INFO source_info;
+              fill_source_info_file (&source_info, self, line_nr, file);
+
+              message_list_line_error_ext (&self->error_messages,
+                self->conf, MSG_warning, 0, &source_info, "missing type");
+              continue;
+            }
+          else if (htmlxref_type == htmlxref_split_type_none)
+            {
+              SOURCE_INFO source_info;
+              fill_source_info_file (&source_info, self, line_nr, file);
+
+              message_list_line_error_ext (&self->error_messages,
+                self->conf, MSG_warning, 0, &source_info,
+                "unrecognized type: %s", split_or_mono);
+              free (split_or_mono);
+              continue;
+            }
+
+          manual = strndup (p, len);
+
+          spaces_len = strspn (q, whitespace_chars);
+          if (spaces_len && *q)
+            {
+              q += spaces_len;
+              size_t spec_len = strcspn (q, whitespace_chars);
+              if (spec_len)
+                {
+                  href = strndup (q, spec_len);
+                }
+            }
+
+          if (!href)
+            {
+              SOURCE_INFO source_info;
+              fill_source_info_file (&source_info, self, line_nr, file);
+
+              message_list_line_error_ext (&self->error_messages,
+                self->conf, MSG_warning, 0, &source_info,
+                "missing %s URL prefix for `%s'", split_or_mono, manual);
+              free (split_or_mono);
+              free (manual);
+              continue;
+            }
+
+          free (split_or_mono);
+
+          htmlxref_manual
+            = get_create_htmlxref_manual (htmlxref_list, manual);
+          free (manual);
+
+           /*
+          fprintf (stderr, "FFF %s '%s' %d '%s'\n", htmlxref_manual->manual,
+                             href, htmlxref_type, 
htmlxref_manual->urlprefix[htmlxref_type]);
+            */
+          if (htmlxref_manual->urlprefix[htmlxref_type])
+            {
+              free (href);
+              continue;
+            }
+
+          subst_href = substitute_variables (href, &variables);
+
+          free (href);
+
+          if (htmlxref_type != htmlxref_split_type_mono)
+            {
+              size_t j;
+              for (j = strlen (subst_href); j > 0; j--)
+                if (subst_href[j-1] == '/')
+                  subst_href[j-1] = '\0';
+            }
+
+           /*
+          fprintf (stderr, "HHH %s '%s' %d\n", htmlxref_manual->manual,
+                             subst_href, htmlxref_type);
+           */
+
+          htmlxref_manual->urlprefix[htmlxref_type] = strdup (subst_href);
+          free (subst_href);
+        }
+
+      if (fclose (stream) == EOF)
+        {
+          char *decoded_file;
+          const char *encoding = self->conf->COMMAND_LINE_ENCODING.o.string;
+
+          if (encoding)
+            {
+              int status;
+              /* cast to remove const */
+              decoded_file = decode_string ((char *)file, encoding,
+                                            &status, 0);
+            }
+          else
+            decoded_file = strdup (file);
+          message_list_document_warn (&self->error_messages,
+                 self->conf, 0, "error on closing html refs config file %s: 
%s",
+                                      decoded_file, strerror (errno));
+
+          free (decoded_file);
+        }
+    }
+}
+
+static void
 load_htmlxref_files (CONVERTER *self)
 {
   const char *htmlxref_mode = self->conf->HTMLXREF_MODE.o.string;
@@ -655,6 +1081,67 @@ load_htmlxref_files (CONVERTER *self)
                                          htmlxref_file_name);
       free (encoded_htmlxref_file_name);
     }
+  else
+    {
+      STRING_LIST htmlxref_dirs;
+      memset (&htmlxref_dirs, 0, sizeof (STRING_LIST));
+
+      add_string (".", &htmlxref_dirs);
+
+      if (self->conf->TEST.o.integer > 0)
+        {
+          /* to have reproducible tests, do not use system or user
+             directories if TEST is set. */
+          if (conversion_paths_info.texinfo_uninstalled)
+            {
+              if (conversion_paths_info.p.uninstalled.top_srcdir)
+                {
+                  char *path;
+                  xasprintf (&path, "%s/tp/t/input_files",
+                             conversion_paths_info.p.uninstalled.top_srcdir);
+                  add_string (path, &htmlxref_dirs);
+                  free (path);
+                }
+              else
+                add_string ("tp/t/input_files", &htmlxref_dirs);
+            }
+          add_string (".texinfo", &htmlxref_dirs);
+        }
+      else
+        {
+          copy_strings (&htmlxref_dirs, &self->texinfo_language_config_dirs);
+        }
+
+      if (self->conf->TEST.o.integer > 0)
+        htmlxref_file_name = self->conf->HTMLXREF_FILE.o.string;
+      else if (self->conf->HTMLXREF_FILE.o.string)
+        htmlxref_file_name = self->conf->HTMLXREF_FILE.o.string;
+
+      if (htmlxref_file_name)
+        {
+          char *encoded_htmlxref_file_name;
+          char *path_encoding;
+
+          /* cast to remove const */
+          encoded_htmlxref_file_name
+            = encoded_output_file_name (self->conf,
+                                        &self->document->global_info,
+                                        (char *)htmlxref_file_name,
+                                        &path_encoding, 0);
+          free (path_encoding);
+
+          locate_file_in_dirs (encoded_htmlxref_file_name,
+                               &htmlxref_dirs, &htmlxref_files);
+          free (encoded_htmlxref_file_name);
+        }
+      free_strings_list (&htmlxref_dirs);
+    }
+
+  if (htmlxref_files.number > 0)
+    {
+      parse_htmlxref_files (self, &self->htmlxref, &htmlxref_files);
+      free_strings_list (&htmlxref_files);
+    }
 }
 
 /* this code corresponds to the Perl converter_initialize code, only for
@@ -796,17 +1283,6 @@ new_special_unit_formatting_references (int 
special_units_varieties_nr)
   return formatting_references;
 }
 
-/* Used to get htmlxref info from Perl.  Initialize in C */
-HTMLXREF_MANUAL *
-new_htmlxref_manual_list (size_t size)
-{
-  HTMLXREF_MANUAL *result = (HTMLXREF_MANUAL *)
-        malloc (size * sizeof (HTMLXREF_MANUAL));
-  memset (result, 0, size * sizeof (HTMLXREF_MANUAL));
-
-  return result;
-}
-
 static HTML_DIRECTION_STRING_TRANSLATED *
 new_directions_strings_translated_type (int nr_string_directions)
 {
diff --git a/tp/Texinfo/XS/convert/texinfo.c b/tp/Texinfo/XS/convert/texinfo.c
index d09f745f19..a559cc41a8 100644
--- a/tp/Texinfo/XS/convert/texinfo.c
+++ b/tp/Texinfo/XS/convert/texinfo.c
@@ -287,7 +287,9 @@ CONVERTER *
 txi_converter_setup (const char *format_str,
                      const char *output_format,
                      const char *locale_encoding,
-                     const char *program_file, OPTIONS_LIST *customizations)
+                     const char *program_file,
+                     char * const*texinfo_language_config_dirs,
+                     OPTIONS_LIST *customizations)
 {
   enum converter_format converter_format
     = find_format_name_converter_format (format_str);
@@ -302,6 +304,16 @@ txi_converter_setup (const char *format_str,
   else
     conf->output_format = strdup (format_str);
 
+  if (texinfo_language_config_dirs)
+    {
+      int i;
+      for (i = 0; texinfo_language_config_dirs[i]; i++)
+        {
+          add_string (texinfo_language_config_dirs[i],
+                      &conf->texinfo_language_config_dirs);
+        }
+    }
+
   initialize_options_list (&conf->conf, 10);
 
   /* similar to options coming from texi2any */
diff --git a/tp/Texinfo/XS/convert/texinfo.h b/tp/Texinfo/XS/convert/texinfo.h
index 5ffd458af3..12558fe28f 100644
--- a/tp/Texinfo/XS/convert/texinfo.h
+++ b/tp/Texinfo/XS/convert/texinfo.h
@@ -41,11 +41,12 @@ void txi_complete_document (DOCUMENT *document, unsigned 
long flags,
 
 CONVERTER *txi_converter (enum converter_format format,
                           CONVERTER_INITIALIZATION_INFO *conf);
-CONVERTER *
-txi_converter_setup (const char *converter_format,
+CONVERTER *txi_converter_setup (const char *converter_format,
                      const char *output_format,
                      const char *locale_encoding,
-                     const char *program_file, OPTIONS_LIST *customizations);
+                     const char *program_file,
+                     char *const *texinfo_language_config_dirs,
+                     OPTIONS_LIST *customizations);
 
 char *txi_html_output (CONVERTER *converter, DOCUMENT *document);
 
diff --git a/tp/Texinfo/XS/main/converter_types.h 
b/tp/Texinfo/XS/main/converter_types.h
index 9d9f8cef98..e93949d7d2 100644
--- a/tp/Texinfo/XS/main/converter_types.h
+++ b/tp/Texinfo/XS/main/converter_types.h
@@ -676,6 +676,7 @@ typedef struct HTMLXREF_MANUAL {
 
 typedef struct HTMLXREF_MANUAL_LIST {
     size_t number;
+    size_t space;
     HTMLXREF_MANUAL *list;
 } HTMLXREF_MANUAL_LIST;
 
@@ -763,6 +764,7 @@ typedef struct CONVERTER_INITIALIZATION_INFO {
     char *converted_format;
     char *output_format;
     TRANSLATED_COMMAND *translated_commands;
+    STRING_LIST texinfo_language_config_dirs;
     OPTIONS_LIST conf;
     /* gather strings that are not customization options */
     STRING_LIST non_valid_customization;
@@ -785,6 +787,7 @@ typedef struct CONVERTER {
     OPTION **sorted_options;
     OPTIONS *init_conf;
     OPTIONS *format_defaults_conf;
+    STRING_LIST texinfo_language_config_dirs;
     char *output_format;
     char *converted_format;
     EXPANDED_FORMAT *expanded_formats;
diff --git a/tp/Texinfo/XS/main/utils.c b/tp/Texinfo/XS/main/utils.c
index 4e4314c9a3..623d0e281c 100644
--- a/tp/Texinfo/XS/main/utils.c
+++ b/tp/Texinfo/XS/main/utils.c
@@ -28,6 +28,8 @@
 #include "unicase.h"
 #include "uniwidth.h"
 #include <unictype.h>
+/* for euidaccess.  Not portable, use gnulib */
+#include <unistd.h>
 
 #include "conversion_data.h"
 /* also for xvasprintf */
@@ -270,7 +272,9 @@ isascii_upper (int c)
 }
 
 
+
 /* operations on strings considered as multibytes.  Use libunistring */
+
 /* count characters, not bytes. */
 size_t
 count_multibyte (const char *text)
@@ -360,7 +364,9 @@ word_bytes_len_multibyte (const char *text)
 }
 
 
+
 /* encoding and decoding. Use iconv. */
+
 /* conversion to or from utf-8 should always be set before other
    conversion */
 ENCODING_CONVERSION *
@@ -586,8 +592,10 @@ encode_string (char *input_string, const char *encoding, 
int *status,
 }
 
 
+
 /* code related to the EXPANDED_FORMAT structure holding informations on the
    expanded formats (html, info, tex...) */
+
 void
 clear_expanded_formats (EXPANDED_FORMAT *formats)
 {
@@ -1032,6 +1040,35 @@ find_string (const STRING_LIST *strings_list, const char 
*target)
   return 0;
 }
 
+void
+clear_strings_list (STRING_LIST *strings)
+{
+  size_t i;
+  for (i = 0; i < strings->number; i++)
+    {
+      free (strings->list[i]);
+    }
+  strings->number = 0;
+}
+
+void
+free_strings_list (STRING_LIST *strings)
+{
+  size_t i;
+  for (i = 0; i < strings->number; i++)
+    {
+      free (strings->list[i]);
+    }
+  free (strings->list);
+}
+
+void
+destroy_strings_list (STRING_LIST *strings)
+{
+  free_strings_list (strings);
+  free (strings);
+}
+
 /* Return value to be freed by caller. */
 /* try to locate a file called FILENAME, looking for it in the list of include
    directories. */
@@ -1072,33 +1109,57 @@ locate_include_file (const char *filename, const 
STRING_LIST *include_dirs_list)
   return 0;
 }
 
-void
-clear_strings_list (STRING_LIST *strings)
-{
-  size_t i;
-  for (i = 0; i < strings->number; i++)
-    {
-      free (strings->list[i]);
-    }
-  strings->number = 0;
-}
+/* Return value to be freed by caller. */
+/* Used in main program, tests and HTML Converter.
+
+ FILENAME     file name to locate. It can be a file path. Binary string.
+ DIRECTORIES  list of directories to search the file in. Binary strings.
+ ALL_FILES    if set collect all the files with that name, otherwise stop
+              at first match.
+
+ If ALL_FILES is not set:
+   - if FILENAME is an absolute path: if found, return it;
+   - otherwise return the first file found in the directories;
+   - otherwise return NULL.
+ If ALL_FILES is set return NULL and:
+   - if FILENAME is an absolute path: if found, add to ALL_FILES;
+   - otherwise add all files found to ALL_FILES.
+ */
 
-void
-free_strings_list (STRING_LIST *strings)
+char *
+locate_file_in_dirs (const char *filename,
+                     const STRING_LIST *directories,
+                     STRING_LIST *all_files)
 {
-  size_t i;
-  for (i = 0; i < strings->number; i++)
+  if (!memcmp (filename, "/", 1))
     {
-      free (strings->list[i]);
+      if (euidaccess (filename, R_OK) == 0)
+        {
+          if (all_files)
+            add_string (filename, all_files);
+          else
+            return strdup (filename);
+        }
     }
-  free (strings->list);
-}
+  else
+    {
+      size_t i;
+      for (i = 0; i < directories->number; i++)
+        {
+          char *fullpath;
 
-void
-destroy_strings_list (STRING_LIST *strings)
-{
-  free_strings_list (strings);
-  free (strings);
+          xasprintf (&fullpath, "%s/%s", directories->list[i], filename);
+          if (euidaccess (fullpath, R_OK) == 0)
+            {
+              if (all_files)
+                add_string (fullpath, all_files);
+              else
+                return fullpath;
+            }
+          free (fullpath);
+        }
+    }
+  return 0;
 }
 
 
diff --git a/tp/Texinfo/XS/main/utils.h b/tp/Texinfo/XS/main/utils.h
index 580fa9b601..7b059cdc00 100644
--- a/tp/Texinfo/XS/main/utils.h
+++ b/tp/Texinfo/XS/main/utils.h
@@ -194,6 +194,9 @@ void add_include_directory (const char *filename,
                             STRING_LIST *include_dirs_list);
 char *locate_include_file (const char *filename,
                            const STRING_LIST *include_dirs_list);
+char *locate_file_in_dirs (const char *filename,
+                           const STRING_LIST *directories,
+                           STRING_LIST *all_files);
 
 ENCODING_CONVERSION *get_encoding_conversion (const char *encoding,
                                     ENCODING_CONVERSION_LIST *encodings_list);
diff --git a/tp/Texinfo/XS/teximakehtml.c b/tp/Texinfo/XS/teximakehtml.c
index b7e15e78c4..3d5f4764d2 100644
--- a/tp/Texinfo/XS/teximakehtml.c
+++ b/tp/Texinfo/XS/teximakehtml.c
@@ -100,6 +100,10 @@ main (int argc, char *argv[])
   OPTIONS_LIST convert_options;
   size_t errors_count = 0;
   size_t errors_nr;
+  char *texinfo_language_config_dirs[5] = {".texinfo"};
+  int txi_language_idx = 1;
+  char *home_dir;
+  char *home_texinfo_language_config_dirs = 0;
 
   /*
   const char *texinfo_text;
@@ -123,6 +127,33 @@ main (int argc, char *argv[])
 
   txi_setup (LOCALEDIR, 0, 0, 0, 0);
 
+
+  home_dir = getenv ("HOME");
+  if (home_dir)
+    {
+      xasprintf (&home_texinfo_language_config_dirs, "%s/.texinfo",
+                 home_dir);
+      texinfo_language_config_dirs[txi_language_idx]
+        = home_texinfo_language_config_dirs;
+      txi_language_idx++;
+    }
+  if (strlen (SYSCONFDIR))
+    {
+      texinfo_language_config_dirs[txi_language_idx]
+        = SYSCONFDIR "/texinfo";
+      txi_language_idx++;
+    }
+
+  if (strlen (DATADIR))
+    {
+      texinfo_language_config_dirs[txi_language_idx]
+        = DATADIR "/texinfo";
+      txi_language_idx++;
+    }
+
+  texinfo_language_config_dirs[txi_language_idx] = 0;
+
+
   parse_file_path (argv[0], program_file_name_and_directory);
   program_file = program_file_name_and_directory[0];
   free (program_file_name_and_directory[1]);
@@ -194,14 +225,19 @@ main (int argc, char *argv[])
   add_new_option_value (&convert_options, GOT_integer,
                            "PROGRAM_NAME_IN_FOOTER", 1, 0);
   /* this is set to help with comparison with previous invokations */
+  /*
   add_new_option_value (&convert_options, GOT_integer,
                            "TEST", 1, 0);
+   */
 
   converter = txi_converter_setup ("html", "html", locale_encoding,
-                                   program_file, &convert_options);
+                                   program_file,
+                                   texinfo_language_config_dirs,
+                                   &convert_options);
 
   free_options_list (&convert_options);
   free (program_file);
+  free (home_texinfo_language_config_dirs);
 
 
   /* conversion */



reply via email to

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