Merge from emacs--devo--0
[emacs.git] / src / chartab.c
blob5306e22cefc4b57c4851080f4a81f27e4551a929
1 /* chartab.c -- char-table support
2 Copyright (C) 2003
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, or (at your option)
11 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; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 #include <config.h>
24 #include "lisp.h"
25 #include "character.h"
26 #include "charset.h"
27 #include "ccl.h"
29 /* 64/16/32/128 */
31 /* Number of elements in Nth level char-table. */
32 const int chartab_size[4] =
33 { (1 << CHARTAB_SIZE_BITS_0),
34 (1 << CHARTAB_SIZE_BITS_1),
35 (1 << CHARTAB_SIZE_BITS_2),
36 (1 << CHARTAB_SIZE_BITS_3) };
38 /* Number of characters each element of Nth level char-table
39 covers. */
40 const int chartab_chars[4] =
41 { (1 << (CHARTAB_SIZE_BITS_1 + CHARTAB_SIZE_BITS_2 + CHARTAB_SIZE_BITS_3)),
42 (1 << (CHARTAB_SIZE_BITS_2 + CHARTAB_SIZE_BITS_3)),
43 (1 << CHARTAB_SIZE_BITS_3),
44 1 };
46 /* Number of characters (in bits) each element of Nth level char-table
47 covers. */
48 const int chartab_bits[4] =
49 { (CHARTAB_SIZE_BITS_1 + CHARTAB_SIZE_BITS_2 + CHARTAB_SIZE_BITS_3),
50 (CHARTAB_SIZE_BITS_2 + CHARTAB_SIZE_BITS_3),
51 CHARTAB_SIZE_BITS_3,
52 0 };
54 #define CHARTAB_IDX(c, depth, min_char) \
55 (((c) - (min_char)) >> chartab_bits[(depth)])
58 DEFUN ("make-char-table", Fmake_char_table, Smake_char_table, 1, 2, 0,
59 doc: /* Return a newly created char-table, with purpose PURPOSE.
60 Each element is initialized to INIT, which defaults to nil.
62 PURPOSE should be a symbol. If it has a `char-table-extra-slots'
63 property, the property's value should be an integer between 0 and 10
64 that specifies how many extra slots the char-table has. Otherwise,
65 the char-table has no extra slot. */)
66 (purpose, init)
67 register Lisp_Object purpose, init;
69 Lisp_Object vector;
70 Lisp_Object n;
71 int n_extras;
72 int size;
74 CHECK_SYMBOL (purpose);
75 n = Fget (purpose, Qchar_table_extra_slots);
76 if (NILP (n))
77 n_extras = 0;
78 else
80 CHECK_NATNUM (n);
81 n_extras = XINT (n);
82 if (n_extras > 10)
83 args_out_of_range (n, Qnil);
86 size = VECSIZE (struct Lisp_Char_Table) - 1 + n_extras;
87 vector = Fmake_vector (make_number (size), init);
88 XSETPVECTYPE (XVECTOR (vector), PVEC_CHAR_TABLE);
89 XCHAR_TABLE (vector)->parent = Qnil;
90 XCHAR_TABLE (vector)->purpose = purpose;
91 XSETCHAR_TABLE (vector, XCHAR_TABLE (vector));
92 return vector;
95 static Lisp_Object
96 make_sub_char_table (depth, min_char, defalt)
97 int depth, min_char;
98 Lisp_Object defalt;
100 Lisp_Object table;
101 int size = VECSIZE (struct Lisp_Sub_Char_Table) - 1 + chartab_size[depth];
103 table = Fmake_vector (make_number (size), defalt);
104 XSETPVECTYPE (XVECTOR (table), PVEC_SUB_CHAR_TABLE);
105 XSUB_CHAR_TABLE (table)->depth = make_number (depth);
106 XSUB_CHAR_TABLE (table)->min_char = make_number (min_char);
107 XSETSUB_CHAR_TABLE (table, XSUB_CHAR_TABLE (table));
109 return table;
112 static Lisp_Object
113 char_table_ascii (table)
114 Lisp_Object table;
116 Lisp_Object sub;
118 sub = XCHAR_TABLE (table)->contents[0];
119 if (! SUB_CHAR_TABLE_P (sub))
120 return sub;
121 sub = XSUB_CHAR_TABLE (sub)->contents[0];
122 if (! SUB_CHAR_TABLE_P (sub))
123 return sub;
124 return XSUB_CHAR_TABLE (sub)->contents[0];
127 Lisp_Object
128 copy_sub_char_table (table)
129 Lisp_Object table;
131 Lisp_Object copy;
132 int depth = XINT (XSUB_CHAR_TABLE (table)->depth);
133 int min_char = XINT (XSUB_CHAR_TABLE (table)->min_char);
134 Lisp_Object val;
135 int i;
137 copy = make_sub_char_table (depth, min_char, Qnil);
138 /* Recursively copy any sub char-tables. */
139 for (i = 0; i < chartab_size[depth]; i++)
141 val = XSUB_CHAR_TABLE (table)->contents[i];
142 if (SUB_CHAR_TABLE_P (val))
143 XSUB_CHAR_TABLE (copy)->contents[i] = copy_sub_char_table (val);
144 else
145 XSUB_CHAR_TABLE (copy)->contents[i] = val;
148 return copy;
152 Lisp_Object
153 copy_char_table (table)
154 Lisp_Object table;
156 Lisp_Object copy;
157 int size = XCHAR_TABLE (table)->size & PSEUDOVECTOR_SIZE_MASK;
158 int i;
160 copy = Fmake_vector (make_number (size), Qnil);
161 XSETPVECTYPE (XVECTOR (copy), PVEC_CHAR_TABLE);
162 XCHAR_TABLE (copy)->defalt = XCHAR_TABLE (table)->defalt;
163 XCHAR_TABLE (copy)->parent = XCHAR_TABLE (table)->parent;
164 XCHAR_TABLE (copy)->purpose = XCHAR_TABLE (table)->purpose;
165 XCHAR_TABLE (copy)->ascii = XCHAR_TABLE (table)->ascii;
166 for (i = 0; i < chartab_size[0]; i++)
167 XCHAR_TABLE (copy)->contents[i]
168 = (SUB_CHAR_TABLE_P (XCHAR_TABLE (table)->contents[i])
169 ? copy_sub_char_table (XCHAR_TABLE (table)->contents[i])
170 : XCHAR_TABLE (table)->contents[i]);
171 if (SUB_CHAR_TABLE_P (XCHAR_TABLE (copy)->ascii))
172 XCHAR_TABLE (copy)->ascii = char_table_ascii (copy);
173 size -= VECSIZE (struct Lisp_Char_Table) - 1;
174 for (i = 0; i < size; i++)
175 XCHAR_TABLE (copy)->extras[i] = XCHAR_TABLE (table)->extras[i];
177 XSETCHAR_TABLE (copy, XCHAR_TABLE (copy));
178 return copy;
181 Lisp_Object
182 sub_char_table_ref (table, c)
183 Lisp_Object table;
184 int c;
186 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
187 int depth = XINT (tbl->depth);
188 int min_char = XINT (tbl->min_char);
189 Lisp_Object val;
191 val = tbl->contents[CHARTAB_IDX (c, depth, min_char)];
192 if (SUB_CHAR_TABLE_P (val))
193 val = sub_char_table_ref (val, c);
194 return val;
197 Lisp_Object
198 char_table_ref (table, c)
199 Lisp_Object table;
200 int c;
202 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
203 Lisp_Object val;
205 if (ASCII_CHAR_P (c))
207 val = tbl->ascii;
208 if (SUB_CHAR_TABLE_P (val))
209 val = XSUB_CHAR_TABLE (val)->contents[c];
211 else
213 val = tbl->contents[CHARTAB_IDX (c, 0, 0)];
214 if (SUB_CHAR_TABLE_P (val))
215 val = sub_char_table_ref (val, c);
217 if (NILP (val))
219 val = tbl->defalt;
220 if (NILP (val) && CHAR_TABLE_P (tbl->parent))
221 val = char_table_ref (tbl->parent, c);
223 return val;
226 static Lisp_Object
227 sub_char_table_ref_and_range (table, c, from, to, defalt)
228 Lisp_Object table;
229 int c;
230 int *from, *to;
231 Lisp_Object defalt;
233 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
234 int depth = XINT (tbl->depth);
235 int min_char = XINT (tbl->min_char);
236 int max_char = min_char + chartab_chars[depth - 1] - 1;
237 int index = CHARTAB_IDX (c, depth, min_char);
238 Lisp_Object val;
240 val = tbl->contents[index];
241 *from = min_char + index * chartab_chars[depth];
242 *to = *from + chartab_chars[depth] - 1;
243 if (SUB_CHAR_TABLE_P (val))
244 val = sub_char_table_ref_and_range (val, c, from, to, defalt);
245 else if (NILP (val))
246 val = defalt;
248 while (*from > min_char
249 && *from == min_char + index * chartab_chars[depth])
251 Lisp_Object this_val;
252 int this_from = *from - chartab_chars[depth];
253 int this_to = *from - 1;
255 index--;
256 this_val = tbl->contents[index];
257 if (SUB_CHAR_TABLE_P (this_val))
258 this_val = sub_char_table_ref_and_range (this_val, this_to,
259 &this_from, &this_to,
260 defalt);
261 else if (NILP (this_val))
262 this_val = defalt;
264 if (! EQ (this_val, val))
265 break;
266 *from = this_from;
268 index = CHARTAB_IDX (c, depth, min_char);
269 while (*to < max_char
270 && *to == min_char + (index + 1) * chartab_chars[depth] - 1)
272 Lisp_Object this_val;
273 int this_from = *to + 1;
274 int this_to = this_from + chartab_chars[depth] - 1;
276 index++;
277 this_val = tbl->contents[index];
278 if (SUB_CHAR_TABLE_P (this_val))
279 this_val = sub_char_table_ref_and_range (this_val, this_from,
280 &this_from, &this_to,
281 defalt);
282 else if (NILP (this_val))
283 this_val = defalt;
284 if (! EQ (this_val, val))
285 break;
286 *to = this_to;
289 return val;
293 /* Return the value for C in char-table TABLE. Set *FROM and *TO to
294 the range of characters (containing C) that have the same value as
295 C. It is not assured that the value of (*FROM - 1) and (*TO + 1)
296 is different from that of C. */
298 Lisp_Object
299 char_table_ref_and_range (table, c, from, to)
300 Lisp_Object table;
301 int c;
302 int *from, *to;
304 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
305 int index = CHARTAB_IDX (c, 0, 0);
306 Lisp_Object val;
308 val = tbl->contents[index];
309 *from = index * chartab_chars[0];
310 *to = *from + chartab_chars[0] - 1;
311 if (SUB_CHAR_TABLE_P (val))
312 val = sub_char_table_ref_and_range (val, c, from, to, tbl->defalt);
313 else if (NILP (val))
314 val = tbl->defalt;
316 while (*from > 0 && *from == index * chartab_chars[0])
318 Lisp_Object this_val;
319 int this_from = *from - chartab_chars[0];
320 int this_to = *from - 1;
322 index--;
323 this_val = tbl->contents[index];
324 if (SUB_CHAR_TABLE_P (this_val))
325 this_val = sub_char_table_ref_and_range (this_val, this_to,
326 &this_from, &this_to,
327 tbl->defalt);
328 else if (NILP (this_val))
329 this_val = tbl->defalt;
331 if (! EQ (this_val, val))
332 break;
333 *from = this_from;
335 while (*to < MAX_CHAR && *to == (index + 1) * chartab_chars[0] - 1)
337 Lisp_Object this_val;
338 int this_from = *to + 1;
339 int this_to = this_from + chartab_chars[0] - 1;
341 index++;
342 this_val = tbl->contents[index];
343 if (SUB_CHAR_TABLE_P (this_val))
344 this_val = sub_char_table_ref_and_range (this_val, this_from,
345 &this_from, &this_to,
346 tbl->defalt);
347 else if (NILP (this_val))
348 this_val = tbl->defalt;
349 if (! EQ (this_val, val))
350 break;
351 *to = this_to;
354 return val;
358 #define ASET_RANGE(ARRAY, FROM, TO, LIMIT, VAL) \
359 do { \
360 int limit = (TO) < (LIMIT) ? (TO) : (LIMIT); \
361 for (; (FROM) < limit; (FROM)++) (ARRAY)->contents[(FROM)] = (VAL); \
362 } while (0)
364 #define GET_SUB_CHAR_TABLE(TABLE, SUBTABLE, IDX, DEPTH, MIN_CHAR) \
365 do { \
366 (SUBTABLE) = (TABLE)->contents[(IDX)]; \
367 if (!SUB_CHAR_TABLE_P (SUBTABLE)) \
368 (SUBTABLE) = make_sub_char_table ((DEPTH), (MIN_CHAR), (SUBTABLE)); \
369 } while (0)
372 static void
373 sub_char_table_set (table, c, val)
374 Lisp_Object table;
375 int c;
376 Lisp_Object val;
378 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
379 int depth = XINT ((tbl)->depth);
380 int min_char = XINT ((tbl)->min_char);
381 int i = CHARTAB_IDX (c, depth, min_char);
382 Lisp_Object sub;
384 if (depth == 3)
385 tbl->contents[i] = val;
386 else
388 sub = tbl->contents[i];
389 if (! SUB_CHAR_TABLE_P (sub))
391 sub = make_sub_char_table (depth + 1,
392 min_char + i * chartab_chars[depth], sub);
393 tbl->contents[i] = sub;
395 sub_char_table_set (sub, c, val);
399 Lisp_Object
400 char_table_set (table, c, val)
401 Lisp_Object table;
402 int c;
403 Lisp_Object val;
405 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
407 if (ASCII_CHAR_P (c)
408 && SUB_CHAR_TABLE_P (tbl->ascii))
410 XSUB_CHAR_TABLE (tbl->ascii)->contents[c] = val;
412 else
414 int i = CHARTAB_IDX (c, 0, 0);
415 Lisp_Object sub;
417 sub = tbl->contents[i];
418 if (! SUB_CHAR_TABLE_P (sub))
420 sub = make_sub_char_table (1, i * chartab_chars[0], sub);
421 tbl->contents[i] = sub;
423 sub_char_table_set (sub, c, val);
424 if (ASCII_CHAR_P (c))
425 tbl->ascii = char_table_ascii (table);
427 return val;
430 static void
431 sub_char_table_set_range (table, depth, min_char, from, to, val)
432 Lisp_Object *table;
433 int depth;
434 int min_char;
435 int from, to;
436 Lisp_Object val;
438 int max_char = min_char + chartab_chars[depth] - 1;
440 if (depth == 3 || (from <= min_char && to >= max_char))
441 *table = val;
442 else
444 int i, j;
446 depth++;
447 if (! SUB_CHAR_TABLE_P (*table))
448 *table = make_sub_char_table (depth, min_char, *table);
449 if (from < min_char)
450 from = min_char;
451 if (to > max_char)
452 to = max_char;
453 i = CHARTAB_IDX (from, depth, min_char);
454 j = CHARTAB_IDX (to, depth, min_char);
455 min_char += chartab_chars[depth] * i;
456 for (; i <= j; i++, min_char += chartab_chars[depth])
457 sub_char_table_set_range (XSUB_CHAR_TABLE (*table)->contents + i,
458 depth, min_char, from, to, val);
463 Lisp_Object
464 char_table_set_range (table, from, to, val)
465 Lisp_Object table;
466 int from, to;
467 Lisp_Object val;
469 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
470 Lisp_Object *contents = tbl->contents;
471 int i, min_char;
473 if (from == to)
474 char_table_set (table, from, val);
475 else
477 for (i = CHARTAB_IDX (from, 0, 0), min_char = i * chartab_chars[0];
478 min_char <= to;
479 i++, min_char += chartab_chars[0])
480 sub_char_table_set_range (contents + i, 0, min_char, from, to, val);
481 if (ASCII_CHAR_P (from))
482 tbl->ascii = char_table_ascii (table);
484 return val;
488 DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype,
489 1, 1, 0,
490 doc: /*
491 Return the subtype of char-table CHAR-TABLE. The value is a symbol. */)
492 (char_table)
493 Lisp_Object char_table;
495 CHECK_CHAR_TABLE (char_table);
497 return XCHAR_TABLE (char_table)->purpose;
500 DEFUN ("char-table-parent", Fchar_table_parent, Schar_table_parent,
501 1, 1, 0,
502 doc: /* Return the parent char-table of CHAR-TABLE.
503 The value is either nil or another char-table.
504 If CHAR-TABLE holds nil for a given character,
505 then the actual applicable value is inherited from the parent char-table
506 \(or from its parents, if necessary). */)
507 (char_table)
508 Lisp_Object char_table;
510 CHECK_CHAR_TABLE (char_table);
512 return XCHAR_TABLE (char_table)->parent;
515 DEFUN ("set-char-table-parent", Fset_char_table_parent, Sset_char_table_parent,
516 2, 2, 0,
517 doc: /* Set the parent char-table of CHAR-TABLE to PARENT.
518 Return PARENT. PARENT must be either nil or another char-table. */)
519 (char_table, parent)
520 Lisp_Object char_table, parent;
522 Lisp_Object temp;
524 CHECK_CHAR_TABLE (char_table);
526 if (!NILP (parent))
528 CHECK_CHAR_TABLE (parent);
530 for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent)
531 if (EQ (temp, char_table))
532 error ("Attempt to make a chartable be its own parent");
535 XCHAR_TABLE (char_table)->parent = parent;
537 return parent;
540 DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
541 2, 2, 0,
542 doc: /* Return the value of CHAR-TABLE's extra-slot number N. */)
543 (char_table, n)
544 Lisp_Object char_table, n;
546 CHECK_CHAR_TABLE (char_table);
547 CHECK_NUMBER (n);
548 if (XINT (n) < 0
549 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
550 args_out_of_range (char_table, n);
552 return XCHAR_TABLE (char_table)->extras[XINT (n)];
555 DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
556 Sset_char_table_extra_slot,
557 3, 3, 0,
558 doc: /* Set CHAR-TABLE's extra-slot number N to VALUE. */)
559 (char_table, n, value)
560 Lisp_Object char_table, n, value;
562 CHECK_CHAR_TABLE (char_table);
563 CHECK_NUMBER (n);
564 if (XINT (n) < 0
565 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
566 args_out_of_range (char_table, n);
568 return XCHAR_TABLE (char_table)->extras[XINT (n)] = value;
571 DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
572 2, 2, 0,
573 doc: /* Return the value in CHAR-TABLE for a range of characters RANGE.
574 RANGE should be nil (for the default value),
575 a cons of character codes (for characters in the range), or a character code. */)
576 (char_table, range)
577 Lisp_Object char_table, range;
579 Lisp_Object val;
580 CHECK_CHAR_TABLE (char_table);
582 if (EQ (range, Qnil))
583 val = XCHAR_TABLE (char_table)->defalt;
584 else if (INTEGERP (range))
585 val = CHAR_TABLE_REF (char_table, XINT (range));
586 else if (CONSP (range))
588 int from, to;
590 CHECK_CHARACTER_CAR (range);
591 CHECK_CHARACTER_CDR (range);
592 val = char_table_ref_and_range (char_table, XINT (XCAR (range)),
593 &from, &to);
594 /* Not yet implemented. */
596 else
597 error ("Invalid RANGE argument to `char-table-range'");
598 return val;
601 DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
602 3, 3, 0,
603 doc: /* Set the value in CHAR-TABLE for a range of characters RANGE to VALUE.
604 RANGE should be t (for all characters), nil (for the default value),
605 a cons of character codes (for characters in the range),
606 or a character code. Return VALUE. */)
607 (char_table, range, value)
608 Lisp_Object char_table, range, value;
610 CHECK_CHAR_TABLE (char_table);
611 if (EQ (range, Qt))
613 int i;
615 XCHAR_TABLE (char_table)->ascii = Qnil;
616 for (i = 0; i < chartab_size[0]; i++)
617 XCHAR_TABLE (char_table)->contents[i] = Qnil;
618 XCHAR_TABLE (char_table)->defalt = value;
620 else if (EQ (range, Qnil))
621 XCHAR_TABLE (char_table)->defalt = value;
622 else if (INTEGERP (range))
623 char_table_set (char_table, XINT (range), value);
624 else if (CONSP (range))
626 CHECK_CHARACTER_CAR (range);
627 CHECK_CHARACTER_CDR (range);
628 char_table_set_range (char_table,
629 XINT (XCAR (range)), XINT (XCDR (range)), value);
631 else
632 error ("Invalid RANGE argument to `set-char-table-range'");
634 return value;
637 DEFUN ("set-char-table-default", Fset_char_table_default,
638 Sset_char_table_default, 3, 3, 0,
639 doc: /*
640 This function is obsolete and has no effect. */)
641 (char_table, ch, value)
642 Lisp_Object char_table, ch, value;
644 return Qnil;
647 /* Look up the element in TABLE at index CH, and return it as an
648 integer. If the element is not a character, return CH itself. */
651 char_table_translate (table, ch)
652 Lisp_Object table;
653 int ch;
655 Lisp_Object value;
656 value = Faref (table, make_number (ch));
657 if (! CHARACTERP (value))
658 return ch;
659 return XINT (value);
662 static Lisp_Object
663 optimize_sub_char_table (table)
664 Lisp_Object table;
666 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
667 int depth = XINT (tbl->depth);
668 Lisp_Object elt, this;
669 int i;
671 elt = XSUB_CHAR_TABLE (table)->contents[0];
672 if (SUB_CHAR_TABLE_P (elt))
673 elt = XSUB_CHAR_TABLE (table)->contents[0] = optimize_sub_char_table (elt);
674 if (SUB_CHAR_TABLE_P (elt))
675 return table;
676 for (i = 1; i < chartab_size[depth]; i++)
678 this = XSUB_CHAR_TABLE (table)->contents[i];
679 if (SUB_CHAR_TABLE_P (this))
680 this = XSUB_CHAR_TABLE (table)->contents[i]
681 = optimize_sub_char_table (this);
682 if (SUB_CHAR_TABLE_P (this)
683 || NILP (Fequal (this, elt)))
684 break;
687 return (i < chartab_size[depth] ? table : elt);
690 DEFUN ("optimize-char-table", Foptimize_char_table, Soptimize_char_table,
691 1, 1, 0,
692 doc: /* Optimize CHAR-TABLE. */)
693 (char_table)
694 Lisp_Object char_table;
696 Lisp_Object elt;
697 int i;
699 CHECK_CHAR_TABLE (char_table);
701 for (i = 0; i < chartab_size[0]; i++)
703 elt = XCHAR_TABLE (char_table)->contents[i];
704 if (SUB_CHAR_TABLE_P (elt))
705 XCHAR_TABLE (char_table)->contents[i] = optimize_sub_char_table (elt);
707 return Qnil;
711 /* Map C_FUNCTION or FUNCTION over TABLE (top or sub char-table),
712 calling it for each character or group of characters that share a
713 value. RANGE is a cons (FROM . TO) specifying the range of target
714 characters, VAL is a value of FROM in TABLE, DEFAULT_VAL is the
715 default value of the char-table, PARENT is the parent of the
716 char-table.
718 ARG is passed to C_FUNCTION when that is called.
720 It returns the value of last character covered by TABLE (not the
721 value inheritted from the parent), and by side-effect, the car part
722 of RANGE is updated to the minimum character C where C and all the
723 following characters in TABLE have the same value. */
725 static Lisp_Object
726 map_sub_char_table (c_function, function, table, arg, val, range,
727 default_val, parent)
728 void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
729 Lisp_Object function, table, arg, val, range, default_val, parent;
731 /* Pointer to the elements of TABLE. */
732 Lisp_Object *contents;
733 /* Depth of TABLE. */
734 int depth;
735 /* Minimum and maxinum characters covered by TABLE. */
736 int min_char, max_char;
737 /* Number of characters covered by one element of TABLE. */
738 int chars_in_block;
739 int from = XINT (XCAR (range)), to = XINT (XCDR (range));
740 int i, c;
742 if (SUB_CHAR_TABLE_P (table))
744 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
746 depth = XINT (tbl->depth);
747 contents = tbl->contents;
748 min_char = XINT (tbl->min_char);
749 max_char = min_char + chartab_chars[depth - 1] - 1;
751 else
753 depth = 0;
754 contents = XCHAR_TABLE (table)->contents;
755 min_char = 0;
756 max_char = MAX_CHAR;
758 chars_in_block = chartab_chars[depth];
760 if (to < max_char)
761 max_char = to;
762 /* Set I to the index of the first element to check. */
763 if (from <= min_char)
764 i = 0;
765 else
766 i = (from - min_char) / chars_in_block;
767 for (c = min_char + chars_in_block * i; c <= max_char;
768 i++, c += chars_in_block)
770 Lisp_Object this = contents[i];
771 int nextc = c + chars_in_block;
773 if (SUB_CHAR_TABLE_P (this))
775 if (to >= nextc)
776 XSETCDR (range, make_number (nextc - 1));
777 val = map_sub_char_table (c_function, function, this, arg,
778 val, range, default_val, parent);
780 else
782 if (NILP (this))
783 this = default_val;
784 if (NILP (Fequal (val, this)))
786 int different_value = 1;
788 if (NILP (val))
790 if (! NILP (parent))
792 Lisp_Object temp = XCHAR_TABLE (parent)->parent;
794 /* This is to get a value of FROM in PARENT
795 without checking the parent of PARENT. */
796 XCHAR_TABLE (parent)->parent = Qnil;
797 val = CHAR_TABLE_REF (parent, from);
798 XCHAR_TABLE (parent)->parent = temp;
799 XSETCDR (range, make_number (c - 1));
800 val = map_sub_char_table (c_function, function,
801 parent, arg, val, range,
802 XCHAR_TABLE (parent)->defalt,
803 XCHAR_TABLE (parent)->parent);
804 if (! NILP (Fequal (val, this)))
805 different_value = 0;
808 if (! NILP (val) && different_value)
810 XSETCDR (range, make_number (c - 1));
811 if (EQ (XCAR (range), XCDR (range)))
813 if (c_function)
814 (*c_function) (arg, XCAR (range), val);
815 else
816 call2 (function, XCAR (range), val);
818 else
820 if (c_function)
821 (*c_function) (arg, range, val);
822 else
823 call2 (function, range, val);
826 val = this;
827 from = c;
828 XSETCAR (range, make_number (c));
831 XSETCDR (range, make_number (to));
833 return val;
837 /* Map C_FUNCTION or FUNCTION over TABLE, calling it for each
838 character or group of characters that share a value.
840 ARG is passed to C_FUNCTION when that is called. */
842 void
843 map_char_table (c_function, function, table, arg)
844 void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
845 Lisp_Object function, table, arg;
847 Lisp_Object range, val;
848 int c, i;
849 struct gcpro gcpro1, gcpro2, gcpro3;
851 range = Fcons (make_number (0), make_number (MAX_CHAR));
852 GCPRO3 (table, arg, range);
853 val = XCHAR_TABLE (table)->ascii;
854 if (SUB_CHAR_TABLE_P (val))
855 val = XSUB_CHAR_TABLE (val)->contents[0];
856 val = map_sub_char_table (c_function, function, table, arg, val, range,
857 XCHAR_TABLE (table)->defalt,
858 XCHAR_TABLE (table)->parent);
859 /* If VAL is nil and TABLE has a parent, we must consult the parent
860 recursively. */
861 while (NILP (val) && ! NILP (XCHAR_TABLE (table)->parent))
863 Lisp_Object parent = XCHAR_TABLE (table)->parent;
864 Lisp_Object temp = XCHAR_TABLE (parent)->parent;
865 int from = XINT (XCAR (range));
867 /* This is to get a value of FROM in PARENT without checking the
868 parent of PARENT. */
869 XCHAR_TABLE (parent)->parent = Qnil;
870 val = CHAR_TABLE_REF (parent, from);
871 XCHAR_TABLE (parent)->parent = temp;
872 val = map_sub_char_table (c_function, function, parent, arg, val, range,
873 XCHAR_TABLE (parent)->defalt,
874 XCHAR_TABLE (parent)->parent);
875 table = parent;
878 if (! NILP (val))
880 if (EQ (XCAR (range), XCDR (range)))
882 if (c_function)
883 (*c_function) (arg, XCAR (range), val);
884 else
885 call2 (function, XCAR (range), val);
887 else
889 if (c_function)
890 (*c_function) (arg, range, val);
891 else
892 call2 (function, range, val);
896 UNGCPRO;
899 DEFUN ("map-char-table", Fmap_char_table, Smap_char_table,
900 2, 2, 0,
901 doc: /*
902 Call FUNCTION for each character in CHAR-TABLE that has non-nil value.
903 FUNCTION is called with two arguments--a key and a value.
904 The key is a character code or a cons of character codes specifying a
905 range of characters that have the same value. */)
906 (function, char_table)
907 Lisp_Object function, char_table;
909 CHECK_CHAR_TABLE (char_table);
911 map_char_table (NULL, function, char_table, char_table);
912 return Qnil;
916 static void
917 map_sub_char_table_for_charset (c_function, function, table, arg, range,
918 charset, from, to)
919 void (*c_function) P_ ((Lisp_Object, Lisp_Object));
920 Lisp_Object function, table, arg, range;
921 struct charset *charset;
922 unsigned from, to;
924 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
925 int depth = XINT (tbl->depth);
926 int c, i;
928 if (depth < 3)
929 for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth];
930 i++, c += chartab_chars[depth])
932 Lisp_Object this;
934 this = tbl->contents[i];
935 if (SUB_CHAR_TABLE_P (this))
936 map_sub_char_table_for_charset (c_function, function, this, arg,
937 range, charset, from, to);
938 else
940 if (! NILP (XCAR (range)))
942 XSETCDR (range, make_number (c - 1));
943 if (c_function)
944 (*c_function) (arg, range);
945 else
946 call2 (function, range, arg);
948 XSETCAR (range, Qnil);
951 else
952 for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth]; i++, c ++)
954 Lisp_Object this;
955 unsigned code;
957 this = tbl->contents[i];
958 if (NILP (this)
959 || (charset
960 && (code = ENCODE_CHAR (charset, c),
961 (code < from || code > to))))
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);
970 XSETCAR (range, Qnil);
973 else
975 if (NILP (XCAR (range)))
976 XSETCAR (range, make_number (c));
982 void
983 map_char_table_for_charset (c_function, function, table, arg,
984 charset, from, to)
985 void (*c_function) P_ ((Lisp_Object, Lisp_Object));
986 Lisp_Object function, table, arg;
987 struct charset *charset;
988 unsigned from, to;
990 Lisp_Object range;
991 int c, i;
992 struct gcpro gcpro1;
994 range = Fcons (Qnil, Qnil);
995 GCPRO1 (range);
997 for (i = 0, c = 0; i < chartab_size[0]; i++, c += chartab_chars[0])
999 Lisp_Object this;
1001 this = XCHAR_TABLE (table)->contents[i];
1002 if (SUB_CHAR_TABLE_P (this))
1003 map_sub_char_table_for_charset (c_function, function, this, arg,
1004 range, charset, from, to);
1005 else
1007 if (! NILP (XCAR (range)))
1009 XSETCDR (range, make_number (c - 1));
1010 if (c_function)
1011 (*c_function) (arg, range);
1012 else
1013 call2 (function, range, arg);
1015 XSETCAR (range, Qnil);
1018 if (! NILP (XCAR (range)))
1020 XSETCDR (range, make_number (c - 1));
1021 if (c_function)
1022 (*c_function) (arg, range);
1023 else
1024 call2 (function, range, arg);
1027 UNGCPRO;
1031 void
1032 syms_of_chartab ()
1034 defsubr (&Smake_char_table);
1035 defsubr (&Schar_table_parent);
1036 defsubr (&Schar_table_subtype);
1037 defsubr (&Sset_char_table_parent);
1038 defsubr (&Schar_table_extra_slot);
1039 defsubr (&Sset_char_table_extra_slot);
1040 defsubr (&Schar_table_range);
1041 defsubr (&Sset_char_table_range);
1042 defsubr (&Sset_char_table_default);
1043 defsubr (&Soptimize_char_table);
1044 defsubr (&Smap_char_table);
1047 /* arch-tag: 18b5b560-7ab5-4108-b09e-d5dd65dc6fda
1048 (do not change this comment) */