1 /* plist.c -- plist module.
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
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.
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.
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
26 @brief Property List objects and API for them.
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
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
39 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
40 /*** @addtogroup m17nInternal
47 #include "m17n-misc.h"
49 #include "character.h"
54 static M17NObjectArray plist_table;
56 /** Set PLIST to a newly allocated plist object. */
58 #define MPLIST_NEW(plist) \
60 M17N_OBJECT (plist, free_plist, MERROR_PLIST); \
61 M17N_OBJECT_REGISTER (plist_table, plist); \
65 /** Set the element of PLIST to KEY and VAL. If PLIST is an anchor,
66 append a new anchor. */
68 #define MPLIST_SET(plist, key, val) \
70 MPLIST_KEY (plist) = (key); \
71 MPLIST_VAL (plist) = (val); \
72 if (! (plist)->next) \
73 MPLIST_NEW ((plist)->next); \
77 /** Set the element of PLIST to KEY and VAL. PLIST must be an anchor.
78 Append a new anchor and set PLIST to that anchor. */
80 #define MPLIST_SET_ADVANCE(plist, key, val) \
82 MPLIST_KEY (plist) = (key); \
83 MPLIST_VAL (plist) = (val); \
84 MPLIST_NEW ((plist)->next); \
85 plist = (plist)->next; \
90 free_plist (void *object)
92 MPlist *plist = (MPlist *) object;
95 MPlist *next = plist->next;
97 if (MPLIST_KEY (plist) != Mnil && MPLIST_KEY (plist)->managing_key)
98 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
99 M17N_OBJECT_UNREGISTER (plist_table, plist);
102 } while (plist && plist->control.ref_count == 1);
103 M17N_OBJECT_UNREF (plist);
108 /* Load a plist from a string. */
110 #define READ_CHUNK 0x10000
114 /* File pointer if the stream is associated with a file. Otherwise
118 unsigned char buffer[READ_CHUNK];
119 unsigned char *p, *pend;
123 get_byte (MStream *st)
127 if (! st->fp || st->eof)
129 n = fread (st->buffer, 1, READ_CHUNK, st->fp);
135 st->p = st->buffer + 1;
136 st->pend = st->buffer + n;
137 return st->buffer[0];
141 ((st)->p < (st)->pend ? *(st)->p++ : get_byte (st))
144 #define UNGETC(c, st) \
147 /** Mapping table for reading a number. Hexadecimal chars
148 (0..9,A..F,a..F) are mapped to the corresponding numbers.
149 Apostrophe (code 39) is mapped to 254. All the other bytes are
151 unsigned char hex_mnemonic[256];
153 /** Mapping table for escaped characters. Mnemonic characters (e, b,
154 f, n, r, or t) that follows '\' are mapped to the corresponding
155 character code. All the other bytes are mapped to themselves. */
156 unsigned char escape_mnemonic[256];
159 /** Read an integer from the stream ST. It is assumed that we have
160 already read one character C. */
163 read_decimal (MStream *st, int c)
167 while (c >= '0' && c <= '9')
169 num = (num * 10) + (c - '0');
178 /** Read an unsigned from the stream ST. */
181 read_hexadesimal (MStream *st)
186 while ((c = GETC (st)) != EOF
187 && (n = hex_mnemonic[c]) < 16)
188 num = (num << 4) | n;
195 /** Read an M-text element from ST, and add it to LIST. Return a list
196 for the next element. */
199 read_mtext_element (MPlist *plist, MStream *st)
201 unsigned char buffer[1024];
203 unsigned char *buf = buffer;
207 while ((c = GETC (st)) != EOF && c != '"')
209 if (i + MAX_UTF8_CHAR_BYTES >= bufsize)
214 MTABLE_MALLOC (buf, bufsize, MERROR_PLIST);
215 memcpy (buf, buffer, i);
218 MTABLE_REALLOC (buf, bufsize, MERROR_PLIST);
230 c = read_hexadesimal (st);
236 c = escape_mnemonic[c];
242 MPLIST_SET_ADVANCE (plist, Mtext,
243 mtext__from_data (buf, i, MTEXT_FORMAT_UTF_8, 1));
250 read_character (MStream *st, int c)
252 unsigned char buf[MAX_UTF8_CHAR_BYTES + 1];
253 int len = CHAR_BYTES_BY_HEAD (c);
257 for (i = 1; i < len; i++)
261 || (c & 0xC0) != 0x80)
266 c = STRING_CHAR_UTF8 (buf);
273 /** Read an integer element from ST, and add it to LIST. Return a
274 list for the next element. It is assumed that we have already
275 read the character C. */
278 read_integer_element (MPlist *plist, MStream *st, int c)
282 if (c == '0' || c == '#')
286 num = read_hexadesimal (st);
288 num = read_decimal (st, c);
297 if (c < 128 || ! CHAR_UNITS_BY_HEAD_UTF8 (c))
300 num = read_character (st, c);
307 else if (c < 128 || ! CHAR_UNITS_BY_HEAD_UTF8 (c))
308 num = escape_mnemonic[c];
310 num = read_character (st, c);
314 num = - read_decimal (st, GETC (st));
316 num = read_decimal (st, c);
318 MPLIST_SET_ADVANCE (plist, Minteger, (void *) num);
322 /** Read a symbol element from ST, and add it to LIST. Return a list
323 for the next element. */
326 read_symbol_element (MPlist *plist, MStream *st)
328 unsigned char buffer[1024];
330 unsigned char *buf = buffer;
334 while ((c = GETC (st)) != EOF
336 && c != ')' && c != '(' && c != '"')
343 MTABLE_MALLOC (buf, bufsize, MERROR_PLIST);
344 memcpy (buf, buffer, i);
347 MTABLE_REALLOC (buf, bufsize, MERROR_PLIST);
354 c = escape_mnemonic[c];
360 MPLIST_SET_ADVANCE (plist, Msymbol, msymbol ((char *) buf));
368 /* Read an element of various type from stream ST, and add it to LIST.
369 Return a list for the next element. The element type is decided by
370 the first token character found as below:
373 '0'..'9', '-': integer
374 '?': integer representing character code
375 the other ASCII letters: symbol
379 read_element (MPlist *plist, MStream *st)
383 /* Skip separators and comments. */
386 while ((c = GETC (st)) != EOF && c <= ' ');
389 while ((c = GETC (st)) != EOF && c != '\n');
400 while ((p = read_element (p, st)));
401 MPLIST_SET_ADVANCE (plist, Mplist, pl);
405 return read_mtext_element (plist, st);
406 if ((c >= '0' && c <= '9') || c == '-' || c == '?' || c == '#')
407 return read_integer_element (plist, st, c);
408 if (c == EOF || c == ')')
411 return read_symbol_element (plist, st);
415 write_element (MText *mt, MPlist *plist)
417 if (MPLIST_SYMBOL_P (plist))
419 MSymbol sym = MPLIST_SYMBOL (plist);
423 MTEXT_CAT_ASCII (mt, "nil");
427 char *name = MSYMBOL_NAME (sym);
428 char *buf = alloca (MSYMBOL_NAMELEN (sym) * 2 + 1), *p = buf;
432 if (*name <= ' ' || *name == '"' || *name == ')' || *name == ')')
437 MTEXT_CAT_ASCII (mt, buf);
440 else if (MPLIST_INTEGER_P (plist))
442 int num = MPLIST_INTEGER (plist);
445 sprintf (buf, "%d", num);
446 MTEXT_CAT_ASCII (mt, buf);
448 else if (MPLIST_PLIST_P (plist))
452 plist = MPLIST_PLIST (plist);
453 mtext_cat_char (mt, '(');
454 MPLIST_DO (pl, plist)
457 mtext_cat_char (mt, ' ');
458 write_element (mt, pl);
460 mtext_cat_char (mt, ')');
462 else if (MPLIST_MTEXT_P (plist))
464 mtext_cat_char (mt, '"');
465 /* Not yet implemnted */
466 mtext_cat_char (mt, '"');
470 /* Support functions for mdebug_dump_plist. */
473 dump_string (char *str)
475 char *p = str, *pend = p + strlen (p), *new, *p1;
477 new = p1 = alloca ((pend - p) * 4 + 1);
482 sprintf (p1, "\\x%02X", (unsigned char) *p);
500 fprintf (stderr, "%s", new);
504 dump_plist_element (MPlist *plist, int indent)
506 char *prefix = (char *) alloca (indent + 1);
509 memset (prefix, 32, indent);
512 key = MPLIST_KEY (plist);
513 fprintf (stderr, "(%s(#%d) ", msymbol_name (MPLIST_KEY (plist)),
514 plist->control.ref_count);
516 dump_string (msymbol_name (MPLIST_SYMBOL (plist)));
517 else if (key == Mtext)
518 mdebug_dump_mtext (MPLIST_MTEXT (plist), indent, 0);
519 else if (key == Minteger)
520 fprintf (stderr, "%x", MPLIST_INTEGER (plist));
521 else if (key == Mstring)
522 fprintf (stderr, "\"%s\"", MPLIST_STRING (plist));
523 else if (key == Mplist)
525 fprintf (stderr, "\n%s", prefix);
526 mdebug_dump_plist (MPLIST_PLIST (plist), indent);
529 fprintf (stderr, "0x%X", (unsigned) MPLIST_VAL (plist));
530 fprintf (stderr, ")");
540 plist_table.count = 0;
542 Minteger = msymbol ("integer");
543 Mplist = msymbol_as_managing_key ("plist");
544 Mtext = msymbol_as_managing_key ("mtext");
546 for (i = 0; i < 256; i++)
547 hex_mnemonic[i] = 255;
548 for (i = '0'; i <= '9'; i++)
549 hex_mnemonic[i] = i - '0';
550 for (i = 'A'; i <= 'F'; i++)
551 hex_mnemonic[i] = i - 'A' + 10;
552 for (i = 'a'; i <= 'f'; i++)
553 hex_mnemonic[i] = i - 'a' + 10;
554 for (i = 0; i < 256; i++)
555 escape_mnemonic[i] = i;
556 escape_mnemonic['e'] = 27;
557 escape_mnemonic['b'] = '\b';
558 escape_mnemonic['f'] = '\f';
559 escape_mnemonic['n'] = '\n';
560 escape_mnemonic['r'] = '\r';
561 escape_mnemonic['t'] = '\t';
562 escape_mnemonic['\\'] = '\\';
570 mdebug__report_object ("Plist", &plist_table);
574 /* Parse this form of PLIST:
575 (symbol:KEY1 TYPE1:VAL1 symbol:KEY2 TYPE2:VAL2 ...)
576 and return a newly created plist of this form:
577 (KEY1:VAL1 KEY2:VAL2 ...) */
580 mplist__from_plist (MPlist *plist)
586 while (! MPLIST_TAIL_P (plist))
590 if (! MPLIST_SYMBOL_P (plist))
591 MERROR (MERROR_PLIST, NULL);
592 key = MPLIST_SYMBOL (plist);
593 plist = MPLIST_NEXT (plist);
594 type = MPLIST_KEY (plist);
595 if (type->managing_key)
596 M17N_OBJECT_REF (MPLIST_VAL (plist));
597 MPLIST_SET_ADVANCE (p, key, MPLIST_VAL (plist));
598 plist = MPLIST_NEXT (plist);
603 /** Parse this form of PLIST:
604 ((symbol:KEY1 ANY:VAL1 ... ) (symbol:KEY2 ANY:VAL2 ...) ...)
605 and return a newly created plist of this form:
606 (KEY1:(ANY:VAL1 ...) KEY2:(ANY:VAL2 ...) ...)
607 ANY can be any type. */
610 mplist__from_alist (MPlist *plist)
616 MPLIST_DO (plist, plist)
620 if (! MPLIST_PLIST_P (plist))
621 MERROR (MERROR_PLIST, NULL);
622 elt = MPLIST_PLIST (plist);
623 if (! MPLIST_SYMBOL_P (elt))
624 MERROR (MERROR_PLIST, NULL);
625 MPLIST_SET_ADVANCE (p, MPLIST_SYMBOL (elt), MPLIST_NEXT (elt));
626 M17N_OBJECT_REF (MPLIST_NEXT (elt));
633 mplist__from_file (FILE *fp)
640 st.p = st.pend = st.buffer;
643 while ((pl = read_element (pl, &st)));
648 /** Parse $STR of $N bytes and return a property list object. $FORMAT
649 must be either @c MTEXT_FORMAT_US_ASCII or @c MTEXT_FORMAT_UTF_8,
650 and controls how to produce @c STRING or @c M-TEXT in the
651 following definition.
653 The syntax of $STR is as follows.
655 PLIST ::= '(' ELEMENT * ')'
657 ELEMENT ::= SYMBOL | INTEGER | UNSIGNED | STRING | M-TEXT | PLIST
659 SYMBOL ::= ascii-character-sequence
661 INTEGER ::= '-' ? [ '0' | .. | '9' ] +
663 UNSIGNED ::= '0x' [ '0' | .. | '9' | 'A' | .. | 'F' | 'a' | .. | 'f' ] +
665 STRING ::= '"' byte-sequence '"'
667 M-TEXT ::= '"' byte-sequence '"'
669 Each kind of @c ELEMENT is assigned one of these keys:
670 @c Msymbol, @c Mint, @c Munsigned,
671 @c Mstring, @c Mtext, @c Mplist
673 In an ascii-character-sequence, a backslush (\) is used as the escape
674 character, which means that, for instance, <tt>"abc\ def"</tt>
675 produces a symbol whose name is of length seven with the fourth
676 character being a space.
678 In a byte-sequence, "\r", "\n", "\e", and "\t" are replaced by CR,
679 NL, ESC, and TAB character respectively, "\xXX" are replaced by
680 byte 0xXX. After this replacement, the byte-sequence is decoded
681 into STRING or M-TEXT as below:
683 If $FORMAT is MTEXT_FORMAT_US_ASCII and the byte-sequence
684 contains only ASCII characters, it is decoded into STRING.
685 Otherwise, it is regarded as an UTF-8 sequence, and decoded into
689 mplist__from_string (unsigned char *str, int n)
700 while ((pl = read_element (pl, &st)));
705 mplist__serialize (MText *mt, MPlist *plist)
709 MPLIST_DO (pl, plist)
712 mtext_cat_char (mt, ' ');
713 write_element (mt, pl);
719 mplist__deserialize (MText *mt)
721 if (mt->format > MTEXT_FORMAT_UTF_8)
722 MERROR (MERROR_PLIST, NULL);
723 return mplist__from_string (MTEXT_DATA (mt), mtext_nbytes (mt));
728 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
733 /*** @addtogroup m17nPlist */
738 @brief Symbol whose name is "integer".
740 The symbol @c Minteger has the name <tt>"integer"</tt>. A value
741 of a plist whose key is @c Minteger must be an integer. */
747 @brief Symbol whose name is "plist".
749 The symbol @c Mplist has the name <tt>"plist"</tt>. It is a
750 managing key. A value of a plist whose key is @c Mplist must be a
757 @brief Symbol whose name is "mtext".
759 The symbol @c Mtext has the name <tt>"mtext"</tt>. It is a
760 managing key. A value of a plist whose key is @c Mtext must be an
764 @brief "text" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë
766 ÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë @c Mtext ¤Ï <tt>"text"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä´ÉÍý
774 @brief Create a property list object.
776 The mplist () function returns a newly created property list
777 object of length zero.
780 This function returns a newly created property list.
783 This function never fails. */
798 The mplist_copy () function copies $PLIST. In the copy, the
799 values are the same as those of $PLIST.
802 This function returns a newly created plist which is a copy of
806 This function never fails. */
809 mplist_copy (MPlist *plist)
811 MPlist *copy = mplist (), *pl = copy;
813 MPLIST_DO (plist, plist)
814 pl = mplist_add (pl, MPLIST_KEY (plist), MPLIST_VAL (plist));
821 @brief Set the value of a property in a property list object.
823 The mplist_put () function searches property list object $PLIST
824 from the beginning for a property whose key is $KEY. If such a
825 property is found, its value is changed to $VALUE. Otherwise, a
826 new property whose key is $KEY and value is $VALUE is appended at
827 the end of $PLIST. See the documentation of mplist_add () for
828 the restriction on $KEY and $VAL.
830 If $KEY is a managing key, $VAL must be a managed object. In this
831 case, the reference count of the old value, if not @c NULL, is
832 decremented by one, and that of $VAL is incremented by one.
835 If the operation was successful, mplist_put () returns a sublist of
836 $PLIST whose first element is the just modified or added one.
837 Otherwise, it returns @c NULL. */
840 mplist_put (MPlist *plist, MSymbol key, void *val)
843 MERROR (MERROR_PLIST, NULL);
844 MPLIST_FIND (plist, key);
845 if (key->managing_key)
847 if (! MPLIST_TAIL_P (plist))
848 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
849 M17N_OBJECT_REF (val);
851 MPLIST_SET (plist, key, val);
858 @brief Get the value of a property in a property list object.
860 The mplist_get () function searches property list object $PLIST
861 from the beginning for a property whose key is $KEY. If such a
862 property is found, a pointer to its value is returned as the type
863 of <tt>(void *)</tt>. If not found, @c NULL is returned.
865 When @c NULL is returned, there are two possibilities: one is the
866 case where no property is found (see above); the other is the case
867 where a property is found and its value is @c NULL. In case that
868 these two cases must be distinguished, use the mplist_find_by_key ()
873 mplist_find_by_key () */
876 mplist_get (MPlist *plist, MSymbol key)
878 MPLIST_FIND (plist, key);
879 return (MPLIST_TAIL_P (plist) ? NULL : MPLIST_VAL (plist));
885 @brief Add a property at the end of a property list object.
887 The mplist_add () function appends at the end of $PLIST a property
888 whose key is $KEY and value is $VAL. $KEY can be any symbol
891 If $KEY is a managing key, $VAL must be a managed object. In this
892 case, the reference count of $VAL is incremented by one.
895 If the operation was successful, mplist_add () returns a sublist of
896 $PLIST whose first element is the just added one. Otherwise, it
900 mplist_add (MPlist *plist, MSymbol key, void *val)
903 MERROR (MERROR_PLIST, NULL);
904 MPLIST_FIND (plist, Mnil);
905 if (key->managing_key)
906 M17N_OBJECT_REF (val);
907 MPLIST_KEY (plist) = key;
908 MPLIST_VAL (plist) = val;
909 MPLIST_NEW (plist->next);
916 @brief Push a property to a property list object.
918 The mplist_push () function pushes at the top of $PLIST a
919 property whose key is $KEY and value si $VAL.
921 If $KEY is a managing key, $VAL must be a managed object. In this
922 case, the reference count of $VAL is incremented by one.
925 If the operation was successful, this function returns $PLIST.
926 Otherwise, it returns @c NULL. */
929 mplist_push (MPlist *plist, MSymbol key, void *val)
934 MERROR (MERROR_PLIST, NULL);
936 MPLIST_KEY (pl) = MPLIST_KEY (plist);
937 MPLIST_VAL (pl) = MPLIST_VAL (plist);
938 pl->next = plist->next;
940 if (key->managing_key)
941 M17N_OBJECT_REF (val);
942 MPLIST_KEY (plist) = key;
943 MPLIST_VAL (plist) = val;
950 @brief Pop a property from a property list object.
952 The mplist_pop () function pops the topmost property from $PLIST.
953 As a result, the key and value of $PLIST becomes those of the next
957 If the operation was successful, this function return the value of
958 the just popped property. Otherwise, it returns @c NULL. */
961 mplist_pop (MPlist *plist)
966 if (MPLIST_TAIL_P (plist))
968 val = MPLIST_VAL (plist);
970 MPLIST_KEY (plist) = MPLIST_KEY (next);
971 MPLIST_VAL (plist) = MPLIST_VAL (next);
972 if (MPLIST_KEY (plist) != Mnil
973 && MPLIST_KEY (plist)->managing_key
974 && MPLIST_VAL (plist))
975 M17N_OBJECT_REF (MPLIST_VAL (plist));
976 plist->next = next->next;
978 M17N_OBJECT_REF (plist->next);
979 M17N_OBJECT_UNREF (next);
985 @brief Find a property of a specific key in a property list object.
987 The mplist_find_by_key () function searches property list object
988 $PLIST from the beginning for a property whose key is $KEY. If
989 such a property is found, a sublist of $PLIST whose first element
990 is the found one is returned. Otherwise, @c NULL is returned.
992 If $KEY is Mnil, it returns the last a sublist of $PLIST whose
993 first element is the last one of $PLIST. */
996 mplist_find_by_key (MPlist *plist, MSymbol key)
998 MPLIST_FIND (plist, key);
999 return (MPLIST_TAIL_P (plist)
1000 ? (key == Mnil ? plist : NULL)
1006 @brief Find a property of a specific value in a property list object.
1008 The mplist_find_by_value () function searches property list object
1009 $PLIST from the beginning for a property whose value is $VAL. If
1010 such a property is found, a sublist of $PLIST whose first element
1011 is the found one is returned. Otherwise, @c NULL is returned. */
1014 mplist_find_by_value (MPlist *plist, void *val)
1016 MPLIST_DO (plist, plist)
1018 if (MPLIST_VAL (plist) == val)
1027 @brief Return the next sublist of a plist.
1029 The mplist_next () function returns a pointer to the sublist of
1030 $PLIST, which begins at the second element in $PLIST. If the
1031 length of $PLIST is zero, it returns @c NULL. */
1034 mplist_next (MPlist *plist)
1036 return (MPLIST_TAIL_P (plist) ? NULL : plist->next);
1042 @brief Set the first property in a property list object.
1044 The mplist_set () function sets the key and value of the first
1045 property in property list object $PLIST to $KEY and $VALUE,
1046 respectively. See the documentation of mplist_add () for the
1047 restriction on $KEY and $VAL.
1050 If the operation was successful, mplist_set () returns $PLIST.
1051 Otherwise, it returns @c NULL. */
1054 mplist_set (MPlist *plist, MSymbol key, void * val)
1058 if (! MPLIST_TAIL_P (plist))
1060 key = MPLIST_KEY (plist);
1061 M17N_OBJECT_UNREF (MPLIST_NEXT (plist));
1062 MPLIST_KEY (plist) = Mnil;
1063 if (key->managing_key && MPLIST_VAL (plist))
1064 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1070 if (! MPLIST_TAIL_P (plist)
1071 && MPLIST_KEY (plist)->managing_key
1072 && MPLIST_VAL (plist))
1073 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1074 if (key->managing_key)
1075 M17N_OBJECT_REF (val);
1076 MPLIST_SET (plist, key, val);
1084 @brief Return the length of a plist.
1086 The mplist_length () function returns the number of properties in
1087 property list object $PLIST. */
1090 mplist_length (MPlist *plist)
1094 for (n = 0; ! (MPLIST_TAIL_P (plist)); n++, plist = plist->next);
1101 @brief Return the key of the first property in a property list object.
1103 The mplist_key () function returns the key of the first property
1104 in property list object $PLIST. If the length of $PLIST is zero,
1105 it returns @c Mnil. */
1108 mplist_key (MPlist *plist)
1110 return MPLIST_KEY (plist);
1116 @brief Return the value of the first property in a property list object.
1118 The mplist_value () function returns the value of the first
1119 property in property list object $PLIST. If the length of $PLIST
1120 is zero, it returns @c NULL. */
1123 mplist_value (MPlist *plist)
1125 return MPLIST_VAL (plist);
1130 /*** @addtogroup m17nDebug */
1135 @brief Dump a plist.
1137 The mdebug_dump_plist () function prints $PLIST in a human
1138 readable way to the stderr. $INDENT specifies how many columns to
1139 indent the lines but the first one.
1142 This function returns $PLIST. */
1145 mdebug_dump_plist (MPlist *plist, int indent)
1147 char *prefix = (char *) alloca (indent + 1);
1151 memset (prefix, 32, indent);
1154 fprintf (stderr, "(");
1155 MPLIST_DO (pl, plist)
1160 fprintf (stderr, "\n%s ", prefix);
1161 dump_plist_element (pl, indent + 2);
1163 fprintf (stderr, ")");