1 /* database.c -- database 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
24 @addtogroup m17nDatabase
25 @brief The m17n database and API for it.
27 The m17n library dynamically acquires various kinds of information
28 in need from data in the <i> m17n database</i>. Application
29 programs can also add/load their original data to/from the m17n
30 database. The m17n database contains multiple heterogeneous data,
31 and each data is identified by four tags; TAG0, TAG1, TAG2, TAG3.
32 Each tag must be a symbol.
34 TAG0 specifies the type of data stored in the database as below.
37 If TAG0 is #Mchar_table, the data is of the @e chartable @e
38 type and provides information about each character. In this case,
39 TAG1 specifies the type of the information and must be #Msymbol,
40 #Minteger, #Mstring, #Mtext, or #Mplist. TAG2 and TAG3 can be any
44 If TAG0 is #Mcharset, the data is of the @e charset @e type
45 and provides a decode/encode mapping table for a charset. In this
46 case, TAG1 must be a symbol representing a charset. TAG2 and TAG3
50 If TAG0 is neither #Mchar_table nor #Mcharset, the data is of
51 the @e plist @e type. See the documentation of the
52 mdatabase_load () function for the details.
53 In this case, TAG1, TAG2, and TAG3 can be any symbols.
55 The notation \<TAG0, TAG1, TAG2, TAG3\> means a data with those
58 Application programs first calls the mdatabase_find () function to
59 get a pointer to an object of the type #MDatabase. That object
60 holds information about the specified data. When it is
61 successfully returned, the mdatabase_load () function loads the
62 data. The implementation of the structure #MDatabase is
63 concealed from application programs.
67 @addtogroup m17nDatabase
68 @brief m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤È¤½¤ì¤Ë´Ø¤¹¤ë API.
70 m17n ¥é¥¤¥Ö¥é¥ê¤ÏɬÍפ˱þ¤¸¤ÆưŪ¤Ë @e m17n @e ¥Ç¡¼¥¿¥Ù¡¼¥¹
71 ¤«¤é¾ðÊó¤ò¼èÆÀ¤¹¤ë¡£¤Þ¤¿¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤âÆȼ«¤Î¥Ç¡¼¥¿¤ò
72 m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ËÄɲä·¡¢¤½¤ì¤òưŪ¤Ë¼èÆÀ¤¹¤ë¤³¤È¤¬¤Ç¤¤ë¡£m17n
73 ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤ÏÊ£¿ô¤Î¿Íͤʥǡ¼¥¿¤¬´Þ¤Þ¤ì¤Æ¤ª¤ê¡¢³Æ¥Ç¡¼¥¿¤Ï
74 TAG0, TAG1, TAG2, TAG3¡Ê¤¹¤Ù¤Æ¥·¥ó¥Ü¥ë¡Ë¤Î£´¤Ä¤Î¥¿¥°¤Ë¤è¤Ã¤Æ¼±Ê̤µ¤ì¤ë¡£
76 TAG0 ¤Ë¤è¤Ã¤Æ¡¢¥Ç¡¼¥¿¥Ù¡¼¥¹Æâ¤Î¥Ç¡¼¥¿¤Î¥¿¥¤¥×¤Ï¼¡¤Î¤è¤¦¤Ë»ØÄꤵ¤ì¤ë¡£
79 TAG0 ¤¬ #Mchar_table ¤Ç¤¢¤ë¥Ç¡¼¥¿¤Ï @e chartable¥¿¥¤¥×
80 ¤È¸Æ¤Ð¤ì¡¢³Æʸ»ú¤Ë´Ø¤¹¤ë¾ðÊó¤òÄ󶡤¹¤ë¡£¤³¤Î¾ì¹ç
81 TAG1 ¤Ï¾ðÊó¤Î¼ïÎà¤ò»ØÄꤹ¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢#Msymbol, #Minteger, #Mstring,
82 #Mtext, #Mplist ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£TAG2 ¤È TAG3 ¤ÏǤ°Õ¤Î¥·¥ó¥Ü¥ë¤Ç¤è¤¤¡£
85 TAG0 ¤¬ #Mcharset ¤Ç¤¢¤ë¥Ç¡¼¥¿¤Ï @e charset¥¿¥¤¥×
86 ¤È¸Æ¤Ð¤ì¡¢Ê¸»ú¥»¥Ã¥ÈÍѤΥǥ³¡¼¥É¡¿¥¨¥ó¥³¡¼¥É¥Þ¥Ã¥×¤òÄ󶡤¹¤ë¡£¤³¤Î¾ì¹ç TAG1
87 ¤Ïʸ»ú¥»¥Ã¥È¤Î¥·¥ó¥Ü¥ë¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£TAG2 ¤È TAG3
88 ¤ÏǤ°Õ¤Î¥·¥ó¥Ü¥ë¤Ç¤è¤¤¡£
91 TAG0 ¤¬ #Mchar_table ¤Ç¤â #Mcharset ¤Ç¤â¤Ê¤¤¾ì¹ç¡¢¤½¤Î¥Ç¡¼¥¿¤Ï @e
92 plist¥¿¥¤¥× ¤Ç¤¢¤ë¡£¾ÜºÙ¤Ë´Ø¤·¤Æ¤Ï´Ø¿ô mdatabase_load ()
93 ¤ÎÀâÌÀ¤ò»²¾È¤Î¤³¤È¡£¤³¤Î¾ì¹ç TAG1¡¢TAG2¡¢TAG3 ¤ÏǤ°Õ¤Î¥·¥ó¥Ü¥ë¤Ç¤è¤¤¡£
95 ÆÃÄê¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò \<TAG0, TAG1, TAG2, TAG3\>
98 ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï¡¢¤Þ¤º´Ø¿ô mdatabase_find ()
99 ¤ò»È¤Ã¤Æ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÝ»ý¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¡Ê#MDatabase
100 ·¿¡Ë¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÆÀ¤ë¡£¤½¤ì¤ËÀ®¸ù¤·¤¿¤é¡¢ mdatabase_load ()
101 ¤Ë¤è¤Ã¤Æ¼ÂºÝ¤Ë¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¥í¡¼¥É¤¹¤ë¡£¹½Â¤ÂÎ #MDatabase
102 ¼«¿È¤¬¤É¤¦¼ÂÁõ¤µ¤ì¤Æ¤¤¤ë¤«¤Ï¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤«¤é¤Ï¸«¤¨¤Ê¤¤¡£
104 @latexonly \IPAlabel{database} @endlatexonly
109 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
110 /*** @addtogroup m17nInternal
118 #include <sys/types.h>
119 #include <sys/stat.h>
124 #include "m17n-misc.h"
125 #include "internal.h"
127 #include "character.h"
129 #include "database.h"
133 /** The file containing a list of databases. */
134 #define MDB_DIR "mdb.dir"
135 #define MDB_DIR_LEN 8
137 /** Structure for a data in the m17n database. */
141 /** Tags to identify the data. <tag>[0] specifies the type of
142 database. If it is #Mchar_table, the type is @e chartable, if
143 it is #Mcharset, the type is @e charset, otherwise the type is
147 void *(*loader) (MSymbol *tags, void *extra_info);
149 /** The meaning of the value is dependent on <loader>. If <loader>
150 is load_database (), the value is a string of the file name that
151 contains the data. */
155 /** List of all data. */
162 static struct MDatabaseList mdb_list;
166 read_number (char *buf, int *i)
175 while (c && isspace (c)) c = buf[idx++];
181 for (idx++, c = 0; (n = hex_mnemonic[(unsigned) buf[idx]]) < 16;
195 n = escape_mnemonic[c];
199 while (buf[idx] && buf[idx++] != '\'');
203 else if (hex_mnemonic[c] < 10)
208 while ((n = hex_mnemonic[(unsigned) buf[idx]]) < 10)
209 c = (c * 10) + n, idx++;
215 /** Load a data of type @c chartable from the file FD, and return the
216 newly created chartable. */
219 load_chartable (FILE *fp, MSymbol type)
227 MERROR (MERROR_DB, NULL);
229 table = mchartable (type, (type == Msymbol ? (void *) Mnil
230 : type == Minteger ? (void *) -1
237 for (len = 0; len < 1023 && (c = getc (fp)) != EOF && c != '\n'; len++)
240 if (hex_mnemonic[(unsigned) buf[0]] >= 10)
241 /* skip comment/invalid line */
244 from = read_number (buf, &i);
246 i++, to = read_number (buf, &i);
249 if (from < 0 || to < from)
252 while (buf[i] && isspace ((unsigned) buf[i])) i++;
259 /* VAL is a C-string. */
260 if (! (val = strdup (buf + i)))
261 MEMORY_FULL (MERROR_DB);
263 else if (type == Minteger)
265 /* VAL is an integer. */
271 n = read_number (buf, &i);
274 val = (void *) (n * positive);
276 else if (type == Mtext)
278 /* VAL is an M-text. */
281 mt = mconv_decode_buffer (Mcoding_utf_8,
282 (unsigned char *) (buf + i),
287 while ((c = read_number (buf, &i)) >= 0)
288 mt = mtext_cat_char (mt, c);
292 else if (type == Msymbol)
296 while (*p && ! isspace (*p))
298 if (*p == '\\' && p[1] != '\0')
300 memmove (p, p + 1, buf + len - (p + 1));
306 if (! strcmp (buf + i, "nil"))
309 val = (void *) msymbol (buf + i);
311 else if (type == Mplist)
313 val = (void *) mplist__from_string ((unsigned char *) buf + i,
320 mchartable_set (table, from, val);
322 mchartable_set_range (table, from, to, val);
327 M17N_OBJECT_UNREF (table);
328 MERROR (MERROR_DB, NULL);
332 /** Load a data of type @c charset from the file FD. */
335 load_charset (FILE *fp, MSymbol charset_name)
337 MCharset *charset = MCHARSET (charset_name);
346 MERROR (MERROR_DB, NULL);
347 size = (charset->code_range[15]
348 - (charset->min_code - charset->code_range_min_code));
349 MTABLE_MALLOC (decoder, size, MERROR_DB);
350 for (i = 0; i < size; i++)
352 encoder = mchartable (Minteger, (void *) MCHAR_INVALID_CODE);
354 while ((c = getc (fp)) != EOF)
356 unsigned code1, code2, c1, c2;
361 fgets (buf, 256, fp);
364 if (sscanf (buf, "0x%x-0x%x 0x%x", &code1, &code2, &c1) == 3)
366 idx1 = CODE_POINT_TO_INDEX (charset, code1);
369 idx2 = CODE_POINT_TO_INDEX (charset, code2);
372 c2 = c1 + (idx2 - idx1);
374 else if (sscanf (buf, "0x%x 0x%x", &code1, &c1) == 2)
376 idx1 = idx2 = CODE_POINT_TO_INDEX (charset, code1);
383 if (idx1 >= 0 && idx2 >= 0)
386 mchartable_set (encoder, c1, (void *) code1);
387 for (idx1++, c1++; idx1 <= idx2; idx1++, c1++)
389 code1 = INDEX_TO_CODE_POINT (charset, idx1);
391 mchartable_set (encoder, c1, (void *) code1);
401 M17N_OBJECT_UNREF (encoder);
405 mplist_add (plist, Mt, decoder);
406 mplist_add (plist, Mt, encoder);
411 gen_database_name (char *buf, MSymbol *tags)
415 strcpy (buf, msymbol_name (tags[0]));
416 for (i = 1; i < 4; i++)
419 strcat (buf, msymbol_name (tags[i]));
425 get_database_stream (char *filename)
429 if (filename[0] == '/')
430 fp = fopen (filename, "r");
435 int filelen = strlen (filename);
438 MPLIST_DO (plist, mdatabase__dir_list)
440 int require = strlen ((char *) MPLIST_VAL (plist)) + filelen + 1;
442 SAFE_ALLOCA (path, require);
443 strcpy (path, (char *) MPLIST_VAL (plist));
444 strcat (path, filename);
445 fp = fopen (path, "r");
455 load_database (MSymbol *tags, void *extra_info)
457 FILE *fp = get_database_stream ((char *) extra_info);
461 MERROR (MERROR_DB, NULL);
463 if (tags[0] == Mchar_table)
464 value = load_chartable (fp, tags[1]);
465 else if (tags[0] == Mcharset)
466 value = load_charset (fp, tags[1]);
468 value = mplist__from_file (fp, NULL);
472 MERROR (MERROR_DB, NULL);
477 /** Copy DIRNAME to a newly allocated memory and return it. If
478 DIRNAME does not end with a slash, append a slash to the new memory. */
481 duplicate_dirname (char *dirname)
488 || stat (dirname, &buf) < 0)
491 len = strlen (dirname);
492 MTABLE_MALLOC (str, len + 2, MERROR_DB);
493 memcpy (str, dirname, len + 1);
494 if (str[len - 1] != '/')
505 /** List of database directories. */
506 MPlist *mdatabase__dir_list;
508 MSymbol M_database_hook;
520 Mchar_table = msymbol ("char-table");
521 M_database_hook = msymbol (" database-hook");
523 mdatabase__dir_list = mplist ();
524 /** The macro M17NDIR specifies a directory where the system-wide
525 MDB_DIR file exists. */
526 if ((dir = duplicate_dirname (M17NDIR)))
527 mplist_set (mdatabase__dir_list, Mt, dir);
529 /* The variable mdatabase_dir specifies a directory where an
530 application program specific MDB_DIR file exists. */
531 if ((dir = duplicate_dirname (mdatabase_dir)))
532 mplist_push (mdatabase__dir_list, Mt, dir);
534 /* The environment variable M17NDIR (if non-NULL) specifies a
535 directory where a user specific MDB_DIR file exists. */
536 if ((dir = duplicate_dirname (getenv ("M17NDIR"))))
537 mplist_push (mdatabase__dir_list, Mt, dir);
539 MLIST_INIT1 (&mdb_list, mdbs, 256);
540 MPLIST_DO (plist, mdatabase__dir_list)
545 dir = (char *) MPLIST_VAL (plist);
548 if (len + MDB_DIR_LEN >= PATH_MAX)
550 #endif /* PATH_MAX */
551 SAFE_ALLOCA (path, len + MDB_DIR_LEN);
552 memcpy (path, dir, len);
553 memcpy (path + len, MDB_DIR, MDB_DIR_LEN);
554 if (! (fp = fopen (path, "r")))
556 pl = mplist__from_file (fp, NULL);
567 if (! MPLIST_PLIST_P (p))
569 for (i = 0, p1 = MPLIST_PLIST (p);
570 i < 4 && MPLIST_KEY (p1) == Msymbol;
571 i++, p1 = MPLIST_NEXT (p1))
572 mdb.tag[i] = MPLIST_SYMBOL (p1);
574 || ! MPLIST_MTEXT_P (p1))
578 if (mdatabase_find (mdb.tag[0], mdb.tag[1],
579 mdb.tag[2], mdb.tag[3]))
582 mdb.loader = load_database;
583 mt = MPLIST_MTEXT (p1);
584 if (mt->format >= MTEXT_FORMAT_UTF_16LE)
585 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
586 nbytes = mtext_nbytes (mt);
588 if (nbytes > PATH_MAX)
590 #endif /* PATH_MAX */
591 SAFE_ALLOCA (path, nbytes + 1);
592 memcpy (path, mt->data, nbytes);
594 mdb.extra_info = (void *) strdup (path);
595 if (! mdb.extra_info)
596 MEMORY_FULL (MERROR_DB);
597 MLIST_APPEND1 (&mdb_list, mdbs, mdb, MERROR_DB);
599 M17N_OBJECT_UNREF (pl);
604 mdatabase__finder = ((void *(*) (MSymbol, MSymbol, MSymbol, MSymbol))
606 mdatabase__loader = (void *(*) (void *)) mdatabase_load;
612 mdatabase__fini (void)
617 MPLIST_DO (plist, mdatabase__dir_list)
618 free (MPLIST_VAL (plist));
619 M17N_OBJECT_UNREF (mdatabase__dir_list);
621 for (i = 0; i < mdb_list.used; i++)
623 MDatabase *mdb = mdb_list.mdbs + i;
625 if (mdb->loader == load_database)
626 free (mdb->extra_info);
628 MLIST_FREE1 (&mdb_list, mdbs);
632 mdatabase__load_for_keys (MDatabase *mdb, MPlist *keys)
634 int mdebug_mask = MDEBUG_DATABASE;
639 if (mdb->loader != load_database
640 || mdb->tag[0] == Mchar_table
641 || mdb->tag[0] == Mcharset)
642 MERROR (MERROR_DB, NULL);
643 MDEBUG_PRINT1 (" [DATABASE] loading <%s>.\n",
644 gen_database_name (buf, mdb->tag));
645 fp = get_database_stream ((char *) mdb->extra_info);
647 MERROR (MERROR_DB, NULL);
648 plist = mplist__from_file (fp, keys);
655 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
660 /*** @addtogroup m17nDatabase */
665 @brief Directory for application specific data.
667 If an application program wants to provide a data specific to the
668 program or a data overriding what supplied by the m17n database,
669 it must set this variable to a name of directory that contains the
670 data files before it calls the macro M17N_INIT (). The directory
671 may contain a file "mdb.dir" which contains a list of data
672 definitions in the format described in @ref mdbDir "mdbDir(5)".
674 The default value is NULL. */
676 @brief ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¸ÇͤΥǡ¼¥¿Íѥǥ£¥ì¥¯¥È¥ê.
678 ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤¬¡¢¤½¤Î¥×¥í¥°¥é¥à¸ÇͤΥǡ¼¥¿¤ä m17n
679 ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¾å½ñ¤¤¹¤ë¥Ç¡¼¥¿¤òÄ󶡤¹¤ë¾ì¹ç¤Ë¤Ï¡¢¥Þ¥¯¥í M17N_INIT ()
680 ¤ò¸Æ¤ÖÁ°¤Ë¤³¤ÎÊÑ¿ô¤ò¥Ç¡¼¥¿¥Õ¥¡¥¤¥ë¤ò´Þ¤à¥Ç¥£¥ì¥¯¥È¥ê̾¤Ë¥»¥Ã¥È¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¥Ç¥£¥ì¥¯¥È¥ê¤Ë¤Ï
681 "mdb.dir" ¥Õ¥¡¥¤¥ë¤ò¤ª¤¯¤³¤È¤¬¤Ç¤¤ë¡£¤½¤Î"mdb.dir"¥Õ¥¡¥¤¥ë¤Ë¤Ï¡¢
682 @ref mdbDir "mdbDir(5)" ¤ÇÀâÌÀ¤µ¤ì¤Æ¤¤¤ë¥Õ¥©¡¼¥Þ¥Ã¥È¤Ç¥Ç¡¼¥¿ÄêµÁ¤Î¥ê¥¹¥È¤òµ½Ò¤¹¤ë¡£
684 ¥Ç¥Õ¥©¥ë¥È¤ÎÃÍ¤Ï NULL ¤Ç¤¢¤ë¡£ */
690 @brief Look for a data in the database.
692 The mdatabase_find () function searches the m17n database for a
693 data who has tags $TAG0 through $TAG3, and returns a pointer to
694 the data. If such a data is not found, it returns @c NULL. */
697 @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Î¥Ç¡¼¥¿¤òõ¤¹.
699 ´Ø¿ô mdatabase_find () ¤Ï¡¢ m17n ¸À¸ì¾ðÊó¥Ù¡¼¥¹Ãæ¤Ç $TAG0 ¤«¤é
700 $TAG3 ¤Þ¤Ç¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¤òõ¤·¡¢¤½¤ì¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤Î¤è¤¦¤Ê¥Ç¡¼¥¿¤¬¤Ê¤±¤ì¤Ð
703 @latexonly \IPAlabel{mdatabase_find} @endlatexonly */
706 mdatabase_find (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
709 MDatabaseHookFunc func
710 = (MDatabaseHookFunc) msymbol_get (tag0, M_database_hook);
713 func (tag0, tag1, tag2, tag3);
715 for (i = 0; i < mdb_list.used; i++)
717 MDatabase *mdb = mdb_list.mdbs + i;
719 if (tag0 == mdb->tag[0]
720 && tag1 == mdb->tag[1]
721 && tag2 == mdb->tag[2]
722 && tag3 == mdb->tag[3])
730 @brief Return a data list of the m17n database.
732 The mdatabase_list () function searches the m17n database for data
733 who have tags $TAG0 through $TAG3, and returns their list by a
734 plist. The value #Mnil in $TAGn means a wild card that matches
735 any tag. Each element of the plist has key #Mt and value a
736 pointer to type #MDatabase. */
738 @brief m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥Ç¡¼¥¿¥ê¥¹¥È¤òÊÖ¤¹.
740 ´Ø¿ô mdatabase_list () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é $TAG0 ¤«¤é$TAG3
741 ¤Þ¤Ç¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¤òõ¤·¡¢¤½¤Î¥ê¥¹¥È¤òplist ¤È¤·¤ÆÊÖ¤¹¡£ $TAGn ¤¬ #Mnil
742 ¤Ç¤¢¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢Ç¤°Õ¤Î¥¿¥°¤Ë¥Þ¥Ã¥Á¤¹¤ë¥ï¥¤¥ë¥É¥«¡¼¥É¤È¤·¤Æ¼è¤ê°·¤ï¤ì¤ë¡£ÊÖ¤µ¤ì¤ë
743 plist ¤Î³ÆÍ×ÁǤϥ¡¼ ¤È¤·¤Æ #Mt ¤ò¡¢ÃͤȤ·¤Æ #MDatabase ·¿¤Ø¤Î¥Ý¥¤¥ó¥¿¤ò»ý¤Ä¡£ */
747 mdatabase_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
750 MPlist *plist = NULL, *pl;
751 MDatabaseHookFunc func
752 = (MDatabaseHookFunc) msymbol_get (tag0, M_database_hook);
755 func (tag0, tag1, tag2, tag3);
757 for (i = 0; i < mdb_list.used; i++)
759 MDatabase *mdb = mdb_list.mdbs + i;
761 if ((tag0 == Mnil || tag0 == mdb->tag[0])
762 && (tag1 == Mnil || tag1 == mdb->tag[1])
763 && (tag2 == Mnil || tag2 == mdb->tag[2])
764 && (tag3 == Mnil || tag3 == mdb->tag[3]))
767 plist = pl = mplist ();
768 pl = mplist_add (pl, Mt, mdb);
778 @brief Define a data of the m17n database.
780 The mdatabase_define () function defines a data that has tags
781 $TAG0 through $TAG3 and additional information $EXTRA_INFO.
783 $LOADER is a pointer to a function that loads the data from the
784 database. This function is called from the mdatabase_load ()
785 function with the two arguments $TAGS and $EXTRA_INFO. Here,
786 $TAGS is the array of $TAG0 through $TAG3.
788 If $LOADER is @c NULL, the default loader of the m17n library is
789 used. In this case, $EXTRA_INFO must be a string specifying a
790 filename that contains the data.
793 If the operation was successful, mdatabase_define () returns a
794 pointer to the defined data, which can be used as an argument to
795 mdatabase_load (). Otherwise, it returns @c NULL. */
798 @brief m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥Ç¡¼¥¿¤òÄêµÁ¤¹¤ë.
800 ´Ø¿ô mdatabase_define () ¤Ï $TAG0 ¤«¤é $TAG3 ¤Þ¤Ç¤Î¥¿¥°¤ª¤è¤ÓÉղþðÊó
801 $EXTRA_INFO ¤ò»ý¤Ä¥Ç¡¼¥¿¤òÄêµÁ¤¹¤ë¡£
803 $LOADER ¤Ï¤½¤Î¥Ç¡¼¥¿¤Î¥í¡¼¥É¤ËÍѤ¤¤é¤ì¤ë´Ø¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¤³¤Î´Ø¿ô¤Ï
804 mdatabase_load () ¤«¤é $TAGS ¤È $EXTRA_INFO ¤È¤¤¤¦Æó¤Ä¤Î°ú¿ôÉÕ¤¤Ç¸Æ¤Ó½Ð¤µ¤ì¤ë¡£¤³¤³¤Ç
805 $TAGS ¤Ï $TAG0 ¤«¤é $TAG3 ¤Þ¤Ç¤ÎÇÛÎó¤Ç¤¢¤ë¡£
807 ¤â¤· $LOADER ¤¬ @c NULL ¤Ê¤é¡¢m17n ¥é¥¤¥Ö¥é¥êɸ½à¤Î¥í¡¼¥À¤¬»È¤ï¤ì¤ë¡£¤³¤Î¾ì¹ç¤Ë¤Ï
808 $EXTRA_INFO ¤Ï¥Ç¡¼¥¿¤ò´Þ¤à¥Õ¥¡¥¤¥ë̾¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
811 ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mdatabase_define ()
812 ¤ÏÄêµÁ¤µ¤ì¤¿¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤³¤Î¥Ý¥¤¥ó¥¿¤Ï´Ø¿ô mdatabase_load ()
813 ¤Î°ú¿ô¤È¤·¤ÆÍѤ¤¤ë¤³¤È¤¬¤Ç¤¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£
815 @latexonly \IPAlabel{mdatabase_define} @endlatexonly */
819 mdatabase_load (), mdatabase_define () */
822 mdatabase_define (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3,
823 void *(*loader) (MSymbol *, void *),
827 MDatabaseHookFunc func
828 = (MDatabaseHookFunc) msymbol_get (tag0, M_database_hook);
831 func (tag0, tag1, tag2, tag3);
833 mdb = mdatabase_find (tag0, tag1, tag2, tag3);
838 template.tag[0] = tag0, template.tag[1] = tag1;
839 template.tag[2] = tag2, template.tag[3] = tag3;
840 template.extra_info = NULL;
841 MLIST_APPEND1 (&mdb_list, mdbs, template, MERROR_DB);
842 mdb = mdb_list.mdbs + (mdb_list.used - 1);
844 mdb->loader = loader ? loader : load_database;
845 if (mdb->loader == load_database)
848 free (mdb->extra_info);
849 mdb->extra_info = strdup ((char *) extra_info);
852 mdb->extra_info = extra_info;
853 return (&(mdb_list.mdbs[mdb_list.used - 1]));
858 @brief Load a data from the database.
860 The mdatabase_load () function loads a data specified in $MDB and
861 returns the contents. The type of contents depends on the type of
864 If the data is of the @e plist @e type, this function returns a
867 If the database is of the @e chartable @e type, it returns a
868 chartable. The default value of the chartable is set according to
869 the second tag of the data as below:
871 @li If the tag is #Msymbol, the default value is #Mnil.
872 @li If the tag is #Minteger, the default value is -1.
873 @li Otherwise, the default value is @c NULL.
875 If the data is of the @e charset @e type, it returns a plist of length 2
876 (keys are both #Mt). The value of the first element is an array
877 of integers that maps code points to the corresponding character
878 codes. The value of the second element is a chartable of integers
879 that does the reverse mapping. The charset must be defined in
884 @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹¤«¤é¥Ç¡¼¥¿¤ò¥í¡¼¥É¤¹¤ë.
886 ´Ø¿ô mdatabase_load () ¤Ï $MDB
887 ¤¬»Ø¤¹¥Ç¡¼¥¿¤ò¥í¡¼¥É¤·¡¢¤½¤ÎÃæ¿È¤òÊÖ¤¹¡£ÊÖ¤µ¤ì¤ë¤â¤Î¤Ï¥Ç¡¼¥¿¤Î¥¿¥¤¥×¤Ë¤è¤Ã¤Æ°Û¤Ê¤ë¡£
889 ¥Ç¡¼¥¿¤¬ @e plist¥¿¥¤¥× ¤Ê¤é¤Ð¡¢ @e plist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
891 ¥Ç¡¼¥¿¤¬ @e chartable¥¿¥¤¥× ¤Ê¤é¤Ðʸ»ú¥Æ¡¼¥Ö¥ë¤òÊÖ¤¹¡£
892 ʸ»ú¥Æ¡¼¥Ö¥ë¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤϡ¢¥Ç¡¼¥¿¤ÎÂè2¥¿¥°¤Ë¤è¤Ã¤Æ°Ê²¼¤Î¤è¤¦¤Ë·è¤Þ¤ë¡£
894 @li ¥¿¥°¤¬ #Msymbol ¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï #Mnil
895 @li ¥¿¥°¤¬ #Minteger ¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï -1
896 @li ¤½¤ì°Ê³°¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï @c NULL
898 ¥Ç¡¼¥¿¤¬ @e charset¥¿¥¤¥× ¤Ê¤é¤ÐŤµ 2 ¤Î plist ¤òÊÖ¤¹¡Ê¥¡¼¤Ï¶¦¤Ë#Mt ¡Ë¡£
899 ºÇ½é¤ÎÍ×ÁǤÎÃͤϥ³¡¼¥É¥Ý¥¤¥ó¥È¤òÂбþ¤¹¤ëʸ»ú¥³¡¼¥É¤Ë¥Þ¥Ã¥×¤¹¤ëÀ°¿ô¤ÎÇÛÎó¤Ç¤¢¤ë¡£
900 £²ÈÖÌܤÎÍ×ÁǤÎÃͤϵդΥޥåפò¤¹¤ëʸ»ú¥Æ¡¼¥Ö¥ë¤Ç¤¢¤ë¡£
901 ¤³¤Îʸ»ú¥»¥Ã¥È¤Ïͽ¤áÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
903 @latexonly \IPAlabel{mdatabase_load} @endlatexonly
908 mdatabase_load (), mdatabase_define () */
911 mdatabase_load (MDatabase *mdb)
913 int mdebug_mask = MDEBUG_DATABASE;
916 MDEBUG_PRINT1 (" [DATABASE] loading <%s>.\n",
917 gen_database_name (buf, mdb->tag));
918 return (*mdb->loader) (mdb->tag, mdb->extra_info);
923 @brief Get tags of a data.
925 The mdatabase_tag () function returns an array of tags (symbols)
926 that identify the data in $MDB. The length of the array is
930 @brief ¥Ç¡¼¥¿¤Î¥¿¥°¤òÆÀ¤ë.
932 ´Ø¿ô mdatabase_tag () ¤Ï¡¢¥Ç¡¼¥¿ $MDB ¤Î¥¿¥°¡Ê¥·¥ó¥Ü¥ë¡Ë¤ÎÇÛÎó¤òÊÖ¤¹¡£ÇÛÎó¤ÎŤµ¤Ï
935 @latexonly \IPAlabel{mdatabase_tag} @endlatexonly */
938 mdatabase_tag (MDatabase *mdb)