(m17n_object): Be sure to initialize all members.
[m17n/m17n-lib.git] / src / database.c
index 4f83f8f..f7616e9 100644 (file)
 
 /***en
     @addtogroup m17nDatabase
-    @brief The m17n database and API for it
+    @brief The m17n database and API for it.
 
     The m17n library dynamically acquires various kinds of information
     in need from data in the <i> m17n database</i>.  Application
     programs can also add/load their original data to/from the m17n
     database.  The m17n database contains multiple heterogeneous data,
-    and each data is identified by four tags; TAG1, TAG2, TAG3, TAG4.
+    and each data is identified by four tags; TAG0, TAG1, TAG2, TAG3.
     Each tag must be a symbol.
 
-    TAG1 specifies the type of data stored in the database as below.
+    TAG0 specifies the type of data stored in the database as below.
 
-    <ul>
-
-    <li> If TAG1 is #Mchar_table, the data is of the @e chartable @e
+    @li
+    If TAG0 is #Mchar_table, the data is of the @e chartable @e
     type and provides information about each character.  In this case,
-    TAG2 specifies the type of the information and must be #Msymbol,
-    #Minteger, #Mstring, #Mtext, or #Mplist.  TAG3 and TAG4 can be any
+    TAG1 specifies the type of the information and must be #Msymbol,
+    #Minteger, #Mstring, #Mtext, or #Mplist.  TAG2 and TAG3 can be any
     symbols.
 
-    <li> If TAG1 is #Mcharset, the data is of the @e charset @e type
+    @li
+    If TAG0 is #Mcharset, the data is of the @e charset @e type
     and provides a decode/encode mapping table for a charset.  In this
-    case, TAG2 must be a symbol representing a charset.  TAG3 and TAG4
-    can be any symbols.
-
-    <li> If TAG1 is neither #Mchar_table nor #Mcharset, the data is of
-    the @e plist @e type.  See the documentation of the mdatabase_load
-    () function for the details.  In this case, TAG2, TAG3, and TAG4
+    case, TAG1 must be a symbol representing a charset.  TAG2 and TAG3
     can be any symbols.
 
-    </ul>
+    @li 
+    If TAG0 is neither #Mchar_table nor #Mcharset, the data is of
+    the @e plist @e type.  See the documentation of the 
+    mdatabase_load () function for the details.  
+    In this case, TAG1, TAG2, and TAG3 can be any symbols.
 
-    Below, the notation \<TAG1, TAG2, TAG3, TAG4\> means a data with
-    those tags.
+    The notation \<TAG0, TAG1, TAG2, TAG3\> means a data with those
+    tags.
 
     Application programs first calls the mdatabase_find () function to
     get a pointer to an object of the type #MDatabase.  That object
 
 /***ja
     @addtogroup m17nDatabase
-    @brief ¸À¸ì¾ðÊó¥Ù¡¼¥¹¤Ë¤È¤½¤ì¤Ë´Ø¤¹¤ë API
-
-    m17n ¥é¥¤¥Ö¥é¥ê¤ÏɬÍפ˱þ¤¸¤ÆưŪ¤Ë m17n ¸À¸ì¾ðÊó¥Ù¡¼¥¹¤«¤é¥Ç¡¼¥¿
-    ¤ò¼èÆÀ¤¹¤ë¡£¤Þ¤¿¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤âÆȼ«¤Î¥Ç¡¼¥¿¤ò m17n 
-    ¸À¸ì¾ðÊó¥Ù¡¼¥¹¤ËÄɲä·¡¢¤½¤ì¤òưŪ¤Ë¼èÆÀ¤¹¤ë¤³¤È¤¬¤Ç¤­¤ë¡£m17n ¸À
-    ¸ì¾ðÊó¥Ù¡¼¥¹¤ÏÊ£¿ô¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤«¤é¤Ê¤ê¡¢³Æ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ï£´¤Ä¤Î¥¿
-    ¥° TAG1, TAG2, TAG3, TAG4¡Ê¤¹¤Ù¤Æ¥·¥ó¥Ü¥ë¡Ë¤Ë¤è¤Ã¤Æ¼±Ê̤µ¤ì¤ë¡£
-
-    TAG1 ¤Ï¥Ç¡¼¥¿¥Ù¡¼¥¹Æâ¤Î¥Ç¡¼¥¿¤Î¥¿¥¤¥×¤ò¼¨¤¹¡£
-
-    TAG1 ¤¬ #Mchar_table ¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ï @e chartable¥¿¥¤¥× ¤È¸Æ¤Ð¤ì¡¢
-    ³Æʸ»ú¤Ë´Ø¤¹¤ë¾ðÊó¤òÄ󶡤¹¤ë¡£¤³¤Î¾ì¹ç TAG2 ¤Ï¾ðÊó¤Î¼ïÎà¤ò»ØÄꤹ¤ë
-    ¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢°Ê²¼¤Î¤¤¤º¤ì¤«¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
-
-    @li #Msymbol @li #Minteger @li #Mstring @li #Mtext @li #Mplist
-
-    TAG3 ¤È TAG4 ¤ÏǤ°Õ¤Î¥·¥ó¥Ü¥ë¤Ç¤è¤¤¡£
-
-    TAG1 ¤¬ #Mcharset ¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ï @e charset¥¿¥¤¥× ¤È¸Æ¤Ð¤ì¡¢Ê¸
-    »ú¥»¥Ã¥ÈÍѤΥǥ³¡¼¥É¡¿¥¨¥ó¥³¡¼¥É¥Þ¥Ã¥×¤òÄ󶡤¹¤ë¡£¤³¤Î¾ì¹ç TAG2 ¤Ï
-    Ê¸»ú¥»¥Ã¥È¤Î¥·¥ó¥Ü¥ë¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£TAG3 ¤È TAG4 ¤ÏǤ°Õ¤Î¥·¥ó
-    ¥Ü¥ë¤Ç¤è¤¤¡£
-
-    TAG1 ¤¬ #Mchar_table ¤Ç¤â #Mcharset ¤Ç¤â¤Ê¤¤¾ì¹ç¡¢¤½¤Î¥Ç¡¼¥¿¥Ù¡¼
-    ¥¹¤Ï @e plist ¥¿¥¤¥× ¤È¸Æ¤Ð¤ì¤ë¡£¾ÜºÙ¤Ë´Ø¤·¤Æ¤Ï´Ø¿ô mdatabase_load
-    () ¤ÎÀâÌÀ¤ò»²¾È¤Î¤³¤È¡£¤³¤Î¾ì¹ç TAG2¡¢TAG3¡¢TAG4 ¤ÏǤ°Õ¤Î¥·¥ó¥Ü¥ë
-    ¤Ç¤è¤¤¡£
-
-    °Ê²¼¡¢ÆÃÄê¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò \<TAG1, TAG2, TAG3, TAG4\> ¤È¤¤
-    ¤¦·Á¼°¤Çɽ¤ï¤¹¡£
-
-    ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï¡¢¤Þ¤º´Ø¿ô mdatabase_find () »È¤Ã¤Æ¥Ç¡¼
-    ¥¿¥Ù¡¼¥¹¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÝ»ý¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¡Ê#MDatabase ·¿¡Ë¤Ø¤Î
-    ¥Ý¥¤¥ó¥¿¤òÆÀ¤ë¡£¤½¤ì¤ËÀ®¸ù¤·¤¿¤é¡¢ mdatabase_load () ¤Ë¤è¤Ã¤Æ¼ÂºÝ
-    ¤Ë¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¥í¡¼¥É¤¹¤ë¡£¹½Â¤ÂΠ#MDatabase ¼«¿È¤¬¤É¤¦¼ÂÁõ¤µ¤ì
-    ¤Æ¤¤¤ë¤«¤Ï¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤«¤é¤Ï¸«¤¨¤Ê¤¤¡£
+    @brief m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤È¤½¤ì¤Ë´Ø¤¹¤ë API.
+
+    m17n ¥é¥¤¥Ö¥é¥ê¤ÏɬÍפ˱þ¤¸¤ÆưŪ¤Ë @e m17n @e ¥Ç¡¼¥¿¥Ù¡¼¥¹ 
+    ¤«¤é¾ðÊó¤ò¼èÆÀ¤¹¤ë¡£¤Þ¤¿¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤âÆȼ«¤Î¥Ç¡¼¥¿¤ò 
+    m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ËÄɲä·¡¢¤½¤ì¤òưŪ¤Ë¼èÆÀ¤¹¤ë¤³¤È¤¬¤Ç¤­¤ë¡£m17n 
+    ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤ÏÊ£¿ô¤Î¿Íͤʥǡ¼¥¿¤¬´Þ¤Þ¤ì¤Æ¤ª¤ê¡¢³Æ¥Ç¡¼¥¿¤Ï
+    TAG0, TAG1, TAG2, TAG3¡Ê¤¹¤Ù¤Æ¥·¥ó¥Ü¥ë¡Ë¤Î£´¤Ä¤Î¥¿¥°¤Ë¤è¤Ã¤Æ¼±Ê̤µ¤ì¤ë¡£
+
+    TAG0 ¤Ë¤è¤Ã¤Æ¡¢¥Ç¡¼¥¿¥Ù¡¼¥¹Æâ¤Î¥Ç¡¼¥¿¤Î¥¿¥¤¥×¤Ï¼¡¤Î¤è¤¦¤Ë»ØÄꤵ¤ì¤ë¡£
+
+    @li 
+    TAG0 ¤¬ #Mchar_table ¤Ç¤¢¤ë¥Ç¡¼¥¿¤Ï @e chartable¥¿¥¤¥× 
+    ¤È¸Æ¤Ð¤ì¡¢³Æʸ»ú¤Ë´Ø¤¹¤ë¾ðÊó¤òÄ󶡤¹¤ë¡£¤³¤Î¾ì¹ç
+    TAG1 ¤Ï¾ðÊó¤Î¼ïÎà¤ò»ØÄꤹ¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢#Msymbol, #Minteger, #Mstring,
+    #Mtext, #Mplist ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£TAG2 ¤È TAG3 ¤ÏǤ°Õ¤Î¥·¥ó¥Ü¥ë¤Ç¤è¤¤¡£
+
+    @li 
+    TAG0 ¤¬ #Mcharset ¤Ç¤¢¤ë¥Ç¡¼¥¿¤Ï @e charset¥¿¥¤¥× 
+    ¤È¸Æ¤Ð¤ì¡¢Ê¸»ú¥»¥Ã¥ÈÍѤΥǥ³¡¼¥É¡¿¥¨¥ó¥³¡¼¥É¥Þ¥Ã¥×¤òÄ󶡤¹¤ë¡£¤³¤Î¾ì¹ç TAG1
+    ¤Ïʸ»ú¥»¥Ã¥È¤Î¥·¥ó¥Ü¥ë¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£TAG2 ¤È TAG3
+    ¤ÏǤ°Õ¤Î¥·¥ó¥Ü¥ë¤Ç¤è¤¤¡£
+
+    @li
+    TAG0 ¤¬ #Mchar_table ¤Ç¤â #Mcharset ¤Ç¤â¤Ê¤¤¾ì¹ç¡¢¤½¤Î¥Ç¡¼¥¿¤Ï @e
+    plist¥¿¥¤¥× ¤Ç¤¢¤ë¡£¾ÜºÙ¤Ë´Ø¤·¤Æ¤Ï´Ø¿ô mdatabase_load () 
+    ¤ÎÀâÌÀ¤ò»²¾È¤Î¤³¤È¡£¤³¤Î¾ì¹ç TAG1¡¢TAG2¡¢TAG3 ¤ÏǤ°Õ¤Î¥·¥ó¥Ü¥ë¤Ç¤è¤¤¡£
+
+    ÆÃÄê¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò \<TAG0, TAG1, TAG2, TAG3\> 
+    ¤È¤¤¤¦·Á¼°¤Çɽ¤¹¡£
+
+    ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï¡¢¤Þ¤º´Ø¿ô mdatabase_find () 
+    ¤ò»È¤Ã¤Æ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÝ»ý¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¡Ê#MDatabase
+    ·¿¡Ë¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÆÀ¤ë¡£¤½¤ì¤ËÀ®¸ù¤·¤¿¤é¡¢ mdatabase_load () 
+    ¤Ë¤è¤Ã¤Æ¼ÂºÝ¤Ë¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¥í¡¼¥É¤¹¤ë¡£¹½Â¤ÂΠ#MDatabase 
+    ¼«¿È¤¬¤É¤¦¼ÂÁõ¤µ¤ì¤Æ¤¤¤ë¤«¤Ï¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤«¤é¤Ï¸«¤¨¤Ê¤¤¡£
 
     @latexonly \IPAlabel{database} @endlatexonly
 */
 #define MDB_DIR "mdb.dir"
 #define MDB_DIR_LEN 8
 
-/** List of database directories.  */ 
-static MPlist *mdb_dir_list;
-
 /** Structure for a data in the m17n database.  */
 
 struct MDatabase
@@ -251,13 +246,13 @@ load_chartable (FILE *fp, MSymbol type)
        i++, to = read_number (buf, &i);
       else
        to = from;
-      if (from < 0 || to < 0)
-       goto label_error;
+      if (from < 0 || to < from)
+       continue;
 
       while (buf[i] && isspace ((unsigned) buf[i])) i++;
       c = buf[i];
       if (!c)
-       break;
+       continue;
 
       if (type == Mstring)
        {
@@ -296,6 +291,18 @@ load_chartable (FILE *fp, MSymbol type)
        }
       else if (type == Msymbol)
        {
+         char *p = buf + i;
+
+         while (*p && ! isspace (*p)) 
+           {
+             if (*p == '\\' && p[1] != '\0')
+               {
+                 memmove (p, p + 1, buf + len - (p + 1));
+                 len--;
+               }
+             p++;
+           }
+         *p = '\0';
          if (! strcmp (buf + i, "nil"))
            val = (void *) Mnil;
          else
@@ -414,12 +421,10 @@ gen_database_name (char *buf, MSymbol *tags)
   return buf;
 }
 
-static void *
-load_database (MSymbol *tags, void *extra_info)
+static FILE *
+get_database_stream (char *filename)
 {
-  FILE *fp;
-  char *filename = (char *) extra_info;
-  void *value;
+  FILE *fp = NULL;
 
   if (filename[0] == '/')
     fp = fopen (filename, "r");
@@ -428,7 +433,7 @@ load_database (MSymbol *tags, void *extra_info)
       MPlist *plist;
       char path[PATH_MAX];
 
-      MPLIST_DO (plist, mdb_dir_list)
+      MPLIST_DO (plist, mdatabase__dir_list)
        {
          strcpy (path, (char *) MPLIST_VAL (plist));
          strcat (path, filename);
@@ -437,6 +442,15 @@ load_database (MSymbol *tags, void *extra_info)
            break;
        }
     }
+  return fp;
+}
+
+static void *
+load_database (MSymbol *tags, void *extra_info)
+{
+  FILE *fp = get_database_stream ((char *) extra_info);
+  void *value;
+
   if (! fp)
     MERROR (MERROR_DB, NULL);
 
@@ -445,7 +459,7 @@ load_database (MSymbol *tags, void *extra_info)
   else if (tags[0] == Mcharset)
     value = load_charset (fp, tags[1]);
   else
-    value = mplist__from_file (fp);
+    value = mplist__from_file (fp, NULL);
   fclose (fp);
 
   if (! value)
@@ -482,6 +496,11 @@ duplicate_dirname (char *dirname)
 \f
 /* Internal API */
 
+/** List of database directories.  */ 
+MPlist *mdatabase__dir_list;
+
+MSymbol M_database_hook;
+
 int
 mdatabase__init ()
 {
@@ -491,25 +510,26 @@ mdatabase__init ()
   FILE *fp;
 
   Mchar_table = msymbol ("char-table");
+  M_database_hook = msymbol ("  database-hook");
 
-  mdb_dir_list = mplist ();
+  mdatabase__dir_list = mplist ();
   /** The macro M17NDIR specifies a directory where the system-wide
     MDB_DIR file exists.  */
   if ((dir = duplicate_dirname (M17NDIR)))
-    mplist_set (mdb_dir_list, Mt, dir);
+    mplist_set (mdatabase__dir_list, Mt, dir);
 
   /* The variable mdatabase_dir specifies a directory where an
      application program specific MDB_DIR file exists.  */
   if ((dir = duplicate_dirname (mdatabase_dir)))
-    mplist_push (mdb_dir_list, Mt, dir);
+    mplist_push (mdatabase__dir_list, Mt, dir);
 
   /* The environment variable M17NDIR (if non-NULL) specifies a
      directory where a user specific MDB_DIR file exists.  */
   if ((dir = duplicate_dirname (getenv ("M17NDIR"))))
-    mplist_push (mdb_dir_list, Mt, dir);
+    mplist_push (mdatabase__dir_list, Mt, dir);
 
   MLIST_INIT1 (&mdb_list, mdbs, 256);
-  MPLIST_DO (plist, mdb_dir_list)
+  MPLIST_DO (plist, mdatabase__dir_list)
     {
       MPlist *pl, *p;
       int len;
@@ -523,7 +543,7 @@ mdatabase__init ()
       memcpy (path + len, MDB_DIR, MDB_DIR_LEN);
       if (! (fp = fopen (path, "r")))
        continue;
-      pl = mplist__from_file (fp);
+      pl = mplist__from_file (fp, NULL);
       fclose (fp);
       if (! pl)
        continue;
@@ -573,9 +593,9 @@ mdatabase__fini (void)
   int i;
   MPlist *plist; 
 
-  MPLIST_DO (plist, mdb_dir_list)
+  MPLIST_DO (plist, mdatabase__dir_list)
     free (MPLIST_VAL (plist));
-  M17N_OBJECT_UNREF (mdb_dir_list);
+  M17N_OBJECT_UNREF (mdatabase__dir_list);
 
   for (i = 0; i < mdb_list.used; i++)
     {
@@ -587,6 +607,29 @@ mdatabase__fini (void)
   MLIST_FREE1 (&mdb_list, mdbs);
 }
 
+MPlist *
+mdatabase__load_for_keys (MDatabase *mdb, MPlist *keys)
+{
+  int mdebug_mask = MDEBUG_DATABASE;
+  FILE *fp;
+  MPlist *plist;
+  char buf[256];
+
+  if (mdb->loader != load_database
+      || mdb->tag[0] == Mchar_table
+      || mdb->tag[0] == Mcharset)
+    MERROR (MERROR_DB, NULL);
+  MDEBUG_PRINT1 (" [DATABASE] loading <%s>.\n",
+                gen_database_name (buf, mdb->tag));
+  fp = get_database_stream ((char *) mdb->extra_info);
+  if (! fp)
+    MERROR (MERROR_DB, NULL);
+  plist = mplist__from_file (fp, keys);
+  fclose (fp);
+  return plist;
+}
+
+
 /*** @} */
 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
 
@@ -608,6 +651,16 @@ mdatabase__fini (void)
     definitions in the format described in @ref mdbDir "mdbDir(5)".
 
     The default value is NULL.  */
+/***ja
+    @brief ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¸ÇÍ­¤Î¥Ç¡¼¥¿Íѥǥ£¥ì¥¯¥È¥ê.
+
+    ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤¬¡¢¤½¤Î¥×¥í¥°¥é¥à¸ÇÍ­¤Î¥Ç¡¼¥¿¤ä m17n 
+    ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¾å½ñ¤­¤¹¤ë¥Ç¡¼¥¿¤òÄ󶡤¹¤ë¾ì¹ç¤Ë¤Ï¡¢¥Þ¥¯¥í M17N_INIT () 
+    ¤ò¸Æ¤ÖÁ°¤Ë¤³¤ÎÊÑ¿ô¤ò¥Ç¡¼¥¿¥Õ¥¡¥¤¥ë¤ò´Þ¤à¥Ç¥£¥ì¥¯¥È¥ê̾¤Ë¥»¥Ã¥È¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¥Ç¥£¥ì¥¯¥È¥ê¤Ë¤Ï
+    "mdb.dir" ¥Õ¥¡¥¤¥ë¤ò¤ª¤¯¤³¤È¤¬¤Ç¤­¤ë¡£¤½¤Î"mdb.dir"¥Õ¥¡¥¤¥ë¤Ë¤Ï¡¢ 
+    @ref mdbDir "mdbDir(5)" ¤ÇÀâÌÀ¤µ¤ì¤Æ¤¤¤ë¥Õ¥©¡¼¥Þ¥Ã¥È¤Ç¥Ç¡¼¥¿ÄêµÁ¤Î¥ê¥¹¥È¤òµ­½Ò¤¹¤ë¡£
+
+    ¥Ç¥Õ¥©¥ë¥È¤ÎÃͤϠNULL ¤Ç¤¢¤ë¡£  */
 
 char *mdatabase_dir;
 
@@ -616,16 +669,15 @@ char *mdatabase_dir;
     @brief Look for a data in the database.
 
     The mdatabase_find () function searches the m17n database for a
-    data who has tags $TAG1 through $TAG4, and returns a pointer to
-    the data.  If such a database is not found, it returns @c
-    NULL.  */
+    data who has tags $TAG0 through $TAG3, and returns a pointer to
+    the data.  If such a data is not found, it returns @c NULL.  */
 
 /***ja
-    @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹¤òõ¤¹
+    @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Î¥Ç¡¼¥¿¤òõ¤¹.
 
-    ´Ø¿ô mdatabase_find () ¤Ï¡¢ m17n ¸À¸ì¾ðÊó¥Ù¡¼¥¹Ãæ¤Ç $TAG1 ¤«¤é 
-    $TAG4 ¤Þ¤Ç¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¥Ù¡¼¥¹¤òõ¤·¡¢¤½¤ì¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
-    ¤½¤Î¤è¤¦¤Ê¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£
+    ´Ø¿ô mdatabase_find () ¤Ï¡¢ m17n ¸À¸ì¾ðÊó¥Ù¡¼¥¹Ãæ¤Ç $TAG0 ¤«¤é 
+    $TAG3 ¤Þ¤Ç¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¤òõ¤·¡¢¤½¤ì¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤Î¤è¤¦¤Ê¥Ç¡¼¥¿¤¬¤Ê¤±¤ì¤Ð
+    @c NULL ¤òÊÖ¤¹¡£
 
     @latexonly \IPAlabel{mdatabase_find} @endlatexonly  */
 
@@ -633,6 +685,11 @@ MDatabase *
 mdatabase_find (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
 {
   int i;
+  MDatabaseHookFunc func
+    = (MDatabaseHookFunc) msymbol_get (tag0, M_database_hook);
+
+  if (func)
+    func (tag0, tag1, tag2, tag3);
 
   for (i = 0; i < mdb_list.used; i++)
     {
@@ -652,16 +709,29 @@ mdatabase_find (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
     @brief Return a data list of the m17n database.
 
     The mdatabase_list () function searches the m17n database for data
-    who have tags $TAG1 through $TAG4, and returns their list by a
+    who have tags $TAG0 through $TAG3, and returns their list by a
     plist.  The value #Mnil in $TAGn means a wild card that matches
     any tag.  Each element of the plist has key #Mt and value a
     pointer to type #MDatabase.  */
+/***ja
+    @brief m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥Ç¡¼¥¿¥ê¥¹¥È¤òÊÖ¤¹.
+
+    ´Ø¿ô mdatabase_list () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é $TAG0 ¤«¤é$TAG3 
+    ¤Þ¤Ç¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¤òõ¤·¡¢¤½¤Î¥ê¥¹¥È¤òplist ¤È¤·¤ÆÊÖ¤¹¡£ $TAGn ¤¬ #Mnil
+    ¤Ç¤¢¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢Ç¤°Õ¤Î¥¿¥°¤Ë¥Þ¥Ã¥Á¤¹¤ë¥ï¥¤¥ë¥É¥«¡¼¥É¤È¤·¤Æ¼è¤ê°·¤ï¤ì¤ë¡£ÊÖ¤µ¤ì¤ë
+    plist ¤Î³ÆÍ×ÁǤϥ­¡¼ ¤È¤·¤Æ #Mt ¤ò¡¢ÃͤȤ·¤Æ #MDatabase ·¿¤Ø¤Î¥Ý¥¤¥ó¥¿¤ò»ý¤Ä¡£  */
+
 
 MPlist *
 mdatabase_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
 {
   int i;
   MPlist *plist = NULL, *pl;
+  MDatabaseHookFunc func
+    = (MDatabaseHookFunc) msymbol_get (tag0, M_database_hook);
+
+  if (func)
+    func (tag0, tag1, tag2, tag3);
 
   for (i = 0; i < mdb_list.used; i++)
     {
@@ -687,12 +757,12 @@ mdatabase_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
     @brief Define a data of the m17n database.
 
     The mdatabase_define () function defines a data that has tags
-    $TAG1 through $TAG4 and additional information $EXTRA_INFO.
+    $TAG0 through $TAG3 and additional information $EXTRA_INFO.
 
     $LOADER is a pointer to a function that loads the data from the
     database.  This function is called from the mdatabase_load ()
     function with the two arguments $TAGS and $EXTRA_INFO.  Here,
-    $TAGS is the array of $TAG1 through $TAG4.
+    $TAGS is the array of $TAG0 through $TAG3.
 
     If $LOADER is @c NULL, the default loader of the m17n library is
     used.  In this case, $EXTRA_INFO must be a string specifying a
@@ -704,23 +774,22 @@ mdatabase_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
     mdatabase_load ().  Otherwise, it returns @c NULL.  */
 
 /***ja
-    @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹¤òÄêµÁ¤¹¤ë
+    @brief m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥Ç¡¼¥¿¤òÄêµÁ¤¹¤ë.
 
-    ´Ø¿ô mdatabase_define () ¤Ï $TAG1 ¤«¤é $TAG4 ¤Þ¤Ç¤Î¥¿¥°¤ª¤è¤ÓÉÕ²Ã
-    ¾ðÊó $EXTRA_INFO ¤ò»ý¤Ä¥Ç¡¼¥¿¥Ù¡¼¥¹¤òÄêµÁ¤¹¤ë¡£
+    ´Ø¿ô mdatabase_define () ¤Ï $TAG0 ¤«¤é $TAG3 ¤Þ¤Ç¤Î¥¿¥°¤ª¤è¤ÓÉղþðÊó 
+    $EXTRA_INFO ¤ò»ý¤Ä¥Ç¡¼¥¿¤òÄêµÁ¤¹¤ë¡£
 
-    $LOADER ¤Ï¤½¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥í¡¼¥É¤ËÍѤ¤¤é¤ì¤ë´Ø¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢
-    ¤ë¡£¤³¤Î´Ø¿ô¤Ï mdatabase_load () ¤«¤é $MDB ¤È $EXTRA_INFO ¤È¤¤¤¦2 
-    ¤Ä¤Î°ú¿ôÉÕ¤­¤Ç¸Æ¤Ó½Ð¤µ¤ì¤ë¡£¤³¤³¤Ç $MDB ¤Ï mdatabase_load () ¤ËÅÏ
-    ¤µ¤ì¤¿°ú¿ô¤Ç¤¢¤ë¡£
+    $LOADER ¤Ï¤½¤Î¥Ç¡¼¥¿¤Î¥í¡¼¥É¤ËÍѤ¤¤é¤ì¤ë´Ø¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¤³¤Î´Ø¿ô¤Ï
+    mdatabase_load () ¤«¤é $TAGS ¤È $EXTRA_INFO ¤È¤¤¤¦Æó¤Ä¤Î°ú¿ôÉÕ¤­¤Ç¸Æ¤Ó½Ð¤µ¤ì¤ë¡£¤³¤³¤Ç 
+    $TAGS ¤Ï $TAG0 ¤«¤é $TAG3 ¤Þ¤Ç¤ÎÇÛÎó¤Ç¤¢¤ë¡£
 
-    ¤â¤· $LOADER ¤¬ @c NULL ¤Ê¤é¡¢m17n ¥é¥¤¥Ö¥é¥êɸ½à¤Î¥í¡¼¥À¤¬»È¤ï¤ì
-    ¤ë¡£¤³¤Î¥í¡¼¥À¤Ï¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò $EXTRA_INFO ¤Ë»ØÄꤵ¤ì¤¿Ì¾Á°¤Î¥Õ¥¡
-    ¥¤¥ë¤«¤é¥í¡¼¥É¤¹¤ë¡£
+    ¤â¤· $LOADER ¤¬ @c NULL ¤Ê¤é¡¢m17n ¥é¥¤¥Ö¥é¥êɸ½à¤Î¥í¡¼¥À¤¬»È¤ï¤ì¤ë¡£¤³¤Î¾ì¹ç¤Ë¤Ï
+    $EXTRA_INFO ¤Ï¥Ç¡¼¥¿¤ò´Þ¤à¥Õ¥¡¥¤¥ë̾¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
 
     @return
-    ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mdatabase_define () ¤ÏÄêµÁ¤µ¤ì¤¿¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ø¤Î
-    ¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£
+    ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mdatabase_define () 
+    ¤ÏÄêµÁ¤µ¤ì¤¿¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤³¤Î¥Ý¥¤¥ó¥¿¤Ï´Ø¿ô mdatabase_load () 
+    ¤Î°ú¿ô¤È¤·¤ÆÍѤ¤¤ë¤³¤È¤¬¤Ç¤­¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£
 
     @latexonly \IPAlabel{mdatabase_define} @endlatexonly  */
 
@@ -734,6 +803,11 @@ mdatabase_define (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3,
                  void *extra_info)
 {
   MDatabase *mdb;
+  MDatabaseHookFunc func
+    = (MDatabaseHookFunc) msymbol_get (tag0, M_database_hook);
+
+  if (func)
+    func (tag0, tag1, tag2, tag3);
 
   mdb = mdatabase_find (tag0, tag1, tag2, tag3);
   if (! mdb)
@@ -742,13 +816,19 @@ mdatabase_define (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3,
 
       template.tag[0] = tag0, template.tag[1] = tag1;
       template.tag[2] = tag2, template.tag[3] = tag3;
+      template.extra_info = NULL;
       MLIST_APPEND1 (&mdb_list, mdbs, template, MERROR_DB);
       mdb = mdb_list.mdbs + (mdb_list.used - 1);
     }
   mdb->loader = loader ? loader : load_database;
-  mdb->extra_info = extra_info;
   if (mdb->loader == load_database)
-    mdb->extra_info = strdup ((char *) extra_info);
+    {
+      if (mdb->extra_info)
+       free (mdb->extra_info);
+      mdb->extra_info = strdup ((char *) extra_info);
+    }
+  else
+    mdb->extra_info = extra_info;
   return (&(mdb_list.mdbs[mdb_list.used - 1]));
 }
 
@@ -760,22 +840,18 @@ mdatabase_define (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3,
     returns the contents.  The type of contents depends on the type of
     the data.
 
-    If the data is of the @e plist type, this function returns a
+    If the data is of the @e plist @e type, this function returns a
     pointer to @e plist.
 
-    If the database is of the @e chartable type, it returns a
+    If the database is of the @e chartable @e type, it returns a
     chartable.  The default value of the chartable is set according to
-    the second tag of the database as below:
-
-    <ul>
-
-    <li> If the tag is #Msymbol, the default value is #Mnil.
-    <li> If the tag is #Minteger, the default value is -1.
-    <li> Otherwise, the default value is @c NULL.
+    the second tag of the data as below:
 
-    </ul>
+    @li If the tag is #Msymbol, the default value is #Mnil.
+    @li If the tag is #Minteger, the default value is -1.
+    @li Otherwise, the default value is @c NULL.
 
-    If the data is of the charset type, it returns a plist of length 2
+    If the data is of the @e charset @e type, it returns a plist of length 2
     (keys are both #Mt).  The value of the first element is an array
     of integers that maps code points to the corresponding character
     codes.  The value of the second element is a chartable of integers
@@ -784,24 +860,24 @@ mdatabase_define (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3,
 
 
 /***ja
-    @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¥í¡¼¥É¤¹¤ë
+    @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹¤«¤é¥Ç¡¼¥¿¤ò¥í¡¼¥É¤¹¤ë.
 
-    ´Ø¿ô mdatabase_load () ¤Ï $MDB ¤¬»Ø¤¹¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¥í¡¼¥É¤·¡¢¤½¤Î
-    Ãæ¿È¤òÊÖ¤¹¡£ÊÖ¤µ¤ì¤ë¤â¤Î¤Ï¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥¿¥¤¥×¤Ë¤è¤Ã¤Æ°Û¤Ê¤ë¡£
+    ´Ø¿ô mdatabase_load () ¤Ï $MDB 
+    ¤¬»Ø¤¹¥Ç¡¼¥¿¤ò¥í¡¼¥É¤·¡¢¤½¤ÎÃæ¿È¤òÊÖ¤¹¡£ÊÖ¤µ¤ì¤ë¤â¤Î¤Ï¥Ç¡¼¥¿¤Î¥¿¥¤¥×¤Ë¤è¤Ã¤Æ°Û¤Ê¤ë¡£
 
-    ¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬ plist ¥¿¥¤¥×¤Ê¤é¤Ð¡¢ @e plist ¤òÊÖ¤¹¡£
+    ¥Ç¡¼¥¿¤¬ @e plist¥¿¥¤¥× ¤Ê¤é¤Ð¡¢ @e plist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
 
-    ¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬ chartable ¥¿¥¤¥×¤Ê¤é¤Ðʸ»ú¥Æ¡¼¥Ö¥ë¤òÊÖ¤¹¡£Ê¸»ú
-    ¥Æ¡¼¥Ö¥ë¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤϡ¢Âè2¥¿¥°¤Ë¤è¤Ã¤Æ°Ê²¼¤Î¤è¤¦¤Ë·è¤Þ¤ë¡£
+    ¥Ç¡¼¥¿¤¬ @e chartable¥¿¥¤¥× ¤Ê¤é¤Ðʸ»ú¥Æ¡¼¥Ö¥ë¤òÊÖ¤¹¡£
+    Ê¸»ú¥Æ¡¼¥Ö¥ë¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤϡ¢¥Ç¡¼¥¿¤ÎÂè2¥¿¥°¤Ë¤è¤Ã¤Æ°Ê²¼¤Î¤è¤¦¤Ë·è¤Þ¤ë¡£
 
     @li ¥¿¥°¤¬ #Msymbol ¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃͤϠ#Mnil
     @li ¥¿¥°¤¬ #Minteger ¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃͤϠ-1
     @li ¤½¤ì°Ê³°¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃͤϠ@c NULL
 
-    ¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬ charset ¥¿¥¤¥×¤Ê¤é¤ÐŤµ 2 ¤Î @c plist ¤òÊÖ¤¹¡Ê¥­¡¼
-    ¤Ï¶¦¤Ë #Mt ¡Ë¡£ºÇ½é¤ÎÍ×ÁǤÎÃͤϥ³¡¼¥É¥Ý¥¤¥ó¥È¤òʸ»ú¥³¡¼¥É¤Ë¥Þ¥Ã
-    ¥×¤¹¤ëÀ°¿ô¤ÎÇÛÎó¤Ç¤¢¤ë¡££²ÈÖÌܤÎÍ×ÁǤÎÃͤϤ½¤ÎµÕ¤Î¥Þ¥Ã¥×¤ò¤¹¤ëʸ»ú
-    ¥Æ¡¼¥Ö¥ë¤Ç¤¢¤ë¡£¤³¤Îʸ»ú¥»¥Ã¥È¤Ïͽ¤áÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
+    ¥Ç¡¼¥¿¤¬ @e charset¥¿¥¤¥× ¤Ê¤é¤ÐŤµ 2 ¤Î plist ¤òÊÖ¤¹¡Ê¥­¡¼¤Ï¶¦¤Ë#Mt ¡Ë¡£
+    ºÇ½é¤ÎÍ×ÁǤÎÃͤϥ³¡¼¥É¥Ý¥¤¥ó¥È¤òÂбþ¤¹¤ëʸ»ú¥³¡¼¥É¤Ë¥Þ¥Ã¥×¤¹¤ëÀ°¿ô¤ÎÇÛÎó¤Ç¤¢¤ë¡£
+    £²ÈÖÌܤÎÍ×ÁǤÎÃͤϵդΥޥåפò¤¹¤ëʸ»ú¥Æ¡¼¥Ö¥ë¤Ç¤¢¤ë¡£
+    ¤³¤Îʸ»ú¥»¥Ã¥È¤Ïͽ¤áÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
 
     @latexonly \IPAlabel{mdatabase_load} @endlatexonly
   */
@@ -830,10 +906,10 @@ mdatabase_load (MDatabase *mdb)
     four.  */
 
 /***ja
-    @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥¿¥°¤òÆÀ¤ë
+    @brief ¥Ç¡¼¥¿¤Î¥¿¥°¤òÆÀ¤ë.
 
-    ´Ø¿ô mdatabase_tag () ¤Ï¡¢¥Ç¡¼¥¿¥Ù¡¼¥¹ $MDB ¤Î¥¿¥°¡Ê¥·¥ó¥Ü¥ë¡Ë¤ÎÇÛ
-    Îó¤òÊÖ¤¹¡£ÇÛÎó¤ÎŤµ¤Ï 4 ¤Ç¤¢¤ë¡£
+    ´Ø¿ô mdatabase_tag () ¤Ï¡¢¥Ç¡¼¥¿ $MDB ¤Î¥¿¥°¡Ê¥·¥ó¥Ü¥ë¡Ë¤ÎÇÛÎó¤òÊÖ¤¹¡£ÇÛÎó¤ÎŤµ¤Ï
+    4 ¤Ç¤¢¤ë¡£
 
     @latexonly \IPAlabel{mdatabase_tag} @endlatexonly  */