(mface__realize): Set rfont->layouter to Mnil.
[m17n/m17n-lib.git] / src / plist.c
index abf1bd6..5769e63 100644 (file)
 
     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤È¤½¤ì¤Ë´Ø¤¹¤ë API.
 
-    @e ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È (¤Þ¤¿¤Ï @e plist) ¤Ï 0 ¸Ä°Ê¾å¤Î¥×¥í¥Ñ¥Æ¥£¤Î¥ê
-    ¥¹¥È¤Ç¤¢¤ë¡£¥×¥í¥Ñ¥Æ¥£¤Ï @e ¥­¡¼ ¤È @e ÃÍ ¤«¤é¤Ê¤ë¡£¥­¡¼¤Ï¥·¥ó¥Ü¥ë
-    ¤Ç¤¢¤ê¡¢ÃͤϠ<tt>(void *)</tt> ¤Ë¥­¥ã¥¹¥È¤Ç¤­¤ë¤â¤Î¤Ê¤é¤Ð²¿¤Ç¤âÎÉ
-    ¤¤¡£
+    @e ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È (¤Þ¤¿¤Ï @e plist) ¤Ï 0 
+    ¸Ä°Ê¾å¤Î¥×¥í¥Ñ¥Æ¥£¤Î¥ê¥¹¥È¤Ç¤¢¤ë¡£¥×¥í¥Ñ¥Æ¥£¤Ï @e ¥­¡¼ ¤È @e ÃÍ 
+    ¤«¤é¤Ê¤ë¡£¥­¡¼¤Ï¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢ÃͤϠ<tt>(void *)</tt> 
+    ¤Ë¥­¥ã¥¹¥È¤Ç¤­¤ë¤â¤Î¤Ê¤é¤Ð²¿¤Ç¤âÎɤ¤¡£
 
-    ¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤¬ @e ´ÉÍý¥­¡¼ ¤Ê¤é¤Ð¡¢¤½¤Î @e ÃÍ ¤Ï@e ´ÉÍý²¼
-    ¥ª¥Ö¥¸¥§¥¯¥È ¤Ç¤¢¤ë¡£¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¼«ÂΤâ´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢
-    ¤ë¡£  */
+    ¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤¬ @e ´ÉÍý¥­¡¼ ¤Ê¤é¤Ð¡¢¤½¤Î @e ÃÍ ¤Ï @e ´ÉÍý²¼
+    @e ¥ª¥Ö¥¸¥§¥¯¥È 
+    ¤Ç¤¢¤ë¡£¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¼«ÂΤâ´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ë¡£  */
 
 /*=*/
 
@@ -56,6 +56,7 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "config.h"
 #include "m17n.h"
 #include "m17n-misc.h"
 #include "internal.h"
@@ -150,12 +151,9 @@ get_byte (MStream *st)
   return st->buffer[0];
 }
 
-#define GETC(st)       \
-  ((st)->p < (st)->pend ? *(st)->p++ : get_byte (st))
+#define GETC(st) ((st)->p < (st)->pend ? *(st)->p++ : get_byte (st))
 
-
-#define UNGETC(c, st)  \
-  (*--(st)->p = (c))
+#define UNGETC(c, st) (--((st)->p))
 
 /** Mapping table for reading a number.  Hexadecimal chars
     (0..9,A..F,a..F) are mapped to the corresponding numbers.
@@ -208,35 +206,34 @@ read_hexadesimal (MStream *st)
 /** Read an M-text element from ST, and add it to LIST.  Return a list
     for the next element.  */
 
+#define READ_MTEXT_BUF_SIZE 256
+
 static MPlist *
-read_mtext_element (MPlist *plist, MStream *st)
+read_mtext_element (MPlist *plist, MStream *st, int skip)
 {
-  unsigned char buffer[1024];
-  int bufsize = 1024;
-  unsigned char *buf = buffer;
-  int c, i;
+  union {
+    int chars[READ_MTEXT_BUF_SIZE];
+    unsigned char bytes[sizeof (int) * READ_MTEXT_BUF_SIZE];
+  } buffer;
+  unsigned char *bytes = buffer.bytes;
+  int nbytes = sizeof (int) * READ_MTEXT_BUF_SIZE;
+  int *chars = NULL;
+  int nchars = 0;
+  int c, i, j;
 
   i = 0;
   while ((c = GETC (st)) != EOF && c != '"')
     {
-      if (i + MAX_UTF8_CHAR_BYTES >= bufsize)
-       {
-         bufsize *= 2;
-         if (buf == buffer)
-           {
-             MTABLE_MALLOC (buf, bufsize, MERROR_PLIST);
-             memcpy (buf, buffer, i);
-           }
-         else
-           MTABLE_REALLOC (buf, bufsize, MERROR_PLIST);
-       }
+      int is_char = 0;
 
       if (c == '\\')
        {
          c = GETC (st);
          if (c == EOF)
            break;
-         if (c == 'x')
+         if (c == '\n')
+           continue;
+         if (c == 'x' || c == 'u')
            {
              int next_c;
 
@@ -244,18 +241,76 @@ read_mtext_element (MPlist *plist, MStream *st)
              next_c = GETC (st);
              if (next_c != ' ')
                UNGETC (next_c, st);
+             if (c >= 0x80)
+               is_char = 1;
            }
          else
            c = escape_mnemonic[c];
        }
 
-      buf[i++] = c;
+      if (! skip)
+       {
+         if (is_char && ! chars)
+           {
+             chars = buffer.chars;
+             for (j = i - 1; j >= 0; j--)
+               chars[j] = bytes[j];
+             nchars = READ_MTEXT_BUF_SIZE;
+             if (bytes != buffer.bytes)
+               free (bytes);
+           }
+
+         if (chars)
+           {
+             if (i + 1 >= nchars)
+               {
+                 nchars *= 2;
+                 if (chars == buffer.chars)
+                   {
+                     MTABLE_MALLOC (chars, nchars, MERROR_PLIST);
+                     memcpy (chars, buffer.chars, sizeof (int) * i);
+                   }
+                 else
+                   MTABLE_REALLOC (chars, nchars, MERROR_PLIST);
+               }
+             chars[i++] = c;
+           }
+         else
+           {
+             if (i + MAX_UTF8_CHAR_BYTES >= nbytes)
+               {
+                 nbytes *= 2;
+                 if (bytes == buffer.bytes)
+                   {
+                     MTABLE_MALLOC (bytes, nbytes, MERROR_PLIST);
+                     memcpy (bytes, buffer.bytes, i);
+                   }
+                 else
+                   MTABLE_REALLOC (bytes, nbytes, MERROR_PLIST);
+               }
+             bytes[i++] = c;
+           }
+       }
     }
 
-  MPLIST_SET_ADVANCE (plist, Mtext,
-                     mtext__from_data (buf, i, MTEXT_FORMAT_UTF_8, 1));
-  if (buf != buffer)
-    free (buf);
+  if (! skip)
+    {
+      MText *mt;
+
+      if (chars)
+       {
+         mt = mtext__from_data (chars, i, MTEXT_FORMAT_UTF_32, 1);
+         if (chars != buffer.chars)
+           free (chars);
+       }         
+      else
+       {
+         mt = mtext__from_data (bytes, i, MTEXT_FORMAT_UTF_8, 1);
+         if (bytes != buffer.bytes)
+           free (bytes);
+       }
+      MPLIST_SET_ADVANCE (plist, Mtext, mt);
+    }
   return plist;
 }
 
@@ -288,7 +343,7 @@ read_character (MStream *st, int c)
     read the character C. */
 
 static MPlist *
-read_integer_element (MPlist *plist, MStream *st, int c)
+read_integer_element (MPlist *plist, MStream *st, int c, int skip)
 {
   int num;
 
@@ -328,7 +383,8 @@ read_integer_element (MPlist *plist, MStream *st, int c)
   else
     num = read_decimal (st, c);
 
-  MPLIST_SET_ADVANCE (plist, Minteger, (void *) num);
+  if (! skip)
+    MPLIST_SET_ADVANCE (plist, Minteger, (void *) num);
   return plist;
 }
 
@@ -336,7 +392,7 @@ read_integer_element (MPlist *plist, MStream *st, int c)
     for the next element.  */
 
 static MPlist *
-read_symbol_element (MPlist *plist, MStream *st)
+read_symbol_element (MPlist *plist, MStream *st, int skip)
 {
   unsigned char buffer[1024];
   int bufsize = 1024;
@@ -366,15 +422,19 @@ read_symbol_element (MPlist *plist, MStream *st)
            break;
          c = escape_mnemonic[c];
        }
-      buf[i++] = c;
+      if (! skip)
+       buf[i++] = c;
     }
 
-  buf[i] = 0;
-  MPLIST_SET_ADVANCE (plist, Msymbol, msymbol ((char *) buf));
-  if (buf != buffer)
-    free (buf);
   if (c > ' ')
     UNGETC (c, st);
+  if (! skip)
+    {
+      buf[i] = 0;
+      MPLIST_SET_ADVANCE (plist, Msymbol, msymbol ((char *) buf));
+      if (buf != buffer)
+       free (buf);
+    }
   return plist;
 }
 
@@ -386,10 +446,14 @@ read_symbol_element (MPlist *plist, MStream *st)
        '0'..'9', '-': integer
        '?': integer representing character code
        the other ASCII letters: symbol
-*/
+
+   If KEYS is not NULL, it is a plist contains target keys and stop
+   keys.  In this caes, read only a plist whose key has value 1 in
+   KEYS, and return NULL when we encounter a plist whose key has value
+   0 in KEYS while skipping any other elements.  */
 
 static MPlist *
-read_element (MPlist *plist, MStream *st)
+read_element (MPlist *plist, MStream *st, MPlist *keys)
 {
   int c;
 
@@ -410,18 +474,51 @@ read_element (MPlist *plist, MStream *st)
 
       MPLIST_NEW (pl);
       p = pl;
-      while ((p = read_element (p, st)));
-      MPLIST_SET_ADVANCE (plist, Mplist, pl);
+      p = read_element (p, st, NULL);
+      if (keys && p && MPLIST_SYMBOL_P (pl))
+       {
+         if (MPLIST_TAIL_P (keys))
+           {
+             while ((p = read_element (p, st, NULL)));
+             MPLIST_SET_ADVANCE (plist, Mplist, pl);
+             return NULL;
+           }
+         else
+           {
+             MPlist *p0 = keys;
+
+             MPLIST_FIND (p0, MPLIST_SYMBOL (pl));
+             if (! MPLIST_TAIL_P (p0) && ! MPLIST_VAL (p0))
+               {
+                 M17N_OBJECT_UNREF (pl);
+                 return NULL;
+               }
+             while ((p = read_element (p, st, NULL)));
+             if (! MPLIST_TAIL_P (p0))
+               {
+                 MPLIST_SET_ADVANCE (plist, Mplist, pl);
+                 return NULL;
+               }
+             else
+               M17N_OBJECT_UNREF (pl);
+           }
+       }
+      else
+       {
+         if (p)
+           while ((p = read_element (p, st, NULL)));
+         MPLIST_SET_ADVANCE (plist, Mplist, pl);
+       }
       return plist;
     }
   if (c == '"')
-    return read_mtext_element (plist, st);
+    return (read_mtext_element (plist, st, keys ? 1 : 0));
   if ((c >= '0' && c <= '9') || c == '-' || c == '?' || c == '#')
-    return read_integer_element (plist, st, c);
+    return (read_integer_element (plist, st, c, keys ? 1 : 0));
   if (c == EOF || c == ')')
     return NULL;
   UNGETC (c, st);
-  return read_symbol_element (plist, st);
+  return (read_symbol_element (plist, st, keys ? 1 : 0));
 }
 
 void
@@ -533,7 +630,7 @@ dump_plist_element (MPlist *plist, int indent)
     fprintf (stderr, "%x", MPLIST_INTEGER (plist));
   else if (key == Mstring) 
     fprintf (stderr, "\"%s\"", MPLIST_STRING (plist));
-  else if (key == Mplist)
+  else if (MPLIST_NESTED_P (plist))
     {
       fprintf (stderr, "\n%s", prefix);
       mdebug_dump_plist (MPLIST_PLIST (plist), indent);
@@ -550,7 +647,7 @@ mplist__init ()
 {
   int i;
 
-  plist_table.count = 0;
+  M17N_OBJECT_ADD_ARRAY (plist_table, "Plist");
 
   Minteger = msymbol ("integer");
   Mplist = msymbol_as_managing_key ("plist");
@@ -580,7 +677,6 @@ mplist__init ()
 void
 mplist__fini (void)
 {
-  mdebug__report_object ("Plist", &plist_table);
 }
 
 
@@ -605,7 +701,7 @@ mplist__from_plist (MPlist *plist)
       key = MPLIST_SYMBOL (plist);
       plist = MPLIST_NEXT (plist);
       type = MPLIST_KEY (plist);
-      if (type->managing_key)
+      if (type->managing_key && MPLIST_VAL (plist))
        M17N_OBJECT_REF (MPLIST_VAL (plist));
       MPLIST_SET_ADVANCE (p, key, MPLIST_VAL (plist));
       plist = MPLIST_NEXT (plist);
@@ -643,7 +739,7 @@ mplist__from_alist (MPlist *plist)
 
 
 MPlist *
-mplist__from_file (FILE *fp)
+mplist__from_file (FILE *fp, MPlist *keys)
 {
   MPlist *plist, *pl;
   MStream st;
@@ -653,7 +749,7 @@ mplist__from_file (FILE *fp)
   st.p = st.pend = st.buffer;
   MPLIST_NEW (plist);
   pl = plist;
-  while ((pl = read_element (pl, &st)));
+  while ((pl = read_element (pl, &st, keys)));
   return plist;
 }
 
@@ -702,7 +798,7 @@ mplist__from_string (unsigned char *str, int n)
   st.pend = str + n;
   MPLIST_NEW (plist);
   pl = plist;
-  while ((pl = read_element (pl, &st)));
+  while ((pl = read_element (pl, &st, NULL)));
   return plist;
 }
 
@@ -720,6 +816,55 @@ mplist__serialize (MText *mt, MPlist *plist)
   return 0;
 }
 
+/**en
+    @brief Concatenate two plists.
+
+    The mplist__conc () function concatenates plist $TAIL at the end of
+    plist $PLIST and return $PLIST.  If $TAIL is empty, return $PLIST
+    without modifying it.  */
+
+MPlist *
+mplist__conc (MPlist *plist, MPlist *tail)
+{
+  MPlist *pl;
+
+  if (MPLIST_TAIL_P (tail))
+    return plist;
+  MPLIST_DO (pl, plist);
+  MPLIST_KEY (pl) = MPLIST_KEY (tail);
+  MPLIST_VAL (pl) = MPLIST_VAL (tail);
+  if (MPLIST_KEY (pl)->managing_key)
+    M17N_OBJECT_REF (MPLIST_VAL (pl));
+  tail = MPLIST_NEXT (tail);
+  MPLIST_NEXT (pl) = tail;
+  M17N_OBJECT_REF (tail);
+  return plist;
+}
+
+/*=*/
+/**en
+    @brief Discard a property at the beginning of a property list.
+
+    The mplist__pop_unref () function removes a property at the
+    beginning of property list $PLIST, and if the property value is a
+    managed object, unref it.  As a result, the second key and value
+    of the original $PLIST become the first of those of the new
+    $PLIST.  */
+
+void
+mplist__pop_unref (MPlist *plist)
+{
+  MSymbol key;
+  void *val;
+
+  if (MPLIST_TAIL_P (plist))
+    return;
+  key = MPLIST_KEY (plist);
+  val = mplist_pop (plist);
+  if (key->managing_key)
+    M17N_OBJECT_UNREF (val);
+}
+
 /*** @} */
 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
 
@@ -733,7 +878,7 @@ mplist__serialize (MText *mt, MPlist *plist)
 /***en
     @brief Symbol whose name is "integer".
 
-    The symbol @c Minteger has the name <tt>"integer"</tt>.  A value
+    The symbol @c Minteger has the name <tt>"integer"</tt>.  The value
     of a property whose key is @c Minteger must be an integer.  */
 /***ja
     @brief "integer" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë.
@@ -753,9 +898,9 @@ MSymbol Minteger;
 /***ja
     @brief "plist" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë.
 
-    ¥·¥ó¥Ü¥ë @c Mplist ¤Ï <tt>"plist"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¡£¤³¤ì¤Ï´É
-    Íý¥­¡¼¤Ç¤¢¤ë¡£¥­¡¼¤¬ @c Mplist ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϠplist ¤Ç¤Ê¤¯
-    ¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£  */
+    ¥·¥ó¥Ü¥ë @c Mplist ¤Ï <tt>"plist"</tt> 
+    ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¡£¤³¤ì¤Ï´ÉÍý¥­¡¼¤Ç¤¢¤ë¡£¥­¡¼¤¬ @c Mplist 
+    ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϠplist ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£  */
 
 MSymbol Mplist;
 /*=*/
@@ -770,9 +915,9 @@ MSymbol Mplist;
 /***ja
     @brief "mtext" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë.
 
-    ¥·¥ó¥Ü¥ë @c Mtext ¤Ï <tt>"mtext"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä´ÉÍý¥­¡¼¤Ç¤¢
-    ¤ë¡£¥­¡¼¤¬ @c Mtext ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϠM-text ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê
-    ¤¤¡£      */
+    ¥·¥ó¥Ü¥ë @c Mtext ¤Ï <tt>"mtext"</tt>
+    ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä´ÉÍý¥­¡¼¤Ç¤¢¤ë¡£¥­¡¼¤¬ @c Mtext 
+    ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϠM-text ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£      */
 
 MSymbol Mtext;
 
@@ -791,8 +936,7 @@ MSymbol Mtext;
 /***ja
     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤ë.
 
-    ´Ø¿ô mplist () ¤ÏŤµ 0 ¤Î¿·¤·¤¯ºî¤é¤ì¤¿¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥ª¥Ö¥¸¥§¥¯
-    ¥È¤òÊÖ¤¹¡£
+    ´Ø¿ô mplist () ¤ÏŤµ 0 ¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤ò¿·¤·¤¯ºî¤Ã¤ÆÊÖ¤¹¡£
 
     @returns
     ¤³¤Î´Ø¿ô¤Ï¿·¤·¤¯ºî¤é¤ì¤¿¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹¡£
@@ -825,8 +969,8 @@ mplist ()
 /***ja
     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò¥³¥Ô¡¼¤¹¤ë.
 
-    ´Ø¿ô mplist_copy () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò¥³¥Ô¡¼¤¹¤ë¡£¥³¥Ô¡¼¤Î¤¹¤Ù¤Æ¤Î
-    Ãͤϥ³¥Ô¡¼¸µ $PLIST ¤ÎÃͤÈƱ¤¸¤Ç¤¢¤ë¡£
+    ´Ø¿ô mplist_copy () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST 
+    ¤ò¥³¥Ô¡¼¤¹¤ë¡£¥³¥Ô¡¼¤Î¤¹¤Ù¤Æ¤ÎÃͤϥ³¥Ô¡¼¸µ $PLIST ¤ÎÃͤÈƱ¤¸¤Ç¤¢¤ë¡£
 
     @return
     ¤³¤Î´Ø¿ô¤Ï¿·¤·¤¯ºî¤é¤ì¤¿¡¢$PLIST ¤Î¥³¥Ô¡¼¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤òÊÖ¤¹¡£    
@@ -867,19 +1011,19 @@ mplist_copy (MPlist *plist)
 /***ja
     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃæ¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÀßÄꤹ¤ë.
 
-    ´Ø¿ô mplist_put () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò»Ï¤á¤«¤éõ¤·¤Æ¡¢¥­¡¼
-    ¤¬ $KEY ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤ÎÃͤò $VALUE ¤Ë
-    Êѹ¹¤¹¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¥­¡¼¤¬ $KEY ¤ÇÃͤ¬ $VALUE ¤Ç¤¢¤ë¿·¤·¤¤
-    ¥×¥í¥Ñ¥Æ¥£¤¬$PLIST ¤ÎËöÈø¤ËÄɲ䵤ì¤ë¡£$KEY ¤È $VAL ¤ËÂФ¹¤ëÀ©¸Â¤Ë
-    ¤Ä¤¤¤Æ¤Ï¡¢mplist_add () ¤ÎÀâÌÀ¤ò»²¾È¡£
+    ´Ø¿ô mplist_put () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò»Ï¤á¤«¤éõ¤·¤Æ¡¢¥­¡¼¤¬
+    $KEY ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤ÎÃͤò $VALUE 
+    ¤ËÊѹ¹¤¹¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¥­¡¼¤¬ $KEY ¤ÇÃͤ¬ $VALUE 
+    ¤Ç¤¢¤ë¿·¤·¤¤¥×¥í¥Ñ¥Æ¥£¤¬ $PLIST ¤ÎËöÈø¤ËÄɲ䵤ì¤ë¡£$KEY ¤È $VAL
+    ¤ËÂФ¹¤ëÀ©¸Â¤Ë¤Ä¤¤¤Æ¤Ï¡¢mplist_add () ¤ÎÀâÌÀ¤ò»²¾È¡£
 
-    $KEY ¤¬´ÉÍý¥­¡¼¤Ê¤é¤Ð¡¢$VAL ¤Ï´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
-    ¤³¤Î¾ì¹ç¡¢¸Å¤¤Ãͤλ²¾È¿ô¤Ï @c NULL ¤Ç¤Ê¤±¤ì¤Ð 1 ¸º¤é¤µ¤ì¡¢$VAL ¤Î
-    »²¾È¿ô¤Ï 1 Áý¤ä¤µ¤ì¤ë¡£
+    $KEY ¤¬´ÉÍý¥­¡¼¤Ê¤é¤Ð¡¢
+    $VAL ¤Ï´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤³¤Î¾ì¹ç¡¢¸Å¤¤Ãͤλ²¾È¿ô¤Ï 
+    @c NULL ¤Ç¤Ê¤±¤ì¤Ð 1 ¸º¤é¤µ¤ì¡¢$VAL ¤Î»²¾È¿ô¤Ï 1 Áý¤ä¤µ¤ì¤ë¡£
 
     @return 
-     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mplist_put () ¤ÏÊѹ¹¤µ¤ì¤¿¤«Äɲ䵤줿Í×ÁǤ«¤é»Ï
-    ¤Þ¤ë $PLIST ¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£   */
+    ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mplist_put () ¤ÏÊѹ¹¤µ¤ì¤¿¤«Äɲ䵤줿Í×ÁǤ«¤é»Ï¤Þ¤ë
+    $PLIST ¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£   */
 
 MPlist *
 mplist_put (MPlist *plist, MSymbol key, void *val)
@@ -891,7 +1035,8 @@ mplist_put (MPlist *plist, MSymbol key, void *val)
     {
       if (! MPLIST_TAIL_P (plist))
        M17N_OBJECT_UNREF (MPLIST_VAL (plist));
-      M17N_OBJECT_REF (val);
+      if (val)
+       M17N_OBJECT_REF (val);
     }
   MPLIST_SET (plist, key, val);
   return plist;
@@ -915,13 +1060,13 @@ mplist_put (MPlist *plist, MSymbol key, void *val)
 /***ja
     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃæ¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë.
 
-    ´Ø¿ô mplist_get () ¤Ï¡¢¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò»Ï¤á¤«¤éõ¤·¤Æ¡¢
-    ¥­¡¼¤¬ $KEY ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤ÎÃͤؤΥݥ¤
-    ¥ó¥¿¤ò <tt>(void *)</tt> ·¿¤ÇÊÖ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£
+    ´Ø¿ô mplist_get () ¤Ï¡¢¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò»Ï¤á¤«¤éõ¤·¤Æ¡¢¥­¡¼¤¬
+    $KEY ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤ÎÃͤؤΥݥ¤¥ó¥¿¤ò
+    <tt>(void *)</tt> ·¿¤ÇÊÖ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£
 
-    @c NULL ¤¬Ê֤俺ݤˤÏÆó¤Ä¤Î²ÄǽÀ­¤¬¤¢¤ë:¾åµ­¤Î¤è¤¦¤Ë¥×¥í¥Ñ¥Æ¥£¤¬
-    ¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¤È¡¢¥×¥í¥Ñ¥Æ¥£¤¬¸«¤Ä¤«¤ê¡¢¤½¤ÎÃͤ¬ @c NULL ¤Ç
-    ¤¢¤ë¾ì¹ç¤Ç¤¢¤ë¡£¤³¤ì¤é¤ò¶èÊ̤¹¤ëɬÍפ¬¤¢¤ë¾ì¹ç¤Ë¤Ï´Ø¿ô 
+    @c NULL ¤¬Ê֤俺ݤˤÏÆó¤Ä¤Î²ÄǽÀ­¤¬¤¢¤ë: 
+    ¾åµ­¤Î¤è¤¦¤Ë¥×¥í¥Ñ¥Æ¥£¤¬¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¤È¡¢¥×¥í¥Ñ¥Æ¥£¤¬¸«¤Ä¤«¤ê¡¢¤½¤ÎÃͤ¬
+    @c NULL ¤Ç¤¢¤ë¾ì¹ç¤Ç¤¢¤ë¡£¤³¤ì¤é¤ò¶èÊ̤¹¤ëɬÍפ¬¤¢¤ë¾ì¹ç¤Ë¤Ï´Ø¿ô 
     mplist_find_by_key () ¤ò»È¤¦¤³¤È¡£  */
 
 /***
@@ -941,8 +1086,8 @@ mplist_get (MPlist *plist, MSymbol key)
     @brief Add a property at the end of a property list.
 
     The mplist_add () function appends at the end of property list
-     $PLIST a property whose key is $KEY and value is $VAL.  $KEY can
-     be any symbol other than @c Mnil.
+    $PLIST a property whose key is $KEY and value is $VAL.  $KEY can
+    be any symbol other than @c Mnil.
 
     If $KEY is a managing key, $VAL must be a managed object.  In this
     case, the reference count of $VAL is incremented by one.
@@ -955,14 +1100,13 @@ mplist_get (MPlist *plist, MSymbol key)
     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈËöÈø¤Ë¥×¥í¥Ñ¥Æ¥£¤òÄɲ乤ë.
 
     ´Ø¿ô mplist_add () ¤Ï¡¢¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ÎËöÈø¤Ë¥­¡¼¤¬ $KEY 
-    ¤ÇÃͤ¬ $VAL ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤òÄɲ乤롣$KEY ¤Ï¡¢@c Mnil °Ê³°¤ÎǤ
-    °Õ¤Î¥·¥ó¥Ü¥ë¤Ç¤è¤¤¡£
+    ¤ÇÃͤ¬ $VAL ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤òÄɲ乤롣$KEY ¤Ï¡¢@c Mnil °Ê³°¤ÎǤ°Õ¤Î¥·¥ó¥Ü¥ë¤Ç¤è¤¤¡£
 
-    $KEY ¤¬´ÉÍý¥­¡¼¤Ê¤é¤Ð¡¢$VAL ¤Ï´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
-    ¤³¤Î¾ì¹ç¡¢$VAL ¤Î»²¾È¿ô¤Ï 1 Áý¤ä¤µ¤ì¤ë¡£
+    $KEY ¤¬´ÉÍý¥­¡¼¤Ê¤é¤Ð¡¢$VAL ¤Ï´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤³¤Î¾ì¹ç¡¢
+    $VAL ¤Î»²¾È¿ô¤Ï 1 Áý¤ä¤µ¤ì¤ë¡£
 
     @return
-     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mplist_add () ¤ÏÄɲ䵤줿Í×ÁǤ«¤é»Ï¤Þ¤ë $PLIST 
+    ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mplist_add () ¤ÏÄɲ䵤줿Í×ÁǤ«¤é»Ï¤Þ¤ë $PLIST 
     ¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£  */
 
 MPlist *
@@ -971,7 +1115,7 @@ mplist_add (MPlist *plist, MSymbol key, void *val)
   if (key == Mnil)
     MERROR (MERROR_PLIST, NULL);
   MPLIST_FIND (plist, Mnil);
-  if (key->managing_key)
+  if (val && key->managing_key)
     M17N_OBJECT_REF (val);
   MPLIST_KEY (plist) = key;
   MPLIST_VAL (plist) = val;
@@ -982,10 +1126,10 @@ mplist_add (MPlist *plist, MSymbol key, void *val)
 /*=*/
 
 /***en
-    @brief Push a property to a property list.
+    @brief Add a property at the beginning of a property list.
 
-    The mplist_push () function pushes at the top of property list
-     $PLIST a property whose key is $KEY and value is $VAL.
+    The mplist_push () function inserts at the beginning of property
+    list $PLIST a property whose key is $KEY and value is $VAL.
 
     If $KEY is a managing key, $VAL must be a managed object.  In this
     case, the reference count of $VAL is incremented by one.
@@ -994,17 +1138,17 @@ mplist_add (MPlist *plist, MSymbol key, void *val)
     If the operation was successful, this function returns $PLIST.
     Otherwise, it returns @c NULL.  */
 /***ja
-    @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò¥×¥Ã¥·¥å¤¹¤ë.
+    @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ÎÀèƬ¤Ë¥×¥í¥Ñ¥Æ¥£¤òÁÞÆþ¤¹¤ë.
 
-    ´Ø¿ô mplist_push () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤Î¾å¤Ë¤Ë¥­¡¼¤¬ $KEY 
-    ¤ÇÃͤ¬ $VAL ¤Ç¤¢¤ë¥ª¥Ö¥¸¥§¥¯¥È¤ò¥×¥Ã¥·¥å¤¹¤ë¡£
+    ´Ø¿ô mplist_push () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ÎÀèƬ¤Ë¥­¡¼¤¬ $KEY 
+    ¤ÇÃͤ¬ $VAL ¤Ç¤¢¤ë¥ª¥Ö¥¸¥§¥¯¥È¤òÁÞÆþ¤¹¤ë¡£
 
-    $KEY ¤¬´ÉÍý¥­¡¼¤Ê¤é¤Ð¡¢$VAL ¤Ï´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
-    ¤³¤Î¾ì¹ç¡¢$VAL ¤Î»²¾È¿ô¤Ï 1 Áý¤ä¤µ¤ì¤ë¡£
+    $KEY ¤¬´ÉÍý¥­¡¼¤Ê¤é¤Ð¡¢$VAL ¤Ï´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤³¤Î¾ì¹ç¡¢
+    $VAL ¤Î»²¾È¿ô¤Ï 1 Áý¤ä¤µ¤ì¤ë¡£
 
     @return
-    ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¤³¤Î´Ø¿ô¤Ï $PLIST ¤òÊÖ¤·¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð@c NULL ¤ò
-    ÊÖ¤¹¡£  */
+    ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¤³¤Î´Ø¿ô¤Ï $PLIST ¤òÊÖ¤·¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð@c NULL 
+    ¤òÊÖ¤¹¡£  */
 
 MPlist *
 mplist_push (MPlist *plist, MSymbol key, void *val)
@@ -1016,9 +1160,9 @@ mplist_push (MPlist *plist, MSymbol key, void *val)
   MPLIST_NEW (pl);
   MPLIST_KEY (pl) = MPLIST_KEY (plist);
   MPLIST_VAL (pl) = MPLIST_VAL (plist);
-  pl->next = plist->next;
+  MPLIST_NEXT (pl) = MPLIST_NEXT (plist);
   plist->next = pl;
-  if (key->managing_key)
+  if (val && key->managing_key)
     M17N_OBJECT_REF (val);
   MPLIST_KEY (plist) = key;
   MPLIST_VAL (plist) = val;
@@ -1028,25 +1172,25 @@ mplist_push (MPlist *plist, MSymbol key, void *val)
 /*=*/
 
 /***en
-    @brief Pop a property from a property list.
+    @brief Remove a property at the beginning of a property list.
 
-    The mplist_pop () function pops the topmost property from property
-    list $PLIST.  As a result, the key and value of $PLIST becomes
-    those of the next of $PLIST.
+    The mplist_pop () function removes a property at the beginning of
+    property list $PLIST.  As a result, the second key and value of
+    the original $PLIST become the first of those of the new $PLIST.
 
     @return
     If the operation was successful, this function return the value of
     the just popped property.  Otherwise, it returns @c NULL.  */
 /***ja
-    @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò¥Ý¥Ã¥×¤¹¤ë.
+    @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ÎÀèƬ¤«¤é¥×¥í¥Ñ¥Æ¥£¤òºï½ü¤¹¤ë.
 
-    ´Ø¿ô mplist_pop () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤«¤éºÇ¾å°Ì¤Î¥×¥í¥Ñ¥Æ¥£
-    ¤ò¥Ý¥Ã¥×¤¹¤ë¡£·ë²Ì¤È¤·¤Æ $PLIST ¤Î¥­¡¼¤ÈÃͤϠ$PLIST ¤Î¼¡¤Î¥­¡¼¤ÈÃÍ
-    ¤Ë¤Ê¤ë¡£
+    ´Ø¿ô mplist_pop () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST 
+    ¤ÎÀèƬ¤Î¥×¥í¥Ñ¥Æ¥£¤òºï½ü¤¹¤ë¡£·ë²Ì¤È¤·¤Æ¡¢¸µ¤Î $PLIST ¤Î2ÈÖÌܤΥ­¡¼¤ÈÃͤ¬¡¢¿·¤·¤¤ 
+    $PLIST ¤ÎÀèƬ¤Î¥­¡¼¤ÈÃͤˤʤ롣
 
     @return 
-    ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Ý¥Ã¥×¤µ¤ì¤¿¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹¡£¤½¤¦
-    ¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£  */
+    ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ïºï½ü¤µ¤ì¤¿¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð
+    @c NULL ¤òÊÖ¤¹¡£  */
 
 void *
 mplist_pop (MPlist *plist)
@@ -1057,14 +1201,14 @@ mplist_pop (MPlist *plist)
   if (MPLIST_TAIL_P (plist))
     return NULL;
   val = MPLIST_VAL (plist);
-  next = plist->next;
+  next = MPLIST_NEXT (plist);
   MPLIST_KEY (plist) = MPLIST_KEY (next);
   MPLIST_VAL (plist) = MPLIST_VAL (next);
   if (MPLIST_KEY (plist) != Mnil
       && MPLIST_KEY (plist)->managing_key
       && MPLIST_VAL (plist))
     M17N_OBJECT_REF (MPLIST_VAL (plist));
-  plist->next = next->next;
+  MPLIST_NEXT (plist) = MPLIST_NEXT (next);
   if (plist->next)
     M17N_OBJECT_REF (plist->next);
   M17N_OBJECT_UNREF (next);
@@ -1083,15 +1227,14 @@ mplist_pop (MPlist *plist)
     If $KEY is @c Mnil, it returns a sublist of $PLIST whose
     first element is the last one of $PLIST.  */
 /***ja
-    @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃ椫¤é»ØÄê¤Î¥­¡¼¤ò»ý¤Ä¥ª¥Ö¥¸¥§¥¯¥È¤òõ¤¹.
+    @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃ椫¤é»ØÄê¤Î¥­¡¼¤ò»ý¤Ä¥×¥í¥Ñ¥Æ¥£¤òõ¤¹.
 
-    ´Ø¿ô mplist_find_by_key () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò»Ï¤á¤«¤éõ
-    ¤·¤Æ¡¢¥­¡¼¤¬ $KEY ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤Î¥×¥í
-    ¥Ñ¥Æ¥£¤«¤é»Ï¤Þ¤ë $PLIST ¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð@c NULL 
-    ¤òÊÖ¤¹¡£
+    ´Ø¿ô mplist_find_by_key () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST 
+    ¤ò»Ï¤á¤«¤éõ ¤·¤Æ¡¢¥­¡¼¤¬ $KEY 
+    ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤«¤é»Ï¤Þ¤ë
+    $PLIST ¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£
 
-    $KEY ¤¬ @c Mnil ¤Ê¤é¤Ð¡¢$PLIST ¤ÎºÇ¸å¤ÎÍ×ÁǤ«¤é»Ï¤Þ¤ëÉôʬ¥ê¥¹¥È¤ò
-    ÊÖ¤¹¡£  */
+    $KEY ¤¬ @c Mnil ¤Ê¤é¤Ð¡¢$PLIST ¤ÎºÇ¸å¤ÎÍ×ÁǤ«¤é»Ï¤Þ¤ëÉôʬ¥ê¥¹¥È¤òÊÖ¤¹¡£  */
 
 MPlist *
 mplist_find_by_key (MPlist *plist, MSymbol key)
@@ -1111,12 +1254,12 @@ mplist_find_by_key (MPlist *plist, MSymbol key)
     property is found, a sublist of $PLIST whose first element is the
     found one is returned.  Otherwise, @c NULL is returned.  */
 /***ja
-    @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃ椫¤é»ØÄê¤ÎÃͤò»ý¤Ä¥ª¥Ö¥¸¥§¥¯¥È¤òõ¤¹.
+    @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃ椫¤é»ØÄê¤ÎÃͤò»ý¤Ä¥×¥í¥Ñ¥Æ¥£¤òõ¤¹.
 
-    ´Ø¿ô mplist_find_by_value () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò»Ï¤á¤«¤é
-    Ãµ¤·¤Æ¡¢Ãͤ¬ $VAL ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤Î¥×¥í
-    ¥Ñ¥Æ¥£¤«¤é»Ï¤Þ¤ë $PLIST ¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð@c NULL 
-    ¤òÊÖ¤¹¡£ */
+    ´Ø¿ô mplist_find_by_value () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST 
+    ¤ò»Ï¤á¤«¤éõ¤·¤Æ¡¢Ãͤ¬ $VAL 
+    ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤«¤é»Ï¤Þ¤ë
+    $PLIST ¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£ */
 
 MPlist *
 mplist_find_by_value (MPlist *plist, void *val)
@@ -1140,9 +1283,9 @@ mplist_find_by_value (MPlist *plist, void *val)
 /***ja
     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Î¼¡¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹.
 
-    ´Ø¿ô mplist_next () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤Î£²ÈÖÌÜ
-    ¤ÎÍ×ÁǤ«¤é»Ï¤Þ¤ëÉôʬ¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£$PLIST ¤ÎŤµ¤¬ 0 ¤Ê
-    ¤é¤Ð @c NULL ¤òÊÖ¤¹¡£  */
+    ´Ø¿ô mplist_next () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤Î 2 
+    ÈÖÌܤÎÍ×ÁǤ«¤é»Ï¤Þ¤ëÉôʬ¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£$PLIST ¤ÎŤµ¤¬ 0 
+    ¤Ê¤é¤Ð @c NULL ¤òÊÖ¤¹¡£  */
 
 MPlist *
 mplist_next (MPlist *plist)
@@ -1155,7 +1298,7 @@ mplist_next (MPlist *plist)
 /***en
     @brief Set the first property in a property list.
 
-    The mplist_set () function sets the key and value of the first
+    The mplist_set () function sets the key and the value of the first
     property in property list $PLIST to $KEY and $VALUE, respectively.
     See the documentation of mplist_add () for the restriction on $KEY
     and $VAL.
@@ -1166,13 +1309,12 @@ mplist_next (MPlist *plist)
 /***ja
     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤òÀßÄꤹ¤ë.
 
-    ´Ø¿ô mplist_set () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤Î
-    ¥­¡¼¤ÈÃͤò¤½¤ì¤¾¤ì $KEY ¤È $VALUE ¤ËÀßÄꤹ¤ë¡£$KEY ¤È $VAL ¤ËÂФ¹
-    ¤ëÀ©¸Â¤Ë¤Ä¤¤¤Æ¤Ï¡¢mplist_add () ¤ÎÀâÌÀ¤ò»²¾È¡£
+    ´Ø¿ô mplist_set () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST 
+    ¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤ÈÃͤò¤½¤ì¤¾¤ì $KEY ¤È $VALUE ¤ËÀßÄꤹ¤ë¡£
+    $KEY ¤È $VAL ¤ËÂФ¹¤ëÀ©¸Â¤Ë¤Ä¤¤¤Æ¤Ï¡¢mplist_add () ¤ÎÀâÌÀ¤ò»²¾È¡£
 
     @return
-    ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mplist_set () ¤Ï $PLIST ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð
-    @c NULL ¤òÊÖ¤¹¡£  */
+    ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mplist_set () ¤Ï $PLIST ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£  */
 
 MPlist *
 mplist_set (MPlist *plist, MSymbol key, void * val)
@@ -1184,19 +1326,18 @@ mplist_set (MPlist *plist, MSymbol key, void * val)
          key = MPLIST_KEY (plist);
          M17N_OBJECT_UNREF (MPLIST_NEXT (plist));
          MPLIST_KEY (plist) = Mnil;
-         if (key->managing_key && MPLIST_VAL (plist))
+         if (key->managing_key)
            M17N_OBJECT_UNREF (MPLIST_VAL (plist));
          plist->next = NULL;
        }
     }
   else
     {
+      if (val && key->managing_key)
+       M17N_OBJECT_REF (val);
       if (! MPLIST_TAIL_P (plist)
-         && MPLIST_KEY (plist)->managing_key
-         && MPLIST_VAL (plist))
+         && MPLIST_KEY (plist)->managing_key)
        M17N_OBJECT_UNREF (MPLIST_VAL (plist));
-      if (key->managing_key)
-       M17N_OBJECT_REF (val);
       MPLIST_SET (plist, key, val);
     }
   return plist;
@@ -1212,8 +1353,7 @@ mplist_set (MPlist *plist, MSymbol key, void * val)
 /***ja
     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ÎŤµ¤òÊÖ¤¹.
 
-    ´Ø¿ô mplist_length () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST Ãæ¤Î¥×¥í¥Ñ¥Æ¥£¤Î¿ô
-    ¤òÊÖ¤¹¡£  */
+    ´Ø¿ô mplist_length () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST Ãæ¤Î¥×¥í¥Ñ¥Æ¥£¤Î¿ô¤òÊÖ¤¹¡£  */
 
 int
 mplist_length (MPlist *plist)
@@ -1235,9 +1375,9 @@ mplist_length (MPlist *plist)
 /***ja
     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃæ¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤òÊÖ¤¹.
 
-    ´Ø¿ô mplist_key () ¤Ï¡¢¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST Ãæ¤ÎºÇ
-    ½é¤Î¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤òÊÖ¤¹¡£$PLIST ¤ÎŤµ¤¬ 0 ¤Ê¤é¤Ð¡¢ @c Mnil ¤ò
-    ÊÖ¤¹¡£  */
+    ´Ø¿ô mplist_key () ¤Ï¡¢¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST 
+    Ãæ¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤òÊÖ¤¹¡£$PLIST ¤ÎŤµ¤¬ 0 ¤Ê¤é¤Ð¡¢ @c Mnil 
+    ¤òÊÖ¤¹¡£  */
 
 MSymbol
 mplist_key (MPlist *plist)
@@ -1254,11 +1394,10 @@ mplist_key (MPlist *plist)
     property in property list  $PLIST.  If the length of $PLIST
     is zero, it returns @c NULL.  */
 /***ja
-    @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃæ¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤òÊÖ¤¹.
+    @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃæ¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹.
 
-    ´Ø¿ô mplist_value () ¤Ï¡¢¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST Ãæ¤Î
-    ºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹¡£$PLIST ¤ÎŤµ¤¬ 0 ¤Ê¤é¤Ð¡¢ @c Mnil ¤ò
-    ÊÖ¤¹¡£  */
+    ´Ø¿ô mplist_value () ¤Ï¡¢¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST Ãæ¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹¡£
+    $PLIST ¤ÎŤµ¤¬ 0 ¤Ê¤é¤Ð¡¢ @c Mnil ¤òÊÖ¤¹¡£  */
 
 void *
 mplist_value (MPlist *plist)
@@ -1288,15 +1427,14 @@ mplist_value (MPlist *plist)
     Each alternatives of @c ELEMENT is assigned one of these keys: @c
     Msymbol, @c Minteger, @c Mtext, @c Mplist
 
-    In an ascii-character-sequence, a backslush (\) is used as the escape
+    In an ascii-character-sequence, a backslash (\) is used as the escape
     character, which means that, for instance, <tt>"abc\ def"</tt>
     produces a symbol whose name is of length seven with the fourth
     character being a space.  */
 /***ja
     @brief M-text ¤ò¥Ç¥·¥ê¥¢¥é¥¤¥º¤·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤òºî¤ë.
 
-    ´Ø¿ô mplist_deserialize () ¤Ï M-text $MT ¤ò²òÀϤ·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹
-    ¥È¤òÊÖ¤¹¡£
+    ´Ø¿ô mplist_deserialize () ¤Ï M-text $MT ¤ò²òÀϤ·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤òÊÖ¤¹¡£
 
     $MT ¤Î¥·¥ó¥¿¥Ã¥¯¥¹¤Ï°Ê²¼¤ÎÄ̤ꡣ
 
@@ -1314,19 +1452,27 @@ mplist_value (MPlist *plist)
     @c ELEMENT ¤Î³ÆÁªÂò»è¤Ï¥­¡¼¡§@c Msymbol, @c Minteger, @c Mtext,
     @c Mplist ¤Î¤¤¤º¤ì¤«¤ò³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¡£
 
-    ¥¢¥¹¥­¡¼Ê¸»úÎóÆâ¤Ç¤Ï¡¢¥Ð¥Ã¥¯¥¹¥é¥Ã¥·¥å (\) ¤¬¥¨¥¹¥±¡¼¥×ʸ»ú¤È¤·¤Æ
-    ÍѤ¤¤é¤ì¤ë¡£¤¿¤È¤¨¤Ð <tt>"abc\ def"</tt> ¤Ï£´Ê¸»úÌܤ¬¶õÇòʸ»ú¤Ç¤¢
-    ¤êŤµ¤¬£·¤Ç¤¢¤ë»ý¤Ä̾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤òÀ¸À®¤¹¤ë¡£   */
+    ¥¢¥¹¥­¡¼Ê¸»úÎóÆâ¤Ç¤Ï¡¢¥Ð¥Ã¥¯¥¹¥é¥Ã¥·¥å (\) ¤¬¥¨¥¹¥±¡¼¥×ʸ»ú¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£¤¿¤È¤¨¤Ð
+    <tt>"abc\ def"</tt> ¤Ï 4 Ê¸»úÌܤ¬¶õÇòʸ»ú¤Ç¤¢¤êŤµ¤¬ 7 
+    ¤Ç¤¢¤ë»ý¤Ä̾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤òÀ¸À®¤¹¤ë¡£   */
 
 MPlist *
 mplist_deserialize (MText *mt)
 {
+  MPlist *plist;
+  MText *tmp = NULL;
+
   if (mt->format > MTEXT_FORMAT_UTF_8)
     {
-      if (mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8) < 0)
-       MERROR (MERROR_PLIST, NULL);
+      if (MTEXT_READ_ONLY_P (mt))
+       mt = tmp = mtext_cpy (mtext (), mt);
+      else
+       mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
     }
-  return mplist__from_string (MTEXT_DATA (mt), mtext_nbytes (mt));
+  plist = mplist__from_string (MTEXT_DATA (mt), mtext_nbytes (mt));
+  if (tmp)
+    M17N_OBJECT_UNREF (tmp);
+  return plist;
 }
 
 /*** @}  */
@@ -1347,9 +1493,8 @@ mplist_deserialize (MText *mt)
 /***ja
     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò¥À¥ó¥×¤¹¤ë.
 
-    ´Ø¿ô mdebug_dump_plist () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È @PLIST ¤ò stderr ¤Ë¿Í
-    ´Ö¤Ë²ÄÆɤʠ·Á¤Ç°õºþ¤¹¤ë¡£ $UNDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ
-    ¤ë¡£
+    ´Ø¿ô mdebug_dump_plist () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò stderr 
+    ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£ $INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
 
     @return
     ¤³¤Î´Ø¿ô¤Ï $PLIST ¤òÊÖ¤¹¡£  */