Fix typo in comments.
[m17n/m17n-lib.git] / src / plist.c
1 /* plist.c -- plist module.
2    Copyright (C) 2003, 2004
3      National Institute of Advanced Industrial Science and Technology (AIST)
4      Registration Number H15PRO112
5
6    This file is part of the m17n library.
7
8    The m17n library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public License
10    as published by the Free Software Foundation; either version 2.1 of
11    the License, or (at your option) any later version.
12
13    The m17n library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
17
18    You should have received a copy of the GNU Lesser General Public
19    License along with the m17n library; if not, write to the Free
20    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21    02111-1307, USA.  */
22
23 /***en
24     @addtogroup m17nPlist
25
26     @brief Property List objects and API for them.
27
28     A @e property @e list (or @e plist for short) is a list of zero or
29     more properties.  A property consists of a @e key and a @e value,
30     where key is a symbol and value is anything that can be cast to
31     <tt>(void *)</tt>.
32
33     If the key of a property is a @e managing @e key, its @e value is
34     a @e managed @e object.  A property list itself is a managed
35     objects.  */
36 /***ja
37     @addtogroup m17nPlist
38
39     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤È¤½¤ì¤Ë´Ø¤¹¤ë API.
40
41     @e ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È (¤Þ¤¿¤Ï @e plist) ¤Ï 0 ¸Ä°Ê¾å¤Î¥×¥í¥Ñ¥Æ¥£¤Î¥ê
42     ¥¹¥È¤Ç¤¢¤ë¡£¥×¥í¥Ñ¥Æ¥£¤Ï @e ¥­¡¼ ¤È @e ÃÍ ¤«¤é¤Ê¤ë¡£¥­¡¼¤Ï¥·¥ó¥Ü¥ë
43     ¤Ç¤¢¤ê¡¢ÃͤϠ<tt>(void *)</tt> ¤Ë¥­¥ã¥¹¥È¤Ç¤­¤ë¤â¤Î¤Ê¤é¤Ð²¿¤Ç¤âÎÉ
44     ¤¤¡£
45
46     ¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤¬ @e ´ÉÍý¥­¡¼ ¤Ê¤é¤Ð¡¢¤½¤Î @e ÃÍ ¤Ï@e ´ÉÍý²¼
47     ¥ª¥Ö¥¸¥§¥¯¥È ¤Ç¤¢¤ë¡£¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¼«ÂΤâ´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢
48     ¤ë¡£  */
49
50 /*=*/
51
52 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
53 /*** @addtogroup m17nInternal
54      @{ */
55
56 #include <stdio.h>
57 #include <string.h>
58
59 #include "config.h"
60 #include "m17n.h"
61 #include "m17n-misc.h"
62 #include "internal.h"
63 #include "character.h"
64 #include "mtext.h"
65 #include "symbol.h"
66 #include "plist.h"
67
68 static M17NObjectArray plist_table;
69
70 /** Set PLIST to a newly allocated plist object.  */
71
72 #define MPLIST_NEW(plist)                               \
73   do {                                                  \
74     M17N_OBJECT (plist, free_plist, MERROR_PLIST);      \
75     M17N_OBJECT_REGISTER (plist_table, plist);          \
76   } while (0)
77
78
79 /** Set the element of PLIST to KEY and VAL.  If PLIST is an anchor,
80     append a new anchor.  */
81
82 #define MPLIST_SET(plist, key, val)     \
83   do {                                  \
84     MPLIST_KEY (plist) = (key);         \
85     MPLIST_VAL (plist) = (val);         \
86     if (! (plist)->next)                \
87       MPLIST_NEW ((plist)->next);       \
88   } while (0)
89
90
91 /** Set the element of PLIST to KEY and VAL.  PLIST must be an anchor.
92     Append a new anchor and set PLIST to that anchor.  */
93
94 #define MPLIST_SET_ADVANCE(plist, key, val)     \
95   do {                                          \
96     MPLIST_KEY (plist) = (key);                 \
97     MPLIST_VAL (plist) = (val);                 \
98     MPLIST_NEW ((plist)->next);                 \
99     plist = (plist)->next;                      \
100   } while (0)
101
102
103 static void
104 free_plist (void *object)
105 {
106   MPlist *plist = (MPlist *) object;
107
108   do {
109     MPlist *next = plist->next;
110
111     if (MPLIST_KEY (plist) != Mnil && MPLIST_KEY (plist)->managing_key)
112       M17N_OBJECT_UNREF (MPLIST_VAL (plist));
113     M17N_OBJECT_UNREGISTER (plist_table, plist);
114     free (plist);
115     plist = next;
116   } while (plist && plist->control.ref_count == 1);
117   M17N_OBJECT_UNREF (plist);
118 }
119
120 \f
121
122 /* Load a plist from a string.  */
123
124 #define READ_CHUNK 0x10000
125
126 typedef struct
127 {
128   /* File pointer if the stream is associated with a file.  Otherwise
129      NULL.  */
130   FILE *fp;
131   int eof;
132   unsigned char buffer[READ_CHUNK];
133   unsigned char *p, *pend;
134 } MStream;
135
136 static int
137 get_byte (MStream *st)
138 {
139   int n;
140
141   if (! st->fp || st->eof)
142     return EOF;
143   n = fread (st->buffer, 1, READ_CHUNK, st->fp);
144   if (n <= 0)
145     {
146       st->eof = 1;
147       return EOF;
148     }
149   st->p = st->buffer + 1;
150   st->pend = st->buffer + n;
151   return st->buffer[0];
152 }
153
154 #define GETC(st)        \
155   ((st)->p < (st)->pend ? *(st)->p++ : get_byte (st))
156
157
158 #define UNGETC(c, st)   \
159   (*--(st)->p = (c))
160
161 /** Mapping table for reading a number.  Hexadecimal chars
162     (0..9,A..F,a..F) are mapped to the corresponding numbers.
163     Apostrophe (code 39) is mapped to 254.  All the other bytes are
164     mapped to 255.  */
165 unsigned char hex_mnemonic[256];
166
167 /** Mapping table for escaped characters.  Mnemonic characters (e, b,
168     f, n, r, or t) that follows '\' are mapped to the corresponding
169     character code.  All the other bytes are mapped to themselves.  */
170 unsigned char escape_mnemonic[256];
171
172
173 /** Read an integer from the stream ST.  It is assumed that we have
174     already read one character C.  */
175
176 static int
177 read_decimal (MStream *st, int c)
178 {
179   int num = 0;
180
181   while (c >= '0' && c <= '9')
182     {
183       num = (num * 10) + (c - '0');
184       c = GETC (st);
185     }
186
187   if (c != EOF)
188     UNGETC (c, st);
189   return num;
190 }
191
192 /** Read an unsigned from the stream ST.  */
193
194 static unsigned
195 read_hexadesimal (MStream *st)
196 {
197   int c;
198   unsigned num = 0, n;
199
200   while ((c = GETC (st)) != EOF
201          && (n = hex_mnemonic[c]) < 16)
202     num = (num << 4) | n;
203   if (c != EOF)
204     UNGETC (c, st);
205   return num;
206 }
207
208
209 /** Read an M-text element from ST, and add it to LIST.  Return a list
210     for the next element.  */
211
212 static MPlist *
213 read_mtext_element (MPlist *plist, MStream *st)
214 {
215   unsigned char buffer[1024];
216   int bufsize = 1024;
217   unsigned char *buf = buffer;
218   int c, i;
219
220   i = 0;
221   while ((c = GETC (st)) != EOF && c != '"')
222     {
223       if (i + MAX_UTF8_CHAR_BYTES >= bufsize)
224         {
225           bufsize *= 2;
226           if (buf == buffer)
227             {
228               MTABLE_MALLOC (buf, bufsize, MERROR_PLIST);
229               memcpy (buf, buffer, i);
230             }
231           else
232             MTABLE_REALLOC (buf, bufsize, MERROR_PLIST);
233         }
234
235       if (c == '\\')
236         {
237           c = GETC (st);
238           if (c == EOF)
239             break;
240           if (c == 'x')
241             {
242               int next_c;
243
244               c = read_hexadesimal (st);
245               next_c = GETC (st);
246               if (next_c != ' ')
247                 UNGETC (next_c, st);
248             }
249           else
250             c = escape_mnemonic[c];
251         }
252
253       buf[i++] = c;
254     }
255
256   MPLIST_SET_ADVANCE (plist, Mtext,
257                       mtext__from_data (buf, i, MTEXT_FORMAT_UTF_8, 1));
258   if (buf != buffer)
259     free (buf);
260   return plist;
261 }
262
263 static int
264 read_character (MStream *st, int c)
265 {
266   unsigned char buf[MAX_UTF8_CHAR_BYTES + 1];
267   int len = CHAR_BYTES_BY_HEAD (c);
268   int i;
269
270   buf[0] = c;
271   for (i = 1; i < len; i++)
272     {
273       c = GETC (st);
274       if (c == EOF
275           || (c & 0xC0) != 0x80)
276         break;
277       buf[i] = c;
278     }
279   if (i == len)
280     c = STRING_CHAR_UTF8 (buf);
281   else
282     c = buf[0];
283   return c;
284 }
285
286
287 /** Read an integer element from ST, and add it to LIST.  Return a
288     list for the next element.  It is assumed that we have already
289     read the character C. */
290
291 static MPlist *
292 read_integer_element (MPlist *plist, MStream *st, int c)
293 {
294   int num;
295
296   if (c == '0' || c == '#')
297     {
298       c = GETC (st);
299       if (c == 'x')
300         num = read_hexadesimal (st);
301       else
302         num = read_decimal (st, c);
303     }
304   else if (c == '?')
305     {
306       c = GETC (st);
307       if (c == EOF)
308         num = 0;
309       else if (c != '\\')
310         {
311           if (c < 128 || ! CHAR_UNITS_BY_HEAD_UTF8 (c))
312             num = c;
313           else
314             num = read_character (st, c);
315         }
316       else
317         {
318           c = GETC (st);
319           if (c == EOF)
320             num = '\\';
321           else if (c < 128 || ! CHAR_UNITS_BY_HEAD_UTF8 (c))
322             num = escape_mnemonic[c];
323           else
324             num = read_character (st, c);
325         }
326     }
327   else if (c == '-')
328     num = - read_decimal (st, GETC (st));
329   else
330     num = read_decimal (st, c);
331
332   MPLIST_SET_ADVANCE (plist, Minteger, (void *) num);
333   return plist;
334 }
335
336 /** Read a symbol element from ST, and add it to LIST.  Return a list
337     for the next element.  */
338
339 static MPlist *
340 read_symbol_element (MPlist *plist, MStream *st)
341 {
342   unsigned char buffer[1024];
343   int bufsize = 1024;
344   unsigned char *buf = buffer;
345   int c, i;
346
347   i = 0;
348   while ((c = GETC (st)) != EOF
349          && c > ' '
350          && c != ')' && c != '(' && c != '"')
351     {
352       if (i >= bufsize)
353         {
354           bufsize *= 2;
355           if (buf == buffer)
356             {
357               MTABLE_MALLOC (buf, bufsize, MERROR_PLIST);
358               memcpy (buf, buffer, i);
359             }
360           else
361             MTABLE_REALLOC (buf, bufsize, MERROR_PLIST);
362         }
363       if (c == '\\')
364         {
365           c = GETC (st);
366           if (c == EOF)
367             break;
368           c = escape_mnemonic[c];
369         }
370       buf[i++] = c;
371     }
372
373   buf[i] = 0;
374   MPLIST_SET_ADVANCE (plist, Msymbol, msymbol ((char *) buf));
375   if (buf != buffer)
376     free (buf);
377   if (c > ' ')
378     UNGETC (c, st);
379   return plist;
380 }
381
382 /* Read an element of various type from stream ST, and add it to LIST.
383    Return a list for the next element.  The element type is decided by
384    the first token character found as below:
385         '(': plist
386         '"': mtext
387         '0'..'9', '-': integer
388         '?': integer representing character code
389         the other ASCII letters: symbol
390 */
391
392 static MPlist *
393 read_element (MPlist *plist, MStream *st)
394 {
395   int c;
396
397   /* Skip separators and comments.  */
398   while (1)
399     {
400       while ((c = GETC (st)) != EOF && c <= ' ');
401       if (c != ';')
402         break;
403       while ((c = GETC (st)) != EOF && c != '\n');
404       if (c == EOF)
405         break;
406     }
407
408   if (c == '(')
409     {
410       MPlist *pl, *p;
411
412       MPLIST_NEW (pl);
413       p = pl;
414       while ((p = read_element (p, st)));
415       MPLIST_SET_ADVANCE (plist, Mplist, pl);
416       return plist;
417     }
418   if (c == '"')
419     return read_mtext_element (plist, st);
420   if ((c >= '0' && c <= '9') || c == '-' || c == '?' || c == '#')
421     return read_integer_element (plist, st, c);
422   if (c == EOF || c == ')')
423     return NULL;
424   UNGETC (c, st);
425   return read_symbol_element (plist, st);
426 }
427
428 void
429 write_element (MText *mt, MPlist *plist)
430 {
431   if (MPLIST_SYMBOL_P (plist))
432     {
433       MSymbol sym = MPLIST_SYMBOL (plist);
434
435       if (sym == Mnil)
436         {
437           MTEXT_CAT_ASCII (mt, "nil");
438         }
439       else
440         {
441           char *name = MSYMBOL_NAME (sym);
442           char *buf = alloca (MSYMBOL_NAMELEN (sym) * 2 + 1), *p = buf;
443
444           while (*name)
445             {
446               if (*name <= ' ' || *name == '"' || *name == ')' || *name == ')')
447                 *p++ = '\\';
448               *p++ = *name++;
449             }
450           *p = '\0';
451           MTEXT_CAT_ASCII (mt, buf);
452         }
453     }
454   else if (MPLIST_INTEGER_P (plist))
455     {
456       int num = MPLIST_INTEGER (plist);
457       char buf[128];
458
459       sprintf (buf, "%d", num);
460       MTEXT_CAT_ASCII (mt, buf);
461     }
462   else if (MPLIST_PLIST_P (plist))
463     {
464       MPlist *pl;
465
466       plist = MPLIST_PLIST (plist);
467       mtext_cat_char (mt, '(');
468       MPLIST_DO (pl, plist)
469         {
470           if (pl != plist)
471             mtext_cat_char (mt, ' ');
472           write_element (mt, pl);
473         }
474       mtext_cat_char (mt, ')');
475     }
476   else if (MPLIST_MTEXT_P (plist))
477     {
478       mtext_cat_char (mt, '"');
479       /* Not yet implemnted */
480       mtext_cat_char (mt, '"');
481     }
482 }
483
484 /* Support functions for mdebug_dump_plist.  */
485
486 static void
487 dump_string (char *str)
488 {
489   char *p = str, *pend = p + strlen (p), *new, *p1;
490
491   new = p1 = alloca ((pend - p) * 4 + 1);
492   while (p < pend)
493     {
494       if (*p < 0)
495         {
496           sprintf (p1, "\\x%02X", (unsigned char) *p);
497           p1 += 4;
498         }
499       else if (*p < ' ')
500         {
501           *p1++ = '^';
502           *p1++ = *p + '@';
503         }
504       else if (*p == ' ')
505         {
506           *p1++ = '\\';
507           *p1++ = ' ';
508         }
509       else
510         *p1++ = *p;
511       p++;
512     }
513   *p1 = '\0';
514   fprintf (stderr, "%s", new);
515 }
516
517 static void
518 dump_plist_element (MPlist *plist, int indent)
519 {
520   char *prefix = (char *) alloca (indent + 1);
521   MSymbol key;
522
523   memset (prefix, 32, indent);
524   prefix[indent] = 0;
525
526   key = MPLIST_KEY (plist);
527   fprintf (stderr, "(%s(#%d) ", msymbol_name (MPLIST_KEY (plist)),
528            plist->control.ref_count);
529   if (key == Msymbol)
530     dump_string (msymbol_name (MPLIST_SYMBOL (plist)));
531   else if (key == Mtext)
532     mdebug_dump_mtext (MPLIST_MTEXT (plist), indent, 0);
533   else if (key == Minteger)
534     fprintf (stderr, "%x", MPLIST_INTEGER (plist));
535   else if (key == Mstring) 
536     fprintf (stderr, "\"%s\"", MPLIST_STRING (plist));
537   else if (key == Mplist)
538     {
539       fprintf (stderr, "\n%s", prefix);
540       mdebug_dump_plist (MPLIST_PLIST (plist), indent);
541     }
542   else
543     fprintf (stderr, "0x%X", (unsigned) MPLIST_VAL (plist));
544   fprintf (stderr, ")");
545 }
546
547 \f
548 /* Internal API */
549 int
550 mplist__init ()
551 {
552   int i;
553
554   plist_table.count = 0;
555
556   Minteger = msymbol ("integer");
557   Mplist = msymbol_as_managing_key ("plist");
558   Mtext = msymbol_as_managing_key ("mtext");
559
560   for (i = 0; i < 256; i++)
561     hex_mnemonic[i] = 255;
562   for (i = '0'; i <= '9'; i++)
563     hex_mnemonic[i] = i - '0';
564   for (i = 'A'; i <= 'F'; i++)
565     hex_mnemonic[i] = i - 'A' + 10;
566   for (i = 'a'; i <= 'f'; i++)
567     hex_mnemonic[i] = i - 'a' + 10;
568   for (i = 0; i < 256; i++)
569     escape_mnemonic[i] = i;
570   escape_mnemonic['e'] = 27;
571   escape_mnemonic['b'] = '\b';
572   escape_mnemonic['f'] = '\f';
573   escape_mnemonic['n'] = '\n';
574   escape_mnemonic['r'] = '\r';
575   escape_mnemonic['t'] = '\t';
576   escape_mnemonic['\\'] = '\\';
577
578   return 0;
579 }
580
581 void
582 mplist__fini (void)
583 {
584   mdebug__report_object ("Plist", &plist_table);
585 }
586
587
588 /* Parse this form of PLIST:
589       (symbol:KEY1 TYPE1:VAL1 symbol:KEY2 TYPE2:VAL2 ...)
590    and return a newly created plist of this form:
591       (KEY1:VAL1 KEY2:VAL2 ...)  */
592
593 MPlist *
594 mplist__from_plist (MPlist *plist)
595 {
596   MPlist *pl, *p;
597
598   MPLIST_NEW (pl);
599   p = pl;
600   while (! MPLIST_TAIL_P (plist))
601     {
602       MSymbol key, type;
603
604       if (! MPLIST_SYMBOL_P (plist))
605         MERROR (MERROR_PLIST, NULL);
606       key = MPLIST_SYMBOL (plist);
607       plist = MPLIST_NEXT (plist);
608       type = MPLIST_KEY (plist);
609       if (type->managing_key)
610         M17N_OBJECT_REF (MPLIST_VAL (plist));
611       MPLIST_SET_ADVANCE (p, key, MPLIST_VAL (plist));
612       plist = MPLIST_NEXT (plist);
613     }
614   return pl;
615 }
616
617 /** Parse this form of PLIST:
618       ((symbol:KEY1 ANY:VAL1 ... ) (symbol:KEY2 ANY:VAL2 ...) ...)
619     and return a newly created plist of this form:
620       (KEY1:(ANY:VAL1 ...) KEY2:(ANY:VAL2 ...) ...)
621     ANY can be any type.  */
622
623 MPlist *
624 mplist__from_alist (MPlist *plist)
625 {
626   MPlist *pl, *p;
627
628   MPLIST_NEW (pl);
629   p = pl;
630   MPLIST_DO (plist, plist)
631     {
632       MPlist *elt;
633
634       if (! MPLIST_PLIST_P (plist))
635         MERROR (MERROR_PLIST, NULL);
636       elt = MPLIST_PLIST (plist);
637       if (! MPLIST_SYMBOL_P (elt))
638         MERROR (MERROR_PLIST, NULL);
639       MPLIST_SET_ADVANCE (p, MPLIST_SYMBOL (elt), MPLIST_NEXT (elt));
640       M17N_OBJECT_REF (MPLIST_NEXT (elt));
641     }
642   return pl;
643 }
644
645
646 MPlist *
647 mplist__from_file (FILE *fp)
648 {
649   MPlist *plist, *pl;
650   MStream st;
651
652   st.fp = fp;
653   st.eof = 0;
654   st.p = st.pend = st.buffer;
655   MPLIST_NEW (plist);
656   pl = plist;
657   while ((pl = read_element (pl, &st)));
658   return plist;
659 }
660
661
662 /** Parse $STR of $N bytes and return a property list object.  $FORMAT
663     must be either @c MTEXT_FORMAT_US_ASCII or @c MTEXT_FORMAT_UTF_8,
664     and controls how to produce @c STRING or @c M-TEXT in the
665     following definition.
666
667     The syntax of $STR is as follows.
668
669     PLIST ::= '(' ELEMENT * ')'
670
671     ELEMENT ::= SYMBOL | INTEGER | UNSIGNED | STRING | M-TEXT | PLIST
672
673     SYMBOL ::= ascii-character-sequence
674
675     INTEGER ::= '-' ? [ '0' | .. | '9' ]+
676
677     UNSIGNED ::= '0x' [ '0' | .. | '9' | 'A' | .. | 'F' | 'a' | .. | 'f' ]+
678
679     M-TEXT ::= '"' byte-sequence '"'
680
681     Each kind of @c ELEMENT is assigned one of these keys:
682         @c Msymbol, @c Mint, @c Munsigned, @c Mtext, @c Mplist
683
684     In an ascii-character-sequence, a backslush (\) is used as the escape
685     character, which means that, for instance, <tt>"abc\ def"</tt>
686     produces a symbol whose name is of length seven with the fourth
687     character being a space.
688
689     In a byte-sequence, "\r", "\n", "\e", and "\t" are replaced by CR,
690     NL, ESC, and TAB character respectively, "\xXX" are replaced by
691     byte 0xXX.  After this replacement, the byte-sequence is decoded
692     into M-TEXT by $CODING.  */
693
694 MPlist *
695 mplist__from_string (unsigned char *str, int n)
696 {
697   MPlist *plist, *pl;
698   MStream st;
699
700   st.fp = NULL;
701   st.eof = 0;
702   st.p = str;
703   st.pend = str + n;
704   MPLIST_NEW (plist);
705   pl = plist;
706   while ((pl = read_element (pl, &st)));
707   return plist;
708 }
709
710 int
711 mplist__serialize (MText *mt, MPlist *plist)
712 {
713   MPlist *pl;
714
715   MPLIST_DO (pl, plist)
716     {
717       if (pl != plist)
718         mtext_cat_char (mt, ' ');
719       write_element (mt, pl);
720     }
721   return 0;
722 }
723
724 /*** @} */
725 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
726
727 \f
728 /* External API */
729
730 /*** @addtogroup m17nPlist */
731 /*** @{ */
732 /*=*/
733
734 /***en
735     @brief Symbol whose name is "integer".
736
737     The symbol @c Minteger has the name <tt>"integer"</tt>.  A value
738     of a property whose key is @c Minteger must be an integer.  */
739 /***ja
740     @brief "integer" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë.
741
742     ¥·¥ó¥Ü¥ë @c Minteger ¤Ï <tt>"integer"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¡£¥­¡¼¤¬
743     @c Minteger ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ÎÃͤÏÀ°¿ôÃͤǤʤ¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£  */
744
745 MSymbol Minteger;
746 /*=*/
747
748 /***en
749     @brief Symbol whose name is "plist".
750
751     The symbol @c Mplist has the name <tt>"plist"</tt>.  It is a
752     managing key.  A value of a property whose key is @c Mplist must
753     be a plist.  */
754 /***ja
755     @brief "plist" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë.
756
757     ¥·¥ó¥Ü¥ë @c Mplist ¤Ï <tt>"plist"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¡£¤³¤ì¤Ï´É
758     Íý¥­¡¼¤Ç¤¢¤ë¡£¥­¡¼¤¬ @c Mplist ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϠplist ¤Ç¤Ê¤¯
759     ¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£  */
760
761 MSymbol Mplist;
762 /*=*/
763
764 /***en
765     @brief Symbol whose name is "mtext".
766
767     The symbol @c Mtext has the name <tt>"mtext"</tt>.  It is a
768     managing key.  A value of a property whose key is @c Mtext must be an
769     M-text.  */
770
771 /***ja
772     @brief "mtext" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë.
773
774     ¥·¥ó¥Ü¥ë @c Mtext ¤Ï <tt>"mtext"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä´ÉÍý¥­¡¼¤Ç¤¢
775     ¤ë¡£¥­¡¼¤¬ @c Mtext ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ÎÃͤϠM-text ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê
776     ¤¤¡£      */
777
778 MSymbol Mtext;
779
780 /*=*/
781 /***en
782     @brief Create a property list object.
783
784     The mplist () function returns a newly created property list
785     object of length zero.
786
787     @returns
788     This function returns a newly created property list.
789
790     @errors
791     This function never fails.  */
792 /***ja
793     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤ë.
794
795     ´Ø¿ô mplist () ¤ÏŤµ 0 ¤Î¿·¤·¤¯ºî¤é¤ì¤¿¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥ª¥Ö¥¸¥§¥¯
796     ¥È¤òÊÖ¤¹¡£
797
798     @returns
799     ¤³¤Î´Ø¿ô¤Ï¿·¤·¤¯ºî¤é¤ì¤¿¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹¡£
800
801     @errors
802     ¤³¤Î´Ø¿ô¤Ï·è¤·¤Æ¼ºÇÔ¤·¤Ê¤¤¡£     */
803
804 MPlist *
805 mplist ()
806 {
807   MPlist *plist;
808
809   MPLIST_NEW (plist);
810   return plist;
811 }  
812
813 /*=*/
814 /***en
815     @brief Copy a property list.
816
817     The mplist_copy () function copies property list $PLIST.  In the
818     copy, the values are the same as those of $PLIST.
819
820     @return
821     This function returns a newly created plist which is a copy of
822     $PLIST.  
823
824     @errors
825     This function never fails.  */ 
826 /***ja
827     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò¥³¥Ô¡¼¤¹¤ë.
828
829     ´Ø¿ô mplist_copy () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò¥³¥Ô¡¼¤¹¤ë¡£¥³¥Ô¡¼¤Î¤¹¤Ù¤Æ¤Î
830     Ãͤϥ³¥Ô¡¼¸µ $PLIST ¤ÎÃͤÈƱ¤¸¤Ç¤¢¤ë¡£
831
832     @return
833     ¤³¤Î´Ø¿ô¤Ï¿·¤·¤¯ºî¤é¤ì¤¿¡¢$PLIST ¤Î¥³¥Ô¡¼¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤òÊÖ¤¹¡£    
834
835     @errors
836     ¤³¤Î´Ø¿ô¤Ï·è¤·¤Æ¼ºÇÔ¤·¤Ê¤¤¡£     */
837
838 MPlist *
839 mplist_copy (MPlist *plist)
840 {
841   MPlist *copy = mplist (), *pl = copy;
842
843   MPLIST_DO (plist, plist)
844     pl = mplist_add (pl, MPLIST_KEY (plist), MPLIST_VAL (plist));
845   return copy;
846 }
847
848 /*=*/
849
850 /***en
851     @brief Set the value of a property in a property list.
852
853     The mplist_put () function searches property list $PLIST
854     from the beginning for a property whose key is $KEY.  If such a
855     property is found, its value is changed to $VALUE.  Otherwise, a
856     new property whose key is $KEY and value is $VALUE is appended at
857     the end of $PLIST.  See the documentation of mplist_add () for
858     the restriction on $KEY and $VAL.
859
860     If $KEY is a managing key, $VAL must be a managed object.  In this
861     case, the reference count of the old value, if not @c NULL, is
862     decremented by one, and that of $VAL is incremented by one.
863
864     @return
865     If the operation was successful, mplist_put () returns a sublist of
866     $PLIST whose first element is the just modified or added one.
867     Otherwise, it returns @c NULL.  */
868 /***ja
869     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃæ¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÀßÄꤹ¤ë.
870
871     ´Ø¿ô mplist_put () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò»Ï¤á¤«¤éõ¤·¤Æ¡¢¥­¡¼
872     ¤¬ $KEY ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤ÎÃͤò $VALUE ¤Ë
873     Êѹ¹¤¹¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¥­¡¼¤¬ $KEY ¤ÇÃͤ¬ $VALUE ¤Ç¤¢¤ë¿·¤·¤¤
874     ¥×¥í¥Ñ¥Æ¥£¤¬$PLIST ¤ÎËöÈø¤ËÄɲ䵤ì¤ë¡£$KEY ¤È $VAL ¤ËÂФ¹¤ëÀ©¸Â¤Ë
875     ¤Ä¤¤¤Æ¤Ï¡¢mplist_add () ¤ÎÀâÌÀ¤ò»²¾È¡£
876
877     $KEY ¤¬´ÉÍý¥­¡¼¤Ê¤é¤Ð¡¢$VAL ¤Ï´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
878     ¤³¤Î¾ì¹ç¡¢¸Å¤¤Ãͤλ²¾È¿ô¤Ï @c NULL ¤Ç¤Ê¤±¤ì¤Ð 1 ¸º¤é¤µ¤ì¡¢$VAL ¤Î
879     »²¾È¿ô¤Ï 1 Áý¤ä¤µ¤ì¤ë¡£
880
881     @return 
882      ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mplist_put () ¤ÏÊѹ¹¤µ¤ì¤¿¤«Äɲ䵤줿Í×ÁǤ«¤é»Ï
883     ¤Þ¤ë $PLIST ¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£   */
884
885 MPlist *
886 mplist_put (MPlist *plist, MSymbol key, void *val)
887 {
888   if (key == Mnil)
889     MERROR (MERROR_PLIST, NULL);
890   MPLIST_FIND (plist, key);
891   if (key->managing_key)
892     {
893       if (! MPLIST_TAIL_P (plist))
894         M17N_OBJECT_UNREF (MPLIST_VAL (plist));
895       M17N_OBJECT_REF (val);
896     }
897   MPLIST_SET (plist, key, val);
898   return plist;
899 }
900
901 /*=*/
902
903 /***en
904     @brief Get the value of a property in a property list.
905
906     The mplist_get () function searches property list $PLIST
907     from the beginning for a property whose key is $KEY.  If such a
908     property is found, a pointer to its value is returned as the type
909     of <tt>(void *)</tt>.  If not found, @c NULL is returned.
910
911     When @c NULL is returned, there are two possibilities: one is the
912     case where no property is found (see above); the other is the case
913     where a property is found and its value is @c NULL.  In case that
914     these two cases must be distinguished, use the mplist_find_by_key ()
915     function.  */
916 /***ja
917     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃæ¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë.
918
919     ´Ø¿ô mplist_get () ¤Ï¡¢¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò»Ï¤á¤«¤éõ¤·¤Æ¡¢
920     ¥­¡¼¤¬ $KEY ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤ÎÃͤؤΥݥ¤
921     ¥ó¥¿¤ò <tt>(void *)</tt> ·¿¤ÇÊÖ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£
922
923     @c NULL ¤¬Ê֤俺ݤˤÏÆó¤Ä¤Î²ÄǽÀ­¤¬¤¢¤ë:¾åµ­¤Î¤è¤¦¤Ë¥×¥í¥Ñ¥Æ¥£¤¬
924     ¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¤È¡¢¥×¥í¥Ñ¥Æ¥£¤¬¸«¤Ä¤«¤ê¡¢¤½¤ÎÃͤ¬ @c NULL ¤Ç
925     ¤¢¤ë¾ì¹ç¤Ç¤¢¤ë¡£¤³¤ì¤é¤ò¶èÊ̤¹¤ëɬÍפ¬¤¢¤ë¾ì¹ç¤Ë¤Ï´Ø¿ô 
926     mplist_find_by_key () ¤ò»È¤¦¤³¤È¡£  */
927
928 /***
929     @seealso
930     mplist_find_by_key () */
931
932 void *
933 mplist_get (MPlist *plist, MSymbol key)
934 {
935   MPLIST_FIND (plist, key);
936   return (MPLIST_TAIL_P (plist) ? NULL : MPLIST_VAL (plist));
937 }
938
939 /*=*/
940
941 /***en
942     @brief Add a property at the end of a property list.
943
944     The mplist_add () function appends at the end of property list
945      $PLIST a property whose key is $KEY and value is $VAL.  $KEY can
946      be any symbol other than @c Mnil.
947
948     If $KEY is a managing key, $VAL must be a managed object.  In this
949     case, the reference count of $VAL is incremented by one.
950
951     @return
952     If the operation was successful, mplist_add () returns a sublist of
953     $PLIST whose first element is the just added one.  Otherwise, it
954     returns @c NULL.  */
955 /***ja
956     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈËöÈø¤Ë¥×¥í¥Ñ¥Æ¥£¤òÄɲ乤ë.
957
958     ´Ø¿ô mplist_add () ¤Ï¡¢¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ÎËöÈø¤Ë¥­¡¼¤¬ $KEY 
959     ¤ÇÃͤ¬ $VAL ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤òÄɲ乤롣$KEY ¤Ï¡¢@c Mnil °Ê³°¤ÎǤ
960     °Õ¤Î¥·¥ó¥Ü¥ë¤Ç¤è¤¤¡£
961
962     $KEY ¤¬´ÉÍý¥­¡¼¤Ê¤é¤Ð¡¢$VAL ¤Ï´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
963     ¤³¤Î¾ì¹ç¡¢$VAL ¤Î»²¾È¿ô¤Ï 1 Áý¤ä¤µ¤ì¤ë¡£
964
965     @return
966      ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mplist_add () ¤ÏÄɲ䵤줿Í×ÁǤ«¤é»Ï¤Þ¤ë $PLIST 
967     ¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£  */
968
969 MPlist *
970 mplist_add (MPlist *plist, MSymbol key, void *val)
971 {
972   if (key == Mnil)
973     MERROR (MERROR_PLIST, NULL);
974   MPLIST_FIND (plist, Mnil);
975   if (key->managing_key)
976     M17N_OBJECT_REF (val);
977   MPLIST_KEY (plist) = key;
978   MPLIST_VAL (plist) = val;
979   MPLIST_NEW (plist->next);
980   return plist;
981 }
982
983 /*=*/
984
985 /***en
986     @brief Add a property at the beginning of a property list.
987
988     The mplist_push () function inserts at the beginning of property
989     list $PLIST a property whose key is $KEY and value is $VAL.
990
991     If $KEY is a managing key, $VAL must be a managed object.  In this
992     case, the reference count of $VAL is incremented by one.
993
994     @return
995     If the operation was successful, this function returns $PLIST.
996     Otherwise, it returns @c NULL.  */
997 /***ja
998     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ÎÀèƬ¤Ë¥×¥í¥Ñ¥Æ¥£¤òÁÞÆþ¤¹¤ë.
999
1000     ´Ø¿ô mplist_push () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ÎÀèƬ¤Ë¥­¡¼¤¬ $KEY 
1001     ¤ÇÃͤ¬ $VAL ¤Ç¤¢¤ë¥ª¥Ö¥¸¥§¥¯¥È¤òÁÞÆþ¤¹¤ë¡£
1002
1003     $KEY ¤¬´ÉÍý¥­¡¼¤Ê¤é¤Ð¡¢$VAL ¤Ï´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
1004     ¤³¤Î¾ì¹ç¡¢$VAL ¤Î»²¾È¿ô¤Ï 1 Áý¤ä¤µ¤ì¤ë¡£
1005
1006     @return
1007     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¤³¤Î´Ø¿ô¤Ï $PLIST ¤òÊÖ¤·¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð@c NULL ¤ò
1008     ÊÖ¤¹¡£  */
1009
1010 MPlist *
1011 mplist_push (MPlist *plist, MSymbol key, void *val)
1012 {
1013   MPlist *pl;
1014
1015   if (key == Mnil)
1016     MERROR (MERROR_PLIST, NULL);
1017   MPLIST_NEW (pl);
1018   MPLIST_KEY (pl) = MPLIST_KEY (plist);
1019   MPLIST_VAL (pl) = MPLIST_VAL (plist);
1020   MPLIST_NEXT (pl) = MPLIST_NEXT (plist);
1021   plist->next = pl;
1022   if (key->managing_key)
1023     M17N_OBJECT_REF (val);
1024   MPLIST_KEY (plist) = key;
1025   MPLIST_VAL (plist) = val;
1026   return plist;
1027 }
1028
1029 /*=*/
1030
1031 /***en
1032     @brief Remove a property at the beginning of a property list.
1033
1034     The mplist_pop () function removes a property at the beginning of
1035     property list $PLIST.  As a result, the second key and value of
1036     the original $PLIST become the first of those of the new $PLIST.
1037
1038     @return
1039     If the operation was successful, this function return the value of
1040     the just popped property.  Otherwise, it returns @c NULL.  */
1041 /***ja
1042     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ÎÀèƬ¤«¤é¥×¥í¥Ñ¥Æ¥£¤òºï½ü¤¹¤ë.
1043
1044     ´Ø¿ô mplist_pop () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ÎÀèƬ¤Î¥×¥í¥Ñ¥Æ¥£¤ò
1045     ºï½ü¤¹¤ë¡£·ë²Ì¤È¤·¤Æ¡¢¸µ¤Î $PLIST ¤Î2ÈÖÌܤΥ­¡¼¤ÈÃͤ¬¡¢¿·¤·¤¤ 
1046     $PLIST ¤ÎÀèƬ¤Î¥­¡¼¤ÈÃͤˤʤ롣
1047
1048     @return 
1049     ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ïºï½ü¤µ¤ì¤¿¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹¡£¤½¤¦
1050     ¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£  */
1051
1052 void *
1053 mplist_pop (MPlist *plist)
1054 {
1055   void *val;
1056   MPlist *next;
1057
1058   if (MPLIST_TAIL_P (plist))
1059     return NULL;
1060   val = MPLIST_VAL (plist);
1061   next = MPLIST_NEXT (plist);
1062   MPLIST_KEY (plist) = MPLIST_KEY (next);
1063   MPLIST_VAL (plist) = MPLIST_VAL (next);
1064   if (MPLIST_KEY (plist) != Mnil
1065       && MPLIST_KEY (plist)->managing_key
1066       && MPLIST_VAL (plist))
1067     M17N_OBJECT_REF (MPLIST_VAL (plist));
1068   MPLIST_NEXT (plist) = MPLIST_NEXT (next);
1069   if (plist->next)
1070     M17N_OBJECT_REF (plist->next);
1071   M17N_OBJECT_UNREF (next);
1072   return val;
1073 }
1074
1075 /*=*/
1076 /***en
1077     @brief Find a property of a specific key in a property list.
1078
1079     The mplist_find_by_key () function searches property list
1080     $PLIST from the beginning for a property whose key is $KEY.  If
1081     such a property is found, a sublist of $PLIST whose first element
1082     is the found one is returned.  Otherwise, @c NULL is returned.
1083
1084     If $KEY is @c Mnil, it returns a sublist of $PLIST whose
1085     first element is the last one of $PLIST.  */
1086 /***ja
1087     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃ椫¤é»ØÄê¤Î¥­¡¼¤ò»ý¤Ä¥×¥í¥Ñ¥Æ¥£¤òõ¤¹.
1088
1089     ´Ø¿ô mplist_find_by_key () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò»Ï¤á¤«¤éõ
1090     ¤·¤Æ¡¢¥­¡¼¤¬ $KEY ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤Î¥×¥í
1091     ¥Ñ¥Æ¥£¤«¤é»Ï¤Þ¤ë $PLIST ¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð@c NULL 
1092     ¤òÊÖ¤¹¡£
1093
1094     $KEY ¤¬ @c Mnil ¤Ê¤é¤Ð¡¢$PLIST ¤ÎºÇ¸å¤ÎÍ×ÁǤ«¤é»Ï¤Þ¤ëÉôʬ¥ê¥¹¥È¤ò
1095     ÊÖ¤¹¡£  */
1096
1097 MPlist *
1098 mplist_find_by_key (MPlist *plist, MSymbol key)
1099 {
1100   MPLIST_FIND (plist, key);
1101   return (MPLIST_TAIL_P (plist)
1102           ? (key == Mnil ? plist : NULL)
1103           : plist);
1104 }
1105
1106 /*=*/
1107 /***en
1108     @brief Find a property of a specific value in a property list.
1109
1110     The mplist_find_by_value () function searches property list $PLIST
1111     from the beginning for a property whose value is $VAL.  If such a
1112     property is found, a sublist of $PLIST whose first element is the
1113     found one is returned.  Otherwise, @c NULL is returned.  */
1114 /***ja
1115     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃ椫¤é»ØÄê¤ÎÃͤò»ý¤Ä¥×¥í¥Ñ¥Æ¥£¤òõ¤¹.
1116
1117     ´Ø¿ô mplist_find_by_value () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò»Ï¤á¤«¤é
1118     Ãµ¤·¤Æ¡¢Ãͤ¬ $VAL ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤Î¥×¥í
1119     ¥Ñ¥Æ¥£¤«¤é»Ï¤Þ¤ë $PLIST ¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð@c NULL 
1120     ¤òÊÖ¤¹¡£ */
1121
1122 MPlist *
1123 mplist_find_by_value (MPlist *plist, void *val)
1124 {
1125   MPLIST_DO (plist, plist)
1126     {
1127       if (MPLIST_VAL (plist) == val)
1128         return plist;
1129     }
1130   return NULL;
1131 }
1132
1133 /*=*/
1134
1135 /***en
1136     @brief Return the next sublist of a property list.
1137
1138     The mplist_next () function returns a pointer to the sublist of
1139     property list $PLIST, which begins at the second element in $PLIST.  If the
1140     length of $PLIST is zero, it returns @c NULL.  */
1141 /***ja
1142     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Î¼¡¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹.
1143
1144     ´Ø¿ô mplist_next () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤Î£²ÈÖÌÜ
1145     ¤ÎÍ×ÁǤ«¤é»Ï¤Þ¤ëÉôʬ¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£$PLIST ¤ÎŤµ¤¬ 0 ¤Ê
1146     ¤é¤Ð @c NULL ¤òÊÖ¤¹¡£  */
1147
1148 MPlist *
1149 mplist_next (MPlist *plist)
1150 {
1151   return (MPLIST_TAIL_P (plist) ? NULL : plist->next);
1152 }
1153
1154 /*=*/
1155
1156 /***en
1157     @brief Set the first property in a property list.
1158
1159     The mplist_set () function sets the key and the value of the first
1160     property in property list $PLIST to $KEY and $VALUE, respectively.
1161     See the documentation of mplist_add () for the restriction on $KEY
1162     and $VAL.
1163
1164     @return
1165     If the operation was successful, mplist_set () returns $PLIST.
1166     Otherwise, it returns @c NULL.  */
1167 /***ja
1168     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤òÀßÄꤹ¤ë.
1169
1170     ´Ø¿ô mplist_set () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤Î
1171     ¥­¡¼¤ÈÃͤò¤½¤ì¤¾¤ì $KEY ¤È $VALUE ¤ËÀßÄꤹ¤ë¡£$KEY ¤È $VAL ¤ËÂФ¹
1172     ¤ëÀ©¸Â¤Ë¤Ä¤¤¤Æ¤Ï¡¢mplist_add () ¤ÎÀâÌÀ¤ò»²¾È¡£
1173
1174     @return
1175     ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mplist_set () ¤Ï $PLIST ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð
1176     @c NULL ¤òÊÖ¤¹¡£  */
1177
1178 MPlist *
1179 mplist_set (MPlist *plist, MSymbol key, void * val)
1180 {
1181   if (key == Mnil)
1182     {
1183       if (! MPLIST_TAIL_P (plist))
1184         {
1185           key = MPLIST_KEY (plist);
1186           M17N_OBJECT_UNREF (MPLIST_NEXT (plist));
1187           MPLIST_KEY (plist) = Mnil;
1188           if (key->managing_key && MPLIST_VAL (plist))
1189             M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1190           plist->next = NULL;
1191         }
1192     }
1193   else
1194     {
1195       if (! MPLIST_TAIL_P (plist)
1196           && MPLIST_KEY (plist)->managing_key
1197           && MPLIST_VAL (plist))
1198         M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1199       if (key->managing_key)
1200         M17N_OBJECT_REF (val);
1201       MPLIST_SET (plist, key, val);
1202     }
1203   return plist;
1204 }
1205
1206 /*=*/
1207
1208 /***en
1209     @brief Return the length of a property list.
1210
1211     The mplist_length () function returns the number of properties in
1212     property list  $PLIST.  */
1213 /***ja
1214     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ÎŤµ¤òÊÖ¤¹.
1215
1216     ´Ø¿ô mplist_length () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST Ãæ¤Î¥×¥í¥Ñ¥Æ¥£¤Î¿ô
1217     ¤òÊÖ¤¹¡£  */
1218
1219 int
1220 mplist_length (MPlist *plist)
1221 {
1222   int n;
1223
1224   for (n = 0; ! (MPLIST_TAIL_P (plist)); n++, plist = plist->next);
1225   return n;
1226 }
1227
1228 /*=*/
1229
1230 /***en
1231     @brief Return the key of the first property in a property list.
1232
1233     The mplist_key () function returns the key of the first property
1234     in property list $PLIST.  If the length of $PLIST is zero,
1235     it returns @c Mnil.  */
1236 /***ja
1237     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃæ¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤òÊÖ¤¹.
1238
1239     ´Ø¿ô mplist_key () ¤Ï¡¢¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST Ãæ¤ÎºÇ
1240     ½é¤Î¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤òÊÖ¤¹¡£$PLIST ¤ÎŤµ¤¬ 0 ¤Ê¤é¤Ð¡¢ @c Mnil ¤ò
1241     ÊÖ¤¹¡£  */
1242
1243 MSymbol
1244 mplist_key (MPlist *plist)
1245 {
1246   return MPLIST_KEY (plist);
1247 }
1248
1249 /*=*/
1250
1251 /***en
1252     @brief Return the value of the first property in a property list.
1253
1254     The mplist_value () function returns the value of the first
1255     property in property list  $PLIST.  If the length of $PLIST
1256     is zero, it returns @c NULL.  */
1257 /***ja
1258     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃæ¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹.
1259
1260     ´Ø¿ô mplist_value () ¤Ï¡¢¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST Ãæ¤Î
1261     ºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹¡£$PLIST ¤ÎŤµ¤¬ 0 ¤Ê¤é¤Ð¡¢ @c Mnil ¤ò
1262     ÊÖ¤¹¡£  */
1263
1264 void *
1265 mplist_value (MPlist *plist)
1266 {
1267   return MPLIST_VAL (plist);
1268 }
1269
1270 /***en
1271     @brief Generate a property list by deserializaing an M-text.
1272
1273     The mplist_deserialize () function parses M-text $MT and returns a
1274     property list.
1275
1276     The syntax of $MT is as follows.
1277
1278     MT ::= '(' ELEMENT * ')'
1279
1280     ELEMENT ::= SYMBOL | INTEGER | M-TEXT | PLIST
1281
1282     SYMBOL ::= ascii-character-sequence
1283
1284     INTEGER ::= '-' ? [ '0' | .. | '9' ]+
1285                 | '0x' [ '0' | .. | '9' | 'A' | .. | 'F' | 'a' | .. | 'f' ]+
1286
1287     M-TEXT ::= '"' character-sequence '"'
1288
1289     Each alternatives of @c ELEMENT is assigned one of these keys: @c
1290     Msymbol, @c Minteger, @c Mtext, @c Mplist
1291
1292     In an ascii-character-sequence, a backslush (\) is used as the escape
1293     character, which means that, for instance, <tt>"abc\ def"</tt>
1294     produces a symbol whose name is of length seven with the fourth
1295     character being a space.  */
1296 /***ja
1297     @brief M-text ¤ò¥Ç¥·¥ê¥¢¥é¥¤¥º¤·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤òºî¤ë.
1298
1299     ´Ø¿ô mplist_deserialize () ¤Ï M-text $MT ¤ò²òÀϤ·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹
1300     ¥È¤òÊÖ¤¹¡£
1301
1302     $MT ¤Î¥·¥ó¥¿¥Ã¥¯¥¹¤Ï°Ê²¼¤ÎÄ̤ꡣ
1303
1304     MT ::= '(' ELEMENT * ')'
1305
1306     ELEMENT ::= SYMBOL | INTEGER | M-TEXT | PLIST
1307
1308     SYMBOL ::= ¥¢¥¹¥­¡¼Ê¸»úÎó
1309
1310     INTEGER ::= '-' ? [ '0' | .. | '9' ]+
1311                 | '0x' [ '0' | .. | '9' | 'A' | .. | 'F' | 'a' | .. | 'f' ]+
1312
1313     M-TEXT ::= '"' character-sequence '"'
1314
1315     @c ELEMENT ¤Î³ÆÁªÂò»è¤Ï¥­¡¼¡§@c Msymbol, @c Minteger, @c Mtext,
1316     @c Mplist ¤Î¤¤¤º¤ì¤«¤ò³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¡£
1317
1318     ¥¢¥¹¥­¡¼Ê¸»úÎóÆâ¤Ç¤Ï¡¢¥Ð¥Ã¥¯¥¹¥é¥Ã¥·¥å (\) ¤¬¥¨¥¹¥±¡¼¥×ʸ»ú¤È¤·¤Æ
1319     ÍѤ¤¤é¤ì¤ë¡£¤¿¤È¤¨¤Ð <tt>"abc\ def"</tt> ¤Ï£´Ê¸»úÌܤ¬¶õÇòʸ»ú¤Ç¤¢
1320     ¤êŤµ¤¬£·¤Ç¤¢¤ë»ý¤Ä̾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤òÀ¸À®¤¹¤ë¡£   */
1321
1322 MPlist *
1323 mplist_deserialize (MText *mt)
1324 {
1325   MPlist *plist;
1326   MText *tmp = NULL;
1327
1328   if (mt->format > MTEXT_FORMAT_UTF_8)
1329     {
1330       if (MTEXT_READ_ONLY_P (mt))
1331         mt = tmp = mtext_cpy (mtext (), mt);
1332       else
1333         mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
1334     }
1335   plist = mplist__from_string (MTEXT_DATA (mt), mtext_nbytes (mt));
1336   if (tmp)
1337     M17N_OBJECT_UNREF (tmp);
1338   return plist;
1339 }
1340
1341 /*** @}  */
1342
1343 /*** @addtogroup m17nDebug */
1344 /*=*/
1345 /*** @{  */
1346
1347 /***en
1348     @brief Dump a property list.
1349
1350     The mdebug_dump_plist () function prints a property list $PLIST in
1351     a human readable way to the stderr.  $INDENT specifies how many
1352     columns to indent the lines but the first one.
1353
1354     @return
1355     This function returns $PLIST.  */
1356 /***ja
1357     @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò¥À¥ó¥×¤¹¤ë.
1358
1359     ´Ø¿ô mdebug_dump_plist () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò stderr ¤Ë¿Í
1360     ´Ö¤Ë²ÄÆɤʠ·Á¤Ç°õºþ¤¹¤ë¡£ $UNDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ
1361     ¤ë¡£
1362
1363     @return
1364     ¤³¤Î´Ø¿ô¤Ï $PLIST ¤òÊÖ¤¹¡£  */
1365 MPlist *
1366 mdebug_dump_plist (MPlist *plist, int indent)
1367 {
1368   char *prefix = (char *) alloca (indent + 1);
1369   MPlist *pl;
1370   int first = 1;
1371
1372   memset (prefix, 32, indent);
1373   prefix[indent] = 0;
1374
1375   fprintf (stderr, "(");
1376   MPLIST_DO (pl, plist)
1377     {
1378       if (first)
1379         first = 0;
1380       else
1381         fprintf (stderr, "\n%s ", prefix);
1382       dump_plist_element (pl, indent + 2);
1383     }
1384   fprintf (stderr, ")");
1385   return plist;
1386 }
1387
1388 /*** @} */
1389
1390 /*
1391   Local Variables:
1392   coding: euc-japan
1393   End:
1394 */