*** empty log message ***
authorhanda <handa>
Mon, 16 Feb 2009 02:06:50 +0000 (02:06 +0000)
committerhanda <handa>
Mon, 16 Feb 2009 02:06:50 +0000 (02:06 +0000)
src/Makefile.am
src/coding.c
src/database.c
src/database.h
src/input-xml.c [new file with mode: 0644]
src/input.c
src/plist.c

index 4c282a9..5449f15 100644 (file)
@@ -49,7 +49,7 @@ libm17n_core_la_LDFLAGS = -export-dynamic ${VINFO}
 libm17n_la_SOURCES = \
        charset.h charset.c \
        coding.h coding.c \
-       input.h input.c \
+       input.h input.c input-xml.c \
        language.h language.c \
        mlocale.h locale.c \
        m17n.h m17n.c
index 9e3d29d..b991c83 100644 (file)
@@ -702,7 +702,72 @@ encode_coding_charset (MText *mt, int from, int to,
 }
 
 \f
-/* Staffs for coding-systems of type MCODING_TYPE_UTF (8).  */
+\f
+/* Staffs for coding-systems of type MCODING_TYPE_UTF.  */
+
+enum utf_bom
+  {
+    UTF_BOM_MAYBE,
+    UTF_BOM_NO,
+    UTF_BOM_YES,
+    UTF_BOM_MAX
+  };
+
+enum utf_endian
+  {
+    UTF_BIG_ENDIAN,
+    UTF_LITTLE_ENDIAN,
+    UTF_ENDIAN_MAX
+  };
+
+struct utf_status
+{
+  int surrogate;
+  enum utf_bom bom;
+  enum utf_endian endian;
+};
+
+static int
+setup_coding_utf (MCodingSystem *coding)
+{
+  MCodingInfoUTF *info = (MCodingInfoUTF *) (coding->extra_info);
+  MCodingInfoUTF *spec;
+
+  if (info->code_unit_bits == 8)
+    coding->ascii_compatible = 1;
+  else if (info->code_unit_bits == 16
+          || info->code_unit_bits == 32)
+    {
+      if (info->bom < 0 || info->bom > 2
+         || info->endian < 0 || info->endian > 1)
+       MERROR (MERROR_CODING, -1);
+    }
+  else
+    return -1;
+
+  MSTRUCT_CALLOC (spec, MERROR_CODING);
+  *spec = *info;
+  coding->extra_spec = (void *) (spec);
+  return 0;
+}
+
+static int
+reset_coding_utf (MConverter *converter)
+{
+  MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
+  MCodingSystem *coding = internal->coding;
+  struct utf_status *status = (struct utf_status *) &(converter->status);
+
+  if (! coding->ready
+      && setup_coding_utf (coding) < 0)
+    return -1;
+  coding->ready = 1;
+
+  status->surrogate = 0;
+  status->bom = ((MCodingInfoUTF *) (coding->extra_spec))->bom;
+  status->endian = ((MCodingInfoUTF *) (coding->extra_spec))->endian;
+  return 0;
+}
 
 #define UTF8_CHARSET(p)                                        \
   (! ((p)[0] & 0x80) ? (mcharset__unicode)                     \
@@ -737,10 +802,33 @@ decode_coding_utf_8 (const unsigned char *source, int src_bytes, MText *mt,
   int nchars = 0;
   int last_nchars = 0;
   int at_most = converter->at_most > 0 ? converter->at_most : -1;
+  struct utf_status *status = (struct utf_status *) &(converter->status);
   int error = 0;
   int full = converter->lenient || (coding->charsets[0] == mcharset__m17n);
   MCharset *charset = NULL;
 
+  if (status->bom != UTF_BOM_NO)
+    {
+      int c;
+
+      ONE_MORE_BASE_BYTE (c);
+      if (c != 0xEF)
+       REWIND_SRC_TO_BASE ();
+      else
+       {
+         ONE_MORE_BYTE (c);
+         if (c != 0xBB)
+           REWIND_SRC_TO_BASE ();
+         else
+           {
+             ONE_MORE_BYTE (c);
+             if (c != 0xBF)
+               REWIND_SRC_TO_BASE ();          
+           }
+       }
+      status->bom = UTF_BOM_NO;
+    }
+
   while (1)
     {
       int c, c1, bytes;
@@ -864,73 +952,6 @@ encode_coding_utf_8 (MText *mt, int from, int to,
   return (converter->result == MCONVERSION_RESULT_INVALID_CHAR ? -1 : 0);
 }
 
-\f
-/* Staffs for coding-systems of type MCODING_TYPE_UTF (16 & 32).  */
-
-enum utf_bom
-  {
-    UTF_BOM_MAYBE,
-    UTF_BOM_NO,
-    UTF_BOM_YES,
-    UTF_BOM_MAX
-  };
-
-enum utf_endian
-  {
-    UTF_BIG_ENDIAN,
-    UTF_LITTLE_ENDIAN,
-    UTF_ENDIAN_MAX
-  };
-
-struct utf_status
-{
-  int surrogate;
-  enum utf_bom bom;
-  enum utf_endian endian;
-};
-
-static int
-setup_coding_utf (MCodingSystem *coding)
-{
-  MCodingInfoUTF *info = (MCodingInfoUTF *) (coding->extra_info);
-  MCodingInfoUTF *spec;
-
-  if (info->code_unit_bits == 8)
-    coding->ascii_compatible = 1;
-  else if (info->code_unit_bits == 16
-          || info->code_unit_bits == 32)
-    {
-      if (info->bom < 0 || info->bom > 2
-         || info->endian < 0 || info->endian > 1)
-       MERROR (MERROR_CODING, -1);
-    }
-  else
-    return -1;
-
-  MSTRUCT_CALLOC (spec, MERROR_CODING);
-  *spec = *info;
-  coding->extra_spec = (void *) (spec);
-  return 0;
-}
-
-static int
-reset_coding_utf (MConverter *converter)
-{
-  MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
-  MCodingSystem *coding = internal->coding;
-  struct utf_status *status = (struct utf_status *) &(converter->status);
-
-  if (! coding->ready
-      && setup_coding_utf (coding) < 0)
-    return -1;
-  coding->ready = 1;
-
-  status->surrogate = 0;
-  status->bom = ((MCodingInfoUTF *) (coding->extra_spec))->bom;
-  status->endian = ((MCodingInfoUTF *) (coding->extra_spec))->endian;
-  return 0;
-}
-
 static int
 decode_coding_utf_16 (const unsigned char *source, int src_bytes, MText *mt,
                      MConverter *converter)
@@ -1139,7 +1160,7 @@ encode_coding_utf_16 (MText *mt, int from, int to,
 
   SET_SRC (mt, format, from, to);
 
-  if (status->bom != UTF_BOM_NO)
+  if (status->bom == UTF_BOM_YES)
     {
       CHECK_DST (2);
       if (big_endian)
@@ -1227,7 +1248,7 @@ encode_coding_utf_32 (MText *mt, int from, int to,
 
   SET_SRC (mt, format, from, to);
 
-  if (status->bom != UTF_BOM_NO)
+  if (status->bom == UTF_BOM_YES)
     {
       CHECK_DST (4);
       if (big_endian)
@@ -2941,6 +2962,7 @@ mcoding__init (void)
   mplist_set (charsets, Msymbol, Mcharset_m17n);
   mplist_put (param, Mtype, Mutf);
   mplist_put (param, Mcode_unit, (void *) 8);
+  mplist_put (param, Mbom, Mmaybe);
   Mcoding_utf_8_full = mconv_define_coding ("utf-8-full", param,
                                            NULL, NULL, NULL, NULL);
 
index b3a8e65..d1caecf 100644 (file)
@@ -528,6 +528,7 @@ load_database (MSymbol *tags, void *extra_info)
       MERROR (MERROR_DB, NULL);
     }
 
+#if 0
   if (db_info->status != MDB_STATUS_UPDATED)
     {
       if (! xml_validate (db_info))
@@ -538,6 +539,7 @@ load_database (MSymbol *tags, void *extra_info)
        }
       db_info->status = MDB_STATUS_UPDATED;
     }
+#endif
   MDEBUG_PRINT1 (" from %s\n", MTEXT_STR (path));
 
   if (tags[0] == Mchar_table)
@@ -551,8 +553,20 @@ load_database (MSymbol *tags, void *extra_info)
   else
     {
       int c;
+      unsigned char buf[4];
 
-      while ((c = getc (fp)) != EOF && isspace (c));
+      if (fgets (buf, 4, fp) == NULL)
+       c = EOF;
+      else
+       {
+         /* Skip BOM of UTF-8.  */
+         if ((c = buf[0]) != 0xEF)
+           fseek (fp, 0L, SEEK_SET);
+         else if (buf[1] != 0xBB)
+           fseek (fp, 0L, SEEK_SET);
+         else if (buf[2] != 0xBF)
+           fseek (fp, 0L, SEEK_SET);
+       }
       if (c == '<')
        {
          MDatabaseLoaderXML loader = find_xml_loader (tags);
@@ -561,12 +575,10 @@ load_database (MSymbol *tags, void *extra_info)
            MERROR (MERROR_DB, NULL);
          fclose (fp);
          fp = NULL;
-         value = loader (tags, MTEXT_STR (path),
-                         ! db_info->system_database, NULL);
+         value = loader (db_info, MTEXT_STR (path));
        }
       else if (c != EOF)
        {
-         ungetc (c, fp);
          value = mplist__from_file (fp, NULL);
        }
       else
@@ -605,6 +617,7 @@ static int
 update_dir_info (MDatabaseInfo *dir_info)
 {
   struct stat statbuf;
+  MText *mdb_file;
 
   if (! file_readble_p (dir_info->dirname, NULL, &statbuf))
     {
@@ -616,34 +629,26 @@ update_dir_info (MDatabaseInfo *dir_info)
       return 1;
     }
 
-  if (file_readble_p (dir_info->dirname, mdb_xml, &statbuf))
-    {
-      if (dir_info->filename == mdb_xml
-         && dir_info->time >= statbuf.st_mtime)
-       return 0;
-      M17N_OBJECT_UNREF (dir_info->filename);
-      dir_info->filename = mdb_xml;
-      M17N_OBJECT_REF (mdb_xml);
-      dir_info->format = Mxml;
-      dir_info->mtime = statbuf.st_mtime;
-      dir_info->time = 0;
-      return 1;
-    }
-  if (file_readble_p (dir_info->dirname, mdb_dir, &statbuf))
-    {
-      if (dir_info->filename == mdb_dir
-         && dir_info->time >= statbuf.st_mtime)
-       return 0;
-      M17N_OBJECT_UNREF (dir_info->filename);
-      dir_info->filename = mdb_dir;
-      M17N_OBJECT_REF (mdb_dir);
-      dir_info->format = Mplist;
-      dir_info->mtime = statbuf.st_mtime;
-      dir_info->time = 0;
-      return 1;
-    }
+  for (mdb_file = mdb_xml; mdb_file;
+       mdb_file = (mdb_file == mdb_dir ? NULL : mdb_dir))
+    if (file_readble_p (dir_info->dirname, mdb_file, &statbuf))
+      {
+       if (dir_info->filename == mdb_file
+           && dir_info->time >= statbuf.st_mtime)
+         return 0;
+       dir_info->status = MDB_STATUS_OUTDATED;
+       M17N_OBJECT_UNREF (dir_info->filename);
+       dir_info->filename = mdb_file;
+       M17N_OBJECT_REF (mdb_file);
+       dir_info->format = mdb_file == mdb_xml ? Mxml : Mplist;
+       dir_info->time = dir_info->mtime = statbuf.st_mtime;
+       return 1;
+      }
+  dir_info->status = MDB_STATUS_INVALID;
   if (! dir_info->filename)
     return 0;
+  /* The directory is readable but doesn't have mdb.xml nor
+     mdb.dir.  */
   dir_info->filename = NULL;
   dir_info->mtime = dir_info->time = 0;
   return 1;
@@ -677,10 +682,10 @@ find_database (MSymbol tags[4])
            p = MPLIST_PLIST (MPLIST_NEXT (p));
          mdb = MPLIST_VAL (MPLIST_NEXT (p));
          db_info = mdb->extra_info;
-         if (db_info->status != MDB_STATUS_DISABLED)
+         if (db_info->status == MDB_STATUS_OUTDATED)
            {
              register_databases_in_files (mdb->tag, db_info);
-             db_info->status = MDB_STATUS_DISABLED;
+             db_info->status = MDB_STATUS_UPDATED;
              return find_database (tags);
            }
        }
@@ -782,7 +787,6 @@ register_database (MSymbol tags[4],
       if (mdb->extra_info)
        {
          db_info = mdb->extra_info;
-         M17N_OBJECT_UNREF (db_info->dirname);
          M17N_OBJECT_UNREF (db_info->filename);
          M17N_OBJECT_UNREF (db_info->validater);
          M17N_OBJECT_UNREF (db_info->properties);
@@ -862,10 +866,13 @@ parse_mdb_xml_item (xmlNodePtr node)
              else if (STR_EQ (cur->name, "format"))
                format = msymbol (content);
              else if (STR_EQ (cur->name, "schema"))
-               schema = msymbol (content);
-             else if (STR_EQ (cur->name, "schema-filename"))
-               schema_file = mtext__from_data (content, strlen (content),
-                                               MTEXT_FORMAT_UTF_8, 1);
+               {
+                 attr = xmlHasProp (cur, "type");
+                 schema = msymbol ((char *) attr->children->content);
+                 content = cur->children->children->content;
+                 schema_file = mtext__from_data (content, strlen (content),
+                                                 MTEXT_FORMAT_UTF_8, 1);
+               }
            }
          if (format == Mnil)
            pl = mplist_add (pl, Mtext, filename);
@@ -978,7 +985,7 @@ xml_validate (MDatabaseInfo *db_info)
   xmlDocPtr doc = NULL;
   MText *path = NULL;
   char *file;
-  int result = 0;
+  int result;
 
   if (db_info->schema == Mnil)
     return 1;
@@ -991,62 +998,7 @@ xml_validate (MDatabaseInfo *db_info)
                                  | XML_PARSE_XINCLUDE | XML_PARSE_COMPACT));
   if (! doc)
     MERROR (MERROR_DB, 0);
-  if (db_info->schema == Mdtd)
-    {
-      if (db_info->validater)
-       /* Not yet supported. */
-       result = 0;
-      else
-       result = 1;
-    }
-  else if (! db_info->validater)
-    result = 0;
-  else
-    {
-      path = get_database_file (NULL, db_info->validater);
-      if (! path)
-       result = 0;
-      else
-       {
-         file = MTEXT_STR (path);
-         if (db_info->schema == Mxml_schema)
-           {
-             xmlSchemaParserCtxtPtr context = NULL;
-             xmlSchemaPtr schema = NULL;
-             xmlSchemaValidCtxtPtr valid_context = NULL;
-
-             if ((context = xmlSchemaNewParserCtxt (file))
-                  && (schema = xmlSchemaParse (context))
-                  && (valid_context = xmlSchemaNewValidCtxt (schema))
-                  && xmlSchemaValidateDoc (valid_context, doc) == 0)
-               result = 1;
-             if (valid_context)
-               xmlSchemaFreeValidCtxt (valid_context);
-             if (schema)
-               xmlSchemaFree (schema);
-             if (context)
-               xmlSchemaFreeParserCtxt (context);
-           }
-         else if (db_info->schema == Mrelaxng)
-           {
-             xmlRelaxNGParserCtxtPtr context = NULL;
-             xmlRelaxNGPtr schema = NULL;
-             xmlRelaxNGValidCtxtPtr valid_context = NULL;
-
-             if ((context = xmlRelaxNGNewParserCtxt (file))
-                 && (schema = xmlRelaxNGParse (context))
-                 && (valid_context = xmlRelaxNGNewValidCtxt (schema))
-                 && xmlRelaxNGValidateDoc (valid_context, doc) == 0)
-               result = 1;
-             if (valid_context)
-               xmlRelaxNGFreeValidCtxt (valid_context);
-             if (schema)
-               xmlRelaxNGFree (schema);
-             if (context)
-               xmlRelaxNGFreeParserCtxt (context);
-           }
-       }
-    }
+  result = mdatabase__validate (doc, db_info);
   xmlFreeDoc (doc);
   return result;
 }
@@ -1248,6 +1200,9 @@ parse_header_sexp (char *filename, MSymbol tags[4], MDatabaseInfo *db_info)
       M17N_OBJECT_UNREF (plist);
       MERROR (MERROR_DB, 0);
     }
+  if (db_info->filename)
+    MERROR (MERROR_DB, 0);
+  db_info->filename = MTEXT_FOR_FILE (filename);
   M17N_OBJECT_UNREF (plist);
   return 1;
 }
@@ -1259,7 +1214,7 @@ merge_info (MSymbol tags1[4], MDatabaseInfo *info1,
   int i;
 
   for (i = 0; i < 4; i++)
-    if (tags1[i] != Masterisk && tags1[i] != tags2[i])
+    if (tags1[i] && tags1[i] != Masterisk && tags1[i] != tags2[i])
       goto err;
   if (info2->format == Mnil)
     info2->format = info1->format;
@@ -1274,7 +1229,7 @@ merge_info (MSymbol tags1[4], MDatabaseInfo *info1,
       info2->filename = info1->filename;
       M17N_OBJECT_REF (info2->filename);
     }
-  if (! info2->validater)
+  if (! info2->validater && info1->validater)
     {
       info2->validater = info1->validater;
       M17N_OBJECT_REF (info2->validater);
@@ -1292,21 +1247,27 @@ merge_info (MSymbol tags1[4], MDatabaseInfo *info1,
 static void
 register_databases_in_files (MSymbol tags[4], MDatabaseInfo *db_info)
 {
-  glob_t globbuf;
-  int i;
+  int check[3];
+  glob_t globbuf[3];
+  MText *dirname[3];
+  int i, j;
   MPlist *plist;
-  MText *dirname;
+
+  check[0] = check[1] = check[2] = 0;
 
   if (ABSOLUTE_PATH_P (db_info->filename))
     {
-      if (glob (MTEXT_STR (db_info->filename), GLOB_NOSORT, NULL, &globbuf))
-       return;
-      dirname = NULL;
+      if (glob (MTEXT_STR (db_info->filename), GLOB_NOSORT, NULL, globbuf) == 0)
+       {
+         check[0] = 1;
+         dirname[0] = NULL;
+       }
     }
   else
     {
       MDatabaseInfo *dir_info;
 
+      j = 2;
       MPLIST_DO (plist, mdatabase__dir_list)
        {
          MText *path;
@@ -1315,46 +1276,50 @@ register_databases_in_files (MSymbol tags[4], MDatabaseInfo *db_info)
          if (dir_info->status == MDB_STATUS_DISABLED)
            continue;
          path = GEN_PATH (dir_info->dirname, db_info->filename);
-         if (glob (MTEXT_STR (path), GLOB_NOSORT, NULL, &globbuf) == 0)
-           break;
+         if (glob (MTEXT_STR (path), GLOB_NOSORT, NULL, globbuf + j) == 0)
+           {
+             check[j] = 1;
+             dirname[j] = dir_info->dirname;
+           }
+         j--;
        }
-      if (MPLIST_TAIL_P (plist))
-       return;
-      dirname = dir_info->dirname;
     }
 
-  for (i = 0; i < globbuf.gl_pathc; i++)
-    {
-      MDatabaseInfo this;
-      MSymbol tags2[4];          
-
-      memset (&this, 0, sizeof (MDatabaseInfo));
-      if (dirname)
-       {
-         this.dirname = dirname;
-         M17N_OBJECT_REF (dirname);
-         this.filename = MTEXT_FOR_FILE (globbuf.gl_pathv[i]
-                                         + mtext_nbytes (dirname));
-       }
-      else
-       this.filename = MTEXT_FOR_FILE (globbuf.gl_pathv[i]);
-      if (db_info->format == Mxml)
-       {
-         xmlTextReaderPtr reader
-           = xmlReaderForFile (globbuf.gl_pathv[i], "utf-8",
-                               XML_PARSE_NOBLANKS
-                               | XML_PARSE_NOENT
-                               | XML_PARSE_XINCLUDE);
-         if (reader
-             && parse_header_xml (reader, tags2, &this)
-             && merge_info (tags, db_info, tags2, &this))
-           register_database (tags2, load_database, &this, MDB_TYPE_AUTO);
-       }
-      else if (parse_header_sexp (globbuf.gl_pathv[i], tags2, &this)
-              && merge_info (tags, db_info, tags2, &this))
-       register_database (tags2, load_database, &this, MDB_TYPE_AUTO);
-    }
-  globfree (&globbuf);
+  for (j = 0; j < 3; j++)
+    if (check[j])
+      {
+       for (i = 0; i < globbuf[j].gl_pathc; i++)
+         {
+           MDatabaseInfo this;
+           MSymbol tags2[4];     
+
+           memset (&this, 0, sizeof (MDatabaseInfo));
+           if (dirname[j])
+             this.filename = MTEXT_FOR_FILE (globbuf[j].gl_pathv[i]
+                                             + mtext_nbytes (dirname[j]));
+           else
+             this.filename = MTEXT_FOR_FILE (globbuf[j].gl_pathv[i]);
+           if (db_info->format == Mxml)
+             {
+               xmlTextReaderPtr reader
+                 = xmlReaderForFile (globbuf[j].gl_pathv[i], "utf-8",
+                                     XML_PARSE_NOBLANKS
+                                     | XML_PARSE_NOENT
+                                     | XML_PARSE_XINCLUDE);
+               if (reader
+                   && parse_header_xml (reader, tags2, &this)
+                   && merge_info (tags, db_info, tags2, &this))
+                 register_database (tags2, load_database, &this,
+                                    MDB_TYPE_AUTO);
+             }
+           else if (parse_header_sexp (globbuf[j].gl_pathv[i], tags2, &this)
+                    && merge_info (tags, db_info, tags2, &this))
+             register_database (tags2, load_database, &this, MDB_TYPE_AUTO);
+           M17N_OBJECT_UNREF (this.filename);
+           M17N_OBJECT_UNREF (this.validater);
+         }
+       globfree (globbuf + j);
+      }
 }
 
 static int
@@ -1372,10 +1337,10 @@ expand_wildcard_database (MPlist *plist)
   mdb = MPLIST_VAL (plist);
   if (mdb->loader == load_database
       && (db_info = mdb->extra_info)
-      && db_info->status != MDB_STATUS_DISABLED)
+      && db_info->status != MDB_STATUS_UPDATED)
     {
       register_databases_in_files (mdb->tag, db_info);
-      db_info->status = MDB_STATUS_DISABLED;
+      db_info->status = MDB_STATUS_UPDATED;
       return 1;
     }
   return 0;
@@ -1503,6 +1468,7 @@ mdatabase__update (void)
 {
   MPlist *plist, *p0, *p1, *p2, *p3;
   int rescan = 0;
+  int mdebug_flag = MDEBUG_DATABASE;
 
   /* Update elements of mdatabase__dir_list.  */
   MPLIST_DO (plist, mdatabase__dir_list)
@@ -1554,14 +1520,19 @@ mdatabase__update (void)
       MText *path;
 
       if (dir_info->status == MDB_STATUS_DISABLED
-         || ! dir_info->filename)
+         || dir_info->status == MDB_STATUS_INVALID)
        continue;
       path = GEN_PATH (dir_info->dirname, dir_info->filename);
+      MDEBUG_PRINT1 (" [DB] Parsing <%s>", MTEXT_STR (path));
       p0 = (dir_info->format == Mxml
            ? parse_mdb_xml (MTEXT_STR (path), ! dir_info->system_database)
            : parse_mdb_dir (MTEXT_STR (path)));
       if (! p0)
-       continue;
+       {
+         MDEBUG_PRINT (" fail\n");
+         continue;
+       }
+      MDEBUG_PRINT ("\n");
       MPLIST_DO (p1, p0)
        {
          MSymbol tags[4];
@@ -1616,8 +1587,7 @@ mdatabase__load_for_keys (MDatabase *mdb, MPlist *keys)
 
          if (! loader)
            MERROR (MERROR_DB, NULL);
-         plist = loader (mdb->tag, MTEXT_STR (path),
-                         ! db_info->system_database, keys);
+         plist = loader (db_info, MTEXT_STR (path));
        }
       else if (c != EOF)
        plist = mplist__from_file (fp, keys);
@@ -1667,10 +1637,7 @@ mdatabase__find_file (char *filename)
   if (! path)
     filename = NULL;
   else
-    {
-      filename = strdup (MTEXT_STR (path));
-      M17N_OBJECT_UNREF (path);
-    }
+    filename = strdup (MTEXT_STR (path));
   M17N_OBJECT_UNREF (file);
   return filename;
 }
@@ -1861,11 +1828,77 @@ mdatabase__register_xml_loader (MSymbol tags[4], MDatabaseLoaderXML loader)
          plist = MPLIST_NEXT (pl);
        }
     }
-  MPLIST_KEY (plist) = Mt;
+  mplist_add (plist, Mt, NULL);
   MPLIST_FUNC (plist) = (M17NFunc) loader;
   MPLIST_SET_VAL_FUNC_P (plist);
 }
 
+int
+mdatabase__validate (xmlDocPtr doc, MDatabaseInfo *db_info)
+{
+  int result = 0;
+  MText *path = NULL;
+  char *file;
+
+  if (db_info->schema == Mdtd)
+    {
+      if (db_info->validater)
+       /* Not yet supported. */
+       result = 0;
+      else
+       result = 1;
+    }
+  else if (db_info->validater)
+    {
+      path = get_database_file (NULL, db_info->validater);
+      if (! path)
+       result = 0;
+      else
+       {
+         file = MTEXT_STR (path);
+         if (db_info->schema == Mxml_schema)
+           {
+             xmlSchemaParserCtxtPtr context = NULL;
+             xmlSchemaPtr schema = NULL;
+             xmlSchemaValidCtxtPtr valid_context = NULL;
+
+             if ((context = xmlSchemaNewParserCtxt (file))
+                 && (schema = xmlSchemaParse (context))
+                 && (valid_context = xmlSchemaNewValidCtxt (schema))
+                 && xmlSchemaValidateDoc (valid_context, doc) == 0)
+               result = 1;
+             if (valid_context)
+               xmlSchemaFreeValidCtxt (valid_context);
+             if (schema)
+               xmlSchemaFree (schema);
+             if (context)
+               xmlSchemaFreeParserCtxt (context);
+           }
+         else if (db_info->schema == Mrelaxng)
+           {
+             xmlRelaxNGParserCtxtPtr context = NULL;
+             xmlRelaxNGPtr schema = NULL;
+             xmlRelaxNGValidCtxtPtr valid_context = NULL;
+
+             if ((context = xmlRelaxNGNewParserCtxt (file))
+                 && (schema = xmlRelaxNGParse (context))
+                 && (valid_context = xmlRelaxNGNewValidCtxt (schema))
+                 && xmlRelaxNGValidateDoc (valid_context, doc) == 0)
+               result = 1;
+             if (valid_context)
+               xmlRelaxNGFreeValidCtxt (valid_context);
+             if (schema)
+               xmlRelaxNGFree (schema);
+             if (context)
+               xmlRelaxNGFreeParserCtxt (context);
+             if (! result)
+               MERROR (MERROR_DB, result);
+           }
+       }
+    }
+  return result;
+}
+
 /*** @} */
 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
 
@@ -1969,11 +2002,12 @@ mdatabase_find (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
 MPlist *
 mdatabase_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
 {
-  MPlist *plist = mplist (), *pl = plist;
-  MPlist *p, *p0, *p1, *p2, *p3;
+  MPlist *plist, *pl, *p, *p0, *p1, *p2, *p3;
 
   mdatabase__update ();
 
+ retry:
+  plist = mplist (), pl = plist;
   MPLIST_DO (p, mdatabase__list)
     {
       p0 = MPLIST_PLIST (p);
@@ -1989,7 +2023,7 @@ mdatabase_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
              if (expand_wildcard_database (p1))
                {
                  M17N_OBJECT_UNREF (plist);
-                 return mdatabase_list (tag0, tag1, tag2, tag3);
+                 goto retry;
                }
              continue;
            }
@@ -2003,7 +2037,7 @@ mdatabase_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
                  if (expand_wildcard_database (p2))
                    {
                      M17N_OBJECT_UNREF (plist);
-                     return mdatabase_list (tag0, tag1, tag2, tag3);
+                     goto retry;
                    }
                  continue;
                }
@@ -2017,7 +2051,7 @@ mdatabase_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
                      if (expand_wildcard_database (p3))
                        {
                          M17N_OBJECT_UNREF (plist);
-                         return mdatabase_list (tag0, tag1, tag2, tag3);
+                         goto retry;
                        }
                      continue;
                    }
index 55eb5d5..2589041 100644 (file)
@@ -100,8 +100,7 @@ typedef struct
   MPlist *properties;
 } MDatabaseInfo;
 
-typedef MPlist *(*MDatabaseLoaderXML) (MSymbol *, char *filename, int validate,
-                                      MPlist *keys);
+typedef MPlist *(*MDatabaseLoaderXML) (MDatabaseInfo *, char *filename);
 
 extern MPlist *mdatabase__dir_list;
 
@@ -125,4 +124,7 @@ extern MPlist *mdatabase__props (MDatabase *mdb);
 
 extern void *(*mdatabase__load_charset_func) (FILE *fp, MSymbol charset_name);
 
+#include <libxml/xmlreader.h>
+extern int mdatabase__validate (xmlDocPtr doc, MDatabaseInfo *db_info);
+
 #endif /* not _M17N_DATABASE_H_ */
diff --git a/src/input-xml.c b/src/input-xml.c
new file mode 100644 (file)
index 0000000..201caa1
--- /dev/null
@@ -0,0 +1,1240 @@
+/* input-xml.c -- XML decoder for input method module.
+   Copyright (C) 2009
+     National Institute of Advanced Industrial Science and Technology (AIST)
+     Registration Number H15PRO112
+
+   This file is part of the m17n library.
+
+   The m17n library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License
+   as published by the Free Software Foundation; either version 2.1 of
+   the License, or (at your option) any later version.
+
+   The m17n library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   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., 51 Franklin Street, Fifth Floor,
+   02111-1307, USA.  */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/xinclude.h>
+
+#include "config.h"
+#include "m17n.h"
+#include "m17n-misc.h"
+#include "internal.h"
+#include "database.h"
+
+static void decode_saction (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent);
+
+/* Sometimes isspace () returns non-zero values for chars between 255
+   and EOF. */
+static int
+Isspace (int ch)
+{
+  if (ch == 32 || ch == 8 || ch == 10 || ch == 13)
+    return 1;
+  else
+    return 0;
+}
+
+static MSymbol
+decode_predefined (xmlChar *ptr)
+{
+  char str[3];
+
+  str[0] = '@';
+  str[2] = '\0';
+  if (xmlStrEqual (ptr, (xmlChar *) "first"))
+    str [1] = '<';
+  else if (xmlStrEqual (ptr, (xmlChar *) "current"))
+    str [1] = '=';
+  else if (xmlStrEqual (ptr, (xmlChar *) "last"))
+    str [1] = '>';
+  else if (xmlStrEqual (ptr, (xmlChar *) "previous"))
+    str [1] = '-';
+  else if (xmlStrEqual (ptr, (xmlChar *) "next"))
+    str [1] = '+';
+  else if (xmlStrEqual (ptr, (xmlChar *) "previous_candidate_list"))
+    str [1] = '[';
+  else if (xmlStrEqual (ptr, (xmlChar *) "next_candidate_list"))
+    str [1] = ']';
+  else
+    str [1] = *ptr;
+  return msymbol (str);
+}
+
+static void
+decode_marker (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr = xmlGetProp (cur, (xmlChar *) "position");
+
+  if (ptr)
+    mplist_add (parent, Msymbol, decode_predefined (ptr + 1));
+  else
+    {
+      ptr = xmlGetProp (cur, (xmlChar *) "markerID");
+      mplist_add (parent, Msymbol, msymbol ((char *) ptr));
+    }
+  xmlFree (ptr);
+}
+
+static void
+decode_variable_reference (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  /*
+  xmlChar *id = xmlGetProp (cur, (xmlChar *) "id");
+  xmlChar *type = xmlGetProp (cur, (xmlChar *) "type");
+
+  if (type)
+    {
+      xmlFree (type);
+      if (xmlStrEqual (id, (xmlChar *) "handled-keys"))
+       mplist_add (parent, Msymbol, msymbol ("@@"));
+      else if (xmlStrEqual (id, (xmlChar *) "predefined-surround-text-flag"))
+       mplist_add (parent, Msymbol, msymbol ("@-0"));
+      else
+       mplist_add (parent, Msymbol, msymbol ((char *) id));
+    }
+  else
+    mplist_add (parent, Msymbol, msymbol ((char *) id));
+
+  xmlFree (id);
+  */
+
+  xmlChar *ptr = xmlGetProp (cur, (xmlChar *) "id");
+
+  if (xmlStrEqual (ptr, (xmlChar *) "handled-keys"))
+    mplist_add (parent, Msymbol, msymbol ("@@"));
+  else if (xmlStrEqual (ptr, (xmlChar *) "predefined-surround-text-flag"))
+    mplist_add (parent, Msymbol, msymbol ("@-0"));
+  else
+    mplist_add (parent, Msymbol, msymbol ((char *) ptr));
+  xmlFree (ptr);
+}
+
+static void
+decode_integer (xmlChar *ptr, MPlist *parent)
+{
+  while (Isspace (*ptr))
+    ptr++;
+
+  if (xmlStrlen (ptr) >= 3
+      && (ptr[0] == '0' || ptr[0] == '#')
+      && ptr[1] == 'x')
+    {
+      int val;
+
+      sscanf ((char *) ptr + 2, "%x", &val);
+      mplist_add (parent, Minteger, (void *) val);
+    }
+  else if (ptr[0] == '?')
+    {
+      int val, len = 4;
+
+      val = xmlGetUTF8Char (ptr + 1, &len);
+      mplist_add (parent, Minteger, (void *) val);
+    }
+  else
+    mplist_add (parent, Minteger, (void *) atoi ((char *) ptr));
+}
+
+static void
+decode_keyseq (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+
+  if (xmlStrEqual (cur->name, (xmlChar *) "command-reference"))
+    {
+      ptr = xmlGetProp (cur, (xmlChar *) "id");
+      /* +8 to skip "command-" */
+      mplist_add (parent, Msymbol, msymbol ((char *) ptr + 8));
+      xmlFree (ptr);
+    }
+
+  else if ((ptr = xmlGetProp (cur, (xmlChar *) "keys")))
+    mplist_add (parent, Mtext,
+               mtext_from_data (ptr, xmlStrlen (ptr), MTEXT_FORMAT_UTF_8));
+
+  else
+    {
+      MPlist *plist = mplist ();
+
+      for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
+       {
+         ptr = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+         if (xmlStrEqual (cur->name, (xmlChar *) "key-event"))
+           /*
+             {
+             char *p;
+
+             sscanf ((char *) ptr, " %ms ", &p);
+             mplist_add (plist, Msymbol, msymbol (p));
+             printf ("(%s)", p);
+             free (p);
+             }
+           */
+           mplist_add (plist, Msymbol, msymbol ((char *) ptr));
+         else                  /* character-code */
+           decode_integer (ptr, plist);
+         xmlFree (ptr);
+       }    
+      mplist_add (parent, Mplist, plist);
+    }
+}
+
+static void
+decode_plist (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  /* to be written */
+}
+
+static void
+decode_expr (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  if (xmlStrEqual (cur->name, (xmlChar *) "expr"))
+    {
+      xmlChar *ptr = xmlGetProp (cur, (xmlChar *) "operator");
+      MPlist *plist = mplist ();
+
+      mplist_add (plist, Msymbol, msymbol ((char *) ptr));
+      xmlFree (ptr);
+
+      for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
+       decode_expr (doc, cur, plist);
+
+      mplist_add (parent, Mplist, plist);
+    }
+  else if (xmlStrEqual (cur->name, (xmlChar *) "int-val"))
+    {
+      xmlChar *ptr = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+
+      decode_integer (ptr, parent);
+      xmlFree (ptr);
+    }
+  else if (xmlStrEqual (cur->name, (xmlChar *) "predefined-nth-previous-or-following-character"))
+    {
+      xmlChar *ptr = xmlGetProp (cur, (xmlChar *) "position");
+      char str[8];
+
+      snprintf (str, 8, "@%+d", atoi ((char *) ptr));
+      xmlFree (ptr);
+      mplist_add (parent, Msymbol, msymbol (str));
+    }
+  else                         /* variable-reference */
+      decode_variable_reference (doc, cur, parent);
+}
+    
+static void
+decode_insert (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+  MPlist *plist = mplist ();
+
+  mplist_add (plist, Msymbol, msymbol ("insert"));
+
+  if ((ptr = xmlGetProp (cur, (xmlChar *) "string")))
+    mplist_add (plist, Mtext,
+               mtext_from_data (ptr, xmlStrlen (ptr), MTEXT_FORMAT_UTF_8));
+
+  else if ((ptr = xmlGetProp (cur, (xmlChar *) "character")))
+    {
+      decode_integer (ptr, plist);
+      xmlFree (ptr);
+    }
+
+  else if ((ptr = xmlGetProp (cur, (xmlChar *) "character-or-string")))
+    {
+      xmlFree (ptr);
+      ptr = xmlGetProp (cur->xmlChildrenNode, (xmlChar *) "id");
+      mplist_add (plist, Msymbol, msymbol ((char *) ptr));
+      xmlFree (ptr);
+    }
+
+  else if ((cur = cur->xmlChildrenNode)
+          && xmlStrEqual (cur->name, (xmlChar *) "candidates"))
+    {
+      MPlist *pl = mplist ();
+
+      mplist_add (plist, Mplist, pl);
+      M17N_OBJECT_UNREF (pl);
+      while (cur)
+       {
+         ptr = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+         pl = mplist_add (pl, Mtext,
+                          mtext_from_data (ptr, xmlStrlen (ptr),
+                                           MTEXT_FORMAT_UTF_8));
+         cur = cur->next;
+       }
+    }
+
+  else                         /* list-of-candidates */
+    while (cur)
+      {
+       xmlChar *start;
+       MPlist *plist0 = mplist (), *plist1 = mplist ();
+       int ch, len = 4, skipping = 1;
+
+       ptr = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+
+       while ((ch = xmlGetUTF8Char (ptr, &len)))
+         {
+           if (skipping && ! Isspace (ch))
+             {
+               start = ptr;
+               skipping = 0;
+             }
+           else if (! skipping && Isspace (ch))
+             {
+               *ptr = '\0';
+               mplist_add (plist0, Mtext,
+                           mtext_from_data (start, xmlStrlen (start),
+                                            MTEXT_FORMAT_UTF_8));
+               skipping = 1;
+             }
+           ptr += len;
+           len = 4;
+         }
+       if (!skipping)
+         {
+           mplist_add (plist0, Mtext,
+                       mtext_from_data (start, xmlStrlen (start),
+                                        MTEXT_FORMAT_UTF_8));
+         }
+
+       mplist_add (plist1, Mplist, plist0);
+       mplist_add (plist, Mplist, plist1);
+       cur = cur->next;
+      }
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_delete (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+  MPlist *plist = mplist ();
+
+  mplist_add (plist, Msymbol, msymbol ("delete"));
+
+  if (xmlStrEqual (cur->name, (xmlChar *) "delete-to-marker"))
+    decode_marker (doc, cur, plist);
+  else if (xmlStrEqual (cur->name,
+                       (xmlChar *) "delete-to-character-position"))
+    {
+      ptr = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+      decode_integer (ptr, plist);
+      xmlFree (ptr);
+    }
+  else                         /* delete-n-characters */
+    {
+      char str[8];
+
+      ptr = xmlGetProp (cur, (xmlChar *) "n");
+      snprintf (str, 8, "@%+d", atoi ((char *) ptr));
+      xmlFree (ptr);
+      mplist_add (plist, Msymbol, msymbol (str));
+    }
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_select (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+  MPlist *plist = mplist ();
+
+  mplist_add (plist, Msymbol, msymbol ("select"));
+  
+  if ((ptr = xmlGetProp (cur, (xmlChar *) "selector")))
+    mplist_add (plist, Msymbol, decode_predefined (ptr + 1));
+  else
+    {
+      ptr = xmlGetProp (cur, (xmlChar *) "index");
+      if (xmlStrEqual (ptr, (xmlChar *) "variable"))
+       {
+         xmlFree (ptr);
+         ptr = xmlGetProp (cur->xmlChildrenNode, (xmlChar *) "id");
+         mplist_add (plist, Msymbol, msymbol ((char *) ptr));
+       }
+      else
+       decode_integer (ptr, plist);
+    }
+  xmlFree (ptr);
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_move (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  MPlist *plist = mplist ();
+
+  mplist_add (plist, Msymbol, msymbol ("move"));
+
+  if (xmlStrEqual (cur->name, (xmlChar *) "move-to-marker"))
+    decode_marker (doc, cur, plist);
+
+  else                         /* move-to-character-position */
+    {
+      xmlChar *ptr = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+
+      decode_integer (ptr, plist);
+      xmlFree (ptr);
+    }
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_mark (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  MPlist *plist = mplist ();
+
+  mplist_add (plist, Msymbol, msymbol ("mark"));
+
+  decode_marker (doc, cur, plist);
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_pushback (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  MPlist *plist = mplist ();
+
+  mplist_add (plist, Msymbol, msymbol ("pushback"));
+
+  if (xmlStrEqual (cur->name, (xmlChar *) "pushback-n-events"))
+    {
+      xmlChar *ptr = xmlGetProp (cur, (xmlChar *) "n");
+
+      decode_integer (ptr, plist);
+      xmlFree (ptr);
+    }
+
+  else                         /* pushback-keyseq */
+    decode_keyseq (doc, cur->xmlChildrenNode, plist);
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_undo (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+  MPlist *plist = mplist ();
+
+  mplist_add (plist, Msymbol, msymbol ("undo"));
+
+  if ((ptr = xmlGetProp (cur, (xmlChar *) "target-of-undo")))
+    {
+      decode_integer (ptr, plist);
+      xmlFree (ptr);
+    }
+  else if (cur->xmlChildrenNode)
+    decode_variable_reference (doc, cur->xmlChildrenNode, plist);
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_call (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+  MPlist *plist = mplist ();
+
+  mplist_add (plist, Msymbol, msymbol ("call"));
+
+  ptr = xmlGetProp (cur, (xmlChar *) "id");
+  /* +7 to skip "module-" */
+  mplist_add (plist, Msymbol, msymbol ((char *) ptr + 7));
+  xmlFree (ptr);
+
+  cur = cur->xmlChildrenNode;
+  ptr = xmlGetProp (cur, (xmlChar *) "id");
+  /* +9 to skip "function-" */
+  mplist_add (plist, Msymbol, msymbol ((char *) ptr + 9));
+  xmlFree (ptr);
+
+  for (cur = cur->next; cur; cur = cur->next)
+    {
+      ptr = xmlGetProp (cur, (xmlChar *) "type");
+      if (xmlStrEqual (ptr, (xmlChar *) "string"))
+       {
+         xmlFree (ptr);
+         ptr = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+         mplist_add (plist, Mtext, mtext_from_data (ptr, xmlStrlen (ptr),
+                                                    MTEXT_FORMAT_UTF_8));
+       }
+      else if (xmlStrEqual (ptr, (xmlChar *) "integer"))
+       {
+         xmlFree (ptr);
+         ptr = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+         decode_integer (ptr, plist);
+         xmlFree (ptr);
+       }
+      else if (xmlStrEqual (ptr, (xmlChar *) "plist"))
+       {
+         xmlFree (ptr);
+         decode_plist (doc, cur->xmlChildrenNode, plist);
+       }
+      else                     /* symbol */
+       {
+         xmlFree (ptr);
+         decode_variable_reference (doc, cur->xmlChildrenNode, plist);
+       }
+    }
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_set (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+  MPlist *plist = mplist ();
+
+  mplist_add (plist, Msymbol, msymbol ((char *) cur->name));
+
+  ptr = xmlGetProp (cur, (xmlChar *) "id");
+  mplist_add (plist, Msymbol, msymbol ((char *) ptr));
+  xmlFree (ptr);
+
+  decode_expr (doc, cur->xmlChildrenNode, plist);
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_if (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+  xmlNodePtr cur0;
+  MPlist *plist = mplist (), *plist0 = mplist ();
+
+  ptr = xmlGetProp (cur, (xmlChar *) "condition");
+  mplist_add (plist, Msymbol, msymbol ((char *) ptr));
+  xmlFree (ptr);
+
+  cur = cur->xmlChildrenNode;  /* 1st arg */
+  decode_expr (doc, cur, plist);
+
+  cur =  cur->next;            /* 2nd arg */
+  decode_expr (doc, cur, plist);
+
+  cur = cur->next;             /* then */
+  plist0 = mplist ();
+  for (cur0 = cur->xmlChildrenNode; cur0; cur0 = cur0->next)
+    decode_saction (doc, cur0, plist0);
+  mplist_add (plist, Mplist, plist0);
+
+  cur = cur->next;             /* else */
+  if (cur)
+    {
+      plist0 = mplist ();
+      for (cur0 = cur->xmlChildrenNode; cur0; cur0 = cur0->next)
+       decode_saction (doc, cur0, plist0);
+      mplist_add (plist, Mplist, plist0);
+    }
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_conditional (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  MPlist *plist = mplist ();
+
+  mplist_add (plist, Msymbol, msymbol ("cond"));
+
+  for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
+    {
+      xmlNodePtr cur0 = cur->xmlChildrenNode;
+      MPlist *plist0 = mplist ();
+
+      decode_expr (doc, cur0, plist0);
+
+      while ((cur0 = cur0->next))
+       decode_saction (doc, cur0, plist0);
+
+      mplist_add (plist, Mplist, plist0);
+    }
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_action (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  MPlist *plist = mplist ();
+
+  if (xmlStrEqual (cur->name, (xmlChar *) "insert"))
+    decode_insert (doc, cur, parent);
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "delete-to-marker")
+          || xmlStrEqual (cur->name,
+                          (xmlChar *) "delete-to-character-position")
+          || xmlStrEqual (cur->name, (xmlChar *) "delete-n-characters"))
+    decode_delete (doc, cur, parent);
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "select"))
+    decode_select (doc, cur, parent);
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "show-candidates"))
+    {
+      mplist_add (plist, Msymbol, msymbol ("show"));
+      mplist_add (parent, Mplist, plist);
+    }
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "hide-candidates"))
+    {
+      mplist_add (plist, Msymbol, msymbol ("hide"));
+      mplist_add (parent, Mplist, plist);
+    }
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "move-to-marker")
+          || xmlStrEqual (cur->name, (xmlChar *) "move-to-character-position"))
+    decode_move (doc, cur, parent);
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "mark-current-position"))
+    decode_mark (doc, cur, parent);
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "pushback-n-events")
+          || xmlStrEqual (cur->name, (xmlChar *) "pushback-keyseq"))
+      decode_pushback (doc, cur, parent);
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "pop"))
+    {
+      mplist_add (plist, Msymbol, msymbol ((char *) cur->name));
+      mplist_add (parent, Mplist, plist);
+    }
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "undo"))
+    decode_undo (doc, cur, parent);
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "commit"))
+    {
+      mplist_add (plist, Msymbol, msymbol ((char *) cur->name));
+      mplist_add (parent, Mplist, plist);
+    }
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "unhandle"))
+    {
+      mplist_add (plist, Msymbol, msymbol ((char *) cur->name));
+      mplist_add (parent, Mplist, plist);
+    }
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "call"))
+    decode_call (doc, cur, parent);
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "set")
+          || xmlStrEqual (cur->name, (xmlChar *) "add")
+          || xmlStrEqual (cur->name, (xmlChar *) "sub")
+          || xmlStrEqual (cur->name, (xmlChar *) "mul")
+          || xmlStrEqual (cur->name, (xmlChar *) "div"))
+    decode_set (doc, cur, parent);
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "if"))
+    decode_if (doc, cur, parent);
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "conditional"))
+    decode_conditional (doc, cur, parent);
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "macro-reference"))
+    {
+      xmlChar *ptr = xmlGetProp (cur, (xmlChar *) "id");
+
+      /* +6 to skip "macro-" */
+      mplist_add (plist, Msymbol, msymbol ((char *) ptr + 6));
+      mplist_add (parent, Mplist, plist);
+      xmlFree (ptr);
+    }
+
+  else
+    {
+      /* never comes here */
+    }
+}
+
+static void
+decode_saction (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  if (xmlStrEqual (cur->name, (xmlChar *) "shift-to"))
+    {
+      xmlChar *ptr = xmlGetProp (cur, (xmlChar *) "id");
+      MPlist *plist = mplist ();
+
+      /* +6 to skip "state-" */
+      mplist_add (plist, Msymbol, msymbol ("shift"));
+      mplist_add (plist, Msymbol, msymbol ((char *) ptr + 6));
+      mplist_add (parent, Mplist, plist);
+      xmlFree (ptr);
+    }
+  else
+    decode_action (doc, cur, parent);
+}
+
+static void
+decode_description (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+
+  if (xmlStrEqual (cur->name, (xmlChar *) "get-text"))
+    {
+      MPlist *plist = mplist ();
+
+      ptr = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+      mplist_add (plist, Msymbol, msymbol ("_"));
+      mplist_add (plist, Mtext,
+                 mtext_from_data (ptr, xmlStrlen (ptr), MTEXT_FORMAT_UTF_8));
+      mplist_add (parent, Mplist, plist);
+    }
+  else
+    {
+      ptr = xmlNodeListGetString (doc, cur, 1);
+      mplist_add (parent, Mtext,
+                 mtext_from_data (ptr, xmlStrlen (ptr), MTEXT_FORMAT_UTF_8));
+    }
+}
+
+/***/
+
+static void
+decode_im_declaration (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+  MPlist *plist = mplist ();
+
+  /* tags */
+  mplist_add (plist, Msymbol, msymbol ("input-method"));
+
+  /* language */
+  cur = cur->xmlChildrenNode;
+  ptr = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+  mplist_add (plist, Msymbol, msymbol ((char *) ptr));
+  xmlFree (ptr);
+
+  /* name */
+  cur = cur->next;
+  ptr = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+  mplist_add (plist, Msymbol, msymbol ((char *) ptr));
+  xmlFree (ptr);
+  cur = cur->next;
+
+  /* extra-id */
+  if (cur && xmlStrEqual (cur->name, (xmlChar *) "extra-id"))
+    {
+      ptr = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+      mplist_add (plist, Msymbol, msymbol ((char *) ptr));
+      xmlFree (ptr);
+      cur = cur->next;
+    }
+
+  /* m17n-version */
+  if (cur && xmlStrEqual (cur->name, (xmlChar *) "m17n-version"))
+    {
+      MPlist *plist0 = mplist ();
+
+      ptr = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+      mplist_add (plist0, Msymbol, msymbol ("version"));
+      mplist_add (plist0, Mtext,
+                 mtext_from_data (ptr, xmlStrlen (ptr), MTEXT_FORMAT_UTF_8));
+      mplist_add (plist, Mplist, plist0);
+    }
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_im_description (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  MPlist *plist = mplist ();
+
+  mplist_add (plist, Msymbol, msymbol ("description"));
+  decode_description (doc, cur->xmlChildrenNode, plist);
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_title (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+  MPlist *plist = mplist ();
+
+  mplist_add (plist, Msymbol, msymbol ("title"));
+  mplist_add (plist, Mtext,
+             mtext_from_data (ptr, xmlStrlen (ptr), MTEXT_FORMAT_UTF_8));
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_variable (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+  MPlist *plist = mplist ();
+
+  ptr = xmlGetProp (cur, (xmlChar *) "id");
+  mplist_add (plist, Msymbol, msymbol ((char *) ptr));
+  xmlFree (ptr);
+
+  if ((cur = cur->xmlChildrenNode))
+    {
+      /* description */
+      if (xmlStrEqual (cur->name, (xmlChar *) "description"))
+       {
+         decode_description (doc, cur->xmlChildrenNode, plist);
+         cur = cur->next;
+       }
+      else
+       mplist_add (plist, Msymbol, Mnil);
+
+      /* value */
+      if (cur && xmlStrEqual (cur->name, (xmlChar *) "value"))
+       {
+         xmlChar *valuetype;
+
+         ptr = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+         valuetype = xmlGetProp (cur, (xmlChar *) "type");
+         if (xmlStrEqual (valuetype, (xmlChar *) "string"))
+           mplist_add (plist, Mtext,
+                       mtext_from_data (ptr, xmlStrlen (ptr),
+                                        MTEXT_FORMAT_UTF_8));
+         else if (xmlStrEqual (valuetype, (xmlChar *) "symbol"))
+           {
+             mplist_add (plist, Msymbol, msymbol ((char *) ptr));
+             xmlFree (ptr);
+           }
+         else                  /* integer */
+           {
+             decode_integer (ptr, plist);
+             xmlFree (ptr);
+           }
+         xmlFree (valuetype);
+         cur = cur->next;
+       }
+
+      /* variable-value-candidate */
+      if (cur)
+       for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
+         {
+           if (xmlStrEqual (cur->name, (xmlChar *) "c-value"))
+             {
+               xmlChar *valuetype;
+
+               ptr = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+               valuetype = xmlGetProp (cur, (xmlChar *) "type");
+               if (xmlStrEqual (valuetype, (xmlChar *) "string"))
+                 mplist_add (plist, Mtext,
+                             mtext_from_data (ptr, xmlStrlen (ptr),
+                                              MTEXT_FORMAT_UTF_8));
+               else if (xmlStrEqual (valuetype, (xmlChar *) "symbol"))
+                 {
+                   mplist_add (plist, Msymbol, msymbol ((char *) ptr));
+                   xmlFree (ptr);
+                 }
+               else            /* integer */
+                 {
+                   decode_integer (ptr, plist);
+                   xmlFree (ptr);
+                 }
+               xmlFree (valuetype);
+             }
+           else                        /* c-range */
+             {
+               MPlist *range = mplist ();
+
+               ptr = xmlGetProp (cur, (xmlChar *) "from");
+               decode_integer (ptr, range);
+               xmlFree (ptr);
+               ptr = xmlGetProp (cur, (xmlChar *) "to");
+               decode_integer (ptr, range);
+               xmlFree (ptr);
+               mplist_add (plist, Mplist, range);
+             }
+         }
+    }
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_variable_list (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  MPlist *plist = mplist ();
+
+  mplist_add (plist, Msymbol, msymbol ("variable"));
+
+  for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
+    decode_variable (doc, cur, plist);
+
+  mplist_add (parent, Mplist, plist);
+}
+
+void
+decode_command (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+  MPlist *plist = mplist ();
+
+  ptr = xmlGetProp (cur, (xmlChar *) "id");
+  /* +8 to skip "command-" */
+  mplist_add (plist, Msymbol, msymbol ((char *) ptr + 8));
+  xmlFree (ptr);
+
+  if ((cur = cur->xmlChildrenNode))
+    {
+      /* description */
+      if (xmlStrEqual (cur->name, (xmlChar *) "description"))
+       {
+         decode_description (doc, cur->xmlChildrenNode, plist);
+         cur = cur->next;
+       }
+      else
+       mplist_add (plist, Msymbol, Mnil);
+
+      /* keyseq */
+      for (; cur; cur = cur->next)
+       decode_keyseq (doc, cur, plist);
+    }
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_command_list (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  MPlist *plist = mplist ();
+
+  mplist_add (plist, Msymbol, msymbol ("command"));
+
+  for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
+    decode_command (doc, cur, plist);
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_module (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+  MPlist *plist = mplist ();
+
+  ptr = xmlGetProp (cur, (xmlChar *) "id");
+  /* +7 to skip "module-" */
+  mplist_add (plist, Msymbol, msymbol ((char *) ptr + 7));
+  xmlFree (ptr);
+
+  for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
+    {
+      ptr = xmlGetProp (cur, (xmlChar *) "id");
+      /* +9 to skip "function" */
+      mplist_add (plist, Msymbol, msymbol ((char *) ptr + 9));
+      xmlFree (ptr);
+    }
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_module_list (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  MPlist *plist = mplist ();
+
+  mplist_add (plist, Msymbol, msymbol ("module"));
+
+  for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
+    decode_module (doc, cur, plist);
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_macro (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+  MPlist *plist = mplist ();
+
+  ptr = xmlGetProp (cur, (xmlChar *) "id");
+  /* +6 to skip "macro-" */
+  mplist_add (plist, Msymbol, msymbol ((char *) ptr + 6));
+  xmlFree (ptr);
+
+  for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
+    decode_action (doc, cur, plist);
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_macro_list (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  MPlist *plist = mplist ();
+
+  mplist_add (plist, Msymbol, msymbol ("macro"));
+
+  for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
+    decode_macro (doc, cur, plist);
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_rule (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  MPlist *plist = mplist ();
+
+  cur = cur->xmlChildrenNode;
+  decode_keyseq (doc, cur, plist);
+  cur = cur->next;
+
+  for (; cur; cur = cur->next)
+    decode_action (doc, cur, plist);
+
+  mplist_add (parent, Mplist, plist);
+}      
+
+static void
+decode_map (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+  MPlist *plist = mplist ();
+
+  ptr = xmlGetProp (cur, (xmlChar *) "id");
+  /* +4 to skip "map-" */
+  mplist_add (plist, Msymbol, msymbol ((char *) ptr + 4));
+  xmlFree (ptr);
+
+  for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
+    decode_rule (doc, cur, plist);
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_map_list (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  MPlist *plist = mplist ();
+
+  mplist_add (plist, Msymbol, msymbol ("map"));
+  for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
+    decode_map (doc, cur, plist);
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_branch (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+  MPlist *plist = mplist ();
+
+  if (xmlStrEqual (cur->name, (xmlChar *) "state-hook"))
+    mplist_add (plist, Msymbol, Mt);
+  else if (xmlStrEqual (cur->name, (xmlChar *) "catch-all-branch"))
+    mplist_add (plist, Msymbol, Mnil);
+  else         /* branch */
+    {
+      ptr = xmlGetProp (cur, (xmlChar *) "branch-selecting-map");
+      /* +4 to skip "map-" */
+      mplist_add (plist, Msymbol, msymbol ((char *) ptr + 4));
+      xmlFree (ptr);
+    }
+
+  for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
+    decode_saction (doc, cur, plist);
+
+  if (mplist_length (plist))
+    mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_state (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+  MPlist *plist = mplist ();
+
+  ptr = xmlGetProp (cur, (xmlChar *) "id");
+  /* +6 to skip "state-" */
+  mplist_add (plist, Msymbol, msymbol ((char *) ptr + 6));
+  xmlFree (ptr);
+
+  for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
+    {
+      if (xmlStrEqual (cur->name, (xmlChar *) "state-title-text"))
+       {
+         ptr = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+         mplist_add (plist, Mtext, mtext_from_data (ptr, xmlStrlen (ptr),
+                                                    MTEXT_FORMAT_UTF_8));
+       }
+      else
+       decode_branch (doc, cur, plist);
+    }
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static void
+decode_state_list (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  MPlist *plist = mplist ();
+
+  mplist_add (plist, Msymbol, msymbol ("state"));
+
+  for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
+    decode_state (doc, cur, plist);
+
+  mplist_add (parent, Mplist, plist);
+}
+
+static int
+rewrite_include (xmlNodePtr cur)
+{
+  xmlChar *ptr, *suffix, *filename, *fullname, *newvalue;
+  int len;
+
+  ptr = xmlGetProp (cur, (xmlChar *) "href");
+  suffix = (xmlChar *) xmlStrstr (ptr, (xmlChar *) "#xmlns");
+
+  len = suffix - ptr;
+  filename = malloc (len + 1);
+  filename[0] = '\0';
+  xmlStrncat (filename, ptr, len);
+  fullname = (xmlChar *) mdatabase__find_file ((char *) filename);
+  if (! fullname)
+    {
+      xmlFree (ptr);
+      free (filename);
+      return -1;
+    }
+  else
+    {
+      newvalue = xmlStrncatNew (fullname, suffix, -1);
+      xmlSetProp (cur, (xmlChar *) "href", newvalue);
+      xmlFree (ptr);
+      free (filename);
+      free (fullname);
+      xmlFree (newvalue);
+      return 0;
+    }
+}
+
+static int
+prepare_include (xmlNodePtr cur)
+{
+  xmlNodePtr cur0;
+
+  for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
+    if (xmlStrEqual (cur->name, (xmlChar *) "macro-list")
+       || xmlStrEqual (cur->name, (xmlChar *) "map-list")
+       || xmlStrEqual (cur->name, (xmlChar *) "state-list"))
+      for (cur0 = cur->xmlChildrenNode; cur0; cur0 = cur0->next)
+       if (xmlStrEqual (cur0->name, (xmlChar *) "include"))
+         if (rewrite_include (cur0) == -1)
+           return -1;
+  return 0;
+}
+
+MPlist *
+minput__load_xml (MDatabaseInfo *db_info, char *filename)
+{
+  xmlDocPtr doc;
+  xmlNodePtr cur;
+  MPlist *xml = mplist ();
+
+  doc = xmlReadFile (filename, NULL, XML_PARSE_NOENT | XML_PARSE_NOBLANKS);
+  if (! doc)
+    return NULL;
+
+  cur = xmlDocGetRootElement (doc);
+  if (! cur)
+    {
+      xmlFreeDoc (doc);
+      return NULL;
+    }
+
+  if (xmlStrcmp (cur->name, (xmlChar *) "input-method"))
+    {
+      xmlFreeDoc (doc);
+      return NULL;
+    }
+
+  if (prepare_include (cur) == -1)
+    {
+      xmlFreeDoc (doc);
+      return NULL;
+    }
+
+  xmlXIncludeProcessFlags (doc, XML_PARSE_NOENT | XML_PARSE_NOBLANKS
+                          | XML_PARSE_NOXINCNODE);
+  if (! mdatabase__validate (doc, db_info))
+    {
+      xmlFreeDoc (doc);
+      MERROR (MERROR_IM, NULL);
+    }
+
+  cur = xmlDocGetRootElement (doc)->xmlChildrenNode;
+  decode_im_declaration (doc, cur, xml);
+  cur = cur->next;
+
+  if (cur && xmlStrEqual (cur->name, (xmlChar *) "description"))
+    {
+      decode_im_description (doc, cur, xml);
+      cur = cur->next;
+    }
+
+  if (cur && xmlStrEqual (cur->name, (xmlChar *) "title"))
+    {
+      decode_title (doc, cur, xml);
+      cur = cur->next;
+    }
+
+  if (cur && xmlStrEqual (cur->name, (xmlChar *) "variable-list"))
+    {
+      decode_variable_list (doc, cur, xml);
+      cur = cur->next;
+    }
+
+  if (cur && xmlStrEqual (cur->name, (xmlChar *) "command-list"))
+    {
+      decode_command_list (doc, cur, xml);
+      cur = cur->next;
+    }
+
+  if (cur && xmlStrEqual (cur->name, (xmlChar *) "module-list"))
+    {
+      decode_module_list (doc, cur, xml);
+      cur = cur->next;
+    }
+
+  if (cur && xmlStrEqual (cur->name, (xmlChar *) "macro-list"))
+    {
+      decode_macro_list (doc, cur, xml);
+      cur = cur->next;
+    }
+
+  if (cur && xmlStrEqual (cur->name, (xmlChar *) "map-list"))
+    {
+      decode_map_list (doc, cur, xml);
+      cur = cur->next;
+    }
+
+  if (cur && xmlStrEqual (cur->name, (xmlChar *) "state-list"))
+    {
+      decode_state_list (doc, cur, xml);
+      cur = cur->next;
+    }
+
+  xmlFreeDoc (doc);
+  return xml;
+}
index 631bb84..5123eac 100644 (file)
@@ -1,5 +1,5 @@
 /* input.c -- input method module.
-   Copyright (C) 2003, 2004, 2005, 2006
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H15PRO112
 
@@ -270,7 +270,8 @@ static int update_global_info (void);
 static int update_custom_info (void);
 static MInputMethodInfo *get_im_info (MSymbol, MSymbol, MSymbol, MSymbol);
 
-static MDatabaseLoaderXML load_xml_input_method;
+extern MPlist minput__load_xml (MDatabaseInfo *, char *);
+/*extern MDatabaseLoaderXML minput__load_xml;*/
 
 \f
 void
@@ -504,7 +505,7 @@ fully_initialize ()
 
     tags[0] = Minput_method;
     tags[1] = tags[2] = tags[3] = Mnil;
-    mdatabase__register_xml_loader (tags, load_xml_input_method);
+    mdatabase__register_xml_loader (tags, minput__load_xml);
   }
 
   im_info_list = mplist ();
@@ -1492,9 +1493,10 @@ update_custom_info (void)
          || (mtext_nbytes (custom_dir_info->filename) + strlen (CUSTOM_FILE)
              > PATH_MAX - 1))
        return -1;
-      dirname = mtext_data (custom_dir_info->filename, NULL, &len, NULL, NULL);
+      dirname = mtext_data (custom_dir_info->dirname, NULL, &len, NULL, NULL);
       strcpy (custom_path, dirname);
-      custom_path[len++] = PATH_SEPARATOR;
+      if (custom_path[len - 1] != PATH_SEPARATOR)
+       custom_path[len++] = PATH_SEPARATOR;
       strcpy (custom_path + len, CUSTOM_FILE);
       im_custom_mdb = mdatabase_define (Minput_method, Mt, Mnil, Mconfig,
                                        NULL, custom_path);
index be42e1d..38cab18 100644 (file)
@@ -177,6 +177,31 @@ get_byte (MStream *st)
 
 #define UNGETC(c, st) (--((st)->p))
 
+static void
+init_stream (MStream *st, FILE *fp, unsigned char *str, int n)
+{
+  st->eof = 0;
+  st->fp = fp;
+  if (fp)
+    {
+      int c;
+
+      st->fp = fp;
+      st->p = st->pend = st->buffer;
+      if ((c = GETC (st)) != 0xEF)
+       st->p = st->buffer;
+      else if ((c = GETC (st)) != 0xBB)
+       st->p = st->buffer;
+      else if ((c = GETC (st)) != 0xBF)
+       st->p = st->buffer;
+    }
+  else
+    {
+      st->p = str;
+      st->pend = str + n;
+    }
+}
+
 /** Mapping table for reading a number.  Hexadecimal chars
     (0..9,A..F,a..F) are mapped to the corresponding numbers.
     Apostrophe (code 39) is mapped to 254.  All the other bytes are
@@ -800,9 +825,7 @@ mplist__from_file (FILE *fp, MPlist *keys)
   MPlist *plist, *pl;
   MStream st;
 
-  st.fp = fp;
-  st.eof = 0;
-  st.p = st.pend = st.buffer;
+  init_stream (&st, fp, NULL, 0);
   MPLIST_NEW (plist);
   pl = plist;
   while ((pl = read_element (pl, &st, keys)));
@@ -848,10 +871,7 @@ mplist__from_string (unsigned char *str, int n)
   MPlist *plist, *pl;
   MStream st;
 
-  st.fp = NULL;
-  st.eof = 0;
-  st.p = str;
-  st.pend = str + n;
+  init_stream (&st, NULL, str, n);
   MPLIST_NEW (plist);
   pl = plist;
   while ((pl = read_element (pl, &st, NULL)));