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>
125 #include "m17n-misc.h"
126 #include "internal.h"
128 #include "character.h"
130 #include "database.h"
134 /** The file containing a list of databases. */
135 #define MDB_DIR "mdb.dir"
136 #define MDB_DIR_LEN 8
138 #define MAX_TIME(TIME1, TIME2) ((TIME1) >= (TIME2) ? (TIME1) : (TIME2))
140 static MSymbol Masterisk;
142 /** Structure for a data in the m17n database. */
146 /** Tags to identify the data. <tag>[0] specifies the type of
147 database. If it is #Mchar_table, the type is @e chartable, if
148 it is #Mcharset, the type is @e charset, otherwise the type is
152 void *(*loader) (MSymbol *tags, void *extra_info);
154 /** The meaning of the value is dependent on <loader>. If <loader>
155 is load_database (), the value is a string of the file name that
156 contains the data. */
160 /** List of all data. */
167 static struct MDatabaseList mdb_list;
171 read_number (char *buf, int *i)
180 while (c && isspace (c)) c = buf[idx++];
186 for (idx++, c = 0; (n = hex_mnemonic[(unsigned) buf[idx]]) < 16;
200 n = escape_mnemonic[c];
204 while (buf[idx] && buf[idx++] != '\'');
208 else if (hex_mnemonic[c] < 10)
213 while ((n = hex_mnemonic[(unsigned) buf[idx]]) < 10)
214 c = (c * 10) + n, idx++;
220 /** Load a data of type @c chartable from the file FD, and return the
221 newly created chartable. */
224 load_chartable (FILE *fp, MSymbol type)
232 MERROR (MERROR_DB, NULL);
234 table = mchartable (type, (type == Msymbol ? (void *) Mnil
235 : type == Minteger ? (void *) -1
242 for (len = 0; len < 1023 && (c = getc (fp)) != EOF && c != '\n'; len++)
245 if (hex_mnemonic[(unsigned) buf[0]] >= 10)
246 /* skip comment/invalid line */
249 from = read_number (buf, &i);
251 i++, to = read_number (buf, &i);
254 if (from < 0 || to < from)
257 while (buf[i] && isspace ((unsigned) buf[i])) i++;
264 /* VAL is a C-string. */
265 if (! (val = strdup (buf + i)))
266 MEMORY_FULL (MERROR_DB);
268 else if (type == Minteger)
270 /* VAL is an integer. */
276 n = read_number (buf, &i);
279 val = (void *) (n * positive);
281 else if (type == Mtext)
283 /* VAL is an M-text. */
286 mt = mconv_decode_buffer (Mcoding_utf_8,
287 (unsigned char *) (buf + i),
292 while ((c = read_number (buf, &i)) >= 0)
293 mt = mtext_cat_char (mt, c);
297 else if (type == Msymbol)
301 while (*p && ! isspace (*p))
303 if (*p == '\\' && p[1] != '\0')
305 memmove (p, p + 1, buf + len - (p + 1));
311 if (! strcmp (buf + i, "nil"))
314 val = (void *) msymbol (buf + i);
316 else if (type == Mplist)
318 val = (void *) mplist__from_string ((unsigned char *) buf + i,
325 mchartable_set (table, from, val);
327 mchartable_set_range (table, from, to, val);
332 M17N_OBJECT_UNREF (table);
333 MERROR (MERROR_DB, NULL);
337 /** Load a data of type @c charset from the file FD. */
340 load_charset (FILE *fp, MSymbol charset_name)
342 MCharset *charset = MCHARSET (charset_name);
351 MERROR (MERROR_DB, NULL);
352 size = (charset->code_range[15]
353 - (charset->min_code - charset->code_range_min_code));
354 MTABLE_MALLOC (decoder, size, MERROR_DB);
355 for (i = 0; i < size; i++)
357 encoder = mchartable (Minteger, (void *) MCHAR_INVALID_CODE);
359 while ((c = getc (fp)) != EOF)
361 unsigned code1, code2, c1, c2;
366 fgets (buf, 256, fp);
369 if (sscanf (buf, "0x%x-0x%x 0x%x", &code1, &code2, &c1) == 3)
371 idx1 = CODE_POINT_TO_INDEX (charset, code1);
374 idx2 = CODE_POINT_TO_INDEX (charset, code2);
377 c2 = c1 + (idx2 - idx1);
379 else if (sscanf (buf, "0x%x 0x%x", &code1, &c1) == 2)
381 idx1 = idx2 = CODE_POINT_TO_INDEX (charset, code1);
388 if (idx1 >= 0 && idx2 >= 0)
391 mchartable_set (encoder, c1, (void *) code1);
392 for (idx1++, c1++; idx1 <= idx2; idx1++, c1++)
394 code1 = INDEX_TO_CODE_POINT (charset, idx1);
396 mchartable_set (encoder, c1, (void *) code1);
406 M17N_OBJECT_UNREF (encoder);
410 mplist_add (plist, Mt, decoder);
411 mplist_add (plist, Mt, encoder);
416 gen_database_name (char *buf, MSymbol *tags)
420 strcpy (buf, msymbol_name (tags[0]));
421 for (i = 1; i < 4; i++)
424 strcat (buf, msymbol_name (tags[i]));
430 get_database_stream (MDatabaseInfo *db_info)
435 if (db_info->filename[0] == '/')
437 if (stat (db_info->filename, &buf) == 0
438 && (fp = fopen (db_info->filename, "r")))
439 db_info->time = MAX_TIME (buf.st_mtime, buf.st_ctime);
445 int filelen = strlen (db_info->filename);
448 MPLIST_DO (plist, mdatabase__dir_list)
450 MDatabaseInfo *dir_info = MPLIST_VAL (plist);
451 int require = strlen (dir_info->filename) + filelen + 1;
453 SAFE_ALLOCA (path, require);
454 strcpy (path, dir_info->filename);
455 strcat (path, db_info->filename);
456 if (stat (path, &buf) == 0
457 && (fp = fopen (path, "r")))
459 free (db_info->filename);
460 db_info->filename = strdup (path);
461 db_info->time = MAX_TIME (buf.st_mtime, buf.st_ctime);
471 load_database (MSymbol *tags, void *extra_info)
473 FILE *fp = get_database_stream ((MDatabaseInfo *) extra_info);
477 MERROR (MERROR_DB, NULL);
479 if (tags[0] == Mchar_table)
480 value = load_chartable (fp, tags[1]);
481 else if (tags[0] == Mcharset)
482 value = load_charset (fp, tags[1]);
484 value = mplist__from_file (fp, NULL);
488 MERROR (MERROR_DB, NULL);
493 /** If DIRNAME is a readable directory, allocate MDatabaseInfo and
494 copy DIRNAME to a newly allocated memory and return it. If
495 DIRNAME does not end with a slash, append a slash to the new memory. */
497 static MDatabaseInfo *
498 get_dir_info (char *dirname)
502 MDatabaseInfo *dir_info;
505 || stat (dirname, &buf) < 0
506 || ! (buf.st_mode & S_IFDIR))
509 MSTRUCT_MALLOC (dir_info, MERROR_DB);
510 len = strlen (dirname);
511 MTABLE_MALLOC (dir_info->filename, len + 2, MERROR_DB);
512 memcpy (dir_info->filename, dirname, len + 1);
513 if (dir_info->filename[len - 1] != '/')
515 dir_info->filename[len] = '/';
516 dir_info->filename[len + 1] = '\0';
518 /* Set this to zero so that the first call of update_database_list
519 surely checks this directory. */
525 find_database (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
529 for (i = 0; i < mdb_list.used; i++)
531 MDatabase *mdb = mdb_list.mdbs + i;
533 if (tag0 == mdb->tag[0]
534 && tag1 == mdb->tag[1]
535 && tag2 == mdb->tag[2]
536 && tag3 == mdb->tag[3])
543 update_database_list ()
549 /* Usually this avoids path to be reallocated. */
550 SAFE_ALLOCA (path, 256);
552 MPLIST_DO (plist, mdatabase__dir_list)
554 MDatabaseInfo *dir_info = MPLIST_VAL (plist);
560 if (stat (dir_info->filename, &statbuf) < 0)
562 if (dir_info->time >= statbuf.st_ctime
563 && dir_info->time >= statbuf.st_mtime)
565 dir_info->time = MAX_TIME (statbuf.st_ctime, statbuf.st_mtime);
566 len = strlen (dir_info->filename);
568 if (len + MDB_DIR_LEN >= PATH_MAX)
570 #endif /* PATH_MAX */
571 SAFE_ALLOCA (path, len + MDB_DIR_LEN + 1);
572 memcpy (path, dir_info->filename, len);
573 memcpy (path + len, MDB_DIR, MDB_DIR_LEN);
574 path[len + MDB_DIR_LEN] = '\0';
575 if (! (fp = fopen (path, "r")))
577 pl = mplist__from_file (fp, NULL);
587 int with_wildcard = 0;
589 if (! MPLIST_PLIST_P (p))
591 p1 = MPLIST_PLIST (p);
592 if (! MPLIST_SYMBOL_P (p1))
594 for (i = 0, p1 = MPLIST_PLIST (p);
595 i < 4 && MPLIST_KEY (p1) == Msymbol;
596 i++, p1 = MPLIST_NEXT (p1))
597 with_wildcard |= ((mdb.tag[i] = MPLIST_SYMBOL (p1)) == Masterisk);
599 || mdb.tag[0] == Masterisk
600 || ! MPLIST_MTEXT_P (p1))
604 mdb.loader = load_database;
605 mt = MPLIST_MTEXT (p1);
606 if (mt->format >= MTEXT_FORMAT_UTF_16LE)
607 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
608 nbytes = mtext_nbytes (mt);
610 if (nbytes > PATH_MAX)
612 #endif /* PATH_MAX */
614 && mdb.tag[0] != Mchar_table
615 && mdb.tag[0] != Mcharset)
620 SAFE_ALLOCA (path, len + nbytes + 1);
621 memcpy (path, dir_info->filename, len);
622 memcpy (path + len, mt->data, nbytes);
623 path[len + nbytes] = '\0';
625 if (glob (path, GLOB_NOSORT | GLOB_NOCHECK, NULL, &globbuf) != 0)
627 load_key = mplist ();
628 for (i = 0; i < globbuf.gl_pathc; i++)
630 if (! (fp = fopen (globbuf.gl_pathv[i], "r")))
632 p1 = mplist__from_file (fp, load_key);
636 if (MPLIST_PLIST_P (p1))
641 for (j = 0, p0 = MPLIST_PLIST (p1);
642 j < 4 && MPLIST_SYMBOL_P (p0);
643 j++, p0 = MPLIST_NEXT (p0))
644 mdb2.tag[j] = MPLIST_SYMBOL (p0);
647 for (j = 0; j < 4; j++)
648 if (mdb.tag[j] == Masterisk
649 ? mdb2.tag[j] == Mnil
650 : (mdb.tag[j] != Mnil && mdb.tag[j] != mdb2.tag[j]))
653 && ! find_database (mdb2.tag[0], mdb2.tag[1],
654 mdb2.tag[2], mdb2.tag[3]))
656 mdb2.loader = load_database;
657 mdb2.extra_info = calloc (1, sizeof (MDatabaseInfo));
658 if (! mdb2.extra_info)
659 MEMORY_FULL (MERROR_DB);
660 ((MDatabaseInfo*) mdb2.extra_info)->filename
661 = strdup (globbuf.gl_pathv[i]);
662 MLIST_APPEND1 (&mdb_list, mdbs, mdb2, MERROR_DB);
665 M17N_OBJECT_UNREF (p1);
667 M17N_OBJECT_UNREF (load_key);
672 if (find_database (mdb.tag[0], mdb.tag[1],
673 mdb.tag[2], mdb.tag[3]))
675 SAFE_ALLOCA (path, nbytes + 1);
676 memcpy (path, mt->data, nbytes);
678 mdb.extra_info = calloc (1, sizeof (MDatabaseInfo));
679 if (! mdb.extra_info)
680 MEMORY_FULL (MERROR_DB);
681 ((MDatabaseInfo*) mdb.extra_info)->filename = strdup (path);
682 MLIST_APPEND1 (&mdb_list, mdbs, mdb, MERROR_DB);
685 M17N_OBJECT_UNREF (pl);
694 /** List of database directories. */
695 MPlist *mdatabase__dir_list;
700 MDatabaseInfo *dir_info;
702 Mchar_table = msymbol ("char-table");
703 Masterisk = msymbol ("*");
705 mdatabase__dir_list = mplist ();
706 /** The macro M17NDIR specifies a directory where the system-wide
707 MDB_DIR file exists. */
708 if ((dir_info = get_dir_info (M17NDIR)))
709 mplist_set (mdatabase__dir_list, Mt, dir_info);
711 /* The variable mdatabase_dir specifies a directory where an
712 application program specific MDB_DIR file exists. */
713 if ((dir_info = get_dir_info (mdatabase_dir)))
714 mplist_push (mdatabase__dir_list, Mt, dir_info);
716 /* The environment variable M17NDIR (if non-NULL) specifies a
717 directory where a user specific MDB_DIR file exists. */
718 if ((dir_info = get_dir_info (getenv ("M17NDIR"))))
719 mplist_push (mdatabase__dir_list, Mt, dir_info);
721 MLIST_INIT1 (&mdb_list, mdbs, 256);
722 update_database_list ();
724 mdatabase__finder = ((void *(*) (MSymbol, MSymbol, MSymbol, MSymbol))
726 mdatabase__loader = (void *(*) (void *)) mdatabase_load;
732 mdatabase__fini (void)
737 MPLIST_DO (plist, mdatabase__dir_list)
738 free (MPLIST_VAL (plist));
739 M17N_OBJECT_UNREF (mdatabase__dir_list);
741 for (i = 0; i < mdb_list.used; i++)
743 MDatabase *mdb = mdb_list.mdbs + i;
745 if (mdb->loader == load_database)
747 MDatabaseInfo *db_info = mdb->extra_info;
749 free (db_info->filename);
753 MLIST_FREE1 (&mdb_list, mdbs);
757 mdatabase__load_for_keys (MDatabase *mdb, MPlist *keys)
759 int mdebug_mask = MDEBUG_DATABASE;
764 if (mdb->loader != load_database
765 || mdb->tag[0] == Mchar_table
766 || mdb->tag[0] == Mcharset)
767 MERROR (MERROR_DB, NULL);
768 MDEBUG_PRINT1 (" [DATABASE] loading <%s>.\n",
769 gen_database_name (buf, mdb->tag));
770 fp = get_database_stream ((MDatabaseInfo *) mdb->extra_info);
772 MERROR (MERROR_DB, NULL);
773 plist = mplist__from_file (fp, keys);
779 /* Check if the database MDB should be reloaded or not. */
782 mdatabase__check (MDatabase *mdb)
784 MDatabaseInfo *db_info = (MDatabaseInfo *) mdb->extra_info;
787 if (stat (db_info->filename, &buf) < 0)
789 return (db_info->time >= buf.st_ctime
790 && db_info->time >= buf.st_mtime);
794 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
799 /*** @addtogroup m17nDatabase */
804 @brief Directory for application specific data.
806 If an application program wants to provide a data specific to the
807 program or a data overriding what supplied by the m17n database,
808 it must set this variable to a name of directory that contains the
809 data files before it calls the macro M17N_INIT (). The directory
810 may contain a file "mdb.dir" which contains a list of data
811 definitions in the format described in @ref mdbDir "mdbDir(5)".
813 The default value is NULL. */
815 @brief ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¸ÇͤΥǡ¼¥¿Íѥǥ£¥ì¥¯¥È¥ê.
817 ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤¬¡¢¤½¤Î¥×¥í¥°¥é¥à¸ÇͤΥǡ¼¥¿¤ä m17n
818 ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¾å½ñ¤¤¹¤ë¥Ç¡¼¥¿¤òÄ󶡤¹¤ë¾ì¹ç¤Ë¤Ï¡¢¥Þ¥¯¥í M17N_INIT ()
819 ¤ò¸Æ¤ÖÁ°¤Ë¤³¤ÎÊÑ¿ô¤ò¥Ç¡¼¥¿¥Õ¥¡¥¤¥ë¤ò´Þ¤à¥Ç¥£¥ì¥¯¥È¥ê̾¤Ë¥»¥Ã¥È¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¥Ç¥£¥ì¥¯¥È¥ê¤Ë¤Ï
820 "mdb.dir" ¥Õ¥¡¥¤¥ë¤ò¤ª¤¯¤³¤È¤¬¤Ç¤¤ë¡£¤½¤Î"mdb.dir"¥Õ¥¡¥¤¥ë¤Ë¤Ï¡¢
821 @ref mdbDir "mdbDir(5)" ¤ÇÀâÌÀ¤µ¤ì¤Æ¤¤¤ë¥Õ¥©¡¼¥Þ¥Ã¥È¤Ç¥Ç¡¼¥¿ÄêµÁ¤Î¥ê¥¹¥È¤òµ½Ò¤¹¤ë¡£
823 ¥Ç¥Õ¥©¥ë¥È¤ÎÃÍ¤Ï NULL ¤Ç¤¢¤ë¡£ */
829 @brief Look for a data in the database.
831 The mdatabase_find () function searches the m17n database for a
832 data who has tags $TAG0 through $TAG3, and returns a pointer to
833 the data. If such a data is not found, it returns @c NULL. */
836 @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Î¥Ç¡¼¥¿¤òõ¤¹.
838 ´Ø¿ô mdatabase_find () ¤Ï¡¢ m17n ¸À¸ì¾ðÊó¥Ù¡¼¥¹Ãæ¤Ç $TAG0 ¤«¤é
839 $TAG3 ¤Þ¤Ç¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¤òõ¤·¡¢¤½¤ì¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤Î¤è¤¦¤Ê¥Ç¡¼¥¿¤¬¤Ê¤±¤ì¤Ð
842 @latexonly \IPAlabel{mdatabase_find} @endlatexonly */
845 mdatabase_find (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
847 update_database_list ();
848 return find_database (tag0, tag1, tag2, tag3);
853 @brief Return a data list of the m17n database.
855 The mdatabase_list () function searches the m17n database for data
856 who have tags $TAG0 through $TAG3, and returns their list by a
857 plist. The value #Mnil in $TAGn means a wild card that matches
858 any tag. Each element of the plist has key #Mt and value a
859 pointer to type #MDatabase. */
861 @brief m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥Ç¡¼¥¿¥ê¥¹¥È¤òÊÖ¤¹.
863 ´Ø¿ô mdatabase_list () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é $TAG0 ¤«¤é$TAG3
864 ¤Þ¤Ç¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¤òõ¤·¡¢¤½¤Î¥ê¥¹¥È¤òplist ¤È¤·¤ÆÊÖ¤¹¡£ $TAGn ¤¬ #Mnil
865 ¤Ç¤¢¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢Ç¤°Õ¤Î¥¿¥°¤Ë¥Þ¥Ã¥Á¤¹¤ë¥ï¥¤¥ë¥É¥«¡¼¥É¤È¤·¤Æ¼è¤ê°·¤ï¤ì¤ë¡£ÊÖ¤µ¤ì¤ë
866 plist ¤Î³ÆÍ×ÁǤϥ¡¼ ¤È¤·¤Æ #Mt ¤ò¡¢ÃͤȤ·¤Æ #MDatabase ·¿¤Ø¤Î¥Ý¥¤¥ó¥¿¤ò»ý¤Ä¡£ */
869 mdatabase_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
872 MPlist *plist = NULL, *pl;
874 update_database_list ();
876 for (i = 0; i < mdb_list.used; i++)
878 MDatabase *mdb = mdb_list.mdbs + i;
880 if ((tag0 == Mnil || tag0 == mdb->tag[0])
881 && (tag1 == Mnil || tag1 == mdb->tag[1])
882 && (tag2 == Mnil || tag2 == mdb->tag[2])
883 && (tag3 == Mnil || tag3 == mdb->tag[3]))
886 plist = pl = mplist ();
887 pl = mplist_add (pl, Mt, mdb);
895 @brief Define a data of the m17n database.
897 The mdatabase_define () function defines a data that has tags
898 $TAG0 through $TAG3 and additional information $EXTRA_INFO.
900 $LOADER is a pointer to a function that loads the data from the
901 database. This function is called from the mdatabase_load ()
902 function with the two arguments $TAGS and $EXTRA_INFO. Here,
903 $TAGS is the array of $TAG0 through $TAG3.
905 If $LOADER is @c NULL, the default loader of the m17n library is
906 used. In this case, $EXTRA_INFO must be a string specifying a
907 filename that contains the data.
910 If the operation was successful, mdatabase_define () returns a
911 pointer to the defined data, which can be used as an argument to
912 mdatabase_load (). Otherwise, it returns @c NULL. */
915 @brief m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥Ç¡¼¥¿¤òÄêµÁ¤¹¤ë.
917 ´Ø¿ô mdatabase_define () ¤Ï $TAG0 ¤«¤é $TAG3 ¤Þ¤Ç¤Î¥¿¥°¤ª¤è¤ÓÉղþðÊó
918 $EXTRA_INFO ¤ò»ý¤Ä¥Ç¡¼¥¿¤òÄêµÁ¤¹¤ë¡£
920 $LOADER ¤Ï¤½¤Î¥Ç¡¼¥¿¤Î¥í¡¼¥É¤ËÍѤ¤¤é¤ì¤ë´Ø¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¤³¤Î´Ø¿ô¤Ï
921 mdatabase_load () ¤«¤é $TAGS ¤È $EXTRA_INFO ¤È¤¤¤¦Æó¤Ä¤Î°ú¿ôÉÕ¤¤Ç¸Æ¤Ó½Ð¤µ¤ì¤ë¡£¤³¤³¤Ç
922 $TAGS ¤Ï $TAG0 ¤«¤é $TAG3 ¤Þ¤Ç¤ÎÇÛÎó¤Ç¤¢¤ë¡£
924 ¤â¤· $LOADER ¤¬ @c NULL ¤Ê¤é¡¢m17n ¥é¥¤¥Ö¥é¥êɸ½à¤Î¥í¡¼¥À¤¬»È¤ï¤ì¤ë¡£¤³¤Î¾ì¹ç¤Ë¤Ï
925 $EXTRA_INFO ¤Ï¥Ç¡¼¥¿¤ò´Þ¤à¥Õ¥¡¥¤¥ë̾¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
928 ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mdatabase_define ()
929 ¤ÏÄêµÁ¤µ¤ì¤¿¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤³¤Î¥Ý¥¤¥ó¥¿¤Ï´Ø¿ô mdatabase_load ()
930 ¤Î°ú¿ô¤È¤·¤ÆÍѤ¤¤ë¤³¤È¤¬¤Ç¤¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£
932 @latexonly \IPAlabel{mdatabase_define} @endlatexonly */
936 mdatabase_load (), mdatabase_define () */
939 mdatabase_define (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3,
940 void *(*loader) (MSymbol *, void *),
945 mdb = mdatabase_find (tag0, tag1, tag2, tag3);
950 template.tag[0] = tag0, template.tag[1] = tag1;
951 template.tag[2] = tag2, template.tag[3] = tag3;
952 template.extra_info = NULL;
953 MLIST_APPEND1 (&mdb_list, mdbs, template, MERROR_DB);
954 mdb = mdb_list.mdbs + (mdb_list.used - 1);
956 mdb->loader = loader ? loader : load_database;
957 if (mdb->loader == load_database)
959 MDatabaseInfo *db_info = mdb->extra_info;
962 free (db_info->filename);
964 db_info = mdb->extra_info = malloc (sizeof (MDatabaseInfo));
965 db_info->filename = strdup ((char *) extra_info);
969 mdb->extra_info = extra_info;
970 return (&(mdb_list.mdbs[mdb_list.used - 1]));
975 @brief Load a data from the database.
977 The mdatabase_load () function loads a data specified in $MDB and
978 returns the contents. The type of contents depends on the type of
981 If the data is of the @e plist @e type, this function returns a
984 If the database is of the @e chartable @e type, it returns a
985 chartable. The default value of the chartable is set according to
986 the second tag of the data as below:
988 @li If the tag is #Msymbol, the default value is #Mnil.
989 @li If the tag is #Minteger, the default value is -1.
990 @li Otherwise, the default value is @c NULL.
992 If the data is of the @e charset @e type, it returns a plist of length 2
993 (keys are both #Mt). The value of the first element is an array
994 of integers that maps code points to the corresponding character
995 codes. The value of the second element is a chartable of integers
996 that does the reverse mapping. The charset must be defined in
1001 @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹¤«¤é¥Ç¡¼¥¿¤ò¥í¡¼¥É¤¹¤ë.
1003 ´Ø¿ô mdatabase_load () ¤Ï $MDB
1004 ¤¬»Ø¤¹¥Ç¡¼¥¿¤ò¥í¡¼¥É¤·¡¢¤½¤ÎÃæ¿È¤òÊÖ¤¹¡£ÊÖ¤µ¤ì¤ë¤â¤Î¤Ï¥Ç¡¼¥¿¤Î¥¿¥¤¥×¤Ë¤è¤Ã¤Æ°Û¤Ê¤ë¡£
1006 ¥Ç¡¼¥¿¤¬ @e plist¥¿¥¤¥× ¤Ê¤é¤Ð¡¢ @e plist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
1008 ¥Ç¡¼¥¿¤¬ @e chartable¥¿¥¤¥× ¤Ê¤é¤Ðʸ»ú¥Æ¡¼¥Ö¥ë¤òÊÖ¤¹¡£
1009 ʸ»ú¥Æ¡¼¥Ö¥ë¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤϡ¢¥Ç¡¼¥¿¤ÎÂè2¥¿¥°¤Ë¤è¤Ã¤Æ°Ê²¼¤Î¤è¤¦¤Ë·è¤Þ¤ë¡£
1011 @li ¥¿¥°¤¬ #Msymbol ¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï #Mnil
1012 @li ¥¿¥°¤¬ #Minteger ¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï -1
1013 @li ¤½¤ì°Ê³°¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï @c NULL
1015 ¥Ç¡¼¥¿¤¬ @e charset¥¿¥¤¥× ¤Ê¤é¤ÐŤµ 2 ¤Î plist ¤òÊÖ¤¹¡Ê¥¡¼¤Ï¶¦¤Ë#Mt ¡Ë¡£
1016 ºÇ½é¤ÎÍ×ÁǤÎÃͤϥ³¡¼¥É¥Ý¥¤¥ó¥È¤òÂбþ¤¹¤ëʸ»ú¥³¡¼¥É¤Ë¥Þ¥Ã¥×¤¹¤ëÀ°¿ô¤ÎÇÛÎó¤Ç¤¢¤ë¡£
1017 £²ÈÖÌܤÎÍ×ÁǤÎÃͤϵդΥޥåפò¤¹¤ëʸ»ú¥Æ¡¼¥Ö¥ë¤Ç¤¢¤ë¡£
1018 ¤³¤Îʸ»ú¥»¥Ã¥È¤Ïͽ¤áÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
1020 @latexonly \IPAlabel{mdatabase_load} @endlatexonly
1025 mdatabase_load (), mdatabase_define () */
1028 mdatabase_load (MDatabase *mdb)
1030 int mdebug_mask = MDEBUG_DATABASE;
1033 MDEBUG_PRINT1 (" [DATABASE] loading <%s>.\n",
1034 gen_database_name (buf, mdb->tag));
1035 return (*mdb->loader) (mdb->tag, mdb->extra_info);
1040 @brief Get tags of a data.
1042 The mdatabase_tag () function returns an array of tags (symbols)
1043 that identify the data in $MDB. The length of the array is
1047 @brief ¥Ç¡¼¥¿¤Î¥¿¥°¤òÆÀ¤ë.
1049 ´Ø¿ô mdatabase_tag () ¤Ï¡¢¥Ç¡¼¥¿ $MDB ¤Î¥¿¥°¡Ê¥·¥ó¥Ü¥ë¡Ë¤ÎÇÛÎó¤òÊÖ¤¹¡£ÇÛÎó¤ÎŤµ¤Ï
1052 @latexonly \IPAlabel{mdatabase_tag} @endlatexonly */
1055 mdatabase_tag (MDatabase *mdb)