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