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., 51 Franklin Street, Fifth Floor,
24 @addtogroup m17nDatabase
25 @brief The m17n database and API for it.
27 The m17n library acquires various kinds of information
28 from data in the <i> m17n database</i> on demand. Application
29 programs can also add/load their original data to/from the m17n
30 database by setting the variable #mdatabase_dir to an
31 application-specific directory and storing data in it. Users can
32 overwrite those data by storing preferable data in the directory
33 specified by the environment variable "M17NDIR", or if it is not
34 set, in the directory "~/.m17n.d".
36 The m17n database contains multiple heterogeneous data, and each
37 data is identified by four tags; TAG0, TAG1, TAG2, TAG3. Each tag
40 TAG0 specifies the type of data stored in the database as below.
43 If TAG0 is #Mchar_table, the data is of the @e chartable @e
44 type and provides information about each character. In this case,
45 TAG1 specifies the type of the information and must be #Msymbol,
46 #Minteger, #Mstring, #Mtext, or #Mplist. TAG2 and TAG3 can be any
50 If TAG0 is #Mcharset, the data is of the @e charset @e type
51 and provides a decode/encode mapping table for a charset. In this
52 case, TAG1 must be a symbol representing a charset. TAG2 and TAG3
56 If TAG0 is neither #Mchar_table nor #Mcharset, the data is of
57 the @e plist @e type. See the documentation of the
58 mdatabase_load () function for the details.
59 In this case, TAG1, TAG2, and TAG3 can be any symbols.
61 The notation \<TAG0, TAG1, TAG2, TAG3\> means a data with those
64 Application programs first calls the mdatabase_find () function to
65 get a pointer to an object of the type #MDatabase. That object
66 holds information about the specified data. When it is
67 successfully returned, the mdatabase_load () function loads the
68 data. The implementation of the structure #MDatabase is
69 concealed from application programs.
73 @addtogroup m17nDatabase
74 @brief m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤È¤½¤ì¤Ë´Ø¤¹¤ë API.
76 m17n ¥é¥¤¥Ö¥é¥ê¤ÏɬÍפ˱þ¤¸¤ÆưŪ¤Ë @e m17n @e ¥Ç¡¼¥¿¥Ù¡¼¥¹
77 ¤«¤é¾ðÊó¤ò¼èÆÀ¤¹¤ë¡£¤Þ¤¿¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤â¡¢Æȼ«¤Î¥Ç¡¼¥¿¤ò
78 m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ËÄɲä·¡¢¤½¤ì¤òưŪ¤Ë¼èÆÀ¤¹¤ë¤³¤È¤¬¤Ç¤¤ë¡£
79 ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤¬Æȼ«¤Î¥Ç¡¼¥¿¤òÄɲᦼèÆÀ¤¹¤ë¤Ë¤Ï¡¢ÊÑ¿ô
80 #mdatabase_dir ¤Ë¤½¤Î¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¸ÇͤΥǥ£¥ì¥¯¥È¥ê¤ò¥»¥Ã¥È¤·¡¢
81 ¤½¤ÎÃæ¤Ë¥Ç¡¼¥¿¤ò³ÊǼ¤¹¤ë¡£¥æ¡¼¥¶¤¬¤½¤Î¥Ç¡¼¥¿¤ò¥ª¡¼¥Ð¡¼¥é¥¤¥È¤·¤¿¤¤
82 ¤È¤¤Ï¡¢´Ä¶ÊÑ¿ô "M17NDIR" ¤Ç»ØÄꤵ¤ì¤ë¥Ç¥£¥ì¥¯¥È¥ê¡Ê»ØÄꤵ¤ì¤Æ¤¤¤Ê
83 ¤¤¤È¤¤Ï "~/.m17n.d" ¤È¤¤¤¦¥Ç¥£¥ì¥¯¥È¥ê¡Ë¤ËÊ̤Υǡ¼¥¿¤òÃÖ¤¯¡£
86 ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤ÏÊ£¿ô¤Î¿Íͤʥǡ¼¥¿¤¬´Þ¤Þ¤ì¤Æ¤ª¤ê¡¢³Æ¥Ç¡¼¥¿¤Ï
87 TAG0, TAG1, TAG2, TAG3¡Ê¤¹¤Ù¤Æ¥·¥ó¥Ü¥ë¡Ë¤Î£´¤Ä¤Î¥¿¥°¤Ë¤è¤Ã¤Æ¼±Ê̤µ¤ì¤ë¡£
89 TAG0 ¤Ë¤è¤Ã¤Æ¡¢¥Ç¡¼¥¿¥Ù¡¼¥¹Æâ¤Î¥Ç¡¼¥¿¤Î¥¿¥¤¥×¤Ï¼¡¤Î¤è¤¦¤Ë»ØÄꤵ¤ì¤ë¡£
92 TAG0 ¤¬ #Mchar_table ¤Ç¤¢¤ë¥Ç¡¼¥¿¤Ï @e chartable¥¿¥¤¥×
93 ¤È¸Æ¤Ð¤ì¡¢³Æʸ»ú¤Ë´Ø¤¹¤ë¾ðÊó¤òÄ󶡤¹¤ë¡£¤³¤Î¾ì¹ç
94 TAG1 ¤Ï¾ðÊó¤Î¼ïÎà¤ò»ØÄꤹ¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢#Msymbol, #Minteger, #Mstring,
95 #Mtext, #Mplist ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£TAG2 ¤È TAG3 ¤ÏǤ°Õ¤Î¥·¥ó¥Ü¥ë¤Ç¤è¤¤¡£
98 TAG0 ¤¬ #Mcharset ¤Ç¤¢¤ë¥Ç¡¼¥¿¤Ï @e charset¥¿¥¤¥×
99 ¤È¸Æ¤Ð¤ì¡¢Ê¸»ú¥»¥Ã¥ÈÍѤΥǥ³¡¼¥É¡¿¥¨¥ó¥³¡¼¥É¥Þ¥Ã¥×¤òÄ󶡤¹¤ë¡£¤³¤Î¾ì¹ç TAG1
100 ¤Ïʸ»ú¥»¥Ã¥È¤Î¥·¥ó¥Ü¥ë¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£TAG2 ¤È TAG3
101 ¤ÏǤ°Õ¤Î¥·¥ó¥Ü¥ë¤Ç¤è¤¤¡£
104 TAG0 ¤¬ #Mchar_table ¤Ç¤â #Mcharset ¤Ç¤â¤Ê¤¤¾ì¹ç¡¢¤½¤Î¥Ç¡¼¥¿¤Ï @e
105 plist¥¿¥¤¥× ¤Ç¤¢¤ë¡£¾ÜºÙ¤Ë´Ø¤·¤Æ¤Ï´Ø¿ô mdatabase_load ()
106 ¤ÎÀâÌÀ¤ò»²¾È¤Î¤³¤È¡£¤³¤Î¾ì¹ç TAG1¡¢TAG2¡¢TAG3 ¤ÏǤ°Õ¤Î¥·¥ó¥Ü¥ë¤Ç¤è¤¤¡£
108 ÆÃÄê¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò \<TAG0, TAG1, TAG2, TAG3\>
111 ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï¡¢¤Þ¤º´Ø¿ô mdatabase_find ()
112 ¤ò»È¤Ã¤Æ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÝ»ý¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¡Ê#MDatabase
113 ·¿¡Ë¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÆÀ¤ë¡£¤½¤ì¤ËÀ®¸ù¤·¤¿¤é¡¢ mdatabase_load ()
114 ¤Ë¤è¤Ã¤Æ¼ÂºÝ¤Ë¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¥í¡¼¥É¤¹¤ë¡£¹½Â¤ÂÎ #MDatabase
115 ¼«¿È¤¬¤É¤¦¼ÂÁõ¤µ¤ì¤Æ¤¤¤ë¤«¤Ï¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤«¤é¤Ï¸«¤¨¤Ê¤¤¡£
117 @latexonly \IPAlabel{database} @endlatexonly
122 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
123 /*** @addtogroup m17nInternal
131 #include <sys/types.h>
132 #include <sys/stat.h>
140 #include "m17n-misc.h"
141 #include "internal.h"
143 #include "character.h"
145 #include "database.h"
149 /** The file containing a list of databases. */
150 #define MDB_DIR "mdb.dir"
151 /** Length of MDB_DIR. */
152 #define MDB_DIR_LEN 7
154 #define MAX_TIME(TIME1, TIME2) ((TIME1) >= (TIME2) ? (TIME1) : (TIME2))
156 #define GEN_PATH(path, dir, dir_len, file, file_len) \
157 (dir_len + file_len > PATH_MAX ? 0 \
158 : (memcpy (path, dir, dir_len), \
159 memcpy (path + dir_len, file, file_len), \
160 path[dir_len + file_len] = '\0', 1))
162 static MSymbol Masterisk;
163 static MSymbol Mversion;
165 /** Structure for a data in the m17n database. */
169 /** Tags to identify the data. <tag>[0] specifies the type of
170 database. If it is #Mchar_table, the type is @e chartable, if
171 it is #Mcharset, the type is @e charset, otherwise the type is
175 void *(*loader) (MSymbol *tags, void *extra_info);
177 /** The meaning of the value is dependent on <loader>. If <loader>
178 is load_database (), the value is a string of the file name that
179 contains the data. */
183 static MPlist *mdatabase__list;
186 read_number (char *buf, int *i)
195 while (c && isspace (c)) c = buf[idx++];
201 for (idx++, c = 0; (n = hex_mnemonic[(unsigned) buf[idx]]) < 16;
215 n = escape_mnemonic[c];
219 while (buf[idx] && buf[idx++] != '\'');
223 else if (hex_mnemonic[c] < 10)
228 while ((n = hex_mnemonic[(unsigned) buf[idx]]) < 10)
229 c = (c * 10) + n, idx++;
235 /** Load a data of type @c chartable from the file FD, and return the
236 newly created chartable. */
239 load_chartable (FILE *fp, MSymbol type)
247 MERROR (MERROR_DB, NULL);
249 table = mchartable (type, (type == Msymbol ? (void *) Mnil
250 : type == Minteger ? (void *) -1
257 for (len = 0; len < 1023 && (c = getc (fp)) != EOF && c != '\n'; len++)
260 if (hex_mnemonic[(unsigned) buf[0]] >= 10)
261 /* skip comment/invalid line */
264 from = read_number (buf, &i);
266 i++, to = read_number (buf, &i);
269 if (from < 0 || to < from)
272 while (buf[i] && isspace ((unsigned) buf[i])) i++;
279 /* VAL is a C-string. */
280 if (! (val = strdup (buf + i)))
281 MEMORY_FULL (MERROR_DB);
283 else if (type == Minteger)
285 /* VAL is an integer. */
291 n = read_number (buf, &i);
294 val = (void *) (n * positive);
296 else if (type == Mtext)
298 /* VAL is an M-text. */
301 mt = mconv_decode_buffer (Mcoding_utf_8,
302 (unsigned char *) (buf + i),
307 while ((c = read_number (buf, &i)) >= 0)
308 mt = mtext_cat_char (mt, c);
312 else if (type == Msymbol)
316 while (*p && ! isspace (*p))
318 if (*p == '\\' && p[1] != '\0')
320 memmove (p, p + 1, buf + len - (p + 1));
326 if (! strcmp (buf + i, "nil"))
329 val = (void *) msymbol (buf + i);
331 else if (type == Mplist)
333 val = (void *) mplist__from_string ((unsigned char *) buf + i,
340 mchartable_set (table, from, val);
342 mchartable_set_range (table, from, to, val);
347 M17N_OBJECT_UNREF (table);
348 MERROR (MERROR_DB, NULL);
352 /** Load a data of type @c charset from the file FD. */
355 load_charset (FILE *fp, MSymbol charset_name)
357 MCharset *charset = MCHARSET (charset_name);
366 MERROR (MERROR_DB, NULL);
367 size = (charset->code_range[15]
368 - (charset->min_code - charset->code_range_min_code));
369 MTABLE_MALLOC (decoder, size, MERROR_DB);
370 for (i = 0; i < size; i++)
372 encoder = mchartable (Minteger, (void *) MCHAR_INVALID_CODE);
374 while ((c = getc (fp)) != EOF)
376 unsigned code1, code2, c1, c2;
381 fgets (buf, 256, fp);
384 if (sscanf (buf, "0x%x-0x%x 0x%x", &code1, &code2, &c1) == 3)
386 idx1 = CODE_POINT_TO_INDEX (charset, code1);
389 idx2 = CODE_POINT_TO_INDEX (charset, code2);
392 c2 = c1 + (idx2 - idx1);
394 else if (sscanf (buf, "0x%x 0x%x", &code1, &c1) == 2)
396 idx1 = idx2 = CODE_POINT_TO_INDEX (charset, code1);
403 if (idx1 >= 0 && idx2 >= 0)
406 mchartable_set (encoder, c1, (void *) code1);
407 for (idx1++, c1++; idx1 <= idx2; idx1++, c1++)
409 code1 = INDEX_TO_CODE_POINT (charset, idx1);
411 mchartable_set (encoder, c1, (void *) code1);
421 M17N_OBJECT_UNREF (encoder);
425 mplist_add (plist, Mt, decoder);
426 mplist_add (plist, Mt, encoder);
431 gen_database_name (char *buf, MSymbol *tags)
435 strcpy (buf, msymbol_name (tags[0]));
436 for (i = 1; i < 4; i++)
439 strcat (buf, msymbol_name (tags[i]));
445 find_file (MDatabaseInfo *db_info, struct stat *buf)
448 char path[PATH_MAX + 1];
450 MPLIST_DO (plist, mdatabase__dir_list)
452 MDatabaseInfo *dir_info = MPLIST_VAL (plist);
454 if (dir_info->status != MDB_STATUS_DISABLED
455 && GEN_PATH (path, dir_info->filename, dir_info->len,
456 db_info->filename, db_info->len)
457 && stat (path, buf) == 0)
458 return strdup (path);
464 /* Return the absolute file name for DB_INFO->filename. If BUF is
465 non-NULL, store the result of `stat' call in it. It returns NULL
466 if no absolute file name was found. */
469 get_database_file (MDatabaseInfo *db_info, struct stat *buf)
471 if (db_info->status == MDB_STATUS_DISABLED)
473 if (db_info->absolute_filename)
476 stat (db_info->absolute_filename, buf);
480 struct stat stat_buf;
481 struct stat *statbuf = buf ? buf : &stat_buf;
483 db_info->absolute_filename = find_file (db_info, statbuf);
486 return db_info->absolute_filename;
490 load_database (MSymbol *tags, void *extra_info)
492 MDatabaseInfo *db_info = extra_info;
494 char *filename = get_database_file (db_info, NULL);
496 int mdebug_mask = MDEBUG_DATABASE;
499 MDEBUG_PRINT1 (" [DB] <%s>", gen_database_name (buf, tags));
500 if (! filename || ! (fp = fopen (filename, "r")))
503 MDEBUG_PRINT1 (" open fail: %s\n", filename);
505 MDEBUG_PRINT1 (" not found: %s\n", db_info->filename);
506 MERROR (MERROR_DB, NULL);
509 MDEBUG_PRINT1 (" from %s\n", filename);
511 if (tags[0] == Mchar_table)
512 value = load_chartable (fp, tags[1]);
513 else if (tags[0] == Mcharset)
514 value = load_charset (fp, tags[1]);
516 value = mplist__from_file (fp, NULL);
520 MERROR (MERROR_DB, NULL);
521 db_info->time = time (NULL);
526 /** Return a newly allocated MDatabaseInfo for DIRNAME. */
528 static MDatabaseInfo *
529 get_dir_info (char *dirname)
531 MDatabaseInfo *dir_info;
533 MSTRUCT_CALLOC (dir_info, MERROR_DB);
536 int len = strlen (dirname);
538 if (len + MDB_DIR_LEN < PATH_MAX)
540 MTABLE_MALLOC (dir_info->filename, len + 2, MERROR_DB);
541 memcpy (dir_info->filename, dirname, len + 1);
542 /* Append PATH_SEPARATOR if DIRNAME doesn't end with it. */
543 if (dir_info->filename[len - 1] != PATH_SEPARATOR)
545 dir_info->filename[len] = PATH_SEPARATOR;
546 dir_info->filename[++len] = '\0';
549 dir_info->status = MDB_STATUS_OUTDATED;
552 dir_info->status = MDB_STATUS_DISABLED;
555 dir_info->status = MDB_STATUS_DISABLED;
559 static void register_databases_in_files (MSymbol tags[4],
560 char *filename, int len);
563 find_database (MSymbol tags[4])
569 if (! mdatabase__list)
571 for (i = 0, plist = mdatabase__list; i < 4; i++)
573 MPlist *pl = mplist__assq (plist, tags[i]);
576 if ((p = mplist__assq (plist, Masterisk)))
578 MDatabaseInfo *db_info;
581 p = MPLIST_PLIST (p);
582 for (j = i + 1; j < 4; j++)
583 p = MPLIST_PLIST (MPLIST_NEXT (p));
584 mdb = MPLIST_VAL (MPLIST_NEXT (p));
585 db_info = mdb->extra_info;
586 if (db_info->status != MDB_STATUS_DISABLED)
588 register_databases_in_files (mdb->tag,
589 db_info->filename, db_info->len);
590 db_info->status = MDB_STATUS_DISABLED;
591 return find_database (tags);
596 plist = MPLIST_PLIST (pl);
597 plist = MPLIST_NEXT (plist);
599 mdb = MPLIST_VAL (plist);
604 free_db_info (MDatabaseInfo *db_info)
606 free (db_info->filename);
607 if (db_info->absolute_filename
608 && db_info->filename != db_info->absolute_filename)
609 free (db_info->absolute_filename);
610 M17N_OBJECT_UNREF (db_info->properties);
615 check_version (MText *version)
617 char *verstr = (char *) MTEXT_DATA (version);
618 char *endp = verstr + mtext_nbytes (version);
622 ver[0] = ver[1] = ver[2] = 0;
623 for (i = 0; verstr < endp; verstr++)
632 if (! isdigit (*verstr))
634 ver[i] = ver[i] * 10 + (*verstr - '0');
636 return (ver[0] < M17NLIB_MAJOR_VERSION
637 || (ver[0] == M17NLIB_MAJOR_VERSION
638 && (ver[1] < M17NLIB_MINOR_VERSION
639 || (ver[1] == M17NLIB_MINOR_VERSION
640 && ver[2] <= M17NLIB_PATCH_LEVEL))));
644 register_database (MSymbol tags[4],
645 void *(*loader) (MSymbol *, void *),
646 void *extra_info, enum MDatabaseStatus status,
650 MDatabaseInfo *db_info;
656 MPLIST_DO (plist, properties)
657 if (MPLIST_PLIST_P (plist))
659 MPlist *p = MPLIST_PLIST (plist);
661 if (MPLIST_SYMBOL_P (p)
662 && MPLIST_SYMBOL (p) == Mversion
663 && MPLIST_MTEXT_P (MPLIST_NEXT (p)))
665 if (check_version (MPLIST_MTEXT (MPLIST_NEXT (p))))
672 for (i = 0, plist = mdatabase__list; i < 4; i++)
674 MPlist *pl = mplist__assq (plist, tags[i]);
677 pl = MPLIST_PLIST (pl);
681 mplist_add (pl, Msymbol, tags[i]);
682 mplist_push (plist, Mplist, pl);
683 M17N_OBJECT_UNREF (pl);
685 plist = MPLIST_NEXT (pl);
688 if (MPLIST_TAIL_P (plist))
690 MSTRUCT_MALLOC (mdb, MERROR_DB);
691 for (i = 0; i < 4; i++)
692 mdb->tag[i] = tags[i];
693 mdb->loader = loader;
694 if (loader == load_database)
696 MSTRUCT_CALLOC (db_info, MERROR_DB);
697 mdb->extra_info = db_info;
702 mdb->extra_info = extra_info;
704 mplist_push (plist, Mt, mdb);
708 mdb = MPLIST_VAL (plist);
709 if (loader == load_database)
710 db_info = mdb->extra_info;
717 db_info->status = status;
718 if (! db_info->filename
719 || strcmp (db_info->filename, (char *) extra_info) != 0)
721 if (db_info->filename)
722 free (db_info->filename);
723 if (db_info->absolute_filename
724 && db_info->filename != db_info->absolute_filename)
725 free (db_info->absolute_filename);
726 db_info->filename = strdup ((char *) extra_info);
727 db_info->len = strlen ((char *) extra_info);
730 if (db_info->filename[0] == PATH_SEPARATOR)
731 db_info->absolute_filename = db_info->filename;
733 db_info->absolute_filename = NULL;
734 M17N_OBJECT_UNREF (db_info->properties);
737 db_info->properties = properties;
738 M17N_OBJECT_REF (properties);
742 if (mdb->tag[0] == Mchar_table
743 && mdb->tag[2] != Mnil
744 && (mdb->tag[1] == Mstring || mdb->tag[1] == Mtext
745 || mdb->tag[1] == Msymbol || mdb->tag[1] == Minteger
746 || mdb->tag[1] == Mplist))
747 mchar__define_prop (mdb->tag[2], mdb->tag[1], mdb);
752 register_databases_in_files (MSymbol tags[4], char *filename, int len)
755 MPlist *load_key = mplist ();
759 MPLIST_DO (plist, mdatabase__dir_list)
764 if (filename[0] == PATH_SEPARATOR)
766 if (glob (filename, GLOB_NOSORT, NULL, &globbuf))
772 MDatabaseInfo *d_info = MPLIST_VAL (plist);
773 char path[PATH_MAX + 1];
775 if (d_info->status == MDB_STATUS_DISABLED)
777 if (! GEN_PATH (path, d_info->filename, d_info->len, filename, len))
779 if (glob (path, GLOB_NOSORT, NULL, &globbuf))
781 headlen = d_info->len;
784 for (i = 0; i < globbuf.gl_pathc; i++)
786 if (! (fp = fopen (globbuf.gl_pathv[i], "r")))
788 pl = mplist__from_file (fp, load_key);
792 if (MPLIST_PLIST_P (pl))
797 for (j = 0, p = MPLIST_PLIST (pl); j < 4 && MPLIST_SYMBOL_P (p);
798 j++, p = MPLIST_NEXT (p))
799 tags2[j] = MPLIST_SYMBOL (p);
802 for (j = 0; j < 4; j++)
803 if (tags[j] != Masterisk && tags[j] != tags2[j])
806 register_database (tags2, load_database,
807 globbuf.gl_pathv[i] + headlen,
810 M17N_OBJECT_UNREF (pl);
813 if (filename[0] == PATH_SEPARATOR)
816 M17N_OBJECT_UNREF (load_key);
822 /** List of database directories. */
823 MPlist *mdatabase__dir_list;
828 MDatabaseInfo *dir_info;
831 Mchar_table = msymbol ("char-table");
832 Masterisk = msymbol ("*");
833 Mversion = msymbol ("version");
835 mdatabase__dir_list = mplist ();
836 /** The macro M17NDIR specifies a directory where the system-wide
837 MDB_DIR file exists. */
838 mplist_set (mdatabase__dir_list, Mt, get_dir_info (M17NDIR));
840 /* The variable mdatabase_dir specifies a directory where an
841 application program specific MDB_DIR file exists. */
842 if (mdatabase_dir && strlen (mdatabase_dir) > 0)
843 mplist_push (mdatabase__dir_list, Mt, get_dir_info (mdatabase_dir));
845 /* The environment variable M17NDIR specifies a directory where a
846 user specific MDB_DIR file exists. */
847 path = getenv ("M17NDIR");
848 if (path && strlen (path) > 0)
849 mplist_push (mdatabase__dir_list, Mt, get_dir_info (path));
852 /* If the env var M17NDIR is not set, check "~/.m17n.d". */
853 char *home = getenv ("HOME");
857 && (len = strlen (home))
858 && (path = alloca (len + 9)))
861 if (path[len - 1] != PATH_SEPARATOR)
862 path[len++] = PATH_SEPARATOR;
863 strcpy (path + len, ".m17n.d");
864 dir_info = get_dir_info (path);
865 mplist_push (mdatabase__dir_list, Mt, dir_info);
868 mplist_push (mdatabase__dir_list, Mt, get_dir_info (NULL));
871 mdatabase__finder = ((void *(*) (MSymbol, MSymbol, MSymbol, MSymbol))
873 mdatabase__loader = (void *(*) (void *)) mdatabase_load;
875 mdatabase__list = mplist ();
876 mdatabase__update ();
881 mdatabase__fini (void)
883 MPlist *plist, *p0, *p1, *p2, *p3;
885 MPLIST_DO (plist, mdatabase__dir_list)
886 free_db_info (MPLIST_VAL (plist));
887 M17N_OBJECT_UNREF (mdatabase__dir_list);
889 /* MDATABASE_LIST ::= ((TAG0 (TAG1 (TAG2 (TAG3 t:MDB) ...) ...) ...) ...) */
890 MPLIST_DO (plist, mdatabase__list)
892 p0 = MPLIST_PLIST (plist);
893 /* P0 ::= (TAG0 (TAG1 (TAG2 (TAG3 t:MDB) ...) ...) ...) */
894 MPLIST_DO (p0, MPLIST_NEXT (p0))
896 p1 = MPLIST_PLIST (p0);
897 /* P1 ::= (TAG1 (TAG2 (TAG3 t:MDB) ...) ...) */
898 MPLIST_DO (p1, MPLIST_NEXT (p1))
900 p2 = MPLIST_PLIST (p1);
901 /* P2 ::= (TAG2 (TAG3 t:MDB) ...) */
902 MPLIST_DO (p2, MPLIST_NEXT (p2))
906 p3 = MPLIST_PLIST (p2); /* P3 ::= (TAG3 t:MDB) */
907 p3 = MPLIST_NEXT (p3);
908 mdb = MPLIST_VAL (p3);
909 if (mdb->loader == load_database)
910 free_db_info (mdb->extra_info);
916 M17N_OBJECT_UNREF (mdatabase__list);
920 mdatabase__update (void)
922 MPlist *plist, *p0, *p1, *p2, *p3;
923 char path[PATH_MAX + 1];
924 MDatabaseInfo *dir_info;
928 /* Update elements of mdatabase__dir_list. */
929 MPLIST_DO (plist, mdatabase__dir_list)
931 dir_info = MPLIST_VAL (plist);
932 if (dir_info->filename)
934 if (stat (dir_info->filename, &statbuf) == 0
935 && (statbuf.st_mode & S_IFDIR))
937 if (dir_info->time < statbuf.st_mtime)
940 dir_info->time = statbuf.st_mtime;
942 if (GEN_PATH (path, dir_info->filename, dir_info->len,
943 MDB_DIR, MDB_DIR_LEN)
944 && stat (path, &statbuf) >= 0
945 && dir_info->time < statbuf.st_mtime)
948 dir_info->time = statbuf.st_mtime;
950 dir_info->status = MDB_STATUS_UPDATED;
954 if (dir_info->status != MDB_STATUS_DISABLED)
958 dir_info->status = MDB_STATUS_DISABLED;
967 /* At first, mark all databases defined automatically from mdb.dir
968 file(s) as "disabled". */
969 MPLIST_DO (plist, mdatabase__list)
971 p0 = MPLIST_PLIST (plist);
972 /* P0 ::= (TAG0 (TAG1 (TAG2 (TAG3 MDB) ...) ...) ...) */
973 MPLIST_DO (p0, MPLIST_NEXT (p0))
975 p1 = MPLIST_PLIST (p0);
976 MPLIST_DO (p1, MPLIST_NEXT (p1))
978 p2 = MPLIST_PLIST (p1);
979 MPLIST_DO (p2, MPLIST_NEXT (p2))
982 MDatabaseInfo *db_info;
984 p3 = MPLIST_PLIST (p2);
985 p3 = MPLIST_NEXT (p3);
986 mdb = MPLIST_VAL (p3);
987 db_info = mdb->extra_info;
988 if (db_info->status == MDB_STATUS_AUTO)
989 db_info->status = MDB_STATUS_DISABLED;
996 MPLIST_DO (p0, mdatabase__dir_list)
997 mplist_push (plist, MPLIST_KEY (p0), MPLIST_VAL (p0));
999 while (! MPLIST_TAIL_P (plist))
1001 MDatabaseInfo *dir_info = mplist_pop (plist);
1006 if (dir_info->status == MDB_STATUS_DISABLED)
1008 if (! GEN_PATH (path, dir_info->filename, dir_info->len,
1009 MDB_DIR, MDB_DIR_LEN))
1011 if (! (fp = fopen (path, "r")))
1013 pl = mplist__from_file (fp, NULL);
1023 int with_wildcard = 0;
1025 if (! MPLIST_PLIST_P (p))
1027 for (i = 0, p1 = MPLIST_PLIST (p); i < 4 && MPLIST_SYMBOL_P (p1);
1028 i++, p1 = MPLIST_NEXT (p1))
1029 with_wildcard |= ((tags[i] = MPLIST_SYMBOL (p1)) == Masterisk);
1031 || tags[0] == Masterisk
1032 || ! MPLIST_MTEXT_P (p1))
1035 tags[i] = with_wildcard ? Masterisk : Mnil;
1036 mt = MPLIST_MTEXT (p1);
1037 nbytes = mtext_nbytes (mt);
1038 if (nbytes > PATH_MAX)
1040 memcpy (path, MTEXT_DATA (mt), nbytes);
1041 path[nbytes] = '\0';
1043 register_database (tags, load_database, path,
1044 MDB_STATUS_AUTO_WILDCARD, NULL);
1046 register_database (tags, load_database, path,
1047 MDB_STATUS_AUTO, p1);
1049 M17N_OBJECT_UNREF (pl);
1051 M17N_OBJECT_UNREF (plist);
1055 mdatabase__load_for_keys (MDatabase *mdb, MPlist *keys)
1057 int mdebug_mask = MDEBUG_DATABASE;
1058 MDatabaseInfo *db_info;
1064 if (mdb->loader != load_database
1065 || mdb->tag[0] == Mchar_table
1066 || mdb->tag[0] == Mcharset)
1067 MERROR (MERROR_DB, NULL);
1068 MDEBUG_PRINT1 (" [DB] <%s>.\n",
1069 gen_database_name (name, mdb->tag));
1070 db_info = mdb->extra_info;
1071 filename = get_database_file (db_info, NULL);
1072 if (! filename || ! (fp = fopen (filename, "r")))
1073 MERROR (MERROR_DB, NULL);
1074 plist = mplist__from_file (fp, keys);
1080 /* Check if the database MDB should be reloaded or not. It returns:
1082 1: The database has not been updated since it was loaded last
1085 0: The database has never been loaded or has been updated
1086 since it was loaded last time.
1088 -1: The database is not loadable at the moment. */
1091 mdatabase__check (MDatabase *mdb)
1093 MDatabaseInfo *db_info = (MDatabaseInfo *) mdb->extra_info;
1096 if (! get_database_file (db_info, &buf))
1098 if (db_info->time < buf.st_mtime)
1100 if (db_info->status == MDB_STATUS_AUTO
1101 && db_info->filename != db_info->absolute_filename)
1105 mdatabase__update ();
1106 new = find_database (mdb->tag);
1114 /* Search directories in mdatabase__dir_list for file FILENAME. If
1115 the file exist, return the absolute pathname. If FILENAME is
1116 already absolute, return a copy of it. */
1119 mdatabase__find_file (char *filename)
1122 MDatabaseInfo db_info;
1124 if (filename[0] == PATH_SEPARATOR)
1125 return (stat (filename, &buf) == 0 ? filename : NULL);
1126 db_info.filename = filename;
1127 db_info.len = strlen (filename);
1129 db_info.absolute_filename = NULL;
1130 if (! get_database_file (&db_info, &buf)
1131 || stat (db_info.absolute_filename, &buf) < 0)
1133 return db_info.absolute_filename;
1137 mdatabase__file (MDatabase *mdb)
1139 MDatabaseInfo *db_info;
1141 if (mdb->loader != load_database)
1143 db_info = mdb->extra_info;
1144 return get_database_file (db_info, NULL);
1148 mdatabase__lock (MDatabase *mdb)
1150 MDatabaseInfo *db_info;
1156 if (mdb->loader != load_database)
1158 db_info = mdb->extra_info;
1159 if (db_info->lock_file)
1161 file = get_database_file (db_info, NULL);
1164 len = strlen (file);
1165 db_info->uniq_file = malloc (len + 35);
1166 if (! db_info->uniq_file)
1168 db_info->lock_file = malloc (len + 5);
1169 if (! db_info->lock_file)
1171 free (db_info->uniq_file);
1174 sprintf (db_info->uniq_file, "%s.%X.%X", db_info->absolute_filename,
1175 (unsigned) time (NULL), (unsigned) getpid ());
1176 sprintf (db_info->lock_file, "%s.LCK", db_info->absolute_filename);
1178 fp = fopen (db_info->uniq_file, "w");
1181 char *str = strdup (db_info->uniq_file);
1182 char *dir = dirname (str);
1184 if (stat (dir, &buf) == 0
1185 || mkdir (dir, 0777) < 0
1186 || ! (fp = fopen (db_info->uniq_file, "w")))
1188 free (db_info->uniq_file);
1189 free (db_info->lock_file);
1190 db_info->lock_file = NULL;
1197 if (link (db_info->uniq_file, db_info->lock_file) < 0
1198 && (stat (db_info->uniq_file, &buf) < 0
1199 || buf.st_nlink != 2))
1201 unlink (db_info->uniq_file);
1202 unlink (db_info->lock_file);
1203 free (db_info->uniq_file);
1204 free (db_info->lock_file);
1205 db_info->lock_file = NULL;
1212 mdatabase__save (MDatabase *mdb, MPlist *data)
1214 MDatabaseInfo *db_info;
1220 if (mdb->loader != load_database)
1222 db_info = mdb->extra_info;
1223 if (! db_info->lock_file)
1225 file = get_database_file (db_info, NULL);
1229 if (mplist__serialize (mt, data, 1) < 0)
1231 M17N_OBJECT_UNREF (mt);
1234 fp = fopen (db_info->uniq_file, "w");
1237 M17N_OBJECT_UNREF (mt);
1240 mconv_encode_stream (msymbol ("utf-8"), mt, fp);
1241 M17N_OBJECT_UNREF (mt);
1243 if ((ret = rename (db_info->uniq_file, file)) < 0)
1244 unlink (db_info->uniq_file);
1245 free (db_info->uniq_file);
1246 db_info->uniq_file = NULL;
1251 mdatabase__unlock (MDatabase *mdb)
1253 MDatabaseInfo *db_info;
1255 if (mdb->loader != load_database)
1257 db_info = mdb->extra_info;
1258 if (! db_info->lock_file)
1260 unlink (db_info->lock_file);
1261 free (db_info->lock_file);
1262 db_info->lock_file = NULL;
1263 if (db_info->uniq_file)
1265 unlink (db_info->uniq_file);
1266 free (db_info->uniq_file);
1272 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1277 /*** @addtogroup m17nDatabase */
1282 @brief Directory for application specific data.
1284 If an application program wants to provide a data specific to the
1285 program or a data overriding what supplied by the m17n database,
1286 it must set this variable to a name of directory that contains the
1287 data files before it calls the macro M17N_INIT (). The directory
1288 may contain a file "mdb.dir" which contains a list of data
1289 definitions in the format described in @ref mdbDir "mdbDir(5)".
1291 The default value is NULL. */
1293 @brief ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¸ÇͤΥǡ¼¥¿Íѥǥ£¥ì¥¯¥È¥ê.
1295 ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤¬¡¢¤½¤Î¥×¥í¥°¥é¥à¸ÇͤΥǡ¼¥¿¤ä m17n
1296 ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¾å½ñ¤¤¹¤ë¥Ç¡¼¥¿¤òÄ󶡤¹¤ë¾ì¹ç¤Ë¤Ï¡¢¥Þ¥¯¥í M17N_INIT ()
1297 ¤ò¸Æ¤ÖÁ°¤Ë¤³¤ÎÊÑ¿ô¤ò¥Ç¡¼¥¿¥Õ¥¡¥¤¥ë¤ò´Þ¤à¥Ç¥£¥ì¥¯¥È¥ê̾¤Ë¥»¥Ã¥È¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¥Ç¥£¥ì¥¯¥È¥ê¤Ë¤Ï
1298 "mdb.dir" ¥Õ¥¡¥¤¥ë¤ò¤ª¤¯¤³¤È¤¬¤Ç¤¤ë¡£¤½¤Î"mdb.dir"¥Õ¥¡¥¤¥ë¤Ë¤Ï¡¢
1299 @ref mdbDir "mdbDir(5)" ¤ÇÀâÌÀ¤µ¤ì¤Æ¤¤¤ë¥Õ¥©¡¼¥Þ¥Ã¥È¤Ç¥Ç¡¼¥¿ÄêµÁ¤Î¥ê¥¹¥È¤òµ½Ò¤¹¤ë¡£
1301 ¥Ç¥Õ¥©¥ë¥È¤ÎÃÍ¤Ï NULL ¤Ç¤¢¤ë¡£ */
1303 char *mdatabase_dir;
1307 @brief Look for a data in the database.
1309 The mdatabase_find () function searches the m17n database for a
1310 data who has tags $TAG0 through $TAG3, and returns a pointer to
1311 the data. If such a data is not found, it returns @c NULL. */
1314 @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Î¥Ç¡¼¥¿¤òõ¤¹.
1316 ´Ø¿ô mdatabase_find () ¤Ï¡¢ m17n ¸À¸ì¾ðÊó¥Ù¡¼¥¹Ãæ¤Ç $TAG0 ¤«¤é
1317 $TAG3 ¤Þ¤Ç¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¤òõ¤·¡¢¤½¤ì¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤Î¤è¤¦¤Ê¥Ç¡¼¥¿¤¬¤Ê¤±¤ì¤Ð
1320 @latexonly \IPAlabel{mdatabase_find} @endlatexonly */
1323 mdatabase_find (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
1327 mdatabase__update ();
1328 tags[0] = tag0, tags[1] = tag1, tags[2] = tag2, tags[3] = tag3;
1329 return find_database (tags);
1334 @brief Return a data list of the m17n database.
1336 The mdatabase_list () function searches the m17n database for data
1337 who have tags $TAG0 through $TAG3, and returns their list by a
1338 plist. The value #Mnil in $TAGn means a wild card that matches
1339 any tag. Each element of the plist has key #Mt and value a
1340 pointer to type #MDatabase. */
1342 @brief m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥Ç¡¼¥¿¥ê¥¹¥È¤òÊÖ¤¹.
1344 ´Ø¿ô mdatabase_list () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é $TAG0 ¤«¤é$TAG3
1345 ¤Þ¤Ç¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¤òõ¤·¡¢¤½¤Î¥ê¥¹¥È¤òplist ¤È¤·¤ÆÊÖ¤¹¡£ $TAGn ¤¬ #Mnil
1346 ¤Ç¤¢¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢Ç¤°Õ¤Î¥¿¥°¤Ë¥Þ¥Ã¥Á¤¹¤ë¥ï¥¤¥ë¥É¥«¡¼¥É¤È¤·¤Æ¼è¤ê°·¤ï¤ì¤ë¡£ÊÖ¤µ¤ì¤ë
1347 plist ¤Î³ÆÍ×ÁǤϥ¡¼ ¤È¤·¤Æ #Mt ¤ò¡¢ÃͤȤ·¤Æ #MDatabase ·¿¤Ø¤Î¥Ý¥¤¥ó¥¿¤ò»ý¤Ä¡£ */
1350 mdatabase_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
1352 MPlist *plist = mplist (), *pl = plist;
1353 MPlist *p, *p0, *p1, *p2, *p3;
1355 MDatabaseInfo *db_info;
1357 mdatabase__update ();
1359 MPLIST_DO (p, mdatabase__list)
1361 p0 = MPLIST_PLIST (p);
1362 /* P0 ::= (TAG0 (TAG1 (TAG2 (TAG3 MDB) ...) ...) ...) */
1363 if (MPLIST_SYMBOL (p0) == Masterisk
1364 || (tag0 != Mnil && MPLIST_SYMBOL (p0) != tag0))
1366 MPLIST_DO (p0, MPLIST_NEXT (p0))
1368 p1 = MPLIST_PLIST (p0);
1369 if (MPLIST_SYMBOL (p1) == Masterisk)
1371 p1 = MPLIST_PLIST (MPLIST_NEXT (p1));
1372 p1 = MPLIST_PLIST (MPLIST_NEXT (p1));
1373 mdb = MPLIST_VAL (MPLIST_NEXT (p1));
1374 if (mdb->loader == load_database
1375 && (db_info = mdb->extra_info)
1376 && db_info->status != MDB_STATUS_DISABLED)
1378 register_databases_in_files (mdb->tag,
1379 db_info->filename, db_info->len);
1380 db_info->status = MDB_STATUS_DISABLED;
1381 M17N_OBJECT_UNREF (plist);
1382 return mdatabase_list (tag0, tag1, tag2, tag3);
1386 if (tag1 != Mnil && MPLIST_SYMBOL (p1) != tag1)
1388 MPLIST_DO (p1, MPLIST_NEXT (p1))
1390 p2 = MPLIST_PLIST (p1);
1391 if (MPLIST_SYMBOL (p2) == Masterisk
1392 || (tag2 != Mnil && MPLIST_SYMBOL (p2) != tag2))
1394 MPLIST_DO (p2, MPLIST_NEXT (p2))
1396 p3 = MPLIST_PLIST (p2);
1397 if (MPLIST_SYMBOL (p3) == Masterisk
1398 || (tag3 != Mnil && MPLIST_SYMBOL (p3) != tag3))
1400 p3 = MPLIST_NEXT (p3);
1401 pl = mplist_add (pl, Mt, MPLIST_VAL (p3));
1406 if (MPLIST_TAIL_P (plist))
1407 M17N_OBJECT_UNREF (plist);
1413 @brief Define a data of the m17n database.
1415 The mdatabase_define () function defines a data that has tags
1416 $TAG0 through $TAG3 and additional information $EXTRA_INFO.
1418 $LOADER is a pointer to a function that loads the data from the
1419 database. This function is called from the mdatabase_load ()
1420 function with the two arguments $TAGS and $EXTRA_INFO. Here,
1421 $TAGS is the array of $TAG0 through $TAG3.
1423 If $LOADER is @c NULL, the default loader of the m17n library is
1424 used. In this case, $EXTRA_INFO must be a string specifying a
1425 filename that contains the data.
1428 If the operation was successful, mdatabase_define () returns a
1429 pointer to the defined data, which can be used as an argument to
1430 mdatabase_load (). Otherwise, it returns @c NULL. */
1433 @brief m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥Ç¡¼¥¿¤òÄêµÁ¤¹¤ë.
1435 ´Ø¿ô mdatabase_define () ¤Ï $TAG0 ¤«¤é $TAG3 ¤Þ¤Ç¤Î¥¿¥°¤ª¤è¤ÓÉղþðÊó
1436 $EXTRA_INFO ¤ò»ý¤Ä¥Ç¡¼¥¿¤òÄêµÁ¤¹¤ë¡£
1438 $LOADER ¤Ï¤½¤Î¥Ç¡¼¥¿¤Î¥í¡¼¥É¤ËÍѤ¤¤é¤ì¤ë´Ø¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¤³¤Î´Ø¿ô¤Ï
1439 mdatabase_load () ¤«¤é $TAGS ¤È $EXTRA_INFO ¤È¤¤¤¦Æó¤Ä¤Î°ú¿ôÉÕ¤¤Ç¸Æ¤Ó½Ð¤µ¤ì¤ë¡£¤³¤³¤Ç
1440 $TAGS ¤Ï $TAG0 ¤«¤é $TAG3 ¤Þ¤Ç¤ÎÇÛÎó¤Ç¤¢¤ë¡£
1442 ¤â¤· $LOADER ¤¬ @c NULL ¤Ê¤é¡¢m17n ¥é¥¤¥Ö¥é¥êɸ½à¤Î¥í¡¼¥À¤¬»È¤ï¤ì¤ë¡£¤³¤Î¾ì¹ç¤Ë¤Ï
1443 $EXTRA_INFO ¤Ï¥Ç¡¼¥¿¤ò´Þ¤à¥Õ¥¡¥¤¥ë̾¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
1446 ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mdatabase_define ()
1447 ¤ÏÄêµÁ¤µ¤ì¤¿¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤³¤Î¥Ý¥¤¥ó¥¿¤Ï´Ø¿ô mdatabase_load ()
1448 ¤Î°ú¿ô¤È¤·¤ÆÍѤ¤¤ë¤³¤È¤¬¤Ç¤¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£
1450 @latexonly \IPAlabel{mdatabase_define} @endlatexonly */
1454 mdatabase_load (), mdatabase_define () */
1457 mdatabase_define (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3,
1458 void *(*loader) (MSymbol *, void *),
1464 tags[0] = tag0, tags[1] = tag1, tags[2] = tag2, tags[3] = tag3;
1466 loader = load_database;
1467 mdb = register_database (tags, loader, extra_info, MDB_STATUS_EXPLICIT, NULL);
1473 @brief Load a data from the database.
1475 The mdatabase_load () function loads a data specified in $MDB and
1476 returns the contents. The type of contents depends on the type of
1479 If the data is of the @e plist @e type, this function returns a
1480 pointer to @e plist.
1482 If the database is of the @e chartable @e type, it returns a
1483 chartable. The default value of the chartable is set according to
1484 the second tag of the data as below:
1486 @li If the tag is #Msymbol, the default value is #Mnil.
1487 @li If the tag is #Minteger, the default value is -1.
1488 @li Otherwise, the default value is @c NULL.
1490 If the data is of the @e charset @e type, it returns a plist of length 2
1491 (keys are both #Mt). The value of the first element is an array
1492 of integers that maps code points to the corresponding character
1493 codes. The value of the second element is a chartable of integers
1494 that does the reverse mapping. The charset must be defined in
1499 @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹¤«¤é¥Ç¡¼¥¿¤ò¥í¡¼¥É¤¹¤ë.
1501 ´Ø¿ô mdatabase_load () ¤Ï $MDB
1502 ¤¬»Ø¤¹¥Ç¡¼¥¿¤ò¥í¡¼¥É¤·¡¢¤½¤ÎÃæ¿È¤òÊÖ¤¹¡£ÊÖ¤µ¤ì¤ë¤â¤Î¤Ï¥Ç¡¼¥¿¤Î¥¿¥¤¥×¤Ë¤è¤Ã¤Æ°Û¤Ê¤ë¡£
1504 ¥Ç¡¼¥¿¤¬ @e plist¥¿¥¤¥× ¤Ê¤é¤Ð¡¢ @e plist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
1506 ¥Ç¡¼¥¿¤¬ @e chartable¥¿¥¤¥× ¤Ê¤é¤Ðʸ»ú¥Æ¡¼¥Ö¥ë¤òÊÖ¤¹¡£
1507 ʸ»ú¥Æ¡¼¥Ö¥ë¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤϡ¢¥Ç¡¼¥¿¤ÎÂè2¥¿¥°¤Ë¤è¤Ã¤Æ°Ê²¼¤Î¤è¤¦¤Ë·è¤Þ¤ë¡£
1509 @li ¥¿¥°¤¬ #Msymbol ¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï #Mnil
1510 @li ¥¿¥°¤¬ #Minteger ¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï -1
1511 @li ¤½¤ì°Ê³°¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï @c NULL
1513 ¥Ç¡¼¥¿¤¬ @e charset¥¿¥¤¥× ¤Ê¤é¤ÐŤµ 2 ¤Î plist ¤òÊÖ¤¹¡Ê¥¡¼¤Ï¶¦¤Ë#Mt ¡Ë¡£
1514 ºÇ½é¤ÎÍ×ÁǤÎÃͤϥ³¡¼¥É¥Ý¥¤¥ó¥È¤òÂбþ¤¹¤ëʸ»ú¥³¡¼¥É¤Ë¥Þ¥Ã¥×¤¹¤ëÀ°¿ô¤ÎÇÛÎó¤Ç¤¢¤ë¡£
1515 £²ÈÖÌܤÎÍ×ÁǤÎÃͤϵդΥޥåפò¤¹¤ëʸ»ú¥Æ¡¼¥Ö¥ë¤Ç¤¢¤ë¡£
1516 ¤³¤Îʸ»ú¥»¥Ã¥È¤Ïͽ¤áÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
1518 @latexonly \IPAlabel{mdatabase_load} @endlatexonly
1523 mdatabase_load (), mdatabase_define () */
1526 mdatabase_load (MDatabase *mdb)
1528 return (*mdb->loader) (mdb->tag, mdb->extra_info);
1533 @brief Get tags of a data.
1535 The mdatabase_tag () function returns an array of tags (symbols)
1536 that identify the data in $MDB. The length of the array is
1540 @brief ¥Ç¡¼¥¿¤Î¥¿¥°¤òÆÀ¤ë.
1542 ´Ø¿ô mdatabase_tag () ¤Ï¡¢¥Ç¡¼¥¿ $MDB ¤Î¥¿¥°¡Ê¥·¥ó¥Ü¥ë¡Ë¤ÎÇÛÎó¤òÊÖ¤¹¡£ÇÛÎó¤ÎŤµ¤Ï
1545 @latexonly \IPAlabel{mdatabase_tag} @endlatexonly */
1548 mdatabase_tag (MDatabase *mdb)