comparison src/chartab.c @ 70:131b0175ea99 r20-0b30

Import from CVS: tag r20-0b30
author cvs
date Mon, 13 Aug 2007 09:02:59 +0200
parents
children cf808b4c4290
comparison
equal deleted inserted replaced
69:804d1389bcd6 70:131b0175ea99
1 /* XEmacs routines to deal with char tables.
2 Copyright (C) 1992, 1995 Free Software Foundation, Inc.
3 Copyright (C) 1995 Sun Microsystems, Inc.
4 Copyright (C) 1995, 1996 Ben Wing.
5
6 This file is part of XEmacs.
7
8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
11 later version.
12
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with XEmacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
22
23 /* Synched up with: Mule 2.3. Not synched with FSF.
24
25 This file was written independently of the FSF implementation,
26 and is not compatible. */
27
28 /* Authorship:
29
30 Ben Wing: wrote, for 19.13 (Mule). Some category table stuff
31 loosely based on the original Mule.
32 */
33
34 #include <config.h>
35 #include "lisp.h"
36
37 #include "buffer.h"
38 #include "chartab.h"
39 #include "commands.h"
40 #include "syntax.h"
41
42 Lisp_Object Qchar_tablep, Qchar_table;
43
44 Lisp_Object Vall_syntax_tables;
45
46 #ifdef MULE
47 Lisp_Object Qcategory_table_p;
48 Lisp_Object Qcategory_designator_p;
49 Lisp_Object Qcategory_table_value_p;
50
51 Lisp_Object Vstandard_category_table;
52 #endif
53
54
55 /* A char table maps from ranges of characters to values.
56
57 Implementing a general data structure that maps from arbitrary
58 ranges of numbers to values is tricky to do efficiently. As it
59 happens, it should suffice fine (and is usually more convenient,
60 anyway) when dealing with characters to restrict the sorts of
61 ranges that can be assigned values, as follows:
62
63 1) All characters.
64 2) All characters in a charset.
65 3) All characters in a particular row of a charset, where a "row"
66 means all characters with the same first byte.
67 4) A particular character in a charset.
68
69
70 We use char tables to generalize the 256-element vectors now
71 littering the Emacs code.
72
73 Possible uses (all should be converted at some point):
74
75 1) category tables
76 2) syntax tables
77 3) display tables
78 4) case tables
79 5) keyboard-translate-table?
80
81 We do the very non-Stallman-esque thing of actually providing an
82 abstract type to generalize the Emacs vectors and Mule
83 vectors-of-vectors goo.
84 */
85
86 /************************************************************************/
87 /* Char Table object */
88 /************************************************************************/
89
90 #ifdef MULE
91
92 static Lisp_Object mark_char_table_entry (Lisp_Object, void (*) (Lisp_Object));
93 static int char_table_entry_equal (Lisp_Object, Lisp_Object, int depth);
94 static unsigned long char_table_entry_hash (Lisp_Object obj, int depth);
95 DEFINE_LRECORD_IMPLEMENTATION ("char-table-entry", char_table_entry,
96 mark_char_table_entry, internal_object_printer,
97 0, char_table_entry_equal,
98 char_table_entry_hash,
99 struct Lisp_Char_Table_Entry);
100
101 static Lisp_Object
102 mark_char_table_entry (Lisp_Object obj, void (*markobj) (Lisp_Object))
103 {
104 struct Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (obj);
105 int i;
106
107 for (i = 0; i < 96; i++)
108 {
109 (markobj) (cte->level2[i]);
110 }
111 return Qnil;
112 }
113
114 static int
115 char_table_entry_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
116 {
117 struct Lisp_Char_Table_Entry *cte1 = XCHAR_TABLE_ENTRY (obj1);
118 struct Lisp_Char_Table_Entry *cte2 = XCHAR_TABLE_ENTRY (obj2);
119 int i;
120
121 for (i = 0; i < 96; i++)
122 if (!internal_equal (cte1->level2[i], cte2->level2[i], depth + 1))
123 return 0;
124
125 return 1;
126 }
127
128 static unsigned long
129 char_table_entry_hash (Lisp_Object obj, int depth)
130 {
131 struct Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (obj);
132
133 return internal_array_hash (cte->level2, 96, depth);
134 }
135
136 #endif /* MULE */
137
138 static Lisp_Object mark_char_table (Lisp_Object, void (*) (Lisp_Object));
139 static void print_char_table (Lisp_Object, Lisp_Object, int);
140 static int char_table_equal (Lisp_Object, Lisp_Object, int depth);
141 static unsigned long char_table_hash (Lisp_Object obj, int depth);
142 DEFINE_LRECORD_IMPLEMENTATION ("char-table", char_table,
143 mark_char_table, print_char_table, 0,
144 char_table_equal, char_table_hash,
145 struct Lisp_Char_Table);
146
147 static Lisp_Object
148 mark_char_table (Lisp_Object obj, void (*markobj) (Lisp_Object))
149 {
150 struct Lisp_Char_Table *ct = XCHAR_TABLE (obj);
151 int i;
152
153 for (i = 0; i < NUM_ASCII_CHARS; i++)
154 (markobj) (ct->ascii[i]);
155 #ifdef MULE
156 for (i = 0; i < NUM_LEADING_BYTES; i++)
157 (markobj) (ct->level1[i]);
158 #endif
159 return ct->mirror_table;
160 }
161
162 /* WARNING: All functions of this nature need to be written extremely
163 carefully to avoid crashes during GC. Cf. prune_specifiers()
164 and prune_weak_hashtables(). */
165
166 void
167 prune_syntax_tables (int (*obj_marked_p) (Lisp_Object))
168 {
169 Lisp_Object rest, prev = Qnil;
170
171 for (rest = Vall_syntax_tables;
172 !GC_NILP (rest);
173 rest = XCHAR_TABLE (rest)->next_table)
174 {
175 if (! ((*obj_marked_p) (rest)))
176 {
177 /* This table is garbage. Remove it from the list. */
178 if (GC_NILP (prev))
179 Vall_syntax_tables = XCHAR_TABLE (rest)->next_table;
180 else
181 XCHAR_TABLE (prev)->next_table =
182 XCHAR_TABLE (rest)->next_table;
183 }
184 }
185 }
186
187 static Lisp_Object
188 char_table_type_to_symbol (enum char_table_type type)
189 {
190 switch (type)
191 {
192 case CHAR_TABLE_TYPE_GENERIC: return Qgeneric;
193 case CHAR_TABLE_TYPE_SYNTAX: return Qsyntax;
194 case CHAR_TABLE_TYPE_DISPLAY: return Qdisplay;
195 case CHAR_TABLE_TYPE_CHAR: return Qchar;
196 #ifdef MULE
197 case CHAR_TABLE_TYPE_CATEGORY: return Qcategory;
198 #endif
199 }
200
201 abort ();
202 return Qnil; /* not reached */
203 }
204
205 static enum char_table_type
206 symbol_to_char_table_type (Lisp_Object symbol)
207 {
208 CHECK_SYMBOL (symbol);
209
210 if (EQ (symbol, Qgeneric)) return CHAR_TABLE_TYPE_GENERIC;
211 if (EQ (symbol, Qsyntax)) return CHAR_TABLE_TYPE_SYNTAX;
212 if (EQ (symbol, Qdisplay)) return CHAR_TABLE_TYPE_DISPLAY;
213 if (EQ (symbol, Qchar)) return CHAR_TABLE_TYPE_CHAR;
214 #ifdef MULE
215 if (EQ (symbol, Qcategory)) return CHAR_TABLE_TYPE_CATEGORY;
216 #endif
217
218 signal_simple_error ("Unrecognized char table type", symbol);
219 return CHAR_TABLE_TYPE_GENERIC; /* not reached */
220 }
221
222 static void
223 print_chartab_range (Emchar first, Emchar last, Lisp_Object val,
224 Lisp_Object printcharfun)
225 {
226 if (first != last)
227 {
228 write_c_string (" (", printcharfun);
229 print_internal (make_char (first), printcharfun, 0);
230 write_c_string (" ", printcharfun);
231 print_internal (make_char (last), printcharfun, 0);
232 write_c_string (") ", printcharfun);
233 }
234 else
235 {
236 write_c_string (" ", printcharfun);
237 print_internal (make_char (first), printcharfun, 0);
238 write_c_string (" ", printcharfun);
239 }
240 print_internal (val, printcharfun, 1);
241 }
242
243 #ifdef MULE
244
245 static void
246 print_chartab_charset_row (Lisp_Object charset,
247 int row,
248 struct Lisp_Char_Table_Entry *cte,
249 Lisp_Object printcharfun)
250 {
251 int i;
252 Lisp_Object cat = Qunbound;
253 int first = -1;
254
255 for (i = 32; i < 128; i++)
256 {
257 Lisp_Object pam = cte->level2[i - 32];
258
259 if (first == -1)
260 {
261 first = i;
262 cat = pam;
263 continue;
264 }
265
266 if (!EQ (cat, pam))
267 {
268 if (row == -1)
269 print_chartab_range (MAKE_CHAR (charset, first, 0),
270 MAKE_CHAR (charset, i - 1, 0),
271 cat, printcharfun);
272 else
273 print_chartab_range (MAKE_CHAR (charset, row, first),
274 MAKE_CHAR (charset, row, i - 1),
275 cat, printcharfun);
276 first = -1;
277 i--;
278 }
279 }
280
281 if (first != -1)
282 {
283 if (row == -1)
284 print_chartab_range (MAKE_CHAR (charset, first, 0),
285 MAKE_CHAR (charset, i - 1, 0),
286 cat, printcharfun);
287 else
288 print_chartab_range (MAKE_CHAR (charset, row, first),
289 MAKE_CHAR (charset, row, i - 1),
290 cat, printcharfun);
291 }
292 }
293
294 static void
295 print_chartab_two_byte_charset (Lisp_Object charset,
296 struct Lisp_Char_Table_Entry *cte,
297 Lisp_Object printcharfun)
298 {
299 int i;
300
301 for (i = 32; i < 128; i++)
302 {
303 Lisp_Object jen = cte->level2[i - 32];
304
305 if (!CHAR_TABLE_ENTRYP (jen))
306 {
307 char buf[100];
308
309 write_c_string (" [", printcharfun);
310 print_internal (XCHARSET_NAME (charset), printcharfun, 0);
311 sprintf (buf, " %d] ", i);
312 write_c_string (buf, printcharfun);
313 print_internal (jen, printcharfun, 0);
314 }
315 else
316 print_chartab_charset_row (charset, i, XCHAR_TABLE_ENTRY (jen),
317 printcharfun);
318 }
319 }
320
321 #endif /* MULE */
322
323 static void
324 print_char_table (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
325 {
326 struct Lisp_Char_Table *ct = XCHAR_TABLE (obj);
327 char buf[200];
328
329 sprintf (buf, "#s(char-table type %s data (",
330 string_data (symbol_name (XSYMBOL
331 (char_table_type_to_symbol (ct->type)))));
332 write_c_string (buf, printcharfun);
333
334 /* Now write out the ASCII/Control-1 stuff. */
335 {
336 int i;
337 int first = -1;
338 Lisp_Object val = Qunbound;
339
340 for (i = 0; i < NUM_ASCII_CHARS; i++)
341 {
342 if (first == -1)
343 {
344 first = i;
345 val = ct->ascii[i];
346 continue;
347 }
348
349 if (!EQ (ct->ascii[i], val))
350 {
351 print_chartab_range (first, i - 1, val, printcharfun);
352 first = -1;
353 i--;
354 }
355 }
356
357 if (first != -1)
358 print_chartab_range (first, i - 1, val, printcharfun);
359 }
360
361 #ifdef MULE
362 {
363 int i;
364
365 for (i = MIN_LEADING_BYTE; i < MIN_LEADING_BYTE + NUM_LEADING_BYTES;
366 i++)
367 {
368 Lisp_Object ann = ct->level1[i - MIN_LEADING_BYTE];
369 Lisp_Object charset = CHARSET_BY_LEADING_BYTE (i);
370
371 if (!CHARSETP (charset) || i == LEADING_BYTE_ASCII
372 || i == LEADING_BYTE_CONTROL_1)
373 continue;
374 if (!CHAR_TABLE_ENTRYP (ann))
375 {
376 write_c_string (" ", printcharfun);
377 print_internal (XCHARSET_NAME (charset),
378 printcharfun, 0);
379 write_c_string (" ", printcharfun);
380 print_internal (ann, printcharfun, 0);
381 }
382 else
383 {
384 struct Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (ann);
385 if (XCHARSET_DIMENSION (charset) == 1)
386 print_chartab_charset_row (charset, -1, cte, printcharfun);
387 else
388 print_chartab_two_byte_charset (charset, cte, printcharfun);
389 }
390 }
391 }
392 #endif /* MULE */
393
394 write_c_string ("))", printcharfun);
395 }
396
397 static int
398 char_table_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
399 {
400 struct Lisp_Char_Table *ct1 = XCHAR_TABLE (obj1);
401 struct Lisp_Char_Table *ct2 = XCHAR_TABLE (obj2);
402 int i;
403
404 if (CHAR_TABLE_TYPE (ct1) != CHAR_TABLE_TYPE (ct2))
405 return 0;
406
407 for (i = 0; i < NUM_ASCII_CHARS; i++)
408 if (!internal_equal (ct1->ascii[i], ct2->ascii[i], depth + 1))
409 return 0;
410
411 #ifdef MULE
412 for (i = 0; i < NUM_LEADING_BYTES; i++)
413 if (!internal_equal (ct1->level1[i], ct2->level1[i], depth + 1))
414 return 0;
415 #endif /* MULE */
416
417 return 1;
418 }
419
420 static unsigned long
421 char_table_hash (Lisp_Object obj, int depth)
422 {
423 struct Lisp_Char_Table *ct = XCHAR_TABLE (obj);
424 unsigned long hashval = internal_array_hash (ct->ascii, NUM_ASCII_CHARS,
425 depth);
426 #ifdef MULE
427 hashval = HASH2 (hashval,
428 internal_array_hash (ct->level1, NUM_LEADING_BYTES, depth));
429 #endif /* MULE */
430 return hashval;
431 }
432
433 DEFUN ("char-table-p", Fchar_table_p, 1, 1, 0, /*
434 Return non-nil if OBJECT is a char table.
435
436 A char table is a table that maps characters (or ranges of characters)
437 to values. Char tables are specialized for characters, only allowing
438 particular sorts of ranges to be assigned values. Although this
439 loses in generality, it makes for extremely fast (constant-time)
440 lookups, and thus is feasible for applications that do an extremely
441 large number of lookups (e.g. scanning a buffer for a character in
442 a particular syntax, where a lookup in the syntax table must occur
443 once per character).
444
445 When Mule support exists, the types of ranges that can be assigned
446 values are
447
448 -- all characters
449 -- an entire charset
450 -- a single row in a two-octet charset
451 -- a single character
452
453 When Mule support is not present, the types of ranges that can be
454 assigned values are
455
456 -- all characters
457 -- a single character
458
459 To create a char table, use `make-char-table'. To modify a char
460 table, use `put-char-table' or `remove-char-table'. To retrieve the
461 value for a particular character, use `get-char-table'. See also
462 `map-char-table', `clear-char-table', `copy-char-table',
463 `valid-char-table-type-p', `char-table-type-list', `valid-char-table-value-p',
464 and `check-char-table-value'.
465 */
466 (object))
467 {
468 return (CHAR_TABLEP (object) ? Qt : Qnil);
469 }
470
471 DEFUN ("char-table-type-list", Fchar_table_type_list, 0, 0, 0, /*
472 Return a list of the recognized char table types.
473 See `valid-char-table-type-p'.
474 */
475 ())
476 {
477 #ifdef MULE
478 return list5 (Qchar, Qcategory, Qdisplay, Qgeneric, Qsyntax);
479 #else
480 return list4 (Qchar, Qdisplay, Qgeneric, Qsyntax);
481 #endif
482 }
483
484 DEFUN ("valid-char-table-type-p", Fvalid_char_table_type_p, 1, 1, 0, /*
485 Return t if TYPE if a recognized char table type.
486
487 Each char table type is used for a different purpose and allows different
488 sorts of values. The different char table types are
489
490 `category'
491 Used for category tables, which specify the regexp categories
492 that a character is in. The valid values are nil or a
493 bit vector of 95 elements. Higher-level Lisp functions are
494 provided for working with category tables. Currently categories
495 and category tables only exist when Mule support is present.
496 `char'
497 A generalized char table, for mapping from one character to
498 another. Used for case tables, syntax matching tables,
499 `keyboard-translate-table', etc. The valid values are characters.
500 `generic'
501 An even more generalized char table, for mapping from a
502 character to anything.
503 `display'
504 Used for display tables, which specify how a particular character
505 is to appear when displayed. #### Not yet implemented.
506 `syntax'
507 Used for syntax tables, which specify the syntax of a particular
508 character. Higher-level Lisp functions are provided for
509 working with syntax tables. The valid values are integers.
510
511 */
512 (type))
513 {
514 if (EQ (type, Qchar)
515 #ifdef MULE
516 || EQ (type, Qcategory)
517 #endif
518 || EQ (type, Qdisplay)
519 || EQ (type, Qgeneric)
520 || EQ (type, Qsyntax))
521 return Qt;
522
523 return Qnil;
524 }
525
526 DEFUN ("char-table-type", Fchar_table_type, 1, 1, 0, /*
527 Return the type of char table TABLE.
528 See `valid-char-table-type-p'.
529 */
530 (table))
531 {
532 CHECK_CHAR_TABLE (table);
533 return char_table_type_to_symbol (XCHAR_TABLE (table)->type);
534 }
535
536 void
537 fill_char_table (struct Lisp_Char_Table *ct, Lisp_Object value)
538 {
539 int i;
540
541 for (i = 0; i < NUM_ASCII_CHARS; i++)
542 ct->ascii[i] = value;
543 #ifdef MULE
544 for (i = 0; i < NUM_LEADING_BYTES; i++)
545 ct->level1[i] = value;
546 #endif /* MULE */
547
548 if (ct->type == CHAR_TABLE_TYPE_SYNTAX)
549 update_syntax_table (ct);
550 }
551
552 DEFUN ("reset-char-table", Freset_char_table, 1, 1, 0, /*
553 Reset a char table to its default state.
554 */
555 (table))
556 {
557 struct Lisp_Char_Table *ct;
558
559 CHECK_CHAR_TABLE (table);
560 ct = XCHAR_TABLE (table);
561
562 switch (ct->type)
563 {
564 case CHAR_TABLE_TYPE_CHAR:
565 case CHAR_TABLE_TYPE_DISPLAY:
566 case CHAR_TABLE_TYPE_GENERIC:
567 #ifdef MULE
568 case CHAR_TABLE_TYPE_CATEGORY:
569 fill_char_table (ct, Qnil);
570 break;
571 #endif
572
573 case CHAR_TABLE_TYPE_SYNTAX:
574 fill_char_table (ct, make_int (Sinherit));
575 break;
576
577 default:
578 abort ();
579 }
580
581 return Qnil;
582 }
583
584 DEFUN ("make-char-table", Fmake_char_table, 1, 1, 0, /*
585 Make a new, empty char table of type TYPE.
586 Currently recognized types are 'char, 'category, 'display, 'generic,
587 and 'syntax. See `valid-char-table-type-p'.
588 */
589 (type))
590 {
591 struct Lisp_Char_Table *ct;
592 Lisp_Object obj = Qnil;
593 enum char_table_type ty = symbol_to_char_table_type (type);
594
595 ct = (struct Lisp_Char_Table *)
596 alloc_lcrecord (sizeof (struct Lisp_Char_Table), lrecord_char_table);
597 ct->type = ty;
598 if (ty == CHAR_TABLE_TYPE_SYNTAX)
599 {
600 ct->mirror_table = Fmake_char_table (Qgeneric);
601 }
602 else
603 ct->mirror_table = Qnil;
604 ct->next_table = Qnil;
605 XSETCHAR_TABLE (obj, ct);
606 if (ty == CHAR_TABLE_TYPE_SYNTAX)
607 {
608 ct->next_table = Vall_syntax_tables;
609 Vall_syntax_tables = obj;
610 }
611 Freset_char_table (obj);
612 return obj;
613 }
614
615 #ifdef MULE
616
617 static Lisp_Object
618 make_char_table_entry (Lisp_Object initval)
619 {
620 struct Lisp_Char_Table_Entry *cte;
621 Lisp_Object obj = Qnil;
622 int i;
623
624 cte = (struct Lisp_Char_Table_Entry *)
625 alloc_lcrecord (sizeof (struct Lisp_Char_Table_Entry),
626 lrecord_char_table_entry);
627 for (i = 0; i < 96; i++)
628 cte->level2[i] = initval;
629 XSETCHAR_TABLE_ENTRY (obj, cte);
630 return obj;
631 }
632
633 static Lisp_Object
634 copy_char_table_entry (Lisp_Object entry)
635 {
636 struct Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (entry);
637 struct Lisp_Char_Table_Entry *ctenew;
638 Lisp_Object obj = Qnil;
639 int i;
640
641 ctenew = (struct Lisp_Char_Table_Entry *)
642 alloc_lcrecord (sizeof (struct Lisp_Char_Table_Entry),
643 lrecord_char_table_entry);
644 for (i = 0; i < 96; i++)
645 {
646 Lisp_Object new = cte->level2[i];
647 if (CHAR_TABLE_ENTRYP (new))
648 ctenew->level2[i] = copy_char_table_entry (new);
649 else
650 ctenew->level2[i] = new;
651 }
652
653 XSETCHAR_TABLE_ENTRY (obj, cte);
654 return obj;
655 }
656
657 #endif /* MULE */
658
659 DEFUN ("copy-char-table", Fcopy_char_table, 1, 1, 0, /*
660 Make a new char table which is a copy of OLD-TABLE.
661 It will contain the same values for the same characters and ranges
662 as OLD-TABLE. The values will not themselves be copied.
663 */
664 (old_table))
665 {
666 struct Lisp_Char_Table *ct, *ctnew;
667 Lisp_Object obj = Qnil;
668 int i;
669
670 CHECK_CHAR_TABLE (old_table);
671 ct = XCHAR_TABLE (old_table);
672 ctnew = (struct Lisp_Char_Table *)
673 alloc_lcrecord (sizeof (struct Lisp_Char_Table), lrecord_char_table);
674 ctnew->type = ct->type;
675
676 for (i = 0; i < NUM_ASCII_CHARS; i++)
677 {
678 Lisp_Object new = ct->ascii[i];
679 #ifdef MULE
680 assert (! (CHAR_TABLE_ENTRYP (new)));
681 #endif /* MULE */
682 ctnew->ascii[i] = new;
683 }
684
685 #ifdef MULE
686
687 for (i = 0; i < NUM_LEADING_BYTES; i++)
688 {
689 Lisp_Object new = ct->level1[i];
690 if (CHAR_TABLE_ENTRYP (new))
691 ctnew->level1[i] = copy_char_table_entry (new);
692 else
693 ctnew->level1[i] = new;
694 }
695
696 #endif /* MULE */
697
698 if (CHAR_TABLEP (ct->mirror_table))
699 ctnew->mirror_table = Fcopy_char_table (ct->mirror_table);
700 else
701 ctnew->mirror_table = ct->mirror_table;
702 XSETCHAR_TABLE (obj, ctnew);
703 return obj;
704 }
705
706 static void
707 decode_char_table_range (Lisp_Object range, struct chartab_range *outrange)
708 {
709 if (EQ (range, Qt))
710 outrange->type = CHARTAB_RANGE_ALL;
711 else if (CHAR_OR_CHAR_INTP (range))
712 {
713 outrange->type = CHARTAB_RANGE_CHAR;
714 outrange->ch = XCHAR_OR_CHAR_INT (range);
715 }
716 #ifndef MULE
717 else
718 signal_simple_error ("Range must be t or a character", range);
719 #else /* MULE */
720 else if (VECTORP (range))
721 {
722 struct Lisp_Vector *vec = XVECTOR (range);
723 Lisp_Object *elts = vector_data (vec);
724 if (vector_length (vec) != 2)
725 signal_simple_error ("Length of charset row vector must be 2",
726 range);
727 outrange->type = CHARTAB_RANGE_ROW;
728 outrange->charset = Fget_charset (elts[0]);
729 CHECK_INT (elts[1]);
730 outrange->row = XINT (elts[1]);
731 switch (XCHARSET_TYPE (outrange->charset))
732 {
733 case CHARSET_TYPE_94:
734 case CHARSET_TYPE_96:
735 signal_simple_error ("Charset in row vector must be multi-byte",
736 outrange->charset);
737 case CHARSET_TYPE_94X94:
738 check_int_range (outrange->row, 33, 126);
739 break;
740 case CHARSET_TYPE_96X96:
741 check_int_range (outrange->row, 32, 127);
742 break;
743 default:
744 abort ();
745 }
746 }
747 else
748 {
749 if (!CHARSETP (range) && !SYMBOLP (range))
750 signal_simple_error
751 ("Char table range must be t, charset, char, or vector", range);
752 outrange->type = CHARTAB_RANGE_CHARSET;
753 outrange->charset = Fget_charset (range);
754 }
755 #endif /* MULE */
756 }
757
758 #ifdef MULE
759
760 /* called from CHAR_TABLE_VALUE(). */
761 Lisp_Object
762 get_non_ascii_char_table_value (struct Lisp_Char_Table *ct, int leading_byte,
763 Emchar c)
764 {
765 Lisp_Object val;
766 Lisp_Object charset = CHARSET_BY_LEADING_BYTE (leading_byte);
767 int byte1, byte2;
768
769 BREAKUP_CHAR_1_UNSAFE (c, charset, byte1, byte2);
770 val = ct->level1[leading_byte - MIN_LEADING_BYTE];
771 if (CHAR_TABLE_ENTRYP (val))
772 {
773 struct Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (val);
774 val = cte->level2[byte1 - 32];
775 if (CHAR_TABLE_ENTRYP (val))
776 {
777 cte = XCHAR_TABLE_ENTRY (val);
778 assert (byte2 >= 32);
779 val = cte->level2[byte2 - 32];
780 assert (!CHAR_TABLE_ENTRYP (val));
781 }
782 }
783
784 return val;
785 }
786
787 #endif /* MULE */
788
789 DEFUN ("get-char-table", Fget_char_table, 2, 2, 0, /*
790 Find value for char CH in TABLE.
791 */
792 (ch, table))
793 {
794 struct Lisp_Char_Table *ct;
795
796 CHECK_CHAR_TABLE (table);
797 ct = XCHAR_TABLE (table);
798 CHECK_CHAR_COERCE_INT (ch);
799
800 #ifdef MULE
801 {
802 Lisp_Object charset;
803 int byte1, byte2;
804 Lisp_Object val;
805
806 BREAKUP_CHAR (XCHAR (ch), charset, byte1, byte2);
807
808 if (EQ (charset, Vcharset_ascii))
809 val = ct->ascii[byte1];
810 else if (EQ (charset, Vcharset_control_1))
811 val = ct->ascii[byte1 + 128];
812 else
813 {
814 int lb = XCHARSET_LEADING_BYTE (charset) - MIN_LEADING_BYTE;
815 val = ct->level1[lb];
816 if (CHAR_TABLE_ENTRYP (val))
817 {
818 struct Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (val);
819 val = cte->level2[byte1 - 32];
820 if (CHAR_TABLE_ENTRYP (val))
821 {
822 cte = XCHAR_TABLE_ENTRY (val);
823 assert (byte2 >= 32);
824 val = cte->level2[byte2 - 32];
825 assert (!CHAR_TABLE_ENTRYP (val));
826 }
827 }
828 }
829
830 return val;
831 }
832 #else /* not MULE */
833 return ct->ascii[(unsigned char) XCHAR (ch)];
834 #endif /* not MULE */
835 }
836
837 DEFUN ("get-range-char-table", Fget_range_char_table, 2, 3, 0, /*
838 Find value for a range in TABLE.
839 If there is more than one value, return MULTI (defaults to nil).
840 */
841 (range, table, multi))
842 {
843 struct Lisp_Char_Table *ct;
844 struct chartab_range rainj;
845
846 if (CHAR_OR_CHAR_INTP (range))
847 return Fget_char_table (range, table);
848 CHECK_CHAR_TABLE (table);
849 ct = XCHAR_TABLE (table);
850
851 decode_char_table_range (range, &rainj);
852 switch (rainj.type)
853 {
854 case CHARTAB_RANGE_ALL:
855 {
856 int i;
857 Lisp_Object first = ct->ascii[0];
858
859 for (i = 1; i < NUM_ASCII_CHARS; i++)
860 if (!EQ (first, ct->ascii[i]))
861 return multi;
862
863 #ifdef MULE
864 for (i = MIN_LEADING_BYTE; i < MIN_LEADING_BYTE + NUM_LEADING_BYTES;
865 i++)
866 {
867 if (!CHARSETP (CHARSET_BY_LEADING_BYTE (i))
868 || i == LEADING_BYTE_ASCII
869 || i == LEADING_BYTE_CONTROL_1)
870 continue;
871 if (!EQ (first, ct->level1[i - MIN_LEADING_BYTE]))
872 return multi;
873 }
874 #endif /* MULE */
875
876 return first;
877 }
878
879 #ifdef MULE
880 case CHARTAB_RANGE_CHARSET:
881 if (EQ (rainj.charset, Vcharset_ascii))
882 {
883 int i;
884 Lisp_Object first = ct->ascii[0];
885
886 for (i = 1; i < 128; i++)
887 if (!EQ (first, ct->ascii[i]))
888 return multi;
889 return first;
890 }
891
892 if (EQ (rainj.charset, Vcharset_control_1))
893 {
894 int i;
895 Lisp_Object first = ct->ascii[128];
896
897 for (i = 129; i < 160; i++)
898 if (!EQ (first, ct->ascii[i]))
899 return multi;
900 return first;
901 }
902
903 {
904 Lisp_Object val = ct->level1[XCHARSET_LEADING_BYTE (rainj.charset) -
905 MIN_LEADING_BYTE];
906 if (CHAR_TABLE_ENTRYP (val))
907 return multi;
908 return val;
909 }
910
911 case CHARTAB_RANGE_ROW:
912 {
913 Lisp_Object val = ct->level1[XCHARSET_LEADING_BYTE (rainj.charset) -
914 MIN_LEADING_BYTE];
915 if (!CHAR_TABLE_ENTRYP (val))
916 return val;
917 val = XCHAR_TABLE_ENTRY (val)->level2[rainj.row - 32];
918 if (CHAR_TABLE_ENTRYP (val))
919 return multi;
920 return val;
921 }
922 #endif /* not MULE */
923
924 default:
925 abort ();
926 }
927
928 return Qnil; /* not reached */
929 }
930
931 static int
932 check_valid_char_table_value (Lisp_Object value, enum char_table_type type,
933 Error_behavior errb)
934 {
935 switch (type)
936 {
937 case CHAR_TABLE_TYPE_SYNTAX:
938 if (!ERRB_EQ (errb, ERROR_ME))
939 return INTP (value) || (CONSP (value) && INTP (XCAR (value))
940 && CHAR_OR_CHAR_INTP (XCDR (value)));
941 if (CONSP (value))
942 {
943 Lisp_Object cdr = XCDR (value);
944 CHECK_INT (XCAR (value));
945 CHECK_CHAR_COERCE_INT (cdr);
946 }
947 else
948 CHECK_INT (value);
949 break;
950
951 #ifdef MULE
952 case CHAR_TABLE_TYPE_CATEGORY:
953 if (!ERRB_EQ (errb, ERROR_ME))
954 return CATEGORY_TABLE_VALUEP (value);
955 CHECK_CATEGORY_TABLE_VALUE (value);
956 break;
957 #endif
958
959 case CHAR_TABLE_TYPE_GENERIC:
960 return 1;
961
962 case CHAR_TABLE_TYPE_DISPLAY:
963 /* #### fix this */
964 maybe_signal_simple_error ("Display char tables not yet implemented",
965 value, Qchar_table, errb);
966 return 0;
967
968 case CHAR_TABLE_TYPE_CHAR:
969 if (!ERRB_EQ (errb, ERROR_ME))
970 return CHAR_OR_CHAR_INTP (value);
971 CHECK_CHAR_COERCE_INT (value);
972 break;
973
974 default:
975 abort ();
976 }
977
978 return 0; /* not reached */
979 }
980
981 static Lisp_Object
982 canonicalize_char_table_value (Lisp_Object value, enum char_table_type type)
983 {
984 switch (type)
985 {
986 case CHAR_TABLE_TYPE_SYNTAX:
987 if (CONSP (value))
988 {
989 Lisp_Object car = XCAR (value);
990 Lisp_Object cdr = XCDR (value);
991 CHECK_CHAR_COERCE_INT (cdr);
992 return Fcons (car, cdr);
993 }
994 default:
995 break;
996 }
997 return value;
998 }
999
1000 DEFUN ("valid-char-table-value-p", Fvalid_char_table_value_p, 2, 2, 0, /*
1001 Return non-nil if VALUE is a valid value for CHAR-TABLE-TYPE.
1002 */
1003 (value, char_table_type))
1004 {
1005 enum char_table_type type = symbol_to_char_table_type (char_table_type);
1006
1007 return check_valid_char_table_value (value, type, ERROR_ME_NOT) ? Qt : Qnil;
1008 }
1009
1010 DEFUN ("check-valid-char-table-value", Fcheck_valid_char_table_value, 2, 2, 0, /*
1011 Signal an error if VALUE is not a valid value for CHAR-TABLE-TYPE.
1012 */
1013 (value, char_table_type))
1014 {
1015 enum char_table_type type = symbol_to_char_table_type (char_table_type);
1016
1017 check_valid_char_table_value (value, type, ERROR_ME);
1018 return Qnil;
1019 }
1020
1021 /* Assign VAL to all characters in RANGE in char table CT. */
1022
1023 void
1024 put_char_table (struct Lisp_Char_Table *ct, struct chartab_range *range,
1025 Lisp_Object val)
1026 {
1027 switch (range->type)
1028 {
1029 case CHARTAB_RANGE_ALL:
1030 fill_char_table (ct, val);
1031 return; /* avoid the duplicate call to update_syntax_table() below,
1032 since fill_char_table() also did that. */
1033
1034 #ifdef MULE
1035 case CHARTAB_RANGE_CHARSET:
1036 if (EQ (range->charset, Vcharset_ascii))
1037 {
1038 int i;
1039 for (i = 0; i < 128; i++)
1040 ct->ascii[i] = val;
1041 }
1042 else if (EQ (range->charset, Vcharset_control_1))
1043 {
1044 int i;
1045 for (i = 128; i < 160; i++)
1046 ct->ascii[i] = val;
1047 }
1048 else
1049 {
1050 int lb = XCHARSET_LEADING_BYTE (range->charset) - MIN_LEADING_BYTE;
1051 ct->level1[lb] = val;
1052 }
1053 break;
1054
1055 case CHARTAB_RANGE_ROW:
1056 {
1057 struct Lisp_Char_Table_Entry *cte;
1058 int lb = XCHARSET_LEADING_BYTE (range->charset) - MIN_LEADING_BYTE;
1059 /* make sure that there is a separate entry for the row. */
1060 if (!CHAR_TABLE_ENTRYP (ct->level1[lb]))
1061 ct->level1[lb] = make_char_table_entry (ct->level1[lb]);
1062 cte = XCHAR_TABLE_ENTRY (ct->level1[lb]);
1063 cte->level2[range->row - 32] = val;
1064 }
1065 break;
1066 #endif /* MULE */
1067
1068 case CHARTAB_RANGE_CHAR:
1069 #ifdef MULE
1070 {
1071 Lisp_Object charset;
1072 int byte1, byte2;
1073
1074 BREAKUP_CHAR (range->ch, charset, byte1, byte2);
1075 if (EQ (charset, Vcharset_ascii))
1076 ct->ascii[byte1] = val;
1077 else if (EQ (charset, Vcharset_control_1))
1078 ct->ascii[byte1 + 128] = val;
1079 else
1080 {
1081 struct Lisp_Char_Table_Entry *cte;
1082 int lb = XCHARSET_LEADING_BYTE (charset) - MIN_LEADING_BYTE;
1083 /* make sure that there is a separate entry for the row. */
1084 if (!CHAR_TABLE_ENTRYP (ct->level1[lb]))
1085 ct->level1[lb] = make_char_table_entry (ct->level1[lb]);
1086 cte = XCHAR_TABLE_ENTRY (ct->level1[lb]);
1087 /* now CTE is a char table entry for the charset;
1088 each entry is for a single row (or character of
1089 a one-octet charset). */
1090 if (XCHARSET_DIMENSION (charset) == 1)
1091 cte->level2[byte1 - 32] = val;
1092 else
1093 {
1094 /* assigning to one character in a two-octet charset. */
1095 /* make sure that the charset row contains a separate
1096 entry for each character. */
1097 if (!CHAR_TABLE_ENTRYP (cte->level2[byte1 - 32]))
1098 cte->level2[byte1 - 32] =
1099 make_char_table_entry (cte->level2[byte1 - 32]);
1100 cte = XCHAR_TABLE_ENTRY (cte->level2[byte1 - 32]);
1101 cte->level2[byte2 - 32] = val;
1102 }
1103 }
1104 }
1105 #else /* not MULE */
1106 ct->ascii[(unsigned char) (range->ch)] = val;
1107 break;
1108 #endif /* not MULE */
1109 }
1110
1111 if (ct->type == CHAR_TABLE_TYPE_SYNTAX)
1112 update_syntax_table (ct);
1113 }
1114
1115 DEFUN ("put-char-table", Fput_char_table, 3, 3, 0, /*
1116 Set the value for chars in RANGE to be VAL in TABLE.
1117
1118 RANGE specifies one or more characters to be affected and should be
1119 one of the following:
1120
1121 -- t (all characters are affected)
1122 -- A charset (only allowed when Mule support is present)
1123 -- A vector of two elements: a two-octet charset and a row number
1124 (only allowed when Mule support is present)
1125 -- A single character
1126
1127 VAL must be a value appropriate for the type of TABLE.
1128 See `valid-char-table-type-p'.
1129 */
1130 (range, val, table))
1131 {
1132 struct Lisp_Char_Table *ct;
1133 struct chartab_range rainj;
1134
1135 CHECK_CHAR_TABLE (table);
1136 ct = XCHAR_TABLE (table);
1137 check_valid_char_table_value (val, ct->type, ERROR_ME);
1138 decode_char_table_range (range, &rainj);
1139 val = canonicalize_char_table_value (val, ct->type);
1140 put_char_table (ct, &rainj, val);
1141 return Qnil;
1142 }
1143
1144 /* Map FN over the ASCII chars in CT. */
1145
1146 static int
1147 map_over_charset_ascii (struct Lisp_Char_Table *ct,
1148 int (*fn) (struct chartab_range *range,
1149 Lisp_Object val, void *arg),
1150 void *arg)
1151 {
1152 int i;
1153
1154 #ifdef MULE
1155 for (i = 0; i < 128; i++)
1156 #else
1157 for (i = 0; i < 256; i++)
1158 #endif
1159 {
1160 Lisp_Object val = ct->ascii[i];
1161 struct chartab_range rainj;
1162 int retval;
1163
1164 rainj.type = CHARTAB_RANGE_CHAR;
1165 rainj.ch = (Emchar) i;
1166 retval = (fn) (&rainj, val, arg);
1167 if (retval)
1168 return retval;
1169 }
1170
1171 return 0;
1172 }
1173
1174 #ifdef MULE
1175
1176 /* Map FN over the Control-1 chars in CT. */
1177
1178 static int
1179 map_over_charset_control_1 (struct Lisp_Char_Table *ct,
1180 int (*fn) (struct chartab_range *range,
1181 Lisp_Object val, void *arg),
1182 void *arg)
1183 {
1184 int i;
1185
1186 for (i = 0; i < 32; i++)
1187 {
1188 Lisp_Object val = ct->ascii[i + 128];
1189 struct chartab_range rainj;
1190 int retval;
1191
1192 rainj.type = CHARTAB_RANGE_CHAR;
1193 rainj.ch = (Emchar) (i + 128);
1194 retval = (fn) (&rainj, val, arg);
1195 if (retval)
1196 return retval;
1197 }
1198
1199 return 0;
1200 }
1201
1202 /* Map FN over the row ROW of two-byte charset CHARSET.
1203 There must be a separate value for that row in the char table.
1204 CTE specifies the char table entry for CHARSET. */
1205
1206 static int
1207 map_over_charset_row (struct Lisp_Char_Table_Entry *cte,
1208 Lisp_Object charset, int row,
1209 int (*fn) (struct chartab_range *range,
1210 Lisp_Object val, void *arg),
1211 void *arg)
1212 {
1213 Lisp_Object val;
1214
1215 val = cte->level2[row - 32];
1216 if (!CHAR_TABLE_ENTRYP (val))
1217 {
1218 struct chartab_range rainj;
1219
1220 rainj.type = CHARTAB_RANGE_ROW;
1221 rainj.charset = charset;
1222 rainj.row = row;
1223 return (fn) (&rainj, val, arg);
1224 }
1225 else
1226 {
1227 int i;
1228 int start, stop;
1229
1230 cte = XCHAR_TABLE_ENTRY (val);
1231 if (XCHARSET_CHARS (charset) == 94)
1232 {
1233 start = 33;
1234 stop = 127;
1235 }
1236 else
1237 {
1238 start = 32;
1239 stop = 128;
1240 }
1241
1242 for (i = start; i < stop; i++)
1243 {
1244 int retval;
1245 struct chartab_range rainj;
1246
1247 rainj.type = CHARTAB_RANGE_CHAR;
1248 rainj.ch = MAKE_CHAR (charset, row, i);
1249
1250 val = cte->level2[i - 32];
1251 retval = (fn) (&rainj, val, arg);
1252 if (retval)
1253 return retval;
1254 }
1255 }
1256
1257 return 0;
1258 }
1259
1260 static int
1261 map_over_other_charset (struct Lisp_Char_Table *ct, int lb,
1262 int (*fn) (struct chartab_range *range,
1263 Lisp_Object val, void *arg),
1264 void *arg)
1265 {
1266 Lisp_Object charset;
1267 Lisp_Object val;
1268
1269 val = ct->level1[lb - MIN_LEADING_BYTE];
1270
1271 charset = CHARSET_BY_LEADING_BYTE (lb);
1272 if (!CHARSETP (charset) || lb == LEADING_BYTE_ASCII
1273 || lb == LEADING_BYTE_CONTROL_1)
1274 return 0;
1275 if (!CHAR_TABLE_ENTRYP (val))
1276 {
1277 struct chartab_range rainj;
1278
1279 rainj.type = CHARTAB_RANGE_CHARSET;
1280 rainj.charset = charset;
1281 return (fn) (&rainj, val, arg);
1282 }
1283 else if (XCHARSET_DIMENSION (charset) == 1)
1284 {
1285 int i;
1286 struct Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (val);
1287 int start, stop;
1288
1289 if (XCHARSET_CHARS (charset) == 94)
1290 {
1291 start = 33;
1292 stop = 127;
1293 }
1294 else
1295 {
1296 start = 32;
1297 stop = 128;
1298 }
1299
1300 for (i = start; i < stop; i++)
1301 {
1302 int retval;
1303 struct chartab_range rainj;
1304
1305 rainj.type = CHARTAB_RANGE_CHAR;
1306 rainj.ch = MAKE_CHAR (charset, i, 0);
1307 retval = (fn) (&rainj, cte->level2[i - 32], arg);
1308 if (retval)
1309 return retval;
1310 }
1311 }
1312 else
1313 {
1314 int i;
1315 struct Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (val);
1316 int start, stop;
1317
1318 if (XCHARSET_CHARS (charset) == 94)
1319 {
1320 start = 33;
1321 stop = 127;
1322 }
1323 else
1324 {
1325 start = 32;
1326 stop = 128;
1327 }
1328
1329 for (i = start; i < stop; i++)
1330 {
1331 int retval =
1332 map_over_charset_row (cte, charset, i, fn, arg);
1333 if (retval)
1334 return retval;
1335 }
1336 }
1337
1338 return 0;
1339 }
1340
1341 #endif /* MULE */
1342
1343 /* Map FN (with client data ARG) over range RANGE in char table CT.
1344 Mapping stops the first time FN returns non-zero, and that value
1345 becomes the return value of map_char_table(). */
1346
1347 int
1348 map_char_table (struct Lisp_Char_Table *ct,
1349 struct chartab_range *range,
1350 int (*fn) (struct chartab_range *range,
1351 Lisp_Object val, void *arg),
1352 void *arg)
1353 {
1354 switch (range->type)
1355 {
1356 case CHARTAB_RANGE_ALL:
1357 {
1358 int retval;
1359
1360 retval = map_over_charset_ascii (ct, fn, arg);
1361 if (retval)
1362 return retval;
1363 #ifdef MULE
1364 retval = map_over_charset_control_1 (ct, fn, arg);
1365 if (retval)
1366 return retval;
1367 {
1368 int i;
1369 for (i = MIN_LEADING_BYTE; i < MIN_LEADING_BYTE + NUM_LEADING_BYTES;
1370 i++)
1371 {
1372 retval = map_over_other_charset (ct, i, fn, arg);
1373 if (retval)
1374 return retval;
1375 }
1376 }
1377 #endif
1378 }
1379 break;
1380
1381 #ifdef MULE
1382 case CHARTAB_RANGE_CHARSET:
1383 return map_over_other_charset (ct,
1384 XCHARSET_LEADING_BYTE (range->charset),
1385 fn, arg);
1386
1387 case CHARTAB_RANGE_ROW:
1388 {
1389 Lisp_Object val = ct->level1[XCHARSET_LEADING_BYTE (range->charset)];
1390 if (!CHAR_TABLE_ENTRYP (val))
1391 {
1392 struct chartab_range rainj;
1393
1394 rainj.type = CHARTAB_RANGE_ROW;
1395 rainj.charset = range->charset;
1396 rainj.row = range->row;
1397 return (fn) (&rainj, val, arg);
1398 }
1399 else
1400 return map_over_charset_row (XCHAR_TABLE_ENTRY (val),
1401 range->charset, range->row,
1402 fn, arg);
1403 }
1404 #endif /* MULE */
1405
1406 case CHARTAB_RANGE_CHAR:
1407 {
1408 Emchar ch = range->ch;
1409 Lisp_Object val = CHAR_TABLE_VALUE_UNSAFE (ct, ch);
1410 struct chartab_range rainj;
1411
1412 rainj.type = CHARTAB_RANGE_CHAR;
1413 rainj.ch = ch;
1414 return (fn) (&rainj, val, arg);
1415 }
1416
1417 default:
1418 abort ();
1419 }
1420
1421 return 0;
1422 }
1423
1424 struct slow_map_char_table_arg
1425 {
1426 Lisp_Object function;
1427 Lisp_Object retval;
1428 };
1429
1430 static int
1431 slow_map_char_table_fun (struct chartab_range *range,
1432 Lisp_Object val, void *arg)
1433 {
1434 Lisp_Object ranjarg = Qnil;
1435 struct slow_map_char_table_arg *closure =
1436 (struct slow_map_char_table_arg *) arg;
1437
1438 switch (range->type)
1439 {
1440 case CHARTAB_RANGE_ALL:
1441 ranjarg = Qt;
1442 break;
1443
1444 #ifdef MULE
1445 case CHARTAB_RANGE_CHARSET:
1446 ranjarg = XCHARSET_NAME (range->charset);
1447 break;
1448
1449 case CHARTAB_RANGE_ROW:
1450 ranjarg = vector2 (XCHARSET_NAME (range->charset),
1451 make_int (range->row));
1452 break;
1453 #endif
1454 case CHARTAB_RANGE_CHAR:
1455 ranjarg = make_char (range->ch);
1456 break;
1457 default:
1458 abort ();
1459 }
1460
1461 closure->retval = call2 (closure->function, ranjarg, val);
1462 return (!NILP (closure->retval));
1463 }
1464
1465 DEFUN ("map-char-table", Fmap_char_table, 2, 3, 0, /*
1466 Map FUNCTION over entries in TABLE, calling it with two args,
1467 each key and value in the table.
1468
1469 RANGE specifies a subrange to map over and is in the same format as
1470 the RANGE argument to `put-range-table'. If omitted or t, it defaults to
1471 the entire table.
1472 */
1473 (function, table, range))
1474 {
1475 struct Lisp_Char_Table *ct;
1476 struct slow_map_char_table_arg slarg;
1477 struct gcpro gcpro1, gcpro2;
1478 struct chartab_range rainj;
1479
1480 CHECK_CHAR_TABLE (table);
1481 ct = XCHAR_TABLE (table);
1482 if (NILP (range))
1483 range = Qt;
1484 decode_char_table_range (range, &rainj);
1485 slarg.function = function;
1486 slarg.retval = Qnil;
1487 GCPRO2 (slarg.function, slarg.retval);
1488 map_char_table (ct, &rainj, slow_map_char_table_fun, &slarg);
1489 UNGCPRO;
1490
1491 return slarg.retval;
1492 }
1493
1494
1495 /************************************************************************/
1496 /* Char table read syntax */
1497 /************************************************************************/
1498
1499 static int
1500 chartab_type_validate (Lisp_Object keyword, Lisp_Object value,
1501 Error_behavior errb)
1502 {
1503 /* #### should deal with ERRB */
1504 (void) symbol_to_char_table_type (value);
1505 return 1;
1506 }
1507
1508 static int
1509 chartab_data_validate (Lisp_Object keyword, Lisp_Object value,
1510 Error_behavior errb)
1511 {
1512 Lisp_Object rest;
1513
1514 /* #### should deal with ERRB */
1515 EXTERNAL_LIST_LOOP (rest, value)
1516 {
1517 Lisp_Object range = XCAR (rest);
1518 struct chartab_range dummy;
1519
1520 rest = XCDR (rest);
1521 if (!CONSP (rest))
1522 signal_simple_error ("Invalid list format", value);
1523 if (CONSP (range))
1524 {
1525 if (!CONSP (XCDR (range))
1526 || !NILP (XCDR (XCDR (range))))
1527 signal_simple_error ("Invalid range format", range);
1528 decode_char_table_range (XCAR (range), &dummy);
1529 decode_char_table_range (XCAR (XCDR (range)), &dummy);
1530 }
1531 else
1532 decode_char_table_range (range, &dummy);
1533 }
1534
1535 return 1;
1536 }
1537
1538 static Lisp_Object
1539 chartab_instantiate (Lisp_Object data)
1540 {
1541 Lisp_Object chartab;
1542 Lisp_Object type = Qgeneric;
1543 Lisp_Object dataval = Qnil;
1544
1545 while (!NILP (data))
1546 {
1547 Lisp_Object keyw = Fcar (data);
1548 Lisp_Object valw;
1549
1550 data = Fcdr (data);
1551 valw = Fcar (data);
1552 data = Fcdr (data);
1553 if (EQ (keyw, Qtype))
1554 type = valw;
1555 else if (EQ (keyw, Qdata))
1556 dataval = valw;
1557 }
1558
1559 chartab = Fmake_char_table (type);
1560
1561 data = dataval;
1562 while (!NILP (data))
1563 {
1564 Lisp_Object range = Fcar (data);
1565 Lisp_Object val = Fcar (Fcdr (data));
1566
1567 data = Fcdr (Fcdr (data));
1568 if (CONSP (range))
1569 {
1570 if (CHAR_OR_CHAR_INTP (XCAR (range)))
1571 {
1572 Emchar first = XCHAR_OR_CHAR_INT (Fcar (range));
1573 Emchar last = XCHAR_OR_CHAR_INT (Fcar (Fcdr (range)));
1574 Emchar i;
1575
1576 for (i = first; i <= last; i++)
1577 Fput_char_table (make_char (i), val, chartab);
1578 }
1579 else
1580 abort ();
1581 }
1582 else
1583 Fput_char_table (range, val, chartab);
1584 }
1585
1586 return chartab;
1587 }
1588
1589 #ifdef MULE
1590
1591
1592 /************************************************************************/
1593 /* Category Tables, specifically */
1594 /************************************************************************/
1595
1596 DEFUN ("category-table-p", Fcategory_table_p, 1, 1, 0, /*
1597 Return t if ARG is a category table.
1598 A category table is a type of char table used for keeping track of
1599 categories. Categories are used for classifying characters for use
1600 in regexps -- you can refer to a category rather than having to use
1601 a complicated [] expression (and category lookups are significantly
1602 faster).
1603
1604 There are 95 different categories available, one for each printable
1605 character (including space) in the ASCII charset. Each category
1606 is designated by one such character, called a \"category designator\".
1607 They are specified in a regexp using the syntax \"\\cX\", where X is
1608 a category designator. (This is not yet implemented.)
1609
1610 A category table specifies, for each character, the categories that
1611 the character is in. Note that a character can be in more than one
1612 category. More specifically, a category table maps from a character
1613 to either the value nil (meaning the character is in no categories)
1614 or a 95-element bit vector, specifying for each of the 95 categories
1615 whether the character is in that category.
1616
1617 Special Lisp functions are provided that abstract this, so you do not
1618 have to directly manipulate bit vectors.
1619 */
1620 (obj))
1621 {
1622 if (CHAR_TABLEP (obj) && XCHAR_TABLE_TYPE (obj) == CHAR_TABLE_TYPE_CATEGORY)
1623 return Qt;
1624 return Qnil;
1625 }
1626
1627 static Lisp_Object
1628 check_category_table (Lisp_Object obj, Lisp_Object def)
1629 {
1630 if (NILP (obj))
1631 obj = def;
1632 while (NILP (Fcategory_table_p (obj)))
1633 obj = wrong_type_argument (Qcategory_table_p, obj);
1634 return (obj);
1635 }
1636
1637 DEFUN ("category-table", Fcategory_table, 0, 1, 0, /*
1638 Return the current category table.
1639 This is the one specified by the current buffer, or by BUFFER if it
1640 is non-nil.
1641 */
1642 (buffer))
1643 {
1644 return decode_buffer (buffer, 0)->category_table;
1645 }
1646
1647 DEFUN ("standard-category-table", Fstandard_category_table, 0, 0, 0, /*
1648 Return the standard category table.
1649 This is the one used for new buffers.
1650 */
1651 ())
1652 {
1653 return Vstandard_category_table;
1654 }
1655
1656 DEFUN ("copy-category-table", Fcopy_category_table, 0, 1, 0, /*
1657 Construct a new category table and return it.
1658 It is a copy of the TABLE, which defaults to the standard category table.
1659 */
1660 (table))
1661 {
1662 if (NILP (Vstandard_category_table))
1663 return Fmake_char_table (Qcategory);
1664
1665 table = check_category_table (table, Vstandard_category_table);
1666 return Fcopy_char_table (table);
1667 }
1668
1669 DEFUN ("set-category-table", Fset_category_table, 1, 2, 0, /*
1670 Select a new category table for BUFFER.
1671 One argument, a category table.
1672 BUFFER defaults to the current buffer if omitted.
1673 */
1674 (table, buffer))
1675 {
1676 struct buffer *buf = decode_buffer (buffer, 0);
1677 table = check_category_table (table, Qnil);
1678 buf->category_table = table;
1679 /* Indicate that this buffer now has a specified category table. */
1680 buf->local_var_flags |= XINT (buffer_local_flags.category_table);
1681 return table;
1682 }
1683
1684 DEFUN ("category-designator-p", Fcategory_designator_p, 1, 1, 0, /*
1685 Return t if ARG is a category designator (a char in the range ' ' to '~').
1686 */
1687 (obj))
1688 {
1689 if (CATEGORY_DESIGNATORP (obj))
1690 return Qt;
1691 return Qnil;
1692 }
1693
1694 DEFUN ("category-table-value-p", Fcategory_table_value_p, 1, 1, 0, /*
1695 Return t if ARG is a category table value.
1696 Valid values are nil or a bit vector of size 95.
1697 */
1698 (obj))
1699 {
1700 if (CATEGORY_TABLE_VALUEP (obj))
1701 return Qt;
1702 return Qnil;
1703 }
1704
1705 #endif /* MULE */
1706
1707
1708 void
1709 syms_of_chartab (void)
1710 {
1711 #ifdef MULE
1712 defsymbol (&Qcategory_table_p, "category-table-p");
1713 defsymbol (&Qcategory_designator_p, "category-designator-p");
1714 defsymbol (&Qcategory_table_value_p, "category-table-value-p");
1715 #endif /* MULE */
1716
1717 defsymbol (&Qchar_table, "char-table");
1718 defsymbol (&Qchar_tablep, "char-table-p");
1719
1720 DEFSUBR (Fchar_table_p);
1721 DEFSUBR (Fchar_table_type_list);
1722 DEFSUBR (Fvalid_char_table_type_p);
1723 DEFSUBR (Fchar_table_type);
1724 DEFSUBR (Freset_char_table);
1725 DEFSUBR (Fmake_char_table);
1726 DEFSUBR (Fcopy_char_table);
1727 DEFSUBR (Fget_char_table);
1728 DEFSUBR (Fget_range_char_table);
1729 DEFSUBR (Fvalid_char_table_value_p);
1730 DEFSUBR (Fcheck_valid_char_table_value);
1731 DEFSUBR (Fput_char_table);
1732 DEFSUBR (Fmap_char_table);
1733
1734 #ifdef MULE
1735 DEFSUBR (Fcategory_table_p);
1736 DEFSUBR (Fcategory_table);
1737 DEFSUBR (Fstandard_category_table);
1738 DEFSUBR (Fcopy_category_table);
1739 DEFSUBR (Fset_category_table);
1740
1741 DEFSUBR (Fcategory_designator_p);
1742 DEFSUBR (Fcategory_table_value_p);
1743 #endif /* MULE */
1744
1745 /* DO NOT staticpro this. It works just like Vweak_hash_tables. */
1746 Vall_syntax_tables = Qnil;
1747 }
1748
1749 void
1750 structure_type_create_chartab (void)
1751 {
1752 struct structure_type *st;
1753
1754 st = define_structure_type (Qchar_table, 0, chartab_instantiate);
1755
1756 define_structure_type_keyword (st, Qtype, chartab_type_validate);
1757 define_structure_type_keyword (st, Qdata, chartab_data_validate);
1758 }
1759
1760 void
1761 complex_vars_of_chartab (void)
1762 {
1763 #ifdef MULE
1764 /* Set this now, so first buffer creation can refer to it. */
1765 /* Make it nil before calling copy-category-table
1766 so that copy-category-table will know not to try to copy from garbage */
1767 Vstandard_category_table = Qnil;
1768 Vstandard_category_table = Fcopy_category_table (Qnil);
1769 staticpro (&Vstandard_category_table);
1770 #endif /* MULE */
1771 }