X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fdatabase.c;h=ca33ec418e9ec647a0d0577ab3f3a4f208573dd6;hb=4c04d78211538ceef48f25fe8ca5402160e6e2d2;hp=0f7891c16fd35b4fa1747e77956ac15ddbfcc75a;hpb=9d702d41b71552b4673e2ac6197373822409c70c;p=m17n%2Fm17n-lib.git diff --git a/src/database.c b/src/database.c index 0f7891c..ca33ec4 100644 --- a/src/database.c +++ b/src/database.c @@ -1,5 +1,5 @@ /* database.c -- database module. - Copyright (C) 2003, 2004 + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H15PRO112 @@ -136,14 +136,12 @@ #include #include -#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. */ @@ -160,6 +158,7 @@ path[dir_len + file_len] = '\0', 1)) static MSymbol Masterisk; +static MSymbol Mversion; /** Structure for a data in the m17n database. */ @@ -297,9 +296,7 @@ load_chartable (FILE *fp, MSymbol type) /* 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 (); @@ -348,84 +345,6 @@ load_chartable (FILE *fp, MSymbol type) } -/** 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) { @@ -440,46 +359,42 @@ gen_database_name (char *buf, MSymbol *tags) 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]; - db_info->absolute_filename = find_file (db_info, statbuf); + 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) + && (res = stat (path, statbuf)) == 0) + { + db_info->absolute_filename = strdup (path); + if (result) + *result = res; + break; + } + } } return db_info->absolute_filename; @@ -490,9 +405,9 @@ load_database (MSymbol *tags, void *extra_info) { 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_mask = MDEBUG_DATABASE; + int mdebug_flag = MDEBUG_DATABASE; char buf[256]; MDEBUG_PRINT1 (" [DB] <%s>", gen_database_name (buf, tags)); @@ -510,7 +425,11 @@ load_database (MSymbol *tags, void *extra_info) 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); @@ -555,23 +474,48 @@ get_dir_info (char *dirname) 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 @@ -581,6 +525,7 @@ free_db_info (MDatabaseInfo *db_info) 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); } @@ -616,15 +561,31 @@ check_version (MText *version) static MDatabase * register_database (MSymbol tags[4], void *(*loader) (MSymbol *, void *), - void *extra_info, enum MDatabaseStatus status) + void *extra_info, enum MDatabaseStatus status, + MPlist *properties) { MDatabase *mdb; MDatabaseInfo *db_info; int i; MPlist *plist; - if (! mdatabase__list) - mdatabase__list = mplist (); + if (properties) + { + 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; + } + } + } for (i = 0, plist = mdatabase__list; i < 4; i++) { @@ -688,6 +649,12 @@ register_database (MSymbol tags[4], 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 @@ -700,66 +667,117 @@ register_database (MSymbol tags[4], } static void -register_databases_in_files (MSymbol tags[4], glob_t *globbuf, int headlen) +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) - { - MText *version = NULL; + if (glob (filename, GLOB_NOSORT, NULL, &globbuf)) + break; + headlen = 0; + } + 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; + } - MPLIST_DO (pl, pl) - version = MPLIST_MTEXT_P (pl) ? MPLIST_MTEXT (pl) : NULL; - if (! version || check_version (version)) + 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); + globbuf.gl_pathv[i] + headlen, + MDB_STATUS_AUTO, p); } + M17N_OBJECT_UNREF (pl); } - M17N_OBJECT_UNREF (plist); + 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; +} + /* 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 @@ -797,10 +815,6 @@ mdatabase__init () 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; @@ -961,7 +975,7 @@ mdatabase__update (void) || ! MPLIST_MTEXT_P (p1)) continue; for (; i < 4; i++) - tags[i] = Mnil; + tags[i] = with_wildcard ? Masterisk : Mnil; mt = MPLIST_MTEXT (p1); nbytes = mtext_nbytes (mt); if (nbytes > PATH_MAX) @@ -969,44 +983,11 @@ mdatabase__update (void) 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, 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); - } - } + register_database (tags, load_database, path, + MDB_STATUS_AUTO_WILDCARD, NULL); 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); - } + register_database (tags, load_database, path, + MDB_STATUS_AUTO, p1); } M17N_OBJECT_UNREF (pl); } @@ -1016,7 +997,7 @@ mdatabase__update (void) 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; @@ -1030,7 +1011,7 @@ mdatabase__load_for_keys (MDatabase *mdb, MPlist *keys) 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); @@ -1054,22 +1035,17 @@ mdatabase__check (MDatabase *mdb) { 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; - 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; - } - return 1; } @@ -1081,16 +1057,17 @@ char * 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; } @@ -1103,7 +1080,7 @@ mdatabase__file (MDatabase *mdb) 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 @@ -1120,7 +1097,7 @@ mdatabase__lock (MDatabase *mdb) 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); @@ -1184,7 +1161,7 @@ mdatabase__save (MDatabase *mdb, MPlist *data) 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 (); @@ -1199,9 +1176,11 @@ mdatabase__save (MDatabase *mdb, MPlist *data) 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); @@ -1230,12 +1209,45 @@ mdatabase__unlock (MDatabase *mdb) 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 */ /* 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 + "charset". */ + +/***ja + @brief ¥·¥ó¥Ü¥ë @c Mcharset. + + ¥Ç¥³¡¼¥É¤µ¤ì¤¿ M-text ¤Ï¡¢¥­¡¼¤¬ @c Mcharset + ¤Ç¤¢¤ë¤è¤¦¤Ê¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¡£ + ¥·¥ó¥Ü¥ë @c Mcharset ¤Ï "charset" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¡£ */ + +MSymbol Mcharset; +/*=*/ +/*** @} */ +/*=*/ + /*** @addtogroup m17nDatabase */ /*** @{ */ @@ -1320,21 +1332,49 @@ mdatabase_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3) { 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); @@ -1344,10 +1384,7 @@ mdatabase_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3) } } if (MPLIST_TAIL_P (plist)) - { - M17N_OBJECT_UNREF (plist); - plist = NULL; - } + M17N_OBJECT_UNREF (plist); return plist; } @@ -1407,7 +1444,7 @@ mdatabase_define (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3, 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); + mdb = register_database (tags, loader, extra_info, MDB_STATUS_EXPLICIT, NULL); return mdb; }