+ Lisp_Byte_Table *cte;
+
+ cte = alloc_lcrecord_type (Lisp_Byte_Table, &lrecord_byte_table);
+
+ for (i = 0; i < 256; i++)
+ cte->property[i] = initval;
+
+ XSETBYTE_TABLE (obj, cte);
+ return obj;
+}
+
+static int
+byte_table_same_value_p (Lisp_Object obj)
+{
+ Lisp_Byte_Table *bte = XBYTE_TABLE (obj);
+ Lisp_Object v0 = bte->property[0];
+ int i;
+
+ for (i = 1; i < 256; i++)
+ {
+ if (!internal_equal (bte->property[i], v0, 0))
+ return 0;
+ }
+ return -1;
+}
+
+
+Lisp_Object get_byte_table (Lisp_Object table, unsigned char idx);
+Lisp_Object put_byte_table (Lisp_Object table, unsigned char idx,
+ Lisp_Object value);
+
+Lisp_Object
+get_byte_table (Lisp_Object table, unsigned char idx)
+{
+ if (UINT8_BYTE_TABLE_P (table))
+ return UINT8_DECODE (XUINT8_BYTE_TABLE(table)->property[idx]);
+ else if (UINT16_BYTE_TABLE_P (table))
+ return UINT16_DECODE (XUINT16_BYTE_TABLE(table)->property[idx]);
+ else if (BYTE_TABLE_P (table))
+ return XBYTE_TABLE(table)->property[idx];
+ else
+ return table;
+}
+
+Lisp_Object
+put_byte_table (Lisp_Object table, unsigned char idx, Lisp_Object value)
+{
+ if (UINT8_BYTE_TABLE_P (table))
+ {
+ if (UINT8_VALUE_P (value))
+ {
+ XUINT8_BYTE_TABLE(table)->property[idx] = UINT8_ENCODE (value);
+ if (!UINT8_BYTE_TABLE_P (value) &&
+ !UINT16_BYTE_TABLE_P (value) && !BYTE_TABLE_P (value)
+ && uint8_byte_table_same_value_p (table))
+ {
+ return value;
+ }
+ }
+ else if (UINT16_VALUE_P (value))
+ {
+ Lisp_Object new = expand_uint8_byte_table_to_uint16 (table);
+
+ XUINT16_BYTE_TABLE(new)->property[idx] = UINT16_ENCODE (value);
+ return new;
+ }
+ else
+ {
+ Lisp_Object new = make_byte_table (Qnil);
+ int i;
+
+ for (i = 0; i < 256; i++)
+ {
+ XBYTE_TABLE(new)->property[i]
+ = UINT8_DECODE (XUINT8_BYTE_TABLE(table)->property[i]);
+ }
+ XBYTE_TABLE(new)->property[idx] = value;
+ return new;
+ }
+ }
+ else if (UINT16_BYTE_TABLE_P (table))
+ {
+ if (UINT16_VALUE_P (value))
+ {
+ XUINT16_BYTE_TABLE(table)->property[idx] = UINT16_ENCODE (value);
+ if (!UINT8_BYTE_TABLE_P (value) &&
+ !UINT16_BYTE_TABLE_P (value) && !BYTE_TABLE_P (value)
+ && uint16_byte_table_same_value_p (table))
+ {
+ return value;
+ }
+ }
+ else
+ {
+ Lisp_Object new = make_byte_table (Qnil);
+ int i;
+
+ for (i = 0; i < 256; i++)
+ {
+ XBYTE_TABLE(new)->property[i]
+ = UINT16_DECODE (XUINT16_BYTE_TABLE(table)->property[i]);
+ }
+ XBYTE_TABLE(new)->property[idx] = value;
+ return new;
+ }
+ }
+ else if (BYTE_TABLE_P (table))
+ {
+ XBYTE_TABLE(table)->property[idx] = value;
+ if (!UINT8_BYTE_TABLE_P (value) &&
+ !UINT16_BYTE_TABLE_P (value) && !BYTE_TABLE_P (value)
+ && byte_table_same_value_p (table))
+ {
+ return value;
+ }
+ }
+ else if (!internal_equal (table, value, 0))
+ {
+ if (UINT8_VALUE_P (table) && UINT8_VALUE_P (value))
+ {
+ table = make_uint8_byte_table (UINT8_ENCODE (table));
+ XUINT8_BYTE_TABLE(table)->property[idx] = UINT8_ENCODE (value);
+ }
+ else if (UINT16_VALUE_P (table) && UINT16_VALUE_P (value))
+ {
+ table = make_uint16_byte_table (UINT16_ENCODE (table));
+ XUINT16_BYTE_TABLE(table)->property[idx] = UINT16_ENCODE (value);
+ }
+ else
+ {
+ table = make_byte_table (table);
+ XBYTE_TABLE(table)->property[idx] = value;
+ }
+ }
+ return table;
+}
+
+static Lisp_Object
+mark_char_id_table (Lisp_Object obj)
+{
+ Lisp_Char_ID_Table *cte = XCHAR_ID_TABLE (obj);
+
+ return cte->table;
+}
+
+static void
+print_char_id_table (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
+{
+ Lisp_Object table = XCHAR_ID_TABLE (obj)->table;
+ int i;
+ struct gcpro gcpro1, gcpro2;
+ GCPRO2 (obj, printcharfun);
+
+ write_c_string ("#<char-id-table ", printcharfun);
+ for (i = 0; i < 256; i++)
+ {
+ Lisp_Object elt = get_byte_table (table, i);
+ if (i != 0) write_c_string ("\n ", printcharfun);
+ if (EQ (elt, Qunbound))
+ write_c_string ("void", printcharfun);
+ else
+ print_internal (elt, printcharfun, escapeflag);
+ }
+ UNGCPRO;
+ write_c_string (">", printcharfun);
+}
+
+static int
+char_id_table_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
+{
+ Lisp_Object table1 = XCHAR_ID_TABLE (obj1)->table;
+ Lisp_Object table2 = XCHAR_ID_TABLE (obj2)->table;
+ int i;
+
+ for (i = 0; i < 256; i++)
+ {
+ if (!internal_equal (get_byte_table (table1, i),
+ get_byte_table (table2, i), 0))
+ return 0;
+ }
+ return -1;
+}
+
+static unsigned long
+char_id_table_hash (Lisp_Object obj, int depth)
+{
+ Lisp_Char_ID_Table *cte = XCHAR_ID_TABLE (obj);
+
+ return char_id_table_hash (cte->table, depth + 1);
+}
+
+static const struct lrecord_description char_id_table_description[] = {
+ { XD_LISP_OBJECT, offsetof(Lisp_Char_ID_Table, table) },
+ { XD_END }
+};
+
+DEFINE_LRECORD_IMPLEMENTATION ("char-id-table", char_id_table,
+ mark_char_id_table,
+ print_char_id_table,
+ 0, char_id_table_equal,
+ char_id_table_hash,
+ char_id_table_description,
+ Lisp_Char_ID_Table);
+
+static Lisp_Object
+make_char_id_table (Lisp_Object initval)
+{
+ Lisp_Object obj;
+ Lisp_Char_ID_Table *cte;
+
+ cte = alloc_lcrecord_type (Lisp_Char_ID_Table, &lrecord_char_id_table);
+
+ cte->table = make_byte_table (initval);
+
+ XSETCHAR_ID_TABLE (obj, cte);
+ return obj;
+}
+
+
+Lisp_Object
+get_char_id_table (Emchar ch, Lisp_Object table)
+{
+ unsigned int code = ch;
+
+ return
+ get_byte_table
+ (get_byte_table
+ (get_byte_table
+ (get_byte_table
+ (XCHAR_ID_TABLE (table)->table,
+ (unsigned char)(code >> 24)),
+ (unsigned char) (code >> 16)),
+ (unsigned char) (code >> 8)),
+ (unsigned char) code);
+}
+
+void put_char_id_table (Emchar ch, Lisp_Object value, Lisp_Object table);
+void
+put_char_id_table (Emchar ch, Lisp_Object value, Lisp_Object table)
+{
+ unsigned int code = ch;
+ Lisp_Object table1, table2, table3, table4;
+
+ table1 = XCHAR_ID_TABLE (table)->table;
+ table2 = get_byte_table (table1, (unsigned char)(code >> 24));
+ table3 = get_byte_table (table2, (unsigned char)(code >> 16));
+ table4 = get_byte_table (table3, (unsigned char)(code >> 8));
+
+ table4 = put_byte_table (table4, (unsigned char)code, value);
+ table3 = put_byte_table (table3, (unsigned char)(code >> 8), table4);
+ table2 = put_byte_table (table2, (unsigned char)(code >> 16), table3);
+ XCHAR_ID_TABLE (table)->table
+ = put_byte_table (table1, (unsigned char)(code >> 24), table2);
+}