--- /dev/null
+#include "chise.h"
+
+#define xzero(lvalue) ((void) memset (&(lvalue), '\0', sizeof (lvalue)))
+
+
+int
+chise_open_data_source (CHISE_DS *ds, CHISE_DS_Type type, char *location)
+{
+ ds->type = type;
+ ds->location = location;
+ return 0;
+}
+
+int
+chise_close_data_source (CHISE_DS *ds)
+{
+ ds->type = CHISE_DS_NONE;
+ ds->location = NULL;
+ return 0;
+}
+
+
+int
+chise_open_decoding_table (CHISE_Decoding_Table **db,
+ CHISE_DS *ds, const char *ccs,
+ DBTYPE real_subtype,
+ u_int32_t accessmask, int modemask)
+{
+ return
+ chise_open_attribute_table (db, ds->location,
+ ccs, "system-char-id",
+ real_subtype, accessmask, modemask);
+}
+
+int
+chise_close_decoding_table (CHISE_Decoding_Table *db)
+{
+ if (db)
+ return chise_close_attribute_table (db);
+ return -1;
+}
+
+CHISE_Char_ID
+chise_dt_get_char (CHISE_Decoding_Table *db, int code_point)
+{
+ CHISE_Value valdatum;
+ int status = 0;
+ char key_buf[16];
+
+ sprintf(key_buf, "%d", code_point);
+ status = chise_get_attribute_table (db, key_buf, &valdatum);
+ if (!status)
+ {
+ unsigned char *str
+ = (unsigned char *)chise_value_to_c_string (&valdatum);
+ int len = strlen (str);
+ int i;
+
+ if ( (len >= 2) && (str[0] == '?') )
+ {
+ unsigned char c = str[1];
+ int counter;
+ CHISE_Char_ID cid;
+
+ if ( c < 0xC0 )
+ {
+ cid = c;
+ counter = 0;
+ }
+ else if ( c < 0xE0 )
+ {
+ cid = c & 0x1f;
+ counter = 1;
+ }
+ else if ( c < 0xF0 )
+ {
+ cid = c & 0x0f;
+ counter = 2;
+ }
+ else if ( c < 0xF8 )
+ {
+ cid = c & 0x07;
+ counter = 3;
+ }
+ else if ( c < 0xFC )
+ {
+ cid = c & 0x03;
+ counter = 4;
+ }
+ else
+ {
+ cid = c & 0x01;
+ counter = 5;
+ }
+
+ if (counter + 2 <= len)
+ {
+ int i;
+
+ for (i = 0; i < counter; i++)
+ cid = (cid << 6) | (str[i + 2] & 0x3F);
+ return cid;
+ }
+ }
+ }
+ return -1;
+}
+
+
+
+int
+chise_open_feature_table (CHISE_Feature_Table **db,
+ CHISE_DS *ds, const char *feature,
+ DBTYPE real_subtype,
+ u_int32_t accessmask, int modemask)
+{
+ return
+ chise_open_attribute_table (db, ds->location,
+ "system-char-id", feature,
+ real_subtype, accessmask, modemask);
+}
+
+int
+chise_close_feature_table (CHISE_Feature_Table *db)
+{
+ if (db)
+ return chise_close_attribute_table (db);
+ return -1;
+}
+
+int chise_ft_get_value (CHISE_Feature_Table *db,
+ CHISE_Char_ID cid, CHISE_Value *valdatum)
+{
+ unsigned char key_buf[8];
+
+ key_buf[0] = '?';
+ if (cid <= 0x7f)
+ {
+ key_buf[1] = cid;
+ key_buf[2] = '\0';
+ }
+ else if (cid <= 0x7ff)
+ {
+ key_buf[1] = (cid >> 6) | 0xc0;
+ key_buf[2] = (cid & 0x3f) | 0x80;
+ key_buf[3] = '\0';
+ }
+ else if (cid <= 0xffff)
+ {
+ key_buf[1] = (cid >> 12) | 0xe0;
+ key_buf[2]= ((cid >> 6) & 0x3f) | 0x80;
+ key_buf[3]= (cid & 0x3f) | 0x80;
+ key_buf[4] = '\0';
+ }
+ else if (cid <= 0x1fffff)
+ {
+ key_buf[1]= (cid >> 18) | 0xf0;
+ key_buf[2]= ((cid >> 12) & 0x3f) | 0x80;
+ key_buf[3]= ((cid >> 6) & 0x3f) | 0x80;
+ key_buf[4]= (cid & 0x3f) | 0x80;
+ key_buf[5] = '\0';
+ }
+ else if (cid <= 0x3ffffff)
+ {
+ key_buf[1]= (cid >> 24) | 0xf8;
+ key_buf[2]= ((cid >> 18) & 0x3f) | 0x80;
+ key_buf[3]= ((cid >> 12) & 0x3f) | 0x80;
+ key_buf[4]= ((cid >> 6) & 0x3f) | 0x80;
+ key_buf[5]= (cid & 0x3f) | 0x80;
+ key_buf[6] = '\0';
+ }
+ else
+ {
+ key_buf[1]= (cid >> 30) | 0xfc;
+ key_buf[2]= ((cid >> 24) & 0x3f) | 0x80;
+ key_buf[3]= ((cid >> 18) & 0x3f) | 0x80;
+ key_buf[4]= ((cid >> 12) & 0x3f) | 0x80;
+ key_buf[5]= ((cid >> 6) & 0x3f) | 0x80;
+ key_buf[6]= (cid & 0x3f) | 0x80;
+ key_buf[7] = '\0';
+ }
+ return
+ chise_get_attribute_table (db, key_buf, valdatum);
+}
+
+
+int
+chise_open_attribute_table (CHISE_Attribute_Table **db,
+ const char *db_dir,
+ const char *encoding, const char *feature,
+ DBTYPE real_subtype,
+ u_int32_t accessmask, int modemask)
+{
+ DB* dbase;
+ int status;
+ int len;
+ int size;
+ char *db_file_name;
+
+ status = db_create (&dbase, NULL, 0);
+ if (status)
+ return -1;
+
+ len = strlen (db_dir);
+ size = len + strlen (encoding) + strlen (feature) + 4;
+ db_file_name = alloca (size);
+ strcpy (db_file_name, db_dir);
+ if (db_file_name[len - 1] != '/')
+ {
+ db_file_name[len++] = '/';
+ db_file_name[len] = '\0';
+ }
+ strcat (db_file_name, encoding);
+ strcat (db_file_name, "/");
+ strcat (db_file_name, feature);
+ status = dbase->open (dbase, db_file_name, NULL,
+ real_subtype, accessmask, modemask);
+ if (status)
+ {
+ dbase->close (dbase, 0);
+ return -1;
+ }
+ *db = dbase;
+ return 0;
+}
+
+int
+chise_close_attribute_table (CHISE_Attribute_Table *db)
+{
+ if (db)
+ {
+ db->sync (db, 0);
+ db->close (db, 0);
+ }
+ return 0;
+}
+
+int
+chise_get_attribute_table (CHISE_Attribute_Table *db,
+ char *key, CHISE_Value *valdatum)
+{
+ DBT keydatum;
+ int status = 0;
+
+ /* DB Version 2 requires DBT's to be zeroed before use. */
+ xzero (keydatum);
+ xzero (*valdatum);
+
+ keydatum.data = key;
+ keydatum.size = strlen (key);
+
+ status = db->get (db, NULL, &keydatum, valdatum, 0);
+ return status;
+}
--- /dev/null
+#ifndef _CHISE_H
+
+#include <db.h>
+#include <errno.h>
+
+
+typedef enum CHISE_DS_Type
+{
+ CHISE_DS_NONE,
+ CHISE_DS_Berkeley_DB
+} CHISE_DS_Type;
+
+typedef struct CHISE_DS
+{
+ CHISE_DS_Type type;
+ char *location;
+} CHISE_DS;
+
+int chise_open_data_source (CHISE_DS *ds, CHISE_DS_Type type,
+ char *location);
+
+int chise_close_data_source (CHISE_DS *ds);
+
+
+typedef int CHISE_Char_ID;
+
+
+typedef DBT CHISE_Value;
+
+static inline int
+chise_value_size (const CHISE_Value *s)
+{
+ return s->size;
+}
+
+static inline char *
+chise_value_to_c_string (const CHISE_Value *s)
+{
+ return s->data;
+}
+
+
+typedef DB CHISE_Attribute_Table;
+
+
+typedef CHISE_Attribute_Table CHISE_Decoding_Table;
+
+int chise_open_decoding_table (CHISE_Decoding_Table **db,
+ CHISE_DS *ds, const char *ccs,
+ DBTYPE real_subtype,
+ u_int32_t accessmask, int modemask);
+
+int chise_close_decoding_table (CHISE_Decoding_Table *db);
+
+CHISE_Char_ID chise_dt_get_char (CHISE_Decoding_Table *db, int code_point);
+
+
+typedef CHISE_Attribute_Table CHISE_Feature_Table;
+
+int chise_open_feature_table (CHISE_Feature_Table **db,
+ CHISE_DS *ds, const char *feature,
+ DBTYPE real_subtype,
+ u_int32_t accessmask, int modemask);
+
+int chise_close_feature_table (CHISE_Feature_Table *db);
+
+int chise_ft_get_value (CHISE_Feature_Table *db,
+ CHISE_Char_ID cid, CHISE_Value *valdatum);
+
+
+
+CHISE_Char_ID chise_decode_char (CHISE_DS *ds, char *ccs, int code_point);
+
+int chise_get_feature (CHISE_DS *ds, CHISE_Char_ID cid,
+ char *key, CHISE_Value *valdatum);
+
+
+int chise_open_attribute_table (CHISE_Attribute_Table **db,
+ const char *db_dir,
+ const char *encoding, const char *feature,
+ DBTYPE real_subtype,
+ u_int32_t accessmask, int modemask);
+
+int chise_close_attribute_table (CHISE_Attribute_Table *db);
+
+int chise_get_attribute_table (CHISE_Attribute_Table *db,
+ char *key, CHISE_Value *valdatum);
+
+#endif /* !_CHISE_H */
--- /dev/null
+#include "chise.h"
+
+#define xzero(lvalue) ((void) memset (&(lvalue), '\0', sizeof (lvalue)))
+
+char db_dir[] = "/usr/local/lib/xemacs-21.4.10/i586-pc-linux/char-db";
+
+int
+main (int argc, char* argv[])
+{
+ CHISE_DS ds;
+ CHISE_Decoding_Table *dt;
+ CHISE_Feature_Table *ft;
+ int modemask;
+ int accessmask = 0;
+ DBTYPE real_subtype;
+ int status;
+ CHISE_Char_ID char_id;
+ CHISE_Value value;
+
+ status = chise_open_data_source (&ds, CHISE_DS_Berkeley_DB, db_dir);
+ if (status)
+ {
+ chise_close_data_source (&ds);
+ return -1;
+ }
+
+ modemask = 0755; /* rwxr-xr-x */
+
+ real_subtype = DB_HASH;
+ accessmask = DB_RDONLY;
+
+ status = chise_open_decoding_table (&dt, &ds,
+ "ideograph-daikanwa",
+ real_subtype, accessmask, modemask);
+ if (status)
+ {
+ chise_close_decoding_table (dt);
+ chise_close_data_source (&ds);
+ return -1;
+ }
+
+ char_id = chise_dt_get_char (dt, 20);
+ chise_close_decoding_table (dt);
+
+ status = chise_open_feature_table (&ft, &ds,
+ "ideographic-structure",
+ real_subtype, accessmask, modemask);
+ if (status)
+ {
+ chise_close_feature_table (ft);
+ chise_close_data_source (&ds);
+ return -1;
+ }
+
+ status = chise_ft_get_value (ft, char_id, &value);
+ if (!status)
+ printf ("#x%X => %s\n", char_id, chise_value_to_c_string(&value));
+ else
+ printf ("#x%X (%d)\n", char_id, status);
+
+ chise_close_feature_table (ft);
+ chise_close_data_source (&ds);
+}