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]));
444 /* Return the absolute file name for DB_INFO->filename or NULL if no
445 absolute file name was found. If BUF is non-NULL, store the result
446 of `stat' call in it. In that case, set *RESULT to the return
450 get_database_file (MDatabaseInfo *db_info, struct stat *buf, int *result)
452 if (db_info->absolute_filename)
455 *result = stat (db_info->absolute_filename, buf);
459 struct stat stat_buf;
460 struct stat *statbuf = buf ? buf : &stat_buf;
463 char path[PATH_MAX + 1];
465 MPLIST_DO (plist, mdatabase__dir_list)
467 MDatabaseInfo *dir_info = MPLIST_VAL (plist);
469 if (dir_info->status != MDB_STATUS_DISABLED
470 && GEN_PATH (path, dir_info->filename, dir_info->len,
471 db_info->filename, db_info->len)
472 && (res = stat (path, statbuf)) == 0)
474 db_info->absolute_filename = strdup (path);
482 return db_info->absolute_filename;
486 load_database (MSymbol *tags, void *extra_info)
488 MDatabaseInfo *db_info = extra_info;
490 char *filename = get_database_file (db_info, NULL, NULL);
492 int mdebug_mask = MDEBUG_DATABASE;
495 MDEBUG_PRINT1 (" [DB] <%s>", gen_database_name (buf, tags));
496 if (! filename || ! (fp = fopen (filename, "r")))
499 MDEBUG_PRINT1 (" open fail: %s\n", filename);
501 MDEBUG_PRINT1 (" not found: %s\n", db_info->filename);
502 MERROR (MERROR_DB, NULL);
505 MDEBUG_PRINT1 (" from %s\n", filename);
507 if (tags[0] == Mchar_table)
508 value = load_chartable (fp, tags[1]);
509 else if (tags[0] == Mcharset)
510 value = load_charset (fp, tags[1]);
512 value = mplist__from_file (fp, NULL);
516 MERROR (MERROR_DB, NULL);
517 db_info->time = time (NULL);
522 /** Return a newly allocated MDatabaseInfo for DIRNAME. */
524 static MDatabaseInfo *
525 get_dir_info (char *dirname)
527 MDatabaseInfo *dir_info;
529 MSTRUCT_CALLOC (dir_info, MERROR_DB);
532 int len = strlen (dirname);
534 if (len + MDB_DIR_LEN < PATH_MAX)
536 MTABLE_MALLOC (dir_info->filename, len + 2, MERROR_DB);
537 memcpy (dir_info->filename, dirname, len + 1);
538 /* Append PATH_SEPARATOR if DIRNAME doesn't end with it. */
539 if (dir_info->filename[len - 1] != PATH_SEPARATOR)
541 dir_info->filename[len] = PATH_SEPARATOR;
542 dir_info->filename[++len] = '\0';
545 dir_info->status = MDB_STATUS_OUTDATED;
548 dir_info->status = MDB_STATUS_DISABLED;
551 dir_info->status = MDB_STATUS_DISABLED;
555 static void register_databases_in_files (MSymbol tags[4],
556 char *filename, int len);
559 find_database (MSymbol tags[4])
565 if (! mdatabase__list)
567 for (i = 0, plist = mdatabase__list; i < 4; i++)
569 MPlist *pl = mplist__assq (plist, tags[i]);
572 if ((p = mplist__assq (plist, Masterisk)))
574 MDatabaseInfo *db_info;
577 p = MPLIST_PLIST (p);
578 for (j = i + 1; j < 4; j++)
579 p = MPLIST_PLIST (MPLIST_NEXT (p));
580 mdb = MPLIST_VAL (MPLIST_NEXT (p));
581 db_info = mdb->extra_info;
582 if (db_info->status != MDB_STATUS_DISABLED)
584 register_databases_in_files (mdb->tag,
585 db_info->filename, db_info->len);
586 db_info->status = MDB_STATUS_DISABLED;
587 return find_database (tags);
592 plist = MPLIST_PLIST (pl);
593 plist = MPLIST_NEXT (plist);
595 mdb = MPLIST_VAL (plist);
600 free_db_info (MDatabaseInfo *db_info)
602 free (db_info->filename);
603 if (db_info->absolute_filename
604 && db_info->filename != db_info->absolute_filename)
605 free (db_info->absolute_filename);
606 M17N_OBJECT_UNREF (db_info->properties);
611 check_version (MText *version)
613 char *verstr = (char *) MTEXT_DATA (version);
614 char *endp = verstr + mtext_nbytes (version);
618 ver[0] = ver[1] = ver[2] = 0;
619 for (i = 0; verstr < endp; verstr++)
628 if (! isdigit (*verstr))
630 ver[i] = ver[i] * 10 + (*verstr - '0');
632 return (ver[0] < M17NLIB_MAJOR_VERSION
633 || (ver[0] == M17NLIB_MAJOR_VERSION
634 && (ver[1] < M17NLIB_MINOR_VERSION
635 || (ver[1] == M17NLIB_MINOR_VERSION
636 && ver[2] <= M17NLIB_PATCH_LEVEL))));
640 register_database (MSymbol tags[4],
641 void *(*loader) (MSymbol *, void *),
642 void *extra_info, enum MDatabaseStatus status,
646 MDatabaseInfo *db_info;
652 MPLIST_DO (plist, properties)
653 if (MPLIST_PLIST_P (plist))
655 MPlist *p = MPLIST_PLIST (plist);
657 if (MPLIST_SYMBOL_P (p)
658 && MPLIST_SYMBOL (p) == Mversion
659 && MPLIST_MTEXT_P (MPLIST_NEXT (p)))
661 if (check_version (MPLIST_MTEXT (MPLIST_NEXT (p))))
668 for (i = 0, plist = mdatabase__list; i < 4; i++)
670 MPlist *pl = mplist__assq (plist, tags[i]);
673 pl = MPLIST_PLIST (pl);
677 mplist_add (pl, Msymbol, tags[i]);
678 mplist_push (plist, Mplist, pl);
679 M17N_OBJECT_UNREF (pl);
681 plist = MPLIST_NEXT (pl);
684 if (MPLIST_TAIL_P (plist))
686 MSTRUCT_MALLOC (mdb, MERROR_DB);
687 for (i = 0; i < 4; i++)
688 mdb->tag[i] = tags[i];
689 mdb->loader = loader;
690 if (loader == load_database)
692 MSTRUCT_CALLOC (db_info, MERROR_DB);
693 mdb->extra_info = db_info;
698 mdb->extra_info = extra_info;
700 mplist_push (plist, Mt, mdb);
704 mdb = MPLIST_VAL (plist);
705 if (loader == load_database)
706 db_info = mdb->extra_info;
713 db_info->status = status;
714 if (! db_info->filename
715 || strcmp (db_info->filename, (char *) extra_info) != 0)
717 if (db_info->filename)
718 free (db_info->filename);
719 if (db_info->absolute_filename
720 && db_info->filename != db_info->absolute_filename)
721 free (db_info->absolute_filename);
722 db_info->filename = strdup ((char *) extra_info);
723 db_info->len = strlen ((char *) extra_info);
726 if (db_info->filename[0] == PATH_SEPARATOR)
727 db_info->absolute_filename = db_info->filename;
729 db_info->absolute_filename = NULL;
730 M17N_OBJECT_UNREF (db_info->properties);
733 db_info->properties = properties;
734 M17N_OBJECT_REF (properties);
738 if (mdb->tag[0] == Mchar_table
739 && mdb->tag[2] != Mnil
740 && (mdb->tag[1] == Mstring || mdb->tag[1] == Mtext
741 || mdb->tag[1] == Msymbol || mdb->tag[1] == Minteger
742 || mdb->tag[1] == Mplist))
743 mchar__define_prop (mdb->tag[2], mdb->tag[1], mdb);
748 register_databases_in_files (MSymbol tags[4], char *filename, int len)
751 MPlist *load_key = mplist ();
755 MPLIST_DO (plist, mdatabase__dir_list)
760 if (filename[0] == PATH_SEPARATOR)
762 if (glob (filename, GLOB_NOSORT, NULL, &globbuf))
768 MDatabaseInfo *d_info = MPLIST_VAL (plist);
769 char path[PATH_MAX + 1];
771 if (d_info->status == MDB_STATUS_DISABLED)
773 if (! GEN_PATH (path, d_info->filename, d_info->len, filename, len))
775 if (glob (path, GLOB_NOSORT, NULL, &globbuf))
777 headlen = d_info->len;
780 for (i = 0; i < globbuf.gl_pathc; i++)
782 if (! (fp = fopen (globbuf.gl_pathv[i], "r")))
784 pl = mplist__from_file (fp, load_key);
788 if (MPLIST_PLIST_P (pl))
793 for (j = 0, p = MPLIST_PLIST (pl); j < 4 && MPLIST_SYMBOL_P (p);
794 j++, p = MPLIST_NEXT (p))
795 tags2[j] = MPLIST_SYMBOL (p);
798 for (j = 0; j < 4; j++)
799 if (tags[j] != Masterisk && tags[j] != tags2[j])
802 register_database (tags2, load_database,
803 globbuf.gl_pathv[i] + headlen,
806 M17N_OBJECT_UNREF (pl);
809 if (filename[0] == PATH_SEPARATOR)
812 M17N_OBJECT_UNREF (load_key);
816 expand_wildcard_database (MPlist *plist)
819 MDatabaseInfo *db_info;
821 plist = MPLIST_NEXT (plist);
822 while (MPLIST_PLIST_P (plist))
824 plist = MPLIST_PLIST (plist);
825 plist = MPLIST_NEXT (plist);
827 mdb = MPLIST_VAL (plist);
828 if (mdb->loader == load_database
829 && (db_info = mdb->extra_info)
830 && db_info->status != MDB_STATUS_DISABLED)
832 register_databases_in_files (mdb->tag, db_info->filename, db_info->len);
833 db_info->status = MDB_STATUS_DISABLED;
842 /** List of database directories. */
843 MPlist *mdatabase__dir_list;
848 MDatabaseInfo *dir_info;
851 Mchar_table = msymbol ("char-table");
852 Masterisk = msymbol ("*");
853 Mversion = msymbol ("version");
855 mdatabase__dir_list = mplist ();
856 /** The macro M17NDIR specifies a directory where the system-wide
857 MDB_DIR file exists. */
858 mplist_set (mdatabase__dir_list, Mt, get_dir_info (M17NDIR));
860 /* The variable mdatabase_dir specifies a directory where an
861 application program specific MDB_DIR file exists. */
862 if (mdatabase_dir && strlen (mdatabase_dir) > 0)
863 mplist_push (mdatabase__dir_list, Mt, get_dir_info (mdatabase_dir));
865 /* The environment variable M17NDIR specifies a directory where a
866 user specific MDB_DIR file exists. */
867 path = getenv ("M17NDIR");
868 if (path && strlen (path) > 0)
869 mplist_push (mdatabase__dir_list, Mt, get_dir_info (path));
872 /* If the env var M17NDIR is not set, check "~/.m17n.d". */
873 char *home = getenv ("HOME");
877 && (len = strlen (home))
878 && (path = alloca (len + 9)))
881 if (path[len - 1] != PATH_SEPARATOR)
882 path[len++] = PATH_SEPARATOR;
883 strcpy (path + len, ".m17n.d");
884 dir_info = get_dir_info (path);
885 mplist_push (mdatabase__dir_list, Mt, dir_info);
888 mplist_push (mdatabase__dir_list, Mt, get_dir_info (NULL));
891 mdatabase__finder = ((void *(*) (MSymbol, MSymbol, MSymbol, MSymbol))
893 mdatabase__loader = (void *(*) (void *)) mdatabase_load;
895 mdatabase__list = mplist ();
896 mdatabase__update ();
901 mdatabase__fini (void)
903 MPlist *plist, *p0, *p1, *p2, *p3;
905 MPLIST_DO (plist, mdatabase__dir_list)
906 free_db_info (MPLIST_VAL (plist));
907 M17N_OBJECT_UNREF (mdatabase__dir_list);
909 /* MDATABASE_LIST ::= ((TAG0 (TAG1 (TAG2 (TAG3 t:MDB) ...) ...) ...) ...) */
910 MPLIST_DO (plist, mdatabase__list)
912 p0 = MPLIST_PLIST (plist);
913 /* P0 ::= (TAG0 (TAG1 (TAG2 (TAG3 t:MDB) ...) ...) ...) */
914 MPLIST_DO (p0, MPLIST_NEXT (p0))
916 p1 = MPLIST_PLIST (p0);
917 /* P1 ::= (TAG1 (TAG2 (TAG3 t:MDB) ...) ...) */
918 MPLIST_DO (p1, MPLIST_NEXT (p1))
920 p2 = MPLIST_PLIST (p1);
921 /* P2 ::= (TAG2 (TAG3 t:MDB) ...) */
922 MPLIST_DO (p2, MPLIST_NEXT (p2))
926 p3 = MPLIST_PLIST (p2); /* P3 ::= (TAG3 t:MDB) */
927 p3 = MPLIST_NEXT (p3);
928 mdb = MPLIST_VAL (p3);
929 if (mdb->loader == load_database)
930 free_db_info (mdb->extra_info);
936 M17N_OBJECT_UNREF (mdatabase__list);
940 mdatabase__update (void)
942 MPlist *plist, *p0, *p1, *p2, *p3;
943 char path[PATH_MAX + 1];
944 MDatabaseInfo *dir_info;
948 /* Update elements of mdatabase__dir_list. */
949 MPLIST_DO (plist, mdatabase__dir_list)
951 dir_info = MPLIST_VAL (plist);
952 if (dir_info->filename)
954 if (stat (dir_info->filename, &statbuf) == 0
955 && (statbuf.st_mode & S_IFDIR))
957 if (dir_info->time < statbuf.st_mtime)
960 dir_info->time = statbuf.st_mtime;
962 if (GEN_PATH (path, dir_info->filename, dir_info->len,
963 MDB_DIR, MDB_DIR_LEN)
964 && stat (path, &statbuf) >= 0
965 && dir_info->time < statbuf.st_mtime)
968 dir_info->time = statbuf.st_mtime;
970 dir_info->status = MDB_STATUS_UPDATED;
974 if (dir_info->status != MDB_STATUS_DISABLED)
978 dir_info->status = MDB_STATUS_DISABLED;
987 /* At first, mark all databases defined automatically from mdb.dir
988 file(s) as "disabled". */
989 MPLIST_DO (plist, mdatabase__list)
991 p0 = MPLIST_PLIST (plist);
992 /* P0 ::= (TAG0 (TAG1 (TAG2 (TAG3 MDB) ...) ...) ...) */
993 MPLIST_DO (p0, MPLIST_NEXT (p0))
995 p1 = MPLIST_PLIST (p0);
996 MPLIST_DO (p1, MPLIST_NEXT (p1))
998 p2 = MPLIST_PLIST (p1);
999 MPLIST_DO (p2, MPLIST_NEXT (p2))
1002 MDatabaseInfo *db_info;
1004 p3 = MPLIST_PLIST (p2);
1005 p3 = MPLIST_NEXT (p3);
1006 mdb = MPLIST_VAL (p3);
1007 db_info = mdb->extra_info;
1008 if (db_info->status == MDB_STATUS_AUTO)
1009 db_info->status = MDB_STATUS_DISABLED;
1016 MPLIST_DO (p0, mdatabase__dir_list)
1017 mplist_push (plist, MPLIST_KEY (p0), MPLIST_VAL (p0));
1019 while (! MPLIST_TAIL_P (plist))
1021 MDatabaseInfo *dir_info = mplist_pop (plist);
1026 if (dir_info->status == MDB_STATUS_DISABLED)
1028 if (! GEN_PATH (path, dir_info->filename, dir_info->len,
1029 MDB_DIR, MDB_DIR_LEN))
1031 if (! (fp = fopen (path, "r")))
1033 pl = mplist__from_file (fp, NULL);
1043 int with_wildcard = 0;
1045 if (! MPLIST_PLIST_P (p))
1047 for (i = 0, p1 = MPLIST_PLIST (p); i < 4 && MPLIST_SYMBOL_P (p1);
1048 i++, p1 = MPLIST_NEXT (p1))
1049 with_wildcard |= ((tags[i] = MPLIST_SYMBOL (p1)) == Masterisk);
1051 || tags[0] == Masterisk
1052 || ! MPLIST_MTEXT_P (p1))
1055 tags[i] = with_wildcard ? Masterisk : Mnil;
1056 mt = MPLIST_MTEXT (p1);
1057 nbytes = mtext_nbytes (mt);
1058 if (nbytes > PATH_MAX)
1060 memcpy (path, MTEXT_DATA (mt), nbytes);
1061 path[nbytes] = '\0';
1063 register_database (tags, load_database, path,
1064 MDB_STATUS_AUTO_WILDCARD, NULL);
1066 register_database (tags, load_database, path,
1067 MDB_STATUS_AUTO, p1);
1069 M17N_OBJECT_UNREF (pl);
1071 M17N_OBJECT_UNREF (plist);
1075 mdatabase__load_for_keys (MDatabase *mdb, MPlist *keys)
1077 int mdebug_mask = MDEBUG_DATABASE;
1078 MDatabaseInfo *db_info;
1084 if (mdb->loader != load_database
1085 || mdb->tag[0] == Mchar_table
1086 || mdb->tag[0] == Mcharset)
1087 MERROR (MERROR_DB, NULL);
1088 MDEBUG_PRINT1 (" [DB] <%s>.\n",
1089 gen_database_name (name, mdb->tag));
1090 db_info = mdb->extra_info;
1091 filename = get_database_file (db_info, NULL, NULL);
1092 if (! filename || ! (fp = fopen (filename, "r")))
1093 MERROR (MERROR_DB, NULL);
1094 plist = mplist__from_file (fp, keys);
1100 /* Check if the database MDB should be reloaded or not. It returns:
1102 1: The database has not been updated since it was loaded last
1105 0: The database has never been loaded or has been updated
1106 since it was loaded last time.
1108 -1: The database is not loadable at the moment. */
1111 mdatabase__check (MDatabase *mdb)
1113 MDatabaseInfo *db_info = (MDatabaseInfo *) mdb->extra_info;
1117 if (db_info->absolute_filename != db_info->filename
1118 || db_info->status == MDB_STATUS_AUTO)
1119 mdatabase__update ();
1121 if (! get_database_file (db_info, &buf, &result)
1124 if (db_info->time < buf.st_mtime)
1129 /* Search directories in mdatabase__dir_list for file FILENAME. If
1130 the file exist, return the absolute pathname. If FILENAME is
1131 already absolute, return a copy of it. */
1134 mdatabase__find_file (char *filename)
1138 MDatabaseInfo db_info;
1140 if (filename[0] == PATH_SEPARATOR)
1141 return (stat (filename, &buf) == 0 ? filename : NULL);
1142 db_info.filename = filename;
1143 db_info.len = strlen (filename);
1145 db_info.absolute_filename = NULL;
1146 if (! get_database_file (&db_info, &buf, &result)
1149 return db_info.absolute_filename;
1153 mdatabase__file (MDatabase *mdb)
1155 MDatabaseInfo *db_info;
1157 if (mdb->loader != load_database)
1159 db_info = mdb->extra_info;
1160 return get_database_file (db_info, NULL, NULL);
1164 mdatabase__lock (MDatabase *mdb)
1166 MDatabaseInfo *db_info;
1172 if (mdb->loader != load_database)
1174 db_info = mdb->extra_info;
1175 if (db_info->lock_file)
1177 file = get_database_file (db_info, NULL, NULL);
1180 len = strlen (file);
1181 db_info->uniq_file = malloc (len + 35);
1182 if (! db_info->uniq_file)
1184 db_info->lock_file = malloc (len + 5);
1185 if (! db_info->lock_file)
1187 free (db_info->uniq_file);
1190 sprintf (db_info->uniq_file, "%s.%X.%X", db_info->absolute_filename,
1191 (unsigned) time (NULL), (unsigned) getpid ());
1192 sprintf (db_info->lock_file, "%s.LCK", db_info->absolute_filename);
1194 fp = fopen (db_info->uniq_file, "w");
1197 char *str = strdup (db_info->uniq_file);
1198 char *dir = dirname (str);
1200 if (stat (dir, &buf) == 0
1201 || mkdir (dir, 0777) < 0
1202 || ! (fp = fopen (db_info->uniq_file, "w")))
1204 free (db_info->uniq_file);
1205 free (db_info->lock_file);
1206 db_info->lock_file = NULL;
1213 if (link (db_info->uniq_file, db_info->lock_file) < 0
1214 && (stat (db_info->uniq_file, &buf) < 0
1215 || buf.st_nlink != 2))
1217 unlink (db_info->uniq_file);
1218 unlink (db_info->lock_file);
1219 free (db_info->uniq_file);
1220 free (db_info->lock_file);
1221 db_info->lock_file = NULL;
1228 mdatabase__save (MDatabase *mdb, MPlist *data)
1230 MDatabaseInfo *db_info;
1236 if (mdb->loader != load_database)
1238 db_info = mdb->extra_info;
1239 if (! db_info->lock_file)
1241 file = get_database_file (db_info, NULL, NULL);
1245 if (mplist__serialize (mt, data, 1) < 0)
1247 M17N_OBJECT_UNREF (mt);
1250 fp = fopen (db_info->uniq_file, "w");
1253 M17N_OBJECT_UNREF (mt);
1256 mconv_encode_stream (msymbol ("utf-8"), mt, fp);
1257 M17N_OBJECT_UNREF (mt);
1259 if ((ret = rename (db_info->uniq_file, file)) < 0)
1260 unlink (db_info->uniq_file);
1261 free (db_info->uniq_file);
1262 db_info->uniq_file = NULL;
1267 mdatabase__unlock (MDatabase *mdb)
1269 MDatabaseInfo *db_info;
1271 if (mdb->loader != load_database)
1273 db_info = mdb->extra_info;
1274 if (! db_info->lock_file)
1276 unlink (db_info->lock_file);
1277 free (db_info->lock_file);
1278 db_info->lock_file = NULL;
1279 if (db_info->uniq_file)
1281 unlink (db_info->uniq_file);
1282 free (db_info->uniq_file);
1288 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1293 /*** @addtogroup m17nDatabase */
1298 @brief Directory for application specific data.
1300 If an application program wants to provide a data specific to the
1301 program or a data overriding what supplied by the m17n database,
1302 it must set this variable to a name of directory that contains the
1303 data files before it calls the macro M17N_INIT (). The directory
1304 may contain a file "mdb.dir" which contains a list of data
1305 definitions in the format described in @ref mdbDir "mdbDir(5)".
1307 The default value is NULL. */
1309 @brief ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¸ÇͤΥǡ¼¥¿Íѥǥ£¥ì¥¯¥È¥ê.
1311 ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤¬¡¢¤½¤Î¥×¥í¥°¥é¥à¸ÇͤΥǡ¼¥¿¤ä m17n
1312 ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¾å½ñ¤¤¹¤ë¥Ç¡¼¥¿¤òÄ󶡤¹¤ë¾ì¹ç¤Ë¤Ï¡¢¥Þ¥¯¥í M17N_INIT ()
1313 ¤ò¸Æ¤ÖÁ°¤Ë¤³¤ÎÊÑ¿ô¤ò¥Ç¡¼¥¿¥Õ¥¡¥¤¥ë¤ò´Þ¤à¥Ç¥£¥ì¥¯¥È¥ê̾¤Ë¥»¥Ã¥È¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¥Ç¥£¥ì¥¯¥È¥ê¤Ë¤Ï
1314 "mdb.dir" ¥Õ¥¡¥¤¥ë¤ò¤ª¤¯¤³¤È¤¬¤Ç¤¤ë¡£¤½¤Î"mdb.dir"¥Õ¥¡¥¤¥ë¤Ë¤Ï¡¢
1315 @ref mdbDir "mdbDir(5)" ¤ÇÀâÌÀ¤µ¤ì¤Æ¤¤¤ë¥Õ¥©¡¼¥Þ¥Ã¥È¤Ç¥Ç¡¼¥¿ÄêµÁ¤Î¥ê¥¹¥È¤òµ½Ò¤¹¤ë¡£
1317 ¥Ç¥Õ¥©¥ë¥È¤ÎÃÍ¤Ï NULL ¤Ç¤¢¤ë¡£ */
1319 char *mdatabase_dir;
1323 @brief Look for a data in the database.
1325 The mdatabase_find () function searches the m17n database for a
1326 data who has tags $TAG0 through $TAG3, and returns a pointer to
1327 the data. If such a data is not found, it returns @c NULL. */
1330 @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Î¥Ç¡¼¥¿¤òõ¤¹.
1332 ´Ø¿ô mdatabase_find () ¤Ï¡¢ m17n ¸À¸ì¾ðÊó¥Ù¡¼¥¹Ãæ¤Ç $TAG0 ¤«¤é
1333 $TAG3 ¤Þ¤Ç¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¤òõ¤·¡¢¤½¤ì¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤Î¤è¤¦¤Ê¥Ç¡¼¥¿¤¬¤Ê¤±¤ì¤Ð
1336 @latexonly \IPAlabel{mdatabase_find} @endlatexonly */
1339 mdatabase_find (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
1343 mdatabase__update ();
1344 tags[0] = tag0, tags[1] = tag1, tags[2] = tag2, tags[3] = tag3;
1345 return find_database (tags);
1350 @brief Return a data list of the m17n database.
1352 The mdatabase_list () function searches the m17n database for data
1353 who have tags $TAG0 through $TAG3, and returns their list by a
1354 plist. The value #Mnil in $TAGn means a wild card that matches
1355 any tag. Each element of the plist has key #Mt and value a
1356 pointer to type #MDatabase. */
1358 @brief m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥Ç¡¼¥¿¥ê¥¹¥È¤òÊÖ¤¹.
1360 ´Ø¿ô mdatabase_list () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é $TAG0 ¤«¤é$TAG3
1361 ¤Þ¤Ç¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¤òõ¤·¡¢¤½¤Î¥ê¥¹¥È¤òplist ¤È¤·¤ÆÊÖ¤¹¡£ $TAGn ¤¬ #Mnil
1362 ¤Ç¤¢¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢Ç¤°Õ¤Î¥¿¥°¤Ë¥Þ¥Ã¥Á¤¹¤ë¥ï¥¤¥ë¥É¥«¡¼¥É¤È¤·¤Æ¼è¤ê°·¤ï¤ì¤ë¡£ÊÖ¤µ¤ì¤ë
1363 plist ¤Î³ÆÍ×ÁǤϥ¡¼ ¤È¤·¤Æ #Mt ¤ò¡¢ÃͤȤ·¤Æ #MDatabase ·¿¤Ø¤Î¥Ý¥¤¥ó¥¿¤ò»ý¤Ä¡£ */
1366 mdatabase_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
1368 MPlist *plist = mplist (), *pl = plist;
1369 MPlist *p, *p0, *p1, *p2, *p3;
1371 mdatabase__update ();
1373 MPLIST_DO (p, mdatabase__list)
1375 p0 = MPLIST_PLIST (p);
1376 /* P0 ::= (TAG0 (TAG1 (TAG2 (TAG3 MDB) ...) ...) ...) */
1377 if (MPLIST_SYMBOL (p0) == Masterisk
1378 || (tag0 != Mnil && MPLIST_SYMBOL (p0) != tag0))
1380 MPLIST_DO (p0, MPLIST_NEXT (p0))
1382 p1 = MPLIST_PLIST (p0);
1383 if (MPLIST_SYMBOL (p1) == Masterisk)
1385 if (expand_wildcard_database (p1))
1387 M17N_OBJECT_UNREF (plist);
1388 return mdatabase_list (tag0, tag1, tag2, tag3);
1392 if (tag1 != Mnil && MPLIST_SYMBOL (p1) != tag1)
1394 MPLIST_DO (p1, MPLIST_NEXT (p1))
1396 p2 = MPLIST_PLIST (p1);
1397 if (MPLIST_SYMBOL (p2) == Masterisk)
1399 if (expand_wildcard_database (p2))
1401 M17N_OBJECT_UNREF (plist);
1402 return mdatabase_list (tag0, tag1, tag2, tag3);
1406 if (tag2 != Mnil && MPLIST_SYMBOL (p2) != tag2)
1408 MPLIST_DO (p2, MPLIST_NEXT (p2))
1410 p3 = MPLIST_PLIST (p2);
1411 if (MPLIST_SYMBOL (p3) == Masterisk)
1413 if (expand_wildcard_database (p3))
1415 M17N_OBJECT_UNREF (plist);
1416 return mdatabase_list (tag0, tag1, tag2, tag3);
1420 if (tag3 != Mnil && MPLIST_SYMBOL (p3) != tag3)
1422 p3 = MPLIST_NEXT (p3);
1423 pl = mplist_add (pl, Mt, MPLIST_VAL (p3));
1428 if (MPLIST_TAIL_P (plist))
1429 M17N_OBJECT_UNREF (plist);
1435 @brief Define a data of the m17n database.
1437 The mdatabase_define () function defines a data that has tags
1438 $TAG0 through $TAG3 and additional information $EXTRA_INFO.
1440 $LOADER is a pointer to a function that loads the data from the
1441 database. This function is called from the mdatabase_load ()
1442 function with the two arguments $TAGS and $EXTRA_INFO. Here,
1443 $TAGS is the array of $TAG0 through $TAG3.
1445 If $LOADER is @c NULL, the default loader of the m17n library is
1446 used. In this case, $EXTRA_INFO must be a string specifying a
1447 filename that contains the data.
1450 If the operation was successful, mdatabase_define () returns a
1451 pointer to the defined data, which can be used as an argument to
1452 mdatabase_load (). Otherwise, it returns @c NULL. */
1455 @brief m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥Ç¡¼¥¿¤òÄêµÁ¤¹¤ë.
1457 ´Ø¿ô mdatabase_define () ¤Ï $TAG0 ¤«¤é $TAG3 ¤Þ¤Ç¤Î¥¿¥°¤ª¤è¤ÓÉղþðÊó
1458 $EXTRA_INFO ¤ò»ý¤Ä¥Ç¡¼¥¿¤òÄêµÁ¤¹¤ë¡£
1460 $LOADER ¤Ï¤½¤Î¥Ç¡¼¥¿¤Î¥í¡¼¥É¤ËÍѤ¤¤é¤ì¤ë´Ø¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¤³¤Î´Ø¿ô¤Ï
1461 mdatabase_load () ¤«¤é $TAGS ¤È $EXTRA_INFO ¤È¤¤¤¦Æó¤Ä¤Î°ú¿ôÉÕ¤¤Ç¸Æ¤Ó½Ð¤µ¤ì¤ë¡£¤³¤³¤Ç
1462 $TAGS ¤Ï $TAG0 ¤«¤é $TAG3 ¤Þ¤Ç¤ÎÇÛÎó¤Ç¤¢¤ë¡£
1464 ¤â¤· $LOADER ¤¬ @c NULL ¤Ê¤é¡¢m17n ¥é¥¤¥Ö¥é¥êɸ½à¤Î¥í¡¼¥À¤¬»È¤ï¤ì¤ë¡£¤³¤Î¾ì¹ç¤Ë¤Ï
1465 $EXTRA_INFO ¤Ï¥Ç¡¼¥¿¤ò´Þ¤à¥Õ¥¡¥¤¥ë̾¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
1468 ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mdatabase_define ()
1469 ¤ÏÄêµÁ¤µ¤ì¤¿¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤³¤Î¥Ý¥¤¥ó¥¿¤Ï´Ø¿ô mdatabase_load ()
1470 ¤Î°ú¿ô¤È¤·¤ÆÍѤ¤¤ë¤³¤È¤¬¤Ç¤¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£
1472 @latexonly \IPAlabel{mdatabase_define} @endlatexonly */
1476 mdatabase_load (), mdatabase_define () */
1479 mdatabase_define (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3,
1480 void *(*loader) (MSymbol *, void *),
1486 tags[0] = tag0, tags[1] = tag1, tags[2] = tag2, tags[3] = tag3;
1488 loader = load_database;
1489 mdb = register_database (tags, loader, extra_info, MDB_STATUS_EXPLICIT, NULL);
1495 @brief Load a data from the database.
1497 The mdatabase_load () function loads a data specified in $MDB and
1498 returns the contents. The type of contents depends on the type of
1501 If the data is of the @e plist @e type, this function returns a
1502 pointer to @e plist.
1504 If the database is of the @e chartable @e type, it returns a
1505 chartable. The default value of the chartable is set according to
1506 the second tag of the data as below:
1508 @li If the tag is #Msymbol, the default value is #Mnil.
1509 @li If the tag is #Minteger, the default value is -1.
1510 @li Otherwise, the default value is @c NULL.
1512 If the data is of the @e charset @e type, it returns a plist of length 2
1513 (keys are both #Mt). The value of the first element is an array
1514 of integers that maps code points to the corresponding character
1515 codes. The value of the second element is a chartable of integers
1516 that does the reverse mapping. The charset must be defined in
1521 @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹¤«¤é¥Ç¡¼¥¿¤ò¥í¡¼¥É¤¹¤ë.
1523 ´Ø¿ô mdatabase_load () ¤Ï $MDB
1524 ¤¬»Ø¤¹¥Ç¡¼¥¿¤ò¥í¡¼¥É¤·¡¢¤½¤ÎÃæ¿È¤òÊÖ¤¹¡£ÊÖ¤µ¤ì¤ë¤â¤Î¤Ï¥Ç¡¼¥¿¤Î¥¿¥¤¥×¤Ë¤è¤Ã¤Æ°Û¤Ê¤ë¡£
1526 ¥Ç¡¼¥¿¤¬ @e plist¥¿¥¤¥× ¤Ê¤é¤Ð¡¢ @e plist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
1528 ¥Ç¡¼¥¿¤¬ @e chartable¥¿¥¤¥× ¤Ê¤é¤Ðʸ»ú¥Æ¡¼¥Ö¥ë¤òÊÖ¤¹¡£
1529 ʸ»ú¥Æ¡¼¥Ö¥ë¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤϡ¢¥Ç¡¼¥¿¤ÎÂè2¥¿¥°¤Ë¤è¤Ã¤Æ°Ê²¼¤Î¤è¤¦¤Ë·è¤Þ¤ë¡£
1531 @li ¥¿¥°¤¬ #Msymbol ¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï #Mnil
1532 @li ¥¿¥°¤¬ #Minteger ¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï -1
1533 @li ¤½¤ì°Ê³°¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï @c NULL
1535 ¥Ç¡¼¥¿¤¬ @e charset¥¿¥¤¥× ¤Ê¤é¤ÐŤµ 2 ¤Î plist ¤òÊÖ¤¹¡Ê¥¡¼¤Ï¶¦¤Ë#Mt ¡Ë¡£
1536 ºÇ½é¤ÎÍ×ÁǤÎÃͤϥ³¡¼¥É¥Ý¥¤¥ó¥È¤òÂбþ¤¹¤ëʸ»ú¥³¡¼¥É¤Ë¥Þ¥Ã¥×¤¹¤ëÀ°¿ô¤ÎÇÛÎó¤Ç¤¢¤ë¡£
1537 £²ÈÖÌܤÎÍ×ÁǤÎÃͤϵդΥޥåפò¤¹¤ëʸ»ú¥Æ¡¼¥Ö¥ë¤Ç¤¢¤ë¡£
1538 ¤³¤Îʸ»ú¥»¥Ã¥È¤Ïͽ¤áÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
1540 @latexonly \IPAlabel{mdatabase_load} @endlatexonly
1545 mdatabase_load (), mdatabase_define () */
1548 mdatabase_load (MDatabase *mdb)
1550 return (*mdb->loader) (mdb->tag, mdb->extra_info);
1555 @brief Get tags of a data.
1557 The mdatabase_tag () function returns an array of tags (symbols)
1558 that identify the data in $MDB. The length of the array is
1562 @brief ¥Ç¡¼¥¿¤Î¥¿¥°¤òÆÀ¤ë.
1564 ´Ø¿ô mdatabase_tag () ¤Ï¡¢¥Ç¡¼¥¿ $MDB ¤Î¥¿¥°¡Ê¥·¥ó¥Ü¥ë¡Ë¤ÎÇÛÎó¤òÊÖ¤¹¡£ÇÛÎó¤ÎŤµ¤Ï
1567 @latexonly \IPAlabel{mdatabase_tag} @endlatexonly */
1570 mdatabase_tag (MDatabase *mdb)