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