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