* eval.c (internal_lisp_condition_case): Don't overrun the stack
[emacs.git] / src / chartab.c
blob2a8bbc6983a328aa696ae6b5c2fbe20e367b6011
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))))
87 static void
88 CHECK_CHAR_TABLE (Lisp_Object x)
90 CHECK_TYPE (CHAR_TABLE_P (x), Qchar_table_p, x);
93 static void
94 set_char_table_ascii (Lisp_Object table, Lisp_Object val)
96 XCHAR_TABLE (table)->ascii = val;
98 static void
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)
114 Lisp_Object vector;
115 Lisp_Object n;
116 int n_extras;
117 int size;
119 CHECK_SYMBOL (purpose);
120 n = Fget (purpose, Qchar_table_extra_slots);
121 if (NILP (n))
122 n_extras = 0;
123 else
125 CHECK_NATNUM (n);
126 if (XINT (n) > 10)
127 args_out_of_range (n, Qnil);
128 n_extras = XINT (n);
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));
137 return vector;
140 static Lisp_Object
141 make_sub_char_table (int depth, int min_char, Lisp_Object defalt)
143 Lisp_Object table;
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);
152 return table;
155 static Lisp_Object
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))
162 return sub;
163 sub = XSUB_CHAR_TABLE (sub)->contents[0];
164 if (! SUB_CHAR_TABLE_P (sub))
165 return 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);
169 return val;
172 static Lisp_Object
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);
178 int i;
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);
188 return copy;
192 Lisp_Object
193 copy_char_table (Lisp_Object table)
195 Lisp_Object copy;
196 int size = XCHAR_TABLE (table)->header.size & PSEUDOVECTOR_SIZE_MASK;
197 int i;
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
206 (copy, i,
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));
216 return copy;
219 static Lisp_Object
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);
225 Lisp_Object val;
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);
233 return val;
236 Lisp_Object
237 char_table_ref (Lisp_Object table, int c)
239 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
240 Lisp_Object val;
242 if (ASCII_CHAR_P (c))
244 val = tbl->ascii;
245 if (SUB_CHAR_TABLE_P (val))
246 val = XSUB_CHAR_TABLE (val)->contents[c];
248 else
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));
254 if (NILP (val))
256 val = tbl->defalt;
257 if (NILP (val) && CHAR_TABLE_P (tbl->parent))
258 val = char_table_ref (tbl->parent, c);
260 return val;
263 static Lisp_Object
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;
271 Lisp_Object val;
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);
278 else if (NILP (val))
279 val = defalt;
281 idx = chartab_idx;
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;
287 idx--;
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,
293 is_uniprop);
294 else if (NILP (this_val))
295 this_val = defalt;
297 if (! EQ (this_val, val))
299 *from = c + 1;
300 break;
303 while (((c = (chartab_idx + 1) * chartab_chars[depth])
304 < chartab_chars[depth - 1])
305 && (c += min_char) <= *to)
307 Lisp_Object this_val;
309 chartab_idx++;
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,
315 is_uniprop);
316 else if (NILP (this_val))
317 this_val = defalt;
318 if (! EQ (this_val, val))
320 *to = c - 1;
321 break;
325 return 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. */
334 Lisp_Object
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;
339 Lisp_Object val;
340 bool is_uniprop = UNIPROP_TABLE_P (table);
342 val = tbl->contents[chartab_idx];
343 if (*from < 0)
344 *from = 0;
345 if (*to < 0)
346 *to = MAX_CHAR;
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,
351 is_uniprop);
352 else if (NILP (val))
353 val = tbl->defalt;
354 idx = chartab_idx;
355 while (*from < idx * chartab_chars[0])
357 Lisp_Object this_val;
359 c = idx * chartab_chars[0] - 1;
360 idx--;
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))
372 *from = c + 1;
373 break;
376 while (*to >= (chartab_idx + 1) * chartab_chars[0])
378 Lisp_Object this_val;
380 chartab_idx++;
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))
392 *to = c - 1;
393 break;
397 return val;
401 static void
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);
408 Lisp_Object sub;
410 if (depth == 3)
411 set_sub_char_table_contents (table, i, val);
412 else
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);
419 else
421 sub = make_sub_char_table (depth + 1,
422 min_char + i * chartab_chars[depth],
423 sub);
424 set_sub_char_table_contents (table, i, sub);
427 sub_char_table_set (sub, c, val, is_uniprop);
431 void
432 char_table_set (Lisp_Object table, int c, Lisp_Object val)
434 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
436 if (ASCII_CHAR_P (c)
437 && SUB_CHAR_TABLE_P (tbl->ascii))
438 set_sub_char_table_contents (tbl->ascii, c, val);
439 else
441 int i = CHARTAB_IDX (c, 0, 0);
442 Lisp_Object sub;
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));
456 static void
457 sub_char_table_set_range (Lisp_Object table, int from, int to, Lisp_Object val,
458 bool is_uniprop)
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];
466 if (from < min_char)
467 from = min_char;
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)
472 if (c > to)
473 break;
474 if (from <= c && c + chars_in_block - 1 <= to)
475 set_sub_char_table_contents (table, i, val);
476 else
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);
483 else
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);
495 void
496 char_table_set_range (Lisp_Object table, int from, int to, Lisp_Object val)
498 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
500 if (from == to)
501 char_table_set (table, from, val);
502 else
504 bool is_uniprop = UNIPROP_TABLE_P (table);
505 int lim = CHARTAB_IDX (to, 0, 0);
506 int i, c;
508 for (i = CHARTAB_IDX (from, 0, 0), c = 0; i <= lim;
509 i++, c += chartab_chars[0])
511 if (c > to)
512 break;
513 if (from <= c && c + chartab_chars[0] - 1 <= to)
514 set_char_table_contents (table, i, val);
515 else
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,
533 1, 1, 0,
534 doc: /*
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,
544 1, 1, 0,
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,
558 2, 2, 0,
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)
563 Lisp_Object temp;
565 CHECK_CHAR_TABLE (char_table);
567 if (!NILP (parent))
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);
578 return parent;
581 DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
582 2, 2, 0,
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);
587 CHECK_NUMBER (n);
588 if (XINT (n) < 0
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,
597 3, 3, 0,
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);
602 CHECK_NUMBER (n);
603 if (XINT (n) < 0
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);
608 return value;
611 DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
612 2, 2, 0,
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)
618 Lisp_Object val;
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))
627 int from, to;
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. */
636 else
637 error ("Invalid RANGE argument to `char-table-range'");
638 return val;
641 DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
642 3, 3, 0,
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);
650 if (EQ (range, Qt))
652 int i;
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);
669 else
670 error ("Invalid RANGE argument to `set-char-table-range'");
672 return value;
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)
681 Lisp_Object value;
682 value = Faref (table, make_number (ch));
683 if (! CHARACTERP (value))
684 return ch;
685 return XINT (value);
688 static Lisp_Object
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;
694 int i;
695 bool optimizable;
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);
712 if (optimizable
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))))
716 optimizable = 0;
719 return (optimizable ? elt : table);
722 DEFUN ("optimize-char-table", Foptimize_char_table, Soptimize_char_table,
723 1, 2, 0,
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)
729 Lisp_Object elt;
730 int i;
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));
744 return Qnil;
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
752 char-table.
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. */
761 static Lisp_Object
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. */
767 int depth;
768 /* Minimum and maximum characters covered by TABLE. */
769 int min_char, max_char;
770 /* Number of characters covered by one element of TABLE. */
771 int chars_in_block;
772 int from = XINT (XCAR (range)), to = XINT (XCDR (range));
773 int i, c;
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;
785 else
787 depth = 0;
788 min_char = 0;
789 max_char = MAX_CHAR;
791 chars_in_block = chartab_chars[depth];
793 if (to < max_char)
794 max_char = to;
795 /* Set I to the index of the first element to check. */
796 if (from <= min_char)
797 i = 0;
798 else
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))
812 if (to >= nextc)
813 XSETCDR (range, make_number (nextc - 1));
814 val = map_sub_char_table (c_function, function, this, arg,
815 val, range, top);
817 else
819 if (NILP (this))
820 this = XCHAR_TABLE (top)->defalt;
821 if (!EQ (val, this))
823 bool different_value = 1;
825 if (NILP (val))
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,
840 parent);
841 if (EQ (val, this))
842 different_value = 0;
845 if (! NILP (val) && different_value)
847 XSETCDR (range, make_number (c - 1));
848 if (EQ (XCAR (range), XCDR (range)))
850 if (c_function)
851 (*c_function) (arg, XCAR (range), val);
852 else
854 if (decoder)
855 val = decoder (top, val);
856 call2 (function, XCAR (range), val);
859 else
861 if (c_function)
862 (*c_function) (arg, range, val);
863 else
865 if (decoder)
866 val = decoder (top, val);
867 call2 (function, range, val);
871 val = this;
872 from = c;
873 XSETCAR (range, make_number (c));
876 XSETCDR (range, make_number (to));
878 return val;
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. */
887 void
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,
903 table);
905 /* If VAL is nil and TABLE has a parent, we must consult the parent
906 recursively. */
907 while (NILP (val) && ! NILP (XCHAR_TABLE (table)->parent))
909 Lisp_Object temp;
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
915 parent of PARENT. */
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,
920 parent);
921 table = parent;
924 if (! NILP (val))
926 if (EQ (XCAR (range), XCDR (range)))
928 if (c_function)
929 (*c_function) (arg, XCAR (range), val);
930 else
932 if (decoder)
933 val = decoder (table, val);
934 call2 (function, XCAR (range), val);
937 else
939 if (c_function)
940 (*c_function) (arg, range, val);
941 else
943 if (decoder)
944 val = decoder (table, val);
945 call2 (function, range, val);
950 UNGCPRO;
953 DEFUN ("map-char-table", Fmap_char_table, Smap_char_table,
954 2, 2, 0,
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);
965 return Qnil;
969 static void
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);
977 int c, i;
979 if (depth < 3)
980 for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth];
981 i++, c += chartab_chars[depth])
983 Lisp_Object this;
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);
989 else
991 if (! NILP (XCAR (range)))
993 XSETCDR (range, make_number (c - 1));
994 if (c_function)
995 (*c_function) (arg, range);
996 else
997 call2 (function, range, arg);
999 XSETCAR (range, Qnil);
1002 else
1003 for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth]; i++, c ++)
1005 Lisp_Object this;
1006 unsigned code;
1008 this = tbl->contents[i];
1009 if (NILP (this)
1010 || (charset
1011 && (code = ENCODE_CHAR (charset, c),
1012 (code < from || code > to))))
1014 if (! NILP (XCAR (range)))
1016 XSETCDR (range, make_number (c - 1));
1017 if (c_function)
1018 (*c_function) (arg, range);
1019 else
1020 call2 (function, range, arg);
1021 XSETCAR (range, Qnil);
1024 else
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. */
1054 void
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)
1060 Lisp_Object range;
1061 int c, i;
1062 struct gcpro gcpro1;
1064 range = Fcons (Qnil, Qnil);
1065 GCPRO1 (range);
1067 for (i = 0, c = 0; i < chartab_size[0]; i++, c += chartab_chars[0])
1069 Lisp_Object this;
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);
1075 else
1077 if (! NILP (XCAR (range)))
1079 XSETCDR (range, make_number (c - 1));
1080 if (c_function)
1081 (*c_function) (arg, range);
1082 else
1083 call2 (function, range, arg);
1085 XSETCAR (range, Qnil);
1088 if (! NILP (XCAR (range)))
1090 XSETCDR (range, make_number (c - 1));
1091 if (c_function)
1092 (*c_function) (arg, range);
1093 else
1094 call2 (function, range, arg);
1097 UNGCPRO;
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
1109 an example):
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
1116 is used.)
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. */
1146 static Lisp_Object
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);
1157 if (*p == 1)
1159 /* SIMPLE TABLE */
1160 p++;
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);
1169 else if (*p == 2)
1171 /* RUN-LENGTH TABLE */
1172 p++;
1173 for (idx = 0; p < pend; )
1175 int v = STRING_CHAR_ADVANCE (p);
1176 int count = 1;
1177 int len;
1179 if (p < pend)
1181 count = STRING_CHAR_AND_LENGTH (p, len);
1182 if (count < 128)
1183 count = 1;
1184 else
1186 count -= 128;
1187 p += len;
1190 while (count-- > 0)
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. */
1196 #if 0
1197 else if (*p == 0)
1199 /* WORD-LIST TABLE */
1201 #endif
1202 return sub;
1206 /* Decode VALUE as an element of char-table TABLE. */
1208 static Lisp_Object
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));
1218 return value;
1221 static uniprop_decoder_t uniprop_decoder [] =
1222 { uniprop_decode_value_run_length };
1224 static int uniprop_decoder_count
1225 = (sizeof uniprop_decoder) / sizeof (uniprop_decoder[0]);
1228 /* Return the decoder of char-table TABLE or nil if none. */
1230 static uniprop_decoder_t
1231 uniprop_get_decoder (Lisp_Object table)
1233 EMACS_INT i;
1235 if (! INTEGERP (XCHAR_TABLE (table)->extras[1]))
1236 return NULL;
1237 i = XINT (XCHAR_TABLE (table)->extras[1]);
1238 if (i < 0 || i >= uniprop_decoder_count)
1239 return NULL;
1240 return uniprop_decoder[i];
1244 /* Encode VALUE as an element of char-table TABLE which contains
1245 characters as elements. */
1247 static Lisp_Object
1248 uniprop_encode_value_character (Lisp_Object table, Lisp_Object value)
1250 if (! NILP (value) && ! CHARACTERP (value))
1251 wrong_type_argument (Qintegerp, value);
1252 return value;
1256 /* Encode VALUE as an element of char-table TABLE which adopts RUN-LENGTH
1257 compression. */
1259 static Lisp_Object
1260 uniprop_encode_value_run_length (Lisp_Object table, Lisp_Object value)
1262 Lisp_Object *value_table = XVECTOR (XCHAR_TABLE (table)->extras[4])->contents;
1263 int i, size = ASIZE (XCHAR_TABLE (table)->extras[4]);
1265 for (i = 0; i < size; i++)
1266 if (EQ (value, value_table[i]))
1267 break;
1268 if (i == size)
1269 wrong_type_argument (build_string ("Unicode property value"), value);
1270 return make_number (i);
1274 /* Encode VALUE as an element of char-table TABLE which adopts RUN-LENGTH
1275 compression and contains numbers as elements. */
1277 static Lisp_Object
1278 uniprop_encode_value_numeric (Lisp_Object table, Lisp_Object value)
1280 Lisp_Object *value_table = XVECTOR (XCHAR_TABLE (table)->extras[4])->contents;
1281 int i, size = ASIZE (XCHAR_TABLE (table)->extras[4]);
1283 CHECK_NUMBER (value);
1284 for (i = 0; i < size; i++)
1285 if (EQ (value, value_table[i]))
1286 break;
1287 value = make_number (i);
1288 if (i == size)
1290 Lisp_Object args[2];
1292 args[0] = XCHAR_TABLE (table)->extras[4];
1293 args[1] = Fmake_vector (make_number (1), value);
1294 set_char_table_extras (table, 4, Fvconcat (2, args));
1296 return make_number (i);
1299 static uniprop_encoder_t uniprop_encoder[] =
1300 { uniprop_encode_value_character,
1301 uniprop_encode_value_run_length,
1302 uniprop_encode_value_numeric };
1304 static int uniprop_encoder_count
1305 = (sizeof uniprop_encoder) / sizeof (uniprop_encoder[0]);
1308 /* Return the encoder of char-table TABLE or nil if none. */
1310 static uniprop_decoder_t
1311 uniprop_get_encoder (Lisp_Object table)
1313 EMACS_INT i;
1315 if (! INTEGERP (XCHAR_TABLE (table)->extras[2]))
1316 return NULL;
1317 i = XINT (XCHAR_TABLE (table)->extras[2]);
1318 if (i < 0 || i >= uniprop_encoder_count)
1319 return NULL;
1320 return uniprop_encoder[i];
1323 /* Return a char-table for Unicode character property PROP. This
1324 function may load a Lisp file and thus may cause
1325 garbage-collection. */
1327 Lisp_Object
1328 uniprop_table (Lisp_Object prop)
1330 Lisp_Object val, table, result;
1332 val = Fassq (prop, Vchar_code_property_alist);
1333 if (! CONSP (val))
1334 return Qnil;
1335 table = XCDR (val);
1336 if (STRINGP (table))
1338 struct gcpro gcpro1;
1339 GCPRO1 (val);
1340 result = Fload (concat2 (build_string ("international/"), table),
1341 Qt, Qt, Qt, Qt);
1342 UNGCPRO;
1343 if (NILP (result))
1344 return Qnil;
1345 table = XCDR (val);
1347 if (! CHAR_TABLE_P (table)
1348 || ! UNIPROP_TABLE_P (table))
1349 return Qnil;
1350 val = XCHAR_TABLE (table)->extras[1];
1351 if (INTEGERP (val)
1352 ? (XINT (val) < 0 || XINT (val) >= uniprop_decoder_count)
1353 : ! NILP (val))
1354 return Qnil;
1355 /* Prepare ASCII values in advance for CHAR_TABLE_REF. */
1356 set_char_table_ascii (table, char_table_ascii (table));
1357 return table;
1360 DEFUN ("unicode-property-table-internal", Funicode_property_table_internal,
1361 Sunicode_property_table_internal, 1, 1, 0,
1362 doc: /* Return a char-table for Unicode character property PROP.
1363 Use `get-unicode-property-internal' and
1364 `put-unicode-property-internal' instead of `aref' and `aset' to get
1365 and put an element value. */)
1366 (Lisp_Object prop)
1368 Lisp_Object table = uniprop_table (prop);
1370 if (CHAR_TABLE_P (table))
1371 return table;
1372 return Fcdr (Fassq (prop, Vchar_code_property_alist));
1375 DEFUN ("get-unicode-property-internal", Fget_unicode_property_internal,
1376 Sget_unicode_property_internal, 2, 2, 0,
1377 doc: /* Return an element of CHAR-TABLE for character CH.
1378 CHAR-TABLE must be what returned by `unicode-property-table-internal'. */)
1379 (Lisp_Object char_table, Lisp_Object ch)
1381 Lisp_Object val;
1382 uniprop_decoder_t decoder;
1384 CHECK_CHAR_TABLE (char_table);
1385 CHECK_CHARACTER (ch);
1386 if (! UNIPROP_TABLE_P (char_table))
1387 error ("Invalid Unicode property table");
1388 val = CHAR_TABLE_REF (char_table, XINT (ch));
1389 decoder = uniprop_get_decoder (char_table);
1390 return (decoder ? decoder (char_table, val) : val);
1393 DEFUN ("put-unicode-property-internal", Fput_unicode_property_internal,
1394 Sput_unicode_property_internal, 3, 3, 0,
1395 doc: /* Set an element of CHAR-TABLE for character CH to VALUE.
1396 CHAR-TABLE must be what returned by `unicode-property-table-internal'. */)
1397 (Lisp_Object char_table, Lisp_Object ch, Lisp_Object value)
1399 uniprop_encoder_t encoder;
1401 CHECK_CHAR_TABLE (char_table);
1402 CHECK_CHARACTER (ch);
1403 if (! UNIPROP_TABLE_P (char_table))
1404 error ("Invalid Unicode property table");
1405 encoder = uniprop_get_encoder (char_table);
1406 if (encoder)
1407 value = encoder (char_table, value);
1408 CHAR_TABLE_SET (char_table, XINT (ch), value);
1409 return Qnil;
1413 void
1414 syms_of_chartab (void)
1416 DEFSYM (Qchar_code_property_table, "char-code-property-table");
1418 defsubr (&Smake_char_table);
1419 defsubr (&Schar_table_parent);
1420 defsubr (&Schar_table_subtype);
1421 defsubr (&Sset_char_table_parent);
1422 defsubr (&Schar_table_extra_slot);
1423 defsubr (&Sset_char_table_extra_slot);
1424 defsubr (&Schar_table_range);
1425 defsubr (&Sset_char_table_range);
1426 defsubr (&Soptimize_char_table);
1427 defsubr (&Smap_char_table);
1428 defsubr (&Sunicode_property_table_internal);
1429 defsubr (&Sget_unicode_property_internal);
1430 defsubr (&Sput_unicode_property_internal);
1432 /* Each element has the form (PROP . TABLE).
1433 PROP is a symbol representing a character property.
1434 TABLE is a char-table containing the property value for each character.
1435 TABLE may be a name of file to load to build a char-table.
1436 This variable should be modified only through
1437 `define-char-code-property'. */
1439 DEFVAR_LISP ("char-code-property-alist", Vchar_code_property_alist,
1440 doc: /* Alist of character property name vs char-table containing property values.
1441 Internal use only. */);
1442 Vchar_code_property_alist = Qnil;