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