(msymbol__list): New function.
[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 /** Return a plist of symbols that has non-NULL property PROP.  If
191     PROP is Mnil, return a plist of all symbols.  Values of the plist
192     is NULL.  */
193
194 MPlist *
195 msymbol__list (MSymbol prop)
196 {
197   MPlist *plist = mplist ();
198   int i;
199   MSymbol sym;
200
201   for (i = 0; i < SYMBOL_TABLE_SIZE; i++)
202     for (sym = symbol_table[i]; sym; sym = sym->next)
203       if (prop == Mnil || msymbol_get (sym, prop))
204         mplist_push (plist, sym, NULL);
205   return plist;
206 }
207
208
209 /** Canonicalize the name of SYM, and return a symbol of the
210     canonicalized name.  Canonicalization is done by this rule:
211         o convert all uppercase characters to lowercase.
212         o remove all non alpha-numeric characters.
213         o change the leading "ibm" to "cp".
214         o change the leading "cp" to "ibm"
215         o remove the leading "iso".
216     For instance:
217         "ISO-8859-2" -> "88592"
218         "euc-JP" -> "eucjp"
219         "IBM851" -> "cp851"
220         "CP1250" -> "ibm1250"
221
222     This function is used to canonicalize charset and coding system
223     names.  */
224
225 MSymbol
226 msymbol__canonicalize (MSymbol sym)
227 {
228   char *name = sym->name;
229   /* Extra 2 bytes are for changing "cpXXX" to "ibmXXX" and
230      terminating '\0'.  */
231   char *canon = (char *) alloca (strlen (name) + 2);
232   char *p = canon;
233
234   for (; *name; name++)
235     if (ISALNUM (*name))
236       *p++ = TOLOWER (*name);
237   *p = '\0';
238   if (p - canon > 3 && canon[0] == 'i')
239     {
240       if (canon[1] == 'b' && canon[2] == 'm' && isdigit (canon[3]))
241         {
242           /* Change "ibmXXX" to "cpXXX".  */
243           canon++;
244           canon[0] = 'c';
245           canon[1] = 'p';
246         }
247       else if (canon[1] == 's' && canon[2] == 'o')
248         {
249           /* Change "isoXXX" to "XXX".  */
250           canon += 3;
251         }
252     }
253   else if (p - canon > 2
254            && canon[0] == 'c' && canon[1] == 'p' && isdigit (canon[2]))
255     {
256       /* Change "cpXXX" to "ibmXXX".  */
257       for (; p >= canon + 2; p--)
258         p[1] = p[0];
259       canon[0] = 'i';
260       canon[1] = 'b';
261       canon[2] = 'm';
262     }
263
264   return msymbol (canon);
265 }
266
267 MTextPropSerializeFunc msymbol__serializer = serialize_symbol;
268 MTextPropDeserializeFunc msymbol__deserializer = deserialize_symbol;
269
270 /*** @} */
271 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
272
273 \f
274 /* External API */
275
276 /*** @addtogroup m17nSymbol */
277 /*** @{ */
278
279 /*=*/
280 /***en
281     @brief Symbol whose name is "nil".
282
283     The symbol #Mnil has the name <tt>"nil"</tt> and, in general,
284     represents @e false or @e no.  When coerced to "int", its value is
285     zero.  #Mnil can't have any symbol property.  */
286 /***ja
287     @brief "nil" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë.
288
289     ¥·¥ó¥Ü¥ë #Mnil ¤Ï <tt>"nil"</tt> 
290     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢°ìÈ̤ˡֵ¶¡×¤Þ¤¿¤Ï¡ÖÈÝÄê¡×¤ò°ÕÌ£¤¹¤ë¡£
291     "int" ¤ËÊÑ´¹¤µ¤ì¤¿¾ì¹ç¡¢ÃͤϠ0 ¤Ç¤¢¤ë¡£
292     #Mnil ¼«¿È¤Ï¤¤¤«¤Ê¤ë¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£¤â»ý¤¿¤Ê¤¤¡£  */
293
294 MSymbol Mnil;
295
296 /*=*/
297
298 /***en
299     @brief Symbol whose name is "t".
300
301     The symbol #Mt has the name <tt>"t"</tt> and, in general,
302     represents @e true or @e yes.  */
303 /***ja
304     @brief "t" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë.
305
306     ¥·¥ó¥Ü¥ë #Mt ¤Ï <tt>"t"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢°ìÈ̤ˡֿ¿¡×¤Þ¤¿¤Ï¡Ö¹ÎÄê¡×¤ò°ÕÌ£¤¹¤ë¡£  */
307
308 MSymbol Mt;
309
310 /*=*/
311
312 /***en
313     @brief Symbol whose name is "string".
314
315     The symbol #Mstring has the name <tt>"string"</tt> and is used
316     as an argument of the functions mchar_define_property (),
317     etc.  */
318 /***ja
319     @brief "string" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë.
320
321     ¥·¥ó¥Ü¥ë #Mstring ¤Ï <tt>"string"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢´Ø¿ô 
322     mchar_define_property () ¤Ê¤É¤Î°ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£  */
323
324 MSymbol Mstring;
325
326 /*=*/
327
328 /***en
329     @brief Symbol whose name is "symbol".
330
331     The symbol #Msymbol has the name <tt>"symbol"</tt> and is used
332     as an argument of the functions mchar_define_property (),
333     etc.  */
334 /***ja
335     @brief "symbol" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë.
336
337     ÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë #Msymbol ¤Ï <tt>"symbol"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢´Ø¿ô
338     mchar_define_property () ¤Ê¤É¤Î°ú¿ô¤È¤·¤Æ»È¤ï¤ì¤ë¡£  */
339
340 MSymbol Msymbol;
341
342 /*=*/
343
344 /***en
345     @brief Get a symbol.
346
347     The msymbol () function returns the canonical symbol whose name is
348     $NAME.  If there is none, one is created.  The created one is not
349     a managing key.
350
351     Symbols whose name starts by two spaces are reserved by the m17n
352     library, and are used by the library only internally.
353
354     @return
355     This function returns the found or created symbol.
356
357     @errors
358     This function never fails.  */
359 /***ja
360     @brief ¥·¥ó¥Ü¥ë¤òÆÀ¤ë.
361
362     ´Ø¿ô msymbol () ¤Ï $NAME 
363     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤ÄÀµµ¬²½¤µ¤ì¤¿¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£¤½¤Î¤è¤¦¤Ê¥·¥ó¥Ü¥ë¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢À¸À®¤¹¤ë¡£À¸À®¤µ¤ì¤¿¥·¥ó¥Ü¥ë¤Ï´ÉÍý¥­¡¼¤Ç¤Ï¤Ê¤¤¡£
364
365     ¶õÇòʸ»úÆó¤Ä¤Ç»Ï¤Þ¤ë¥·¥ó¥Ü¥ë¤Ï m17n ¥é¥¤¥Ö¥é¥êÍѤǤ¢¤ê¡¢ÆâÉôŪ¤Ë¤Î¤ßÍѤ¤¤é¤ì¤ë¡£
366
367     @return
368     ¤³¤Î´Ø¿ô¤Ï¸«¤Ä¤±¤¿¤«À¸À®¤·¤¿¤«¤·¤¿¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£
369
370     @errors
371     ¤³¤Î´Ø¿ô¤Ï·è¤·¤Æ¼ºÇÔ¤·¤Ê¤¤¡£
372
373     @latexonly \IPAlabel{msymbol} @endlatexonly  */
374
375 /***
376     @seealso
377     msymbol_as_managing_key (), msymbol_name (), msymbol_exist ()  */
378
379 MSymbol
380 msymbol (const char *name)
381 {
382   MSymbol sym;
383   int len;
384   unsigned hash;
385
386   len = strlen (name);
387   if (len == 3 && name[0] == 'n' && name[1] == 'i' && name[2] == 'l')
388     return Mnil;
389   hash = hash_string (name, len);
390   len++;
391   for (sym = symbol_table[hash]; sym; sym = sym->next)
392     if (len == sym->length
393         && *name == *(sym->name)
394         && ! memcmp (name, sym->name, len))
395       return sym;
396
397   num_symbols++;
398   MTABLE_CALLOC (sym, 1, MERROR_SYMBOL);
399   MTABLE_MALLOC (sym->name, len, MERROR_SYMBOL);
400   memcpy (sym->name, name, len);
401   sym->length = len;
402   sym->next = symbol_table[hash];
403   symbol_table[hash] = sym;
404   return sym;
405 }
406
407 /***en
408     @brief Create a managing key.
409
410     The msymbol_as_managing_key () function returns a newly created
411     managing key whose name is $NAME.  It there already exists a
412     symbol of name $NAME, it returns #Mnil.
413
414     Symbols whose name starts by two spaces are reserved by the m17n
415     library, and are used by the library only internally.
416
417     @return
418     If the operation was successful, this function returns the created
419     symbol.  Otherwise, it returns #Mnil.  */
420 /***ja
421     @brief ´ÉÍý¥­¡¼¤òºî¤ë.
422
423     ´Ø¿ô msymbol_as_managing_key () ¤Ï̾Á° $NAME 
424     ¤ò»ý¤Ä¿·¤·¤¯ºî¤é¤ì¤¿´ÉÍý¥­¡¼¤òÊÖ¤¹¡£¤¹¤Ç¤Ë̾Á° $NAME ¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤¬¤¢¤ì¤Ð¡¢
425     #Mnil ¤òÊÖ¤¹¡£
426
427     ¶õÇòʸ»úÆó¤Ä¤Ç»Ï¤Þ¤ë¥·¥ó¥Ü¥ë¤Ï m17n ¥é¥¤¥Ö¥é¥êÍѤǤ¢¤ê¡¢ÆâÉôŪ¤Ë¤Î¤ßÍѤ¤¤é¤ì¤ë¡£
428
429     @return
430     ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏÀ¸À®¤·¤¿¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð
431     #Mnil ¤òÊÖ¤¹¡£   */
432
433 /***
434     @errors
435     MERROR_SYMBOL
436
437     @seealso
438     msymbol (), msymbol_exist ()  */
439
440 MSymbol
441 msymbol_as_managing_key (const char *name)
442 {
443   MSymbol sym;
444   int len;
445   unsigned hash;
446
447   len = strlen (name);
448   if (len == 3 && name[0] == 'n' && name[1] == 'i' && name[2] == 'l')
449     MERROR (MERROR_SYMBOL, Mnil);
450   hash = hash_string (name, len);
451   len++;
452   for (sym = symbol_table[hash]; sym; sym = sym->next)
453     if (len == sym->length
454         && *name == *(sym->name)
455         && ! memcmp (name, sym->name, len))
456       MERROR (MERROR_SYMBOL, Mnil);
457
458   num_symbols++;
459   MTABLE_CALLOC (sym, 1, MERROR_SYMBOL);
460   sym->managing_key = 1;
461   MTABLE_MALLOC (sym->name, len, MERROR_SYMBOL);
462   memcpy (sym->name, name, len);
463   sym->length = len;
464   sym->next = symbol_table[hash];
465   symbol_table[hash] = sym;
466   return sym;
467 }
468
469 /*=*/
470
471 /***en
472     @brief Search for a symbol that has a specified name.
473
474     The msymbol_exist () function searches for the symbol whose name
475     is $NAME.
476
477     @return
478     If such a symbol exists, msymbol_exist () returns that symbol.
479     Otherwise it returns the predefined symbol #Mnil.
480
481     @errors
482     This function never fails.  */
483 /***ja
484     @brief »ØÄꤵ¤ì¤¿Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤òõ¤¹.
485
486     ´Ø¿ô msymbol_exist () ¤Ï $NAME ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤òõ¤¹¡£
487
488     @return
489     ¤â¤·¤½¤Î¤è¤¦¤Ê¥·¥ó¥Ü¥ë¤¬Â¸ºß¤¹¤ë¤Ê¤é¤Ð¤½¤Î¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢ÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë
490     #Mnil ¤òÊÖ¤¹¡£  
491
492     @errors
493     ¤³¤Î´Ø¿ô¤Ï·è¤·¤Æ¼ºÇÔ¤·¤Ê¤¤¡£     */
494
495 /***@seealso
496     msymbol_name (), msymbol ()  */
497
498 MSymbol
499 msymbol_exist (const char *name)
500 {
501   MSymbol sym;
502   int len;
503   unsigned hash;
504
505   len = strlen (name);
506   if (len == 3 && name[0] == 'n' && name[1] == 'i' && name[2] == 'l')
507     return Mnil;
508   hash = hash_string (name, len);
509   len++;
510   for (sym = symbol_table[hash]; sym; sym = sym->next)
511     if (len == sym->length
512         && *name == *(sym->name)
513         && ! memcmp (name, sym->name, len))
514       return sym;
515   return Mnil;
516 }
517
518 /*=*/
519
520 /***en
521     @brief Get symbol name.
522
523     The msymbol_name () function returns a pointer to a string
524     containing the name of $SYMBOL.
525
526     @errors
527     This function never fails.  */
528 /***ja
529     @brief ¥·¥ó¥Ü¥ë¤Î̾Á°¤òÆÀ¤ë.
530
531     ´Ø¿ô msymbol_name () ¤Ï»ØÄꤵ¤ì¤¿¥·¥ó¥Ü¥ë $SYMBOL 
532     ¤Î̾Á°¤ò´Þ¤àʸ»úÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
533
534     @errors
535     ¤³¤Î´Ø¿ô¤Ï·è¤·¤Æ¼ºÇÔ¤·¤Ê¤¤¡£     */
536
537 /***@seealso
538     msymbol (), msymbol_exist ()  */
539
540 char *
541 msymbol_name (MSymbol symbol)
542 {
543   return (symbol == Mnil ? "nil" : symbol->name);
544 }
545
546 /*=*/
547 /***en
548     @brief Set the value of a symbol property.
549
550     The msymbol_put () function assigns $VAL to the value of the
551     symbol property that belongs to $SYMBOL and whose key is $KEY.  If
552     the symbol property already has a value, $VAL overwrites the old
553     one.  Both $SYMBOL and $KEY must not be #Mnil.
554
555     If $KEY is a managing key, $VAL must be a managed object.  In this
556     case, the reference count of the old value, if not @c NULL, is
557     decremented by one, and that of $VAL is incremented by one.
558
559     @return
560     If the operation was successful, msymbol_put () returns 0.
561     Otherwise it returns -1 and assigns an error code to the external
562     variable #merror_code.  */
563 /***ja
564     @brief ¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£¤ËÃͤòÀßÄꤹ¤ë.
565
566     ´Ø¿ô msymbol_put () ¤Ï¡¢¥·¥ó¥Ü¥ë $SYMBOL Ãæ¤Ç¥­¡¼¤¬ $KEY ¤Ç¤¢¤ë¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£¤ÎÃͤò
567     $VAL ¤ËÀßÄꤹ¤ë¡£¤½¤Î¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£¤Ë¤¹¤Ç¤ËÃͤ¬¤¢¤ì¤Ð¾å½ñ¤­¤¹¤ë¡£
568     $SYMBOL, $KEY ¤È¤â #Mnil ¤Ç¤¢¤Ã¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
569
570     $KEY ¤¬´ÉÍý¥­¡¼¤Ê¤é¤Ð¡¢$VAL ¤Ï´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤³¤Î¾ì¹ç¡¢¸Å¤¤Ãͤλ²¾È¿ô¤Ï
571     @c NULL ¤Ç¤Ê¤±¤ì¤Ð 1 ¸º¤é¤µ¤ì¡¢$VAL ¤Î»²¾È¿ô¤Ï 1 Áý¤ä¤µ¤ì¤ë¡£
572
573     @return
574     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢msymbol_put () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 
575     ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
576
577 /***
578     @errors
579     @c MERROR_SYMBOL
580
581     @seealso
582     msymbol_get () */
583
584 int
585 msymbol_put (MSymbol symbol, MSymbol key, void *val)
586 {
587   if (symbol == Mnil || key == Mnil)
588     MERROR (MERROR_SYMBOL, -1);
589   mplist_put (&symbol->plist, key, val);
590   return 0;
591 }
592
593 /*=*/
594
595 /***en
596     @brief Get the value of a symbol property.
597
598     The msymbol_get () function searches for the value of the symbol
599     property that belongs to $SYMBOL and whose key is $KEY.  If
600     $SYMBOL has such a symbol property, its value is returned.
601     Otherwise @c NULL is returned.
602
603     @return
604     If an error is detected, msymbol_get () returns @c NULL and
605     assigns an error code to the external variable #merror_code.  */
606 /***ja
607     @brief ¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë.
608
609     ´Ø¿ô msymbol_get () ¤Ï¡¢¥·¥ó¥Ü¥ë $SYMBOL 
610     ¤¬»ý¤Ä¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥­¡¼¤¬ $KEY 
611     ¤Ç¤¢¤ë¤â¤Î¤òõ¤¹¡£¤â¤·³ºÅö¤¹¤ë¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£¤¬Â¸ºß¤¹¤ì¤Ð¡¢¤½¤ì¤ÎÃͤòÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð
612     @c NULL ¤òÊÖ¤¹¡£
613
614     @return 
615     ¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¡¢msymbol_get () ¤Ï @c NULL 
616     ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
617
618 /***
619     @errors
620     @c MERROR_SYMBOL
621
622     @seealso
623     msymbol_put () */
624
625 void *
626 msymbol_get (MSymbol symbol, MSymbol key)
627 {
628   MPlist *plist;
629
630   if (symbol == Mnil || key == Mnil)
631     return NULL;
632   plist = &symbol->plist;
633   MPLIST_FIND (plist, key);
634   return (MPLIST_TAIL_P (plist) ? NULL : MPLIST_VAL (plist));
635 }
636
637 /*** @} */
638
639 #include <stdio.h>
640
641 /*** @addtogroup m17nDebug */
642 /*=*/
643 /*** @{ */
644
645 /***en
646     @brief Dump a symbol.
647
648     The mdebug_dump_symbol () function prints symbol $SYMBOL in a human
649     readable way to the stderr.  $INDENT specifies how many columns to
650     indent the lines but the first one.
651
652     @return
653     This function returns $SYMBOL.
654
655     @errors
656     MERROR_DEBUG  */
657 /***ja
658     @brief ¥·¥ó¥Ü¥ë¤ò¥À¥ó¥×¤¹¤ë.
659
660     ´Ø¿ô mdebug_dump_symbol () ¤Ï¥·¥ó¥Ü¥ë $symbol ¤ò stderr 
661     ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£ $INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
662
663     @return
664     ¤³¤Î´Ø¿ô¤Ï $SYMBOL ¤òÊÖ¤¹¡£ 
665
666     @errors
667     MERROR_DEBUG  */
668
669 MSymbol
670 mdebug_dump_symbol (MSymbol symbol, int indent)
671 {
672   char *prefix;
673   MPlist *plist;
674   char *name;
675
676   if (indent < 0)
677     MERROR (MERROR_DEBUG, Mnil);
678   prefix = (char *) alloca (indent + 1);
679   memset (prefix, 32, indent);
680   prefix[indent] = 0;
681
682   if (symbol == Mnil)
683     plist = NULL, name = "nil";
684   else
685     plist = &symbol->plist, name = symbol->name;
686
687   fprintf (stderr, "%s%s", prefix, name);
688   while (plist && MPLIST_KEY (plist) != Mnil)
689     {
690       fprintf (stderr, ":%s", MPLIST_KEY (plist)->name);
691       plist = MPLIST_NEXT (plist);
692     }
693   return symbol;
694 }
695
696 /***en
697     @brief Dump all symbol names.
698
699     The mdebug_dump_all_symbols () function prints names of all
700     symbols to the stderr.  $INDENT specifies how many columns to
701     indent the lines but the first one.
702
703     @return
704     This function returns #Mnil.
705
706     @errors
707     MERROR_DEBUG  */
708 /***ja
709     @brief ¤¹¤Ù¤Æ¤Î¥·¥ó¥Ü¥ë̾¤ò¥À¥ó¥×¤¹¤ë.
710
711     ´Ø¿ô mdebug_dump_all_symbols () ¤Ï¡¢¤¹¤Ù¤Æ¤Î¥·¥ó¥Ü¥ë¤Î̾Á°¤ò 
712     stderr ¤Ë°õºþ¤¹¤ë¡£ $INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
713
714     @return
715     ¤³¤Î´Ø¿ô¤Ï #Mnil ¤òÊÖ¤¹¡£ 
716
717     @errors
718     MERROR_DEBUG  */
719
720
721 MSymbol
722 mdebug_dump_all_symbols (int indent)
723 {
724   char *prefix;
725   int i, n;
726   MSymbol sym;
727
728   if (indent < 0)
729     MERROR (MERROR_DEBUG, Mnil);
730   prefix = (char *) alloca (indent + 1);
731   memset (prefix, 32, indent);
732   prefix[indent] = 0;
733
734   fprintf (stderr, "(symbol-list");
735   for (i = n = 0; i < SYMBOL_TABLE_SIZE; i++)
736     if ((sym = symbol_table[i]))
737       {
738         fprintf (stderr, "\n%s  (%4d", prefix, i);
739         for (; sym; sym = sym->next, n++)
740           fprintf (stderr, " '%s'", sym->name);
741         fprintf (stderr, ")");
742       }
743   fprintf (stderr, "\n%s  (total %d)", prefix, n);
744   fprintf (stderr, ")");
745   return Mnil;
746 }
747
748 /*** @} */ 
749
750 /*
751   Local Variables:
752   coding: euc-japan
753   End:
754 */