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;
164 /** Structure for a data in the m17n database. */
168 /** Tags to identify the data. <tag>[0] specifies the type of
169 database. If it is #Mchar_table, the type is @e chartable, if
170 it is #Mcharset, the type is @e charset, otherwise the type is
174 void *(*loader) (MSymbol *tags, void *extra_info);
176 /** The meaning of the value is dependent on <loader>. If <loader>
177 is load_database (), the value is a string of the file name that
178 contains the data. */
182 static MPlist *mdatabase__list;
185 read_number (char *buf, int *i)
194 while (c && isspace (c)) c = buf[idx++];
200 for (idx++, c = 0; (n = hex_mnemonic[(unsigned) buf[idx]]) < 16;
214 n = escape_mnemonic[c];
218 while (buf[idx] && buf[idx++] != '\'');
222 else if (hex_mnemonic[c] < 10)
227 while ((n = hex_mnemonic[(unsigned) buf[idx]]) < 10)
228 c = (c * 10) + n, idx++;
234 /** Load a data of type @c chartable from the file FD, and return the
235 newly created chartable. */
238 load_chartable (FILE *fp, MSymbol type)
246 MERROR (MERROR_DB, NULL);
248 table = mchartable (type, (type == Msymbol ? (void *) Mnil
249 : type == Minteger ? (void *) -1
256 for (len = 0; len < 1023 && (c = getc (fp)) != EOF && c != '\n'; len++)
259 if (hex_mnemonic[(unsigned) buf[0]] >= 10)
260 /* skip comment/invalid line */
263 from = read_number (buf, &i);
265 i++, to = read_number (buf, &i);
268 if (from < 0 || to < from)
271 while (buf[i] && isspace ((unsigned) buf[i])) i++;
278 /* VAL is a C-string. */
279 if (! (val = strdup (buf + i)))
280 MEMORY_FULL (MERROR_DB);
282 else if (type == Minteger)
284 /* VAL is an integer. */
290 n = read_number (buf, &i);
293 val = (void *) (n * positive);
295 else if (type == Mtext)
297 /* VAL is an M-text. */
300 mt = mconv_decode_buffer (Mcoding_utf_8,
301 (unsigned char *) (buf + i),
306 while ((c = read_number (buf, &i)) >= 0)
307 mt = mtext_cat_char (mt, c);
311 else if (type == Msymbol)
315 while (*p && ! isspace (*p))
317 if (*p == '\\' && p[1] != '\0')
319 memmove (p, p + 1, buf + len - (p + 1));
325 if (! strcmp (buf + i, "nil"))
328 val = (void *) msymbol (buf + i);
330 else if (type == Mplist)
332 val = (void *) mplist__from_string ((unsigned char *) buf + i,
339 mchartable_set (table, from, val);
341 mchartable_set_range (table, from, to, val);
346 M17N_OBJECT_UNREF (table);
347 MERROR (MERROR_DB, NULL);
351 /** Load a data of type @c charset from the file FD. */
354 load_charset (FILE *fp, MSymbol charset_name)
356 MCharset *charset = MCHARSET (charset_name);
365 MERROR (MERROR_DB, NULL);
366 size = (charset->code_range[15]
367 - (charset->min_code - charset->code_range_min_code));
368 MTABLE_MALLOC (decoder, size, MERROR_DB);
369 for (i = 0; i < size; i++)
371 encoder = mchartable (Minteger, (void *) MCHAR_INVALID_CODE);
373 while ((c = getc (fp)) != EOF)
375 unsigned code1, code2, c1, c2;
380 fgets (buf, 256, fp);
383 if (sscanf (buf, "0x%x-0x%x 0x%x", &code1, &code2, &c1) == 3)
385 idx1 = CODE_POINT_TO_INDEX (charset, code1);
388 idx2 = CODE_POINT_TO_INDEX (charset, code2);
391 c2 = c1 + (idx2 - idx1);
393 else if (sscanf (buf, "0x%x 0x%x", &code1, &c1) == 2)
395 idx1 = idx2 = CODE_POINT_TO_INDEX (charset, code1);
402 if (idx1 >= 0 && idx2 >= 0)
405 mchartable_set (encoder, c1, (void *) code1);
406 for (idx1++, c1++; idx1 <= idx2; idx1++, c1++)
408 code1 = INDEX_TO_CODE_POINT (charset, idx1);
410 mchartable_set (encoder, c1, (void *) code1);
420 M17N_OBJECT_UNREF (encoder);
424 mplist_add (plist, Mt, decoder);
425 mplist_add (plist, Mt, encoder);
430 gen_database_name (char *buf, MSymbol *tags)
434 strcpy (buf, msymbol_name (tags[0]));
435 for (i = 1; i < 4; i++)
438 strcat (buf, msymbol_name (tags[i]));
444 find_file (MDatabaseInfo *db_info, struct stat *buf)
447 char path[PATH_MAX + 1];
449 MPLIST_DO (plist, mdatabase__dir_list)
451 MDatabaseInfo *dir_info = MPLIST_VAL (plist);
453 if (dir_info->status != MDB_STATUS_DISABLED
454 && GEN_PATH (path, dir_info->filename, dir_info->len,
455 db_info->filename, db_info->len)
456 && stat (path, buf) == 0)
457 return strdup (path);
463 /* Return the absolute file name for DB_INFO->filename. If BUF is
464 non-NULL, store the result of `stat' call in it. It returns NULL
465 if no absolute file name was found. */
468 get_database_file (MDatabaseInfo *db_info, struct stat *buf)
470 if (db_info->status == MDB_STATUS_DISABLED)
472 if (db_info->absolute_filename)
475 stat (db_info->absolute_filename, buf);
479 struct stat stat_buf;
480 struct stat *statbuf = buf ? buf : &stat_buf;
482 db_info->absolute_filename = find_file (db_info, statbuf);
485 return db_info->absolute_filename;
489 load_database (MSymbol *tags, void *extra_info)
491 MDatabaseInfo *db_info = extra_info;
493 char *filename = get_database_file (db_info, NULL);
495 int mdebug_mask = MDEBUG_DATABASE;
498 MDEBUG_PRINT1 (" [DB] <%s>", gen_database_name (buf, tags));
499 if (! filename || ! (fp = fopen (filename, "r")))
502 MDEBUG_PRINT1 (" open fail: %s\n", filename);
504 MDEBUG_PRINT1 (" not found: %s\n", db_info->filename);
505 MERROR (MERROR_DB, NULL);
508 MDEBUG_PRINT1 (" from %s\n", filename);
510 if (tags[0] == Mchar_table)
511 value = load_chartable (fp, tags[1]);
512 else if (tags[0] == Mcharset)
513 value = load_charset (fp, tags[1]);
515 value = mplist__from_file (fp, NULL);
519 MERROR (MERROR_DB, NULL);
520 db_info->time = time (NULL);
525 /** Return a newly allocated MDatabaseInfo for DIRNAME. */
527 static MDatabaseInfo *
528 get_dir_info (char *dirname)
530 MDatabaseInfo *dir_info;
532 MSTRUCT_CALLOC (dir_info, MERROR_DB);
535 int len = strlen (dirname);
537 if (len + MDB_DIR_LEN < PATH_MAX)
539 MTABLE_MALLOC (dir_info->filename, len + 2, MERROR_DB);
540 memcpy (dir_info->filename, dirname, len + 1);
541 /* Append PATH_SEPARATOR if DIRNAME doesn't end with it. */
542 if (dir_info->filename[len - 1] != PATH_SEPARATOR)
544 dir_info->filename[len] = PATH_SEPARATOR;
545 dir_info->filename[++len] = '\0';
548 dir_info->status = MDB_STATUS_AUTO;
551 dir_info->status = MDB_STATUS_DISABLED;
554 dir_info->status = MDB_STATUS_DISABLED;
559 find_database (MSymbol tags[4])
564 if (! mdatabase__list)
566 for (i = 0, plist = mdatabase__list; i < 4; i++)
568 plist = mplist__assq (plist, tags[i]);
571 plist = MPLIST_PLIST (plist);
572 plist = MPLIST_NEXT (plist);
574 return MPLIST_VAL (plist);
578 free_db_info (MDatabaseInfo *db_info)
580 free (db_info->filename);
581 if (db_info->absolute_filename
582 && db_info->filename != db_info->absolute_filename)
583 free (db_info->absolute_filename);
588 register_database (MSymbol tags[4], void *(*loader) (MSymbol *, void *),
589 void *extra_info, enum MDatabaseStatus status)
591 MDatabase *mdb = find_database (tags);
592 MDatabaseInfo *db_info = NULL;
596 if (loader == load_database)
597 db_info = mdb->extra_info;
604 MSTRUCT_MALLOC (mdb, MERROR_DB);
605 for (i = 0; i < 4; i++)
606 mdb->tag[i] = tags[i];
607 mdb->loader = loader;
608 if (loader == load_database)
610 MSTRUCT_CALLOC (db_info, MERROR_DB);
611 mdb->extra_info = db_info;
614 mdb->extra_info = extra_info;
615 if (! mdatabase__list)
616 mdatabase__list = mplist ();
617 for (i = 0, plist = mdatabase__list; i < 4; i++)
619 MPlist *pl = mplist__assq (plist, tags[i]);
622 pl = MPLIST_PLIST (pl);
626 mplist_add (pl, Msymbol, tags[i]);
627 mplist_push (plist, Mplist, pl);
628 M17N_OBJECT_UNREF (pl);
630 plist = MPLIST_NEXT (pl);
632 mplist_push (plist, Mt, mdb);
637 db_info->status = status;
638 if (! db_info->filename
639 || strcmp (db_info->filename, (char *) extra_info) != 0)
641 if (db_info->filename)
642 free (db_info->filename);
643 if (db_info->absolute_filename
644 && db_info->filename != db_info->absolute_filename)
645 free (db_info->absolute_filename);
646 db_info->filename = strdup ((char *) extra_info);
647 db_info->len = strlen ((char *) extra_info);
650 if (db_info->filename[0] == PATH_SEPARATOR)
651 db_info->absolute_filename = db_info->filename;
653 db_info->absolute_filename = NULL;
656 if (mdb->tag[0] == Mchar_table
657 && mdb->tag[2] != Mnil
658 && (mdb->tag[1] == Mstring || mdb->tag[1] == Mtext
659 || mdb->tag[1] == Msymbol || mdb->tag[1] == Minteger
660 || mdb->tag[1] == Mplist))
661 mchar__define_prop (mdb->tag[2], mdb->tag[1], mdb);
666 register_databases_in_files (MSymbol tags[4], glob_t *globbuf, int headlen)
669 MPlist *load_key = mplist ();
673 for (i = 0; i < globbuf->gl_pathc; i++)
675 if (! (fp = fopen (globbuf->gl_pathv[i], "r")))
677 plist = mplist__from_file (fp, load_key);
681 if (MPLIST_PLIST_P (plist))
686 for (j = 0, pl = MPLIST_PLIST (plist); j < 4 && MPLIST_SYMBOL_P (pl);
687 j++, pl = MPLIST_NEXT (pl))
688 tags2[j] = MPLIST_SYMBOL (pl);
691 for (j = 0; j < 4; j++)
692 if (tags[j] == Masterisk ? tags2[j] == Mnil
693 : (tags[j] != Mnil && tags[j] != tags2[j]))
696 register_database (tags2, load_database,
697 globbuf->gl_pathv[i] + headlen,
700 M17N_OBJECT_UNREF (plist);
702 M17N_OBJECT_UNREF (load_key);
708 /** List of database directories. */
709 MPlist *mdatabase__dir_list;
714 MDatabaseInfo *dir_info;
717 Mchar_table = msymbol ("char-table");
718 Masterisk = msymbol ("*");
720 mdatabase__dir_list = mplist ();
721 /** The macro M17NDIR specifies a directory where the system-wide
722 MDB_DIR file exists. */
723 mplist_set (mdatabase__dir_list, Mt, get_dir_info (M17NDIR));
725 /* The variable mdatabase_dir specifies a directory where an
726 application program specific MDB_DIR file exists. */
727 if (mdatabase_dir && strlen (mdatabase_dir) > 0)
728 mplist_push (mdatabase__dir_list, Mt, get_dir_info (mdatabase_dir));
730 /* The environment variable M17NDIR specifies a directory where a
731 user specific MDB_DIR file exists. */
732 path = getenv ("M17NDIR");
733 if (path && strlen (path) > 0)
734 mplist_push (mdatabase__dir_list, Mt, get_dir_info (path));
737 /* If the env var M17NDIR is not set, check "~/.m17n.d". */
738 char *home = getenv ("HOME");
742 && (len = strlen (home))
743 && (path = alloca (len + 9)))
746 if (path[len - 1] != PATH_SEPARATOR)
747 path[len++] = PATH_SEPARATOR;
748 strcpy (path + len, ".m17n.d");
749 dir_info = get_dir_info (path);
750 mplist_push (mdatabase__dir_list, Mt, dir_info);
753 mplist_push (mdatabase__dir_list, Mt, get_dir_info (NULL));
756 mdatabase__finder = ((void *(*) (MSymbol, MSymbol, MSymbol, MSymbol))
758 mdatabase__loader = (void *(*) (void *)) mdatabase_load;
760 mdatabase__list = mplist ();
761 mdatabase__update ();
766 mdatabase__fini (void)
768 MPlist *plist, *p0, *p1, *p2, *p3;
770 MPLIST_DO (plist, mdatabase__dir_list)
771 free_db_info (MPLIST_VAL (plist));
772 M17N_OBJECT_UNREF (mdatabase__dir_list);
774 /* MDATABASE_LIST ::= ((TAG0 (TAG1 (TAG2 (TAG3 t:MDB) ...) ...) ...) ...) */
775 MPLIST_DO (plist, mdatabase__list)
777 p0 = MPLIST_PLIST (plist);
778 /* P0 ::= (TAG0 (TAG1 (TAG2 (TAG3 t:MDB) ...) ...) ...) */
779 MPLIST_DO (p0, MPLIST_NEXT (p0))
781 p1 = MPLIST_PLIST (p0);
782 /* P1 ::= (TAG1 (TAG2 (TAG3 t:MDB) ...) ...) */
783 MPLIST_DO (p1, MPLIST_NEXT (p1))
785 p2 = MPLIST_PLIST (p1);
786 /* P2 ::= (TAG2 (TAG3 t:MDB) ...) */
787 MPLIST_DO (p2, MPLIST_NEXT (p2))
791 p3 = MPLIST_PLIST (p2); /* P3 ::= (TAG3 t:MDB) */
792 p3 = MPLIST_NEXT (p3);
793 mdb = MPLIST_VAL (p3);
794 if (mdb->loader == load_database)
795 free_db_info (mdb->extra_info);
801 M17N_OBJECT_UNREF (mdatabase__list);
805 mdatabase__update (void)
807 MPlist *plist, *p0, *p1, *p2, *p3;
808 char path[PATH_MAX + 1];
809 MDatabaseInfo *dir_info;
813 /* Update elements of mdatabase__dir_list. */
814 MPLIST_DO (plist, mdatabase__dir_list)
816 dir_info = MPLIST_VAL (plist);
817 if (dir_info->filename)
819 enum MDatabaseStatus status;
821 if (stat (dir_info->filename, &statbuf) == 0
822 && (statbuf.st_mode & S_IFDIR))
823 status = ((dir_info->time >= statbuf.st_mtime)
824 ? MDB_STATUS_EXPLICIT : MDB_STATUS_AUTO);
826 status = MDB_STATUS_DISABLED;
828 if (dir_info->status != status)
830 dir_info->status = status;
833 else if (dir_info->status == MDB_STATUS_AUTO)
841 /* At first, mark all databases defined automatically from mdb.dir
842 file(s) as "disabled". */
843 MPLIST_DO (plist, mdatabase__list)
845 p0 = MPLIST_PLIST (plist);
846 /* P0 ::= (TAG0 (TAG1 (TAG2 (TAG3 MDB) ...) ...) ...) */
847 MPLIST_DO (p0, MPLIST_NEXT (p0))
849 p1 = MPLIST_PLIST (p0);
850 MPLIST_DO (p1, MPLIST_NEXT (p1))
852 p2 = MPLIST_PLIST (p1);
853 MPLIST_DO (p2, MPLIST_NEXT (p2))
856 MDatabaseInfo *db_info;
858 p3 = MPLIST_PLIST (p2);
859 p3 = MPLIST_NEXT (p3);
860 mdb = MPLIST_VAL (p3);
861 db_info = mdb->extra_info;
862 if (db_info->status == MDB_STATUS_AUTO)
863 db_info->status = MDB_STATUS_DISABLED;
870 MPLIST_DO (p0, mdatabase__dir_list)
871 mplist_push (plist, MPLIST_KEY (p0), MPLIST_VAL (p0));
873 while (! MPLIST_TAIL_P (plist))
875 MDatabaseInfo *dir_info = mplist_pop (plist);
880 if (dir_info->status == MDB_STATUS_DISABLED)
882 if (! GEN_PATH (path, dir_info->filename, dir_info->len,
883 MDB_DIR, MDB_DIR_LEN))
885 if (stat (path, &statbuf) < 0)
887 dir_info->time = statbuf.st_mtime;
888 if (! (fp = fopen (path, "r")))
890 pl = mplist__from_file (fp, NULL);
900 int with_wildcard = 0;
902 if (! MPLIST_PLIST_P (p))
904 for (i = 0, p1 = MPLIST_PLIST (p); i < 4 && MPLIST_SYMBOL_P (p1);
905 i++, p1 = MPLIST_NEXT (p1))
906 with_wildcard |= ((tags[i] = MPLIST_SYMBOL (p1)) == Masterisk);
908 || tags[0] == Masterisk
909 || ! MPLIST_MTEXT_P (p1))
913 mt = MPLIST_MTEXT (p1);
914 if (mt->format >= MTEXT_FORMAT_UTF_16LE)
915 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
916 nbytes = mtext_nbytes (mt);
917 if (nbytes > PATH_MAX)
919 memcpy (path, MTEXT_DATA (mt), nbytes);
926 if (tags[0] == Mchar_table || tags[0] == Mcharset)
928 if (path[0] == PATH_SEPARATOR)
930 if (glob (path, GLOB_NOSORT, NULL, &globbuf))
932 register_databases_in_files (tags, &globbuf, 0);
936 MPLIST_DO (dlist, mdatabase__dir_list)
938 MDatabaseInfo *d_info = MPLIST_VAL (dlist);
940 if (d_info->status == MDB_STATUS_DISABLED)
942 if (! GEN_PATH (path, d_info->filename, d_info->len,
943 MTEXT_DATA (mt), nbytes))
945 if (glob (path, GLOB_NOSORT, NULL, &globbuf))
947 register_databases_in_files (tags, &globbuf, d_info->len);
953 register_database (tags, load_database, path, MDB_STATUS_AUTO);
956 M17N_OBJECT_UNREF (pl);
961 mdatabase__load_for_keys (MDatabase *mdb, MPlist *keys)
963 int mdebug_mask = MDEBUG_DATABASE;
964 MDatabaseInfo *db_info;
970 if (mdb->loader != load_database
971 || mdb->tag[0] == Mchar_table
972 || mdb->tag[0] == Mcharset)
973 MERROR (MERROR_DB, NULL);
974 MDEBUG_PRINT1 (" [DB] <%s>.\n",
975 gen_database_name (name, mdb->tag));
976 db_info = mdb->extra_info;
977 filename = get_database_file (db_info, NULL);
978 if (! filename || ! (fp = fopen (filename, "r")))
979 MERROR (MERROR_DB, NULL);
980 plist = mplist__from_file (fp, keys);
986 /* Check if the database MDB should be reloaded or not. It returns:
988 1: The database has not been updated since it was loaded last
991 0: The database has never been loaded or has been updated
992 since it was loaded last time.
994 -1: The database is not loadable at the moment. */
997 mdatabase__check (MDatabase *mdb)
999 MDatabaseInfo *db_info = (MDatabaseInfo *) mdb->extra_info;
1002 if (! get_database_file (db_info, &buf))
1004 if (db_info->time < buf.st_mtime)
1009 /* Search directories in mdatabase__dir_list for file FILENAME. If
1010 the file exist, return the absolute pathname. If FILENAME is
1011 already absolute, return a copy of it. */
1014 mdatabase__find_file (char *filename)
1017 MDatabaseInfo db_info;
1019 if (filename[0] == PATH_SEPARATOR)
1020 return (stat (filename, &buf) == 0 ? filename : NULL);
1021 db_info.filename = filename;
1022 db_info.len = strlen (filename);
1024 db_info.absolute_filename = NULL;
1025 if (! get_database_file (&db_info, &buf)
1026 || stat (db_info.absolute_filename, &buf) < 0)
1028 return db_info.absolute_filename;
1032 mdatabase__file (MDatabase *mdb)
1034 MDatabaseInfo *db_info;
1036 if (mdb->loader != load_database)
1038 db_info = mdb->extra_info;
1039 return get_database_file (db_info, NULL);
1043 mdatabase__lock (MDatabase *mdb)
1045 MDatabaseInfo *db_info;
1051 if (mdb->loader != load_database)
1053 db_info = mdb->extra_info;
1054 if (db_info->lock_file)
1056 file = get_database_file (db_info, NULL);
1059 len = strlen (file);
1060 db_info->uniq_file = malloc (len + 35);
1061 if (! db_info->uniq_file)
1063 db_info->lock_file = malloc (len + 5);
1064 if (! db_info->lock_file)
1066 free (db_info->uniq_file);
1069 sprintf (db_info->uniq_file, "%s.%X.%X", db_info->absolute_filename,
1070 (unsigned) time (NULL), (unsigned) getpid ());
1071 sprintf (db_info->lock_file, "%s.LCK", db_info->absolute_filename);
1073 fp = fopen (db_info->uniq_file, "w");
1076 char *str = strdup (db_info->uniq_file);
1077 char *dir = dirname (str);
1079 if (stat (dir, &buf) == 0
1080 || mkdir (dir, 0777) < 0
1081 || ! (fp = fopen (db_info->uniq_file, "w")))
1083 free (db_info->uniq_file);
1084 free (db_info->lock_file);
1085 db_info->lock_file = NULL;
1092 if (link (db_info->uniq_file, db_info->lock_file) < 0
1093 && (stat (db_info->uniq_file, &buf) < 0
1094 || buf.st_nlink != 2))
1096 unlink (db_info->uniq_file);
1097 unlink (db_info->lock_file);
1098 free (db_info->uniq_file);
1099 free (db_info->lock_file);
1100 db_info->lock_file = NULL;
1107 mdatabase__save (MDatabase *mdb, MPlist *data)
1109 MDatabaseInfo *db_info;
1115 if (mdb->loader != load_database)
1117 db_info = mdb->extra_info;
1118 if (! db_info->lock_file)
1120 file = get_database_file (db_info, NULL);
1124 if (mplist__serialize (mt, data, 1) < 0)
1126 M17N_OBJECT_UNREF (mt);
1129 fp = fopen (db_info->uniq_file, "w");
1132 M17N_OBJECT_UNREF (mt);
1135 mconv_encode_stream (msymbol ("utf-8"), mt, fp);
1136 M17N_OBJECT_UNREF (mt);
1138 if ((ret = rename (db_info->uniq_file, file)) < 0)
1139 unlink (db_info->uniq_file);
1140 free (db_info->uniq_file);
1141 db_info->uniq_file = NULL;
1146 mdatabase__unlock (MDatabase *mdb)
1148 MDatabaseInfo *db_info;
1150 if (mdb->loader != load_database)
1152 db_info = mdb->extra_info;
1153 if (! db_info->lock_file)
1155 unlink (db_info->lock_file);
1156 free (db_info->lock_file);
1157 db_info->lock_file = NULL;
1158 if (db_info->uniq_file)
1160 unlink (db_info->uniq_file);
1161 free (db_info->uniq_file);
1167 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1172 /*** @addtogroup m17nDatabase */
1177 @brief Directory for application specific data.
1179 If an application program wants to provide a data specific to the
1180 program or a data overriding what supplied by the m17n database,
1181 it must set this variable to a name of directory that contains the
1182 data files before it calls the macro M17N_INIT (). The directory
1183 may contain a file "mdb.dir" which contains a list of data
1184 definitions in the format described in @ref mdbDir "mdbDir(5)".
1186 The default value is NULL. */
1188 @brief ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¸ÇͤΥǡ¼¥¿Íѥǥ£¥ì¥¯¥È¥ê.
1190 ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤¬¡¢¤½¤Î¥×¥í¥°¥é¥à¸ÇͤΥǡ¼¥¿¤ä m17n
1191 ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¾å½ñ¤¤¹¤ë¥Ç¡¼¥¿¤òÄ󶡤¹¤ë¾ì¹ç¤Ë¤Ï¡¢¥Þ¥¯¥í M17N_INIT ()
1192 ¤ò¸Æ¤ÖÁ°¤Ë¤³¤ÎÊÑ¿ô¤ò¥Ç¡¼¥¿¥Õ¥¡¥¤¥ë¤ò´Þ¤à¥Ç¥£¥ì¥¯¥È¥ê̾¤Ë¥»¥Ã¥È¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¥Ç¥£¥ì¥¯¥È¥ê¤Ë¤Ï
1193 "mdb.dir" ¥Õ¥¡¥¤¥ë¤ò¤ª¤¯¤³¤È¤¬¤Ç¤¤ë¡£¤½¤Î"mdb.dir"¥Õ¥¡¥¤¥ë¤Ë¤Ï¡¢
1194 @ref mdbDir "mdbDir(5)" ¤ÇÀâÌÀ¤µ¤ì¤Æ¤¤¤ë¥Õ¥©¡¼¥Þ¥Ã¥È¤Ç¥Ç¡¼¥¿ÄêµÁ¤Î¥ê¥¹¥È¤òµ½Ò¤¹¤ë¡£
1196 ¥Ç¥Õ¥©¥ë¥È¤ÎÃÍ¤Ï NULL ¤Ç¤¢¤ë¡£ */
1198 char *mdatabase_dir;
1202 @brief Look for a data in the database.
1204 The mdatabase_find () function searches the m17n database for a
1205 data who has tags $TAG0 through $TAG3, and returns a pointer to
1206 the data. If such a data is not found, it returns @c NULL. */
1209 @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Î¥Ç¡¼¥¿¤òõ¤¹.
1211 ´Ø¿ô mdatabase_find () ¤Ï¡¢ m17n ¸À¸ì¾ðÊó¥Ù¡¼¥¹Ãæ¤Ç $TAG0 ¤«¤é
1212 $TAG3 ¤Þ¤Ç¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¤òõ¤·¡¢¤½¤ì¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤Î¤è¤¦¤Ê¥Ç¡¼¥¿¤¬¤Ê¤±¤ì¤Ð
1215 @latexonly \IPAlabel{mdatabase_find} @endlatexonly */
1218 mdatabase_find (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
1222 mdatabase__update ();
1223 tags[0] = tag0, tags[1] = tag1, tags[2] = tag2, tags[3] = tag3;
1224 return find_database (tags);
1229 @brief Return a data list of the m17n database.
1231 The mdatabase_list () function searches the m17n database for data
1232 who have tags $TAG0 through $TAG3, and returns their list by a
1233 plist. The value #Mnil in $TAGn means a wild card that matches
1234 any tag. Each element of the plist has key #Mt and value a
1235 pointer to type #MDatabase. */
1237 @brief m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥Ç¡¼¥¿¥ê¥¹¥È¤òÊÖ¤¹.
1239 ´Ø¿ô mdatabase_list () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é $TAG0 ¤«¤é$TAG3
1240 ¤Þ¤Ç¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¤òõ¤·¡¢¤½¤Î¥ê¥¹¥È¤òplist ¤È¤·¤ÆÊÖ¤¹¡£ $TAGn ¤¬ #Mnil
1241 ¤Ç¤¢¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢Ç¤°Õ¤Î¥¿¥°¤Ë¥Þ¥Ã¥Á¤¹¤ë¥ï¥¤¥ë¥É¥«¡¼¥É¤È¤·¤Æ¼è¤ê°·¤ï¤ì¤ë¡£ÊÖ¤µ¤ì¤ë
1242 plist ¤Î³ÆÍ×ÁǤϥ¡¼ ¤È¤·¤Æ #Mt ¤ò¡¢ÃͤȤ·¤Æ #MDatabase ·¿¤Ø¤Î¥Ý¥¤¥ó¥¿¤ò»ý¤Ä¡£ */
1245 mdatabase_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
1247 MPlist *plist = mplist (), *pl = plist;
1248 MPlist *p, *p0, *p1, *p2, *p3;
1250 mdatabase__update ();
1252 MPLIST_DO (p, mdatabase__list)
1254 p0 = MPLIST_PLIST (p);
1255 /* P0 ::= (TAG0 (TAG1 (TAG2 (TAG3 MDB) ...) ...) ...) */
1256 if (tag0 != Mnil && MPLIST_SYMBOL (p0) != tag0)
1258 MPLIST_DO (p0, MPLIST_NEXT (p0))
1260 p1 = MPLIST_PLIST (p0);
1261 if (tag1 != Mnil && MPLIST_SYMBOL (p1) != tag1)
1263 MPLIST_DO (p1, MPLIST_NEXT (p1))
1265 p2 = MPLIST_PLIST (p1);
1266 if (tag2 != Mnil && MPLIST_SYMBOL (p2) != tag2)
1268 MPLIST_DO (p2, MPLIST_NEXT (p2))
1270 p3 = MPLIST_PLIST (p2);
1271 if (tag3 != Mnil && MPLIST_SYMBOL (p3) != tag3)
1273 p3 = MPLIST_NEXT (p3);
1274 pl = mplist_add (pl, Mt, MPLIST_VAL (p3));
1279 if (MPLIST_TAIL_P (plist))
1281 M17N_OBJECT_UNREF (plist);
1289 @brief Define a data of the m17n database.
1291 The mdatabase_define () function defines a data that has tags
1292 $TAG0 through $TAG3 and additional information $EXTRA_INFO.
1294 $LOADER is a pointer to a function that loads the data from the
1295 database. This function is called from the mdatabase_load ()
1296 function with the two arguments $TAGS and $EXTRA_INFO. Here,
1297 $TAGS is the array of $TAG0 through $TAG3.
1299 If $LOADER is @c NULL, the default loader of the m17n library is
1300 used. In this case, $EXTRA_INFO must be a string specifying a
1301 filename that contains the data.
1304 If the operation was successful, mdatabase_define () returns a
1305 pointer to the defined data, which can be used as an argument to
1306 mdatabase_load (). Otherwise, it returns @c NULL. */
1309 @brief m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥Ç¡¼¥¿¤òÄêµÁ¤¹¤ë.
1311 ´Ø¿ô mdatabase_define () ¤Ï $TAG0 ¤«¤é $TAG3 ¤Þ¤Ç¤Î¥¿¥°¤ª¤è¤ÓÉղþðÊó
1312 $EXTRA_INFO ¤ò»ý¤Ä¥Ç¡¼¥¿¤òÄêµÁ¤¹¤ë¡£
1314 $LOADER ¤Ï¤½¤Î¥Ç¡¼¥¿¤Î¥í¡¼¥É¤ËÍѤ¤¤é¤ì¤ë´Ø¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¤³¤Î´Ø¿ô¤Ï
1315 mdatabase_load () ¤«¤é $TAGS ¤È $EXTRA_INFO ¤È¤¤¤¦Æó¤Ä¤Î°ú¿ôÉÕ¤¤Ç¸Æ¤Ó½Ð¤µ¤ì¤ë¡£¤³¤³¤Ç
1316 $TAGS ¤Ï $TAG0 ¤«¤é $TAG3 ¤Þ¤Ç¤ÎÇÛÎó¤Ç¤¢¤ë¡£
1318 ¤â¤· $LOADER ¤¬ @c NULL ¤Ê¤é¡¢m17n ¥é¥¤¥Ö¥é¥êɸ½à¤Î¥í¡¼¥À¤¬»È¤ï¤ì¤ë¡£¤³¤Î¾ì¹ç¤Ë¤Ï
1319 $EXTRA_INFO ¤Ï¥Ç¡¼¥¿¤ò´Þ¤à¥Õ¥¡¥¤¥ë̾¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
1322 ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mdatabase_define ()
1323 ¤ÏÄêµÁ¤µ¤ì¤¿¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤³¤Î¥Ý¥¤¥ó¥¿¤Ï´Ø¿ô mdatabase_load ()
1324 ¤Î°ú¿ô¤È¤·¤ÆÍѤ¤¤ë¤³¤È¤¬¤Ç¤¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£
1326 @latexonly \IPAlabel{mdatabase_define} @endlatexonly */
1330 mdatabase_load (), mdatabase_define () */
1333 mdatabase_define (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3,
1334 void *(*loader) (MSymbol *, void *),
1340 tags[0] = tag0, tags[1] = tag1, tags[2] = tag2, tags[3] = tag3;
1342 loader = load_database;
1343 mdb = register_database (tags, loader, extra_info, MDB_STATUS_EXPLICIT);
1349 @brief Load a data from the database.
1351 The mdatabase_load () function loads a data specified in $MDB and
1352 returns the contents. The type of contents depends on the type of
1355 If the data is of the @e plist @e type, this function returns a
1356 pointer to @e plist.
1358 If the database is of the @e chartable @e type, it returns a
1359 chartable. The default value of the chartable is set according to
1360 the second tag of the data as below:
1362 @li If the tag is #Msymbol, the default value is #Mnil.
1363 @li If the tag is #Minteger, the default value is -1.
1364 @li Otherwise, the default value is @c NULL.
1366 If the data is of the @e charset @e type, it returns a plist of length 2
1367 (keys are both #Mt). The value of the first element is an array
1368 of integers that maps code points to the corresponding character
1369 codes. The value of the second element is a chartable of integers
1370 that does the reverse mapping. The charset must be defined in
1375 @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹¤«¤é¥Ç¡¼¥¿¤ò¥í¡¼¥É¤¹¤ë.
1377 ´Ø¿ô mdatabase_load () ¤Ï $MDB
1378 ¤¬»Ø¤¹¥Ç¡¼¥¿¤ò¥í¡¼¥É¤·¡¢¤½¤ÎÃæ¿È¤òÊÖ¤¹¡£ÊÖ¤µ¤ì¤ë¤â¤Î¤Ï¥Ç¡¼¥¿¤Î¥¿¥¤¥×¤Ë¤è¤Ã¤Æ°Û¤Ê¤ë¡£
1380 ¥Ç¡¼¥¿¤¬ @e plist¥¿¥¤¥× ¤Ê¤é¤Ð¡¢ @e plist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
1382 ¥Ç¡¼¥¿¤¬ @e chartable¥¿¥¤¥× ¤Ê¤é¤Ðʸ»ú¥Æ¡¼¥Ö¥ë¤òÊÖ¤¹¡£
1383 ʸ»ú¥Æ¡¼¥Ö¥ë¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤϡ¢¥Ç¡¼¥¿¤ÎÂè2¥¿¥°¤Ë¤è¤Ã¤Æ°Ê²¼¤Î¤è¤¦¤Ë·è¤Þ¤ë¡£
1385 @li ¥¿¥°¤¬ #Msymbol ¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï #Mnil
1386 @li ¥¿¥°¤¬ #Minteger ¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï -1
1387 @li ¤½¤ì°Ê³°¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï @c NULL
1389 ¥Ç¡¼¥¿¤¬ @e charset¥¿¥¤¥× ¤Ê¤é¤ÐŤµ 2 ¤Î plist ¤òÊÖ¤¹¡Ê¥¡¼¤Ï¶¦¤Ë#Mt ¡Ë¡£
1390 ºÇ½é¤ÎÍ×ÁǤÎÃͤϥ³¡¼¥É¥Ý¥¤¥ó¥È¤òÂбþ¤¹¤ëʸ»ú¥³¡¼¥É¤Ë¥Þ¥Ã¥×¤¹¤ëÀ°¿ô¤ÎÇÛÎó¤Ç¤¢¤ë¡£
1391 £²ÈÖÌܤÎÍ×ÁǤÎÃͤϵդΥޥåפò¤¹¤ëʸ»ú¥Æ¡¼¥Ö¥ë¤Ç¤¢¤ë¡£
1392 ¤³¤Îʸ»ú¥»¥Ã¥È¤Ïͽ¤áÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
1394 @latexonly \IPAlabel{mdatabase_load} @endlatexonly
1399 mdatabase_load (), mdatabase_define () */
1402 mdatabase_load (MDatabase *mdb)
1404 return (*mdb->loader) (mdb->tag, mdb->extra_info);
1409 @brief Get tags of a data.
1411 The mdatabase_tag () function returns an array of tags (symbols)
1412 that identify the data in $MDB. The length of the array is
1416 @brief ¥Ç¡¼¥¿¤Î¥¿¥°¤òÆÀ¤ë.
1418 ´Ø¿ô mdatabase_tag () ¤Ï¡¢¥Ç¡¼¥¿ $MDB ¤Î¥¿¥°¡Ê¥·¥ó¥Ü¥ë¡Ë¤ÎÇÛÎó¤òÊÖ¤¹¡£ÇÛÎó¤ÎŤµ¤Ï
1421 @latexonly \IPAlabel{mdatabase_tag} @endlatexonly */
1424 mdatabase_tag (MDatabase *mdb)