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. */
166 /** List of all data. */
173 static struct MDatabaseList mdb_list;
177 read_number (char *buf, int *i)
186 while (c && isspace (c)) c = buf[idx++];
192 for (idx++, c = 0; (n = hex_mnemonic[(unsigned) buf[idx]]) < 16;
206 n = escape_mnemonic[c];
210 while (buf[idx] && buf[idx++] != '\'');
214 else if (hex_mnemonic[c] < 10)
219 while ((n = hex_mnemonic[(unsigned) buf[idx]]) < 10)
220 c = (c * 10) + n, idx++;
226 /** Load a data of type @c chartable from the file FD, and return the
227 newly created chartable. */
230 load_chartable (FILE *fp, MSymbol type)
238 MERROR (MERROR_DB, NULL);
240 table = mchartable (type, (type == Msymbol ? (void *) Mnil
241 : type == Minteger ? (void *) -1
248 for (len = 0; len < 1023 && (c = getc (fp)) != EOF && c != '\n'; len++)
251 if (hex_mnemonic[(unsigned) buf[0]] >= 10)
252 /* skip comment/invalid line */
255 from = read_number (buf, &i);
257 i++, to = read_number (buf, &i);
260 if (from < 0 || to < from)
263 while (buf[i] && isspace ((unsigned) buf[i])) i++;
270 /* VAL is a C-string. */
271 if (! (val = strdup (buf + i)))
272 MEMORY_FULL (MERROR_DB);
274 else if (type == Minteger)
276 /* VAL is an integer. */
282 n = read_number (buf, &i);
285 val = (void *) (n * positive);
287 else if (type == Mtext)
289 /* VAL is an M-text. */
292 mt = mconv_decode_buffer (Mcoding_utf_8,
293 (unsigned char *) (buf + i),
298 while ((c = read_number (buf, &i)) >= 0)
299 mt = mtext_cat_char (mt, c);
303 else if (type == Msymbol)
307 while (*p && ! isspace (*p))
309 if (*p == '\\' && p[1] != '\0')
311 memmove (p, p + 1, buf + len - (p + 1));
317 if (! strcmp (buf + i, "nil"))
320 val = (void *) msymbol (buf + i);
322 else if (type == Mplist)
324 val = (void *) mplist__from_string ((unsigned char *) buf + i,
331 mchartable_set (table, from, val);
333 mchartable_set_range (table, from, to, val);
338 M17N_OBJECT_UNREF (table);
339 MERROR (MERROR_DB, NULL);
343 /** Load a data of type @c charset from the file FD. */
346 load_charset (FILE *fp, MSymbol charset_name)
348 MCharset *charset = MCHARSET (charset_name);
357 MERROR (MERROR_DB, NULL);
358 size = (charset->code_range[15]
359 - (charset->min_code - charset->code_range_min_code));
360 MTABLE_MALLOC (decoder, size, MERROR_DB);
361 for (i = 0; i < size; i++)
363 encoder = mchartable (Minteger, (void *) MCHAR_INVALID_CODE);
365 while ((c = getc (fp)) != EOF)
367 unsigned code1, code2, c1, c2;
372 fgets (buf, 256, fp);
375 if (sscanf (buf, "0x%x-0x%x 0x%x", &code1, &code2, &c1) == 3)
377 idx1 = CODE_POINT_TO_INDEX (charset, code1);
380 idx2 = CODE_POINT_TO_INDEX (charset, code2);
383 c2 = c1 + (idx2 - idx1);
385 else if (sscanf (buf, "0x%x 0x%x", &code1, &c1) == 2)
387 idx1 = idx2 = CODE_POINT_TO_INDEX (charset, code1);
394 if (idx1 >= 0 && idx2 >= 0)
397 mchartable_set (encoder, c1, (void *) code1);
398 for (idx1++, c1++; idx1 <= idx2; idx1++, c1++)
400 code1 = INDEX_TO_CODE_POINT (charset, idx1);
402 mchartable_set (encoder, c1, (void *) code1);
412 M17N_OBJECT_UNREF (encoder);
416 mplist_add (plist, Mt, decoder);
417 mplist_add (plist, Mt, encoder);
422 gen_database_name (char *buf, MSymbol *tags)
426 strcpy (buf, msymbol_name (tags[0]));
427 for (i = 1; i < 4; i++)
430 strcat (buf, msymbol_name (tags[i]));
436 get_database_stream (MDatabaseInfo *db_info)
441 if (db_info->filename[0] == '/')
443 if (stat (db_info->filename, &buf) == 0
444 && (fp = fopen (db_info->filename, "r")))
445 db_info->time = MAX_TIME (buf.st_mtime, buf.st_ctime);
451 int filelen = strlen (db_info->filename);
454 MPLIST_DO (plist, mdatabase__dir_list)
456 MDatabaseInfo *dir_info = MPLIST_VAL (plist);
457 int require = strlen (dir_info->filename) + filelen + 1;
459 SAFE_ALLOCA (path, require);
460 strcpy (path, dir_info->filename);
461 strcat (path, db_info->filename);
462 if (stat (path, &buf) == 0
463 && (fp = fopen (path, "r")))
465 free (db_info->filename);
466 db_info->filename = strdup (path);
467 db_info->time = MAX_TIME (buf.st_mtime, buf.st_ctime);
477 load_database (MSymbol *tags, void *extra_info)
479 FILE *fp = get_database_stream ((MDatabaseInfo *) extra_info);
483 MERROR (MERROR_DB, NULL);
485 if (tags[0] == Mchar_table)
486 value = load_chartable (fp, tags[1]);
487 else if (tags[0] == Mcharset)
488 value = load_charset (fp, tags[1]);
490 value = mplist__from_file (fp, NULL);
494 MERROR (MERROR_DB, NULL);
499 /** If DIRNAME is a readable directory, allocate MDatabaseInfo and
500 copy DIRNAME to a newly allocated memory and return it. If
501 DIRNAME does not end with a slash, append a slash to the new memory. */
503 static MDatabaseInfo *
504 get_dir_info (char *dirname)
508 MDatabaseInfo *dir_info;
511 || stat (dirname, &buf) < 0
512 || ! (buf.st_mode & S_IFDIR))
515 MSTRUCT_MALLOC (dir_info, MERROR_DB);
516 len = strlen (dirname);
517 MTABLE_MALLOC (dir_info->filename, len + 2, MERROR_DB);
518 memcpy (dir_info->filename, dirname, len + 1);
519 if (dir_info->filename[len - 1] != '/')
521 dir_info->filename[len] = '/';
522 dir_info->filename[len + 1] = '\0';
524 /* Set this to zero so that the first call of update_database_list
525 surely checks this directory. */
531 find_database (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
535 for (i = 0; i < mdb_list.used; i++)
537 MDatabase *mdb = mdb_list.mdbs + i;
539 if (tag0 == mdb->tag[0]
540 && tag1 == mdb->tag[1]
541 && tag2 == mdb->tag[2]
542 && tag3 == mdb->tag[3])
549 update_database_list ()
555 /* Usually this avoids path to be reallocated. */
556 SAFE_ALLOCA (path, 256);
558 MPLIST_DO (plist, mdatabase__dir_list)
560 MDatabaseInfo *dir_info = MPLIST_VAL (plist);
566 if (stat (dir_info->filename, &statbuf) < 0)
568 if (dir_info->time >= statbuf.st_ctime
569 && dir_info->time >= statbuf.st_mtime)
571 dir_info->time = MAX_TIME (statbuf.st_ctime, statbuf.st_mtime);
572 len = strlen (dir_info->filename);
574 if (len + MDB_DIR_LEN >= PATH_MAX)
576 #endif /* PATH_MAX */
577 SAFE_ALLOCA (path, len + MDB_DIR_LEN + 1);
578 memcpy (path, dir_info->filename, len);
579 memcpy (path + len, MDB_DIR, MDB_DIR_LEN);
580 path[len + MDB_DIR_LEN] = '\0';
581 if (! (fp = fopen (path, "r")))
583 pl = mplist__from_file (fp, NULL);
593 int with_wildcard = 0;
595 if (! MPLIST_PLIST_P (p))
597 p1 = MPLIST_PLIST (p);
598 if (! MPLIST_SYMBOL_P (p1))
600 for (i = 0, p1 = MPLIST_PLIST (p);
601 i < 4 && MPLIST_KEY (p1) == Msymbol;
602 i++, p1 = MPLIST_NEXT (p1))
603 with_wildcard |= ((mdb.tag[i] = MPLIST_SYMBOL (p1)) == Masterisk);
605 || mdb.tag[0] == Masterisk
606 || ! MPLIST_MTEXT_P (p1))
610 mdb.loader = load_database;
611 mt = MPLIST_MTEXT (p1);
612 if (mt->format >= MTEXT_FORMAT_UTF_16LE)
613 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
614 nbytes = mtext_nbytes (mt);
616 if (nbytes > PATH_MAX)
618 #endif /* PATH_MAX */
620 && mdb.tag[0] != Mchar_table
621 && mdb.tag[0] != Mcharset)
626 SAFE_ALLOCA (path, len + nbytes + 1);
627 memcpy (path, dir_info->filename, len);
628 memcpy (path + len, mt->data, nbytes);
629 path[len + nbytes] = '\0';
631 if (glob (path, GLOB_NOSORT | GLOB_NOCHECK, NULL, &globbuf) != 0)
633 load_key = mplist ();
634 for (i = 0; i < globbuf.gl_pathc; i++)
636 if (! (fp = fopen (globbuf.gl_pathv[i], "r")))
638 p1 = mplist__from_file (fp, load_key);
642 if (MPLIST_PLIST_P (p1))
647 for (j = 0, p0 = MPLIST_PLIST (p1);
648 j < 4 && MPLIST_SYMBOL_P (p0);
649 j++, p0 = MPLIST_NEXT (p0))
650 mdb2.tag[j] = MPLIST_SYMBOL (p0);
653 for (j = 0; j < 4; j++)
654 if (mdb.tag[j] == Masterisk
655 ? mdb2.tag[j] == Mnil
656 : (mdb.tag[j] != Mnil && mdb.tag[j] != mdb2.tag[j]))
659 && ! find_database (mdb2.tag[0], mdb2.tag[1],
660 mdb2.tag[2], mdb2.tag[3]))
662 mdb2.loader = load_database;
663 mdb2.extra_info = calloc (1, sizeof (MDatabaseInfo));
664 if (! mdb2.extra_info)
665 MEMORY_FULL (MERROR_DB);
666 ((MDatabaseInfo*) mdb2.extra_info)->filename
667 = strdup (globbuf.gl_pathv[i]);
668 MLIST_APPEND1 (&mdb_list, mdbs, mdb2, MERROR_DB);
669 if (mdb2.tag[0] == Mchar_table
670 && mdb2.tag[2] != Mnil
671 && (mdb2.tag[1] == Mstring
672 || mdb2.tag[1] == Mtext
673 || mdb2.tag[1] == Msymbol
674 || mdb2.tag[1] == Minteger
675 || mdb2.tag[1] == Mplist))
676 mchar__define_prop (mdb2.tag[2], mdb2.tag[1],
678 + mdb_list.used - 1));
681 M17N_OBJECT_UNREF (p1);
683 M17N_OBJECT_UNREF (load_key);
688 if (find_database (mdb.tag[0], mdb.tag[1],
689 mdb.tag[2], mdb.tag[3]))
691 SAFE_ALLOCA (path, nbytes + 1);
692 memcpy (path, mt->data, nbytes);
694 mdb.extra_info = calloc (1, sizeof (MDatabaseInfo));
695 if (! mdb.extra_info)
696 MEMORY_FULL (MERROR_DB);
697 ((MDatabaseInfo*) mdb.extra_info)->filename = strdup (path);
698 MLIST_APPEND1 (&mdb_list, mdbs, mdb, MERROR_DB);
699 if (mdb.tag[0] == Mchar_table
700 && mdb.tag[2] != Mnil
701 && (mdb.tag[1] == Mstring
702 || mdb.tag[1] == Mtext
703 || mdb.tag[1] == Msymbol
704 || mdb.tag[1] == Minteger
705 || mdb.tag[1] == Mplist))
706 mchar__define_prop (mdb.tag[2], mdb.tag[1],
707 mdb_list.mdbs + mdb_list.used - 1);
710 M17N_OBJECT_UNREF (pl);
719 /** List of database directories. */
720 MPlist *mdatabase__dir_list;
725 MDatabaseInfo *dir_info;
727 Mchar_table = msymbol ("char-table");
728 Masterisk = msymbol ("*");
730 mdatabase__dir_list = mplist ();
731 /** The macro M17NDIR specifies a directory where the system-wide
732 MDB_DIR file exists. */
733 if ((dir_info = get_dir_info (M17NDIR)))
734 mplist_set (mdatabase__dir_list, Mt, dir_info);
736 /* The variable mdatabase_dir specifies a directory where an
737 application program specific MDB_DIR file exists. */
738 if ((dir_info = get_dir_info (mdatabase_dir)))
739 mplist_push (mdatabase__dir_list, Mt, dir_info);
741 /* The environment variable M17NDIR (if non-NULL) specifies a
742 directory where a user specific MDB_DIR file exists. */
743 if ((dir_info = get_dir_info (getenv ("M17NDIR"))))
744 mplist_push (mdatabase__dir_list, Mt, dir_info);
746 MLIST_INIT1 (&mdb_list, mdbs, 256);
747 update_database_list ();
749 mdatabase__finder = ((void *(*) (MSymbol, MSymbol, MSymbol, MSymbol))
751 mdatabase__loader = (void *(*) (void *)) mdatabase_load;
757 mdatabase__fini (void)
762 MPLIST_DO (plist, mdatabase__dir_list)
764 MDatabaseInfo *dir_info = MPLIST_VAL (plist);
766 free (dir_info->filename);
769 M17N_OBJECT_UNREF (mdatabase__dir_list);
771 for (i = 0; i < mdb_list.used; i++)
773 MDatabase *mdb = mdb_list.mdbs + i;
775 if (mdb->loader == load_database)
777 MDatabaseInfo *db_info = mdb->extra_info;
779 free (db_info->filename);
783 MLIST_FREE1 (&mdb_list, mdbs);
787 mdatabase__load_for_keys (MDatabase *mdb, MPlist *keys)
789 int mdebug_mask = MDEBUG_DATABASE;
794 if (mdb->loader != load_database
795 || mdb->tag[0] == Mchar_table
796 || mdb->tag[0] == Mcharset)
797 MERROR (MERROR_DB, NULL);
798 MDEBUG_PRINT1 (" [DATABASE] loading <%s>.\n",
799 gen_database_name (buf, mdb->tag));
800 fp = get_database_stream ((MDatabaseInfo *) mdb->extra_info);
802 MERROR (MERROR_DB, NULL);
803 plist = mplist__from_file (fp, keys);
809 /* Check if the database MDB should be reloaded or not. */
812 mdatabase__check (MDatabase *mdb)
814 MDatabaseInfo *db_info = (MDatabaseInfo *) mdb->extra_info;
817 if (stat (db_info->filename, &buf) < 0)
819 return (db_info->time >= buf.st_ctime
820 && db_info->time >= buf.st_mtime);
824 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
829 /*** @addtogroup m17nDatabase */
834 @brief Directory for application specific data.
836 If an application program wants to provide a data specific to the
837 program or a data overriding what supplied by the m17n database,
838 it must set this variable to a name of directory that contains the
839 data files before it calls the macro M17N_INIT (). The directory
840 may contain a file "mdb.dir" which contains a list of data
841 definitions in the format described in @ref mdbDir "mdbDir(5)".
843 The default value is NULL. */
845 @brief ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¸ÇͤΥǡ¼¥¿Íѥǥ£¥ì¥¯¥È¥ê.
847 ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤¬¡¢¤½¤Î¥×¥í¥°¥é¥à¸ÇͤΥǡ¼¥¿¤ä m17n
848 ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¾å½ñ¤¤¹¤ë¥Ç¡¼¥¿¤òÄ󶡤¹¤ë¾ì¹ç¤Ë¤Ï¡¢¥Þ¥¯¥í M17N_INIT ()
849 ¤ò¸Æ¤ÖÁ°¤Ë¤³¤ÎÊÑ¿ô¤ò¥Ç¡¼¥¿¥Õ¥¡¥¤¥ë¤ò´Þ¤à¥Ç¥£¥ì¥¯¥È¥ê̾¤Ë¥»¥Ã¥È¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¥Ç¥£¥ì¥¯¥È¥ê¤Ë¤Ï
850 "mdb.dir" ¥Õ¥¡¥¤¥ë¤ò¤ª¤¯¤³¤È¤¬¤Ç¤¤ë¡£¤½¤Î"mdb.dir"¥Õ¥¡¥¤¥ë¤Ë¤Ï¡¢
851 @ref mdbDir "mdbDir(5)" ¤ÇÀâÌÀ¤µ¤ì¤Æ¤¤¤ë¥Õ¥©¡¼¥Þ¥Ã¥È¤Ç¥Ç¡¼¥¿ÄêµÁ¤Î¥ê¥¹¥È¤òµ½Ò¤¹¤ë¡£
853 ¥Ç¥Õ¥©¥ë¥È¤ÎÃÍ¤Ï NULL ¤Ç¤¢¤ë¡£ */
859 @brief Look for a data in the database.
861 The mdatabase_find () function searches the m17n database for a
862 data who has tags $TAG0 through $TAG3, and returns a pointer to
863 the data. If such a data is not found, it returns @c NULL. */
866 @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Î¥Ç¡¼¥¿¤òõ¤¹.
868 ´Ø¿ô mdatabase_find () ¤Ï¡¢ m17n ¸À¸ì¾ðÊó¥Ù¡¼¥¹Ãæ¤Ç $TAG0 ¤«¤é
869 $TAG3 ¤Þ¤Ç¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¤òõ¤·¡¢¤½¤ì¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤Î¤è¤¦¤Ê¥Ç¡¼¥¿¤¬¤Ê¤±¤ì¤Ð
872 @latexonly \IPAlabel{mdatabase_find} @endlatexonly */
875 mdatabase_find (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
877 update_database_list ();
878 return find_database (tag0, tag1, tag2, tag3);
883 @brief Return a data list of the m17n database.
885 The mdatabase_list () function searches the m17n database for data
886 who have tags $TAG0 through $TAG3, and returns their list by a
887 plist. The value #Mnil in $TAGn means a wild card that matches
888 any tag. Each element of the plist has key #Mt and value a
889 pointer to type #MDatabase. */
891 @brief m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥Ç¡¼¥¿¥ê¥¹¥È¤òÊÖ¤¹.
893 ´Ø¿ô mdatabase_list () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é $TAG0 ¤«¤é$TAG3
894 ¤Þ¤Ç¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¤òõ¤·¡¢¤½¤Î¥ê¥¹¥È¤òplist ¤È¤·¤ÆÊÖ¤¹¡£ $TAGn ¤¬ #Mnil
895 ¤Ç¤¢¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢Ç¤°Õ¤Î¥¿¥°¤Ë¥Þ¥Ã¥Á¤¹¤ë¥ï¥¤¥ë¥É¥«¡¼¥É¤È¤·¤Æ¼è¤ê°·¤ï¤ì¤ë¡£ÊÖ¤µ¤ì¤ë
896 plist ¤Î³ÆÍ×ÁǤϥ¡¼ ¤È¤·¤Æ #Mt ¤ò¡¢ÃͤȤ·¤Æ #MDatabase ·¿¤Ø¤Î¥Ý¥¤¥ó¥¿¤ò»ý¤Ä¡£ */
899 mdatabase_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
902 MPlist *plist = NULL, *pl;
904 update_database_list ();
906 for (i = 0; i < mdb_list.used; i++)
908 MDatabase *mdb = mdb_list.mdbs + i;
910 if ((tag0 == Mnil || tag0 == mdb->tag[0])
911 && (tag1 == Mnil || tag1 == mdb->tag[1])
912 && (tag2 == Mnil || tag2 == mdb->tag[2])
913 && (tag3 == Mnil || tag3 == mdb->tag[3]))
916 plist = pl = mplist ();
917 pl = mplist_add (pl, Mt, mdb);
925 @brief Define a data of the m17n database.
927 The mdatabase_define () function defines a data that has tags
928 $TAG0 through $TAG3 and additional information $EXTRA_INFO.
930 $LOADER is a pointer to a function that loads the data from the
931 database. This function is called from the mdatabase_load ()
932 function with the two arguments $TAGS and $EXTRA_INFO. Here,
933 $TAGS is the array of $TAG0 through $TAG3.
935 If $LOADER is @c NULL, the default loader of the m17n library is
936 used. In this case, $EXTRA_INFO must be a string specifying a
937 filename that contains the data.
940 If the operation was successful, mdatabase_define () returns a
941 pointer to the defined data, which can be used as an argument to
942 mdatabase_load (). Otherwise, it returns @c NULL. */
945 @brief m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥Ç¡¼¥¿¤òÄêµÁ¤¹¤ë.
947 ´Ø¿ô mdatabase_define () ¤Ï $TAG0 ¤«¤é $TAG3 ¤Þ¤Ç¤Î¥¿¥°¤ª¤è¤ÓÉղþðÊó
948 $EXTRA_INFO ¤ò»ý¤Ä¥Ç¡¼¥¿¤òÄêµÁ¤¹¤ë¡£
950 $LOADER ¤Ï¤½¤Î¥Ç¡¼¥¿¤Î¥í¡¼¥É¤ËÍѤ¤¤é¤ì¤ë´Ø¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¤³¤Î´Ø¿ô¤Ï
951 mdatabase_load () ¤«¤é $TAGS ¤È $EXTRA_INFO ¤È¤¤¤¦Æó¤Ä¤Î°ú¿ôÉÕ¤¤Ç¸Æ¤Ó½Ð¤µ¤ì¤ë¡£¤³¤³¤Ç
952 $TAGS ¤Ï $TAG0 ¤«¤é $TAG3 ¤Þ¤Ç¤ÎÇÛÎó¤Ç¤¢¤ë¡£
954 ¤â¤· $LOADER ¤¬ @c NULL ¤Ê¤é¡¢m17n ¥é¥¤¥Ö¥é¥êɸ½à¤Î¥í¡¼¥À¤¬»È¤ï¤ì¤ë¡£¤³¤Î¾ì¹ç¤Ë¤Ï
955 $EXTRA_INFO ¤Ï¥Ç¡¼¥¿¤ò´Þ¤à¥Õ¥¡¥¤¥ë̾¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
958 ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mdatabase_define ()
959 ¤ÏÄêµÁ¤µ¤ì¤¿¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤³¤Î¥Ý¥¤¥ó¥¿¤Ï´Ø¿ô mdatabase_load ()
960 ¤Î°ú¿ô¤È¤·¤ÆÍѤ¤¤ë¤³¤È¤¬¤Ç¤¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£
962 @latexonly \IPAlabel{mdatabase_define} @endlatexonly */
966 mdatabase_load (), mdatabase_define () */
969 mdatabase_define (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3,
970 void *(*loader) (MSymbol *, void *),
975 mdb = mdatabase_find (tag0, tag1, tag2, tag3);
980 template.tag[0] = tag0, template.tag[1] = tag1;
981 template.tag[2] = tag2, template.tag[3] = tag3;
982 template.extra_info = NULL;
983 MLIST_APPEND1 (&mdb_list, mdbs, template, MERROR_DB);
984 mdb = mdb_list.mdbs + (mdb_list.used - 1);
986 mdb->loader = loader ? loader : load_database;
987 if (mdb->loader == load_database)
989 MDatabaseInfo *db_info = mdb->extra_info;
992 free (db_info->filename);
994 db_info = mdb->extra_info = malloc (sizeof (MDatabaseInfo));
995 db_info->filename = strdup ((char *) extra_info);
999 mdb->extra_info = extra_info;
1000 return (&(mdb_list.mdbs[mdb_list.used - 1]));
1005 @brief Load a data from the database.
1007 The mdatabase_load () function loads a data specified in $MDB and
1008 returns the contents. The type of contents depends on the type of
1011 If the data is of the @e plist @e type, this function returns a
1012 pointer to @e plist.
1014 If the database is of the @e chartable @e type, it returns a
1015 chartable. The default value of the chartable is set according to
1016 the second tag of the data as below:
1018 @li If the tag is #Msymbol, the default value is #Mnil.
1019 @li If the tag is #Minteger, the default value is -1.
1020 @li Otherwise, the default value is @c NULL.
1022 If the data is of the @e charset @e type, it returns a plist of length 2
1023 (keys are both #Mt). The value of the first element is an array
1024 of integers that maps code points to the corresponding character
1025 codes. The value of the second element is a chartable of integers
1026 that does the reverse mapping. The charset must be defined in
1031 @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹¤«¤é¥Ç¡¼¥¿¤ò¥í¡¼¥É¤¹¤ë.
1033 ´Ø¿ô mdatabase_load () ¤Ï $MDB
1034 ¤¬»Ø¤¹¥Ç¡¼¥¿¤ò¥í¡¼¥É¤·¡¢¤½¤ÎÃæ¿È¤òÊÖ¤¹¡£ÊÖ¤µ¤ì¤ë¤â¤Î¤Ï¥Ç¡¼¥¿¤Î¥¿¥¤¥×¤Ë¤è¤Ã¤Æ°Û¤Ê¤ë¡£
1036 ¥Ç¡¼¥¿¤¬ @e plist¥¿¥¤¥× ¤Ê¤é¤Ð¡¢ @e plist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
1038 ¥Ç¡¼¥¿¤¬ @e chartable¥¿¥¤¥× ¤Ê¤é¤Ðʸ»ú¥Æ¡¼¥Ö¥ë¤òÊÖ¤¹¡£
1039 ʸ»ú¥Æ¡¼¥Ö¥ë¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤϡ¢¥Ç¡¼¥¿¤ÎÂè2¥¿¥°¤Ë¤è¤Ã¤Æ°Ê²¼¤Î¤è¤¦¤Ë·è¤Þ¤ë¡£
1041 @li ¥¿¥°¤¬ #Msymbol ¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï #Mnil
1042 @li ¥¿¥°¤¬ #Minteger ¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï -1
1043 @li ¤½¤ì°Ê³°¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï @c NULL
1045 ¥Ç¡¼¥¿¤¬ @e charset¥¿¥¤¥× ¤Ê¤é¤ÐŤµ 2 ¤Î plist ¤òÊÖ¤¹¡Ê¥¡¼¤Ï¶¦¤Ë#Mt ¡Ë¡£
1046 ºÇ½é¤ÎÍ×ÁǤÎÃͤϥ³¡¼¥É¥Ý¥¤¥ó¥È¤òÂбþ¤¹¤ëʸ»ú¥³¡¼¥É¤Ë¥Þ¥Ã¥×¤¹¤ëÀ°¿ô¤ÎÇÛÎó¤Ç¤¢¤ë¡£
1047 £²ÈÖÌܤÎÍ×ÁǤÎÃͤϵդΥޥåפò¤¹¤ëʸ»ú¥Æ¡¼¥Ö¥ë¤Ç¤¢¤ë¡£
1048 ¤³¤Îʸ»ú¥»¥Ã¥È¤Ïͽ¤áÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
1050 @latexonly \IPAlabel{mdatabase_load} @endlatexonly
1055 mdatabase_load (), mdatabase_define () */
1058 mdatabase_load (MDatabase *mdb)
1060 int mdebug_mask = MDEBUG_DATABASE;
1063 MDEBUG_PRINT1 (" [DATABASE] loading <%s>.\n",
1064 gen_database_name (buf, mdb->tag));
1065 return (*mdb->loader) (mdb->tag, mdb->extra_info);
1070 @brief Get tags of a data.
1072 The mdatabase_tag () function returns an array of tags (symbols)
1073 that identify the data in $MDB. The length of the array is
1077 @brief ¥Ç¡¼¥¿¤Î¥¿¥°¤òÆÀ¤ë.
1079 ´Ø¿ô mdatabase_tag () ¤Ï¡¢¥Ç¡¼¥¿ $MDB ¤Î¥¿¥°¡Ê¥·¥ó¥Ü¥ë¡Ë¤ÎÇÛÎó¤òÊÖ¤¹¡£ÇÛÎó¤ÎŤµ¤Ï
1082 @latexonly \IPAlabel{mdatabase_tag} @endlatexonly */
1085 mdatabase_tag (MDatabase *mdb)