Auto-commit of loaddefs files.
[emacs.git] / src / chartab.c
blob7430235b4afa3fddb43cd7efe09e05b569ee7d87
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/>. */
21 #include <config.h>
23 #include "lisp.h"
24 #include "character.h"
25 #include "charset.h"
26 #include "ccl.h"
28 /* 64/16/32/128 */
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
38 covers. */
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),
43 1 };
45 /* Number of characters (in bits) each element of Nth level char-table
46 covers. */
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),
50 CHARTAB_SIZE_BITS_3,
51 0 };
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 DEFUN ("make-char-table", Fmake_char_table, Smake_char_table, 1, 2, 0,
89 doc: /* Return a newly created char-table, with purpose PURPOSE.
90 Each element is initialized to INIT, which defaults to nil.
92 PURPOSE should be a symbol. If it has a `char-table-extra-slots'
93 property, the property's value should be an integer between 0 and 10
94 that specifies how many extra slots the char-table has. Otherwise,
95 the char-table has no extra slot. */)
96 (register Lisp_Object purpose, Lisp_Object init)
98 Lisp_Object vector;
99 Lisp_Object n;
100 int n_extras;
101 int size;
103 CHECK_SYMBOL (purpose);
104 n = Fget (purpose, Qchar_table_extra_slots);
105 if (NILP (n))
106 n_extras = 0;
107 else
109 CHECK_NATNUM (n);
110 if (XINT (n) > 10)
111 args_out_of_range (n, Qnil);
112 n_extras = XINT (n);
115 size = VECSIZE (struct Lisp_Char_Table) - 1 + n_extras;
116 vector = Fmake_vector (make_number (size), init);
117 XSETPVECTYPE (XVECTOR (vector), PVEC_CHAR_TABLE);
118 set_char_table_parent (vector, Qnil);
119 set_char_table_purpose (vector, purpose);
120 XSETCHAR_TABLE (vector, XCHAR_TABLE (vector));
121 return vector;
124 static Lisp_Object
125 make_sub_char_table (int depth, int min_char, Lisp_Object defalt)
127 Lisp_Object table;
128 int size = VECSIZE (struct Lisp_Sub_Char_Table) - 1 + chartab_size[depth];
130 table = Fmake_vector (make_number (size), defalt);
131 XSETPVECTYPE (XVECTOR (table), PVEC_SUB_CHAR_TABLE);
132 XSUB_CHAR_TABLE (table)->depth = make_number (depth);
133 XSUB_CHAR_TABLE (table)->min_char = make_number (min_char);
135 return table;
138 static Lisp_Object
139 char_table_ascii (Lisp_Object table)
141 Lisp_Object sub, val;
143 sub = XCHAR_TABLE (table)->contents[0];
144 if (! SUB_CHAR_TABLE_P (sub))
145 return sub;
146 sub = XSUB_CHAR_TABLE (sub)->contents[0];
147 if (! SUB_CHAR_TABLE_P (sub))
148 return sub;
149 val = XSUB_CHAR_TABLE (sub)->contents[0];
150 if (UNIPROP_TABLE_P (table) && UNIPROP_COMPRESSED_FORM_P (val))
151 val = uniprop_table_uncompress (sub, 0);
152 return val;
155 static Lisp_Object
156 copy_sub_char_table (Lisp_Object table)
158 int depth = XINT (XSUB_CHAR_TABLE (table)->depth);
159 int min_char = XINT (XSUB_CHAR_TABLE (table)->min_char);
160 Lisp_Object copy = make_sub_char_table (depth, min_char, Qnil);
161 int i;
163 /* Recursively copy any sub char-tables. */
164 for (i = 0; i < chartab_size[depth]; i++)
166 Lisp_Object val = XSUB_CHAR_TABLE (table)->contents[i];
167 set_sub_char_table_contents
168 (copy, i, SUB_CHAR_TABLE_P (val) ? copy_sub_char_table (val) : val);
171 return copy;
175 Lisp_Object
176 copy_char_table (Lisp_Object table)
178 Lisp_Object copy;
179 int size = XCHAR_TABLE (table)->header.size & PSEUDOVECTOR_SIZE_MASK;
180 int i;
182 copy = Fmake_vector (make_number (size), Qnil);
183 XSETPVECTYPE (XVECTOR (copy), PVEC_CHAR_TABLE);
184 set_char_table_defalt (copy, XCHAR_TABLE (table)->defalt);
185 set_char_table_parent (copy, XCHAR_TABLE (table)->parent);
186 set_char_table_purpose (copy, XCHAR_TABLE (table)->purpose);
187 for (i = 0; i < chartab_size[0]; i++)
188 set_char_table_contents
189 (copy, i,
190 (SUB_CHAR_TABLE_P (XCHAR_TABLE (table)->contents[i])
191 ? copy_sub_char_table (XCHAR_TABLE (table)->contents[i])
192 : XCHAR_TABLE (table)->contents[i]));
193 set_char_table_ascii (copy, char_table_ascii (copy));
194 size -= VECSIZE (struct Lisp_Char_Table) - 1;
195 for (i = 0; i < size; i++)
196 set_char_table_extras (copy, i, XCHAR_TABLE (table)->extras[i]);
198 XSETCHAR_TABLE (copy, XCHAR_TABLE (copy));
199 return copy;
202 static Lisp_Object
203 sub_char_table_ref (Lisp_Object table, int c, bool is_uniprop)
205 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
206 int depth = XINT (tbl->depth);
207 int min_char = XINT (tbl->min_char);
208 Lisp_Object val;
209 int idx = CHARTAB_IDX (c, depth, min_char);
211 val = tbl->contents[idx];
212 if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (val))
213 val = uniprop_table_uncompress (table, idx);
214 if (SUB_CHAR_TABLE_P (val))
215 val = sub_char_table_ref (val, c, is_uniprop);
216 return val;
219 Lisp_Object
220 char_table_ref (Lisp_Object table, int c)
222 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
223 Lisp_Object val;
225 if (ASCII_CHAR_P (c))
227 val = tbl->ascii;
228 if (SUB_CHAR_TABLE_P (val))
229 val = XSUB_CHAR_TABLE (val)->contents[c];
231 else
233 val = tbl->contents[CHARTAB_IDX (c, 0, 0)];
234 if (SUB_CHAR_TABLE_P (val))
235 val = sub_char_table_ref (val, c, UNIPROP_TABLE_P (table));
237 if (NILP (val))
239 val = tbl->defalt;
240 if (NILP (val) && CHAR_TABLE_P (tbl->parent))
241 val = char_table_ref (tbl->parent, c);
243 return val;
246 static Lisp_Object
247 sub_char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to,
248 Lisp_Object defalt, bool is_uniprop)
250 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
251 int depth = XINT (tbl->depth);
252 int min_char = XINT (tbl->min_char);
253 int chartab_idx = CHARTAB_IDX (c, depth, min_char), idx;
254 Lisp_Object val;
256 val = tbl->contents[chartab_idx];
257 if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (val))
258 val = uniprop_table_uncompress (table, chartab_idx);
259 if (SUB_CHAR_TABLE_P (val))
260 val = sub_char_table_ref_and_range (val, c, from, to, defalt, is_uniprop);
261 else if (NILP (val))
262 val = defalt;
264 idx = chartab_idx;
265 while (idx > 0 && *from < min_char + idx * chartab_chars[depth])
267 Lisp_Object this_val;
269 c = min_char + idx * chartab_chars[depth] - 1;
270 idx--;
271 this_val = tbl->contents[idx];
272 if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (this_val))
273 this_val = uniprop_table_uncompress (table, idx);
274 if (SUB_CHAR_TABLE_P (this_val))
275 this_val = sub_char_table_ref_and_range (this_val, c, from, to, defalt,
276 is_uniprop);
277 else if (NILP (this_val))
278 this_val = defalt;
280 if (! EQ (this_val, val))
282 *from = c + 1;
283 break;
286 while (((c = (chartab_idx + 1) * chartab_chars[depth])
287 < chartab_chars[depth - 1])
288 && (c += min_char) <= *to)
290 Lisp_Object this_val;
292 chartab_idx++;
293 this_val = tbl->contents[chartab_idx];
294 if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (this_val))
295 this_val = uniprop_table_uncompress (table, chartab_idx);
296 if (SUB_CHAR_TABLE_P (this_val))
297 this_val = sub_char_table_ref_and_range (this_val, c, from, to, defalt,
298 is_uniprop);
299 else if (NILP (this_val))
300 this_val = defalt;
301 if (! EQ (this_val, val))
303 *to = c - 1;
304 break;
308 return val;
312 /* Return the value for C in char-table TABLE. Shrink the range *FROM
313 and *TO to cover characters (containing C) that have the same value
314 as C. It is not assured that the values of (*FROM - 1) and (*TO +
315 1) are different from that of C. */
317 Lisp_Object
318 char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to)
320 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
321 int chartab_idx = CHARTAB_IDX (c, 0, 0), idx;
322 Lisp_Object val;
323 bool is_uniprop = UNIPROP_TABLE_P (table);
325 val = tbl->contents[chartab_idx];
326 if (*from < 0)
327 *from = 0;
328 if (*to < 0)
329 *to = MAX_CHAR;
330 if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (val))
331 val = uniprop_table_uncompress (table, chartab_idx);
332 if (SUB_CHAR_TABLE_P (val))
333 val = sub_char_table_ref_and_range (val, c, from, to, tbl->defalt,
334 is_uniprop);
335 else if (NILP (val))
336 val = tbl->defalt;
337 idx = chartab_idx;
338 while (*from < idx * chartab_chars[0])
340 Lisp_Object this_val;
342 c = idx * chartab_chars[0] - 1;
343 idx--;
344 this_val = tbl->contents[idx];
345 if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (this_val))
346 this_val = uniprop_table_uncompress (table, idx);
347 if (SUB_CHAR_TABLE_P (this_val))
348 this_val = sub_char_table_ref_and_range (this_val, c, from, to,
349 tbl->defalt, is_uniprop);
350 else if (NILP (this_val))
351 this_val = tbl->defalt;
353 if (! EQ (this_val, val))
355 *from = c + 1;
356 break;
359 while (*to >= (chartab_idx + 1) * chartab_chars[0])
361 Lisp_Object this_val;
363 chartab_idx++;
364 c = chartab_idx * chartab_chars[0];
365 this_val = tbl->contents[chartab_idx];
366 if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (this_val))
367 this_val = uniprop_table_uncompress (table, chartab_idx);
368 if (SUB_CHAR_TABLE_P (this_val))
369 this_val = sub_char_table_ref_and_range (this_val, c, from, to,
370 tbl->defalt, is_uniprop);
371 else if (NILP (this_val))
372 this_val = tbl->defalt;
373 if (! EQ (this_val, val))
375 *to = c - 1;
376 break;
380 return val;
384 static void
385 sub_char_table_set (Lisp_Object table, int c, Lisp_Object val, bool is_uniprop)
387 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
388 int depth = XINT ((tbl)->depth);
389 int min_char = XINT ((tbl)->min_char);
390 int i = CHARTAB_IDX (c, depth, min_char);
391 Lisp_Object sub;
393 if (depth == 3)
394 set_sub_char_table_contents (table, i, val);
395 else
397 sub = tbl->contents[i];
398 if (! SUB_CHAR_TABLE_P (sub))
400 if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (sub))
401 sub = uniprop_table_uncompress (table, i);
402 else
404 sub = make_sub_char_table (depth + 1,
405 min_char + i * chartab_chars[depth],
406 sub);
407 set_sub_char_table_contents (table, i, sub);
410 sub_char_table_set (sub, c, val, is_uniprop);
414 void
415 char_table_set (Lisp_Object table, int c, Lisp_Object val)
417 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
419 if (ASCII_CHAR_P (c)
420 && SUB_CHAR_TABLE_P (tbl->ascii))
421 set_sub_char_table_contents (tbl->ascii, c, val);
422 else
424 int i = CHARTAB_IDX (c, 0, 0);
425 Lisp_Object sub;
427 sub = tbl->contents[i];
428 if (! SUB_CHAR_TABLE_P (sub))
430 sub = make_sub_char_table (1, i * chartab_chars[0], sub);
431 set_char_table_contents (table, i, sub);
433 sub_char_table_set (sub, c, val, UNIPROP_TABLE_P (table));
434 if (ASCII_CHAR_P (c))
435 set_char_table_ascii (table, char_table_ascii (table));
439 static void
440 sub_char_table_set_range (Lisp_Object table, int from, int to, Lisp_Object val,
441 bool is_uniprop)
443 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
444 int depth = XINT ((tbl)->depth);
445 int min_char = XINT ((tbl)->min_char);
446 int chars_in_block = chartab_chars[depth];
447 int i, c, lim = chartab_size[depth];
449 if (from < min_char)
450 from = min_char;
451 i = CHARTAB_IDX (from, depth, min_char);
452 c = min_char + chars_in_block * i;
453 for (; i < lim; i++, c += chars_in_block)
455 if (c > to)
456 break;
457 if (from <= c && c + chars_in_block - 1 <= to)
458 set_sub_char_table_contents (table, i, val);
459 else
461 Lisp_Object sub = tbl->contents[i];
462 if (! SUB_CHAR_TABLE_P (sub))
464 if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (sub))
465 sub = uniprop_table_uncompress (table, i);
466 else
468 sub = make_sub_char_table (depth + 1, c, sub);
469 set_sub_char_table_contents (table, i, sub);
472 sub_char_table_set_range (sub, from, to, val, is_uniprop);
478 void
479 char_table_set_range (Lisp_Object table, int from, int to, Lisp_Object val)
481 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
483 if (from == to)
484 char_table_set (table, from, val);
485 else
487 bool is_uniprop = UNIPROP_TABLE_P (table);
488 int lim = CHARTAB_IDX (to, 0, 0);
489 int i, c;
491 for (i = CHARTAB_IDX (from, 0, 0), c = 0; i <= lim;
492 i++, c += chartab_chars[0])
494 if (c > to)
495 break;
496 if (from <= c && c + chartab_chars[0] - 1 <= to)
497 set_char_table_contents (table, i, val);
498 else
500 Lisp_Object sub = tbl->contents[i];
501 if (! SUB_CHAR_TABLE_P (sub))
503 sub = make_sub_char_table (1, i * chartab_chars[0], sub);
504 set_char_table_contents (table, i, sub);
506 sub_char_table_set_range (sub, from, to, val, is_uniprop);
509 if (ASCII_CHAR_P (from))
510 set_char_table_ascii (table, char_table_ascii (table));
515 DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype,
516 1, 1, 0,
517 doc: /*
518 Return the subtype of char-table CHAR-TABLE. The value is a symbol. */)
519 (Lisp_Object char_table)
521 CHECK_CHAR_TABLE (char_table);
523 return XCHAR_TABLE (char_table)->purpose;
526 DEFUN ("char-table-parent", Fchar_table_parent, Schar_table_parent,
527 1, 1, 0,
528 doc: /* Return the parent char-table of CHAR-TABLE.
529 The value is either nil or another char-table.
530 If CHAR-TABLE holds nil for a given character,
531 then the actual applicable value is inherited from the parent char-table
532 \(or from its parents, if necessary). */)
533 (Lisp_Object char_table)
535 CHECK_CHAR_TABLE (char_table);
537 return XCHAR_TABLE (char_table)->parent;
540 DEFUN ("set-char-table-parent", Fset_char_table_parent, Sset_char_table_parent,
541 2, 2, 0,
542 doc: /* Set the parent char-table of CHAR-TABLE to PARENT.
543 Return PARENT. PARENT must be either nil or another char-table. */)
544 (Lisp_Object char_table, Lisp_Object parent)
546 Lisp_Object temp;
548 CHECK_CHAR_TABLE (char_table);
550 if (!NILP (parent))
552 CHECK_CHAR_TABLE (parent);
554 for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent)
555 if (EQ (temp, char_table))
556 error ("Attempt to make a chartable be its own parent");
559 set_char_table_parent (char_table, parent);
561 return parent;
564 DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
565 2, 2, 0,
566 doc: /* Return the value of CHAR-TABLE's extra-slot number N. */)
567 (Lisp_Object char_table, Lisp_Object n)
569 CHECK_CHAR_TABLE (char_table);
570 CHECK_NUMBER (n);
571 if (XINT (n) < 0
572 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
573 args_out_of_range (char_table, n);
575 return XCHAR_TABLE (char_table)->extras[XINT (n)];
578 DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
579 Sset_char_table_extra_slot,
580 3, 3, 0,
581 doc: /* Set CHAR-TABLE's extra-slot number N to VALUE. */)
582 (Lisp_Object char_table, Lisp_Object n, Lisp_Object value)
584 CHECK_CHAR_TABLE (char_table);
585 CHECK_NUMBER (n);
586 if (XINT (n) < 0
587 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
588 args_out_of_range (char_table, n);
590 set_char_table_extras (char_table, XINT (n), value);
591 return value;
594 DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
595 2, 2, 0,
596 doc: /* Return the value in CHAR-TABLE for a range of characters RANGE.
597 RANGE should be nil (for the default value),
598 a cons of character codes (for characters in the range), or a character code. */)
599 (Lisp_Object char_table, Lisp_Object range)
601 Lisp_Object val;
602 CHECK_CHAR_TABLE (char_table);
604 if (EQ (range, Qnil))
605 val = XCHAR_TABLE (char_table)->defalt;
606 else if (CHARACTERP (range))
607 val = CHAR_TABLE_REF (char_table, XFASTINT (range));
608 else if (CONSP (range))
610 int from, to;
612 CHECK_CHARACTER_CAR (range);
613 CHECK_CHARACTER_CDR (range);
614 from = XFASTINT (XCAR (range));
615 to = XFASTINT (XCDR (range));
616 val = char_table_ref_and_range (char_table, from, &from, &to);
617 /* Not yet implemented. */
619 else
620 error ("Invalid RANGE argument to `char-table-range'");
621 return val;
624 DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
625 3, 3, 0,
626 doc: /* Set the value in CHAR-TABLE for a range of characters RANGE to VALUE.
627 RANGE should be t (for all characters), nil (for the default value),
628 a cons of character codes (for characters in the range),
629 or a character code. Return VALUE. */)
630 (Lisp_Object char_table, Lisp_Object range, Lisp_Object value)
632 CHECK_CHAR_TABLE (char_table);
633 if (EQ (range, Qt))
635 int i;
637 set_char_table_ascii (char_table, value);
638 for (i = 0; i < chartab_size[0]; i++)
639 set_char_table_contents (char_table, i, value);
641 else if (EQ (range, Qnil))
642 set_char_table_defalt (char_table, value);
643 else if (CHARACTERP (range))
644 char_table_set (char_table, XINT (range), value);
645 else if (CONSP (range))
647 CHECK_CHARACTER_CAR (range);
648 CHECK_CHARACTER_CDR (range);
649 char_table_set_range (char_table,
650 XINT (XCAR (range)), XINT (XCDR (range)), value);
652 else
653 error ("Invalid RANGE argument to `set-char-table-range'");
655 return value;
658 /* Look up the element in TABLE at index CH, and return it as an
659 integer. If the element is not a character, return CH itself. */
662 char_table_translate (Lisp_Object table, int ch)
664 Lisp_Object value;
665 value = Faref (table, make_number (ch));
666 if (! CHARACTERP (value))
667 return ch;
668 return XINT (value);
671 static Lisp_Object
672 optimize_sub_char_table (Lisp_Object table, Lisp_Object test)
674 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
675 int depth = XINT (tbl->depth);
676 Lisp_Object elt, this;
677 int i;
678 bool optimizable;
680 elt = XSUB_CHAR_TABLE (table)->contents[0];
681 if (SUB_CHAR_TABLE_P (elt))
683 elt = optimize_sub_char_table (elt, test);
684 set_sub_char_table_contents (table, 0, elt);
686 optimizable = SUB_CHAR_TABLE_P (elt) ? 0 : 1;
687 for (i = 1; i < chartab_size[depth]; i++)
689 this = XSUB_CHAR_TABLE (table)->contents[i];
690 if (SUB_CHAR_TABLE_P (this))
692 this = optimize_sub_char_table (this, test);
693 set_sub_char_table_contents (table, i, this);
695 if (optimizable
696 && (NILP (test) ? NILP (Fequal (this, elt)) /* defaults to `equal'. */
697 : EQ (test, Qeq) ? !EQ (this, elt) /* Optimize `eq' case. */
698 : NILP (call2 (test, this, elt))))
699 optimizable = 0;
702 return (optimizable ? elt : table);
705 DEFUN ("optimize-char-table", Foptimize_char_table, Soptimize_char_table,
706 1, 2, 0,
707 doc: /* Optimize CHAR-TABLE.
708 TEST is the comparison function used to decide whether two entries are
709 equivalent and can be merged. It defaults to `equal'. */)
710 (Lisp_Object char_table, Lisp_Object test)
712 Lisp_Object elt;
713 int i;
715 CHECK_CHAR_TABLE (char_table);
717 for (i = 0; i < chartab_size[0]; i++)
719 elt = XCHAR_TABLE (char_table)->contents[i];
720 if (SUB_CHAR_TABLE_P (elt))
721 set_char_table_contents
722 (char_table, i, optimize_sub_char_table (elt, test));
724 /* Reset the `ascii' cache, in case it got optimized away. */
725 set_char_table_ascii (char_table, char_table_ascii (char_table));
727 return Qnil;
731 /* Map C_FUNCTION or FUNCTION over TABLE (top or sub char-table),
732 calling it for each character or group of characters that share a
733 value. RANGE is a cons (FROM . TO) specifying the range of target
734 characters, VAL is a value of FROM in TABLE, TOP is the top
735 char-table.
737 ARG is passed to C_FUNCTION when that is called.
739 It returns the value of last character covered by TABLE (not the
740 value inherited from the parent), and by side-effect, the car part
741 of RANGE is updated to the minimum character C where C and all the
742 following characters in TABLE have the same value. */
744 static Lisp_Object
745 map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object),
746 Lisp_Object function, Lisp_Object table, Lisp_Object arg, Lisp_Object val,
747 Lisp_Object range, Lisp_Object top)
749 /* Depth of TABLE. */
750 int depth;
751 /* Minimum and maximum characters covered by TABLE. */
752 int min_char, max_char;
753 /* Number of characters covered by one element of TABLE. */
754 int chars_in_block;
755 int from = XINT (XCAR (range)), to = XINT (XCDR (range));
756 int i, c;
757 bool is_uniprop = UNIPROP_TABLE_P (top);
758 uniprop_decoder_t decoder = UNIPROP_GET_DECODER (top);
760 if (SUB_CHAR_TABLE_P (table))
762 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
764 depth = XINT (tbl->depth);
765 min_char = XINT (tbl->min_char);
766 max_char = min_char + chartab_chars[depth - 1] - 1;
768 else
770 depth = 0;
771 min_char = 0;
772 max_char = MAX_CHAR;
774 chars_in_block = chartab_chars[depth];
776 if (to < max_char)
777 max_char = to;
778 /* Set I to the index of the first element to check. */
779 if (from <= min_char)
780 i = 0;
781 else
782 i = (from - min_char) / chars_in_block;
783 for (c = min_char + chars_in_block * i; c <= max_char;
784 i++, c += chars_in_block)
786 Lisp_Object this = (SUB_CHAR_TABLE_P (table)
787 ? XSUB_CHAR_TABLE (table)->contents[i]
788 : XCHAR_TABLE (table)->contents[i]);
789 int nextc = c + chars_in_block;
791 if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (this))
792 this = uniprop_table_uncompress (table, i);
793 if (SUB_CHAR_TABLE_P (this))
795 if (to >= nextc)
796 XSETCDR (range, make_number (nextc - 1));
797 val = map_sub_char_table (c_function, function, this, arg,
798 val, range, top);
800 else
802 if (NILP (this))
803 this = XCHAR_TABLE (top)->defalt;
804 if (!EQ (val, this))
806 bool different_value = 1;
808 if (NILP (val))
810 if (! NILP (XCHAR_TABLE (top)->parent))
812 Lisp_Object parent = XCHAR_TABLE (top)->parent;
813 Lisp_Object temp = XCHAR_TABLE (parent)->parent;
815 /* This is to get a value of FROM in PARENT
816 without checking the parent of PARENT. */
817 set_char_table_parent (parent, Qnil);
818 val = CHAR_TABLE_REF (parent, from);
819 set_char_table_parent (parent, temp);
820 XSETCDR (range, make_number (c - 1));
821 val = map_sub_char_table (c_function, function,
822 parent, arg, val, range,
823 parent);
824 if (EQ (val, this))
825 different_value = 0;
828 if (! NILP (val) && different_value)
830 XSETCDR (range, make_number (c - 1));
831 if (EQ (XCAR (range), XCDR (range)))
833 if (c_function)
834 (*c_function) (arg, XCAR (range), val);
835 else
837 if (decoder)
838 val = decoder (top, val);
839 call2 (function, XCAR (range), val);
842 else
844 if (c_function)
845 (*c_function) (arg, range, val);
846 else
848 if (decoder)
849 val = decoder (top, val);
850 call2 (function, range, val);
854 val = this;
855 from = c;
856 XSETCAR (range, make_number (c));
859 XSETCDR (range, make_number (to));
861 return val;
865 /* Map C_FUNCTION or FUNCTION over TABLE, calling it for each
866 character or group of characters that share a value.
868 ARG is passed to C_FUNCTION when that is called. */
870 void
871 map_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object),
872 Lisp_Object function, Lisp_Object table, Lisp_Object arg)
874 Lisp_Object range, val, parent;
875 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
876 uniprop_decoder_t decoder = UNIPROP_GET_DECODER (table);
878 range = Fcons (make_number (0), make_number (MAX_CHAR));
879 parent = XCHAR_TABLE (table)->parent;
881 GCPRO4 (table, arg, range, parent);
882 val = XCHAR_TABLE (table)->ascii;
883 if (SUB_CHAR_TABLE_P (val))
884 val = XSUB_CHAR_TABLE (val)->contents[0];
885 val = map_sub_char_table (c_function, function, table, arg, val, range,
886 table);
888 /* If VAL is nil and TABLE has a parent, we must consult the parent
889 recursively. */
890 while (NILP (val) && ! NILP (XCHAR_TABLE (table)->parent))
892 Lisp_Object temp;
893 int from = XINT (XCAR (range));
895 parent = XCHAR_TABLE (table)->parent;
896 temp = XCHAR_TABLE (parent)->parent;
897 /* This is to get a value of FROM in PARENT without checking the
898 parent of PARENT. */
899 set_char_table_parent (parent, Qnil);
900 val = CHAR_TABLE_REF (parent, from);
901 set_char_table_parent (parent, temp);
902 val = map_sub_char_table (c_function, function, parent, arg, val, range,
903 parent);
904 table = parent;
907 if (! NILP (val))
909 if (EQ (XCAR (range), XCDR (range)))
911 if (c_function)
912 (*c_function) (arg, XCAR (range), val);
913 else
915 if (decoder)
916 val = decoder (table, val);
917 call2 (function, XCAR (range), val);
920 else
922 if (c_function)
923 (*c_function) (arg, range, val);
924 else
926 if (decoder)
927 val = decoder (table, val);
928 call2 (function, range, val);
933 UNGCPRO;
936 DEFUN ("map-char-table", Fmap_char_table, Smap_char_table,
937 2, 2, 0,
938 doc: /* Call FUNCTION for each character in CHAR-TABLE that has non-nil value.
939 FUNCTION is called with two arguments, KEY and VALUE.
940 KEY is a character code or a cons of character codes specifying a
941 range of characters that have the same value.
942 VALUE is what (char-table-range CHAR-TABLE KEY) returns. */)
943 (Lisp_Object function, Lisp_Object char_table)
945 CHECK_CHAR_TABLE (char_table);
947 map_char_table (NULL, function, char_table, char_table);
948 return Qnil;
952 static void
953 map_sub_char_table_for_charset (void (*c_function) (Lisp_Object, Lisp_Object),
954 Lisp_Object function, Lisp_Object table, Lisp_Object arg,
955 Lisp_Object range, struct charset *charset,
956 unsigned from, unsigned to)
958 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
959 int depth = XINT (tbl->depth);
960 int c, i;
962 if (depth < 3)
963 for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth];
964 i++, c += chartab_chars[depth])
966 Lisp_Object this;
968 this = tbl->contents[i];
969 if (SUB_CHAR_TABLE_P (this))
970 map_sub_char_table_for_charset (c_function, function, this, arg,
971 range, charset, from, to);
972 else
974 if (! NILP (XCAR (range)))
976 XSETCDR (range, make_number (c - 1));
977 if (c_function)
978 (*c_function) (arg, range);
979 else
980 call2 (function, range, arg);
982 XSETCAR (range, Qnil);
985 else
986 for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth]; i++, c ++)
988 Lisp_Object this;
989 unsigned code;
991 this = tbl->contents[i];
992 if (NILP (this)
993 || (charset
994 && (code = ENCODE_CHAR (charset, c),
995 (code < from || code > to))))
997 if (! NILP (XCAR (range)))
999 XSETCDR (range, make_number (c - 1));
1000 if (c_function)
1001 (*c_function) (arg, range);
1002 else
1003 call2 (function, range, arg);
1004 XSETCAR (range, Qnil);
1007 else
1009 if (NILP (XCAR (range)))
1010 XSETCAR (range, make_number (c));
1016 /* Support function for `map-charset-chars'. Map C_FUNCTION or
1017 FUNCTION over TABLE, calling it for each character or a group of
1018 succeeding characters that have non-nil value in TABLE. TABLE is a
1019 "mapping table" or a "deunifier table" of a certain charset.
1021 If CHARSET is not NULL (this is the case that `map-charset-chars'
1022 is called with non-nil FROM-CODE and TO-CODE), it is a charset who
1023 owns TABLE, and the function is called only on a character in the
1024 range FROM and TO. FROM and TO are not character codes, but code
1025 points of a character in CHARSET.
1027 This function is called in these two cases:
1029 (1) A charset has a mapping file name in :map property.
1031 (2) A charset has an upper code space in :offset property and a
1032 mapping file name in :unify-map property. In this case, this
1033 function is called only for characters in the Unicode code space.
1034 Characters in upper code space are handled directly in
1035 map_charset_chars. */
1037 void
1038 map_char_table_for_charset (void (*c_function) (Lisp_Object, Lisp_Object),
1039 Lisp_Object function, Lisp_Object table, Lisp_Object arg,
1040 struct charset *charset,
1041 unsigned from, unsigned to)
1043 Lisp_Object range;
1044 int c, i;
1045 struct gcpro gcpro1;
1047 range = Fcons (Qnil, Qnil);
1048 GCPRO1 (range);
1050 for (i = 0, c = 0; i < chartab_size[0]; i++, c += chartab_chars[0])
1052 Lisp_Object this;
1054 this = XCHAR_TABLE (table)->contents[i];
1055 if (SUB_CHAR_TABLE_P (this))
1056 map_sub_char_table_for_charset (c_function, function, this, arg,
1057 range, charset, from, to);
1058 else
1060 if (! NILP (XCAR (range)))
1062 XSETCDR (range, make_number (c - 1));
1063 if (c_function)
1064 (*c_function) (arg, range);
1065 else
1066 call2 (function, range, arg);
1068 XSETCAR (range, Qnil);
1071 if (! NILP (XCAR (range)))
1073 XSETCDR (range, make_number (c - 1));
1074 if (c_function)
1075 (*c_function) (arg, range);
1076 else
1077 call2 (function, range, arg);
1080 UNGCPRO;
1084 /* Unicode character property tables.
1086 This section provides a convenient and efficient way to get Unicode
1087 character properties of characters from C code (from Lisp, you must
1088 use get-char-code-property).
1090 The typical usage is to get a char-table object for a specific
1091 property like this (use of the "bidi-class" property below is just
1092 an example):
1094 Lisp_Object bidi_class_table = uniprop_table (intern ("bidi-class"));
1096 (uniprop_table can return nil if it fails to find data for the
1097 named property, or if it fails to load the appropriate Lisp support
1098 file, so the return value should be tested to be non-nil, before it
1099 is used.)
1101 To get a property value for character CH use CHAR_TABLE_REF:
1103 Lisp_Object bidi_class = CHAR_TABLE_REF (bidi_class_table, CH);
1105 In this case, what you actually get is an index number to the
1106 vector of property values (symbols nil, L, R, etc).
1108 The full list of Unicode character properties supported by Emacs is
1109 documented in the ELisp manual, in the node "Character Properties".
1111 A table for Unicode character property has these characteristics:
1113 o The purpose is `char-code-property-table', which implies that the
1114 table has 5 extra slots.
1116 o The second extra slot is a Lisp function, an index (integer) to
1117 the array uniprop_decoder[], or nil. If it is a Lisp function, we
1118 can't use such a table from C (at the moment). If it is nil, it
1119 means that we don't have to decode values.
1121 o The third extra slot is a Lisp function, an index (integer) to
1122 the array uniprop_encoder[], or nil. If it is a Lisp function, we
1123 can't use such a table from C (at the moment). If it is nil, it
1124 means that we don't have to encode values. */
1127 /* Uncompress the IDXth element of sub-char-table TABLE. */
1129 static Lisp_Object
1130 uniprop_table_uncompress (Lisp_Object table, int idx)
1132 Lisp_Object val = XSUB_CHAR_TABLE (table)->contents[idx];
1133 int min_char = (XINT (XSUB_CHAR_TABLE (table)->min_char)
1134 + chartab_chars[2] * idx);
1135 Lisp_Object sub = make_sub_char_table (3, min_char, Qnil);
1136 const unsigned char *p, *pend;
1138 set_sub_char_table_contents (table, idx, sub);
1139 p = SDATA (val), pend = p + SBYTES (val);
1140 if (*p == 1)
1142 /* SIMPLE TABLE */
1143 p++;
1144 idx = STRING_CHAR_ADVANCE (p);
1145 while (p < pend && idx < chartab_chars[2])
1147 int v = STRING_CHAR_ADVANCE (p);
1148 set_sub_char_table_contents
1149 (sub, idx++, v > 0 ? make_number (v) : Qnil);
1152 else if (*p == 2)
1154 /* RUN-LENGTH TABLE */
1155 p++;
1156 for (idx = 0; p < pend; )
1158 int v = STRING_CHAR_ADVANCE (p);
1159 int count = 1;
1160 int len;
1162 if (p < pend)
1164 count = STRING_CHAR_AND_LENGTH (p, len);
1165 if (count < 128)
1166 count = 1;
1167 else
1169 count -= 128;
1170 p += len;
1173 while (count-- > 0)
1174 set_sub_char_table_contents (sub, idx++, make_number (v));
1177 /* It seems that we don't need this function because C code won't need
1178 to get a property that is compressed in this form. */
1179 #if 0
1180 else if (*p == 0)
1182 /* WORD-LIST TABLE */
1184 #endif
1185 return sub;
1189 /* Decode VALUE as an element of char-table TABLE. */
1191 static Lisp_Object
1192 uniprop_decode_value_run_length (Lisp_Object table, Lisp_Object value)
1194 if (VECTORP (XCHAR_TABLE (table)->extras[4]))
1196 Lisp_Object valvec = XCHAR_TABLE (table)->extras[4];
1198 if (XINT (value) >= 0 && XINT (value) < ASIZE (valvec))
1199 value = AREF (valvec, XINT (value));
1201 return value;
1204 static uniprop_decoder_t uniprop_decoder [] =
1205 { uniprop_decode_value_run_length };
1207 static int uniprop_decoder_count
1208 = (sizeof uniprop_decoder) / sizeof (uniprop_decoder[0]);
1211 /* Return the decoder of char-table TABLE or nil if none. */
1213 static uniprop_decoder_t
1214 uniprop_get_decoder (Lisp_Object table)
1216 EMACS_INT i;
1218 if (! INTEGERP (XCHAR_TABLE (table)->extras[1]))
1219 return NULL;
1220 i = XINT (XCHAR_TABLE (table)->extras[1]);
1221 if (i < 0 || i >= uniprop_decoder_count)
1222 return NULL;
1223 return uniprop_decoder[i];
1227 /* Encode VALUE as an element of char-table TABLE which contains
1228 characters as elements. */
1230 static Lisp_Object
1231 uniprop_encode_value_character (Lisp_Object table, Lisp_Object value)
1233 if (! NILP (value) && ! CHARACTERP (value))
1234 wrong_type_argument (Qintegerp, value);
1235 return value;
1239 /* Encode VALUE as an element of char-table TABLE which adopts RUN-LENGTH
1240 compression. */
1242 static Lisp_Object
1243 uniprop_encode_value_run_length (Lisp_Object table, Lisp_Object value)
1245 Lisp_Object *value_table = XVECTOR (XCHAR_TABLE (table)->extras[4])->contents;
1246 int i, size = ASIZE (XCHAR_TABLE (table)->extras[4]);
1248 for (i = 0; i < size; i++)
1249 if (EQ (value, value_table[i]))
1250 break;
1251 if (i == size)
1252 wrong_type_argument (build_string ("Unicode property value"), value);
1253 return make_number (i);
1257 /* Encode VALUE as an element of char-table TABLE which adopts RUN-LENGTH
1258 compression and contains numbers as elements . */
1260 static Lisp_Object
1261 uniprop_encode_value_numeric (Lisp_Object table, Lisp_Object value)
1263 Lisp_Object *value_table = XVECTOR (XCHAR_TABLE (table)->extras[4])->contents;
1264 int i, size = ASIZE (XCHAR_TABLE (table)->extras[4]);
1266 CHECK_NUMBER (value);
1267 for (i = 0; i < size; i++)
1268 if (EQ (value, value_table[i]))
1269 break;
1270 value = make_number (i);
1271 if (i == size)
1273 Lisp_Object args[2];
1275 args[0] = XCHAR_TABLE (table)->extras[4];
1276 args[1] = Fmake_vector (make_number (1), value);
1277 set_char_table_extras (table, 4, Fvconcat (2, args));
1279 return make_number (i);
1282 static uniprop_encoder_t uniprop_encoder[] =
1283 { uniprop_encode_value_character,
1284 uniprop_encode_value_run_length,
1285 uniprop_encode_value_numeric };
1287 static int uniprop_encoder_count
1288 = (sizeof uniprop_encoder) / sizeof (uniprop_encoder[0]);
1291 /* Return the encoder of char-table TABLE or nil if none. */
1293 static uniprop_decoder_t
1294 uniprop_get_encoder (Lisp_Object table)
1296 EMACS_INT i;
1298 if (! INTEGERP (XCHAR_TABLE (table)->extras[2]))
1299 return NULL;
1300 i = XINT (XCHAR_TABLE (table)->extras[2]);
1301 if (i < 0 || i >= uniprop_encoder_count)
1302 return NULL;
1303 return uniprop_encoder[i];
1306 /* Return a char-table for Unicode character property PROP. This
1307 function may load a Lisp file and thus may cause
1308 garbage-collection. */
1310 Lisp_Object
1311 uniprop_table (Lisp_Object prop)
1313 Lisp_Object val, table, result;
1315 val = Fassq (prop, Vchar_code_property_alist);
1316 if (! CONSP (val))
1317 return Qnil;
1318 table = XCDR (val);
1319 if (STRINGP (table))
1321 struct gcpro gcpro1;
1322 GCPRO1 (val);
1323 result = Fload (concat2 (build_string ("international/"), table),
1324 Qt, Qt, Qt, Qt);
1325 UNGCPRO;
1326 if (NILP (result))
1327 return Qnil;
1328 table = XCDR (val);
1330 if (! CHAR_TABLE_P (table)
1331 || ! UNIPROP_TABLE_P (table))
1332 return Qnil;
1333 val = XCHAR_TABLE (table)->extras[1];
1334 if (INTEGERP (val)
1335 ? (XINT (val) < 0 || XINT (val) >= uniprop_decoder_count)
1336 : ! NILP (val))
1337 return Qnil;
1338 /* Prepare ASCII values in advance for CHAR_TABLE_REF. */
1339 set_char_table_ascii (table, char_table_ascii (table));
1340 return table;
1343 DEFUN ("unicode-property-table-internal", Funicode_property_table_internal,
1344 Sunicode_property_table_internal, 1, 1, 0,
1345 doc: /* Return a char-table for Unicode character property PROP.
1346 Use `get-unicode-property-internal' and
1347 `put-unicode-property-internal' instead of `aref' and `aset' to get
1348 and put an element value. */)
1349 (Lisp_Object prop)
1351 Lisp_Object table = uniprop_table (prop);
1353 if (CHAR_TABLE_P (table))
1354 return table;
1355 return Fcdr (Fassq (prop, Vchar_code_property_alist));
1358 DEFUN ("get-unicode-property-internal", Fget_unicode_property_internal,
1359 Sget_unicode_property_internal, 2, 2, 0,
1360 doc: /* Return an element of CHAR-TABLE for character CH.
1361 CHAR-TABLE must be what returned by `unicode-property-table-internal'. */)
1362 (Lisp_Object char_table, Lisp_Object ch)
1364 Lisp_Object val;
1365 uniprop_decoder_t decoder;
1367 CHECK_CHAR_TABLE (char_table);
1368 CHECK_CHARACTER (ch);
1369 if (! UNIPROP_TABLE_P (char_table))
1370 error ("Invalid Unicode property table");
1371 val = CHAR_TABLE_REF (char_table, XINT (ch));
1372 decoder = uniprop_get_decoder (char_table);
1373 return (decoder ? decoder (char_table, val) : val);
1376 DEFUN ("put-unicode-property-internal", Fput_unicode_property_internal,
1377 Sput_unicode_property_internal, 3, 3, 0,
1378 doc: /* Set an element of CHAR-TABLE for character CH to VALUE.
1379 CHAR-TABLE must be what returned by `unicode-property-table-internal'. */)
1380 (Lisp_Object char_table, Lisp_Object ch, Lisp_Object value)
1382 uniprop_encoder_t encoder;
1384 CHECK_CHAR_TABLE (char_table);
1385 CHECK_CHARACTER (ch);
1386 if (! UNIPROP_TABLE_P (char_table))
1387 error ("Invalid Unicode property table");
1388 encoder = uniprop_get_encoder (char_table);
1389 if (encoder)
1390 value = encoder (char_table, value);
1391 CHAR_TABLE_SET (char_table, XINT (ch), value);
1392 return Qnil;
1396 void
1397 syms_of_chartab (void)
1399 DEFSYM (Qchar_code_property_table, "char-code-property-table");
1401 defsubr (&Smake_char_table);
1402 defsubr (&Schar_table_parent);
1403 defsubr (&Schar_table_subtype);
1404 defsubr (&Sset_char_table_parent);
1405 defsubr (&Schar_table_extra_slot);
1406 defsubr (&Sset_char_table_extra_slot);
1407 defsubr (&Schar_table_range);
1408 defsubr (&Sset_char_table_range);
1409 defsubr (&Soptimize_char_table);
1410 defsubr (&Smap_char_table);
1411 defsubr (&Sunicode_property_table_internal);
1412 defsubr (&Sget_unicode_property_internal);
1413 defsubr (&Sput_unicode_property_internal);
1415 /* Each element has the form (PROP . TABLE).
1416 PROP is a symbol representing a character property.
1417 TABLE is a char-table containing the property value for each character.
1418 TABLE may be a name of file to load to build a char-table.
1419 This variable should be modified only through
1420 `define-char-code-property'. */
1422 DEFVAR_LISP ("char-code-property-alist", Vchar_code_property_alist,
1423 doc: /* Alist of character property name vs char-table containing property values.
1424 Internal use only. */);
1425 Vchar_code_property_alist = Qnil;