1 /* chartab.c -- char-table support
2 Copyright (C) 2001, 2002
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H13PRO009
6 This file is part of GNU Emacs.
8 GNU Emacs is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
25 #include <character.h>
31 /* Number of elements in Nth level char-table. */
32 const int chartab_size
[4] =
33 { (1 << CHARTAB_SIZE_BITS_0
),
34 (1 << CHARTAB_SIZE_BITS_1
),
35 (1 << CHARTAB_SIZE_BITS_2
),
36 (1 << CHARTAB_SIZE_BITS_3
) };
38 /* Number of characters each element of Nth level char-table
40 const int chartab_chars
[4] =
41 { (1 << (CHARTAB_SIZE_BITS_1
+ CHARTAB_SIZE_BITS_2
+ CHARTAB_SIZE_BITS_3
)),
42 (1 << (CHARTAB_SIZE_BITS_2
+ CHARTAB_SIZE_BITS_3
)),
43 (1 << CHARTAB_SIZE_BITS_3
),
46 /* Number of characters (in bits) each element of Nth level char-table
48 const int chartab_bits
[4] =
49 { (CHARTAB_SIZE_BITS_1
+ CHARTAB_SIZE_BITS_2
+ CHARTAB_SIZE_BITS_3
),
50 (CHARTAB_SIZE_BITS_2
+ CHARTAB_SIZE_BITS_3
),
54 #define CHARTAB_IDX(c, depth, min_char) \
55 (((c) - (min_char)) >> chartab_bits[(depth)])
58 DEFUN ("make-char-table", Fmake_char_table
, Smake_char_table
, 1, 2, 0,
59 doc
: /* Return a newly created char-table.
60 Each element is initialized to INIT, which defaults to nil.
62 Optional second argument PURPOSE, if non-nil, should be a symbol
63 which has a `char-table-extra-slots' property.
64 The property's value should be an integer between 0 and 10
65 that specify how many extra slots the char-table has.
66 By default, the char-table has no extra slot. */)
68 register Lisp_Object purpose
, init
;
75 CHECK_SYMBOL (purpose
);
78 n
= Fget (purpose
, Qchar_table_extra_slots
);
81 if (XINT (n
) < 0 || XINT (n
) > 10)
82 args_out_of_range (n
, Qnil
);
87 size
= VECSIZE (struct Lisp_Char_Table
) - 1 + n_extras
;
88 vector
= Fmake_vector (make_number (size
), init
);
89 XCHAR_TABLE (vector
)->parent
= Qnil
;
90 XCHAR_TABLE (vector
)->purpose
= purpose
;
91 XSETCHAR_TABLE (vector
, XCHAR_TABLE (vector
));
96 make_sub_char_table (depth
, min_char
, defalt
)
101 int size
= VECSIZE (struct Lisp_Sub_Char_Table
) - 1 + chartab_size
[depth
];
104 table
= Fmake_vector (make_number (size
), defalt
);
105 XSUB_CHAR_TABLE (table
)->depth
= make_number (depth
);
106 XSUB_CHAR_TABLE (table
)->min_char
= make_number (min_char
);
107 XSETSUB_CHAR_TABLE (table
, XSUB_CHAR_TABLE (table
));
113 char_table_ascii (table
)
118 sub
= XCHAR_TABLE (table
)->contents
[0];
119 sub
= XSUB_CHAR_TABLE (sub
)->contents
[0];
120 return XSUB_CHAR_TABLE (sub
)->contents
[0];
124 copy_sub_char_table (table
)
128 int depth
= XINT (XSUB_CHAR_TABLE (table
)->depth
);
129 int min_char
= XINT (XSUB_CHAR_TABLE (table
)->min_char
);
133 copy
= make_sub_char_table (depth
, min_char
, Qnil
);
134 /* Recursively copy any sub char-tables. */
135 for (i
= 0; i
< chartab_size
[depth
]; i
++)
137 val
= XSUB_CHAR_TABLE (table
)->contents
[i
];
138 if (SUB_CHAR_TABLE_P (val
))
139 XSUB_CHAR_TABLE (copy
)->contents
[i
] = copy_sub_char_table (val
);
141 XSUB_CHAR_TABLE (copy
)->contents
[i
] = val
;
149 copy_char_table (table
)
153 int size
= XCHAR_TABLE (table
)->size
& PSEUDOVECTOR_SIZE_MASK
;
156 copy
= Fmake_vector (make_number (size
), Qnil
);
157 XCHAR_TABLE (copy
)->defalt
= XCHAR_TABLE (table
)->defalt
;
158 XCHAR_TABLE (copy
)->parent
= XCHAR_TABLE (table
)->parent
;
159 XCHAR_TABLE (copy
)->purpose
= XCHAR_TABLE (table
)->purpose
;
160 XCHAR_TABLE (copy
)->ascii
= XCHAR_TABLE (table
)->ascii
;
161 for (i
= 0; i
< chartab_size
[0]; i
++)
162 XCHAR_TABLE (copy
)->contents
[i
]
163 = (SUB_CHAR_TABLE_P (XCHAR_TABLE (table
)->contents
[i
])
164 ? copy_sub_char_table (XCHAR_TABLE (table
)->contents
[i
])
165 : XCHAR_TABLE (table
)->contents
[i
]);
166 if (SUB_CHAR_TABLE_P (XCHAR_TABLE (copy
)->ascii
))
167 XCHAR_TABLE (copy
)->ascii
= char_table_ascii (copy
);
168 size
-= VECSIZE (struct Lisp_Char_Table
) - 1;
169 for (i
= 0; i
< size
; i
++)
170 XCHAR_TABLE (copy
)->extras
[i
] = XCHAR_TABLE (table
)->extras
[i
];
172 XSETCHAR_TABLE (copy
, XCHAR_TABLE (copy
));
177 sub_char_table_ref (table
, c
)
181 struct Lisp_Sub_Char_Table
*tbl
= XSUB_CHAR_TABLE (table
);
182 int depth
= XINT (tbl
->depth
);
183 int min_char
= XINT (tbl
->min_char
);
186 val
= tbl
->contents
[CHARTAB_IDX (c
, depth
, min_char
)];
187 if (SUB_CHAR_TABLE_P (val
))
188 val
= sub_char_table_ref (val
, c
);
193 char_table_ref (table
, c
)
197 struct Lisp_Char_Table
*tbl
= XCHAR_TABLE (table
);
200 if (ASCII_CHAR_P (c
))
203 if (SUB_CHAR_TABLE_P (val
))
204 val
= XSUB_CHAR_TABLE (val
)->contents
[c
];
208 val
= tbl
->contents
[CHARTAB_IDX (c
, 0, 0)];
209 if (SUB_CHAR_TABLE_P (val
))
210 val
= sub_char_table_ref (val
, c
);
215 if (NILP (val
) && CHAR_TABLE_P (tbl
->parent
))
216 val
= char_table_ref (tbl
->parent
, c
);
222 sub_char_table_ref_and_range (table
, c
, from
, to
)
227 struct Lisp_Sub_Char_Table
*tbl
= XSUB_CHAR_TABLE (table
);
228 int depth
= XINT (tbl
->depth
);
229 int min_char
= XINT (tbl
->min_char
);
232 val
= tbl
->contents
[CHARTAB_IDX (c
, depth
, min_char
)];
237 else if (SUB_CHAR_TABLE_P (val
))
239 val
= sub_char_table_ref_and_range (val
, c
, from
, to
);
243 *from
= (CHARTAB_IDX (c
, depth
, min_char
) * chartab_chars
[depth
]
245 *to
= *from
+ chartab_chars
[depth
] - 1;
252 char_table_ref_and_range (table
, c
, from
, to
)
257 struct Lisp_Char_Table
*tbl
= XCHAR_TABLE (table
);
260 if (ASCII_CHAR_P (c
))
263 if (SUB_CHAR_TABLE_P (val
))
265 val
= XSUB_CHAR_TABLE (val
)->contents
[c
];
270 *from
= 0, *to
= 127;
275 val
= tbl
->contents
[CHARTAB_IDX (c
, 0, 0)];
276 if (SUB_CHAR_TABLE_P (val
))
278 val
= sub_char_table_ref_and_range (val
, c
, from
, to
);
282 *from
= CHARTAB_IDX (c
, 0, 0) * chartab_chars
[0];
283 *to
= *from
+ chartab_chars
[0] - 1;
290 *from
= 0, *to
= MAX_CHAR
;
291 if (NILP (val
) && CHAR_TABLE_P (tbl
->parent
))
292 val
= char_table_ref_and_range (tbl
->parent
, c
, from
, to
);
298 #define ASET_RANGE(ARRAY, FROM, TO, LIMIT, VAL) \
300 int limit = (TO) < (LIMIT) ? (TO) : (LIMIT); \
301 for (; (FROM) < limit; (FROM)++) (ARRAY)->contents[(FROM)] = (VAL); \
304 #define GET_SUB_CHAR_TABLE(TABLE, SUBTABLE, IDX, DEPTH, MIN_CHAR) \
306 (SUBTABLE) = (TABLE)->contents[(IDX)]; \
307 if (!SUB_CHAR_TABLE_P (SUBTABLE)) \
308 (SUBTABLE) = make_sub_char_table ((DEPTH), (MIN_CHAR), (SUBTABLE)); \
313 sub_char_table_set (table
, c
, val
)
318 struct Lisp_Sub_Char_Table
*tbl
= XSUB_CHAR_TABLE (table
);
319 int depth
= XINT ((tbl
)->depth
);
320 int min_char
= XINT ((tbl
)->min_char
);
321 int i
= CHARTAB_IDX (c
, depth
, min_char
);
325 tbl
->contents
[i
] = val
;
328 sub
= tbl
->contents
[i
];
329 if (! SUB_CHAR_TABLE_P (sub
))
331 sub
= make_sub_char_table (depth
+ 1,
332 min_char
+ i
* chartab_chars
[depth
], sub
);
333 tbl
->contents
[i
] = sub
;
335 sub_char_table_set (sub
, c
, val
);
340 char_table_set (table
, c
, val
)
345 struct Lisp_Char_Table
*tbl
= XCHAR_TABLE (table
);
348 && SUB_CHAR_TABLE_P (tbl
->ascii
))
350 XSUB_CHAR_TABLE (tbl
->ascii
)->contents
[c
] = val
;
354 int i
= CHARTAB_IDX (c
, 0, 0);
357 sub
= tbl
->contents
[i
];
358 if (! SUB_CHAR_TABLE_P (sub
))
360 sub
= make_sub_char_table (1, i
* chartab_chars
[0], sub
);
361 tbl
->contents
[i
] = sub
;
363 sub_char_table_set (sub
, c
, val
);
364 if (ASCII_CHAR_P (c
))
365 tbl
->ascii
= char_table_ascii (tbl
);
371 sub_char_table_set_range (table
, depth
, min_char
, from
, to
, val
)
378 int max_char
= min_char
+ chartab_chars
[depth
] - 1;
380 if (depth
== 3 || from
<= min_char
&& to
>= max_char
)
387 if (! SUB_CHAR_TABLE_P (*table
))
388 *table
= make_sub_char_table (depth
, min_char
, *table
);
393 i
= CHARTAB_IDX (from
, depth
, min_char
);
394 j
= CHARTAB_IDX (to
, depth
, min_char
);
395 min_char
+= chartab_chars
[depth
] * i
;
396 for (; i
<= j
; i
++, min_char
+= chartab_chars
[depth
])
397 sub_char_table_set_range (XSUB_CHAR_TABLE (*table
)->contents
+ i
,
398 depth
, min_char
, from
, to
, val
);
404 char_table_set_range (table
, from
, to
, val
)
409 struct Lisp_Char_Table
*tbl
= XCHAR_TABLE (table
);
410 Lisp_Object
*contents
= tbl
->contents
;
414 char_table_set (table
, from
, val
);
417 for (i
= CHARTAB_IDX (from
, 0, 0), min_char
= i
* chartab_chars
[0];
419 i
++, min_char
+= chartab_chars
[0])
420 sub_char_table_set_range (contents
+ i
, 0, min_char
, from
, to
, val
);
421 if (ASCII_CHAR_P (from
))
422 tbl
->ascii
= char_table_ascii (tbl
);
428 DEFUN ("char-table-subtype", Fchar_table_subtype
, Schar_table_subtype
,
431 Return the subtype of char-table CHAR-TABLE. The value is a symbol. */)
433 Lisp_Object char_table
;
435 CHECK_CHAR_TABLE (char_table
);
437 return XCHAR_TABLE (char_table
)->purpose
;
440 DEFUN ("char-table-parent", Fchar_table_parent
, Schar_table_parent
,
442 doc
: /* Return the parent char-table of CHAR-TABLE.
443 The value is either nil or another char-table.
444 If CHAR-TABLE holds nil for a given character,
445 then the actual applicable value is inherited from the parent char-table
446 \(or from its parents, if necessary). */)
448 Lisp_Object char_table
;
450 CHECK_CHAR_TABLE (char_table
);
452 return XCHAR_TABLE (char_table
)->parent
;
455 DEFUN ("set-char-table-parent", Fset_char_table_parent
, Sset_char_table_parent
,
457 doc
: /* Set the parent char-table of CHAR-TABLE to PARENT.
458 PARENT must be either nil or another char-table. */)
460 Lisp_Object char_table
, parent
;
464 CHECK_CHAR_TABLE (char_table
);
468 CHECK_CHAR_TABLE (parent
);
470 for (temp
= parent
; !NILP (temp
); temp
= XCHAR_TABLE (temp
)->parent
)
471 if (EQ (temp
, char_table
))
472 error ("Attempt to make a chartable be its own parent");
475 XCHAR_TABLE (char_table
)->parent
= parent
;
480 DEFUN ("char-table-extra-slot", Fchar_table_extra_slot
, Schar_table_extra_slot
,
482 doc
: /* Return the value of CHAR-TABLE's extra-slot number N. */)
484 Lisp_Object char_table
, n
;
486 CHECK_CHAR_TABLE (char_table
);
489 || XINT (n
) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table
)))
490 args_out_of_range (char_table
, n
);
492 return XCHAR_TABLE (char_table
)->extras
[XINT (n
)];
495 DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot
,
496 Sset_char_table_extra_slot
,
498 doc
: /* Set CHAR-TABLE's extra-slot number N to VALUE. */)
499 (char_table
, n
, value
)
500 Lisp_Object char_table
, n
, value
;
502 CHECK_CHAR_TABLE (char_table
);
505 || XINT (n
) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table
)))
506 args_out_of_range (char_table
, n
);
508 return XCHAR_TABLE (char_table
)->extras
[XINT (n
)] = value
;
511 DEFUN ("char-table-range", Fchar_table_range
, Schar_table_range
,
513 doc
: /* Return the value in CHAR-TABLE for a range of characters RANGE.
514 RANGE should be nil (for the default value),
515 a cons of character codes (for characters in the range), or a character code. */)
517 Lisp_Object char_table
, range
;
520 CHECK_CHAR_TABLE (char_table
);
522 if (EQ (range
, Qnil
))
523 val
= XCHAR_TABLE (char_table
)->defalt
;
524 else if (INTEGERP (range
))
525 val
= CHAR_TABLE_REF (char_table
, XINT (range
));
526 else if (CONSP (range
))
530 CHECK_CHARACTER (XCAR (range
));
531 CHECK_CHARACTER (XCDR (range
));
532 val
= char_table_ref_and_range (char_table
, XINT (XCAR (range
)),
534 /* Not yet implemented. */
537 error ("Invalid RANGE argument to `char-table-range'");
541 DEFUN ("set-char-table-range", Fset_char_table_range
, Sset_char_table_range
,
544 Set the value in CHAR-TABLE for characters specified by RANGE to VALUE.
545 RANGE should be t (for all characters), nil (for the default value),
546 a cons of character codes (for characters in the range), or a character code. */)
547 (char_table
, range
, value
)
548 Lisp_Object char_table
, range
, value
;
550 CHECK_CHAR_TABLE (char_table
);
555 XCHAR_TABLE (char_table
)->ascii
= Qnil
;
556 for (i
= 0; i
< chartab_size
[0]; i
++)
557 XCHAR_TABLE (char_table
)->contents
[i
] = Qnil
;
558 XCHAR_TABLE (char_table
)->defalt
= value
;
560 else if (EQ (range
, Qnil
))
561 XCHAR_TABLE (char_table
)->defalt
= value
;
562 else if (INTEGERP (range
))
563 char_table_set (char_table
, XINT (range
), value
);
564 else if (CONSP (range
))
566 CHECK_CHARACTER (XCAR (range
));
567 CHECK_CHARACTER (XCDR (range
));
568 char_table_set_range (char_table
,
569 XINT (XCAR (range
)), XINT (XCDR (range
)), value
);
572 error ("Invalid RANGE argument to `set-char-table-range'");
577 DEFUN ("set-char-table-default", Fset_char_table_default
,
578 Sset_char_table_default
, 3, 3, 0,
580 Set the default value in CHAR-TABLE for a generic character CHAR to VALUE.
581 The generic character specifies the group of characters.
582 See also the documentation of make-char. */)
583 (char_table
, ch
, value
)
584 Lisp_Object char_table
, ch
, value
;
589 /* Look up the element in TABLE at index CH, and return it as an
590 integer. If the element is nil, return CH itself. (Actually we do
591 that for any non-integer.) */
594 char_table_translate (table
, ch
)
599 value
= Faref (table
, make_number (ch
));
600 if (! INTEGERP (value
))
606 optimize_sub_char_table (table
)
609 struct Lisp_Sub_Char_Table
*tbl
= XSUB_CHAR_TABLE (table
);
610 int depth
= XINT (tbl
->depth
);
611 Lisp_Object elt
, this;
614 elt
= XSUB_CHAR_TABLE (table
)->contents
[0];
615 if (SUB_CHAR_TABLE_P (elt
))
616 elt
= XSUB_CHAR_TABLE (table
)->contents
[0] = optimize_sub_char_table (elt
);
617 if (SUB_CHAR_TABLE_P (elt
))
619 for (i
= 1; i
< chartab_size
[depth
]; i
++)
621 this = XSUB_CHAR_TABLE (table
)->contents
[i
];
622 if (SUB_CHAR_TABLE_P (this))
623 this = XSUB_CHAR_TABLE (table
)->contents
[i
]
624 = optimize_sub_char_table (this);
625 if (SUB_CHAR_TABLE_P (this)
626 || NILP (Fequal (this, elt
)))
630 return (i
< chartab_size
[depth
] ? table
: elt
);
633 DEFUN ("optimize-char-table", Foptimize_char_table
, Soptimize_char_table
,
635 doc
: /* Optimize CHAR-TABLE. */)
637 Lisp_Object char_table
;
642 CHECK_CHAR_TABLE (char_table
);
644 for (i
= 0; i
< chartab_size
[0]; i
++)
646 elt
= XCHAR_TABLE (char_table
)->contents
[i
];
647 if (SUB_CHAR_TABLE_P (elt
))
648 XCHAR_TABLE (char_table
)->contents
[i
] = optimize_sub_char_table (elt
);
655 map_sub_char_table (c_function
, function
, table
, arg
, val
, range
)
656 void (*c_function
) P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
));
657 Lisp_Object function
, table
, arg
, val
, range
;
659 struct Lisp_Sub_Char_Table
*tbl
= XSUB_CHAR_TABLE (table
);
660 int depth
= XINT (tbl
->depth
);
663 for (i
= 0, c
= XINT (tbl
->min_char
); i
< chartab_size
[depth
];
664 i
++, c
+= chartab_chars
[depth
])
668 this = tbl
->contents
[i
];
669 if (SUB_CHAR_TABLE_P (this))
670 val
= map_sub_char_table (c_function
, function
, this, arg
, val
, range
);
671 else if (NILP (Fequal (val
, this)))
675 XCDR (range
) = make_number (c
- 1);
677 && EQ (XCAR (range
), XCDR (range
)))
680 (*c_function
) (arg
, XCAR (range
), val
);
682 call2 (function
, XCAR (range
), val
);
687 (*c_function
) (arg
, range
, val
);
689 call2 (function
, range
, val
);
693 XCAR (range
) = make_number (c
);
700 /* Map C_FUNCTION or FUNCTION over TABLE, calling it for each
701 character or group of characters that share a value.
703 ARG is passed to C_FUNCTION when that is called.
705 DEPTH and INDICES are ignored. They are removed in the new
709 map_char_table (c_function
, function
, table
, arg
, depth
, indices
)
710 void (*c_function
) P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
));
711 Lisp_Object function
, table
, arg
, *indices
;
714 Lisp_Object range
, val
;
717 range
= Fcons (make_number (0), Qnil
);
718 val
= char_table_ref (table
, 0);
720 for (i
= 0, c
= 0; i
< chartab_size
[0]; i
++, c
+= chartab_chars
[0])
724 this = XCHAR_TABLE (table
)->contents
[i
];
725 if (SUB_CHAR_TABLE_P (this))
726 val
= map_sub_char_table (c_function
, function
, this, arg
, val
, range
);
727 else if (NILP (Fequal (val
, this)))
731 XCDR (range
) = make_number (c
- 1);
733 (*c_function
) (arg
, range
, val
);
735 call2 (function
, range
, val
);
738 XCAR (range
) = make_number (c
);
743 DEFUN ("map-char-table", Fmap_char_table
, Smap_char_table
,
746 Call FUNCTION for each (normal and generic) characters in CHAR-TABLE.
747 FUNCTION is called with two arguments--a key and a value.
748 The key is always a possible IDX argument to `aref'. */)
749 (function
, char_table
)
750 Lisp_Object function
, char_table
;
752 CHECK_CHAR_TABLE (char_table
);
754 map_char_table (NULL
, function
, char_table
, char_table
, 0, NULL
);
761 make_class_table (purpose
)
769 args
[2] = QCextra_slots
;
770 args
[3] = Fmake_vector (make_number (2), Qnil
);
771 ASET (args
[3], 0, Fmakehash (Qequal
));
772 table
= Fmake_char_table (4, args
);
777 modify_class_entry (c
, val
, table
, set
)
779 Lisp_Object val
, table
, set
;
781 Lisp_Object classes
, hash
, canon
;
784 hash
= XCHAR_TABLE (table
)->extras
[0];
785 classes
= CHAR_TABLE_REF (table
, c
);
787 if (! BOOL_VECTOR_P (classes
))
788 classes
= (NILP (set
)
790 : Fmake_bool_vector (make_number ((ival
/ 8) * 8 + 8), Qnil
));
791 else if (ival
< XBOOL_VECTOR (classes
)->size
)
795 classes
= Fmake_bool_vector (make_number ((ival
/ 8) * 8 + 8), Qnil
);
796 for (i
= 0; i
< XBOOL_VECTOR (classes
)->size
; i
++)
797 Faset (classes
, make_number (i
), Faref (old
, make_number (i
)));
798 Faset (classes
, val
, set
);
800 else if (NILP (Faref (classes
, val
)) != NILP (set
))
802 classes
= Fcopy_sequence (classes
);
803 Faset (classes
, val
, set
);
810 canon
= Fgethash (classes
, hash
, Qnil
);
814 Fputhash (canon
, canon
, hash
);
816 char_table_set (table
, c
, canon
);
827 defsubr (&Smake_char_table
);
828 defsubr (&Schar_table_parent
);
829 defsubr (&Schar_table_subtype
);
830 defsubr (&Sset_char_table_parent
);
831 defsubr (&Schar_table_extra_slot
);
832 defsubr (&Sset_char_table_extra_slot
);
833 defsubr (&Schar_table_range
);
834 defsubr (&Sset_char_table_range
);
835 defsubr (&Sset_char_table_default
);
836 defsubr (&Soptimize_char_table
);
837 defsubr (&Smap_char_table
);