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