You should have received a copy of the GNU Lesser General Public
License along with the m17n library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
02111-1307, USA. */
/***en
@addtogroup m17nDatabase
@brief The m17n database and API for it.
- The m17n library dynamically acquires various kinds of information
- in need from data in the <i> m17n database</i>. Application
+ The m17n library acquires various kinds of information
+ from data in the <i> m17n database</i> on demand. Application
programs can also add/load their original data to/from the m17n
- database. The m17n database contains multiple heterogeneous data,
- and each data is identified by four tags; TAG0, TAG1, TAG2, TAG3.
- Each tag must be a symbol.
+ database by setting the variable #mdatabase_dir to an
+ application-specific directory and storing data in it. Users can
+ overwrite those data by storing preferable data in the directory
+ specified by the environment variable "M17NDIR", or if it is not
+ set, in the directory "~/.m17n.d".
+
+ The m17n database contains multiple heterogeneous data, and each
+ data is identified by four tags; TAG0, TAG1, TAG2, TAG3. Each tag
+ must be a symbol.
TAG0 specifies the type of data stored in the database as below.
@li
-
If TAG0 is #Mchar_table, the data is of the @e chartable @e
type and provides information about each character. In this case,
TAG1 specifies the type of the information and must be #Msymbol,
symbols.
@li
-
If TAG0 is #Mcharset, the data is of the @e charset @e type
and provides a decode/encode mapping table for a charset. In this
case, TAG1 must be a symbol representing a charset. TAG2 and TAG3
can be any symbols.
@li
-
If TAG0 is neither #Mchar_table nor #Mcharset, the data is of
- the @e plist @e type. See the documentation of the mdatabase_load
- () function for the details. In this case, TAG1, TAG2, and TAG3
- can be any symbols.
+ the @e plist @e type. See the documentation of the
+ mdatabase_load () function for the details.
+ In this case, TAG1, TAG2, and TAG3 can be any symbols.
The notation \<TAG0, TAG1, TAG2, TAG3\> means a data with those
tags.
@addtogroup m17nDatabase
@brief m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤È¤½¤ì¤Ë´Ø¤¹¤ë API.
- m17n ¥é¥¤¥Ö¥é¥ê¤ÏɬÍפ˱þ¤¸¤ÆưŪ¤Ë @e m17n @e ¥Ç¡¼¥¿¥Ù¡¼¥¹ ¤«¤é¾ð
- Êó¤ò¼èÆÀ¤¹¤ë¡£¤Þ¤¿¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤âÆȼ«¤Î¥Ç¡¼¥¿¤ò
- m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ËÄɲä·¡¢¤½¤ì¤òưŪ¤Ë¼èÆÀ¤¹¤ë¤³¤È¤¬¤Ç¤¤ë¡£m17n
- ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤ÏÊ£¿ô¤Î¿Íͤʥǡ¼¥¿¤¬´Þ¤Þ¤ì¤Æ¤ª¤ê¡¢³Æ¥Ç¡¼¥¿¤Ï£´¤Ä¤Î
- ¥¿¥° TAG0, TAG1, TAG2, TAG3¡Ê¤¹¤Ù¤Æ¥·¥ó¥Ü¥ë¡Ë¤Ë¤è¤Ã¤Æ¼±Ê̤µ¤ì¤ë¡£
+ m17n ¥é¥¤¥Ö¥é¥ê¤ÏɬÍפ˱þ¤¸¤ÆưŪ¤Ë @e m17n @e ¥Ç¡¼¥¿¥Ù¡¼¥¹
+ ¤«¤é¾ðÊó¤ò¼èÆÀ¤¹¤ë¡£¤Þ¤¿¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤â¡¢Æȼ«¤Î¥Ç¡¼¥¿¤ò
+ m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ËÄɲä·¡¢¤½¤ì¤òưŪ¤Ë¼èÆÀ¤¹¤ë¤³¤È¤¬¤Ç¤¤ë¡£
+ ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤¬Æȼ«¤Î¥Ç¡¼¥¿¤òÄɲᦼèÆÀ¤¹¤ë¤Ë¤Ï¡¢ÊÑ¿ô
+ #mdatabase_dir ¤Ë¤½¤Î¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¸ÇͤΥǥ£¥ì¥¯¥È¥ê¤ò¥»¥Ã¥È¤·¡¢
+ ¤½¤ÎÃæ¤Ë¥Ç¡¼¥¿¤ò³ÊǼ¤¹¤ë¡£¥æ¡¼¥¶¤¬¤½¤Î¥Ç¡¼¥¿¤ò¥ª¡¼¥Ð¡¼¥é¥¤¥È¤·¤¿¤¤
+ ¤È¤¤Ï¡¢´Ä¶ÊÑ¿ô "M17NDIR" ¤Ç»ØÄꤵ¤ì¤ë¥Ç¥£¥ì¥¯¥È¥ê¡Ê»ØÄꤵ¤ì¤Æ¤¤¤Ê
+ ¤¤¤È¤¤Ï "~/.m17n.d" ¤È¤¤¤¦¥Ç¥£¥ì¥¯¥È¥ê¡Ë¤ËÊ̤Υǡ¼¥¿¤òÃÖ¤¯¡£
- TAG0 ¤Ï¥Ç¡¼¥¿¥Ù¡¼¥¹Æâ¤Î¥Ç¡¼¥¿¤Î¥¿¥¤¥×¤ò°Ê²¼¤Î¤è¤¦¤Ë»ØÄꤹ¤ë¡£
+ m17n
+ ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤ÏÊ£¿ô¤Î¿Íͤʥǡ¼¥¿¤¬´Þ¤Þ¤ì¤Æ¤ª¤ê¡¢³Æ¥Ç¡¼¥¿¤Ï
+ TAG0, TAG1, TAG2, TAG3¡Ê¤¹¤Ù¤Æ¥·¥ó¥Ü¥ë¡Ë¤Î£´¤Ä¤Î¥¿¥°¤Ë¤è¤Ã¤Æ¼±Ê̤µ¤ì¤ë¡£
- @li
-
- TAG0 ¤¬ #Mchar_table ¤Ç¤¢¤ë¥Ç¡¼¥¿¤Ï @e chartable¥¿¥¤¥× ¤È¸Æ¤Ð¤ì¡¢
- ³Æʸ»ú¤Ë´Ø¤¹¤ë¾ðÊó¤òÄ󶡤¹¤ë¡£¤³¤Î¾ì¹ç TAG1 ¤Ï¾ðÊó¤Î¼ïÎà¤ò»ØÄꤹ¤ë
- ¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢#Msymbol, #Minteger, #Mstring, #Mtext, #Mplist ¤Î
- ¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£TAG2 ¤È TAG3 ¤ÏǤ°Õ¤Î¥·¥ó¥Ü¥ë¤Ç¤è¤¤¡£
+ TAG0 ¤Ë¤è¤Ã¤Æ¡¢¥Ç¡¼¥¿¥Ù¡¼¥¹Æâ¤Î¥Ç¡¼¥¿¤Î¥¿¥¤¥×¤Ï¼¡¤Î¤è¤¦¤Ë»ØÄꤵ¤ì¤ë¡£
@li
+ TAG0 ¤¬ #Mchar_table ¤Ç¤¢¤ë¥Ç¡¼¥¿¤Ï @e chartable¥¿¥¤¥×
+ ¤È¸Æ¤Ð¤ì¡¢³Æʸ»ú¤Ë´Ø¤¹¤ë¾ðÊó¤òÄ󶡤¹¤ë¡£¤³¤Î¾ì¹ç
+ TAG1 ¤Ï¾ðÊó¤Î¼ïÎà¤ò»ØÄꤹ¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢#Msymbol, #Minteger, #Mstring,
+ #Mtext, #Mplist ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£TAG2 ¤È TAG3 ¤ÏǤ°Õ¤Î¥·¥ó¥Ü¥ë¤Ç¤è¤¤¡£
- TAG0 ¤¬ #Mcharset ¤Ç¤¢¤ë¥Ç¡¼¥¿¤Ï @e charset¥¿¥¤¥× ¤È¸Æ¤Ð¤ì¡¢Ê¸
- »ú¥»¥Ã¥ÈÍѤΥǥ³¡¼¥É¡¿¥¨¥ó¥³¡¼¥É¥Þ¥Ã¥×¤òÄ󶡤¹¤ë¡£¤³¤Î¾ì¹ç TAG1 ¤Ï
- ʸ»ú¥»¥Ã¥È¤Î¥·¥ó¥Ü¥ë¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£TAG2 ¤È TAG3 ¤ÏǤ°Õ¤Î¥·¥ó
- ¥Ü¥ë¤Ç¤è¤¤¡£
+ @li
+ TAG0 ¤¬ #Mcharset ¤Ç¤¢¤ë¥Ç¡¼¥¿¤Ï @e charset¥¿¥¤¥×
+ ¤È¸Æ¤Ð¤ì¡¢Ê¸»ú¥»¥Ã¥ÈÍѤΥǥ³¡¼¥É¡¿¥¨¥ó¥³¡¼¥É¥Þ¥Ã¥×¤òÄ󶡤¹¤ë¡£¤³¤Î¾ì¹ç TAG1
+ ¤Ïʸ»ú¥»¥Ã¥È¤Î¥·¥ó¥Ü¥ë¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£TAG2 ¤È TAG3
+ ¤ÏǤ°Õ¤Î¥·¥ó¥Ü¥ë¤Ç¤è¤¤¡£
@li
-
TAG0 ¤¬ #Mchar_table ¤Ç¤â #Mcharset ¤Ç¤â¤Ê¤¤¾ì¹ç¡¢¤½¤Î¥Ç¡¼¥¿¤Ï @e
- plist ¥¿¥¤¥× ¤Ç¤¢¤ë¡£¾ÜºÙ¤Ë´Ø¤·¤Æ¤Ï´Ø¿ô mdatabase_load () ¤ÎÀâÌÀ¤ò
- »²¾È¤Î¤³¤È¡£¤³¤Î¾ì¹ç TAG1¡¢TAG2¡¢TAG3 ¤ÏǤ°Õ¤Î¥·¥ó¥Ü¥ë¤Ç¤è¤¤¡£
+ plist¥¿¥¤¥× ¤Ç¤¢¤ë¡£¾ÜºÙ¤Ë´Ø¤·¤Æ¤Ï´Ø¿ô mdatabase_load ()
+ ¤ÎÀâÌÀ¤ò»²¾È¤Î¤³¤È¡£¤³¤Î¾ì¹ç TAG1¡¢TAG2¡¢TAG3 ¤ÏǤ°Õ¤Î¥·¥ó¥Ü¥ë¤Ç¤è¤¤¡£
- ÆÃÄê¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò \<TAG0, TAG1, TAG2, TAG3\> ¤È¤¤¤¦·Á
- ¼°¤Çɽ¤ï¤¹¡£
+ ÆÃÄê¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò \<TAG0, TAG1, TAG2, TAG3\>
+ ¤È¤¤¤¦·Á¼°¤Çɽ¤¹¡£
- ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï¡¢¤Þ¤º´Ø¿ô mdatabase_find () ¤ò»È¤Ã¤Æ¥Ç¡¼
- ¥¿¥Ù¡¼¥¹¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÝ»ý¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¡Ê#MDatabase ·¿¡Ë¤Ø¤Î
- ¥Ý¥¤¥ó¥¿¤òÆÀ¤ë¡£¤½¤ì¤ËÀ®¸ù¤·¤¿¤é¡¢ mdatabase_load () ¤Ë¤è¤Ã¤Æ¼ÂºÝ
- ¤Ë¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¥í¡¼¥É¤¹¤ë¡£¹½Â¤ÂÎ #MDatabase ¼«¿È¤¬¤É¤¦¼ÂÁõ¤µ¤ì
- ¤Æ¤¤¤ë¤«¤Ï¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤«¤é¤Ï¸«¤¨¤Ê¤¤¡£
+ ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï¡¢¤Þ¤º´Ø¿ô mdatabase_find ()
+ ¤ò»È¤Ã¤Æ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÝ»ý¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¡Ê#MDatabase
+ ·¿¡Ë¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÆÀ¤ë¡£¤½¤ì¤ËÀ®¸ù¤·¤¿¤é¡¢ mdatabase_load ()
+ ¤Ë¤è¤Ã¤Æ¼ÂºÝ¤Ë¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¥í¡¼¥É¤¹¤ë¡£¹½Â¤ÂÎ #MDatabase
+ ¼«¿È¤¬¤É¤¦¼ÂÁõ¤µ¤ì¤Æ¤¤¤ë¤«¤Ï¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤«¤é¤Ï¸«¤¨¤Ê¤¤¡£
@latexonly \IPAlabel{database} @endlatexonly
*/
#include <sys/stat.h>
#include <unistd.h>
#include <limits.h>
+#include <glob.h>
+#include <time.h>
+#include <libgen.h>
#include "m17n.h"
#include "m17n-misc.h"
/** The file containing a list of databases. */
#define MDB_DIR "mdb.dir"
-#define MDB_DIR_LEN 8
+/** Length of MDB_DIR. */
+#define MDB_DIR_LEN 7
-/** List of database directories. */
-static MPlist *mdb_dir_list;
+#define MAX_TIME(TIME1, TIME2) ((TIME1) >= (TIME2) ? (TIME1) : (TIME2))
+
+#define GEN_PATH(path, dir, dir_len, file, file_len) \
+ (dir_len + file_len > PATH_MAX ? 0 \
+ : (memcpy (path, dir, dir_len), \
+ memcpy (path + dir_len, file, file_len), \
+ path[dir_len + file_len] = '\0', 1))
+
+static MSymbol Masterisk;
/** Structure for a data in the m17n database. */
void *extra_info;
};
-/** List of all data. */
-struct MDatabaseList
-{
- int size, inc, used;
- MDatabase *mdbs;
-};
-
-static struct MDatabaseList mdb_list;
-
+static MPlist *mdatabase__list;
static int
read_number (char *buf, int *i)
i++, to = read_number (buf, &i);
else
to = from;
- if (from < 0 || to < 0)
- goto label_error;
+ if (from < 0 || to < from)
+ continue;
while (buf[i] && isspace ((unsigned) buf[i])) i++;
c = buf[i];
if (!c)
- break;
+ continue;
if (type == Mstring)
{
}
else if (type == Msymbol)
{
+ char *p = buf + i;
+
+ while (*p && ! isspace (*p))
+ {
+ if (*p == '\\' && p[1] != '\0')
+ {
+ memmove (p, p + 1, buf + len - (p + 1));
+ len--;
+ }
+ p++;
+ }
+ *p = '\0';
if (! strcmp (buf + i, "nil"))
val = (void *) Mnil;
else
strcpy (buf, msymbol_name (tags[0]));
for (i = 1; i < 4; i++)
{
- strcat (buf, ", ");
+ strcat (buf, ",");
strcat (buf, msymbol_name (tags[i]));
}
return buf;
}
+char *
+find_file (MDatabaseInfo *db_info, struct stat *buf)
+{
+ MPlist *plist;
+ char path[PATH_MAX + 1];
+
+ MPLIST_DO (plist, mdatabase__dir_list)
+ {
+ MDatabaseInfo *dir_info = MPLIST_VAL (plist);
+
+ if (dir_info->status != MDB_STATUS_DISABLED
+ && GEN_PATH (path, dir_info->filename, dir_info->len,
+ db_info->filename, db_info->len)
+ && stat (path, buf) == 0)
+ return strdup (path);
+ }
+ return NULL;
+}
+
+
+/* Return the absolute file name for DB_INFO->filename. If BUF is
+ non-NULL, store the result of `stat' call in it. It returns NULL
+ if no absolute file name was found. */
+
+char *
+get_database_file (MDatabaseInfo *db_info, struct stat *buf)
+{
+ if (db_info->status == MDB_STATUS_DISABLED)
+ return NULL;
+ if (db_info->absolute_filename)
+ {
+ if (buf)
+ stat (db_info->absolute_filename, buf);
+ }
+ else
+ {
+ struct stat stat_buf;
+ struct stat *statbuf = buf ? buf : &stat_buf;
+
+ db_info->absolute_filename = find_file (db_info, statbuf);
+ }
+
+ return db_info->absolute_filename;
+}
+
static void *
load_database (MSymbol *tags, void *extra_info)
{
- FILE *fp;
- char *filename = (char *) extra_info;
+ MDatabaseInfo *db_info = extra_info;
void *value;
+ char *filename = get_database_file (db_info, NULL);
+ FILE *fp;
+ int mdebug_mask = MDEBUG_DATABASE;
+ char buf[256];
- if (filename[0] == '/')
- fp = fopen (filename, "r");
- else
+ MDEBUG_PRINT1 (" [DB] <%s>", gen_database_name (buf, tags));
+ if (! filename || ! (fp = fopen (filename, "r")))
{
- MPlist *plist;
- char path[PATH_MAX];
-
- MPLIST_DO (plist, mdb_dir_list)
- {
- strcpy (path, (char *) MPLIST_VAL (plist));
- strcat (path, filename);
- fp = fopen (path, "r");
- if (fp)
- break;
- }
+ if (filename)
+ MDEBUG_PRINT1 (" open fail: %s\n", filename);
+ else
+ MDEBUG_PRINT1 (" not found: %s\n", db_info->filename);
+ MERROR (MERROR_DB, NULL);
}
- if (! fp)
- MERROR (MERROR_DB, NULL);
+
+ MDEBUG_PRINT1 (" from %s\n", filename);
if (tags[0] == Mchar_table)
value = load_chartable (fp, tags[1]);
else if (tags[0] == Mcharset)
value = load_charset (fp, tags[1]);
else
- value = mplist__from_file (fp);
+ value = mplist__from_file (fp, NULL);
fclose (fp);
if (! value)
MERROR (MERROR_DB, NULL);
+ db_info->time = time (NULL);
return value;
}
-/** Copy DIRNAME to a newly allocated memory and return it. If
- DIRNAME does not end with a slash, append a slash to the new memory. */
+/** Return a newly allocated MDatabaseInfo for DIRNAME. */
-static char *
-duplicate_dirname (char *dirname)
+static MDatabaseInfo *
+get_dir_info (char *dirname)
{
- struct stat buf;
- int len;
- char *str;
+ MDatabaseInfo *dir_info;
+
+ MSTRUCT_CALLOC (dir_info, MERROR_DB);
+ if (dirname)
+ {
+ int len = strlen (dirname);
+
+ if (len + MDB_DIR_LEN < PATH_MAX)
+ {
+ MTABLE_MALLOC (dir_info->filename, len + 2, MERROR_DB);
+ memcpy (dir_info->filename, dirname, len + 1);
+ /* Append PATH_SEPARATOR if DIRNAME doesn't end with it. */
+ if (dir_info->filename[len - 1] != PATH_SEPARATOR)
+ {
+ dir_info->filename[len] = PATH_SEPARATOR;
+ dir_info->filename[++len] = '\0';
+ }
+ dir_info->len = len;
+ dir_info->status = MDB_STATUS_OUTDATED;
+ }
+ else
+ dir_info->status = MDB_STATUS_DISABLED;
+ }
+ else
+ dir_info->status = MDB_STATUS_DISABLED;
+ return dir_info;
+}
- if (! dirname
- || stat (dirname, &buf) < 0)
+static MDatabase *
+find_database (MSymbol tags[4])
+{
+ MPlist *plist;
+ int i;
+
+ if (! mdatabase__list)
return NULL;
+ for (i = 0, plist = mdatabase__list; i < 4; i++)
+ {
+ plist = mplist__assq (plist, tags[i]);
+ if (! plist)
+ return NULL;
+ plist = MPLIST_PLIST (plist);
+ plist = MPLIST_NEXT (plist);
+ }
+ return MPLIST_VAL (plist);
+}
+
+static void
+free_db_info (MDatabaseInfo *db_info)
+{
+ free (db_info->filename);
+ if (db_info->absolute_filename
+ && db_info->filename != db_info->absolute_filename)
+ free (db_info->absolute_filename);
+ free (db_info);
+}
+
+static int
+check_version (MText *version)
+{
+ char *verstr = (char *) MTEXT_DATA (version);
+ char *endp = verstr + mtext_nbytes (version);
+ int ver[3];
+ int i;
- len = strlen (dirname);
- MTABLE_MALLOC (str, len + 2, MERROR_DB);
- memcpy (str, dirname, len + 1);
- if (str[len - 1] != '/')
+ ver[0] = ver[1] = ver[2] = 0;
+ for (i = 0; verstr < endp; verstr++)
{
- str[len] = '/';
- str[len + 1] = '\0';
+ if (*verstr == '.')
+ {
+ i++;
+ if (i == 3)
+ break;
+ continue;
+ }
+ if (! isdigit (*verstr))
+ break;
+ ver[i] = ver[i] * 10 + (*verstr - '0');
}
- return str;
+ return (ver[0] < M17NLIB_MAJOR_VERSION
+ || (ver[0] == M17NLIB_MAJOR_VERSION
+ && (ver[1] < M17NLIB_MINOR_VERSION
+ || (ver[1] == M17NLIB_MINOR_VERSION
+ && ver[2] <= M17NLIB_PATCH_LEVEL))));
+}
+
+static MDatabase *
+register_database (MSymbol tags[4],
+ void *(*loader) (MSymbol *, void *),
+ void *extra_info, enum MDatabaseStatus status)
+{
+ MDatabase *mdb;
+ MDatabaseInfo *db_info;
+ int i;
+ MPlist *plist;
+
+ if (! mdatabase__list)
+ mdatabase__list = mplist ();
+
+ for (i = 0, plist = mdatabase__list; i < 4; i++)
+ {
+ MPlist *pl = mplist__assq (plist, tags[i]);
+
+ if (pl)
+ pl = MPLIST_PLIST (pl);
+ else
+ {
+ pl = mplist ();
+ mplist_add (pl, Msymbol, tags[i]);
+ mplist_push (plist, Mplist, pl);
+ M17N_OBJECT_UNREF (pl);
+ }
+ plist = MPLIST_NEXT (pl);
+ }
+
+ if (MPLIST_TAIL_P (plist))
+ {
+ MSTRUCT_MALLOC (mdb, MERROR_DB);
+ for (i = 0; i < 4; i++)
+ mdb->tag[i] = tags[i];
+ mdb->loader = loader;
+ if (loader == load_database)
+ {
+ MSTRUCT_CALLOC (db_info, MERROR_DB);
+ mdb->extra_info = db_info;
+ }
+ else
+ {
+ db_info = NULL;
+ mdb->extra_info = extra_info;
+ }
+ mplist_push (plist, Mt, mdb);
+ }
+ else
+ {
+ mdb = MPLIST_VAL (plist);
+ if (loader == load_database)
+ db_info = mdb->extra_info;
+ else
+ db_info = NULL;
+ }
+
+ if (db_info)
+ {
+ db_info->status = status;
+ if (! db_info->filename
+ || strcmp (db_info->filename, (char *) extra_info) != 0)
+ {
+ if (db_info->filename)
+ free (db_info->filename);
+ if (db_info->absolute_filename
+ && db_info->filename != db_info->absolute_filename)
+ free (db_info->absolute_filename);
+ db_info->filename = strdup ((char *) extra_info);
+ db_info->len = strlen ((char *) extra_info);
+ db_info->time = 0;
+ }
+ if (db_info->filename[0] == PATH_SEPARATOR)
+ db_info->absolute_filename = db_info->filename;
+ else
+ db_info->absolute_filename = NULL;
+ }
+
+ if (mdb->tag[0] == Mchar_table
+ && mdb->tag[2] != Mnil
+ && (mdb->tag[1] == Mstring || mdb->tag[1] == Mtext
+ || mdb->tag[1] == Msymbol || mdb->tag[1] == Minteger
+ || mdb->tag[1] == Mplist))
+ mchar__define_prop (mdb->tag[2], mdb->tag[1], mdb);
+ return mdb;
+}
+
+static void
+register_databases_in_files (MSymbol tags[4], glob_t *globbuf, int headlen)
+{
+ int i, j;
+ MPlist *load_key = mplist ();
+ FILE *fp;
+ MPlist *plist;
+
+ for (i = 0; i < globbuf->gl_pathc; i++)
+ {
+ if (! (fp = fopen (globbuf->gl_pathv[i], "r")))
+ continue;
+ plist = mplist__from_file (fp, load_key);
+ fclose (fp);
+ if (! plist)
+ continue;
+ if (MPLIST_PLIST_P (plist))
+ {
+ MPlist *pl;
+ MSymbol tags2[4];
+
+ for (j = 0, pl = MPLIST_PLIST (plist); j < 4 && MPLIST_SYMBOL_P (pl);
+ j++, pl = MPLIST_NEXT (pl))
+ tags2[j] = MPLIST_SYMBOL (pl);
+ for (; j < 4; j++)
+ tags2[j] = Mnil;
+ for (j = 0; j < 4; j++)
+ if (tags[j] == Masterisk ? tags2[j] == Mnil
+ : (tags[j] != Mnil && tags[j] != tags2[j]))
+ break;
+ if (j == 4)
+ {
+ MText *version = NULL;
+
+ MPLIST_DO (pl, pl)
+ version = MPLIST_MTEXT_P (pl) ? MPLIST_MTEXT (pl) : NULL;
+ if (! version || check_version (version))
+ register_database (tags2, load_database,
+ globbuf->gl_pathv[i] + headlen,
+ MDB_STATUS_AUTO);
+ }
+ }
+ M17N_OBJECT_UNREF (plist);
+ }
+ M17N_OBJECT_UNREF (load_key);
}
\f
/* Internal API */
+/** List of database directories. */
+MPlist *mdatabase__dir_list;
+
int
mdatabase__init ()
{
- char *dir;
- int i;
- MPlist *plist;
- FILE *fp;
+ MDatabaseInfo *dir_info;
+ char *path;
Mchar_table = msymbol ("char-table");
+ Masterisk = msymbol ("*");
- mdb_dir_list = mplist ();
+ mdatabase__dir_list = mplist ();
/** The macro M17NDIR specifies a directory where the system-wide
MDB_DIR file exists. */
- if ((dir = duplicate_dirname (M17NDIR)))
- mplist_set (mdb_dir_list, Mt, dir);
+ mplist_set (mdatabase__dir_list, Mt, get_dir_info (M17NDIR));
/* The variable mdatabase_dir specifies a directory where an
application program specific MDB_DIR file exists. */
- if ((dir = duplicate_dirname (mdatabase_dir)))
- mplist_push (mdb_dir_list, Mt, dir);
+ if (mdatabase_dir && strlen (mdatabase_dir) > 0)
+ mplist_push (mdatabase__dir_list, Mt, get_dir_info (mdatabase_dir));
+
+ /* The environment variable M17NDIR specifies a directory where a
+ user specific MDB_DIR file exists. */
+ path = getenv ("M17NDIR");
+ if (path && strlen (path) > 0)
+ mplist_push (mdatabase__dir_list, Mt, get_dir_info (path));
+ else
+ {
+ /* If the env var M17NDIR is not set, check "~/.m17n.d". */
+ char *home = getenv ("HOME");
+ int len;
+
+ if (home
+ && (len = strlen (home))
+ && (path = alloca (len + 9)))
+ {
+ strcpy (path, home);
+ if (path[len - 1] != PATH_SEPARATOR)
+ path[len++] = PATH_SEPARATOR;
+ strcpy (path + len, ".m17n.d");
+ dir_info = get_dir_info (path);
+ mplist_push (mdatabase__dir_list, Mt, dir_info);
+ }
+ else
+ mplist_push (mdatabase__dir_list, Mt, get_dir_info (NULL));
+ }
+
+ mdatabase__finder = ((void *(*) (MSymbol, MSymbol, MSymbol, MSymbol))
+ mdatabase_find);
+ mdatabase__loader = (void *(*) (void *)) mdatabase_load;
+
+ mdatabase__list = mplist ();
+ mdatabase__update ();
+ return 0;
+}
+
+void
+mdatabase__fini (void)
+{
+ MPlist *plist, *p0, *p1, *p2, *p3;
- /* The environment variable M17NDIR (if non-NULL) specifies a
- directory where a user specific MDB_DIR file exists. */
- if ((dir = duplicate_dirname (getenv ("M17NDIR"))))
- mplist_push (mdb_dir_list, Mt, dir);
+ MPLIST_DO (plist, mdatabase__dir_list)
+ free_db_info (MPLIST_VAL (plist));
+ M17N_OBJECT_UNREF (mdatabase__dir_list);
- MLIST_INIT1 (&mdb_list, mdbs, 256);
- MPLIST_DO (plist, mdb_dir_list)
+ /* MDATABASE_LIST ::= ((TAG0 (TAG1 (TAG2 (TAG3 t:MDB) ...) ...) ...) ...) */
+ MPLIST_DO (plist, mdatabase__list)
{
+ p0 = MPLIST_PLIST (plist);
+ /* P0 ::= (TAG0 (TAG1 (TAG2 (TAG3 t:MDB) ...) ...) ...) */
+ MPLIST_DO (p0, MPLIST_NEXT (p0))
+ {
+ p1 = MPLIST_PLIST (p0);
+ /* P1 ::= (TAG1 (TAG2 (TAG3 t:MDB) ...) ...) */
+ MPLIST_DO (p1, MPLIST_NEXT (p1))
+ {
+ p2 = MPLIST_PLIST (p1);
+ /* P2 ::= (TAG2 (TAG3 t:MDB) ...) */
+ MPLIST_DO (p2, MPLIST_NEXT (p2))
+ {
+ MDatabase *mdb;
+
+ p3 = MPLIST_PLIST (p2); /* P3 ::= (TAG3 t:MDB) */
+ p3 = MPLIST_NEXT (p3);
+ mdb = MPLIST_VAL (p3);
+ if (mdb->loader == load_database)
+ free_db_info (mdb->extra_info);
+ free (mdb);
+ }
+ }
+ }
+ }
+ M17N_OBJECT_UNREF (mdatabase__list);
+}
+
+void
+mdatabase__update (void)
+{
+ MPlist *plist, *p0, *p1, *p2, *p3;
+ char path[PATH_MAX + 1];
+ MDatabaseInfo *dir_info;
+ struct stat statbuf;
+ int rescan = 0;
+
+ /* Update elements of mdatabase__dir_list. */
+ MPLIST_DO (plist, mdatabase__dir_list)
+ {
+ dir_info = MPLIST_VAL (plist);
+ if (dir_info->filename)
+ {
+ if (stat (dir_info->filename, &statbuf) == 0
+ && (statbuf.st_mode & S_IFDIR))
+ {
+ if (dir_info->time < statbuf.st_mtime)
+ {
+ rescan = 1;
+ dir_info->time = statbuf.st_mtime;
+ }
+ if (GEN_PATH (path, dir_info->filename, dir_info->len,
+ MDB_DIR, MDB_DIR_LEN)
+ && stat (path, &statbuf) >= 0
+ && dir_info->time < statbuf.st_mtime)
+ {
+ rescan = 1;
+ dir_info->time = statbuf.st_mtime;
+ }
+ dir_info->status = MDB_STATUS_UPDATED;
+ }
+ else
+ {
+ if (dir_info->status != MDB_STATUS_DISABLED)
+ {
+ rescan = 1;
+ dir_info->time = 0;
+ dir_info->status = MDB_STATUS_DISABLED;
+ }
+ }
+ }
+ }
+
+ if (! rescan)
+ return;
+
+ /* At first, mark all databases defined automatically from mdb.dir
+ file(s) as "disabled". */
+ MPLIST_DO (plist, mdatabase__list)
+ {
+ p0 = MPLIST_PLIST (plist);
+ /* P0 ::= (TAG0 (TAG1 (TAG2 (TAG3 MDB) ...) ...) ...) */
+ MPLIST_DO (p0, MPLIST_NEXT (p0))
+ {
+ p1 = MPLIST_PLIST (p0);
+ MPLIST_DO (p1, MPLIST_NEXT (p1))
+ {
+ p2 = MPLIST_PLIST (p1);
+ MPLIST_DO (p2, MPLIST_NEXT (p2))
+ {
+ MDatabase *mdb;
+ MDatabaseInfo *db_info;
+
+ p3 = MPLIST_PLIST (p2);
+ p3 = MPLIST_NEXT (p3);
+ mdb = MPLIST_VAL (p3);
+ db_info = mdb->extra_info;
+ if (db_info->status == MDB_STATUS_AUTO)
+ db_info->status = MDB_STATUS_DISABLED;
+ }
+ }
+ }
+ }
+
+ plist = mplist ();
+ MPLIST_DO (p0, mdatabase__dir_list)
+ mplist_push (plist, MPLIST_KEY (p0), MPLIST_VAL (p0));
+
+ while (! MPLIST_TAIL_P (plist))
+ {
+ MDatabaseInfo *dir_info = mplist_pop (plist);
MPlist *pl, *p;
- int len;
- char path[PATH_MAX];
+ int i;
+ FILE *fp;
- dir = (char *) MPLIST_VAL (plist);
- len = strlen (dir);
- if (len + MDB_DIR_LEN >= PATH_MAX)
+ if (dir_info->status == MDB_STATUS_DISABLED)
+ continue;
+ if (! GEN_PATH (path, dir_info->filename, dir_info->len,
+ MDB_DIR, MDB_DIR_LEN))
continue;
- memcpy (path, dir, len);
- memcpy (path + len, MDB_DIR, MDB_DIR_LEN);
if (! (fp = fopen (path, "r")))
continue;
- pl = mplist__from_file (fp);
+ pl = mplist__from_file (fp, NULL);
fclose (fp);
if (! pl)
continue;
MPLIST_DO (p, pl)
{
- MDatabase mdb;
+ MSymbol tags[4];
MPlist *p1;
+ MText *mt;
int nbytes;
+ int with_wildcard = 0;
if (! MPLIST_PLIST_P (p))
continue;
- for (i = 0, p1 = MPLIST_PLIST (p);
- i < 4 && MPLIST_KEY (p1) == Msymbol;
+ for (i = 0, p1 = MPLIST_PLIST (p); i < 4 && MPLIST_SYMBOL_P (p1);
i++, p1 = MPLIST_NEXT (p1))
- mdb.tag[i] = MPLIST_SYMBOL (p1);
+ with_wildcard |= ((tags[i] = MPLIST_SYMBOL (p1)) == Masterisk);
if (i == 0
+ || tags[0] == Masterisk
|| ! MPLIST_MTEXT_P (p1))
continue;
for (; i < 4; i++)
- mdb.tag[i] = Mnil;
- if (mdatabase_find (mdb.tag[0], mdb.tag[1],
- mdb.tag[2], mdb.tag[3]))
+ tags[i] = Mnil;
+ mt = MPLIST_MTEXT (p1);
+ nbytes = mtext_nbytes (mt);
+ if (nbytes > PATH_MAX)
continue;
+ memcpy (path, MTEXT_DATA (mt), nbytes);
+ path[nbytes] = '\0';
+ if (with_wildcard)
+ {
+ glob_t globbuf;
+ MPlist *dlist;
- mdb.loader = load_database;
- nbytes = mconv_encode_buffer (Mcoding_utf_8, MPLIST_MTEXT (p1),
- (unsigned char *) path, PATH_MAX);
- if (nbytes < 0 || nbytes >= PATH_MAX)
- continue;
- path[nbytes++] = '\0';
- mdb.extra_info = (void *) strdup (path);
- MLIST_APPEND1 (&mdb_list, mdbs, mdb, MERROR_DB);
+ if (tags[0] == Mchar_table || tags[0] == Mcharset)
+ continue;
+ if (path[0] == PATH_SEPARATOR)
+ {
+ if (glob (path, GLOB_NOSORT, NULL, &globbuf))
+ continue;
+ register_databases_in_files (tags, &globbuf, 0);
+ globfree (&globbuf);
+ }
+ else
+ MPLIST_DO (dlist, mdatabase__dir_list)
+ {
+ MDatabaseInfo *d_info = MPLIST_VAL (dlist);
+
+ if (d_info->status == MDB_STATUS_DISABLED)
+ continue;
+ if (! GEN_PATH (path, d_info->filename, d_info->len,
+ MTEXT_DATA (mt), nbytes))
+ continue;
+ if (glob (path, GLOB_NOSORT, NULL, &globbuf))
+ continue;
+ register_databases_in_files (tags, &globbuf, d_info->len);
+ globfree (&globbuf);
+ }
+ }
+ else
+ {
+ MText *version = NULL;
+
+ MPLIST_DO (p1, p1)
+ version = MPLIST_MTEXT_P (pl) ? MPLIST_MTEXT (pl) : NULL;
+ if (! version || check_version (version))
+ register_database (tags, load_database, path, MDB_STATUS_AUTO);
+ }
}
M17N_OBJECT_UNREF (pl);
}
+ M17N_OBJECT_UNREF (plist);
+}
- mdatabase__finder = ((void *(*) (MSymbol, MSymbol, MSymbol, MSymbol))
- mdatabase_find);
- mdatabase__loader = (void *(*) (void *)) mdatabase_load;
+MPlist *
+mdatabase__load_for_keys (MDatabase *mdb, MPlist *keys)
+{
+ int mdebug_mask = MDEBUG_DATABASE;
+ MDatabaseInfo *db_info;
+ char *filename;
+ FILE *fp;
+ MPlist *plist;
+ char name[256];
- return 0;
+ if (mdb->loader != load_database
+ || mdb->tag[0] == Mchar_table
+ || mdb->tag[0] == Mcharset)
+ MERROR (MERROR_DB, NULL);
+ MDEBUG_PRINT1 (" [DB] <%s>.\n",
+ gen_database_name (name, mdb->tag));
+ db_info = mdb->extra_info;
+ filename = get_database_file (db_info, NULL);
+ if (! filename || ! (fp = fopen (filename, "r")))
+ MERROR (MERROR_DB, NULL);
+ plist = mplist__from_file (fp, keys);
+ fclose (fp);
+ return plist;
}
-void
-mdatabase__fini (void)
+
+/* Check if the database MDB should be reloaded or not. It returns:
+
+ 1: The database has not been updated since it was loaded last
+ time.
+
+ 0: The database has never been loaded or has been updated
+ since it was loaded last time.
+
+ -1: The database is not loadable at the moment. */
+
+int
+mdatabase__check (MDatabase *mdb)
{
- int i;
- MPlist *plist;
+ MDatabaseInfo *db_info = (MDatabaseInfo *) mdb->extra_info;
+ struct stat buf;
+
+ if (! get_database_file (db_info, &buf))
+ return -1;
+ if (db_info->time < buf.st_mtime)
+ return 0;
+ if (db_info->status == MDB_STATUS_AUTO
+ && db_info->filename != db_info->absolute_filename)
+ {
+ MDatabase *new;
+
+ mdatabase__update ();
+ new = find_database (mdb->tag);
+ if (new != mdb)
+ return 0;
+ }
- MPLIST_DO (plist, mdb_dir_list)
- free (MPLIST_VAL (plist));
- M17N_OBJECT_UNREF (mdb_dir_list);
+ return 1;
+}
- for (i = 0; i < mdb_list.used; i++)
+/* Search directories in mdatabase__dir_list for file FILENAME. If
+ the file exist, return the absolute pathname. If FILENAME is
+ already absolute, return a copy of it. */
+
+char *
+mdatabase__find_file (char *filename)
+{
+ struct stat buf;
+ MDatabaseInfo db_info;
+
+ if (filename[0] == PATH_SEPARATOR)
+ return (stat (filename, &buf) == 0 ? filename : NULL);
+ db_info.filename = filename;
+ db_info.len = strlen (filename);
+ db_info.time = 0;
+ db_info.absolute_filename = NULL;
+ if (! get_database_file (&db_info, &buf)
+ || stat (db_info.absolute_filename, &buf) < 0)
+ return NULL;
+ return db_info.absolute_filename;
+}
+
+char *
+mdatabase__file (MDatabase *mdb)
+{
+ MDatabaseInfo *db_info;
+
+ if (mdb->loader != load_database)
+ return NULL;
+ db_info = mdb->extra_info;
+ return get_database_file (db_info, NULL);
+}
+
+int
+mdatabase__lock (MDatabase *mdb)
+{
+ MDatabaseInfo *db_info;
+ struct stat buf;
+ FILE *fp;
+ int len;
+ char *file;
+
+ if (mdb->loader != load_database)
+ return -1;
+ db_info = mdb->extra_info;
+ if (db_info->lock_file)
+ return -1;
+ file = get_database_file (db_info, NULL);
+ if (! file)
+ return -1;
+ len = strlen (file);
+ db_info->uniq_file = malloc (len + 35);
+ if (! db_info->uniq_file)
+ return -1;
+ db_info->lock_file = malloc (len + 5);
+ if (! db_info->lock_file)
+ {
+ free (db_info->uniq_file);
+ return -1;
+ }
+ sprintf (db_info->uniq_file, "%s.%X.%X", db_info->absolute_filename,
+ (unsigned) time (NULL), (unsigned) getpid ());
+ sprintf (db_info->lock_file, "%s.LCK", db_info->absolute_filename);
+
+ fp = fopen (db_info->uniq_file, "w");
+ if (! fp)
+ {
+ char *str = strdup (db_info->uniq_file);
+ char *dir = dirname (str);
+
+ if (stat (dir, &buf) == 0
+ || mkdir (dir, 0777) < 0
+ || ! (fp = fopen (db_info->uniq_file, "w")))
+ {
+ free (db_info->uniq_file);
+ free (db_info->lock_file);
+ db_info->lock_file = NULL;
+ free (str);
+ return -1;
+ }
+ free (str);
+ }
+ fclose (fp);
+ if (link (db_info->uniq_file, db_info->lock_file) < 0
+ && (stat (db_info->uniq_file, &buf) < 0
+ || buf.st_nlink != 2))
+ {
+ unlink (db_info->uniq_file);
+ unlink (db_info->lock_file);
+ free (db_info->uniq_file);
+ free (db_info->lock_file);
+ db_info->lock_file = NULL;
+ return 0;
+ }
+ return 1;
+}
+
+int
+mdatabase__save (MDatabase *mdb, MPlist *data)
+{
+ MDatabaseInfo *db_info;
+ FILE *fp;
+ char *file;
+ MText *mt;
+ int ret;
+
+ if (mdb->loader != load_database)
+ return -1;
+ db_info = mdb->extra_info;
+ if (! db_info->lock_file)
+ return -1;
+ file = get_database_file (db_info, NULL);
+ if (! file)
+ return -1;
+ mt = mtext ();
+ if (mplist__serialize (mt, data, 1) < 0)
+ {
+ M17N_OBJECT_UNREF (mt);
+ return -1;
+ }
+ fp = fopen (db_info->uniq_file, "w");
+ if (! fp)
{
- MDatabase *mdb = mdb_list.mdbs + i;
+ M17N_OBJECT_UNREF (mt);
+ return -1;
+ }
+ mconv_encode_stream (msymbol ("utf-8"), mt, fp);
+ M17N_OBJECT_UNREF (mt);
+ fclose (fp);
+ if ((ret = rename (db_info->uniq_file, file)) < 0)
+ unlink (db_info->uniq_file);
+ free (db_info->uniq_file);
+ db_info->uniq_file = NULL;
+ return ret;
+}
- if (mdb->loader == load_database)
- free (mdb->extra_info);
+int
+mdatabase__unlock (MDatabase *mdb)
+{
+ MDatabaseInfo *db_info;
+
+ if (mdb->loader != load_database)
+ return -1;
+ db_info = mdb->extra_info;
+ if (! db_info->lock_file)
+ return -1;
+ unlink (db_info->lock_file);
+ free (db_info->lock_file);
+ db_info->lock_file = NULL;
+ if (db_info->uniq_file)
+ {
+ unlink (db_info->uniq_file);
+ free (db_info->uniq_file);
}
- MLIST_FREE1 (&mdb_list, mdbs);
+ return 0;
}
/*** @} */
/***ja
@brief ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¸ÇͤΥǡ¼¥¿Íѥǥ£¥ì¥¯¥È¥ê.
- ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤¬¡¢¤½¤Î¥×¥í¥°¥é¥à¸ÇͤΥǡ¼¥¿¤ä m17n ¥Ç¡¼
- ¥¿¥Ù¡¼¥¹¤ò¾å½ñ¤¤¹¤ë¥Ç¡¼¥¿¤òÄ󶡤¹¤ë¾ì¹ç¤Ë¤Ï¡¢¥Þ¥¯¥í M17N_INIT ()
- ¤ò¸Æ¤ÖÁ°¤Ë¤³¤ÎÊÑ¿ô¤ò¥Ç¡¼¥¿¥Õ¥¡¥¤¥ë¤ò´Þ¤à¥Ç¥£¥ì¥¯¥È¥ê̾¤Ë¥»¥Ã¥È¤·¤Ê
- ¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¥Ç¥£¥ì¥¯¥È¥ê¤Ë¤Ï "mdb.dir" ¥Õ¥¡¥¤¥ë¤ò¤ª¤¯¤³¤È¤¬¤Ç
- ¤¤ë¡£¤½¤Î"mdb.dir"¥Õ¥¡¥¤¥ë¤Ë¤Ï¡¢ @ref mdbDir "mdbDir(5)" ¤ÇÀâÌÀ¤µ
- ¤ì¤Æ¤¤¤ë¥Õ¥©¡¼¥Þ¥Ã¥È¤Ç¥Ç¡¼¥¿ÄêµÁ¤Î¥ê¥¹¥È¤òµ½Ò¤¹¤ë¡£
+ ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤¬¡¢¤½¤Î¥×¥í¥°¥é¥à¸ÇͤΥǡ¼¥¿¤ä m17n
+ ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¾å½ñ¤¤¹¤ë¥Ç¡¼¥¿¤òÄ󶡤¹¤ë¾ì¹ç¤Ë¤Ï¡¢¥Þ¥¯¥í M17N_INIT ()
+ ¤ò¸Æ¤ÖÁ°¤Ë¤³¤ÎÊÑ¿ô¤ò¥Ç¡¼¥¿¥Õ¥¡¥¤¥ë¤ò´Þ¤à¥Ç¥£¥ì¥¯¥È¥ê̾¤Ë¥»¥Ã¥È¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¥Ç¥£¥ì¥¯¥È¥ê¤Ë¤Ï
+ "mdb.dir" ¥Õ¥¡¥¤¥ë¤ò¤ª¤¯¤³¤È¤¬¤Ç¤¤ë¡£¤½¤Î"mdb.dir"¥Õ¥¡¥¤¥ë¤Ë¤Ï¡¢
+ @ref mdbDir "mdbDir(5)" ¤ÇÀâÌÀ¤µ¤ì¤Æ¤¤¤ë¥Õ¥©¡¼¥Þ¥Ã¥È¤Ç¥Ç¡¼¥¿ÄêµÁ¤Î¥ê¥¹¥È¤òµ½Ò¤¹¤ë¡£
¥Ç¥Õ¥©¥ë¥È¤ÎÃÍ¤Ï NULL ¤Ç¤¢¤ë¡£ */
The mdatabase_find () function searches the m17n database for a
data who has tags $TAG0 through $TAG3, and returns a pointer to
- the data. If such a database is not found, it returns @c
- NULL. */
+ the data. If such a data is not found, it returns @c NULL. */
/***ja
- @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹¤òõ¤¹.
+ @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Î¥Ç¡¼¥¿¤òõ¤¹.
´Ø¿ô mdatabase_find () ¤Ï¡¢ m17n ¸À¸ì¾ðÊó¥Ù¡¼¥¹Ãæ¤Ç $TAG0 ¤«¤é
- $TAG3 ¤Þ¤Ç¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¥Ù¡¼¥¹¤òõ¤·¡¢¤½¤ì¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
- ¤½¤Î¤è¤¦¤Ê¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£
+ $TAG3 ¤Þ¤Ç¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¤òõ¤·¡¢¤½¤ì¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤Î¤è¤¦¤Ê¥Ç¡¼¥¿¤¬¤Ê¤±¤ì¤Ð
+ @c NULL ¤òÊÖ¤¹¡£
@latexonly \IPAlabel{mdatabase_find} @endlatexonly */
MDatabase *
mdatabase_find (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
{
- int i;
-
- for (i = 0; i < mdb_list.used; i++)
- {
- MDatabase *mdb = mdb_list.mdbs + i;
+ MSymbol tags[4];
- if (tag0 == mdb->tag[0]
- && tag1 == mdb->tag[1]
- && tag2 == mdb->tag[2]
- && tag3 == mdb->tag[3])
- return mdb;
- }
- return NULL;
+ mdatabase__update ();
+ tags[0] = tag0, tags[1] = tag1, tags[2] = tag2, tags[3] = tag3;
+ return find_database (tags);
}
/*=*/
/***ja
@brief m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥Ç¡¼¥¿¥ê¥¹¥È¤òÊÖ¤¹.
- ´Ø¿ô mdatabase_list () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤éÆÃÄê¤Î¥¿¥°$TAG0
- .. $TAG3 ¤ò»ý¤Ä¥Ç¡¼¥¿¤òõ¤·¡¢¤½¤Î¥ê¥¹¥È¤òplist ¤È¤·¤ÆÊÖ¤¹¡£ $TAGn
- ¤¬ #Mnil ¤Ç¤¢¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢Ç¤°Õ¤Î¥¿¥°¤Ë¥Þ¥Ã¥Á¤¹¤ë¥ï¥¤¥ë¥É¥«¡¼¥É¤È
- ¤·¤Æ¼è¤ê°·¤ï¤ì¤ë¡£ÊÖ¤µ¤ì¤ë plist ¤Î³ÆÍ×ÁǤϥ¡¼ ¤È¤·¤Æ #Mt ¤ò¡¢ÃÍ
- ¤È¤·¤Æ #MDatabase ·¿¤Ø¤Î¥Ý¥¤¥ó¥¿¤ò»ý¤Ä¡£ */
-
+ ´Ø¿ô mdatabase_list () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é $TAG0 ¤«¤é$TAG3
+ ¤Þ¤Ç¤Î¥¿¥°¤ò»ý¤Ä¥Ç¡¼¥¿¤òõ¤·¡¢¤½¤Î¥ê¥¹¥È¤òplist ¤È¤·¤ÆÊÖ¤¹¡£ $TAGn ¤¬ #Mnil
+ ¤Ç¤¢¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢Ç¤°Õ¤Î¥¿¥°¤Ë¥Þ¥Ã¥Á¤¹¤ë¥ï¥¤¥ë¥É¥«¡¼¥É¤È¤·¤Æ¼è¤ê°·¤ï¤ì¤ë¡£ÊÖ¤µ¤ì¤ë
+ plist ¤Î³ÆÍ×ÁǤϥ¡¼ ¤È¤·¤Æ #Mt ¤ò¡¢ÃͤȤ·¤Æ #MDatabase ·¿¤Ø¤Î¥Ý¥¤¥ó¥¿¤ò»ý¤Ä¡£ */
MPlist *
mdatabase_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
{
- int i;
- MPlist *plist = NULL, *pl;
+ MPlist *plist = mplist (), *pl = plist;
+ MPlist *p, *p0, *p1, *p2, *p3;
- for (i = 0; i < mdb_list.used; i++)
- {
- MDatabase *mdb = mdb_list.mdbs + i;
+ mdatabase__update ();
- if ((tag0 == Mnil || tag0 == mdb->tag[0])
- && (tag1 == Mnil || tag1 == mdb->tag[1])
- && (tag2 == Mnil || tag2 == mdb->tag[2])
- && (tag3 == Mnil || tag3 == mdb->tag[3]))
+ MPLIST_DO (p, mdatabase__list)
+ {
+ p0 = MPLIST_PLIST (p);
+ /* P0 ::= (TAG0 (TAG1 (TAG2 (TAG3 MDB) ...) ...) ...) */
+ if (tag0 != Mnil && MPLIST_SYMBOL (p0) != tag0)
+ continue;
+ MPLIST_DO (p0, MPLIST_NEXT (p0))
{
- if (! plist)
- plist = pl = mplist ();
- pl = mplist_add (pl, Mt, mdb);
+ p1 = MPLIST_PLIST (p0);
+ if (tag1 != Mnil && MPLIST_SYMBOL (p1) != tag1)
+ continue;
+ MPLIST_DO (p1, MPLIST_NEXT (p1))
+ {
+ p2 = MPLIST_PLIST (p1);
+ if (tag2 != Mnil && MPLIST_SYMBOL (p2) != tag2)
+ continue;
+ MPLIST_DO (p2, MPLIST_NEXT (p2))
+ {
+ p3 = MPLIST_PLIST (p2);
+ if (tag3 != Mnil && MPLIST_SYMBOL (p3) != tag3)
+ continue;
+ p3 = MPLIST_NEXT (p3);
+ pl = mplist_add (pl, Mt, MPLIST_VAL (p3));
+ }
+ }
}
}
+ if (MPLIST_TAIL_P (plist))
+ {
+ M17N_OBJECT_UNREF (plist);
+ plist = NULL;
+ }
return plist;
}
-
-
/*=*/
/***en
@brief Define a data of the m17n database.
/***ja
@brief m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥Ç¡¼¥¿¤òÄêµÁ¤¹¤ë.
- ´Ø¿ô mdatabase_define () ¤Ï $TAG0 ¤«¤é $TAG3 ¤Þ¤Ç¤Î¥¿¥°¤ª¤è¤ÓÉÕ²Ã
- ¾ðÊó $EXTRA_INFO ¤ò»ý¤Ä¥Ç¡¼¥¿¤òÄêµÁ¤¹¤ë¡£
+ ´Ø¿ô mdatabase_define () ¤Ï $TAG0 ¤«¤é $TAG3 ¤Þ¤Ç¤Î¥¿¥°¤ª¤è¤ÓÉղþðÊó
+ $EXTRA_INFO ¤ò»ý¤Ä¥Ç¡¼¥¿¤òÄêµÁ¤¹¤ë¡£
- $LOADER ¤Ï¤½¤Î¥Ç¡¼¥¿¤Î¥í¡¼¥É¤ËÍѤ¤¤é¤ì¤ë´Ø¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¤³
- ¤Î´Ø¿ô¤Ï mdatabase_load () ¤«¤é $TAGS ¤È $EXTRA_INFO ¤È¤¤¤¦2 ¤Ä¤Î
- °ú¿ôÉÕ¤¤Ç¸Æ¤Ó½Ð¤µ¤ì¤ë¡£¤³¤³¤Ç $TAGS ¤Ï $TAG0 ¤«¤é $TAG3 ¤Þ¤Ç¤ÎÇÛ
- Îó¤Ç¤¢¤ë¡£
+ $LOADER ¤Ï¤½¤Î¥Ç¡¼¥¿¤Î¥í¡¼¥É¤ËÍѤ¤¤é¤ì¤ë´Ø¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¤³¤Î´Ø¿ô¤Ï
+ mdatabase_load () ¤«¤é $TAGS ¤È $EXTRA_INFO ¤È¤¤¤¦Æó¤Ä¤Î°ú¿ôÉÕ¤¤Ç¸Æ¤Ó½Ð¤µ¤ì¤ë¡£¤³¤³¤Ç
+ $TAGS ¤Ï $TAG0 ¤«¤é $TAG3 ¤Þ¤Ç¤ÎÇÛÎó¤Ç¤¢¤ë¡£
- ¤â¤· $LOADER ¤¬ @c NULL ¤Ê¤é¡¢m17n ¥é¥¤¥Ö¥é¥êɸ½à¤Î¥í¡¼¥À¤¬»È¤ï¤ì
- ¤ë¡£¤³¤Î¾ì¹ç¤Ë¤Ï $EXTRA_INFO ¤Ï¥Ç¡¼¥¿¤ò´Þ¤à¥Õ¥¡¥¤¥ë̾¤Ç¤Ê¤¯¤Æ¤Ï¤Ê
- ¤é¤Ê¤¤¡£
+ ¤â¤· $LOADER ¤¬ @c NULL ¤Ê¤é¡¢m17n ¥é¥¤¥Ö¥é¥êɸ½à¤Î¥í¡¼¥À¤¬»È¤ï¤ì¤ë¡£¤³¤Î¾ì¹ç¤Ë¤Ï
+ $EXTRA_INFO ¤Ï¥Ç¡¼¥¿¤ò´Þ¤à¥Õ¥¡¥¤¥ë̾¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
- @return ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mdatabase_define () ¤ÏÄêµÁ¤µ¤ì¤¿¥Ç¡¼¥¿¥Ù¡¼
- ¥¹¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤³¤Î¥Ý¥¤¥ó¥¿¤Ï´Ø¿ô mdatabase_load () ¤Î°ú¿ô
- ¤È¤·¤ÆÍѤ¤¤ë¤³¤È¤¬¤Ç¤¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£
+ @return
+ ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mdatabase_define ()
+ ¤ÏÄêµÁ¤µ¤ì¤¿¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤³¤Î¥Ý¥¤¥ó¥¿¤Ï´Ø¿ô mdatabase_load ()
+ ¤Î°ú¿ô¤È¤·¤ÆÍѤ¤¤ë¤³¤È¤¬¤Ç¤¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£
@latexonly \IPAlabel{mdatabase_define} @endlatexonly */
void *extra_info)
{
MDatabase *mdb;
+ MSymbol tags[4];
- mdb = mdatabase_find (tag0, tag1, tag2, tag3);
- if (! mdb)
- {
- MDatabase template;
-
- template.tag[0] = tag0, template.tag[1] = tag1;
- template.tag[2] = tag2, template.tag[3] = tag3;
- MLIST_APPEND1 (&mdb_list, mdbs, template, MERROR_DB);
- mdb = mdb_list.mdbs + (mdb_list.used - 1);
- }
- mdb->loader = loader ? loader : load_database;
- mdb->extra_info = extra_info;
- if (mdb->loader == load_database)
- mdb->extra_info = strdup ((char *) extra_info);
- return (&(mdb_list.mdbs[mdb_list.used - 1]));
+ tags[0] = tag0, tags[1] = tag1, tags[2] = tag2, tags[3] = tag3;
+ if (! loader)
+ loader = load_database;
+ mdb = register_database (tags, loader, extra_info, MDB_STATUS_EXPLICIT);
+ return mdb;
}
/*=*/
returns the contents. The type of contents depends on the type of
the data.
- If the data is of the @e plist type, this function returns a
+ If the data is of the @e plist @e type, this function returns a
pointer to @e plist.
- If the database is of the @e chartable type, it returns a
+ If the database is of the @e chartable @e type, it returns a
chartable. The default value of the chartable is set according to
the second tag of the data as below:
@li If the tag is #Minteger, the default value is -1.
@li Otherwise, the default value is @c NULL.
- If the data is of the @e charset type, it returns a plist of length 2
+ If the data is of the @e charset @e type, it returns a plist of length 2
(keys are both #Mt). The value of the first element is an array
of integers that maps code points to the corresponding character
codes. The value of the second element is a chartable of integers
/***ja
@brief ¥Ç¡¼¥¿¥Ù¡¼¥¹¤«¤é¥Ç¡¼¥¿¤ò¥í¡¼¥É¤¹¤ë.
- ´Ø¿ô mdatabase_load () ¤Ï $MDB ¤¬»Ø¤¹¥Ç¡¼¥¿¤ò¥í¡¼¥É¤·¡¢¤½¤Î
- Ãæ¿È¤òÊÖ¤¹¡£ÊÖ¤µ¤ì¤ë¤â¤Î¤Ï¥Ç¡¼¥¿¤Î¥¿¥¤¥×¤Ë¤è¤Ã¤Æ°Û¤Ê¤ë¡£
+ ´Ø¿ô mdatabase_load () ¤Ï $MDB
+ ¤¬»Ø¤¹¥Ç¡¼¥¿¤ò¥í¡¼¥É¤·¡¢¤½¤ÎÃæ¿È¤òÊÖ¤¹¡£ÊÖ¤µ¤ì¤ë¤â¤Î¤Ï¥Ç¡¼¥¿¤Î¥¿¥¤¥×¤Ë¤è¤Ã¤Æ°Û¤Ê¤ë¡£
- ¥Ç¡¼¥¿¤¬ @e plist ¥¿¥¤¥×¤Ê¤é¤Ð¡¢ @e plist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
+ ¥Ç¡¼¥¿¤¬ @e plist¥¿¥¤¥× ¤Ê¤é¤Ð¡¢ @e plist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
- ¥Ç¡¼¥¿¤¬ @e chartable ¥¿¥¤¥×¤Ê¤é¤Ðʸ»ú¥Æ¡¼¥Ö¥ë¤òÊÖ¤¹¡£Ê¸»ú¥Æ¡¼¥Ö¥ë
- ¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤϡ¢¥Ç¡¼¥¿¤ÎÂè2¥¿¥°¤Ë¤è¤Ã¤Æ°Ê²¼¤Î¤è¤¦¤Ë·è¤Þ¤ë¡£
+ ¥Ç¡¼¥¿¤¬ @e chartable¥¿¥¤¥× ¤Ê¤é¤Ðʸ»ú¥Æ¡¼¥Ö¥ë¤òÊÖ¤¹¡£
+ ʸ»ú¥Æ¡¼¥Ö¥ë¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤϡ¢¥Ç¡¼¥¿¤ÎÂè2¥¿¥°¤Ë¤è¤Ã¤Æ°Ê²¼¤Î¤è¤¦¤Ë·è¤Þ¤ë¡£
@li ¥¿¥°¤¬ #Msymbol ¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï #Mnil
@li ¥¿¥°¤¬ #Minteger ¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï -1
@li ¤½¤ì°Ê³°¤Ê¤é¡¢¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï @c NULL
- ¥Ç¡¼¥¿¤¬ @e charset ¥¿¥¤¥×¤Ê¤é¤ÐŤµ 2 ¤Î plist ¤òÊÖ¤¹¡Ê¥¡¼¤Ï¶¦¤Ë
- #Mt ¡Ë¡£ºÇ½é¤ÎÍ×ÁǤÎÃͤϥ³¡¼¥É¥Ý¥¤¥ó¥È¤òÂбþ¤¹¤ëʸ»ú¥³¡¼¥É¤Ë¥Þ¥Ã¥×
- ¤¹¤ëÀ°¿ô¤ÎÇÛÎó¤Ç¤¢¤ë¡££²ÈÖÌܤÎÍ×ÁǤÎÃͤϵդΥޥåפò¤¹¤ëʸ»ú¥Æ¡¼¥Ö
- ¥ë¤Ç¤¢¤ë¡£¤³¤Îʸ»ú¥»¥Ã¥È¤Ïͽ¤áÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
+ ¥Ç¡¼¥¿¤¬ @e charset¥¿¥¤¥× ¤Ê¤é¤ÐŤµ 2 ¤Î plist ¤òÊÖ¤¹¡Ê¥¡¼¤Ï¶¦¤Ë#Mt ¡Ë¡£
+ ºÇ½é¤ÎÍ×ÁǤÎÃͤϥ³¡¼¥É¥Ý¥¤¥ó¥È¤òÂбþ¤¹¤ëʸ»ú¥³¡¼¥É¤Ë¥Þ¥Ã¥×¤¹¤ëÀ°¿ô¤ÎÇÛÎó¤Ç¤¢¤ë¡£
+ £²ÈÖÌܤÎÍ×ÁǤÎÃͤϵդΥޥåפò¤¹¤ëʸ»ú¥Æ¡¼¥Ö¥ë¤Ç¤¢¤ë¡£
+ ¤³¤Îʸ»ú¥»¥Ã¥È¤Ïͽ¤áÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
@latexonly \IPAlabel{mdatabase_load} @endlatexonly
*/
void *
mdatabase_load (MDatabase *mdb)
{
- int mdebug_mask = MDEBUG_DATABASE;
- char buf[256];
-
- MDEBUG_PRINT1 (" [DATABASE] loading <%s>.\n",
- gen_database_name (buf, mdb->tag));
return (*mdb->loader) (mdb->tag, mdb->extra_info);
}
that identify the data in $MDB. The length of the array is
four. */
-/***oldja
+/***ja
@brief ¥Ç¡¼¥¿¤Î¥¿¥°¤òÆÀ¤ë.
- ´Ø¿ô mdatabase_tag () ¤Ï¡¢¥Ç¡¼¥¿ $MDB ¤Î¥¿¥°¡Ê¥·¥ó¥Ü¥ë¡Ë¤ÎÇÛÎó¤òÊÖ
- ¤¹¡£ÇÛÎó¤ÎŤµ¤Ï 4 ¤Ç¤¢¤ë¡£
+ ´Ø¿ô mdatabase_tag () ¤Ï¡¢¥Ç¡¼¥¿ $MDB ¤Î¥¿¥°¡Ê¥·¥ó¥Ü¥ë¡Ë¤ÎÇÛÎó¤òÊÖ¤¹¡£ÇÛÎó¤ÎŤµ¤Ï
+ 4 ¤Ç¤¢¤ë¡£
@latexonly \IPAlabel{mdatabase_tag} @endlatexonly */