* chartab.c (sub_char_table_ref_and_range): Redo to avoid overflow
[emacs.git] / src / chartab.c
blob9a140eb85603ab8e4ee56cde1c6ba47644c8d8cc
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>
22 #include <setjmp.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 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 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 DEFUN ("make-char-table", Fmake_char_table, Smake_char_table, 1, 2, 0,
58 doc: /* Return a newly created char-table, with purpose PURPOSE.
59 Each element is initialized to INIT, which defaults to nil.
61 PURPOSE should be a symbol. If it has a `char-table-extra-slots'
62 property, the property's value should be an integer between 0 and 10
63 that specifies how many extra slots the char-table has. Otherwise,
64 the char-table has no extra slot. */)
65 (register Lisp_Object purpose, Lisp_Object init)
67 Lisp_Object vector;
68 Lisp_Object n;
69 int n_extras;
70 int size;
72 CHECK_SYMBOL (purpose);
73 n = Fget (purpose, Qchar_table_extra_slots);
74 if (NILP (n))
75 n_extras = 0;
76 else
78 CHECK_NATNUM (n);
79 n_extras = XINT (n);
80 if (n_extras > 10)
81 args_out_of_range (n, Qnil);
84 size = VECSIZE (struct Lisp_Char_Table) - 1 + n_extras;
85 vector = Fmake_vector (make_number (size), init);
86 XSETPVECTYPE (XVECTOR (vector), PVEC_CHAR_TABLE);
87 XCHAR_TABLE (vector)->parent = Qnil;
88 XCHAR_TABLE (vector)->purpose = purpose;
89 XSETCHAR_TABLE (vector, XCHAR_TABLE (vector));
90 return vector;
93 static Lisp_Object
94 make_sub_char_table (int depth, int min_char, Lisp_Object defalt)
96 Lisp_Object table;
97 int size = VECSIZE (struct Lisp_Sub_Char_Table) - 1 + chartab_size[depth];
99 table = Fmake_vector (make_number (size), defalt);
100 XSETPVECTYPE (XVECTOR (table), PVEC_SUB_CHAR_TABLE);
101 XSUB_CHAR_TABLE (table)->depth = make_number (depth);
102 XSUB_CHAR_TABLE (table)->min_char = make_number (min_char);
104 return table;
107 static Lisp_Object
108 char_table_ascii (Lisp_Object table)
110 Lisp_Object sub;
112 sub = XCHAR_TABLE (table)->contents[0];
113 if (! SUB_CHAR_TABLE_P (sub))
114 return sub;
115 sub = XSUB_CHAR_TABLE (sub)->contents[0];
116 if (! SUB_CHAR_TABLE_P (sub))
117 return sub;
118 return XSUB_CHAR_TABLE (sub)->contents[0];
121 static Lisp_Object
122 copy_sub_char_table (Lisp_Object table)
124 Lisp_Object copy;
125 int depth = XINT (XSUB_CHAR_TABLE (table)->depth);
126 int min_char = XINT (XSUB_CHAR_TABLE (table)->min_char);
127 Lisp_Object val;
128 int i;
130 copy = make_sub_char_table (depth, min_char, Qnil);
131 /* Recursively copy any sub char-tables. */
132 for (i = 0; i < chartab_size[depth]; i++)
134 val = XSUB_CHAR_TABLE (table)->contents[i];
135 if (SUB_CHAR_TABLE_P (val))
136 XSUB_CHAR_TABLE (copy)->contents[i] = copy_sub_char_table (val);
137 else
138 XSUB_CHAR_TABLE (copy)->contents[i] = val;
141 return copy;
145 Lisp_Object
146 copy_char_table (Lisp_Object table)
148 Lisp_Object copy;
149 int size = XCHAR_TABLE (table)->size & PSEUDOVECTOR_SIZE_MASK;
150 int i;
152 copy = Fmake_vector (make_number (size), Qnil);
153 XSETPVECTYPE (XVECTOR (copy), PVEC_CHAR_TABLE);
154 XCHAR_TABLE (copy)->defalt = XCHAR_TABLE (table)->defalt;
155 XCHAR_TABLE (copy)->parent = XCHAR_TABLE (table)->parent;
156 XCHAR_TABLE (copy)->purpose = XCHAR_TABLE (table)->purpose;
157 for (i = 0; i < chartab_size[0]; i++)
158 XCHAR_TABLE (copy)->contents[i]
159 = (SUB_CHAR_TABLE_P (XCHAR_TABLE (table)->contents[i])
160 ? copy_sub_char_table (XCHAR_TABLE (table)->contents[i])
161 : XCHAR_TABLE (table)->contents[i]);
162 XCHAR_TABLE (copy)->ascii = char_table_ascii (copy);
163 size -= VECSIZE (struct Lisp_Char_Table) - 1;
164 for (i = 0; i < size; i++)
165 XCHAR_TABLE (copy)->extras[i] = XCHAR_TABLE (table)->extras[i];
167 XSETCHAR_TABLE (copy, XCHAR_TABLE (copy));
168 return copy;
171 static Lisp_Object
172 sub_char_table_ref (Lisp_Object table, int c)
174 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
175 int depth = XINT (tbl->depth);
176 int min_char = XINT (tbl->min_char);
177 Lisp_Object val;
179 val = tbl->contents[CHARTAB_IDX (c, depth, min_char)];
180 if (SUB_CHAR_TABLE_P (val))
181 val = sub_char_table_ref (val, c);
182 return val;
185 Lisp_Object
186 char_table_ref (Lisp_Object table, int c)
188 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
189 Lisp_Object val;
191 if (ASCII_CHAR_P (c))
193 val = tbl->ascii;
194 if (SUB_CHAR_TABLE_P (val))
195 val = XSUB_CHAR_TABLE (val)->contents[c];
197 else
199 val = tbl->contents[CHARTAB_IDX (c, 0, 0)];
200 if (SUB_CHAR_TABLE_P (val))
201 val = sub_char_table_ref (val, c);
203 if (NILP (val))
205 val = tbl->defalt;
206 if (NILP (val) && CHAR_TABLE_P (tbl->parent))
207 val = char_table_ref (tbl->parent, c);
209 return val;
212 static Lisp_Object
213 sub_char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to, Lisp_Object defalt)
215 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
216 int depth = XINT (tbl->depth);
217 int min_char = XINT (tbl->min_char);
218 int char_offset_lim = chartab_chars[depth - 1];
219 int chartab_idx = CHARTAB_IDX (c, depth, min_char), idx;
220 Lisp_Object val;
222 val = tbl->contents[chartab_idx];
223 if (SUB_CHAR_TABLE_P (val))
224 val = sub_char_table_ref_and_range (val, c, from, to, defalt);
225 else if (NILP (val))
226 val = defalt;
228 idx = chartab_idx;
229 while (idx > 0 && *from < min_char + idx * chartab_chars[depth])
231 Lisp_Object this_val;
233 c = min_char + idx * chartab_chars[depth] - 1;
234 idx--;
235 this_val = tbl->contents[idx];
236 if (SUB_CHAR_TABLE_P (this_val))
237 this_val = sub_char_table_ref_and_range (this_val, c, from, to, defalt);
238 else if (NILP (this_val))
239 this_val = defalt;
241 if (! EQ (this_val, val))
243 *from = c + 1;
244 break;
248 while ((c = (chartab_idx + 1) * chartab_chars[depth]) < char_offset_lim
249 && (c += min_char) <= *to)
251 Lisp_Object this_val;
253 chartab_idx++;
254 this_val = tbl->contents[chartab_idx];
255 if (SUB_CHAR_TABLE_P (this_val))
256 this_val = sub_char_table_ref_and_range (this_val, c, from, to, defalt);
257 else if (NILP (this_val))
258 this_val = defalt;
259 if (! EQ (this_val, val))
261 *to = c - 1;
262 break;
266 return val;
270 /* Return the value for C in char-table TABLE. Shrink the range *FROM
271 and *TO to cover characters (containing C) that have the same value
272 as C. It is not assured that the values of (*FROM - 1) and (*TO +
273 1) are different from that of C. */
275 Lisp_Object
276 char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to)
278 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
279 int chartab_idx = CHARTAB_IDX (c, 0, 0), idx;
280 Lisp_Object val;
282 val = tbl->contents[chartab_idx];
283 if (*from < 0)
284 *from = 0;
285 if (*to < 0)
286 *to = MAX_CHAR;
287 if (SUB_CHAR_TABLE_P (val))
288 val = sub_char_table_ref_and_range (val, c, from, to, tbl->defalt);
289 else if (NILP (val))
290 val = tbl->defalt;
292 idx = chartab_idx;
293 while (*from < idx * chartab_chars[0])
295 Lisp_Object this_val;
297 c = idx * chartab_chars[0] - 1;
298 idx--;
299 this_val = tbl->contents[idx];
300 if (SUB_CHAR_TABLE_P (this_val))
301 this_val = sub_char_table_ref_and_range (this_val, c, from, to,
302 tbl->defalt);
303 else if (NILP (this_val))
304 this_val = tbl->defalt;
306 if (! EQ (this_val, val))
308 *from = c + 1;
309 break;
312 while (*to >= (chartab_idx + 1) * chartab_chars[0])
314 Lisp_Object this_val;
316 chartab_idx++;
317 c = chartab_idx * chartab_chars[0];
318 this_val = tbl->contents[chartab_idx];
319 if (SUB_CHAR_TABLE_P (this_val))
320 this_val = sub_char_table_ref_and_range (this_val, c, from, to,
321 tbl->defalt);
322 else if (NILP (this_val))
323 this_val = tbl->defalt;
324 if (! EQ (this_val, val))
326 *to = c - 1;
327 break;
331 return val;
335 static void
336 sub_char_table_set (Lisp_Object table, int c, Lisp_Object val)
338 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
339 int depth = XINT ((tbl)->depth);
340 int min_char = XINT ((tbl)->min_char);
341 int i = CHARTAB_IDX (c, depth, min_char);
342 Lisp_Object sub;
344 if (depth == 3)
345 tbl->contents[i] = val;
346 else
348 sub = tbl->contents[i];
349 if (! SUB_CHAR_TABLE_P (sub))
351 sub = make_sub_char_table (depth + 1,
352 min_char + i * chartab_chars[depth], sub);
353 tbl->contents[i] = sub;
355 sub_char_table_set (sub, c, val);
359 Lisp_Object
360 char_table_set (Lisp_Object table, int c, Lisp_Object val)
362 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
364 if (ASCII_CHAR_P (c)
365 && SUB_CHAR_TABLE_P (tbl->ascii))
367 XSUB_CHAR_TABLE (tbl->ascii)->contents[c] = val;
369 else
371 int i = CHARTAB_IDX (c, 0, 0);
372 Lisp_Object sub;
374 sub = tbl->contents[i];
375 if (! SUB_CHAR_TABLE_P (sub))
377 sub = make_sub_char_table (1, i * chartab_chars[0], sub);
378 tbl->contents[i] = sub;
380 sub_char_table_set (sub, c, val);
381 if (ASCII_CHAR_P (c))
382 tbl->ascii = char_table_ascii (table);
384 return val;
387 static void
388 sub_char_table_set_range (Lisp_Object *table, int depth, int min_char, int from, int to, Lisp_Object val)
390 int max_char = min_char + chartab_chars[depth] - 1;
392 if (depth == 3 || (from <= min_char && to >= max_char))
393 *table = val;
394 else
396 int i, j;
398 depth++;
399 if (! SUB_CHAR_TABLE_P (*table))
400 *table = make_sub_char_table (depth, min_char, *table);
401 if (from < min_char)
402 from = min_char;
403 if (to > max_char)
404 to = max_char;
405 i = CHARTAB_IDX (from, depth, min_char);
406 j = CHARTAB_IDX (to, depth, min_char);
407 min_char += chartab_chars[depth] * i;
408 for (; i <= j; i++, min_char += chartab_chars[depth])
409 sub_char_table_set_range (XSUB_CHAR_TABLE (*table)->contents + i,
410 depth, min_char, from, to, val);
415 Lisp_Object
416 char_table_set_range (Lisp_Object table, int from, int to, Lisp_Object val)
418 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
419 Lisp_Object *contents = tbl->contents;
420 int i, min_char;
422 if (from == to)
423 char_table_set (table, from, val);
424 else
426 for (i = CHARTAB_IDX (from, 0, 0), min_char = i * chartab_chars[0];
427 min_char <= to;
428 i++, min_char += chartab_chars[0])
429 sub_char_table_set_range (contents + i, 0, min_char, from, to, val);
430 if (ASCII_CHAR_P (from))
431 tbl->ascii = char_table_ascii (table);
433 return val;
437 DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype,
438 1, 1, 0,
439 doc: /*
440 Return the subtype of char-table CHAR-TABLE. The value is a symbol. */)
441 (Lisp_Object char_table)
443 CHECK_CHAR_TABLE (char_table);
445 return XCHAR_TABLE (char_table)->purpose;
448 DEFUN ("char-table-parent", Fchar_table_parent, Schar_table_parent,
449 1, 1, 0,
450 doc: /* Return the parent char-table of CHAR-TABLE.
451 The value is either nil or another char-table.
452 If CHAR-TABLE holds nil for a given character,
453 then the actual applicable value is inherited from the parent char-table
454 \(or from its parents, if necessary). */)
455 (Lisp_Object char_table)
457 CHECK_CHAR_TABLE (char_table);
459 return XCHAR_TABLE (char_table)->parent;
462 DEFUN ("set-char-table-parent", Fset_char_table_parent, Sset_char_table_parent,
463 2, 2, 0,
464 doc: /* Set the parent char-table of CHAR-TABLE to PARENT.
465 Return PARENT. PARENT must be either nil or another char-table. */)
466 (Lisp_Object char_table, Lisp_Object parent)
468 Lisp_Object temp;
470 CHECK_CHAR_TABLE (char_table);
472 if (!NILP (parent))
474 CHECK_CHAR_TABLE (parent);
476 for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent)
477 if (EQ (temp, char_table))
478 error ("Attempt to make a chartable be its own parent");
481 XCHAR_TABLE (char_table)->parent = parent;
483 return parent;
486 DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
487 2, 2, 0,
488 doc: /* Return the value of CHAR-TABLE's extra-slot number N. */)
489 (Lisp_Object char_table, Lisp_Object n)
491 CHECK_CHAR_TABLE (char_table);
492 CHECK_NUMBER (n);
493 if (XINT (n) < 0
494 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
495 args_out_of_range (char_table, n);
497 return XCHAR_TABLE (char_table)->extras[XINT (n)];
500 DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
501 Sset_char_table_extra_slot,
502 3, 3, 0,
503 doc: /* Set CHAR-TABLE's extra-slot number N to VALUE. */)
504 (Lisp_Object char_table, Lisp_Object n, Lisp_Object value)
506 CHECK_CHAR_TABLE (char_table);
507 CHECK_NUMBER (n);
508 if (XINT (n) < 0
509 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
510 args_out_of_range (char_table, n);
512 return XCHAR_TABLE (char_table)->extras[XINT (n)] = value;
515 DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
516 2, 2, 0,
517 doc: /* Return the value in CHAR-TABLE for a range of characters RANGE.
518 RANGE should be nil (for the default value),
519 a cons of character codes (for characters in the range), or a character code. */)
520 (Lisp_Object char_table, Lisp_Object range)
522 Lisp_Object val;
523 CHECK_CHAR_TABLE (char_table);
525 if (EQ (range, Qnil))
526 val = XCHAR_TABLE (char_table)->defalt;
527 else if (INTEGERP (range))
528 val = CHAR_TABLE_REF (char_table, XINT (range));
529 else if (CONSP (range))
531 int from, to;
533 CHECK_CHARACTER_CAR (range);
534 CHECK_CHARACTER_CDR (range);
535 val = char_table_ref_and_range (char_table, XINT (XCAR (range)),
536 &from, &to);
537 /* Not yet implemented. */
539 else
540 error ("Invalid RANGE argument to `char-table-range'");
541 return val;
544 DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
545 3, 3, 0,
546 doc: /* Set the value in CHAR-TABLE for a range of characters RANGE to VALUE.
547 RANGE should be t (for all characters), nil (for the default value),
548 a cons of character codes (for characters in the range),
549 or a character code. Return VALUE. */)
550 (Lisp_Object char_table, Lisp_Object range, Lisp_Object value)
552 CHECK_CHAR_TABLE (char_table);
553 if (EQ (range, Qt))
555 int i;
557 XCHAR_TABLE (char_table)->ascii = value;
558 for (i = 0; i < chartab_size[0]; i++)
559 XCHAR_TABLE (char_table)->contents[i] = value;
561 else if (EQ (range, Qnil))
562 XCHAR_TABLE (char_table)->defalt = value;
563 else if (INTEGERP (range))
564 char_table_set (char_table, XINT (range), value);
565 else if (CONSP (range))
567 CHECK_CHARACTER_CAR (range);
568 CHECK_CHARACTER_CDR (range);
569 char_table_set_range (char_table,
570 XINT (XCAR (range)), XINT (XCDR (range)), value);
572 else
573 error ("Invalid RANGE argument to `set-char-table-range'");
575 return value;
578 DEFUN ("set-char-table-default", Fset_char_table_default,
579 Sset_char_table_default, 3, 3, 0,
580 doc: /*
581 This function is obsolete and has no effect. */)
582 (Lisp_Object char_table, Lisp_Object ch, Lisp_Object value)
584 return Qnil;
587 /* Look up the element in TABLE at index CH, and return it as an
588 integer. If the element is not a character, return CH itself. */
591 char_table_translate (Lisp_Object table, int ch)
593 Lisp_Object value;
594 value = Faref (table, make_number (ch));
595 if (! CHARACTERP (value))
596 return ch;
597 return XINT (value);
600 static Lisp_Object
601 optimize_sub_char_table (Lisp_Object table, Lisp_Object test)
603 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
604 int depth = XINT (tbl->depth);
605 Lisp_Object elt, this;
606 int i, optimizable;
608 elt = XSUB_CHAR_TABLE (table)->contents[0];
609 if (SUB_CHAR_TABLE_P (elt))
610 elt = XSUB_CHAR_TABLE (table)->contents[0]
611 = optimize_sub_char_table (elt, test);
612 optimizable = SUB_CHAR_TABLE_P (elt) ? 0 : 1;
613 for (i = 1; i < chartab_size[depth]; i++)
615 this = XSUB_CHAR_TABLE (table)->contents[i];
616 if (SUB_CHAR_TABLE_P (this))
617 this = XSUB_CHAR_TABLE (table)->contents[i]
618 = optimize_sub_char_table (this, test);
619 if (optimizable
620 && (NILP (test) ? NILP (Fequal (this, elt)) /* defaults to `equal'. */
621 : EQ (test, Qeq) ? !EQ (this, elt) /* Optimize `eq' case. */
622 : NILP (call2 (test, this, elt))))
623 optimizable = 0;
626 return (optimizable ? elt : table);
629 DEFUN ("optimize-char-table", Foptimize_char_table, Soptimize_char_table,
630 1, 2, 0,
631 doc: /* Optimize CHAR-TABLE.
632 TEST is the comparison function used to decide whether two entries are
633 equivalent and can be merged. It defaults to `equal'. */)
634 (Lisp_Object char_table, Lisp_Object test)
636 Lisp_Object elt;
637 int i;
639 CHECK_CHAR_TABLE (char_table);
641 for (i = 0; i < chartab_size[0]; i++)
643 elt = XCHAR_TABLE (char_table)->contents[i];
644 if (SUB_CHAR_TABLE_P (elt))
645 XCHAR_TABLE (char_table)->contents[i]
646 = optimize_sub_char_table (elt, test);
648 /* Reset the `ascii' cache, in case it got optimized away. */
649 XCHAR_TABLE (char_table)->ascii = char_table_ascii (char_table);
651 return Qnil;
655 /* Map C_FUNCTION or FUNCTION over TABLE (top or sub char-table),
656 calling it for each character or group of characters that share a
657 value. RANGE is a cons (FROM . TO) specifying the range of target
658 characters, VAL is a value of FROM in TABLE, DEFAULT_VAL is the
659 default value of the char-table, PARENT is the parent of the
660 char-table.
662 ARG is passed to C_FUNCTION when that is called.
664 It returns the value of last character covered by TABLE (not the
665 value inheritted from the parent), and by side-effect, the car part
666 of RANGE is updated to the minimum character C where C and all the
667 following characters in TABLE have the same value. */
669 static Lisp_Object
670 map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object),
671 Lisp_Object function, Lisp_Object table, Lisp_Object arg, Lisp_Object val,
672 Lisp_Object range, Lisp_Object default_val, Lisp_Object parent)
674 /* Pointer to the elements of TABLE. */
675 Lisp_Object *contents;
676 /* Depth of TABLE. */
677 int depth;
678 /* Minimum and maxinum characters covered by TABLE. */
679 int min_char, max_char;
680 /* Number of characters covered by one element of TABLE. */
681 int chars_in_block;
682 int from = XINT (XCAR (range)), to = XINT (XCDR (range));
683 int i, c;
685 if (SUB_CHAR_TABLE_P (table))
687 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
689 depth = XINT (tbl->depth);
690 contents = tbl->contents;
691 min_char = XINT (tbl->min_char);
692 max_char = min_char + chartab_chars[depth - 1] - 1;
694 else
696 depth = 0;
697 contents = XCHAR_TABLE (table)->contents;
698 min_char = 0;
699 max_char = MAX_CHAR;
701 chars_in_block = chartab_chars[depth];
703 if (to < max_char)
704 max_char = to;
705 /* Set I to the index of the first element to check. */
706 if (from <= min_char)
707 i = 0;
708 else
709 i = (from - min_char) / chars_in_block;
710 for (c = min_char + chars_in_block * i; c <= max_char;
711 i++, c += chars_in_block)
713 Lisp_Object this = contents[i];
714 int nextc = c + chars_in_block;
716 if (SUB_CHAR_TABLE_P (this))
718 if (to >= nextc)
719 XSETCDR (range, make_number (nextc - 1));
720 val = map_sub_char_table (c_function, function, this, arg,
721 val, range, default_val, parent);
723 else
725 if (NILP (this))
726 this = default_val;
727 if (!EQ (val, this))
729 int different_value = 1;
731 if (NILP (val))
733 if (! NILP (parent))
735 Lisp_Object temp = XCHAR_TABLE (parent)->parent;
737 /* This is to get a value of FROM in PARENT
738 without checking the parent of PARENT. */
739 XCHAR_TABLE (parent)->parent = Qnil;
740 val = CHAR_TABLE_REF (parent, from);
741 XCHAR_TABLE (parent)->parent = temp;
742 XSETCDR (range, make_number (c - 1));
743 val = map_sub_char_table (c_function, function,
744 parent, arg, val, range,
745 XCHAR_TABLE (parent)->defalt,
746 XCHAR_TABLE (parent)->parent);
747 if (EQ (val, this))
748 different_value = 0;
751 if (! NILP (val) && different_value)
753 XSETCDR (range, make_number (c - 1));
754 if (EQ (XCAR (range), XCDR (range)))
756 if (c_function)
757 (*c_function) (arg, XCAR (range), val);
758 else
759 call2 (function, XCAR (range), val);
761 else
763 if (c_function)
764 (*c_function) (arg, range, val);
765 else
766 call2 (function, range, val);
769 val = this;
770 from = c;
771 XSETCAR (range, make_number (c));
774 XSETCDR (range, make_number (to));
776 return val;
780 /* Map C_FUNCTION or FUNCTION over TABLE, calling it for each
781 character or group of characters that share a value.
783 ARG is passed to C_FUNCTION when that is called. */
785 void
786 map_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), Lisp_Object function, Lisp_Object table, Lisp_Object arg)
788 Lisp_Object range, val;
789 struct gcpro gcpro1, gcpro2, gcpro3;
791 range = Fcons (make_number (0), make_number (MAX_CHAR));
792 GCPRO3 (table, arg, range);
793 val = XCHAR_TABLE (table)->ascii;
794 if (SUB_CHAR_TABLE_P (val))
795 val = XSUB_CHAR_TABLE (val)->contents[0];
796 val = map_sub_char_table (c_function, function, table, arg, val, range,
797 XCHAR_TABLE (table)->defalt,
798 XCHAR_TABLE (table)->parent);
799 /* If VAL is nil and TABLE has a parent, we must consult the parent
800 recursively. */
801 while (NILP (val) && ! NILP (XCHAR_TABLE (table)->parent))
803 Lisp_Object parent = XCHAR_TABLE (table)->parent;
804 Lisp_Object temp = XCHAR_TABLE (parent)->parent;
805 int from = XINT (XCAR (range));
807 /* This is to get a value of FROM in PARENT without checking the
808 parent of PARENT. */
809 XCHAR_TABLE (parent)->parent = Qnil;
810 val = CHAR_TABLE_REF (parent, from);
811 XCHAR_TABLE (parent)->parent = temp;
812 val = map_sub_char_table (c_function, function, parent, arg, val, range,
813 XCHAR_TABLE (parent)->defalt,
814 XCHAR_TABLE (parent)->parent);
815 table = parent;
818 if (! NILP (val))
820 if (EQ (XCAR (range), XCDR (range)))
822 if (c_function)
823 (*c_function) (arg, XCAR (range), val);
824 else
825 call2 (function, XCAR (range), val);
827 else
829 if (c_function)
830 (*c_function) (arg, range, val);
831 else
832 call2 (function, range, val);
836 UNGCPRO;
839 DEFUN ("map-char-table", Fmap_char_table, Smap_char_table,
840 2, 2, 0,
841 doc: /*
842 Call FUNCTION for each character in CHAR-TABLE that has non-nil value.
843 FUNCTION is called with two arguments--a key and a value.
844 The key is a character code or a cons of character codes specifying a
845 range of characters that have the same value. */)
846 (Lisp_Object function, Lisp_Object char_table)
848 CHECK_CHAR_TABLE (char_table);
850 map_char_table (NULL, function, char_table, char_table);
851 return Qnil;
855 static void
856 map_sub_char_table_for_charset (void (*c_function) (Lisp_Object, Lisp_Object),
857 Lisp_Object function, Lisp_Object table, Lisp_Object arg,
858 Lisp_Object range, struct charset *charset,
859 unsigned from, unsigned to)
861 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
862 int depth = XINT (tbl->depth);
863 int c, i;
865 if (depth < 3)
866 for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth];
867 i++, c += chartab_chars[depth])
869 Lisp_Object this;
871 this = tbl->contents[i];
872 if (SUB_CHAR_TABLE_P (this))
873 map_sub_char_table_for_charset (c_function, function, this, arg,
874 range, charset, from, to);
875 else
877 if (! NILP (XCAR (range)))
879 XSETCDR (range, make_number (c - 1));
880 if (c_function)
881 (*c_function) (arg, range);
882 else
883 call2 (function, range, arg);
885 XSETCAR (range, Qnil);
888 else
889 for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth]; i++, c ++)
891 Lisp_Object this;
892 unsigned code;
894 this = tbl->contents[i];
895 if (NILP (this)
896 || (charset
897 && (code = ENCODE_CHAR (charset, c),
898 (code < from || code > to))))
900 if (! NILP (XCAR (range)))
902 XSETCDR (range, make_number (c - 1));
903 if (c_function)
904 (*c_function) (arg, range);
905 else
906 call2 (function, range, arg);
907 XSETCAR (range, Qnil);
910 else
912 if (NILP (XCAR (range)))
913 XSETCAR (range, make_number (c));
919 /* Support function for `map-charset-chars'. Map C_FUNCTION or
920 FUNCTION over TABLE, calling it for each character or a group of
921 succeeding characters that have non-nil value in TABLE. TABLE is a
922 "mapping table" or a "deunifier table" of a certain charset.
924 If CHARSET is not NULL (this is the case that `map-charset-chars'
925 is called with non-nil FROM-CODE and TO-CODE), it is a charset who
926 owns TABLE, and the function is called only on a character in the
927 range FROM and TO. FROM and TO are not character codes, but code
928 points of a character in CHARSET.
930 This function is called in these two cases:
932 (1) A charset has a mapping file name in :map property.
934 (2) A charset has an upper code space in :offset property and a
935 mapping file name in :unify-map property. In this case, this
936 function is called only for characters in the Unicode code space.
937 Characters in upper code space are handled directly in
938 map_charset_chars. */
940 void
941 map_char_table_for_charset (void (*c_function) (Lisp_Object, Lisp_Object),
942 Lisp_Object function, Lisp_Object table, Lisp_Object arg,
943 struct charset *charset,
944 unsigned from, unsigned to)
946 Lisp_Object range;
947 int c, i;
948 struct gcpro gcpro1;
950 range = Fcons (Qnil, Qnil);
951 GCPRO1 (range);
953 for (i = 0, c = 0; i < chartab_size[0]; i++, c += chartab_chars[0])
955 Lisp_Object this;
957 this = XCHAR_TABLE (table)->contents[i];
958 if (SUB_CHAR_TABLE_P (this))
959 map_sub_char_table_for_charset (c_function, function, this, arg,
960 range, charset, from, to);
961 else
963 if (! NILP (XCAR (range)))
965 XSETCDR (range, make_number (c - 1));
966 if (c_function)
967 (*c_function) (arg, range);
968 else
969 call2 (function, range, arg);
971 XSETCAR (range, Qnil);
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);
983 UNGCPRO;
987 void
988 syms_of_chartab (void)
990 defsubr (&Smake_char_table);
991 defsubr (&Schar_table_parent);
992 defsubr (&Schar_table_subtype);
993 defsubr (&Sset_char_table_parent);
994 defsubr (&Schar_table_extra_slot);
995 defsubr (&Sset_char_table_extra_slot);
996 defsubr (&Schar_table_range);
997 defsubr (&Sset_char_table_range);
998 defsubr (&Sset_char_table_default);
999 defsubr (&Soptimize_char_table);
1000 defsubr (&Smap_char_table);