(Fccl_execute_on_string): Add `const' to local variables.
[bpt/emacs.git] / src / chartab.c
CommitLineData
1ee5d538
KH
1/* chartab.c -- char-table support
2 Copyright (C) 2001, 2002
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H13PRO009
5
6This file is part of GNU Emacs.
7
8GNU Emacs is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2, or (at your option)
11any later version.
12
13GNU Emacs is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with GNU Emacs; see the file COPYING. If not, write to
20the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21Boston, MA 02111-1307, USA. */
22
23#include <config.h>
b4a12c67
DL
24#include "lisp.h"
25#include "character.h"
26#include "charset.h"
27#include "ccl.h"
1ee5d538
KH
28
29/* 64/16/32/128 */
30
31/* Number of elements in Nth level char-table. */
32const 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) };
37
38/* Number of characters each element of Nth level char-table
39 covers. */
40const 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 };
45
46/* Number of characters (in bits) each element of Nth level char-table
47 covers. */
48const 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 };
53
54#define CHARTAB_IDX(c, depth, min_char) \
55 (((c) - (min_char)) >> chartab_bits[(depth)])
56
57
58DEFUN ("make-char-table", Fmake_char_table, Smake_char_table, 1, 2, 0,
59 doc: /* Return a newly created char-table.
60Each element is initialized to INIT, which defaults to nil.
61
62Optional second argument PURPOSE, if non-nil, should be a symbol
63which has a `char-table-extra-slots' property.
64The property's value should be an integer between 0 and 10
65that specify how many extra slots the char-table has.
66By default, the char-table has no extra slot. */)
67 (purpose, init)
68 register Lisp_Object purpose, init;
69{
70 Lisp_Object vector;
71 Lisp_Object n;
72 int n_extras = 0;
73 int size;
74
75 CHECK_SYMBOL (purpose);
76 if (! NILP (purpose))
77 {
78 n = Fget (purpose, Qchar_table_extra_slots);
79 if (INTEGERP (n))
80 {
81 if (XINT (n) < 0 || XINT (n) > 10)
82 args_out_of_range (n, Qnil);
83 n_extras = XINT (n);
84 }
85 }
86
87 size = VECSIZE (struct Lisp_Char_Table) - 1 + n_extras;
88 vector = Fmake_vector (make_number (size), init);
89 XCHAR_TABLE (vector)->parent = Qnil;
90 XCHAR_TABLE (vector)->purpose = purpose;
91 XSETCHAR_TABLE (vector, XCHAR_TABLE (vector));
92 return vector;
93}
94
95static Lisp_Object
96make_sub_char_table (depth, min_char, defalt)
97 int depth, min_char;
98 Lisp_Object defalt;
99{
100 Lisp_Object table;
101 int size = VECSIZE (struct Lisp_Sub_Char_Table) - 1 + chartab_size[depth];
1ee5d538
KH
102
103 table = Fmake_vector (make_number (size), defalt);
104 XSUB_CHAR_TABLE (table)->depth = make_number (depth);
105 XSUB_CHAR_TABLE (table)->min_char = make_number (min_char);
106 XSETSUB_CHAR_TABLE (table, XSUB_CHAR_TABLE (table));
107
108 return table;
109}
110
111static Lisp_Object
112char_table_ascii (table)
113 Lisp_Object table;
114{
115 Lisp_Object sub;
116
117 sub = XCHAR_TABLE (table)->contents[0];
118 sub = XSUB_CHAR_TABLE (sub)->contents[0];
119 return XSUB_CHAR_TABLE (sub)->contents[0];
120}
121
122Lisp_Object
123copy_sub_char_table (table)
124 Lisp_Object table;
125{
126 Lisp_Object copy;
127 int depth = XINT (XSUB_CHAR_TABLE (table)->depth);
128 int min_char = XINT (XSUB_CHAR_TABLE (table)->min_char);
129 Lisp_Object val;
130 int i;
131
132 copy = make_sub_char_table (depth, min_char, Qnil);
133 /* Recursively copy any sub char-tables. */
134 for (i = 0; i < chartab_size[depth]; i++)
135 {
136 val = XSUB_CHAR_TABLE (table)->contents[i];
137 if (SUB_CHAR_TABLE_P (val))
138 XSUB_CHAR_TABLE (copy)->contents[i] = copy_sub_char_table (val);
139 else
140 XSUB_CHAR_TABLE (copy)->contents[i] = val;
141 }
142
143 return copy;
144}
145
146
147Lisp_Object
148copy_char_table (table)
149 Lisp_Object table;
150{
151 Lisp_Object copy;
152 int size = XCHAR_TABLE (table)->size & PSEUDOVECTOR_SIZE_MASK;
153 int i;
154
155 copy = Fmake_vector (make_number (size), Qnil);
156 XCHAR_TABLE (copy)->defalt = XCHAR_TABLE (table)->defalt;
157 XCHAR_TABLE (copy)->parent = XCHAR_TABLE (table)->parent;
158 XCHAR_TABLE (copy)->purpose = XCHAR_TABLE (table)->purpose;
159 XCHAR_TABLE (copy)->ascii = XCHAR_TABLE (table)->ascii;
160 for (i = 0; i < chartab_size[0]; i++)
161 XCHAR_TABLE (copy)->contents[i]
162 = (SUB_CHAR_TABLE_P (XCHAR_TABLE (table)->contents[i])
163 ? copy_sub_char_table (XCHAR_TABLE (table)->contents[i])
164 : XCHAR_TABLE (table)->contents[i]);
165 if (SUB_CHAR_TABLE_P (XCHAR_TABLE (copy)->ascii))
166 XCHAR_TABLE (copy)->ascii = char_table_ascii (copy);
167 size -= VECSIZE (struct Lisp_Char_Table) - 1;
168 for (i = 0; i < size; i++)
169 XCHAR_TABLE (copy)->extras[i] = XCHAR_TABLE (table)->extras[i];
170
171 XSETCHAR_TABLE (copy, XCHAR_TABLE (copy));
172 return copy;
173}
174
175Lisp_Object
176sub_char_table_ref (table, c)
177 Lisp_Object table;
178 int c;
179{
180 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
181 int depth = XINT (tbl->depth);
182 int min_char = XINT (tbl->min_char);
183 Lisp_Object val;
184
185 val = tbl->contents[CHARTAB_IDX (c, depth, min_char)];
186 if (SUB_CHAR_TABLE_P (val))
187 val = sub_char_table_ref (val, c);
188 return val;
189}
190
191Lisp_Object
192char_table_ref (table, c)
193 Lisp_Object table;
194 int c;
195{
196 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
197 Lisp_Object val;
198
199 if (ASCII_CHAR_P (c))
200 {
201 val = tbl->ascii;
202 if (SUB_CHAR_TABLE_P (val))
203 val = XSUB_CHAR_TABLE (val)->contents[c];
204 }
205 else
206 {
207 val = tbl->contents[CHARTAB_IDX (c, 0, 0)];
208 if (SUB_CHAR_TABLE_P (val))
209 val = sub_char_table_ref (val, c);
210 }
211 if (NILP (val))
212 {
213 val = tbl->defalt;
214 if (NILP (val) && CHAR_TABLE_P (tbl->parent))
215 val = char_table_ref (tbl->parent, c);
216 }
217 return val;
218}
219
220static Lisp_Object
e15009d9 221sub_char_table_ref_and_range (table, c, from, to, defalt)
1ee5d538
KH
222 Lisp_Object table;
223 int c;
224 int *from, *to;
e15009d9 225 Lisp_Object defalt;
1ee5d538
KH
226{
227 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
228 int depth = XINT (tbl->depth);
229 int min_char = XINT (tbl->min_char);
e15009d9
KH
230 int max_char = min_char + chartab_chars[depth - 1] - 1;
231 int index = CHARTAB_IDX (c, depth, min_char);
1ee5d538
KH
232 Lisp_Object val;
233
e15009d9
KH
234 val = tbl->contents[index];
235 *from = min_char + index * chartab_chars[depth];
236 *to = *from + chartab_chars[depth] - 1;
237 if (SUB_CHAR_TABLE_P (val))
238 val = sub_char_table_ref_and_range (val, c, from, to, defalt);
239 else if (NILP (val))
240 val = defalt;
241
242 while (*from > min_char
243 && *from == min_char + index * chartab_chars[depth])
1ee5d538 244 {
e15009d9
KH
245 Lisp_Object this_val;
246 int this_from = *from - chartab_chars[depth];
247 int this_to = *from - 1;
248
249 index--;
250 this_val = tbl->contents[index];
251 if (SUB_CHAR_TABLE_P (this_val))
252 this_val = sub_char_table_ref_and_range (this_val, this_to,
253 &this_from, &this_to,
254 defalt);
255 else if (NILP (this_val))
256 this_val = defalt;
257
258 if (! EQ (this_val, val))
259 break;
260 *from = this_from;
1ee5d538 261 }
e15009d9
KH
262 index = CHARTAB_IDX (c, depth, min_char);
263 while (*to < max_char
264 && *to == min_char + (index + 1) * chartab_chars[depth] - 1)
1ee5d538 265 {
e15009d9
KH
266 Lisp_Object this_val;
267 int this_from = *to + 1;
268 int this_to = this_from + chartab_chars[depth] - 1;
269
270 index++;
271 this_val = tbl->contents[index];
272 if (SUB_CHAR_TABLE_P (this_val))
273 this_val = sub_char_table_ref_and_range (this_val, this_from,
274 &this_from, &this_to,
275 defalt);
276 else if (NILP (this_val))
277 this_val = defalt;
278 if (! EQ (this_val, val))
279 break;
280 *to = this_to;
1ee5d538 281 }
e15009d9 282
1ee5d538
KH
283 return val;
284}
285
286
e15009d9
KH
287/* Return the value for C in char-table TABLE. Set *FROM and *TO to
288 the range of characters (containing C) that have the same value as
289 C. It is not assured that the value of (*FROM - 1) and (*TO + 1)
290 is different from that of C. */
291
1ee5d538
KH
292Lisp_Object
293char_table_ref_and_range (table, c, from, to)
294 Lisp_Object table;
295 int c;
296 int *from, *to;
297{
298 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
e15009d9 299 int index = CHARTAB_IDX (c, 0, 0);
1ee5d538
KH
300 Lisp_Object val;
301
e15009d9
KH
302 val = tbl->contents[index];
303 *from = index * chartab_chars[0];
304 *to = *from + chartab_chars[0] - 1;
305 if (SUB_CHAR_TABLE_P (val))
306 val = sub_char_table_ref_and_range (val, c, from, to, tbl->defalt);
307 else if (NILP (val))
308 val = tbl->defalt;
309
310 while (*from > 0 && *from == index * chartab_chars[0])
1ee5d538 311 {
e15009d9
KH
312 Lisp_Object this_val;
313 int this_from = *from - chartab_chars[0];
314 int this_to = *from - 1;
315
316 index--;
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, this_to,
320 &this_from, &this_to,
321 tbl->defalt);
322 else if (NILP (this_val))
323 this_val = tbl->defalt;
324
325 if (! EQ (this_val, val))
326 break;
327 *from = this_from;
1ee5d538 328 }
e15009d9 329 while (*to < MAX_CHAR && *to == (index + 1) * chartab_chars[0] - 1)
1ee5d538 330 {
e15009d9
KH
331 Lisp_Object this_val;
332 int this_from = *to + 1;
333 int this_to = this_from + chartab_chars[0] - 1;
334
335 index++;
336 this_val = tbl->contents[index];
337 if (SUB_CHAR_TABLE_P (this_val))
338 this_val = sub_char_table_ref_and_range (this_val, this_from,
339 &this_from, &this_to,
340 tbl->defalt);
341 else if (NILP (this_val))
342 this_val = tbl->defalt;
343 if (! EQ (this_val, val))
344 break;
345 *to = this_to;
1ee5d538
KH
346 }
347
1ee5d538 348 return val;
e15009d9 349}
1ee5d538
KH
350
351
352#define ASET_RANGE(ARRAY, FROM, TO, LIMIT, VAL) \
353 do { \
354 int limit = (TO) < (LIMIT) ? (TO) : (LIMIT); \
355 for (; (FROM) < limit; (FROM)++) (ARRAY)->contents[(FROM)] = (VAL); \
356 } while (0)
357
358#define GET_SUB_CHAR_TABLE(TABLE, SUBTABLE, IDX, DEPTH, MIN_CHAR) \
359 do { \
360 (SUBTABLE) = (TABLE)->contents[(IDX)]; \
361 if (!SUB_CHAR_TABLE_P (SUBTABLE)) \
362 (SUBTABLE) = make_sub_char_table ((DEPTH), (MIN_CHAR), (SUBTABLE)); \
363 } while (0)
364
365
366static void
367sub_char_table_set (table, c, val)
368 Lisp_Object table;
369 int c;
370 Lisp_Object val;
371{
372 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
373 int depth = XINT ((tbl)->depth);
374 int min_char = XINT ((tbl)->min_char);
375 int i = CHARTAB_IDX (c, depth, min_char);
376 Lisp_Object sub;
377
378 if (depth == 3)
379 tbl->contents[i] = val;
380 else
381 {
382 sub = tbl->contents[i];
383 if (! SUB_CHAR_TABLE_P (sub))
384 {
385 sub = make_sub_char_table (depth + 1,
386 min_char + i * chartab_chars[depth], sub);
387 tbl->contents[i] = sub;
388 }
389 sub_char_table_set (sub, c, val);
390 }
391}
392
393Lisp_Object
394char_table_set (table, c, val)
395 Lisp_Object table;
396 int c;
397 Lisp_Object val;
398{
399 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
400
401 if (ASCII_CHAR_P (c)
402 && SUB_CHAR_TABLE_P (tbl->ascii))
403 {
404 XSUB_CHAR_TABLE (tbl->ascii)->contents[c] = val;
405 }
406 else
407 {
408 int i = CHARTAB_IDX (c, 0, 0);
409 Lisp_Object sub;
410
411 sub = tbl->contents[i];
412 if (! SUB_CHAR_TABLE_P (sub))
413 {
414 sub = make_sub_char_table (1, i * chartab_chars[0], sub);
415 tbl->contents[i] = sub;
416 }
417 sub_char_table_set (sub, c, val);
418 if (ASCII_CHAR_P (c))
419 tbl->ascii = char_table_ascii (tbl);
420 }
421 return val;
422}
423
424static void
425sub_char_table_set_range (table, depth, min_char, from, to, val)
426 Lisp_Object *table;
427 int depth;
428 int min_char;
429 int from, to;
430 Lisp_Object val;
431{
432 int max_char = min_char + chartab_chars[depth] - 1;
433
22d49f94 434 if (depth == 3 || from <= min_char && to >= max_char)
1ee5d538
KH
435 *table = val;
436 else
437 {
438 int i, j;
439
440 depth++;
441 if (! SUB_CHAR_TABLE_P (*table))
442 *table = make_sub_char_table (depth, min_char, *table);
443 if (from < min_char)
444 from = min_char;
445 if (to > max_char)
446 to = max_char;
22d49f94 447 i = CHARTAB_IDX (from, depth, min_char);
1ee5d538 448 j = CHARTAB_IDX (to, depth, min_char);
22d49f94
KH
449 min_char += chartab_chars[depth] * i;
450 for (; i <= j; i++, min_char += chartab_chars[depth])
1ee5d538 451 sub_char_table_set_range (XSUB_CHAR_TABLE (*table)->contents + i,
22d49f94 452 depth, min_char, from, to, val);
1ee5d538
KH
453 }
454}
455
456
457Lisp_Object
458char_table_set_range (table, from, to, val)
459 Lisp_Object table;
460 int from, to;
461 Lisp_Object val;
462{
463 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
464 Lisp_Object *contents = tbl->contents;
465 int i, min_char;
466
467 if (from == to)
468 char_table_set (table, from, val);
469 else
470 {
471 for (i = CHARTAB_IDX (from, 0, 0), min_char = i * chartab_chars[0];
472 min_char <= to;
473 i++, min_char += chartab_chars[0])
474 sub_char_table_set_range (contents + i, 0, min_char, from, to, val);
475 if (ASCII_CHAR_P (from))
476 tbl->ascii = char_table_ascii (tbl);
477 }
478 return val;
479}
480
481\f
482DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype,
483 1, 1, 0,
484 doc: /*
485Return the subtype of char-table CHAR-TABLE. The value is a symbol. */)
486 (char_table)
487 Lisp_Object char_table;
488{
489 CHECK_CHAR_TABLE (char_table);
490
491 return XCHAR_TABLE (char_table)->purpose;
492}
493
494DEFUN ("char-table-parent", Fchar_table_parent, Schar_table_parent,
495 1, 1, 0,
496 doc: /* Return the parent char-table of CHAR-TABLE.
497The value is either nil or another char-table.
498If CHAR-TABLE holds nil for a given character,
499then the actual applicable value is inherited from the parent char-table
500\(or from its parents, if necessary). */)
501 (char_table)
502 Lisp_Object char_table;
503{
504 CHECK_CHAR_TABLE (char_table);
505
506 return XCHAR_TABLE (char_table)->parent;
507}
508
509DEFUN ("set-char-table-parent", Fset_char_table_parent, Sset_char_table_parent,
510 2, 2, 0,
511 doc: /* Set the parent char-table of CHAR-TABLE to PARENT.
512PARENT must be either nil or another char-table. */)
513 (char_table, parent)
514 Lisp_Object char_table, parent;
515{
516 Lisp_Object temp;
517
518 CHECK_CHAR_TABLE (char_table);
519
520 if (!NILP (parent))
521 {
522 CHECK_CHAR_TABLE (parent);
523
524 for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent)
525 if (EQ (temp, char_table))
526 error ("Attempt to make a chartable be its own parent");
527 }
528
529 XCHAR_TABLE (char_table)->parent = parent;
530
531 return parent;
532}
533
534DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
535 2, 2, 0,
536 doc: /* Return the value of CHAR-TABLE's extra-slot number N. */)
537 (char_table, n)
538 Lisp_Object char_table, n;
539{
540 CHECK_CHAR_TABLE (char_table);
541 CHECK_NUMBER (n);
542 if (XINT (n) < 0
543 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
544 args_out_of_range (char_table, n);
545
546 return XCHAR_TABLE (char_table)->extras[XINT (n)];
547}
548
549DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
550 Sset_char_table_extra_slot,
551 3, 3, 0,
552 doc: /* Set CHAR-TABLE's extra-slot number N to VALUE. */)
553 (char_table, n, value)
554 Lisp_Object char_table, n, value;
555{
556 CHECK_CHAR_TABLE (char_table);
557 CHECK_NUMBER (n);
558 if (XINT (n) < 0
559 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
560 args_out_of_range (char_table, n);
561
562 return XCHAR_TABLE (char_table)->extras[XINT (n)] = value;
563}
564\f
565DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
566 2, 2, 0,
567 doc: /* Return the value in CHAR-TABLE for a range of characters RANGE.
568RANGE should be nil (for the default value),
569a cons of character codes (for characters in the range), or a character code. */)
570 (char_table, range)
571 Lisp_Object char_table, range;
572{
573 Lisp_Object val;
574 CHECK_CHAR_TABLE (char_table);
575
576 if (EQ (range, Qnil))
577 val = XCHAR_TABLE (char_table)->defalt;
578 else if (INTEGERP (range))
579 val = CHAR_TABLE_REF (char_table, XINT (range));
580 else if (CONSP (range))
581 {
582 int from, to;
583
584 CHECK_CHARACTER (XCAR (range));
585 CHECK_CHARACTER (XCDR (range));
586 val = char_table_ref_and_range (char_table, XINT (XCAR (range)),
587 &from, &to);
588 /* Not yet implemented. */
589 }
590 else
591 error ("Invalid RANGE argument to `char-table-range'");
592 return val;
593}
594
595DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
596 3, 3, 0,
597 doc: /*
598Set the value in CHAR-TABLE for characters specified by RANGE to VALUE.
599RANGE should be t (for all characters), nil (for the default value),
600a cons of character codes (for characters in the range), or a character code. */)
601 (char_table, range, value)
602 Lisp_Object char_table, range, value;
603{
604 CHECK_CHAR_TABLE (char_table);
605 if (EQ (range, Qt))
606 {
607 int i;
608
609 XCHAR_TABLE (char_table)->ascii = Qnil;
610 for (i = 0; i < chartab_size[0]; i++)
611 XCHAR_TABLE (char_table)->contents[i] = Qnil;
612 XCHAR_TABLE (char_table)->defalt = value;
613 }
614 else if (EQ (range, Qnil))
615 XCHAR_TABLE (char_table)->defalt = value;
616 else if (INTEGERP (range))
617 char_table_set (char_table, XINT (range), value);
618 else if (CONSP (range))
619 {
620 CHECK_CHARACTER (XCAR (range));
621 CHECK_CHARACTER (XCDR (range));
622 char_table_set_range (char_table,
623 XINT (XCAR (range)), XINT (XCDR (range)), value);
624 }
625 else
626 error ("Invalid RANGE argument to `set-char-table-range'");
627
628 return value;
629}
630
631DEFUN ("set-char-table-default", Fset_char_table_default,
632 Sset_char_table_default, 3, 3, 0,
633 doc: /*
f6e5cae0 634This function is obsolete and has no effect. */)
1ee5d538
KH
635 (char_table, ch, value)
636 Lisp_Object char_table, ch, value;
637{
638 return Qnil;
639}
640
641/* Look up the element in TABLE at index CH, and return it as an
642 integer. If the element is nil, return CH itself. (Actually we do
643 that for any non-integer.) */
644
645int
646char_table_translate (table, ch)
647 Lisp_Object table;
648 int ch;
649{
650 Lisp_Object value;
651 value = Faref (table, make_number (ch));
f6e5cae0 652 if (! INTEGERP (value)) /* fixme: use CHARACTERP? */
1ee5d538
KH
653 return ch;
654 return XINT (value);
655}
656
657static Lisp_Object
658optimize_sub_char_table (table)
659 Lisp_Object table;
660{
661 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
662 int depth = XINT (tbl->depth);
663 Lisp_Object elt, this;
664 int i;
665
666 elt = XSUB_CHAR_TABLE (table)->contents[0];
667 if (SUB_CHAR_TABLE_P (elt))
668 elt = XSUB_CHAR_TABLE (table)->contents[0] = optimize_sub_char_table (elt);
669 if (SUB_CHAR_TABLE_P (elt))
670 return table;
671 for (i = 1; i < chartab_size[depth]; i++)
672 {
673 this = XSUB_CHAR_TABLE (table)->contents[i];
674 if (SUB_CHAR_TABLE_P (this))
675 this = XSUB_CHAR_TABLE (table)->contents[i]
676 = optimize_sub_char_table (this);
677 if (SUB_CHAR_TABLE_P (this)
678 || NILP (Fequal (this, elt)))
679 break;
680 }
681
682 return (i < chartab_size[depth] ? table : elt);
683}
684
685DEFUN ("optimize-char-table", Foptimize_char_table, Soptimize_char_table,
686 1, 1, 0,
687 doc: /* Optimize CHAR-TABLE. */)
688 (char_table)
689 Lisp_Object char_table;
690{
691 Lisp_Object elt;
692 int i;
693
694 CHECK_CHAR_TABLE (char_table);
695
696 for (i = 0; i < chartab_size[0]; i++)
697 {
698 elt = XCHAR_TABLE (char_table)->contents[i];
699 if (SUB_CHAR_TABLE_P (elt))
700 XCHAR_TABLE (char_table)->contents[i] = optimize_sub_char_table (elt);
701 }
702 return Qnil;
703}
704
705\f
706static Lisp_Object
707map_sub_char_table (c_function, function, table, arg, val, range)
708 void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
709 Lisp_Object function, table, arg, val, range;
710{
711 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
712 int depth = XINT (tbl->depth);
713 int i, c;
714
715 for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth];
716 i++, c += chartab_chars[depth])
717 {
718 Lisp_Object this;
719
720 this = tbl->contents[i];
721 if (SUB_CHAR_TABLE_P (this))
722 val = map_sub_char_table (c_function, function, this, arg, val, range);
723 else if (NILP (Fequal (val, this)))
724 {
725 if (! NILP (val))
726 {
727 XCDR (range) = make_number (c - 1);
728 if (depth == 3
729 && EQ (XCAR (range), XCDR (range)))
730 {
731 if (c_function)
732 (*c_function) (arg, XCAR (range), val);
733 else
734 call2 (function, XCAR (range), val);
735 }
736 else
737 {
738 if (c_function)
739 (*c_function) (arg, range, val);
740 else
741 call2 (function, range, val);
742 }
743 }
744 val = this;
745 XCAR (range) = make_number (c);
746 }
747 }
748 return val;
749}
750
751
752/* Map C_FUNCTION or FUNCTION over TABLE, calling it for each
753 character or group of characters that share a value.
754
755 ARG is passed to C_FUNCTION when that is called.
756
757 DEPTH and INDICES are ignored. They are removed in the new
758 feature. */
759
760void
761map_char_table (c_function, function, table, arg, depth, indices)
762 void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
763 Lisp_Object function, table, arg, *indices;
764 int depth;
765{
766 Lisp_Object range, val;
767 int c, i;
768
769 range = Fcons (make_number (0), Qnil);
770 val = char_table_ref (table, 0);
771
772 for (i = 0, c = 0; i < chartab_size[0]; i++, c += chartab_chars[0])
773 {
774 Lisp_Object this;
775
776 this = XCHAR_TABLE (table)->contents[i];
777 if (SUB_CHAR_TABLE_P (this))
778 val = map_sub_char_table (c_function, function, this, arg, val, range);
779 else if (NILP (Fequal (val, this)))
780 {
781 if (! NILP (val))
782 {
783 XCDR (range) = make_number (c - 1);
784 if (c_function)
785 (*c_function) (arg, range, val);
786 else
787 call2 (function, range, val);
788 }
789 val = this;
790 XCAR (range) = make_number (c);
791 }
792 }
793}
794
795DEFUN ("map-char-table", Fmap_char_table, Smap_char_table,
796 2, 2, 0,
797 doc: /*
f6e5cae0 798Call FUNCTION for each character in CHAR-TABLE.
1ee5d538
KH
799FUNCTION is called with two arguments--a key and a value.
800The key is always a possible IDX argument to `aref'. */)
801 (function, char_table)
802 Lisp_Object function, char_table;
803{
804 CHECK_CHAR_TABLE (char_table);
805
806 map_char_table (NULL, function, char_table, char_table, 0, NULL);
807 return Qnil;
808}
809
e15009d9
KH
810
811static void
812map_sub_char_table_for_charset (c_function, function, table, arg, range,
813 charset, from, to)
814 void (*c_function) P_ ((Lisp_Object, Lisp_Object));
815 Lisp_Object function, table, arg, range;
816 struct charset *charset;
817 unsigned from, to;
818{
819 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
820 int depth = XINT (tbl->depth);
821 int c, i;
822
823 if (depth < 3)
824 for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth];
825 i++, c += chartab_chars[depth])
826 {
827 Lisp_Object this;
828
829 this = tbl->contents[i];
830 if (SUB_CHAR_TABLE_P (this))
831 map_sub_char_table_for_charset (c_function, function, this, arg,
832 range, charset, from, to);
833 else
834 {
835 if (! NILP (XCAR (range)))
836 {
837 XSETCDR (range, make_number (c - 1));
838 if (c_function)
839 (*c_function) (arg, range);
840 else
841 call2 (function, range, arg);
842 }
843 XSETCAR (range, Qnil);
844 }
845 }
846 else
847 for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth]; i++, c ++)
848 {
849 Lisp_Object this;
850 unsigned code;
851
852 this = tbl->contents[i];
853 if (NILP (this)
854 || (charset
855 && (code = ENCODE_CHAR (charset, c),
856 (code < from || code > to))))
857 {
858 if (! NILP (XCAR (range)))
859 {
860 XSETCDR (range, make_number (c - 1));
861 if (c_function)
862 (*c_function) (range, arg);
863 else
864 call2 (function, range, arg);
865 XSETCAR (range, Qnil);
866 }
867 }
868 else
869 {
870 if (NILP (XCAR (range)))
871 XSETCAR (range, make_number (c));
872 }
873 }
874}
875
876
877void
878map_char_table_for_charset (c_function, function, table, arg,
879 charset, from, to)
880 void (*c_function) P_ ((Lisp_Object, Lisp_Object));
881 Lisp_Object function, table, arg;
882 struct charset *charset;
883 unsigned from, to;
884{
885 Lisp_Object range;
886 int c, i;
887
888 if (NILP (char_table_ref (table, 0)))
889 range = Fcons (Qnil, Qnil);
890 else
891 range = Fcons (make_number (0), make_number (0));
892
893 for (i = 0, c = 0; i < chartab_size[0]; i++, c += chartab_chars[0])
894 {
895 Lisp_Object this;
896
897 this = XCHAR_TABLE (table)->contents[i];
898 if (SUB_CHAR_TABLE_P (this))
899 map_sub_char_table_for_charset (c_function, function, this, arg,
900 range, charset, from, to);
901 else
902 {
903 if (! NILP (XCAR (range)))
904 {
905 XSETCDR (range, make_number (c - 1));
906 if (c_function)
907 (*c_function) (arg, range);
908 else
909 call2 (function, range, arg);
910 }
911 XSETCAR (range, Qnil);
912 }
913 }
914 if (! NILP (XCAR (range)))
915 {
916 XSETCDR (range, make_number (c - 1));
917 if (c_function)
918 (*c_function) (arg, range);
919 else
920 call2 (function, range, arg);
921 }
922}
923
924
1ee5d538
KH
925\f
926#if 0
927Lisp_Object
928make_class_table (purpose)
929 Lisp_Object purpose;
930{
931 Lisp_Object table;
932 Lisp_Object args[4];
933
934 args[0] = purpose;
935 args[1] = Qnil;
936 args[2] = QCextra_slots;
937 args[3] = Fmake_vector (make_number (2), Qnil);
938 ASET (args[3], 0, Fmakehash (Qequal));
939 table = Fmake_char_table (4, args);
940 return table;
941}
942
943Lisp_Object
944modify_class_entry (c, val, table, set)
945 int c;
946 Lisp_Object val, table, set;
947{
948 Lisp_Object classes, hash, canon;
949 int i, ival;
950
951 hash = XCHAR_TABLE (table)->extras[0];
952 classes = CHAR_TABLE_REF (table, c);
953
954 if (! BOOL_VECTOR_P (classes))
955 classes = (NILP (set)
956 ? Qnil
957 : Fmake_bool_vector (make_number ((ival / 8) * 8 + 8), Qnil));
958 else if (ival < XBOOL_VECTOR (classes)->size)
959 {
960 Lisp_Object old;
961 old = classes;
962 classes = Fmake_bool_vector (make_number ((ival / 8) * 8 + 8), Qnil);
963 for (i = 0; i < XBOOL_VECTOR (classes)->size; i++)
964 Faset (classes, make_number (i), Faref (old, make_number (i)));
965 Faset (classes, val, set);
966 }
967 else if (NILP (Faref (classes, val)) != NILP (set))
968 {
969 classes = Fcopy_sequence (classes);
970 Faset (classes, val, set);
971 }
972 else
973 classes = Qnil;
974
975 if (!NILP (classes))
976 {
977 canon = Fgethash (classes, hash, Qnil);
978 if (NILP (canon))
979 {
980 canon = classes;
981 Fputhash (canon, canon, hash);
982 }
983 char_table_set (table, c, canon);
984 }
985
986 return val;
987}
988#endif
989
990\f
991void
992syms_of_chartab ()
993{
994 defsubr (&Smake_char_table);
995 defsubr (&Schar_table_parent);
996 defsubr (&Schar_table_subtype);
997 defsubr (&Sset_char_table_parent);
998 defsubr (&Schar_table_extra_slot);
999 defsubr (&Sset_char_table_extra_slot);
1000 defsubr (&Schar_table_range);
1001 defsubr (&Sset_char_table_range);
1002 defsubr (&Sset_char_table_default);
1003 defsubr (&Soptimize_char_table);
1004 defsubr (&Smap_char_table);
1005}