+ 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;
+
+ 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)
+{
+ 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;
+ }
+