1 /* chartab.c -- char-table support
2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
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 3 of the License, or
11 (at your option) any later version.
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. If not, see <http://www.gnu.org/licenses/>. */
24 #include "character.h"
30 /* Number of elements in Nth level char-table. */
31 const int chartab_size
[4] =
32 { (1 << CHARTAB_SIZE_BITS_0
),
33 (1 << CHARTAB_SIZE_BITS_1
),
34 (1 << CHARTAB_SIZE_BITS_2
),
35 (1 << CHARTAB_SIZE_BITS_3
) };
37 /* Number of characters each element of Nth level char-table
39 static const int chartab_chars
[4] =
40 { (1 << (CHARTAB_SIZE_BITS_1
+ CHARTAB_SIZE_BITS_2
+ CHARTAB_SIZE_BITS_3
)),
41 (1 << (CHARTAB_SIZE_BITS_2
+ CHARTAB_SIZE_BITS_3
)),
42 (1 << CHARTAB_SIZE_BITS_3
),
45 /* Number of characters (in bits) each element of Nth level char-table
47 static const int chartab_bits
[4] =
48 { (CHARTAB_SIZE_BITS_1
+ CHARTAB_SIZE_BITS_2
+ CHARTAB_SIZE_BITS_3
),
49 (CHARTAB_SIZE_BITS_2
+ CHARTAB_SIZE_BITS_3
),
53 #define CHARTAB_IDX(c, depth, min_char) \
54 (((c) - (min_char)) >> chartab_bits[(depth)])
57 /* Preamble for uniprop (Unicode character property) tables. See the
58 comment of "Unicode character property tables". */
60 /* Purpose of uniprop tables. */
61 static Lisp_Object Qchar_code_property_table
;
63 /* Types of decoder and encoder functions for uniprop values. */
64 typedef Lisp_Object (*uniprop_decoder_t
) (Lisp_Object
, Lisp_Object
);
65 typedef Lisp_Object (*uniprop_encoder_t
) (Lisp_Object
, Lisp_Object
);
67 static Lisp_Object
uniprop_table_uncompress (Lisp_Object
, int);
68 static uniprop_decoder_t
uniprop_get_decoder (Lisp_Object
);
70 /* 1 iff TABLE is a uniprop table. */
71 #define UNIPROP_TABLE_P(TABLE) \
72 (EQ (XCHAR_TABLE (TABLE)->purpose, Qchar_code_property_table) \
73 && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (TABLE)) == 5)
75 /* Return a decoder for values in the uniprop table TABLE. */
76 #define UNIPROP_GET_DECODER(TABLE) \
77 (UNIPROP_TABLE_P (TABLE) ? uniprop_get_decoder (TABLE) : NULL)
79 /* Nonzero iff OBJ is a string representing uniprop values of 128
80 succeeding characters (the bottom level of a char-table) by a
81 compressed format. We are sure that no property value has a string
82 starting with '\001' nor '\002'. */
83 #define UNIPROP_COMPRESSED_FORM_P(OBJ) \
84 (STRINGP (OBJ) && SCHARS (OBJ) > 0 \
85 && ((SREF (OBJ, 0) == 1 || (SREF (OBJ, 0) == 2))))
88 CHECK_CHAR_TABLE (Lisp_Object x
)
90 CHECK_TYPE (CHAR_TABLE_P (x
), Qchar_table_p
, x
);
94 set_char_table_ascii (Lisp_Object table
, Lisp_Object val
)
96 XCHAR_TABLE (table
)->ascii
= val
;
99 set_char_table_parent (Lisp_Object table
, Lisp_Object val
)
101 XCHAR_TABLE (table
)->parent
= val
;
104 DEFUN ("make-char-table", Fmake_char_table
, Smake_char_table
, 1, 2, 0,
105 doc
: /* Return a newly created char-table, with purpose PURPOSE.
106 Each element is initialized to INIT, which defaults to nil.
108 PURPOSE should be a symbol. If it has a `char-table-extra-slots'
109 property, the property's value should be an integer between 0 and 10
110 that specifies how many extra slots the char-table has. Otherwise,
111 the char-table has no extra slot. */)
112 (register Lisp_Object purpose
, Lisp_Object init
)
119 CHECK_SYMBOL (purpose
);
120 n
= Fget (purpose
, Qchar_table_extra_slots
);
127 args_out_of_range (n
, Qnil
);
131 size
= CHAR_TABLE_STANDARD_SLOTS
+ n_extras
;
132 vector
= Fmake_vector (make_number (size
), init
);
133 XSETPVECTYPE (XVECTOR (vector
), PVEC_CHAR_TABLE
);
134 set_char_table_parent (vector
, Qnil
);
135 set_char_table_purpose (vector
, purpose
);
136 XSETCHAR_TABLE (vector
, XCHAR_TABLE (vector
));
141 make_sub_char_table (int depth
, int min_char
, Lisp_Object defalt
)
144 int size
= (PSEUDOVECSIZE (struct Lisp_Sub_Char_Table
, contents
)
145 + chartab_size
[depth
]);
147 table
= Fmake_vector (make_number (size
), defalt
);
148 XSETPVECTYPE (XVECTOR (table
), PVEC_SUB_CHAR_TABLE
);
149 XSUB_CHAR_TABLE (table
)->depth
= make_number (depth
);
150 XSUB_CHAR_TABLE (table
)->min_char
= make_number (min_char
);
156 char_table_ascii (Lisp_Object table
)
158 Lisp_Object sub
, val
;
160 sub
= XCHAR_TABLE (table
)->contents
[0];
161 if (! SUB_CHAR_TABLE_P (sub
))
163 sub
= XSUB_CHAR_TABLE (sub
)->contents
[0];
164 if (! SUB_CHAR_TABLE_P (sub
))
166 val
= XSUB_CHAR_TABLE (sub
)->contents
[0];
167 if (UNIPROP_TABLE_P (table
) && UNIPROP_COMPRESSED_FORM_P (val
))
168 val
= uniprop_table_uncompress (sub
, 0);
173 copy_sub_char_table (Lisp_Object table
)
175 int depth
= XINT (XSUB_CHAR_TABLE (table
)->depth
);
176 int min_char
= XINT (XSUB_CHAR_TABLE (table
)->min_char
);
177 Lisp_Object copy
= make_sub_char_table (depth
, min_char
, Qnil
);
180 /* Recursively copy any sub char-tables. */
181 for (i
= 0; i
< chartab_size
[depth
]; i
++)
183 Lisp_Object val
= XSUB_CHAR_TABLE (table
)->contents
[i
];
184 set_sub_char_table_contents
185 (copy
, i
, SUB_CHAR_TABLE_P (val
) ? copy_sub_char_table (val
) : val
);
193 copy_char_table (Lisp_Object table
)
196 int size
= XCHAR_TABLE (table
)->header
.size
& PSEUDOVECTOR_SIZE_MASK
;
199 copy
= Fmake_vector (make_number (size
), Qnil
);
200 XSETPVECTYPE (XVECTOR (copy
), PVEC_CHAR_TABLE
);
201 set_char_table_defalt (copy
, XCHAR_TABLE (table
)->defalt
);
202 set_char_table_parent (copy
, XCHAR_TABLE (table
)->parent
);
203 set_char_table_purpose (copy
, XCHAR_TABLE (table
)->purpose
);
204 for (i
= 0; i
< chartab_size
[0]; i
++)
205 set_char_table_contents
207 (SUB_CHAR_TABLE_P (XCHAR_TABLE (table
)->contents
[i
])
208 ? copy_sub_char_table (XCHAR_TABLE (table
)->contents
[i
])
209 : XCHAR_TABLE (table
)->contents
[i
]));
210 set_char_table_ascii (copy
, char_table_ascii (copy
));
211 size
-= CHAR_TABLE_STANDARD_SLOTS
;
212 for (i
= 0; i
< size
; i
++)
213 set_char_table_extras (copy
, i
, XCHAR_TABLE (table
)->extras
[i
]);
215 XSETCHAR_TABLE (copy
, XCHAR_TABLE (copy
));
220 sub_char_table_ref (Lisp_Object table
, int c
, bool is_uniprop
)
222 struct Lisp_Sub_Char_Table
*tbl
= XSUB_CHAR_TABLE (table
);
223 int depth
= XINT (tbl
->depth
);
224 int min_char
= XINT (tbl
->min_char
);
226 int idx
= CHARTAB_IDX (c
, depth
, min_char
);
228 val
= tbl
->contents
[idx
];
229 if (is_uniprop
&& UNIPROP_COMPRESSED_FORM_P (val
))
230 val
= uniprop_table_uncompress (table
, idx
);
231 if (SUB_CHAR_TABLE_P (val
))
232 val
= sub_char_table_ref (val
, c
, is_uniprop
);
237 char_table_ref (Lisp_Object table
, int c
)
239 struct Lisp_Char_Table
*tbl
= XCHAR_TABLE (table
);
242 if (ASCII_CHAR_P (c
))
245 if (SUB_CHAR_TABLE_P (val
))
246 val
= XSUB_CHAR_TABLE (val
)->contents
[c
];
250 val
= tbl
->contents
[CHARTAB_IDX (c
, 0, 0)];
251 if (SUB_CHAR_TABLE_P (val
))
252 val
= sub_char_table_ref (val
, c
, UNIPROP_TABLE_P (table
));
257 if (NILP (val
) && CHAR_TABLE_P (tbl
->parent
))
258 val
= char_table_ref (tbl
->parent
, c
);
264 sub_char_table_ref_and_range (Lisp_Object table
, int c
, int *from
, int *to
,
265 Lisp_Object defalt
, bool is_uniprop
)
267 struct Lisp_Sub_Char_Table
*tbl
= XSUB_CHAR_TABLE (table
);
268 int depth
= XINT (tbl
->depth
);
269 int min_char
= XINT (tbl
->min_char
);
270 int chartab_idx
= CHARTAB_IDX (c
, depth
, min_char
), idx
;
273 val
= tbl
->contents
[chartab_idx
];
274 if (is_uniprop
&& UNIPROP_COMPRESSED_FORM_P (val
))
275 val
= uniprop_table_uncompress (table
, chartab_idx
);
276 if (SUB_CHAR_TABLE_P (val
))
277 val
= sub_char_table_ref_and_range (val
, c
, from
, to
, defalt
, is_uniprop
);
282 while (idx
> 0 && *from
< min_char
+ idx
* chartab_chars
[depth
])
284 Lisp_Object this_val
;
286 c
= min_char
+ idx
* chartab_chars
[depth
] - 1;
288 this_val
= tbl
->contents
[idx
];
289 if (is_uniprop
&& UNIPROP_COMPRESSED_FORM_P (this_val
))
290 this_val
= uniprop_table_uncompress (table
, idx
);
291 if (SUB_CHAR_TABLE_P (this_val
))
292 this_val
= sub_char_table_ref_and_range (this_val
, c
, from
, to
, defalt
,
294 else if (NILP (this_val
))
297 if (! EQ (this_val
, val
))
303 while (((c
= (chartab_idx
+ 1) * chartab_chars
[depth
])
304 < chartab_chars
[depth
- 1])
305 && (c
+= min_char
) <= *to
)
307 Lisp_Object this_val
;
310 this_val
= tbl
->contents
[chartab_idx
];
311 if (is_uniprop
&& UNIPROP_COMPRESSED_FORM_P (this_val
))
312 this_val
= uniprop_table_uncompress (table
, chartab_idx
);
313 if (SUB_CHAR_TABLE_P (this_val
))
314 this_val
= sub_char_table_ref_and_range (this_val
, c
, from
, to
, defalt
,
316 else if (NILP (this_val
))
318 if (! EQ (this_val
, val
))
329 /* Return the value for C in char-table TABLE. Shrink the range *FROM
330 and *TO to cover characters (containing C) that have the same value
331 as C. It is not assured that the values of (*FROM - 1) and (*TO +
332 1) are different from that of C. */
335 char_table_ref_and_range (Lisp_Object table
, int c
, int *from
, int *to
)
337 struct Lisp_Char_Table
*tbl
= XCHAR_TABLE (table
);
338 int chartab_idx
= CHARTAB_IDX (c
, 0, 0), idx
;
340 bool is_uniprop
= UNIPROP_TABLE_P (table
);
342 val
= tbl
->contents
[chartab_idx
];
347 if (is_uniprop
&& UNIPROP_COMPRESSED_FORM_P (val
))
348 val
= uniprop_table_uncompress (table
, chartab_idx
);
349 if (SUB_CHAR_TABLE_P (val
))
350 val
= sub_char_table_ref_and_range (val
, c
, from
, to
, tbl
->defalt
,
355 while (*from
< idx
* chartab_chars
[0])
357 Lisp_Object this_val
;
359 c
= idx
* chartab_chars
[0] - 1;
361 this_val
= tbl
->contents
[idx
];
362 if (is_uniprop
&& UNIPROP_COMPRESSED_FORM_P (this_val
))
363 this_val
= uniprop_table_uncompress (table
, idx
);
364 if (SUB_CHAR_TABLE_P (this_val
))
365 this_val
= sub_char_table_ref_and_range (this_val
, c
, from
, to
,
366 tbl
->defalt
, is_uniprop
);
367 else if (NILP (this_val
))
368 this_val
= tbl
->defalt
;
370 if (! EQ (this_val
, val
))
376 while (*to
>= (chartab_idx
+ 1) * chartab_chars
[0])
378 Lisp_Object this_val
;
381 c
= chartab_idx
* chartab_chars
[0];
382 this_val
= tbl
->contents
[chartab_idx
];
383 if (is_uniprop
&& UNIPROP_COMPRESSED_FORM_P (this_val
))
384 this_val
= uniprop_table_uncompress (table
, chartab_idx
);
385 if (SUB_CHAR_TABLE_P (this_val
))
386 this_val
= sub_char_table_ref_and_range (this_val
, c
, from
, to
,
387 tbl
->defalt
, is_uniprop
);
388 else if (NILP (this_val
))
389 this_val
= tbl
->defalt
;
390 if (! EQ (this_val
, val
))
402 sub_char_table_set (Lisp_Object table
, int c
, Lisp_Object val
, bool is_uniprop
)
404 struct Lisp_Sub_Char_Table
*tbl
= XSUB_CHAR_TABLE (table
);
405 int depth
= XINT ((tbl
)->depth
);
406 int min_char
= XINT ((tbl
)->min_char
);
407 int i
= CHARTAB_IDX (c
, depth
, min_char
);
411 set_sub_char_table_contents (table
, i
, val
);
414 sub
= tbl
->contents
[i
];
415 if (! SUB_CHAR_TABLE_P (sub
))
417 if (is_uniprop
&& UNIPROP_COMPRESSED_FORM_P (sub
))
418 sub
= uniprop_table_uncompress (table
, i
);
421 sub
= make_sub_char_table (depth
+ 1,
422 min_char
+ i
* chartab_chars
[depth
],
424 set_sub_char_table_contents (table
, i
, sub
);
427 sub_char_table_set (sub
, c
, val
, is_uniprop
);
432 char_table_set (Lisp_Object table
, int c
, Lisp_Object val
)
434 struct Lisp_Char_Table
*tbl
= XCHAR_TABLE (table
);
437 && SUB_CHAR_TABLE_P (tbl
->ascii
))
438 set_sub_char_table_contents (tbl
->ascii
, c
, val
);
441 int i
= CHARTAB_IDX (c
, 0, 0);
444 sub
= tbl
->contents
[i
];
445 if (! SUB_CHAR_TABLE_P (sub
))
447 sub
= make_sub_char_table (1, i
* chartab_chars
[0], sub
);
448 set_char_table_contents (table
, i
, sub
);
450 sub_char_table_set (sub
, c
, val
, UNIPROP_TABLE_P (table
));
451 if (ASCII_CHAR_P (c
))
452 set_char_table_ascii (table
, char_table_ascii (table
));
457 sub_char_table_set_range (Lisp_Object table
, int from
, int to
, Lisp_Object val
,
460 struct Lisp_Sub_Char_Table
*tbl
= XSUB_CHAR_TABLE (table
);
461 int depth
= XINT ((tbl
)->depth
);
462 int min_char
= XINT ((tbl
)->min_char
);
463 int chars_in_block
= chartab_chars
[depth
];
464 int i
, c
, lim
= chartab_size
[depth
];
468 i
= CHARTAB_IDX (from
, depth
, min_char
);
469 c
= min_char
+ chars_in_block
* i
;
470 for (; i
< lim
; i
++, c
+= chars_in_block
)
474 if (from
<= c
&& c
+ chars_in_block
- 1 <= to
)
475 set_sub_char_table_contents (table
, i
, val
);
478 Lisp_Object sub
= tbl
->contents
[i
];
479 if (! SUB_CHAR_TABLE_P (sub
))
481 if (is_uniprop
&& UNIPROP_COMPRESSED_FORM_P (sub
))
482 sub
= uniprop_table_uncompress (table
, i
);
485 sub
= make_sub_char_table (depth
+ 1, c
, sub
);
486 set_sub_char_table_contents (table
, i
, sub
);
489 sub_char_table_set_range (sub
, from
, to
, val
, is_uniprop
);
496 char_table_set_range (Lisp_Object table
, int from
, int to
, Lisp_Object val
)
498 struct Lisp_Char_Table
*tbl
= XCHAR_TABLE (table
);
501 char_table_set (table
, from
, val
);
504 bool is_uniprop
= UNIPROP_TABLE_P (table
);
505 int lim
= CHARTAB_IDX (to
, 0, 0);
508 for (i
= CHARTAB_IDX (from
, 0, 0), c
= 0; i
<= lim
;
509 i
++, c
+= chartab_chars
[0])
513 if (from
<= c
&& c
+ chartab_chars
[0] - 1 <= to
)
514 set_char_table_contents (table
, i
, val
);
517 Lisp_Object sub
= tbl
->contents
[i
];
518 if (! SUB_CHAR_TABLE_P (sub
))
520 sub
= make_sub_char_table (1, i
* chartab_chars
[0], sub
);
521 set_char_table_contents (table
, i
, sub
);
523 sub_char_table_set_range (sub
, from
, to
, val
, is_uniprop
);
526 if (ASCII_CHAR_P (from
))
527 set_char_table_ascii (table
, char_table_ascii (table
));
532 DEFUN ("char-table-subtype", Fchar_table_subtype
, Schar_table_subtype
,
535 Return the subtype of char-table CHAR-TABLE. The value is a symbol. */)
536 (Lisp_Object char_table
)
538 CHECK_CHAR_TABLE (char_table
);
540 return XCHAR_TABLE (char_table
)->purpose
;
543 DEFUN ("char-table-parent", Fchar_table_parent
, Schar_table_parent
,
545 doc
: /* Return the parent char-table of CHAR-TABLE.
546 The value is either nil or another char-table.
547 If CHAR-TABLE holds nil for a given character,
548 then the actual applicable value is inherited from the parent char-table
549 \(or from its parents, if necessary). */)
550 (Lisp_Object char_table
)
552 CHECK_CHAR_TABLE (char_table
);
554 return XCHAR_TABLE (char_table
)->parent
;
557 DEFUN ("set-char-table-parent", Fset_char_table_parent
, Sset_char_table_parent
,
559 doc
: /* Set the parent char-table of CHAR-TABLE to PARENT.
560 Return PARENT. PARENT must be either nil or another char-table. */)
561 (Lisp_Object char_table
, Lisp_Object parent
)
565 CHECK_CHAR_TABLE (char_table
);
569 CHECK_CHAR_TABLE (parent
);
571 for (temp
= parent
; !NILP (temp
); temp
= XCHAR_TABLE (temp
)->parent
)
572 if (EQ (temp
, char_table
))
573 error ("Attempt to make a chartable be its own parent");
576 set_char_table_parent (char_table
, parent
);
581 DEFUN ("char-table-extra-slot", Fchar_table_extra_slot
, Schar_table_extra_slot
,
583 doc
: /* Return the value of CHAR-TABLE's extra-slot number N. */)
584 (Lisp_Object char_table
, Lisp_Object n
)
586 CHECK_CHAR_TABLE (char_table
);
589 || XINT (n
) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table
)))
590 args_out_of_range (char_table
, n
);
592 return XCHAR_TABLE (char_table
)->extras
[XINT (n
)];
595 DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot
,
596 Sset_char_table_extra_slot
,
598 doc
: /* Set CHAR-TABLE's extra-slot number N to VALUE. */)
599 (Lisp_Object char_table
, Lisp_Object n
, Lisp_Object value
)
601 CHECK_CHAR_TABLE (char_table
);
604 || XINT (n
) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table
)))
605 args_out_of_range (char_table
, n
);
607 set_char_table_extras (char_table
, XINT (n
), value
);
611 DEFUN ("char-table-range", Fchar_table_range
, Schar_table_range
,
613 doc
: /* Return the value in CHAR-TABLE for a range of characters RANGE.
614 RANGE should be nil (for the default value),
615 a cons of character codes (for characters in the range), or a character code. */)
616 (Lisp_Object char_table
, Lisp_Object range
)
619 CHECK_CHAR_TABLE (char_table
);
621 if (EQ (range
, Qnil
))
622 val
= XCHAR_TABLE (char_table
)->defalt
;
623 else if (CHARACTERP (range
))
624 val
= CHAR_TABLE_REF (char_table
, XFASTINT (range
));
625 else if (CONSP (range
))
629 CHECK_CHARACTER_CAR (range
);
630 CHECK_CHARACTER_CDR (range
);
631 from
= XFASTINT (XCAR (range
));
632 to
= XFASTINT (XCDR (range
));
633 val
= char_table_ref_and_range (char_table
, from
, &from
, &to
);
634 /* Not yet implemented. */
637 error ("Invalid RANGE argument to `char-table-range'");
641 DEFUN ("set-char-table-range", Fset_char_table_range
, Sset_char_table_range
,
643 doc
: /* Set the value in CHAR-TABLE for a range of characters RANGE to VALUE.
644 RANGE should be t (for all characters), nil (for the default value),
645 a cons of character codes (for characters in the range),
646 or a character code. Return VALUE. */)
647 (Lisp_Object char_table
, Lisp_Object range
, Lisp_Object value
)
649 CHECK_CHAR_TABLE (char_table
);
654 set_char_table_ascii (char_table
, value
);
655 for (i
= 0; i
< chartab_size
[0]; i
++)
656 set_char_table_contents (char_table
, i
, value
);
658 else if (EQ (range
, Qnil
))
659 set_char_table_defalt (char_table
, value
);
660 else if (CHARACTERP (range
))
661 char_table_set (char_table
, XINT (range
), value
);
662 else if (CONSP (range
))
664 CHECK_CHARACTER_CAR (range
);
665 CHECK_CHARACTER_CDR (range
);
666 char_table_set_range (char_table
,
667 XINT (XCAR (range
)), XINT (XCDR (range
)), value
);
670 error ("Invalid RANGE argument to `set-char-table-range'");
675 /* Look up the element in TABLE at index CH, and return it as an
676 integer. If the element is not a character, return CH itself. */
679 char_table_translate (Lisp_Object table
, int ch
)
682 value
= Faref (table
, make_number (ch
));
683 if (! CHARACTERP (value
))
689 optimize_sub_char_table (Lisp_Object table
, Lisp_Object test
)
691 struct Lisp_Sub_Char_Table
*tbl
= XSUB_CHAR_TABLE (table
);
692 int depth
= XINT (tbl
->depth
);
693 Lisp_Object elt
, this;
697 elt
= XSUB_CHAR_TABLE (table
)->contents
[0];
698 if (SUB_CHAR_TABLE_P (elt
))
700 elt
= optimize_sub_char_table (elt
, test
);
701 set_sub_char_table_contents (table
, 0, elt
);
703 optimizable
= SUB_CHAR_TABLE_P (elt
) ? 0 : 1;
704 for (i
= 1; i
< chartab_size
[depth
]; i
++)
706 this = XSUB_CHAR_TABLE (table
)->contents
[i
];
707 if (SUB_CHAR_TABLE_P (this))
709 this = optimize_sub_char_table (this, test
);
710 set_sub_char_table_contents (table
, i
, this);
713 && (NILP (test
) ? NILP (Fequal (this, elt
)) /* defaults to `equal'. */
714 : EQ (test
, Qeq
) ? !EQ (this, elt
) /* Optimize `eq' case. */
715 : NILP (call2 (test
, this, elt
))))
719 return (optimizable
? elt
: table
);
722 DEFUN ("optimize-char-table", Foptimize_char_table
, Soptimize_char_table
,
724 doc
: /* Optimize CHAR-TABLE.
725 TEST is the comparison function used to decide whether two entries are
726 equivalent and can be merged. It defaults to `equal'. */)
727 (Lisp_Object char_table
, Lisp_Object test
)
732 CHECK_CHAR_TABLE (char_table
);
734 for (i
= 0; i
< chartab_size
[0]; i
++)
736 elt
= XCHAR_TABLE (char_table
)->contents
[i
];
737 if (SUB_CHAR_TABLE_P (elt
))
738 set_char_table_contents
739 (char_table
, i
, optimize_sub_char_table (elt
, test
));
741 /* Reset the `ascii' cache, in case it got optimized away. */
742 set_char_table_ascii (char_table
, char_table_ascii (char_table
));
748 /* Map C_FUNCTION or FUNCTION over TABLE (top or sub char-table),
749 calling it for each character or group of characters that share a
750 value. RANGE is a cons (FROM . TO) specifying the range of target
751 characters, VAL is a value of FROM in TABLE, TOP is the top
754 ARG is passed to C_FUNCTION when that is called.
756 It returns the value of last character covered by TABLE (not the
757 value inherited from the parent), and by side-effect, the car part
758 of RANGE is updated to the minimum character C where C and all the
759 following characters in TABLE have the same value. */
762 map_sub_char_table (void (*c_function
) (Lisp_Object
, Lisp_Object
, Lisp_Object
),
763 Lisp_Object function
, Lisp_Object table
, Lisp_Object arg
, Lisp_Object val
,
764 Lisp_Object range
, Lisp_Object top
)
766 /* Depth of TABLE. */
768 /* Minimum and maximum characters covered by TABLE. */
769 int min_char
, max_char
;
770 /* Number of characters covered by one element of TABLE. */
772 int from
= XINT (XCAR (range
)), to
= XINT (XCDR (range
));
774 bool is_uniprop
= UNIPROP_TABLE_P (top
);
775 uniprop_decoder_t decoder
= UNIPROP_GET_DECODER (top
);
777 if (SUB_CHAR_TABLE_P (table
))
779 struct Lisp_Sub_Char_Table
*tbl
= XSUB_CHAR_TABLE (table
);
781 depth
= XINT (tbl
->depth
);
782 min_char
= XINT (tbl
->min_char
);
783 max_char
= min_char
+ chartab_chars
[depth
- 1] - 1;
791 chars_in_block
= chartab_chars
[depth
];
795 /* Set I to the index of the first element to check. */
796 if (from
<= min_char
)
799 i
= (from
- min_char
) / chars_in_block
;
800 for (c
= min_char
+ chars_in_block
* i
; c
<= max_char
;
801 i
++, c
+= chars_in_block
)
803 Lisp_Object
this = (SUB_CHAR_TABLE_P (table
)
804 ? XSUB_CHAR_TABLE (table
)->contents
[i
]
805 : XCHAR_TABLE (table
)->contents
[i
]);
806 int nextc
= c
+ chars_in_block
;
808 if (is_uniprop
&& UNIPROP_COMPRESSED_FORM_P (this))
809 this = uniprop_table_uncompress (table
, i
);
810 if (SUB_CHAR_TABLE_P (this))
813 XSETCDR (range
, make_number (nextc
- 1));
814 val
= map_sub_char_table (c_function
, function
, this, arg
,
820 this = XCHAR_TABLE (top
)->defalt
;
823 bool different_value
= 1;
827 if (! NILP (XCHAR_TABLE (top
)->parent
))
829 Lisp_Object parent
= XCHAR_TABLE (top
)->parent
;
830 Lisp_Object temp
= XCHAR_TABLE (parent
)->parent
;
832 /* This is to get a value of FROM in PARENT
833 without checking the parent of PARENT. */
834 set_char_table_parent (parent
, Qnil
);
835 val
= CHAR_TABLE_REF (parent
, from
);
836 set_char_table_parent (parent
, temp
);
837 XSETCDR (range
, make_number (c
- 1));
838 val
= map_sub_char_table (c_function
, function
,
839 parent
, arg
, val
, range
,
845 if (! NILP (val
) && different_value
)
847 XSETCDR (range
, make_number (c
- 1));
848 if (EQ (XCAR (range
), XCDR (range
)))
851 (*c_function
) (arg
, XCAR (range
), val
);
855 val
= decoder (top
, val
);
856 call2 (function
, XCAR (range
), val
);
862 (*c_function
) (arg
, range
, val
);
866 val
= decoder (top
, val
);
867 call2 (function
, range
, val
);
873 XSETCAR (range
, make_number (c
));
876 XSETCDR (range
, make_number (to
));
882 /* Map C_FUNCTION or FUNCTION over TABLE, calling it for each
883 character or group of characters that share a value.
885 ARG is passed to C_FUNCTION when that is called. */
888 map_char_table (void (*c_function
) (Lisp_Object
, Lisp_Object
, Lisp_Object
),
889 Lisp_Object function
, Lisp_Object table
, Lisp_Object arg
)
891 Lisp_Object range
, val
, parent
;
892 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
893 uniprop_decoder_t decoder
= UNIPROP_GET_DECODER (table
);
895 range
= Fcons (make_number (0), make_number (MAX_CHAR
));
896 parent
= XCHAR_TABLE (table
)->parent
;
898 GCPRO4 (table
, arg
, range
, parent
);
899 val
= XCHAR_TABLE (table
)->ascii
;
900 if (SUB_CHAR_TABLE_P (val
))
901 val
= XSUB_CHAR_TABLE (val
)->contents
[0];
902 val
= map_sub_char_table (c_function
, function
, table
, arg
, val
, range
,
905 /* If VAL is nil and TABLE has a parent, we must consult the parent
907 while (NILP (val
) && ! NILP (XCHAR_TABLE (table
)->parent
))
910 int from
= XINT (XCAR (range
));
912 parent
= XCHAR_TABLE (table
)->parent
;
913 temp
= XCHAR_TABLE (parent
)->parent
;
914 /* This is to get a value of FROM in PARENT without checking the
916 set_char_table_parent (parent
, Qnil
);
917 val
= CHAR_TABLE_REF (parent
, from
);
918 set_char_table_parent (parent
, temp
);
919 val
= map_sub_char_table (c_function
, function
, parent
, arg
, val
, range
,
926 if (EQ (XCAR (range
), XCDR (range
)))
929 (*c_function
) (arg
, XCAR (range
), val
);
933 val
= decoder (table
, val
);
934 call2 (function
, XCAR (range
), val
);
940 (*c_function
) (arg
, range
, val
);
944 val
= decoder (table
, val
);
945 call2 (function
, range
, val
);
953 DEFUN ("map-char-table", Fmap_char_table
, Smap_char_table
,
955 doc
: /* Call FUNCTION for each character in CHAR-TABLE that has non-nil value.
956 FUNCTION is called with two arguments, KEY and VALUE.
957 KEY is a character code or a cons of character codes specifying a
958 range of characters that have the same value.
959 VALUE is what (char-table-range CHAR-TABLE KEY) returns. */)
960 (Lisp_Object function
, Lisp_Object char_table
)
962 CHECK_CHAR_TABLE (char_table
);
964 map_char_table (NULL
, function
, char_table
, char_table
);
970 map_sub_char_table_for_charset (void (*c_function
) (Lisp_Object
, Lisp_Object
),
971 Lisp_Object function
, Lisp_Object table
, Lisp_Object arg
,
972 Lisp_Object range
, struct charset
*charset
,
973 unsigned from
, unsigned to
)
975 struct Lisp_Sub_Char_Table
*tbl
= XSUB_CHAR_TABLE (table
);
976 int depth
= XINT (tbl
->depth
);
980 for (i
= 0, c
= XINT (tbl
->min_char
); i
< chartab_size
[depth
];
981 i
++, c
+= chartab_chars
[depth
])
985 this = tbl
->contents
[i
];
986 if (SUB_CHAR_TABLE_P (this))
987 map_sub_char_table_for_charset (c_function
, function
, this, arg
,
988 range
, charset
, from
, to
);
991 if (! NILP (XCAR (range
)))
993 XSETCDR (range
, make_number (c
- 1));
995 (*c_function
) (arg
, range
);
997 call2 (function
, range
, arg
);
999 XSETCAR (range
, Qnil
);
1003 for (i
= 0, c
= XINT (tbl
->min_char
); i
< chartab_size
[depth
]; i
++, c
++)
1008 this = tbl
->contents
[i
];
1011 && (code
= ENCODE_CHAR (charset
, c
),
1012 (code
< from
|| code
> to
))))
1014 if (! NILP (XCAR (range
)))
1016 XSETCDR (range
, make_number (c
- 1));
1018 (*c_function
) (arg
, range
);
1020 call2 (function
, range
, arg
);
1021 XSETCAR (range
, Qnil
);
1026 if (NILP (XCAR (range
)))
1027 XSETCAR (range
, make_number (c
));
1033 /* Support function for `map-charset-chars'. Map C_FUNCTION or
1034 FUNCTION over TABLE, calling it for each character or a group of
1035 succeeding characters that have non-nil value in TABLE. TABLE is a
1036 "mapping table" or a "deunifier table" of a certain charset.
1038 If CHARSET is not NULL (this is the case that `map-charset-chars'
1039 is called with non-nil FROM-CODE and TO-CODE), it is a charset who
1040 owns TABLE, and the function is called only on a character in the
1041 range FROM and TO. FROM and TO are not character codes, but code
1042 points of a character in CHARSET.
1044 This function is called in these two cases:
1046 (1) A charset has a mapping file name in :map property.
1048 (2) A charset has an upper code space in :offset property and a
1049 mapping file name in :unify-map property. In this case, this
1050 function is called only for characters in the Unicode code space.
1051 Characters in upper code space are handled directly in
1052 map_charset_chars. */
1055 map_char_table_for_charset (void (*c_function
) (Lisp_Object
, Lisp_Object
),
1056 Lisp_Object function
, Lisp_Object table
, Lisp_Object arg
,
1057 struct charset
*charset
,
1058 unsigned from
, unsigned to
)
1062 struct gcpro gcpro1
;
1064 range
= Fcons (Qnil
, Qnil
);
1067 for (i
= 0, c
= 0; i
< chartab_size
[0]; i
++, c
+= chartab_chars
[0])
1071 this = XCHAR_TABLE (table
)->contents
[i
];
1072 if (SUB_CHAR_TABLE_P (this))
1073 map_sub_char_table_for_charset (c_function
, function
, this, arg
,
1074 range
, charset
, from
, to
);
1077 if (! NILP (XCAR (range
)))
1079 XSETCDR (range
, make_number (c
- 1));
1081 (*c_function
) (arg
, range
);
1083 call2 (function
, range
, arg
);
1085 XSETCAR (range
, Qnil
);
1088 if (! NILP (XCAR (range
)))
1090 XSETCDR (range
, make_number (c
- 1));
1092 (*c_function
) (arg
, range
);
1094 call2 (function
, range
, arg
);
1101 /* Unicode character property tables.
1103 This section provides a convenient and efficient way to get Unicode
1104 character properties of characters from C code (from Lisp, you must
1105 use get-char-code-property).
1107 The typical usage is to get a char-table object for a specific
1108 property like this (use of the "bidi-class" property below is just
1111 Lisp_Object bidi_class_table = uniprop_table (intern ("bidi-class"));
1113 (uniprop_table can return nil if it fails to find data for the
1114 named property, or if it fails to load the appropriate Lisp support
1115 file, so the return value should be tested to be non-nil, before it
1118 To get a property value for character CH use CHAR_TABLE_REF:
1120 Lisp_Object bidi_class = CHAR_TABLE_REF (bidi_class_table, CH);
1122 In this case, what you actually get is an index number to the
1123 vector of property values (symbols nil, L, R, etc).
1125 The full list of Unicode character properties supported by Emacs is
1126 documented in the ELisp manual, in the node "Character Properties".
1128 A table for Unicode character property has these characteristics:
1130 o The purpose is `char-code-property-table', which implies that the
1131 table has 5 extra slots.
1133 o The second extra slot is a Lisp function, an index (integer) to
1134 the array uniprop_decoder[], or nil. If it is a Lisp function, we
1135 can't use such a table from C (at the moment). If it is nil, it
1136 means that we don't have to decode values.
1138 o The third extra slot is a Lisp function, an index (integer) to
1139 the array uniprop_encoder[], or nil. If it is a Lisp function, we
1140 can't use such a table from C (at the moment). If it is nil, it
1141 means that we don't have to encode values. */
1144 /* Uncompress the IDXth element of sub-char-table TABLE. */
1147 uniprop_table_uncompress (Lisp_Object table
, int idx
)
1149 Lisp_Object val
= XSUB_CHAR_TABLE (table
)->contents
[idx
];
1150 int min_char
= (XINT (XSUB_CHAR_TABLE (table
)->min_char
)
1151 + chartab_chars
[2] * idx
);
1152 Lisp_Object sub
= make_sub_char_table (3, min_char
, Qnil
);
1153 const unsigned char *p
, *pend
;
1155 set_sub_char_table_contents (table
, idx
, sub
);
1156 p
= SDATA (val
), pend
= p
+ SBYTES (val
);
1161 idx
= STRING_CHAR_ADVANCE (p
);
1162 while (p
< pend
&& idx
< chartab_chars
[2])
1164 int v
= STRING_CHAR_ADVANCE (p
);
1165 set_sub_char_table_contents
1166 (sub
, idx
++, v
> 0 ? make_number (v
) : Qnil
);
1171 /* RUN-LENGTH TABLE */
1173 for (idx
= 0; p
< pend
; )
1175 int v
= STRING_CHAR_ADVANCE (p
);
1181 count
= STRING_CHAR_AND_LENGTH (p
, len
);
1191 set_sub_char_table_contents (sub
, idx
++, make_number (v
));
1194 /* It seems that we don't need this function because C code won't need
1195 to get a property that is compressed in this form. */
1199 /* WORD-LIST TABLE */
1206 /* Decode VALUE as an element of char-table TABLE. */
1209 uniprop_decode_value_run_length (Lisp_Object table
, Lisp_Object value
)
1211 if (VECTORP (XCHAR_TABLE (table
)->extras
[4]))
1213 Lisp_Object valvec
= XCHAR_TABLE (table
)->extras
[4];
1215 if (XINT (value
) >= 0 && XINT (value
) < ASIZE (valvec
))
1216 value
= AREF (valvec
, XINT (value
));
1221 static uniprop_decoder_t uniprop_decoder
[] =
1222 { uniprop_decode_value_run_length
};
1224 static const int uniprop_decoder_count
= ARRAYELTS (uniprop_decoder
);
1226 /* Return the decoder of char-table TABLE or nil if none. */
1228 static uniprop_decoder_t
1229 uniprop_get_decoder (Lisp_Object table
)
1233 if (! INTEGERP (XCHAR_TABLE (table
)->extras
[1]))
1235 i
= XINT (XCHAR_TABLE (table
)->extras
[1]);
1236 if (i
< 0 || i
>= uniprop_decoder_count
)
1238 return uniprop_decoder
[i
];
1242 /* Encode VALUE as an element of char-table TABLE which contains
1243 characters as elements. */
1246 uniprop_encode_value_character (Lisp_Object table
, Lisp_Object value
)
1248 if (! NILP (value
) && ! CHARACTERP (value
))
1249 wrong_type_argument (Qintegerp
, value
);
1254 /* Encode VALUE as an element of char-table TABLE which adopts RUN-LENGTH
1258 uniprop_encode_value_run_length (Lisp_Object table
, Lisp_Object value
)
1260 Lisp_Object
*value_table
= XVECTOR (XCHAR_TABLE (table
)->extras
[4])->contents
;
1261 int i
, size
= ASIZE (XCHAR_TABLE (table
)->extras
[4]);
1263 for (i
= 0; i
< size
; i
++)
1264 if (EQ (value
, value_table
[i
]))
1267 wrong_type_argument (build_string ("Unicode property value"), value
);
1268 return make_number (i
);
1272 /* Encode VALUE as an element of char-table TABLE which adopts RUN-LENGTH
1273 compression and contains numbers as elements. */
1276 uniprop_encode_value_numeric (Lisp_Object table
, Lisp_Object value
)
1278 Lisp_Object
*value_table
= XVECTOR (XCHAR_TABLE (table
)->extras
[4])->contents
;
1279 int i
, size
= ASIZE (XCHAR_TABLE (table
)->extras
[4]);
1281 CHECK_NUMBER (value
);
1282 for (i
= 0; i
< size
; i
++)
1283 if (EQ (value
, value_table
[i
]))
1285 value
= make_number (i
);
1288 Lisp_Object args
[2];
1290 args
[0] = XCHAR_TABLE (table
)->extras
[4];
1291 args
[1] = Fmake_vector (make_number (1), value
);
1292 set_char_table_extras (table
, 4, Fvconcat (2, args
));
1294 return make_number (i
);
1297 static uniprop_encoder_t uniprop_encoder
[] =
1298 { uniprop_encode_value_character
,
1299 uniprop_encode_value_run_length
,
1300 uniprop_encode_value_numeric
};
1302 static const int uniprop_encoder_count
= ARRAYELTS (uniprop_encoder
);
1304 /* Return the encoder of char-table TABLE or nil if none. */
1306 static uniprop_decoder_t
1307 uniprop_get_encoder (Lisp_Object table
)
1311 if (! INTEGERP (XCHAR_TABLE (table
)->extras
[2]))
1313 i
= XINT (XCHAR_TABLE (table
)->extras
[2]);
1314 if (i
< 0 || i
>= uniprop_encoder_count
)
1316 return uniprop_encoder
[i
];
1319 /* Return a char-table for Unicode character property PROP. This
1320 function may load a Lisp file and thus may cause
1321 garbage-collection. */
1324 uniprop_table (Lisp_Object prop
)
1326 Lisp_Object val
, table
, result
;
1328 val
= Fassq (prop
, Vchar_code_property_alist
);
1332 if (STRINGP (table
))
1334 struct gcpro gcpro1
;
1336 result
= Fload (concat2 (build_string ("international/"), table
),
1343 if (! CHAR_TABLE_P (table
)
1344 || ! UNIPROP_TABLE_P (table
))
1346 val
= XCHAR_TABLE (table
)->extras
[1];
1348 ? (XINT (val
) < 0 || XINT (val
) >= uniprop_decoder_count
)
1351 /* Prepare ASCII values in advance for CHAR_TABLE_REF. */
1352 set_char_table_ascii (table
, char_table_ascii (table
));
1356 DEFUN ("unicode-property-table-internal", Funicode_property_table_internal
,
1357 Sunicode_property_table_internal
, 1, 1, 0,
1358 doc
: /* Return a char-table for Unicode character property PROP.
1359 Use `get-unicode-property-internal' and
1360 `put-unicode-property-internal' instead of `aref' and `aset' to get
1361 and put an element value. */)
1364 Lisp_Object table
= uniprop_table (prop
);
1366 if (CHAR_TABLE_P (table
))
1368 return Fcdr (Fassq (prop
, Vchar_code_property_alist
));
1371 DEFUN ("get-unicode-property-internal", Fget_unicode_property_internal
,
1372 Sget_unicode_property_internal
, 2, 2, 0,
1373 doc
: /* Return an element of CHAR-TABLE for character CH.
1374 CHAR-TABLE must be what returned by `unicode-property-table-internal'. */)
1375 (Lisp_Object char_table
, Lisp_Object ch
)
1378 uniprop_decoder_t decoder
;
1380 CHECK_CHAR_TABLE (char_table
);
1381 CHECK_CHARACTER (ch
);
1382 if (! UNIPROP_TABLE_P (char_table
))
1383 error ("Invalid Unicode property table");
1384 val
= CHAR_TABLE_REF (char_table
, XINT (ch
));
1385 decoder
= uniprop_get_decoder (char_table
);
1386 return (decoder
? decoder (char_table
, val
) : val
);
1389 DEFUN ("put-unicode-property-internal", Fput_unicode_property_internal
,
1390 Sput_unicode_property_internal
, 3, 3, 0,
1391 doc
: /* Set an element of CHAR-TABLE for character CH to VALUE.
1392 CHAR-TABLE must be what returned by `unicode-property-table-internal'. */)
1393 (Lisp_Object char_table
, Lisp_Object ch
, Lisp_Object value
)
1395 uniprop_encoder_t encoder
;
1397 CHECK_CHAR_TABLE (char_table
);
1398 CHECK_CHARACTER (ch
);
1399 if (! UNIPROP_TABLE_P (char_table
))
1400 error ("Invalid Unicode property table");
1401 encoder
= uniprop_get_encoder (char_table
);
1403 value
= encoder (char_table
, value
);
1404 CHAR_TABLE_SET (char_table
, XINT (ch
), value
);
1410 syms_of_chartab (void)
1412 DEFSYM (Qchar_code_property_table
, "char-code-property-table");
1414 defsubr (&Smake_char_table
);
1415 defsubr (&Schar_table_parent
);
1416 defsubr (&Schar_table_subtype
);
1417 defsubr (&Sset_char_table_parent
);
1418 defsubr (&Schar_table_extra_slot
);
1419 defsubr (&Sset_char_table_extra_slot
);
1420 defsubr (&Schar_table_range
);
1421 defsubr (&Sset_char_table_range
);
1422 defsubr (&Soptimize_char_table
);
1423 defsubr (&Smap_char_table
);
1424 defsubr (&Sunicode_property_table_internal
);
1425 defsubr (&Sget_unicode_property_internal
);
1426 defsubr (&Sput_unicode_property_internal
);
1428 /* Each element has the form (PROP . TABLE).
1429 PROP is a symbol representing a character property.
1430 TABLE is a char-table containing the property value for each character.
1431 TABLE may be a name of file to load to build a char-table.
1432 This variable should be modified only through
1433 `define-char-code-property'. */
1435 DEFVAR_LISP ("char-code-property-alist", Vchar_code_property_alist
,
1436 doc
: /* Alist of character property name vs char-table containing property values.
1437 Internal use only. */);
1438 Vchar_code_property_alist
= Qnil
;