comparison src/casetab.c @ 13242:3a8c500b97c3

Case tables are now char-tables, and the case table is stored in the downcase_table slot only. (Fcurrent_case_table, Fstandard_case_table, set_case_table) (compute_trt_inverse, init_casetab_once): Use new data format.
author Richard M. Stallman <rms@gnu.org>
date Thu, 19 Oct 1995 00:14:14 +0000
parents ac7375e60931
children a09ec2a2f6dd
comparison
equal deleted inserted replaced
13241:b1d118fb7b3e 13242:3a8c500b97c3
21 21
22 #include <config.h> 22 #include <config.h>
23 #include "lisp.h" 23 #include "lisp.h"
24 #include "buffer.h" 24 #include "buffer.h"
25 25
26 Lisp_Object Qcase_table_p; 26 Lisp_Object Qcase_table_p, Qcase_table;
27 Lisp_Object Vascii_downcase_table, Vascii_upcase_table; 27 Lisp_Object Vascii_downcase_table, Vascii_upcase_table;
28 Lisp_Object Vascii_canon_table, Vascii_eqv_table; 28 Lisp_Object Vascii_canon_table, Vascii_eqv_table;
29 29
30 void compute_trt_inverse (); 30 static void compute_trt_inverse ();
31 31
32 DEFUN ("case-table-p", Fcase_table_p, Scase_table_p, 1, 1, 0, 32 DEFUN ("case-table-p", Fcase_table_p, Scase_table_p, 1, 1, 0,
33 "Return t iff ARG is a case table.\n\ 33 "Return t iff ARG is a case table.\n\
34 See `set-case-table' for more information on these data structures.") 34 See `set-case-table' for more information on these data structures.")
35 (table) 35 (table)
36 Lisp_Object table; 36 Lisp_Object table;
37 { 37 {
38 Lisp_Object down, up, canon, eqv; 38 Lisp_Object down, up, canon, eqv;
39 down = Fcar_safe (table); 39
40 up = Fcar_safe (Fcdr_safe (table)); 40 if (! CHAR_TABLE_P (table))
41 canon = Fcar_safe (Fcdr_safe (Fcdr_safe (table))); 41 return Qnil;
42 eqv = Fcar_safe (Fcdr_safe (Fcdr_safe (Fcdr_safe (table)))); 42 if (! EQ (XCHAR_TABLE (table)->purpose, Qcase_table))
43 43 return Qnil;
44 #define STRING256_P(obj) (STRINGP (obj) && XSTRING (obj)->size == 256) 44
45 45 up = XCHAR_TABLE (table)->extras[0];
46 return (STRING256_P (down) 46 canon = XCHAR_TABLE (table)->extras[1];
47 && (NILP (up) || STRING256_P (up)) 47 eqv = XCHAR_TABLE (table)->extras[2];
48
49 return ((NILP (up) || CHAR_TABLE_P (up))
48 && ((NILP (canon) && NILP (eqv)) 50 && ((NILP (canon) && NILP (eqv))
49 || (STRING256_P (canon) 51 || (CHAR_TABLE_P (canon)
50 && (NILP (eqv) || STRING256_P (eqv)))) 52 && (NILP (eqv) || CHAR_TABLE_P (eqv))))
51 ? Qt : Qnil); 53 ? Qt : Qnil);
52 } 54 }
53 55
54 static Lisp_Object 56 static Lisp_Object
55 check_case_table (obj) 57 check_case_table (obj)
66 "Return the case table of the current buffer.") 68 "Return the case table of the current buffer.")
67 () 69 ()
68 { 70 {
69 Lisp_Object down, up, canon, eqv; 71 Lisp_Object down, up, canon, eqv;
70 72
71 down = current_buffer->downcase_table; 73 return current_buffer->downcase_table;
72 up = current_buffer->upcase_table;
73 canon = current_buffer->case_canon_table;
74 eqv = current_buffer->case_eqv_table;
75
76 return Fcons (down, Fcons (up, Fcons (canon, Fcons (eqv, Qnil))));
77 } 74 }
78 75
79 DEFUN ("standard-case-table", Fstandard_case_table, Sstandard_case_table, 0, 0, 0, 76 DEFUN ("standard-case-table", Fstandard_case_table, Sstandard_case_table, 0, 0, 0,
80 "Return the standard case table.\n\ 77 "Return the standard case table.\n\
81 This is the one used for new buffers.") 78 This is the one used for new buffers.")
82 () 79 ()
83 { 80 {
84 return Fcons (Vascii_downcase_table, 81 return Vascii_downcase_table;
85 Fcons (Vascii_upcase_table,
86 Fcons (Vascii_canon_table,
87 Fcons (Vascii_eqv_table, Qnil))));
88 } 82 }
89 83
90 static Lisp_Object set_case_table (); 84 static Lisp_Object set_case_table ();
91 85
92 DEFUN ("set-case-table", Fset_case_table, Sset_case_table, 1, 1, 0, 86 DEFUN ("set-case-table", Fset_case_table, Sset_case_table, 1, 1, 0,
93 "Select a new case table for the current buffer.\n\ 87 "Select a new case table for the current buffer.\n\
94 A case table is a list (DOWNCASE UPCASE CANONICALIZE EQUIVALENCES)\n\ 88 A case table is a char-table which maps characters
95 where each element is either nil or a string of length 256.\n\ 89 to their lower-case equivalents. It also has three \"extra\" slots
96 DOWNCASE maps each character to its lower-case equivalent.\n\ 90 which may be additional char-tables or nil.
91 These slots are called UPCASE, CANONICALIZE and EQUIVALENCES.\n\
97 UPCASE maps each character to its upper-case equivalent;\n\ 92 UPCASE maps each character to its upper-case equivalent;\n\
98 if lower and upper case characters are in 1-1 correspondence,\n\ 93 if lower and upper case characters are in 1-1 correspondence,\n\
99 you may use nil and the upcase table will be deduced from DOWNCASE.\n\ 94 you may use nil and the upcase table will be deduced from DOWNCASE.\n\
100 CANONICALIZE maps each character to a canonical equivalent;\n\ 95 CANONICALIZE maps each character to a canonical equivalent;\n\
101 any two characters that are related by case-conversion have the same\n\ 96 any two characters that are related by case-conversion have the same\n\
126 { 121 {
127 Lisp_Object down, up, canon, eqv; 122 Lisp_Object down, up, canon, eqv;
128 123
129 check_case_table (table); 124 check_case_table (table);
130 125
131 down = Fcar_safe (table); 126 up = XCHAR_TABLE (table)->extras[0];
132 up = Fcar_safe (Fcdr_safe (table)); 127 canon = XCHAR_TABLE (table)->extras[1];
133 canon = Fcar_safe (Fcdr_safe (Fcdr_safe (table))); 128 eqv = XCHAR_TABLE (table)->extras[2];
134 eqv = Fcar_safe (Fcdr_safe (Fcdr_safe (Fcdr_safe (table))));
135 129
136 if (NILP (up)) 130 if (NILP (up))
137 { 131 {
138 up = Fmake_string (make_number (256), make_number (0)); 132 up = Fmake_char_table (Qcase_table, Qnil);
139 compute_trt_inverse (XSTRING (down)->data, XSTRING (up)->data); 133 compute_trt_inverse (XCHAR_TABLE (down), XCHAR_TABLE (up));
134 XCHAR_TABLE (table)->extras[0] = up;
140 } 135 }
141 136
142 if (NILP (canon)) 137 if (NILP (canon))
143 { 138 {
144 register int i; 139 register int i;
145 unsigned char *upvec = XSTRING (up)->data; 140 Lisp_Object *upvec = XCHAR_TABLE (up)->contents;
146 unsigned char *downvec = XSTRING (down)->data; 141 Lisp_Object *downvec = XCHAR_TABLE (down)->contents;
147 142
148 canon = Fmake_string (make_number (256), make_number (0)); 143 up = Fmake_char_table (Qcase_table, Qnil);
149 144
150 /* Set up the CANON vector; for each character, 145 /* Set up the CANON vector; for each character,
151 this sequence of upcasing and downcasing ought to 146 this sequence of upcasing and downcasing ought to
152 get the "preferred" lowercase equivalent. */ 147 get the "preferred" lowercase equivalent. */
153 for (i = 0; i < 256; i++) 148 for (i = 0; i < 256; i++)
154 XSTRING (canon)->data[i] = downvec[upvec[downvec[i]]]; 149 XCHAR_TABLE (canon)->contents[i] = downvec[upvec[downvec[i]]];
150 XCHAR_TABLE (table)->extras[1] = canon;
155 } 151 }
156 152
157 if (NILP (eqv)) 153 if (NILP (eqv))
158 { 154 {
159 eqv = Fmake_string (make_number (256), make_number (0)); 155 eqv = Fmake_char_table (Qcase_table, Qnil);
160 156 compute_trt_inverse (XCHAR_TABLE (canon), XCHAR_TABLE (eqv));
161 compute_trt_inverse (XSTRING (canon)->data, XSTRING (eqv)->data); 157 XCHAR_TABLE (table)->extras[0] = eqv;
162 } 158 }
163 159
164 if (standard) 160 if (standard)
165 { 161 Vascii_downcase_table = down;
166 Vascii_downcase_table = down;
167 Vascii_upcase_table = up;
168 Vascii_canon_table = canon;
169 Vascii_eqv_table = eqv;
170 }
171 else 162 else
172 { 163 current_buffer->downcase_table = down;
173 current_buffer->downcase_table = down; 164
174 current_buffer->upcase_table = up;
175 current_buffer->case_canon_table = canon;
176 current_buffer->case_eqv_table = eqv;
177 }
178 return table; 165 return table;
179 } 166 }
180 167
181 /* Given a translate table TRT, store the inverse mapping into INVERSE. 168 /* Given a translate table TRT, store the inverse mapping into INVERSE.
182 Since TRT is not one-to-one, INVERSE is not a simple mapping. 169 Since TRT is not one-to-one, INVERSE is not a simple mapping.
183 Instead, it divides the space of characters into equivalence classes. 170 Instead, it divides the space of characters into equivalence classes.
184 All characters in a given class form one circular list, chained through 171 All characters in a given class form one circular list, chained through
185 the elements of INVERSE. */ 172 the elements of INVERSE. */
186 173
187 void 174 static void
188 compute_trt_inverse (trt, inverse) 175 compute_trt_inverse (trt, inverse)
189 register unsigned char *trt; 176 struct Lisp_Char_Table *trt, *inverse;
190 register unsigned char *inverse;
191 { 177 {
192 register int i = 0400; 178 register int i = 0400;
193 register unsigned char c, q; 179 register unsigned char c, q;
194 180
195 while (i--) 181 while (i--)
196 inverse[i] = i; 182 inverse->contents[i] = i;
197 i = 0400; 183 i = 0400;
198 while (i--) 184 while (i--)
199 { 185 {
200 if ((q = trt[i]) != (unsigned char) i) 186 if ((q = trt->contents[i]) != (unsigned char) i)
201 { 187 {
202 c = inverse[q]; 188 c = inverse->contents[q];
203 inverse[q] = i; 189 inverse->contents[q] = i;
204 inverse[i] = c; 190 inverse->contents[i] = c;
205 } 191 }
206 } 192 }
207 } 193 }
208 194
209 init_casetab_once () 195 init_casetab_once ()
210 { 196 {
211 register int i; 197 register int i;
212 Lisp_Object tem; 198 Lisp_Object down, up;
213 199 Qcase_table = intern ("case-table");
214 tem = Fmake_string (make_number (256), make_number (0)); 200 staticpro (&Qcase_table);
215 Vascii_downcase_table = tem; 201
216 Vascii_canon_table = tem; 202 /* Intern this now in case it isn't already done.
203 Setting this variable twice is harmless.
204 But don't staticpro it here--that is done in alloc.c. */
205 Qchar_table_extra_slots = intern ("char-table-extra-slots");
206
207 /* Now we are ready to set up this property, so we can
208 create char tables. */
209 Fput (Qcase_table, Qchar_table_extra_slots, make_number (4));
210
211 down = Fmake_char_table (Qcase_table, Qnil);
212 Vascii_downcase_table = down;
217 213
218 for (i = 0; i < 256; i++) 214 for (i = 0; i < 256; i++)
219 XSTRING (tem)->data[i] = (i >= 'A' && i <= 'Z') ? i + 040 : i; 215 XCHAR_TABLE (down)->contents[i] = (i >= 'A' && i <= 'Z') ? i + 040 : i;
220 216
221 tem = Fmake_string (make_number (256), make_number (0)); 217 XCHAR_TABLE (down)->extras[1] = Fcopy_sequence (down);
222 Vascii_upcase_table = tem; 218
223 Vascii_eqv_table = tem; 219 up = Fmake_char_table (Qcase_table, Qnil);
220 XCHAR_TABLE (down)->extras[0] = up;
224 221
225 for (i = 0; i < 256; i++) 222 for (i = 0; i < 256; i++)
226 XSTRING (tem)->data[i] 223 XCHAR_TABLE (up)->contents[i]
227 = ((i >= 'A' && i <= 'Z') 224 = ((i >= 'A' && i <= 'Z')
228 ? i + ('a' - 'A') 225 ? i + ('a' - 'A')
229 : ((i >= 'a' && i <= 'z') 226 : ((i >= 'a' && i <= 'z')
230 ? i + ('A' - 'a') 227 ? i + ('A' - 'a')
231 : i)); 228 : i));
229
230 XCHAR_TABLE (down)->extras[2] = Fcopy_sequence (up);
232 } 231 }
233 232
234 syms_of_casetab () 233 syms_of_casetab ()
235 { 234 {
236 Qcase_table_p = intern ("case-table-p"); 235 Qcase_table_p = intern ("case-table-p");
237 staticpro (&Qcase_table_p); 236 staticpro (&Qcase_table_p);
237
238 staticpro (&Vascii_downcase_table); 238 staticpro (&Vascii_downcase_table);
239 staticpro (&Vascii_upcase_table);
240 staticpro (&Vascii_canon_table);
241 staticpro (&Vascii_eqv_table);
242 239
243 defsubr (&Scase_table_p); 240 defsubr (&Scase_table_p);
244 defsubr (&Scurrent_case_table); 241 defsubr (&Scurrent_case_table);
245 defsubr (&Sstandard_case_table); 242 defsubr (&Sstandard_case_table);
246 defsubr (&Sset_case_table); 243 defsubr (&Sset_case_table);
247 defsubr (&Sset_standard_case_table); 244 defsubr (&Sset_standard_case_table);
248 245 }
249 #if 0
250 DEFVAR_LISP ("ascii-downcase-table", &Vascii_downcase_table,
251 "String mapping ASCII characters to lowercase equivalents.");
252 DEFVAR_LISP ("ascii-upcase-table", &Vascii_upcase_table,
253 "String mapping ASCII characters to uppercase equivalents.");
254 #endif
255 }