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 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤È¤½¤ì¤Ë´Ø¤¹¤ë API.
41 @e ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È (¤Þ¤¿¤Ï @e plist) ¤Ï 0 ¸Ä°Ê¾å¤Î¥×¥í¥Ñ¥Æ¥£¤Î¥ê
42 ¥¹¥È¤Ç¤¢¤ë¡£¥×¥í¥Ñ¥Æ¥£¤Ï @e ¥¡¼ ¤È @e ÃÍ ¤«¤é¤Ê¤ë¡£¥¡¼¤Ï¥·¥ó¥Ü¥ë
43 ¤Ç¤¢¤ê¡¢ÃÍ¤Ï <tt>(void *)</tt> ¤Ë¥¥ã¥¹¥È¤Ç¤¤ë¤â¤Î¤Ê¤é¤Ð²¿¤Ç¤âÎÉ
46 ¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤Î¥¡¼¤¬ @e ´ÉÍý¥¡¼ ¤Ê¤é¤Ð¡¢¤½¤Î @e ÃÍ ¤Ï@e ´ÉÍý²¼
47 ¥ª¥Ö¥¸¥§¥¯¥È ¤Ç¤¢¤ë¡£¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¼«ÂΤâ´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢
52 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
53 /*** @addtogroup m17nInternal
61 #include "m17n-misc.h"
63 #include "character.h"
68 static M17NObjectArray plist_table;
70 /** Set PLIST to a newly allocated plist object. */
72 #define MPLIST_NEW(plist) \
74 M17N_OBJECT (plist, free_plist, MERROR_PLIST); \
75 M17N_OBJECT_REGISTER (plist_table, plist); \
79 /** Set the element of PLIST to KEY and VAL. If PLIST is an anchor,
80 append a new anchor. */
82 #define MPLIST_SET(plist, key, val) \
84 MPLIST_KEY (plist) = (key); \
85 MPLIST_VAL (plist) = (val); \
86 if (! (plist)->next) \
87 MPLIST_NEW ((plist)->next); \
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. */
94 #define MPLIST_SET_ADVANCE(plist, key, val) \
96 MPLIST_KEY (plist) = (key); \
97 MPLIST_VAL (plist) = (val); \
98 MPLIST_NEW ((plist)->next); \
99 plist = (plist)->next; \
104 free_plist (void *object)
106 MPlist *plist = (MPlist *) object;
109 MPlist *next = plist->next;
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);
116 } while (plist && plist->control.ref_count == 1);
117 M17N_OBJECT_UNREF (plist);
122 /* Load a plist from a string. */
124 #define READ_CHUNK 0x10000
128 /* File pointer if the stream is associated with a file. Otherwise
132 unsigned char buffer[READ_CHUNK];
133 unsigned char *p, *pend;
137 get_byte (MStream *st)
141 if (! st->fp || st->eof)
143 n = fread (st->buffer, 1, READ_CHUNK, st->fp);
149 st->p = st->buffer + 1;
150 st->pend = st->buffer + n;
151 return st->buffer[0];
155 ((st)->p < (st)->pend ? *(st)->p++ : get_byte (st))
158 #define UNGETC(c, st) \
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
165 unsigned char hex_mnemonic[256];
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];
173 /** Read an integer from the stream ST. It is assumed that we have
174 already read one character C. */
177 read_decimal (MStream *st, int c)
181 while (c >= '0' && c <= '9')
183 num = (num * 10) + (c - '0');
192 /** Read an unsigned from the stream ST. */
195 read_hexadesimal (MStream *st)
200 while ((c = GETC (st)) != EOF
201 && (n = hex_mnemonic[c]) < 16)
202 num = (num << 4) | n;
209 /** Read an M-text element from ST, and add it to LIST. Return a list
210 for the next element. */
213 read_mtext_element (MPlist *plist, MStream *st)
215 unsigned char buffer[1024];
217 unsigned char *buf = buffer;
221 while ((c = GETC (st)) != EOF && c != '"')
223 if (i + MAX_UTF8_CHAR_BYTES >= bufsize)
228 MTABLE_MALLOC (buf, bufsize, MERROR_PLIST);
229 memcpy (buf, buffer, i);
232 MTABLE_REALLOC (buf, bufsize, MERROR_PLIST);
244 c = read_hexadesimal (st);
250 c = escape_mnemonic[c];
256 MPLIST_SET_ADVANCE (plist, Mtext,
257 mtext__from_data (buf, i, MTEXT_FORMAT_UTF_8, 1));
264 read_character (MStream *st, int c)
266 unsigned char buf[MAX_UTF8_CHAR_BYTES + 1];
267 int len = CHAR_BYTES_BY_HEAD (c);
271 for (i = 1; i < len; i++)
275 || (c & 0xC0) != 0x80)
280 c = STRING_CHAR_UTF8 (buf);
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. */
292 read_integer_element (MPlist *plist, MStream *st, int c)
296 if (c == '0' || c == '#')
300 num = read_hexadesimal (st);
302 num = read_decimal (st, c);
311 if (c < 128 || ! CHAR_UNITS_BY_HEAD_UTF8 (c))
314 num = read_character (st, c);
321 else if (c < 128 || ! CHAR_UNITS_BY_HEAD_UTF8 (c))
322 num = escape_mnemonic[c];
324 num = read_character (st, c);
328 num = - read_decimal (st, GETC (st));
330 num = read_decimal (st, c);
332 MPLIST_SET_ADVANCE (plist, Minteger, (void *) num);
336 /** Read a symbol element from ST, and add it to LIST. Return a list
337 for the next element. */
340 read_symbol_element (MPlist *plist, MStream *st)
342 unsigned char buffer[1024];
344 unsigned char *buf = buffer;
348 while ((c = GETC (st)) != EOF
350 && c != ')' && c != '(' && c != '"')
357 MTABLE_MALLOC (buf, bufsize, MERROR_PLIST);
358 memcpy (buf, buffer, i);
361 MTABLE_REALLOC (buf, bufsize, MERROR_PLIST);
368 c = escape_mnemonic[c];
374 MPLIST_SET_ADVANCE (plist, Msymbol, msymbol ((char *) buf));
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:
387 '0'..'9', '-': integer
388 '?': integer representing character code
389 the other ASCII letters: symbol
393 read_element (MPlist *plist, MStream *st)
397 /* Skip separators and comments. */
400 while ((c = GETC (st)) != EOF && c <= ' ');
403 while ((c = GETC (st)) != EOF && c != '\n');
414 while ((p = read_element (p, st)));
415 MPLIST_SET_ADVANCE (plist, Mplist, pl);
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 == ')')
425 return read_symbol_element (plist, st);
429 write_element (MText *mt, MPlist *plist)
431 if (MPLIST_SYMBOL_P (plist))
433 MSymbol sym = MPLIST_SYMBOL (plist);
437 MTEXT_CAT_ASCII (mt, "nil");
441 char *name = MSYMBOL_NAME (sym);
442 char *buf = alloca (MSYMBOL_NAMELEN (sym) * 2 + 1), *p = buf;
446 if (*name <= ' ' || *name == '"' || *name == ')' || *name == ')')
451 MTEXT_CAT_ASCII (mt, buf);
454 else if (MPLIST_INTEGER_P (plist))
456 int num = MPLIST_INTEGER (plist);
459 sprintf (buf, "%d", num);
460 MTEXT_CAT_ASCII (mt, buf);
462 else if (MPLIST_PLIST_P (plist))
466 plist = MPLIST_PLIST (plist);
467 mtext_cat_char (mt, '(');
468 MPLIST_DO (pl, plist)
471 mtext_cat_char (mt, ' ');
472 write_element (mt, pl);
474 mtext_cat_char (mt, ')');
476 else if (MPLIST_MTEXT_P (plist))
478 mtext_cat_char (mt, '"');
479 /* Not yet implemnted */
480 mtext_cat_char (mt, '"');
484 /* Support functions for mdebug_dump_plist. */
487 dump_string (char *str)
489 char *p = str, *pend = p + strlen (p), *new, *p1;
491 new = p1 = alloca ((pend - p) * 4 + 1);
496 sprintf (p1, "\\x%02X", (unsigned char) *p);
514 fprintf (stderr, "%s", new);
518 dump_plist_element (MPlist *plist, int indent)
520 char *prefix = (char *) alloca (indent + 1);
523 memset (prefix, 32, indent);
526 key = MPLIST_KEY (plist);
527 fprintf (stderr, "(%s(#%d) ", msymbol_name (MPLIST_KEY (plist)),
528 plist->control.ref_count);
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)
539 fprintf (stderr, "\n%s", prefix);
540 mdebug_dump_plist (MPLIST_PLIST (plist), indent);
543 fprintf (stderr, "0x%X", (unsigned) MPLIST_VAL (plist));
544 fprintf (stderr, ")");
554 plist_table.count = 0;
556 Minteger = msymbol ("integer");
557 Mplist = msymbol_as_managing_key ("plist");
558 Mtext = msymbol_as_managing_key ("mtext");
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['\\'] = '\\';
584 mdebug__report_object ("Plist", &plist_table);
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 ...) */
594 mplist__from_plist (MPlist *plist)
600 while (! MPLIST_TAIL_P (plist))
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);
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. */
624 mplist__from_alist (MPlist *plist)
630 MPLIST_DO (plist, plist)
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));
647 mplist__from_file (FILE *fp)
654 st.p = st.pend = st.buffer;
657 while ((pl = read_element (pl, &st)));
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.
667 The syntax of $STR is as follows.
669 PLIST ::= '(' ELEMENT * ')'
671 ELEMENT ::= SYMBOL | INTEGER | UNSIGNED | STRING | M-TEXT | PLIST
673 SYMBOL ::= ascii-character-sequence
675 INTEGER ::= '-' ? [ '0' | .. | '9' ]+
677 UNSIGNED ::= '0x' [ '0' | .. | '9' | 'A' | .. | 'F' | 'a' | .. | 'f' ]+
679 M-TEXT ::= '"' byte-sequence '"'
681 Each kind of @c ELEMENT is assigned one of these keys:
682 @c Msymbol, @c Mint, @c Munsigned, @c Mtext, @c Mplist
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.
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. */
695 mplist__from_string (unsigned char *str, int n)
706 while ((pl = read_element (pl, &st)));
711 mplist__serialize (MText *mt, MPlist *plist)
715 MPLIST_DO (pl, plist)
718 mtext_cat_char (mt, ' ');
719 write_element (mt, pl);
725 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
730 /*** @addtogroup m17nPlist */
735 @brief Symbol whose name is "integer".
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. */
740 @brief "integer" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë.
742 ¥·¥ó¥Ü¥ë @c Minteger ¤Ï <tt>"integer"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¡£¥¡¼¤¬
743 @c Minteger ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ÎÃͤÏÀ°¿ôÃͤǤʤ¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ */
749 @brief Symbol whose name is "plist".
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
755 @brief "plist" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë.
757 ¥·¥ó¥Ü¥ë @c Mplist ¤Ï <tt>"plist"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¡£¤³¤ì¤Ï´É
758 Íý¥¡¼¤Ç¤¢¤ë¡£¥¡¼¤¬ @c Mplist ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ÎÃÍ¤Ï plist ¤Ç¤Ê¤¯
765 @brief Symbol whose name is "mtext".
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
772 @brief "mtext" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë.
774 ¥·¥ó¥Ü¥ë @c Mtext ¤Ï <tt>"mtext"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä´ÉÍý¥¡¼¤Ç¤¢
775 ¤ë¡£¥¡¼¤¬ @c Mtext ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ÎÃÍ¤Ï M-text ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê
782 @brief Create a property list object.
784 The mplist () function returns a newly created property list
785 object of length zero.
788 This function returns a newly created property list.
791 This function never fails. */
793 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤ë.
795 ´Ø¿ô mplist () ¤ÏŤµ 0 ¤Î¿·¤·¤¯ºî¤é¤ì¤¿¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥ª¥Ö¥¸¥§¥¯
799 ¤³¤Î´Ø¿ô¤Ï¿·¤·¤¯ºî¤é¤ì¤¿¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹¡£
802 ¤³¤Î´Ø¿ô¤Ï·è¤·¤Æ¼ºÇÔ¤·¤Ê¤¤¡£ */
815 @brief Copy a property list.
817 The mplist_copy () function copies property list $PLIST. In the
818 copy, the values are the same as those of $PLIST.
821 This function returns a newly created plist which is a copy of
825 This function never fails. */
827 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò¥³¥Ô¡¼¤¹¤ë.
829 ´Ø¿ô mplist_copy () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò¥³¥Ô¡¼¤¹¤ë¡£¥³¥Ô¡¼¤Î¤¹¤Ù¤Æ¤Î
830 Ãͤϥ³¥Ô¡¼¸µ $PLIST ¤ÎÃͤÈƱ¤¸¤Ç¤¢¤ë¡£
833 ¤³¤Î´Ø¿ô¤Ï¿·¤·¤¯ºî¤é¤ì¤¿¡¢$PLIST ¤Î¥³¥Ô¡¼¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤òÊÖ¤¹¡£
836 ¤³¤Î´Ø¿ô¤Ï·è¤·¤Æ¼ºÇÔ¤·¤Ê¤¤¡£ */
839 mplist_copy (MPlist *plist)
841 MPlist *copy = mplist (), *pl = copy;
843 MPLIST_DO (plist, plist)
844 pl = mplist_add (pl, MPLIST_KEY (plist), MPLIST_VAL (plist));
851 @brief Set the value of a property in a property list.
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.
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.
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. */
869 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃæ¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÀßÄꤹ¤ë.
871 ´Ø¿ô mplist_put () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò»Ï¤á¤«¤éõ¤·¤Æ¡¢¥¡¼
872 ¤¬ $KEY ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤ÎÃͤò $VALUE ¤Ë
873 Êѹ¹¤¹¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¥¡¼¤¬ $KEY ¤ÇÃͤ¬ $VALUE ¤Ç¤¢¤ë¿·¤·¤¤
874 ¥×¥í¥Ñ¥Æ¥£¤¬$PLIST ¤ÎËöÈø¤ËÄɲ䵤ì¤ë¡£$KEY ¤È $VAL ¤ËÂФ¹¤ëÀ©¸Â¤Ë
875 ¤Ä¤¤¤Æ¤Ï¡¢mplist_add () ¤ÎÀâÌÀ¤ò»²¾È¡£
877 $KEY ¤¬´ÉÍý¥¡¼¤Ê¤é¤Ð¡¢$VAL ¤Ï´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
878 ¤³¤Î¾ì¹ç¡¢¸Å¤¤Ãͤλ²¾È¿ô¤Ï @c NULL ¤Ç¤Ê¤±¤ì¤Ð 1 ¸º¤é¤µ¤ì¡¢$VAL ¤Î
879 »²¾È¿ô¤Ï 1 Áý¤ä¤µ¤ì¤ë¡£
882 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mplist_put () ¤ÏÊѹ¹¤µ¤ì¤¿¤«Äɲ䵤줿Í×ÁǤ«¤é»Ï
883 ¤Þ¤ë $PLIST ¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£ */
886 mplist_put (MPlist *plist, MSymbol key, void *val)
889 MERROR (MERROR_PLIST, NULL);
890 MPLIST_FIND (plist, key);
891 if (key->managing_key)
893 if (! MPLIST_TAIL_P (plist))
894 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
895 M17N_OBJECT_REF (val);
897 MPLIST_SET (plist, key, val);
904 @brief Get the value of a property in a property list.
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.
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 ()
917 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃæ¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë.
919 ´Ø¿ô mplist_get () ¤Ï¡¢¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò»Ï¤á¤«¤éõ¤·¤Æ¡¢
920 ¥¡¼¤¬ $KEY ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤ÎÃͤؤΥݥ¤
921 ¥ó¥¿¤ò <tt>(void *)</tt> ·¿¤ÇÊÖ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£
923 @c NULL ¤¬Ê֤俺ݤˤÏÆó¤Ä¤Î²ÄǽÀ¤¬¤¢¤ë:¾åµ¤Î¤è¤¦¤Ë¥×¥í¥Ñ¥Æ¥£¤¬
924 ¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¤È¡¢¥×¥í¥Ñ¥Æ¥£¤¬¸«¤Ä¤«¤ê¡¢¤½¤ÎÃͤ¬ @c NULL ¤Ç
925 ¤¢¤ë¾ì¹ç¤Ç¤¢¤ë¡£¤³¤ì¤é¤ò¶èÊ̤¹¤ëɬÍפ¬¤¢¤ë¾ì¹ç¤Ë¤Ï´Ø¿ô
926 mplist_find_by_key () ¤ò»È¤¦¤³¤È¡£ */
930 mplist_find_by_key () */
933 mplist_get (MPlist *plist, MSymbol key)
935 MPLIST_FIND (plist, key);
936 return (MPLIST_TAIL_P (plist) ? NULL : MPLIST_VAL (plist));
942 @brief Add a property at the end of a property list.
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.
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.
952 If the operation was successful, mplist_add () returns a sublist of
953 $PLIST whose first element is the just added one. Otherwise, it
956 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈËöÈø¤Ë¥×¥í¥Ñ¥Æ¥£¤òÄɲ乤ë.
958 ´Ø¿ô mplist_add () ¤Ï¡¢¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ÎËöÈø¤Ë¥¡¼¤¬ $KEY
959 ¤ÇÃͤ¬ $VAL ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤òÄɲ乤롣$KEY ¤Ï¡¢@c Mnil °Ê³°¤ÎǤ
962 $KEY ¤¬´ÉÍý¥¡¼¤Ê¤é¤Ð¡¢$VAL ¤Ï´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
963 ¤³¤Î¾ì¹ç¡¢$VAL ¤Î»²¾È¿ô¤Ï 1 Áý¤ä¤µ¤ì¤ë¡£
966 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mplist_add () ¤ÏÄɲ䵤줿Í×ÁǤ«¤é»Ï¤Þ¤ë $PLIST
967 ¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£ */
970 mplist_add (MPlist *plist, MSymbol key, void *val)
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);
986 @brief Add a property at the beginning of a property list.
988 The mplist_push () function inserts at the beginning of property
989 list $PLIST a property whose key is $KEY and value is $VAL.
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.
995 If the operation was successful, this function returns $PLIST.
996 Otherwise, it returns @c NULL. */
998 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ÎÀèƬ¤Ë¥×¥í¥Ñ¥Æ¥£¤òÁÞÆþ¤¹¤ë.
1000 ´Ø¿ô mplist_push () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ÎÀèƬ¤Ë¥¡¼¤¬ $KEY
1001 ¤ÇÃͤ¬ $VAL ¤Ç¤¢¤ë¥ª¥Ö¥¸¥§¥¯¥È¤òÁÞÆþ¤¹¤ë¡£
1003 $KEY ¤¬´ÉÍý¥¡¼¤Ê¤é¤Ð¡¢$VAL ¤Ï´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
1004 ¤³¤Î¾ì¹ç¡¢$VAL ¤Î»²¾È¿ô¤Ï 1 Áý¤ä¤µ¤ì¤ë¡£
1007 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¤³¤Î´Ø¿ô¤Ï $PLIST ¤òÊÖ¤·¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð@c NULL ¤ò
1011 mplist_push (MPlist *plist, MSymbol key, void *val)
1016 MERROR (MERROR_PLIST, NULL);
1018 MPLIST_KEY (pl) = MPLIST_KEY (plist);
1019 MPLIST_VAL (pl) = MPLIST_VAL (plist);
1020 MPLIST_NEXT (pl) = MPLIST_NEXT (plist);
1022 if (key->managing_key)
1023 M17N_OBJECT_REF (val);
1024 MPLIST_KEY (plist) = key;
1025 MPLIST_VAL (plist) = val;
1032 @brief Remove a property at the beginning of a property list.
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.
1039 If the operation was successful, this function return the value of
1040 the just popped property. Otherwise, it returns @c NULL. */
1042 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ÎÀèƬ¤«¤é¥×¥í¥Ñ¥Æ¥£¤òºï½ü¤¹¤ë.
1044 ´Ø¿ô mplist_pop () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ÎÀèƬ¤Î¥×¥í¥Ñ¥Æ¥£¤ò
1045 ºï½ü¤¹¤ë¡£·ë²Ì¤È¤·¤Æ¡¢¸µ¤Î $PLIST ¤Î2ÈÖÌܤΥ¡¼¤ÈÃͤ¬¡¢¿·¤·¤¤
1046 $PLIST ¤ÎÀèƬ¤Î¥¡¼¤ÈÃͤˤʤ롣
1049 ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ïºï½ü¤µ¤ì¤¿¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹¡£¤½¤¦
1050 ¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£ */
1053 mplist_pop (MPlist *plist)
1058 if (MPLIST_TAIL_P (plist))
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);
1070 M17N_OBJECT_REF (plist->next);
1071 M17N_OBJECT_UNREF (next);
1077 @brief Find a property of a specific key in a property list.
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.
1084 If $KEY is @c Mnil, it returns a sublist of $PLIST whose
1085 first element is the last one of $PLIST. */
1087 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃ椫¤é»ØÄê¤Î¥¡¼¤ò»ý¤Ä¥×¥í¥Ñ¥Æ¥£¤òõ¤¹.
1089 ´Ø¿ô mplist_find_by_key () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò»Ï¤á¤«¤éõ
1090 ¤·¤Æ¡¢¥¡¼¤¬ $KEY ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤Î¥×¥í
1091 ¥Ñ¥Æ¥£¤«¤é»Ï¤Þ¤ë $PLIST ¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð@c NULL
1094 $KEY ¤¬ @c Mnil ¤Ê¤é¤Ð¡¢$PLIST ¤ÎºÇ¸å¤ÎÍ×ÁǤ«¤é»Ï¤Þ¤ëÉôʬ¥ê¥¹¥È¤ò
1098 mplist_find_by_key (MPlist *plist, MSymbol key)
1100 MPLIST_FIND (plist, key);
1101 return (MPLIST_TAIL_P (plist)
1102 ? (key == Mnil ? plist : NULL)
1108 @brief Find a property of a specific value in a property list.
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. */
1115 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃ椫¤é»ØÄê¤ÎÃͤò»ý¤Ä¥×¥í¥Ñ¥Æ¥£¤òõ¤¹.
1117 ´Ø¿ô mplist_find_by_value () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò»Ï¤á¤«¤é
1118 õ¤·¤Æ¡¢Ãͤ¬ $VAL ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤Î¥×¥í
1119 ¥Ñ¥Æ¥£¤«¤é»Ï¤Þ¤ë $PLIST ¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð@c NULL
1123 mplist_find_by_value (MPlist *plist, void *val)
1125 MPLIST_DO (plist, plist)
1127 if (MPLIST_VAL (plist) == val)
1136 @brief Return the next sublist of a property list.
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. */
1142 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Î¼¡¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹.
1144 ´Ø¿ô mplist_next () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤Î£²ÈÖÌÜ
1145 ¤ÎÍ×ÁǤ«¤é»Ï¤Þ¤ëÉôʬ¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£$PLIST ¤ÎŤµ¤¬ 0 ¤Ê
1146 ¤é¤Ð @c NULL ¤òÊÖ¤¹¡£ */
1149 mplist_next (MPlist *plist)
1151 return (MPLIST_TAIL_P (plist) ? NULL : plist->next);
1157 @brief Set the first property in a property list.
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
1165 If the operation was successful, mplist_set () returns $PLIST.
1166 Otherwise, it returns @c NULL. */
1168 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤òÀßÄꤹ¤ë.
1170 ´Ø¿ô mplist_set () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤Î
1171 ¥¡¼¤ÈÃͤò¤½¤ì¤¾¤ì $KEY ¤È $VALUE ¤ËÀßÄꤹ¤ë¡£$KEY ¤È $VAL ¤ËÂФ¹
1172 ¤ëÀ©¸Â¤Ë¤Ä¤¤¤Æ¤Ï¡¢mplist_add () ¤ÎÀâÌÀ¤ò»²¾È¡£
1175 ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mplist_set () ¤Ï $PLIST ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð
1179 mplist_set (MPlist *plist, MSymbol key, void * val)
1183 if (! MPLIST_TAIL_P (plist))
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));
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);
1209 @brief Return the length of a property list.
1211 The mplist_length () function returns the number of properties in
1212 property list $PLIST. */
1214 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ÎŤµ¤òÊÖ¤¹.
1216 ´Ø¿ô mplist_length () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST Ãæ¤Î¥×¥í¥Ñ¥Æ¥£¤Î¿ô
1220 mplist_length (MPlist *plist)
1224 for (n = 0; ! (MPLIST_TAIL_P (plist)); n++, plist = plist->next);
1231 @brief Return the key of the first property in a property list.
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. */
1237 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃæ¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤Î¥¡¼¤òÊÖ¤¹.
1239 ´Ø¿ô mplist_key () ¤Ï¡¢¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST Ãæ¤ÎºÇ
1240 ½é¤Î¥×¥í¥Ñ¥Æ¥£¤Î¥¡¼¤òÊÖ¤¹¡£$PLIST ¤ÎŤµ¤¬ 0 ¤Ê¤é¤Ð¡¢ @c Mnil ¤ò
1244 mplist_key (MPlist *plist)
1246 return MPLIST_KEY (plist);
1252 @brief Return the value of the first property in a property list.
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. */
1258 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃæ¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹.
1260 ´Ø¿ô mplist_value () ¤Ï¡¢¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST Ãæ¤Î
1261 ºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹¡£$PLIST ¤ÎŤµ¤¬ 0 ¤Ê¤é¤Ð¡¢ @c Mnil ¤ò
1265 mplist_value (MPlist *plist)
1267 return MPLIST_VAL (plist);
1271 @brief Generate a property list by deserializaing an M-text.
1273 The mplist_deserialize () function parses M-text $MT and returns a
1276 The syntax of $MT is as follows.
1278 MT ::= '(' ELEMENT * ')'
1280 ELEMENT ::= SYMBOL | INTEGER | M-TEXT | PLIST
1282 SYMBOL ::= ascii-character-sequence
1284 INTEGER ::= '-' ? [ '0' | .. | '9' ]+
1285 | '0x' [ '0' | .. | '9' | 'A' | .. | 'F' | 'a' | .. | 'f' ]+
1287 M-TEXT ::= '"' character-sequence '"'
1289 Each alternatives of @c ELEMENT is assigned one of these keys: @c
1290 Msymbol, @c Minteger, @c Mtext, @c Mplist
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. */
1297 @brief M-text ¤ò¥Ç¥·¥ê¥¢¥é¥¤¥º¤·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤òºî¤ë.
1299 ´Ø¿ô mplist_deserialize () ¤Ï M-text $MT ¤ò²òÀϤ·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹
1302 $MT ¤Î¥·¥ó¥¿¥Ã¥¯¥¹¤Ï°Ê²¼¤ÎÄ̤ꡣ
1304 MT ::= '(' ELEMENT * ')'
1306 ELEMENT ::= SYMBOL | INTEGER | M-TEXT | PLIST
1308 SYMBOL ::= ¥¢¥¹¥¡¼Ê¸»úÎó
1310 INTEGER ::= '-' ? [ '0' | .. | '9' ]+
1311 | '0x' [ '0' | .. | '9' | 'A' | .. | 'F' | 'a' | .. | 'f' ]+
1313 M-TEXT ::= '"' character-sequence '"'
1315 @c ELEMENT ¤Î³ÆÁªÂò»è¤Ï¥¡¼¡§@c Msymbol, @c Minteger, @c Mtext,
1316 @c Mplist ¤Î¤¤¤º¤ì¤«¤ò³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¡£
1318 ¥¢¥¹¥¡¼Ê¸»úÎóÆâ¤Ç¤Ï¡¢¥Ð¥Ã¥¯¥¹¥é¥Ã¥·¥å (\) ¤¬¥¨¥¹¥±¡¼¥×ʸ»ú¤È¤·¤Æ
1319 ÍѤ¤¤é¤ì¤ë¡£¤¿¤È¤¨¤Ð <tt>"abc\ def"</tt> ¤Ï£´Ê¸»úÌܤ¬¶õÇòʸ»ú¤Ç¤¢
1320 ¤êŤµ¤¬£·¤Ç¤¢¤ë»ý¤Ä̾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤òÀ¸À®¤¹¤ë¡£ */
1323 mplist_deserialize (MText *mt)
1328 if (mt->format > MTEXT_FORMAT_UTF_8)
1330 if (MTEXT_READ_ONLY_P (mt))
1331 mt = tmp = mtext_cpy (mtext (), mt);
1333 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
1335 plist = mplist__from_string (MTEXT_DATA (mt), mtext_nbytes (mt));
1337 M17N_OBJECT_UNREF (tmp);
1343 /*** @addtogroup m17nDebug */
1348 @brief Dump a property list.
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.
1355 This function returns $PLIST. */
1357 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò¥À¥ó¥×¤¹¤ë.
1359 ´Ø¿ô mdebug_dump_plist () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò stderr ¤Ë¿Í
1360 ´Ö¤Ë²ÄÆÉ¤Ê ·Á¤Ç°õºþ¤¹¤ë¡£ $UNDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ
1364 ¤³¤Î´Ø¿ô¤Ï $PLIST ¤òÊÖ¤¹¡£ */
1366 mdebug_dump_plist (MPlist *plist, int indent)
1368 char *prefix = (char *) alloca (indent + 1);
1372 memset (prefix, 32, indent);
1375 fprintf (stderr, "(");
1376 MPLIST_DO (pl, plist)
1381 fprintf (stderr, "\n%s ", prefix);
1382 dump_plist_element (pl, indent + 2);
1384 fprintf (stderr, ")");