/* database.c -- database module.
- Copyright (C) 2003, 2004
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H15PRO112
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
#include <limits.h>
#include <glob.h>
#include <time.h>
+#include <libgen.h>
-#include "m17n.h"
+#include "m17n-core.h"
#include "m17n-misc.h"
#include "internal.h"
#include "mtext.h"
#include "character.h"
-#include "charset.h"
#include "database.h"
-#include "coding.h"
#include "plist.h"
/** The file containing a list of databases. */
path[dir_len + file_len] = '\0', 1))
static MSymbol Masterisk;
+static MSymbol Mversion;
/** Structure for a data in the m17n database. */
/* VAL is an M-text. */
MText *mt;
if (c == '"')
- mt = mconv_decode_buffer (Mcoding_utf_8,
- (unsigned char *) (buf + i),
- len - i - 1);
+ mt = mtext__from_data (buf + i, len - i - 1, MTEXT_FORMAT_UTF_8, 1);
else
{
mt = mtext ();
}
-/** Load a data of type @c charset from the file FD. */
-
-static void *
-load_charset (FILE *fp, MSymbol charset_name)
-{
- MCharset *charset = MCHARSET (charset_name);
- int *decoder;
- MCharTable *encoder;
- int size;
- int i, c;
- int found = 0;
- MPlist *plist;
-
- if (! charset)
- MERROR (MERROR_DB, NULL);
- size = (charset->code_range[15]
- - (charset->min_code - charset->code_range_min_code));
- MTABLE_MALLOC (decoder, size, MERROR_DB);
- for (i = 0; i < size; i++)
- decoder[i] = -1;
- encoder = mchartable (Minteger, (void *) MCHAR_INVALID_CODE);
-
- while ((c = getc (fp)) != EOF)
- {
- unsigned code1, code2, c1, c2;
- int idx1, idx2;
- char buf[256];
-
- ungetc (c, fp);
- fgets (buf, 256, fp);
- if (c != '#')
- {
- if (sscanf (buf, "0x%x-0x%x 0x%x", &code1, &code2, &c1) == 3)
- {
- idx1 = CODE_POINT_TO_INDEX (charset, code1);
- if (idx1 >= size)
- continue;
- idx2 = CODE_POINT_TO_INDEX (charset, code2);
- if (idx2 >= size)
- idx2 = size - 1;
- c2 = c1 + (idx2 - idx1);
- }
- else if (sscanf (buf, "0x%x 0x%x", &code1, &c1) == 2)
- {
- idx1 = idx2 = CODE_POINT_TO_INDEX (charset, code1);
- if (idx1 >= size)
- continue;
- c2 = c1;
- }
- else
- continue;
- if (idx1 >= 0 && idx2 >= 0)
- {
- decoder[idx1] = c1;
- mchartable_set (encoder, c1, (void *) code1);
- for (idx1++, c1++; idx1 <= idx2; idx1++, c1++)
- {
- code1 = INDEX_TO_CODE_POINT (charset, idx1);
- decoder[idx1] = c1;
- mchartable_set (encoder, c1, (void *) code1);
- }
- found++;
- }
- }
- }
-
- if (! found)
- {
- free (decoder);
- M17N_OBJECT_UNREF (encoder);
- return NULL;
- }
- plist = mplist ();
- mplist_add (plist, Mt, decoder);
- mplist_add (plist, Mt, encoder);
- return plist;
-}
-
static char *
gen_database_name (char *buf, MSymbol *tags)
{
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. */
+/* Return the absolute file name for DB_INFO->filename or NULL if no
+ absolute file name was found. If BUF is non-NULL, store the result
+ of `stat' call in it. In that case, set *RESULT to the return
+ value of `stat'. */
char *
-get_database_file (MDatabaseInfo *db_info, struct stat *buf)
+get_database_file (MDatabaseInfo *db_info, struct stat *buf, int *result)
{
- if (db_info->status == MDB_STATUS_DISABLED)
- return NULL;
if (db_info->absolute_filename)
{
if (buf)
- stat (db_info->absolute_filename, buf);
+ *result = stat (db_info->absolute_filename, buf);
}
else
{
struct stat stat_buf;
struct stat *statbuf = buf ? buf : &stat_buf;
+ int res;
+ MPlist *plist;
+ char path[PATH_MAX + 1];
+
+ MPLIST_DO (plist, mdatabase__dir_list)
+ {
+ MDatabaseInfo *dir_info = MPLIST_VAL (plist);
- db_info->absolute_filename = find_file (db_info, statbuf);
+ if (dir_info->status != MDB_STATUS_DISABLED
+ && GEN_PATH (path, dir_info->filename, dir_info->len,
+ db_info->filename, db_info->len)
+ && (res = stat (path, statbuf)) == 0)
+ {
+ db_info->absolute_filename = strdup (path);
+ if (result)
+ *result = res;
+ break;
+ }
+ }
}
return db_info->absolute_filename;
{
MDatabaseInfo *db_info = extra_info;
void *value;
- char *filename = get_database_file (db_info, NULL);
+ char *filename = get_database_file (db_info, NULL, NULL);
FILE *fp;
+ int mdebug_flag = MDEBUG_DATABASE;
+ char buf[256];
+ MDEBUG_PRINT1 (" [DB] <%s>", gen_database_name (buf, tags));
if (! filename || ! (fp = fopen (filename, "r")))
- MERROR (MERROR_DB, NULL);
+ {
+ if (filename)
+ MDEBUG_PRINT1 (" open fail: %s\n", filename);
+ else
+ MDEBUG_PRINT1 (" not found: %s\n", db_info->filename);
+ 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]);
+ {
+ if (! mdatabase__load_charset_func)
+ MERROR (MERROR_DB, NULL);
+ value = (*mdatabase__load_charset_func) (fp, tags[1]);
+ }
else
value = mplist__from_file (fp, NULL);
fclose (fp);
if (dirname)
{
int len = strlen (dirname);
- 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)
+
+ if (len + MDB_DIR_LEN < PATH_MAX)
{
- dir_info->filename[len] = PATH_SEPARATOR;
- dir_info->filename[++len] = '\0';
+ 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;
}
- dir_info->len = len;
- dir_info->status = MDB_STATUS_AUTO;
+ else
+ dir_info->status = MDB_STATUS_DISABLED;
}
else
dir_info->status = MDB_STATUS_DISABLED;
return dir_info;
}
+static void register_databases_in_files (MSymbol tags[4],
+ char *filename, int len);
+
static MDatabase *
find_database (MSymbol tags[4])
{
MPlist *plist;
int i;
+ MDatabase *mdb;
if (! mdatabase__list)
return NULL;
for (i = 0, plist = mdatabase__list; i < 4; i++)
{
- plist = mplist__assq (plist, tags[i]);
- if (! plist)
+ MPlist *pl = mplist__assq (plist, tags[i]);
+ MPlist *p;
+
+ if ((p = mplist__assq (plist, Masterisk)))
+ {
+ MDatabaseInfo *db_info;
+ int j;
+
+ p = MPLIST_PLIST (p);
+ for (j = i + 1; j < 4; j++)
+ p = MPLIST_PLIST (MPLIST_NEXT (p));
+ mdb = MPLIST_VAL (MPLIST_NEXT (p));
+ db_info = mdb->extra_info;
+ if (db_info->status != MDB_STATUS_DISABLED)
+ {
+ register_databases_in_files (mdb->tag,
+ db_info->filename, db_info->len);
+ db_info->status = MDB_STATUS_DISABLED;
+ return find_database (tags);
+ }
+ }
+ if (! pl)
return NULL;
- plist = MPLIST_PLIST (plist);
+ plist = MPLIST_PLIST (pl);
plist = MPLIST_NEXT (plist);
}
- return MPLIST_VAL (plist);
+ mdb = MPLIST_VAL (plist);
+ return mdb;
}
static void
if (db_info->absolute_filename
&& db_info->filename != db_info->absolute_filename)
free (db_info->absolute_filename);
+ M17N_OBJECT_UNREF (db_info->properties);
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;
+
+ ver[0] = ver[1] = ver[2] = 0;
+ for (i = 0; verstr < endp; verstr++)
+ {
+ if (*verstr == '.')
+ {
+ i++;
+ if (i == 3)
+ break;
+ continue;
+ }
+ if (! isdigit (*verstr))
+ break;
+ ver[i] = ver[i] * 10 + (*verstr - '0');
+ }
+ 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)
+register_database (MSymbol tags[4],
+ void *(*loader) (MSymbol *, void *),
+ void *extra_info, enum MDatabaseStatus status,
+ MPlist *properties)
{
- MDatabase *mdb = find_database (tags);
- MDatabaseInfo *db_info = NULL;
+ MDatabase *mdb;
+ MDatabaseInfo *db_info;
+ int i;
+ MPlist *plist;
- if (mdb)
+ if (properties)
{
- if (loader == load_database)
- db_info = mdb->extra_info;
+ MPLIST_DO (plist, properties)
+ if (MPLIST_PLIST_P (plist))
+ {
+ MPlist *p = MPLIST_PLIST (plist);
+
+ if (MPLIST_SYMBOL_P (p)
+ && MPLIST_SYMBOL (p) == Mversion
+ && MPLIST_MTEXT_P (MPLIST_NEXT (p)))
+ {
+ if (check_version (MPLIST_MTEXT (MPLIST_NEXT (p))))
+ break;
+ return NULL;
+ }
+ }
}
- else
+
+ for (i = 0, plist = mdatabase__list; i < 4; i++)
{
- int i;
- MPlist *plist;
+ 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->extra_info = db_info;
}
else
- mdb->extra_info = extra_info;
- 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);
+ 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->absolute_filename = db_info->filename;
else
db_info->absolute_filename = NULL;
+ M17N_OBJECT_UNREF (db_info->properties);
+ if (properties)
+ {
+ db_info->properties = properties;
+ M17N_OBJECT_REF (properties);
+ }
}
if (mdb->tag[0] == Mchar_table
}
static void
-register_databases_in_files (MSymbol tags[4], glob_t *globbuf)
+register_databases_in_files (MSymbol tags[4], char *filename, int len)
{
int i, j;
MPlist *load_key = mplist ();
FILE *fp;
- MPlist *plist;
+ MPlist *plist, *pl;
- for (i = 0; i < globbuf->gl_pathc; i++)
+ MPLIST_DO (plist, mdatabase__dir_list)
{
- 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))
+ glob_t globbuf;
+ int headlen;
+
+ if (filename[0] == PATH_SEPARATOR)
{
- 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)
- register_database (tags2, load_database, globbuf->gl_pathv[i], 1);
+ if (glob (filename, GLOB_NOSORT, NULL, &globbuf))
+ break;
+ headlen = 0;
}
- M17N_OBJECT_UNREF (plist);
+ else
+ {
+ MDatabaseInfo *d_info = MPLIST_VAL (plist);
+ char path[PATH_MAX + 1];
+
+ if (d_info->status == MDB_STATUS_DISABLED)
+ continue;
+ if (! GEN_PATH (path, d_info->filename, d_info->len, filename, len))
+ continue;
+ if (glob (path, GLOB_NOSORT, NULL, &globbuf))
+ continue;
+ headlen = d_info->len;
+ }
+
+ for (i = 0; i < globbuf.gl_pathc; i++)
+ {
+ if (! (fp = fopen (globbuf.gl_pathv[i], "r")))
+ continue;
+ pl = mplist__from_file (fp, load_key);
+ fclose (fp);
+ if (! pl)
+ continue;
+ if (MPLIST_PLIST_P (pl))
+ {
+ MPlist *p;
+ MSymbol tags2[4];
+
+ for (j = 0, p = MPLIST_PLIST (pl); j < 4 && MPLIST_SYMBOL_P (p);
+ j++, p = MPLIST_NEXT (p))
+ tags2[j] = MPLIST_SYMBOL (p);
+ for (; j < 4; j++)
+ tags2[j] = Mnil;
+ for (j = 0; j < 4; j++)
+ if (tags[j] != Masterisk && tags[j] != tags2[j])
+ break;
+ if (j == 4)
+ register_database (tags2, load_database,
+ globbuf.gl_pathv[i] + headlen,
+ MDB_STATUS_AUTO, p);
+ }
+ M17N_OBJECT_UNREF (pl);
+ }
+ globfree (&globbuf);
+ if (filename[0] == PATH_SEPARATOR)
+ break;
}
M17N_OBJECT_UNREF (load_key);
}
+static int
+expand_wildcard_database (MPlist *plist)
+{
+ MDatabase *mdb;
+ MDatabaseInfo *db_info;
+
+ plist = MPLIST_NEXT (plist);
+ while (MPLIST_PLIST_P (plist))
+ {
+ plist = MPLIST_PLIST (plist);
+ plist = MPLIST_NEXT (plist);
+ }
+ mdb = MPLIST_VAL (plist);
+ if (mdb->loader == load_database
+ && (db_info = mdb->extra_info)
+ && db_info->status != MDB_STATUS_DISABLED)
+ {
+ register_databases_in_files (mdb->tag, db_info->filename, db_info->len);
+ db_info->status = MDB_STATUS_DISABLED;
+ return 1;
+ }
+ return 0;
+}
+
\f
/* Internal API */
/** List of database directories. */
MPlist *mdatabase__dir_list;
+void *(*mdatabase__load_charset_func) (FILE *fp, MSymbol charset_name);
+
int
mdatabase__init ()
{
MDatabaseInfo *dir_info;
char *path;
+ mdatabase__load_charset_func = NULL;
+
Mchar_table = msymbol ("char-table");
+ Mcharset = msymbol ("charset");
Masterisk = msymbol ("*");
+ Mversion = msymbol ("version");
mdatabase__dir_list = mplist ();
/** The macro M17NDIR specifies a directory where the system-wide
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;
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". */
p2 = MPLIST_PLIST (p1);
MPLIST_DO (p2, MPLIST_NEXT (p2))
{
+ MDatabase *mdb;
MDatabaseInfo *db_info;
p3 = MPLIST_PLIST (p2);
p3 = MPLIST_NEXT (p3);
- db_info = MPLIST_VAL (p3);
+ mdb = MPLIST_VAL (p3);
+ db_info = mdb->extra_info;
if (db_info->status == MDB_STATUS_AUTO)
db_info->status = MDB_STATUS_DISABLED;
}
}
}
- /* Update elements of mdatabase__dir_list. */
- MPLIST_DO (plist, mdatabase__dir_list)
- {
- dir_info = MPLIST_VAL (plist);
- dir_info->status = ((dir_info->filename
- && stat (dir_info->filename, &statbuf) == 0
- && (statbuf.st_mode & S_IFDIR))
- ? MDB_STATUS_AUTO : MDB_STATUS_DISABLED);
- }
+ plist = mplist ();
+ MPLIST_DO (p0, mdatabase__dir_list)
+ mplist_push (plist, MPLIST_KEY (p0), MPLIST_VAL (p0));
- MPLIST_DO (plist, mdatabase__dir_list)
+ while (! MPLIST_TAIL_P (plist))
{
- MDatabaseInfo *dir_info = MPLIST_VAL (plist);
+ MDatabaseInfo *dir_info = mplist_pop (plist);
MPlist *pl, *p;
int i;
FILE *fp;
if (! GEN_PATH (path, dir_info->filename, dir_info->len,
MDB_DIR, MDB_DIR_LEN))
continue;
- if (stat (path, &statbuf) < 0)
- continue;
- if (dir_info->time >= statbuf.st_mtime)
- continue;
- dir_info->time = statbuf.st_mtime;
if (! (fp = fopen (path, "r")))
continue;
pl = mplist__from_file (fp, NULL);
|| ! MPLIST_MTEXT_P (p1))
continue;
for (; i < 4; i++)
- tags[i] = Mnil;
+ tags[i] = with_wildcard ? Masterisk : Mnil;
mt = MPLIST_MTEXT (p1);
- if (mt->format >= MTEXT_FORMAT_UTF_16LE)
- mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
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;
-
- 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);
- 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);
- globfree (&globbuf);
- }
- }
+ register_database (tags, load_database, path,
+ MDB_STATUS_AUTO_WILDCARD, NULL);
else
- {
- register_database (tags, load_database, path, 1);
- }
+ register_database (tags, load_database, path,
+ MDB_STATUS_AUTO, p1);
}
M17N_OBJECT_UNREF (pl);
}
+ M17N_OBJECT_UNREF (plist);
}
MPlist *
mdatabase__load_for_keys (MDatabase *mdb, MPlist *keys)
{
- int mdebug_mask = MDEBUG_DATABASE;
+ int mdebug_flag = MDEBUG_DATABASE;
MDatabaseInfo *db_info;
char *filename;
FILE *fp;
|| mdb->tag[0] == Mchar_table
|| mdb->tag[0] == Mcharset)
MERROR (MERROR_DB, NULL);
- MDEBUG_PRINT1 (" [DATABASE] loading <%s>.\n",
+ MDEBUG_PRINT1 (" [DB] <%s>.\n",
gen_database_name (name, mdb->tag));
db_info = mdb->extra_info;
- filename = get_database_file (db_info, NULL);
+ filename = get_database_file (db_info, NULL, NULL);
if (! filename || ! (fp = fopen (filename, "r")))
MERROR (MERROR_DB, NULL);
plist = mplist__from_file (fp, keys);
{
MDatabaseInfo *db_info = (MDatabaseInfo *) mdb->extra_info;
struct stat buf;
+ int result;
+
+ if (db_info->absolute_filename != db_info->filename
+ || db_info->status == MDB_STATUS_AUTO)
+ mdatabase__update ();
- if (! get_database_file (db_info, &buf))
+ if (! get_database_file (db_info, &buf, &result)
+ || result < 0)
return -1;
if (db_info->time < buf.st_mtime)
return 0;
mdatabase__find_file (char *filename)
{
struct stat buf;
+ int result;
MDatabaseInfo db_info;
if (filename[0] == PATH_SEPARATOR)
- return (stat (filename, &buf) == 0 ? filename : NULL);
+ return (stat (filename, &buf) == 0 ? strdup (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)
+ if (! get_database_file (&db_info, &buf, &result)
+ || result < 0)
return NULL;
return db_info.absolute_filename;
}
if (mdb->loader != load_database)
return NULL;
db_info = mdb->extra_info;
- return get_database_file (db_info, NULL);
+ return get_database_file (db_info, NULL, NULL);
}
int
db_info = mdb->extra_info;
if (db_info->lock_file)
return -1;
- file = get_database_file (db_info, NULL);
+ file = get_database_file (db_info, NULL, NULL);
if (! file)
return -1;
len = strlen (file);
fp = fopen (db_info->uniq_file, "w");
if (! fp)
{
- free (db_info->uniq_file);
- free (db_info->lock_file);
- db_info->lock_file = NULL;
- return -1;
+ 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
db_info = mdb->extra_info;
if (! db_info->lock_file)
return -1;
- file = get_database_file (db_info, NULL);
+ file = get_database_file (db_info, NULL, NULL);
if (! file)
return -1;
mt = mtext ();
M17N_OBJECT_UNREF (mt);
return -1;
}
- mconv_encode_stream (msymbol ("utf-8"), mt, fp);
- M17N_OBJECT_UNREF (mt);
+ if (mt->format > MTEXT_FORMAT_UTF_8)
+ mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
+ fwrite (MTEXT_DATA (mt), 1, mtext_nchars (mt), fp);
fclose (fp);
+ M17N_OBJECT_UNREF (mt);
if ((ret = rename (db_info->uniq_file, file)) < 0)
unlink (db_info->uniq_file);
free (db_info->uniq_file);
free (db_info->lock_file);
db_info->lock_file = NULL;
if (db_info->uniq_file)
- free (db_info->uniq_file);
+ {
+ unlink (db_info->uniq_file);
+ free (db_info->uniq_file);
+ }
return 0;
}
+MPlist *
+mdatabase__props (MDatabase *mdb)
+{
+ MDatabaseInfo *db_info;
+
+ if (mdb->loader != load_database)
+ return NULL;
+ db_info = mdb->extra_info;
+ return db_info->properties;
+}
+
/*** @} */
#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
\f
/* External API */
+/*** @addtogroup m17nCharset */
+/*** @{ */
+/*=*/
+/***en
+ @brief The symbol @c Mcharset.
+
+ Any decoded M-text has a text property whose key is the predefined
+ symbol @c Mcharset. The name of @c Mcharset is
+ <tt>"charset"</tt>. */
+
+/***ja
+ @brief ¥·¥ó¥Ü¥ë @c Mcharset.
+
+ ¥Ç¥³¡¼¥É¤µ¤ì¤¿ M-text ¤Ï¡¢¥¡¼¤¬ @c Mcharset
+ ¤Ç¤¢¤ë¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¡£
+ ¥·¥ó¥Ü¥ë @c Mcharset ¤Ï <tt>"charset"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¡£ */
+
+MSymbol Mcharset;
+/*=*/
+/*** @} */
+/*=*/
+
/*** @addtogroup m17nDatabase */
/*** @{ */
{
p0 = MPLIST_PLIST (p);
/* P0 ::= (TAG0 (TAG1 (TAG2 (TAG3 MDB) ...) ...) ...) */
- if (tag0 != Mnil && MPLIST_SYMBOL (p0) != tag0)
+ if (MPLIST_SYMBOL (p0) == Masterisk
+ || (tag0 != Mnil && MPLIST_SYMBOL (p0) != tag0))
continue;
MPLIST_DO (p0, MPLIST_NEXT (p0))
{
p1 = MPLIST_PLIST (p0);
+ if (MPLIST_SYMBOL (p1) == Masterisk)
+ {
+ if (expand_wildcard_database (p1))
+ {
+ M17N_OBJECT_UNREF (plist);
+ return mdatabase_list (tag0, tag1, tag2, tag3);
+ }
+ continue;
+ }
if (tag1 != Mnil && MPLIST_SYMBOL (p1) != tag1)
continue;
MPLIST_DO (p1, MPLIST_NEXT (p1))
{
p2 = MPLIST_PLIST (p1);
+ if (MPLIST_SYMBOL (p2) == Masterisk)
+ {
+ if (expand_wildcard_database (p2))
+ {
+ M17N_OBJECT_UNREF (plist);
+ return mdatabase_list (tag0, tag1, tag2, tag3);
+ }
+ continue;
+ }
if (tag2 != Mnil && MPLIST_SYMBOL (p2) != tag2)
continue;
MPLIST_DO (p2, MPLIST_NEXT (p2))
{
p3 = MPLIST_PLIST (p2);
+ if (MPLIST_SYMBOL (p3) == Masterisk)
+ {
+ if (expand_wildcard_database (p3))
+ {
+ M17N_OBJECT_UNREF (plist);
+ return mdatabase_list (tag0, tag1, tag2, tag3);
+ }
+ continue;
+ }
if (tag3 != Mnil && MPLIST_SYMBOL (p3) != tag3)
continue;
p3 = MPLIST_NEXT (p3);
}
}
if (MPLIST_TAIL_P (plist))
- {
- M17N_OBJECT_UNREF (plist);
- plist = NULL;
- }
+ M17N_OBJECT_UNREF (plist);
return plist;
}
tags[0] = tag0, tags[1] = tag1, tags[2] = tag2, tags[3] = tag3;
if (! loader)
loader = load_database;
- mdb = register_database (tags, loader, extra_info, 0);
+ mdb = register_database (tags, loader, extra_info, MDB_STATUS_EXPLICIT, NULL);
return mdb;
}
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);
}