(m17n_object): Be sure to initialize all members.
[m17n/m17n-lib.git] / src / symbol.c
1 /* symbol.c -- symbol 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 m17nSymbol
25
26     @brief Symbol objects and API for them.
27
28     The m17n library uses objects called @e symbols as unambiguous
29     identifiers.  Symbols are similar to atoms in the X library, but a
30     symbol can have zero or more @e symbol @e properties.  A symbol
31     property consists of a @e key and a @e value, where key is also a
32     symbol and value is anything that can be cast to <tt>(void *)</tt>.  
33     "The symbol property that belongs to the symbol S and
34     whose key is K" may be shortened to "K property of S".
35
36     Symbols are used mainly in the following three ways.
37
38     @li As keys of symbol properties and other properties.
39
40     @li To represent various objects, e.g. charsets, coding systems,
41     fontsets.
42
43     @li As arguments of the m17n library functions to control
44     their behavior.
45
46     There is a special kind of symbol, a @e managing @e key.  The
47     value of a property whose key is a managing key must be a @e
48     managed @e object.  See @ref m17nObject for the detail.
49 */
50 /***ja
51     @addtogroup m17nSymbol ¥·¥ó¥Ü¥ë
52
53     @brief ¥·¥ó¥Ü¥ë¥ª¥Ö¥¸¥§¥¯¥È¤È¤½¤ì¤Ë´Ø¤¹¤ë API.
54
55     m17n ¥é¥¤¥Ö¥é¥ê¤Ï°ì°Õ¤Ë·è¤Þ¤ë¼±Ê̻ҤȤ·¤Æ @e ¥·¥ó¥Ü¥ë 
56     ¤È¸Æ¤Ö¥ª¥Ö¥¸¥§¥¯¥È¤òÍѤ¤¤ë¡£¥·¥ó¥Ü¥ë¤Ï X ¥é¥¤¥Ö¥é¥ê¤Î¥¢¥È¥à¤È»÷¤Æ¤¤¤ë¤¬¡¢
57     0 ¸Ä°Ê¾å¤Î @e ¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£ ¤ò»ý¤Ä¤³¤È¤¬¤Ç¤­¤ë¡£¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£¤Ï
58     @e ¥­¡¼ ¤È @e ÃÍ ¤«¤é¤Ê¤ë¡£¥­¡¼¤Ï¤½¤ì¼«ÂÎ¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢ÃͤϠ
59     <tt>(void *)</tt> ·¿¤Ë¥­¥ã¥¹¥È¤Ç¤­¤ë¤â¤Î¤Ê¤é²¿¤Ç¤â¤è¤¤¡£¡Ö¥·¥ó¥Ü¥ë 
60     S ¤¬»ý¤Ä¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¥­¡¼¤¬ K ¤Î¤â¤Î¡×¤ò´Êñ¤Ë¡ÖS ¤Î K 
61     ¥×¥í¥Ñ¥Æ¥£¡×¤È¸Æ¤Ö¤³¤È¤¬¤¢¤ë¡£
62
63     ¥·¥ó¥Ü¥ë¤ÎÍÑÅӤϼç¤Ë°Ê²¼¤Î3Ä̤ê¤Ç¤¢¤ë¡£
64
65     @li ¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£¤ª¤è¤Ó¾¤Î¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤òɽ¤¹¡£
66
67     @li Ê¸»ú¥»¥Ã¥È¡¢¥³¡¼¥É·Ï¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Ê¤É¤Î³Æ¼ï¥ª¥Ö¥¸¥§¥¯¥È¤òɽ¤¹¡£
68
69     @li m17n ¥é¥¤¥Ö¥é¥ê´Ø¿ô¤Î°ú¿ô¤È¤Ê¤ê¡¢´Ø¿ô¤ÎµóÆ°¤òÀ©¸æ¤¹¤ë¡£
70
71     @e ´ÉÍý¥­¡¼ ¤È¸Æ¤Ð¤ì¤ëÆÃÊ̤ʥ·¥ó¥Ü¥ë¤¬¤¢¤ê¡¢´ÉÍý¥­¡¼¤ò¥­¡¼¤È¤·¤Æ»ý¤Ä¥×¥í¥Ñ¥Æ¥£¤ÎÃͤÏ
72     @e ´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ï @ref m17nObject »²¾È¡£
73 */
74
75 /*=*/
76
77 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
78 /*** @addtogroup m17nInternal
79      @{ */
80
81 #include <config.h>
82 #include <stdlib.h>
83 #include <string.h>
84 #include <ctype.h>
85
86 #include "m17n.h"
87 #include "m17n-misc.h"
88 #include "internal.h"
89 #include "symbol.h"
90 #include "character.h"
91 #include "mtext.h"
92 #include "plist.h"
93
94 static int num_symbols;
95
96 #define SYMBOL_TABLE_SIZE 1024
97
98 static MSymbol symbol_table[SYMBOL_TABLE_SIZE];
99
100 static unsigned
101 hash_string (const char *str, int len)
102 {
103   unsigned hash = 0;
104   const char *end = str + len;
105   unsigned c;
106
107   while (str < end)
108     {
109       c = *((unsigned char *) str++);
110       if (c >= 0140)
111         c -= 40;
112       hash = ((hash << 3) + (hash >> 28) + c);
113     }
114   return hash & (SYMBOL_TABLE_SIZE - 1);
115 }
116
117
118 static MPlist *
119 serialize_symbol (void *val)
120 {
121   MPlist *plist = mplist ();
122
123   mplist_add (plist, Msymbol, val);
124   return plist;
125 }
126
127 static void *
128 deserialize_symbol (MPlist *plist)
129 {
130   return (MPLIST_SYMBOL_P (plist) ? MPLIST_SYMBOL (plist) : Mnil);
131 }
132
133 \f
134 /* Internal API */
135
136 int
137 msymbol__init ()
138 {
139   num_symbols = 0;
140   Mnil = (MSymbol) 0;
141   Mt = msymbol ("t");
142   Msymbol = msymbol ("symbol");
143   Mstring = msymbol ("string");
144   return 0;
145 }
146
147 void
148 msymbol__fini ()
149 {
150   int i;
151   MSymbol sym, next;
152   int freed_symbols = 0;
153
154   for (i = 0; i < SYMBOL_TABLE_SIZE; i++)
155     for (sym = symbol_table[i]; sym; sym = sym->next)
156       if (! MPLIST_TAIL_P (&sym->plist))
157         {
158           if (sym->plist.key->managing_key)
159             M17N_OBJECT_UNREF (sym->plist.val);
160           M17N_OBJECT_UNREF (sym->plist.next);
161         }
162   for (i = 0; i < SYMBOL_TABLE_SIZE; i++)
163     {
164       for (sym = symbol_table[i]; sym; sym = next)
165         {
166           next = sym->next;
167           free (sym->name);
168           free (sym);
169           freed_symbols++;
170         }
171       symbol_table[i] = NULL;
172     }
173   if (mdebug__flag & MDEBUG_FINI)
174     fprintf (stderr, "%16s %7d %7d %7d\n", "Symbol",
175              num_symbols, freed_symbols, num_symbols - freed_symbols);
176   num_symbols = 0;
177 }
178
179
180 MSymbol
181 msymbol__with_len (const char *name, int len)
182 {
183   char *p = alloca (len + 1);
184
185   memcpy (p, name, len);
186   p[len] = '\0';
187   return msymbol (p);
188 }
189
190
191 /** Canonicalize the name of SYM, and return a symbol of the
192     canonicalized name.  Canonicalization is done by this rule:
193         o convert all uppercase characters to lowercase.
194         o remove all non alpha-numeric characters.
195         o change the leading "ibm" to "cp".
196         o change the leading "cp" to "ibm"
197         o remove the leading "iso".
198     For instance:
199         "ISO-8859-2" -> "88592"
200         "euc-JP" -> "eucjp"
201         "IBM851" -> "cp851"
202         "CP1250" -> "ibm1250"
203
204     This function is used to canonicalize charset and coding system
205     names.  */
206
207 MSymbol
208 msymbol__canonicalize (MSymbol sym)
209 {
210   char *name = sym->name;
211   /* Extra 2 bytes are for changing "cpXXX" to "ibmXXX" and
212      terminating '\0'.  */
213   char *canon = (char *) alloca (strlen (name) + 2);
214   char *p = canon;
215
216   for (; *name; name++)
217     if (ISALNUM (*name))
218       *p++ = TOLOWER (*name);
219   *p = '\0';
220   if (p - canon > 3 && canon[0] == 'i')
221     {
222       if (canon[1] == 'b' && canon[2] == 'm' && isdigit (canon[3]))
223         {
224           /* Change "ibmXXX" to "cpXXX".  */
225           canon++;
226           canon[0] = 'c';
227           canon[1] = 'p';
228         }
229       else if (canon[1] == 's' && canon[2] == 'o')
230         {
231           /* Change "isoXXX" to "XXX".  */
232           canon += 3;
233         }
234     }
235   else if (p - canon > 2
236            && canon[0] == 'c' && canon[1] == 'p' && isdigit (canon[2]))
237     {
238       /* Change "cpXXX" to "ibmXXX".  */
239       for (; p >= canon + 2; p--)
240         p[1] = p[0];
241       canon[0] = 'i';
242       canon[1] = 'b';
243       canon[2] = 'm';
244     }
245
246   return msymbol (canon);
247 }
248
249 MTextPropSerializeFunc msymbol__serializer = serialize_symbol;
250 MTextPropDeserializeFunc msymbol__deserializer = deserialize_symbol;
251
252 /*** @} */
253 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
254
255 \f
256 /* External API */
257
258 /*** @addtogroup m17nSymbol */
259 /*** @{ */
260
261 /*=*/
262 /***en
263     @brief Symbol whose name is "nil".
264
265     The symbol #Mnil has the name <tt>"nil"</tt> and, in general,
266     represents @e false or @e no.  When coerced to "int", its value is
267     zero.  #Mnil can't have any symbol property.  */
268 /***ja
269     @brief "nil" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë.
270
271     ¥·¥ó¥Ü¥ë #Mnil ¤Ï <tt>"nil"</tt> 
272     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢°ìÈ̤ˡֵ¶¡×¤Þ¤¿¤Ï¡ÖÈÝÄê¡×¤ò°ÕÌ£¤¹¤ë¡£
273     "int" ¤ËÊÑ´¹¤µ¤ì¤¿¾ì¹ç¡¢ÃͤϠ0 ¤Ç¤¢¤ë¡£
274     #Mnil ¼«¿È¤Ï¤¤¤«¤Ê¤ë¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£¤â»ý¤¿¤Ê¤¤¡£  */
275
276 MSymbol Mnil;
277
278 /*=*/
279
280 /***en
281     @brief Symbol whose name is "t".
282
283     The symbol #Mt has the name <tt>"t"</tt> and, in general,
284     represents @e true or @e yes.  */
285 /***ja
286     @brief "t" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë.
287
288     ¥·¥ó¥Ü¥ë #Mt ¤Ï <tt>"t"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢°ìÈ̤ˡֿ¿¡×¤Þ¤¿¤Ï¡Ö¹ÎÄê¡×¤ò°ÕÌ£¤¹¤ë¡£  */
289
290 MSymbol Mt;
291
292 /*=*/
293
294 /***en
295     @brief Symbol whose name is "string".
296
297     The symbol #Mstring has the name <tt>"string"</tt> and is used
298     as an argument of the functions mchar_define_property (),
299     etc.  */
300 /***ja
301     @brief "string" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë.
302
303     ¥·¥ó¥Ü¥ë #Mstring ¤Ï <tt>"string"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢´Ø¿ô 
304     mchar_define_property () ¤Ê¤É¤Î°ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£  */
305
306 MSymbol Mstring;
307
308 /*=*/
309
310 /***en
311     @brief Symbol whose name is "symbol".
312
313     The symbol #Msymbol has the name <tt>"symbol"</tt> and is used
314     as an argument of the functions mchar_define_property (),
315     etc.  */
316 /***ja
317     @brief "symbol" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë.
318
319     ÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë #Msymbol ¤Ï <tt>"symbol"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢´Ø¿ô
320     mchar_define_property () ¤Ê¤É¤Î°ú¿ô¤È¤·¤Æ»È¤ï¤ì¤ë¡£  */
321
322 MSymbol Msymbol;
323
324 /*=*/
325
326 /***en
327     @brief Get a symbol.
328
329     The msymbol () function returns the canonical symbol whose name is
330     $NAME.  If there is none, one is created.  The created one is not
331     a managing key.
332
333     Symbols whose name starts by two spaces are reserved by the m17n
334     library, and are used by the library only internally.
335
336     @return
337     This function returns the found or created symbol.
338
339     @errors
340     This function never fails.  */
341 /***ja
342     @brief ¥·¥ó¥Ü¥ë¤òÆÀ¤ë.
343
344     ´Ø¿ô msymbol () ¤Ï $NAME 
345     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤ÄÀµµ¬²½¤µ¤ì¤¿¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£¤½¤Î¤è¤¦¤Ê¥·¥ó¥Ü¥ë¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢À¸À®¤¹¤ë¡£À¸À®¤µ¤ì¤¿¥·¥ó¥Ü¥ë¤Ï´ÉÍý¥­¡¼¤Ç¤Ï¤Ê¤¤¡£
346
347     ¶õÇòʸ»úÆó¤Ä¤Ç»Ï¤Þ¤ë¥·¥ó¥Ü¥ë¤Ï m17n ¥é¥¤¥Ö¥é¥êÍѤǤ¢¤ê¡¢ÆâÉôŪ¤Ë¤Î¤ßÍѤ¤¤é¤ì¤ë¡£
348
349     @return
350     ¤³¤Î´Ø¿ô¤Ï¸«¤Ä¤±¤¿¤«À¸À®¤·¤¿¤«¤·¤¿¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£
351
352     @errors
353     ¤³¤Î´Ø¿ô¤Ï·è¤·¤Æ¼ºÇÔ¤·¤Ê¤¤¡£
354
355     @latexonly \IPAlabel{msymbol} @endlatexonly  */
356
357 /***
358     @seealso
359     msymbol_as_managing_key (), msymbol_name (), msymbol_exist ()  */
360
361 MSymbol
362 msymbol (const char *name)
363 {
364   MSymbol sym;
365   int len;
366   unsigned hash;
367
368   len = strlen (name);
369   if (len == 3 && name[0] == 'n' && name[1] == 'i' && name[2] == 'l')
370     return Mnil;
371   hash = hash_string (name, len);
372   len++;
373   for (sym = symbol_table[hash]; sym; sym = sym->next)
374     if (len == sym->length
375         && *name == *(sym->name)
376         && ! memcmp (name, sym->name, len))
377       return sym;
378
379   num_symbols++;
380   MTABLE_CALLOC (sym, 1, MERROR_SYMBOL);
381   MTABLE_MALLOC (sym->name, len, MERROR_SYMBOL);
382   memcpy (sym->name, name, len);
383   sym->length = len;
384   sym->next = symbol_table[hash];
385   symbol_table[hash] = sym;
386   return sym;
387 }
388
389 /***en
390     @brief Create a managing key.
391
392     The msymbol_as_managing_key () function returns a newly created
393     managing key whose name is $NAME.  It there already exists a
394     symbol of name $NAME, it returns #Mnil.
395
396     Symbols whose name starts by two spaces are reserved by the m17n
397     library, and are used by the library only internally.
398
399     @return
400     If the operation was successful, this function returns the created
401     symbol.  Otherwise, it returns #Mnil.  */
402 /***ja
403     @brief ´ÉÍý¥­¡¼¤òºî¤ë.
404
405     ´Ø¿ô msymbol_as_managing_key () ¤Ï̾Á° $NAME 
406     ¤ò»ý¤Ä¿·¤·¤¯ºî¤é¤ì¤¿´ÉÍý¥­¡¼¤òÊÖ¤¹¡£¤¹¤Ç¤Ë̾Á° $NAME ¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤¬¤¢¤ì¤Ð¡¢
407     #Mnil ¤òÊÖ¤¹¡£
408
409     ¶õÇòʸ»úÆó¤Ä¤Ç»Ï¤Þ¤ë¥·¥ó¥Ü¥ë¤Ï m17n ¥é¥¤¥Ö¥é¥êÍѤǤ¢¤ê¡¢ÆâÉôŪ¤Ë¤Î¤ßÍѤ¤¤é¤ì¤ë¡£
410
411     @return
412     ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏÀ¸À®¤·¤¿¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð
413     #Mnil ¤òÊÖ¤¹¡£   */
414
415 /***
416     @errors
417     MERROR_SYMBOL
418
419     @seealso
420     msymbol (), msymbol_exist ()  */
421
422 MSymbol
423 msymbol_as_managing_key (const char *name)
424 {
425   MSymbol sym;
426   int len;
427   unsigned hash;
428
429   len = strlen (name);
430   if (len == 3 && name[0] == 'n' && name[1] == 'i' && name[2] == 'l')
431     MERROR (MERROR_SYMBOL, Mnil);
432   hash = hash_string (name, len);
433   len++;
434   for (sym = symbol_table[hash]; sym; sym = sym->next)
435     if (len == sym->length
436         && *name == *(sym->name)
437         && ! memcmp (name, sym->name, len))
438       MERROR (MERROR_SYMBOL, Mnil);
439
440   num_symbols++;
441   MTABLE_CALLOC (sym, 1, MERROR_SYMBOL);
442   sym->managing_key = 1;
443   MTABLE_MALLOC (sym->name, len, MERROR_SYMBOL);
444   memcpy (sym->name, name, len);
445   sym->length = len;
446   sym->next = symbol_table[hash];
447   symbol_table[hash] = sym;
448   return sym;
449 }
450
451 /*=*/
452
453 /***en
454     @brief Search for a symbol that has a specified name.
455
456     The msymbol_exist () function searches for the symbol whose name
457     is $NAME.
458
459     @return
460     If such a symbol exists, msymbol_exist () returns that symbol.
461     Otherwise it returns the predefined symbol #Mnil.
462
463     @errors
464     This function never fails.  */
465 /***ja
466     @brief »ØÄꤵ¤ì¤¿Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤òõ¤¹.
467
468     ´Ø¿ô msymbol_exist () ¤Ï $NAME ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤òõ¤¹¡£
469
470     @return
471     ¤â¤·¤½¤Î¤è¤¦¤Ê¥·¥ó¥Ü¥ë¤¬Â¸ºß¤¹¤ë¤Ê¤é¤Ð¤½¤Î¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢ÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë
472     #Mnil ¤òÊÖ¤¹¡£  
473
474     @errors
475     ¤³¤Î´Ø¿ô¤Ï·è¤·¤Æ¼ºÇÔ¤·¤Ê¤¤¡£     */
476
477 /***@seealso
478     msymbol_name (), msymbol ()  */
479
480 MSymbol
481 msymbol_exist (const char *name)
482 {
483   MSymbol sym;
484   int len;
485   unsigned hash;
486
487   len = strlen (name);
488   if (len == 3 && name[0] == 'n' && name[1] == 'i' && name[2] == 'l')
489     return Mnil;
490   hash = hash_string (name, len);
491   len++;
492   for (sym = symbol_table[hash]; sym; sym = sym->next)
493     if (len == sym->length
494         && *name == *(sym->name)
495         && ! memcmp (name, sym->name, len))
496       return sym;
497   return Mnil;
498 }
499
500 /*=*/
501
502 /***en
503     @brief Get symbol name.
504
505     The msymbol_name () function returns a pointer to a string
506     containing the name of $SYMBOL.
507
508     @errors
509     This function never fails.  */
510 /***ja
511     @brief ¥·¥ó¥Ü¥ë¤Î̾Á°¤òÆÀ¤ë.
512
513     ´Ø¿ô msymbol_name () ¤Ï»ØÄꤵ¤ì¤¿¥·¥ó¥Ü¥ë $SYMBOL 
514     ¤Î̾Á°¤ò´Þ¤àʸ»úÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
515
516     @errors
517     ¤³¤Î´Ø¿ô¤Ï·è¤·¤Æ¼ºÇÔ¤·¤Ê¤¤¡£     */
518
519 /***@seealso
520     msymbol (), msymbol_exist ()  */
521
522 char *
523 msymbol_name (MSymbol symbol)
524 {
525   return (symbol == Mnil ? "nil" : symbol->name);
526 }
527
528 /*=*/
529 /***en
530     @brief Set the value of a symbol property.
531
532     The msymbol_put () function assigns $VAL to the value of the
533     symbol property that belongs to $SYMBOL and whose key is $KEY.  If
534     the symbol property already has a value, $VAL overwrites the old
535     one.  Both $SYMBOL and $KEY must not be #Mnil.
536
537     If $KEY is a managing key, $VAL must be a managed object.  In this
538     case, the reference count of the old value, if not @c NULL, is
539     decremented by one, and that of $VAL is incremented by one.
540
541     @return
542     If the operation was successful, msymbol_put () returns 0.
543     Otherwise it returns -1 and assigns an error code to the external
544     variable #merror_code.  */
545 /***ja
546     @brief ¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£¤ËÃͤòÀßÄꤹ¤ë.
547
548     ´Ø¿ô msymbol_put () ¤Ï¡¢¥·¥ó¥Ü¥ë $SYMBOL Ãæ¤Ç¥­¡¼¤¬ $KEY ¤Ç¤¢¤ë¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£¤ÎÃͤò
549     $VAL ¤ËÀßÄꤹ¤ë¡£¤½¤Î¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£¤Ë¤¹¤Ç¤ËÃͤ¬¤¢¤ì¤Ð¾å½ñ¤­¤¹¤ë¡£
550     $SYMBOL, $KEY ¤È¤â #Mnil ¤Ç¤¢¤Ã¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
551
552     $KEY ¤¬´ÉÍý¥­¡¼¤Ê¤é¤Ð¡¢$VAL ¤Ï´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤³¤Î¾ì¹ç¡¢¸Å¤¤Ãͤλ²¾È¿ô¤Ï
553     @c NULL ¤Ç¤Ê¤±¤ì¤Ð 1 ¸º¤é¤µ¤ì¡¢$VAL ¤Î»²¾È¿ô¤Ï 1 Áý¤ä¤µ¤ì¤ë¡£
554
555     @return
556     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢msymbol_put () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 
557     ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
558
559 /***
560     @errors
561     @c MERROR_SYMBOL
562
563     @seealso
564     msymbol_get () */
565
566 int
567 msymbol_put (MSymbol symbol, MSymbol key, void *val)
568 {
569   if (symbol == Mnil || key == Mnil)
570     MERROR (MERROR_SYMBOL, -1);
571   mplist_put (&symbol->plist, key, val);
572   return 0;
573 }
574
575 /*=*/
576
577 /***en
578     @brief Get the value of a symbol property.
579
580     The msymbol_get () function searches for the value of the symbol
581     property that belongs to $SYMBOL and whose key is $KEY.  If
582     $SYMBOL has such a symbol property, its value is returned.
583     Otherwise @c NULL is returned.
584
585     @return
586     If an error is detected, msymbol_get () returns @c NULL and
587     assigns an error code to the external variable #merror_code.  */
588 /***ja
589     @brief ¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë.
590
591     ´Ø¿ô msymbol_get () ¤Ï¡¢¥·¥ó¥Ü¥ë $SYMBOL 
592     ¤¬»ý¤Ä¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥­¡¼¤¬ $KEY 
593     ¤Ç¤¢¤ë¤â¤Î¤òõ¤¹¡£¤â¤·³ºÅö¤¹¤ë¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£¤¬Â¸ºß¤¹¤ì¤Ð¡¢¤½¤ì¤ÎÃͤòÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð
594     @c NULL ¤òÊÖ¤¹¡£
595
596     @return 
597     ¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¡¢msymbol_get () ¤Ï @c NULL 
598     ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
599
600 /***
601     @errors
602     @c MERROR_SYMBOL
603
604     @seealso
605     msymbol_put () */
606
607 void *
608 msymbol_get (MSymbol symbol, MSymbol key)
609 {
610   MPlist *plist;
611
612   if (symbol == Mnil || key == Mnil)
613     return NULL;
614   plist = &symbol->plist;
615   MPLIST_FIND (plist, key);
616   return (MPLIST_TAIL_P (plist) ? NULL : MPLIST_VAL (plist));
617 }
618
619 /*** @} */
620
621 #include <stdio.h>
622
623 /*** @addtogroup m17nDebug */
624 /*=*/
625 /*** @{ */
626
627 /***en
628     @brief Dump a symbol.
629
630     The mdebug_dump_symbol () function prints symbol $SYMBOL in a human
631     readable way to the stderr.  $INDENT specifies how many columns to
632     indent the lines but the first one.
633
634     @return
635     This function returns $SYMBOL.
636
637     @errors
638     MERROR_DEBUG  */
639 /***ja
640     @brief ¥·¥ó¥Ü¥ë¤ò¥À¥ó¥×¤¹¤ë.
641
642     ´Ø¿ô mdebug_dump_symbol () ¤Ï¥·¥ó¥Ü¥ë $symbol ¤ò stderr 
643     ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£ $INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
644
645     @return
646     ¤³¤Î´Ø¿ô¤Ï $SYMBOL ¤òÊÖ¤¹¡£ 
647
648     @errors
649     MERROR_DEBUG  */
650
651 MSymbol
652 mdebug_dump_symbol (MSymbol symbol, int indent)
653 {
654   char *prefix;
655   MPlist *plist;
656   char *name;
657
658   if (indent < 0)
659     MERROR (MERROR_DEBUG, Mnil);
660   prefix = (char *) alloca (indent + 1);
661   memset (prefix, 32, indent);
662   prefix[indent] = 0;
663
664   if (symbol == Mnil)
665     plist = NULL, name = "nil";
666   else
667     plist = &symbol->plist, name = symbol->name;
668
669   fprintf (stderr, "%s%s", prefix, name);
670   while (plist && MPLIST_KEY (plist) != Mnil)
671     {
672       fprintf (stderr, ":%s", MPLIST_KEY (plist)->name);
673       plist = MPLIST_NEXT (plist);
674     }
675   return symbol;
676 }
677
678 /***en
679     @brief Dump all symbol names.
680
681     The mdebug_dump_all_symbols () function prints names of all
682     symbols to the stderr.  $INDENT specifies how many columns to
683     indent the lines but the first one.
684
685     @return
686     This function returns #Mnil.
687
688     @errors
689     MERROR_DEBUG  */
690 /***ja
691     @brief ¤¹¤Ù¤Æ¤Î¥·¥ó¥Ü¥ë̾¤ò¥À¥ó¥×¤¹¤ë.
692
693     ´Ø¿ô mdebug_dump_all_symbols () ¤Ï¡¢¤¹¤Ù¤Æ¤Î¥·¥ó¥Ü¥ë¤Î̾Á°¤ò 
694     stderr ¤Ë°õºþ¤¹¤ë¡£ $INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
695
696     @return
697     ¤³¤Î´Ø¿ô¤Ï #Mnil ¤òÊÖ¤¹¡£ 
698
699     @errors
700     MERROR_DEBUG  */
701
702
703 MSymbol
704 mdebug_dump_all_symbols (int indent)
705 {
706   char *prefix;
707   int i;
708   MSymbol sym;
709
710   if (indent < 0)
711     MERROR (MERROR_DEBUG, Mnil);
712   prefix = (char *) alloca (indent + 1);
713   memset (prefix, 32, indent);
714   prefix[indent] = 0;
715
716   fprintf (stderr, "(symbol-list");
717   for (i = 0; i < SYMBOL_TABLE_SIZE; i++)
718     if ((sym = symbol_table[i]))
719       {
720         fprintf (stderr, "\n%s  (%4d", prefix, i);
721         for (; sym; sym = sym->next)
722           fprintf (stderr, " '%s'", sym->name);
723         fprintf (stderr, ")");
724       }
725   fprintf (stderr, ")");
726   return Mnil;
727 }
728
729 /*** @} */ 
730
731 /*
732   Local Variables:
733   coding: euc-japan
734   End:
735 */