Update.
authorUlrich Drepper <drepper@redhat.com>
Thu, 17 Dec 1998 20:59:54 +0000 (20:59 +0000)
committerUlrich Drepper <drepper@redhat.com>
Thu, 17 Dec 1998 20:59:54 +0000 (20:59 +0000)
* iconv/gconv_int.h (gconv_module): Add new element from_regex_mem.
* iconv/gconv_conf.c (module_compare): Make s1 and s2 const.
(detect_conflict): New function.
(add_alias): Call detect_conflict to see whether there is already
a module for the new name.
(add_module): Make sure there is no alias for the new name.
(read_conf_file): Call add_alias with new argument.
(__gconv_read_conf): Don't destroy module tree immediately after
walking it.  We need it to test the internal conversions for
conflicts.
* iconv/gconv_db.c (find_derivation): Don't allocate memory for
regular expression.  There is now room in the module descriptor.
(free_mem): Don't free memory for regular expression.

ChangeLog
iconv/gconv_conf.c
iconv/gconv_db.c
iconv/gconv_int.h
manual/search.texi
sysdeps/unix/sysv/linux/tcsetattr.c

index 77a6d9a..acd528e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 1998-12-17  Ulrich Drepper  <drepper@cygnus.com>
 
+       * iconv/gconv_int.h (gconv_module): Add new element from_regex_mem.
+       * iconv/gconv_conf.c (module_compare): Make s1 and s2 const.
+       (detect_conflict): New function.
+       (add_alias): Call detect_conflict to see whether there is already
+       a module for the new name.
+       (add_module): Make sure there is no alias for the new name.
+       (read_conf_file): Call add_alias with new argument.
+       (__gconv_read_conf): Don't destroy module tree immediately after
+       walking it.  We need it to test the internal conversions for
+       conflicts.
+       * iconv/gconv_db.c (find_derivation): Don't allocate memory for
+       regular expression.  There is now room in the module descriptor.
+       (free_mem): Don't free memory for regular expression.
+
        * sysdeps/unix/sysv/linux/bits/socket.h: Add AF_IRDA, PF_IRDA and
        MSG_TRYHARD.
 
index 1b0f5b8..d3f516e 100644 (file)
@@ -87,8 +87,8 @@ builtin_aliases[] =
 static int
 module_compare (const void *p1, const void *p2)
 {
-  struct gconv_module *s1 = (struct gconv_module *) p1;
-  struct gconv_module *s2 = (struct gconv_module *) p2;
+  const struct gconv_module *s1 = (const struct gconv_module *) p1;
+  const struct gconv_module *s2 = (const struct gconv_module *) p2;
   int result;
 
   if (s1->from_pattern == NULL)
@@ -110,9 +110,78 @@ module_compare (const void *p1, const void *p2)
 }
 
 
+/* This function is used to test for a conflict which could be introduced
+   if adding a new alias.
+
+   This function is a *very* ugly hack.  The action-function is not
+   supposed to alter the parameter.  But we have to do this.   We will if
+   necessary compile the regular expression  so that we can see whether it
+   matches the alias name.  This is safe in this environment and for the
+   sake of performance we do it this way.  The alternative would be to
+   compile all regular expressions right from the start or to forget about
+   the compilation though we might need it later.
+
+   The second ugliness is that we have no possibility to pass parameters
+   to the function.  Therefore we use a global variable.  This is no problem
+   since we are for sure alone even in multi-threaded applications.  */
+
+/* This is alias we want to check.  */
+static const char *alias_to_test;
+
+/* This variable is set to a nonzero value once we have found a matching
+   entry.  */
+static int abort_conflict_search;
+
+static void
+detect_conflict (const void *p, VISIT value, int level)
+{
+  struct gconv_module *s = *(struct gconv_module **) p;
+
+  if ((value != endorder && value != leaf) || s->from_constpfx == NULL
+      || abort_conflict_search)
+    return;
+
+  /* Before we test the whole expression (if this is a regular expression)
+     make sure the constant prefix matches.  In case this is no regular
+     expression this is the whole string.  */
+  if (strcmp (alias_to_test, s->from_constpfx) == 0)
+    {
+      if (s->from_pattern == NULL)
+       /* This is a simple string and therefore we have a conflict.  */
+       abort_conflict_search = 1;
+      else
+       {
+         /* Make sure the regular expression is compiled (if possible).  */
+         if (s->from_regex == NULL)
+           {
+             /* Beware, this is what I warned you about in the comment
+                above.  We are modifying the object.  */
+             if (__regcomp (&s->from_regex_mem, s->from_pattern,
+                            REG_EXTENDED | REG_ICASE) != 0)
+               /* Something is wrong.  Remember this.  */
+               s->from_regex = (regex_t *) -1L;
+             else
+               s->from_regex = &s->from_regex_mem;
+           }
+
+         if (s->from_regex != (regex_t *) -1L)
+           {
+             regmatch_t match[1];
+
+             if (__regexec (s->from_regex, alias_to_test, 1, match, 0) == 0
+                 && match[0].rm_so == 0
+                 && alias_to_test[match[0].rm_eo] == '\0')
+               /* The whole string matched.  This is also a conflict.  */
+               abort_conflict_search = 1;
+           }
+       }
+    }
+}
+
+
 /* Add new alias.  */
 static inline void
-add_alias (char *rp)
+add_alias (char *rp, void *modules)
 {
   /* We now expect two more string.  The strings are normalized
      (converted to UPPER case) and strored in the alias database.  */
@@ -138,6 +207,16 @@ add_alias (char *rp)
     return;
   *wp++ = '\0';
 
+  /* Test whether this alias conflicts with any available module.  See
+     the comment before the function `detect_conflict' for a description
+     of this ugly hack.  */
+  alias_to_test = from;
+  abort_conflict_search = 0;
+  __twalk (modules, detect_conflict);
+  if (abort_conflict_search)
+    /* It does conflict, don't add the alias.  */
+    return;
+
   new_alias = (struct gconv_alias *)
     malloc (sizeof (struct gconv_alias) + (wp - from));
   if (new_alias != NULL)
@@ -290,6 +369,25 @@ add_module (char *rp, const char *directory, size_t dir_len, void **modules,
       if (need_ext)
        memcpy (tmp - 1, gconv_module_ext, sizeof (gconv_module_ext));
 
+      /* See whether we have already an alias with this name defined.
+        We do allow regular expressions matching this any alias since
+        this expression can also match other names and we test for aliases
+        before testing for modules.  */
+      if (! from_is_regex)
+       {
+         struct gconv_alias fake_alias;
+
+         fake_alias.fromname = new_module->from_constpfx;
+
+         if (__tfind (&fake_alias, &__gconv_alias_db, __gconv_alias_compare)
+             != NULL)
+           {
+             /* This module duplicates an alias.  */
+             free (new_module);
+             return;
+           }
+       }
+
       if (__tfind (new_module, modules, module_compare) == NULL)
        {
          if (__tsearch (new_module, modules, module_compare) == NULL)
@@ -364,7 +462,7 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len,
 
       if (rp - word == sizeof ("alias") - 1
          && memcmp (word, "alias", sizeof ("alias") - 1) == 0)
-       add_alias (rp);
+       add_alias (rp, *modules);
       else if (rp - word == sizeof ("module") - 1
               && memcmp (word, "module", sizeof ("module") - 1) == 0)
        add_module (rp, directory, dir_len, modules, nmodules, modcounter++);
@@ -449,9 +547,6 @@ __gconv_read_conf (void)
          /* Insert all module entries into the array.  */
          __twalk (modules, insert_module);
 
-         /* No remove the tree data structure.  */
-         __tdestroy (modules, nothing);
-
          /* Finally insert the builtin transformations.  */
          for (cnt = 0; cnt < (sizeof (builtin_modules)
                               / sizeof (struct gconv_module)); ++cnt)
@@ -464,8 +559,12 @@ __gconv_read_conf (void)
   while (cnt > 0)
     {
       char *copy = strdupa (builtin_aliases[--cnt]);
-      add_alias (copy);
+      add_alias (copy, modules);
     }
+  
+  if (nmodules != 0)
+    /* Now remove the tree data structure.  */
+    __tdestroy (modules, nothing);
 
   /* Restore the error number.  */
   __set_errno (save_errno);
index f5a67ff..1191454 100644 (file)
@@ -348,17 +348,14 @@ find_derivation (const char *toset, const char *toset_expand,
                /* First compile the regex if not already done.  */
                if (__gconv_modules_db[cnt]->from_regex == NULL)
                  {
-                   regex_t *newp = (regex_t *) malloc (sizeof (regex_t));
-
-                   if (__regcomp (newp, __gconv_modules_db[cnt]->from_pattern,
+                   if (__regcomp (&__gconv_modules_db[cnt]->from_regex_mem,
+                                  __gconv_modules_db[cnt]->from_pattern,
                                   REG_EXTENDED | REG_ICASE) != 0)
-                     {
-                       /* Something is wrong.  Remember this.  */
-                       free (newp);
-                       __gconv_modules_db[cnt]->from_regex = (regex_t *) -1L;
-                     }
+                     /* Something is wrong.  Remember this.  */
+                     __gconv_modules_db[cnt]->from_regex = (regex_t *) -1L;
                    else
-                     __gconv_modules_db[cnt]->from_regex = newp;
+                     __gconv_modules_db[cnt]->from_regex
+                       = &__gconv_modules_db[cnt]->from_regex_mem;
                  }
 
                if (__gconv_modules_db[cnt]->from_regex != (regex_t *) -1L)
@@ -627,15 +624,10 @@ free_mem (void)
     __tdestroy (__gconv_alias_db, free);
 
   for (cnt = 0; cnt < __gconv_nmodules; ++cnt)
-    {
-      if (__gconv_modules_db[cnt]->from_regex != NULL)
-       __regfree ((regex_t *) __gconv_modules_db[cnt]->from_regex);
-
-      /* Modules which names do not start with a slash are builtin
-        transformations and the memory is not allocated dynamically.  */
-      if (__gconv_modules_db[cnt]->module_name[0] == '/')
-       free (__gconv_modules_db[cnt]);
-    }
+    /* Modules which names do not start with a slash are builtin
+       transformations and the memory is not allocated dynamically.  */
+    if (__gconv_modules_db[cnt]->module_name[0] == '/')
+      free (__gconv_modules_db[cnt]);
 
   if (known_derivations != NULL)
     __tdestroy (known_derivations, free_derivation);
index f023919..bc67b0b 100644 (file)
@@ -67,6 +67,7 @@ struct gconv_module
   const char *from_constpfx;
   size_t from_constpfx_len;
   const regex_t *from_regex;
+  regex_t from_regex_mem;
 
   const char *to_string;
 
index 0bcbc9b..b43153a 100644 (file)
@@ -498,10 +498,10 @@ structure there is another function which allows to apply a function on
 all elements of the tree.  The function must have this type:
 
 @smallexample
-int __action_fn_t (const void *nodep, VISIT value, int level);
+void __action_fn_t (const void *nodep, VISIT value, int level);
 @end smallexample
 
-The @var{nodep} is the data value of the current node (nce given as the
+The @var{nodep} is the data value of the current node (once given as the
 @var{key} argument to @code{tsearch}).  @var{level} is a numeric value
 which corresponds to the depth of the current node in the tree.  The
 root node has the depth @math{0} and its children have a depth of
index b919dbe..4a35237 100644 (file)
@@ -73,9 +73,7 @@ tcsetattr (fd, optional_actions, termios_p)
       return -1;
     }
 
-  termios_p->c_iflag &= ~IBAUD0;
-
-  k_termios.c_iflag = termios_p->c_iflag;
+  k_termios.c_iflag = termios_p->c_iflag & ~IBAUD0;
   k_termios.c_oflag = termios_p->c_oflag;
   k_termios.c_cflag = termios_p->c_cflag;
   k_termios.c_lflag = termios_p->c_lflag;