]> code.delx.au - gnu-emacs/blob - src/chartab.c
84b06e1a6fd9b14d7e94d38f762b3bc44c7d8fca
[gnu-emacs] / src / chartab.c
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
5
6 This file is part of GNU Emacs.
7
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.
12
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.
17
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/>. */
20
21 #include <config.h>
22 #include <setjmp.h>
23 #include "lisp.h"
24 #include "character.h"
25 #include "charset.h"
26 #include "ccl.h"
27
28 /* 64/16/32/128 */
29
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) };
36
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 };
44
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 };
52
53 #define CHARTAB_IDX(c, depth, min_char) \
54 (((c) - (min_char)) >> chartab_bits[(depth)])
55
56
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.
60
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)
66 {
67 Lisp_Object vector;
68 Lisp_Object n;
69 int n_extras;
70 int size;
71
72 CHECK_SYMBOL (purpose);
73 n = Fget (purpose, Qchar_table_extra_slots);
74 if (NILP (n))
75 n_extras = 0;
76 else
77 {
78 CHECK_NATNUM (n);
79 n_extras = XINT (n);
80 if (n_extras > 10)
81 args_out_of_range (n, Qnil);
82 }
83
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;
91 }
92
93 static Lisp_Object
94 make_sub_char_table (int depth, int min_char, Lisp_Object defalt)
95 {
96 Lisp_Object table;
97 int size = VECSIZE (struct Lisp_Sub_Char_Table) - 1 + chartab_size[depth];
98
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);
103
104 return table;
105 }
106
107 static Lisp_Object
108 char_table_ascii (Lisp_Object table)
109 {
110 Lisp_Object sub;
111
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];
119 }
120
121 Lisp_Object
122 copy_sub_char_table (Lisp_Object table)
123 {
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;
129
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++)
133 {
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;
139 }
140
141 return copy;
142 }
143
144
145 Lisp_Object
146 copy_char_table (Lisp_Object table)
147 {
148 Lisp_Object copy;
149 int size = XCHAR_TABLE (table)->size & PSEUDOVECTOR_SIZE_MASK;
150 int i;
151
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];
166
167 XSETCHAR_TABLE (copy, XCHAR_TABLE (copy));
168 return copy;
169 }
170
171 static Lisp_Object
172 sub_char_table_ref (Lisp_Object table, int c)
173 {
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;
178
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;
183 }
184
185 Lisp_Object
186 char_table_ref (Lisp_Object table, int c)
187 {
188 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
189 Lisp_Object val;
190
191 if (ASCII_CHAR_P (c))
192 {
193 val = tbl->ascii;
194 if (SUB_CHAR_TABLE_P (val))
195 val = XSUB_CHAR_TABLE (val)->contents[c];
196 }
197 else
198 {
199 val = tbl->contents[CHARTAB_IDX (c, 0, 0)];
200 if (SUB_CHAR_TABLE_P (val))
201 val = sub_char_table_ref (val, c);
202 }
203 if (NILP (val))
204 {
205 val = tbl->defalt;
206 if (NILP (val) && CHAR_TABLE_P (tbl->parent))
207 val = char_table_ref (tbl->parent, c);
208 }
209 return val;
210 }
211
212 static Lisp_Object
213 sub_char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to, Lisp_Object defalt)
214 {
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 max_char = min_char + chartab_chars[depth - 1] - 1;
219 int index = CHARTAB_IDX (c, depth, min_char), idx;
220 Lisp_Object val;
221
222 val = tbl->contents[index];
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;
227
228 idx = index;
229 while (idx > 0 && *from < min_char + idx * chartab_chars[depth])
230 {
231 Lisp_Object this_val;
232
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;
240
241 if (! EQ (this_val, val))
242 {
243 *from = c + 1;
244 break;
245 }
246 }
247 while ((c = min_char + (index + 1) * chartab_chars[depth]) <= max_char
248 && *to >= c)
249 {
250 Lisp_Object this_val;
251
252 index++;
253 this_val = tbl->contents[index];
254 if (SUB_CHAR_TABLE_P (this_val))
255 this_val = sub_char_table_ref_and_range (this_val, c, from, to, defalt);
256 else if (NILP (this_val))
257 this_val = defalt;
258 if (! EQ (this_val, val))
259 {
260 *to = c - 1;
261 break;
262 }
263 }
264
265 return val;
266 }
267
268
269 /* Return the value for C in char-table TABLE. Shrink the range *FROM
270 and *TO to cover characters (containing C) that have the same value
271 as C. It is not assured that the values of (*FROM - 1) and (*TO +
272 1) are different from that of C. */
273
274 Lisp_Object
275 char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to)
276 {
277 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
278 int index = CHARTAB_IDX (c, 0, 0), idx;
279 Lisp_Object val;
280
281 val = tbl->contents[index];
282 if (*from < 0)
283 *from = 0;
284 if (*to < 0)
285 *to = MAX_CHAR;
286 if (SUB_CHAR_TABLE_P (val))
287 val = sub_char_table_ref_and_range (val, c, from, to, tbl->defalt);
288 else if (NILP (val))
289 val = tbl->defalt;
290
291 idx = index;
292 while (*from < idx * chartab_chars[0])
293 {
294 Lisp_Object this_val;
295
296 c = idx * chartab_chars[0] - 1;
297 idx--;
298 this_val = tbl->contents[idx];
299 if (SUB_CHAR_TABLE_P (this_val))
300 this_val = sub_char_table_ref_and_range (this_val, c, from, to,
301 tbl->defalt);
302 else if (NILP (this_val))
303 this_val = tbl->defalt;
304
305 if (! EQ (this_val, val))
306 {
307 *from = c + 1;
308 break;
309 }
310 }
311 while (*to >= (index + 1) * chartab_chars[0])
312 {
313 Lisp_Object this_val;
314
315 index++;
316 c = index * chartab_chars[0];
317 this_val = tbl->contents[index];
318 if (SUB_CHAR_TABLE_P (this_val))
319 this_val = sub_char_table_ref_and_range (this_val, c, from, to,
320 tbl->defalt);
321 else if (NILP (this_val))
322 this_val = tbl->defalt;
323 if (! EQ (this_val, val))
324 {
325 *to = c - 1;
326 break;
327 }
328 }
329
330 return val;
331 }
332
333
334 #define ASET_RANGE(ARRAY, FROM, TO, LIMIT, VAL) \
335 do { \
336 int limit = (TO) < (LIMIT) ? (TO) : (LIMIT); \
337 for (; (FROM) < limit; (FROM)++) (ARRAY)->contents[(FROM)] = (VAL); \
338 } while (0)
339
340 #define GET_SUB_CHAR_TABLE(TABLE, SUBTABLE, IDX, DEPTH, MIN_CHAR) \
341 do { \
342 (SUBTABLE) = (TABLE)->contents[(IDX)]; \
343 if (!SUB_CHAR_TABLE_P (SUBTABLE)) \
344 (SUBTABLE) = make_sub_char_table ((DEPTH), (MIN_CHAR), (SUBTABLE)); \
345 } while (0)
346
347
348 static void
349 sub_char_table_set (Lisp_Object table, int c, Lisp_Object val)
350 {
351 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
352 int depth = XINT ((tbl)->depth);
353 int min_char = XINT ((tbl)->min_char);
354 int i = CHARTAB_IDX (c, depth, min_char);
355 Lisp_Object sub;
356
357 if (depth == 3)
358 tbl->contents[i] = val;
359 else
360 {
361 sub = tbl->contents[i];
362 if (! SUB_CHAR_TABLE_P (sub))
363 {
364 sub = make_sub_char_table (depth + 1,
365 min_char + i * chartab_chars[depth], sub);
366 tbl->contents[i] = sub;
367 }
368 sub_char_table_set (sub, c, val);
369 }
370 }
371
372 Lisp_Object
373 char_table_set (Lisp_Object table, int c, Lisp_Object val)
374 {
375 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
376
377 if (ASCII_CHAR_P (c)
378 && SUB_CHAR_TABLE_P (tbl->ascii))
379 {
380 XSUB_CHAR_TABLE (tbl->ascii)->contents[c] = val;
381 }
382 else
383 {
384 int i = CHARTAB_IDX (c, 0, 0);
385 Lisp_Object sub;
386
387 sub = tbl->contents[i];
388 if (! SUB_CHAR_TABLE_P (sub))
389 {
390 sub = make_sub_char_table (1, i * chartab_chars[0], sub);
391 tbl->contents[i] = sub;
392 }
393 sub_char_table_set (sub, c, val);
394 if (ASCII_CHAR_P (c))
395 tbl->ascii = char_table_ascii (table);
396 }
397 return val;
398 }
399
400 static void
401 sub_char_table_set_range (Lisp_Object *table, int depth, int min_char, int from, int to, Lisp_Object val)
402 {
403 int max_char = min_char + chartab_chars[depth] - 1;
404
405 if (depth == 3 || (from <= min_char && to >= max_char))
406 *table = val;
407 else
408 {
409 int i, j;
410
411 depth++;
412 if (! SUB_CHAR_TABLE_P (*table))
413 *table = make_sub_char_table (depth, min_char, *table);
414 if (from < min_char)
415 from = min_char;
416 if (to > max_char)
417 to = max_char;
418 i = CHARTAB_IDX (from, depth, min_char);
419 j = CHARTAB_IDX (to, depth, min_char);
420 min_char += chartab_chars[depth] * i;
421 for (; i <= j; i++, min_char += chartab_chars[depth])
422 sub_char_table_set_range (XSUB_CHAR_TABLE (*table)->contents + i,
423 depth, min_char, from, to, val);
424 }
425 }
426
427
428 Lisp_Object
429 char_table_set_range (Lisp_Object table, int from, int to, Lisp_Object val)
430 {
431 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
432 Lisp_Object *contents = tbl->contents;
433 int i, min_char;
434
435 if (from == to)
436 char_table_set (table, from, val);
437 else
438 {
439 for (i = CHARTAB_IDX (from, 0, 0), min_char = i * chartab_chars[0];
440 min_char <= to;
441 i++, min_char += chartab_chars[0])
442 sub_char_table_set_range (contents + i, 0, min_char, from, to, val);
443 if (ASCII_CHAR_P (from))
444 tbl->ascii = char_table_ascii (table);
445 }
446 return val;
447 }
448
449 \f
450 DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype,
451 1, 1, 0,
452 doc: /*
453 Return the subtype of char-table CHAR-TABLE. The value is a symbol. */)
454 (Lisp_Object char_table)
455 {
456 CHECK_CHAR_TABLE (char_table);
457
458 return XCHAR_TABLE (char_table)->purpose;
459 }
460
461 DEFUN ("char-table-parent", Fchar_table_parent, Schar_table_parent,
462 1, 1, 0,
463 doc: /* Return the parent char-table of CHAR-TABLE.
464 The value is either nil or another char-table.
465 If CHAR-TABLE holds nil for a given character,
466 then the actual applicable value is inherited from the parent char-table
467 \(or from its parents, if necessary). */)
468 (Lisp_Object char_table)
469 {
470 CHECK_CHAR_TABLE (char_table);
471
472 return XCHAR_TABLE (char_table)->parent;
473 }
474
475 DEFUN ("set-char-table-parent", Fset_char_table_parent, Sset_char_table_parent,
476 2, 2, 0,
477 doc: /* Set the parent char-table of CHAR-TABLE to PARENT.
478 Return PARENT. PARENT must be either nil or another char-table. */)
479 (Lisp_Object char_table, Lisp_Object parent)
480 {
481 Lisp_Object temp;
482
483 CHECK_CHAR_TABLE (char_table);
484
485 if (!NILP (parent))
486 {
487 CHECK_CHAR_TABLE (parent);
488
489 for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent)
490 if (EQ (temp, char_table))
491 error ("Attempt to make a chartable be its own parent");
492 }
493
494 XCHAR_TABLE (char_table)->parent = parent;
495
496 return parent;
497 }
498
499 DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
500 2, 2, 0,
501 doc: /* Return the value of CHAR-TABLE's extra-slot number N. */)
502 (Lisp_Object char_table, Lisp_Object n)
503 {
504 CHECK_CHAR_TABLE (char_table);
505 CHECK_NUMBER (n);
506 if (XINT (n) < 0
507 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
508 args_out_of_range (char_table, n);
509
510 return XCHAR_TABLE (char_table)->extras[XINT (n)];
511 }
512
513 DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
514 Sset_char_table_extra_slot,
515 3, 3, 0,
516 doc: /* Set CHAR-TABLE's extra-slot number N to VALUE. */)
517 (Lisp_Object char_table, Lisp_Object n, Lisp_Object value)
518 {
519 CHECK_CHAR_TABLE (char_table);
520 CHECK_NUMBER (n);
521 if (XINT (n) < 0
522 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
523 args_out_of_range (char_table, n);
524
525 return XCHAR_TABLE (char_table)->extras[XINT (n)] = value;
526 }
527 \f
528 DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
529 2, 2, 0,
530 doc: /* Return the value in CHAR-TABLE for a range of characters RANGE.
531 RANGE should be nil (for the default value),
532 a cons of character codes (for characters in the range), or a character code. */)
533 (Lisp_Object char_table, Lisp_Object range)
534 {
535 Lisp_Object val;
536 CHECK_CHAR_TABLE (char_table);
537
538 if (EQ (range, Qnil))
539 val = XCHAR_TABLE (char_table)->defalt;
540 else if (INTEGERP (range))
541 val = CHAR_TABLE_REF (char_table, XINT (range));
542 else if (CONSP (range))
543 {
544 int from, to;
545
546 CHECK_CHARACTER_CAR (range);
547 CHECK_CHARACTER_CDR (range);
548 val = char_table_ref_and_range (char_table, XINT (XCAR (range)),
549 &from, &to);
550 /* Not yet implemented. */
551 }
552 else
553 error ("Invalid RANGE argument to `char-table-range'");
554 return val;
555 }
556
557 DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
558 3, 3, 0,
559 doc: /* Set the value in CHAR-TABLE for a range of characters RANGE to VALUE.
560 RANGE should be t (for all characters), nil (for the default value),
561 a cons of character codes (for characters in the range),
562 or a character code. Return VALUE. */)
563 (Lisp_Object char_table, Lisp_Object range, Lisp_Object value)
564 {
565 CHECK_CHAR_TABLE (char_table);
566 if (EQ (range, Qt))
567 {
568 int i;
569
570 XCHAR_TABLE (char_table)->ascii = value;
571 for (i = 0; i < chartab_size[0]; i++)
572 XCHAR_TABLE (char_table)->contents[i] = value;
573 }
574 else if (EQ (range, Qnil))
575 XCHAR_TABLE (char_table)->defalt = value;
576 else if (INTEGERP (range))
577 char_table_set (char_table, XINT (range), value);
578 else if (CONSP (range))
579 {
580 CHECK_CHARACTER_CAR (range);
581 CHECK_CHARACTER_CDR (range);
582 char_table_set_range (char_table,
583 XINT (XCAR (range)), XINT (XCDR (range)), value);
584 }
585 else
586 error ("Invalid RANGE argument to `set-char-table-range'");
587
588 return value;
589 }
590
591 DEFUN ("set-char-table-default", Fset_char_table_default,
592 Sset_char_table_default, 3, 3, 0,
593 doc: /*
594 This function is obsolete and has no effect. */)
595 (Lisp_Object char_table, Lisp_Object ch, Lisp_Object value)
596 {
597 return Qnil;
598 }
599
600 /* Look up the element in TABLE at index CH, and return it as an
601 integer. If the element is not a character, return CH itself. */
602
603 int
604 char_table_translate (Lisp_Object table, int ch)
605 {
606 Lisp_Object value;
607 value = Faref (table, make_number (ch));
608 if (! CHARACTERP (value))
609 return ch;
610 return XINT (value);
611 }
612
613 static Lisp_Object
614 optimize_sub_char_table (Lisp_Object table, Lisp_Object test)
615 {
616 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
617 int depth = XINT (tbl->depth);
618 Lisp_Object elt, this;
619 int i, optimizable;
620
621 elt = XSUB_CHAR_TABLE (table)->contents[0];
622 if (SUB_CHAR_TABLE_P (elt))
623 elt = XSUB_CHAR_TABLE (table)->contents[0]
624 = optimize_sub_char_table (elt, test);
625 optimizable = SUB_CHAR_TABLE_P (elt) ? 0 : 1;
626 for (i = 1; i < chartab_size[depth]; i++)
627 {
628 this = XSUB_CHAR_TABLE (table)->contents[i];
629 if (SUB_CHAR_TABLE_P (this))
630 this = XSUB_CHAR_TABLE (table)->contents[i]
631 = optimize_sub_char_table (this, test);
632 if (optimizable
633 && (NILP (test) ? NILP (Fequal (this, elt)) /* defaults to `equal'. */
634 : EQ (test, Qeq) ? !EQ (this, elt) /* Optimize `eq' case. */
635 : NILP (call2 (test, this, elt))))
636 optimizable = 0;
637 }
638
639 return (optimizable ? elt : table);
640 }
641
642 DEFUN ("optimize-char-table", Foptimize_char_table, Soptimize_char_table,
643 1, 2, 0,
644 doc: /* Optimize CHAR-TABLE.
645 TEST is the comparison function used to decide whether two entries are
646 equivalent and can be merged. It defaults to `equal'. */)
647 (Lisp_Object char_table, Lisp_Object test)
648 {
649 Lisp_Object elt;
650 int i;
651
652 CHECK_CHAR_TABLE (char_table);
653
654 for (i = 0; i < chartab_size[0]; i++)
655 {
656 elt = XCHAR_TABLE (char_table)->contents[i];
657 if (SUB_CHAR_TABLE_P (elt))
658 XCHAR_TABLE (char_table)->contents[i]
659 = optimize_sub_char_table (elt, test);
660 }
661 /* Reset the `ascii' cache, in case it got optimized away. */
662 XCHAR_TABLE (char_table)->ascii = char_table_ascii (char_table);
663
664 return Qnil;
665 }
666
667 \f
668 /* Map C_FUNCTION or FUNCTION over TABLE (top or sub char-table),
669 calling it for each character or group of characters that share a
670 value. RANGE is a cons (FROM . TO) specifying the range of target
671 characters, VAL is a value of FROM in TABLE, DEFAULT_VAL is the
672 default value of the char-table, PARENT is the parent of the
673 char-table.
674
675 ARG is passed to C_FUNCTION when that is called.
676
677 It returns the value of last character covered by TABLE (not the
678 value inheritted from the parent), and by side-effect, the car part
679 of RANGE is updated to the minimum character C where C and all the
680 following characters in TABLE have the same value. */
681
682 static Lisp_Object
683 map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object),
684 Lisp_Object function, Lisp_Object table, Lisp_Object arg, Lisp_Object val,
685 Lisp_Object range, Lisp_Object default_val, Lisp_Object parent)
686 {
687 /* Pointer to the elements of TABLE. */
688 Lisp_Object *contents;
689 /* Depth of TABLE. */
690 int depth;
691 /* Minimum and maxinum characters covered by TABLE. */
692 int min_char, max_char;
693 /* Number of characters covered by one element of TABLE. */
694 int chars_in_block;
695 int from = XINT (XCAR (range)), to = XINT (XCDR (range));
696 int i, c;
697
698 if (SUB_CHAR_TABLE_P (table))
699 {
700 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
701
702 depth = XINT (tbl->depth);
703 contents = tbl->contents;
704 min_char = XINT (tbl->min_char);
705 max_char = min_char + chartab_chars[depth - 1] - 1;
706 }
707 else
708 {
709 depth = 0;
710 contents = XCHAR_TABLE (table)->contents;
711 min_char = 0;
712 max_char = MAX_CHAR;
713 }
714 chars_in_block = chartab_chars[depth];
715
716 if (to < max_char)
717 max_char = to;
718 /* Set I to the index of the first element to check. */
719 if (from <= min_char)
720 i = 0;
721 else
722 i = (from - min_char) / chars_in_block;
723 for (c = min_char + chars_in_block * i; c <= max_char;
724 i++, c += chars_in_block)
725 {
726 Lisp_Object this = contents[i];
727 int nextc = c + chars_in_block;
728
729 if (SUB_CHAR_TABLE_P (this))
730 {
731 if (to >= nextc)
732 XSETCDR (range, make_number (nextc - 1));
733 val = map_sub_char_table (c_function, function, this, arg,
734 val, range, default_val, parent);
735 }
736 else
737 {
738 if (NILP (this))
739 this = default_val;
740 if (!EQ (val, this))
741 {
742 int different_value = 1;
743
744 if (NILP (val))
745 {
746 if (! NILP (parent))
747 {
748 Lisp_Object temp = XCHAR_TABLE (parent)->parent;
749
750 /* This is to get a value of FROM in PARENT
751 without checking the parent of PARENT. */
752 XCHAR_TABLE (parent)->parent = Qnil;
753 val = CHAR_TABLE_REF (parent, from);
754 XCHAR_TABLE (parent)->parent = temp;
755 XSETCDR (range, make_number (c - 1));
756 val = map_sub_char_table (c_function, function,
757 parent, arg, val, range,
758 XCHAR_TABLE (parent)->defalt,
759 XCHAR_TABLE (parent)->parent);
760 if (EQ (val, this))
761 different_value = 0;
762 }
763 }
764 if (! NILP (val) && different_value)
765 {
766 XSETCDR (range, make_number (c - 1));
767 if (EQ (XCAR (range), XCDR (range)))
768 {
769 if (c_function)
770 (*c_function) (arg, XCAR (range), val);
771 else
772 call2 (function, XCAR (range), val);
773 }
774 else
775 {
776 if (c_function)
777 (*c_function) (arg, range, val);
778 else
779 call2 (function, range, val);
780 }
781 }
782 val = this;
783 from = c;
784 XSETCAR (range, make_number (c));
785 }
786 }
787 XSETCDR (range, make_number (to));
788 }
789 return val;
790 }
791
792
793 /* Map C_FUNCTION or FUNCTION over TABLE, calling it for each
794 character or group of characters that share a value.
795
796 ARG is passed to C_FUNCTION when that is called. */
797
798 void
799 map_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), Lisp_Object function, Lisp_Object table, Lisp_Object arg)
800 {
801 Lisp_Object range, val;
802 struct gcpro gcpro1, gcpro2, gcpro3;
803
804 range = Fcons (make_number (0), make_number (MAX_CHAR));
805 GCPRO3 (table, arg, range);
806 val = XCHAR_TABLE (table)->ascii;
807 if (SUB_CHAR_TABLE_P (val))
808 val = XSUB_CHAR_TABLE (val)->contents[0];
809 val = map_sub_char_table (c_function, function, table, arg, val, range,
810 XCHAR_TABLE (table)->defalt,
811 XCHAR_TABLE (table)->parent);
812 /* If VAL is nil and TABLE has a parent, we must consult the parent
813 recursively. */
814 while (NILP (val) && ! NILP (XCHAR_TABLE (table)->parent))
815 {
816 Lisp_Object parent = XCHAR_TABLE (table)->parent;
817 Lisp_Object temp = XCHAR_TABLE (parent)->parent;
818 int from = XINT (XCAR (range));
819
820 /* This is to get a value of FROM in PARENT without checking the
821 parent of PARENT. */
822 XCHAR_TABLE (parent)->parent = Qnil;
823 val = CHAR_TABLE_REF (parent, from);
824 XCHAR_TABLE (parent)->parent = temp;
825 val = map_sub_char_table (c_function, function, parent, arg, val, range,
826 XCHAR_TABLE (parent)->defalt,
827 XCHAR_TABLE (parent)->parent);
828 table = parent;
829 }
830
831 if (! NILP (val))
832 {
833 if (EQ (XCAR (range), XCDR (range)))
834 {
835 if (c_function)
836 (*c_function) (arg, XCAR (range), val);
837 else
838 call2 (function, XCAR (range), val);
839 }
840 else
841 {
842 if (c_function)
843 (*c_function) (arg, range, val);
844 else
845 call2 (function, range, val);
846 }
847 }
848
849 UNGCPRO;
850 }
851
852 DEFUN ("map-char-table", Fmap_char_table, Smap_char_table,
853 2, 2, 0,
854 doc: /*
855 Call FUNCTION for each character in CHAR-TABLE that has non-nil value.
856 FUNCTION is called with two arguments--a key and a value.
857 The key is a character code or a cons of character codes specifying a
858 range of characters that have the same value. */)
859 (Lisp_Object function, Lisp_Object char_table)
860 {
861 CHECK_CHAR_TABLE (char_table);
862
863 map_char_table (NULL, function, char_table, char_table);
864 return Qnil;
865 }
866
867
868 static void
869 map_sub_char_table_for_charset (void (*c_function) (Lisp_Object, Lisp_Object),
870 Lisp_Object function, Lisp_Object table, Lisp_Object arg,
871 Lisp_Object range, struct charset *charset,
872 unsigned from, unsigned to)
873 {
874 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
875 int depth = XINT (tbl->depth);
876 int c, i;
877
878 if (depth < 3)
879 for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth];
880 i++, c += chartab_chars[depth])
881 {
882 Lisp_Object this;
883
884 this = tbl->contents[i];
885 if (SUB_CHAR_TABLE_P (this))
886 map_sub_char_table_for_charset (c_function, function, this, arg,
887 range, charset, from, to);
888 else
889 {
890 if (! NILP (XCAR (range)))
891 {
892 XSETCDR (range, make_number (c - 1));
893 if (c_function)
894 (*c_function) (arg, range);
895 else
896 call2 (function, range, arg);
897 }
898 XSETCAR (range, Qnil);
899 }
900 }
901 else
902 for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth]; i++, c ++)
903 {
904 Lisp_Object this;
905 unsigned code;
906
907 this = tbl->contents[i];
908 if (NILP (this)
909 || (charset
910 && (code = ENCODE_CHAR (charset, c),
911 (code < from || code > to))))
912 {
913 if (! NILP (XCAR (range)))
914 {
915 XSETCDR (range, make_number (c - 1));
916 if (c_function)
917 (*c_function) (arg, range);
918 else
919 call2 (function, range, arg);
920 XSETCAR (range, Qnil);
921 }
922 }
923 else
924 {
925 if (NILP (XCAR (range)))
926 XSETCAR (range, make_number (c));
927 }
928 }
929 }
930
931
932 /* Support function for `map-charset-chars'. Map C_FUNCTION or
933 FUNCTION over TABLE, calling it for each character or a group of
934 succeeding characters that have non-nil value in TABLE. TABLE is a
935 "mapping table" or a "deunifier table" of a certain charset.
936
937 If CHARSET is not NULL (this is the case that `map-charset-chars'
938 is called with non-nil FROM-CODE and TO-CODE), it is a charset who
939 owns TABLE, and the function is called only on a character in the
940 range FROM and TO. FROM and TO are not character codes, but code
941 points of a character in CHARSET.
942
943 This function is called in these two cases:
944
945 (1) A charset has a mapping file name in :map property.
946
947 (2) A charset has an upper code space in :offset property and a
948 mapping file name in :unify-map property. In this case, this
949 function is called only for characters in the Unicode code space.
950 Characters in upper code space are handled directly in
951 map_charset_chars. */
952
953 void
954 map_char_table_for_charset (void (*c_function) (Lisp_Object, Lisp_Object),
955 Lisp_Object function, Lisp_Object table, Lisp_Object arg,
956 struct charset *charset,
957 unsigned from, unsigned to)
958 {
959 Lisp_Object range;
960 int c, i;
961 struct gcpro gcpro1;
962
963 range = Fcons (Qnil, Qnil);
964 GCPRO1 (range);
965
966 for (i = 0, c = 0; i < chartab_size[0]; i++, c += chartab_chars[0])
967 {
968 Lisp_Object this;
969
970 this = XCHAR_TABLE (table)->contents[i];
971 if (SUB_CHAR_TABLE_P (this))
972 map_sub_char_table_for_charset (c_function, function, this, arg,
973 range, charset, from, to);
974 else
975 {
976 if (! NILP (XCAR (range)))
977 {
978 XSETCDR (range, make_number (c - 1));
979 if (c_function)
980 (*c_function) (arg, range);
981 else
982 call2 (function, range, arg);
983 }
984 XSETCAR (range, Qnil);
985 }
986 }
987 if (! NILP (XCAR (range)))
988 {
989 XSETCDR (range, make_number (c - 1));
990 if (c_function)
991 (*c_function) (arg, range);
992 else
993 call2 (function, range, arg);
994 }
995
996 UNGCPRO;
997 }
998
999 \f
1000 void
1001 syms_of_chartab (void)
1002 {
1003 defsubr (&Smake_char_table);
1004 defsubr (&Schar_table_parent);
1005 defsubr (&Schar_table_subtype);
1006 defsubr (&Sset_char_table_parent);
1007 defsubr (&Schar_table_extra_slot);
1008 defsubr (&Sset_char_table_extra_slot);
1009 defsubr (&Schar_table_range);
1010 defsubr (&Sset_char_table_range);
1011 defsubr (&Sset_char_table_default);
1012 defsubr (&Soptimize_char_table);
1013 defsubr (&Smap_char_table);
1014 }
1015
1016 /* arch-tag: 18b5b560-7ab5-4108-b09e-d5dd65dc6fda
1017 (do not change this comment) */