]> code.delx.au - gnu-emacs/blob - src/abbrev.c
(Finsert_abbrev_table_description): Reindent.
[gnu-emacs] / src / abbrev.c
1 /* Primitives for word-abbrev mode.
2 Copyright (C) 1985, 1986, 1993, 1996, 1998, 2001
3 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22
23 #include <config.h>
24 #include <stdio.h>
25
26 #include "lisp.h"
27 #include "commands.h"
28 #include "buffer.h"
29 #include "window.h"
30 #include "charset.h"
31 #include "syntax.h"
32
33 /* An abbrev table is an obarray.
34 Each defined abbrev is represented by a symbol in that obarray
35 whose print name is the abbreviation.
36 The symbol's value is a string which is the expansion.
37 If its function definition is non-nil, it is called
38 after the expansion is done.
39 The plist slot of the abbrev symbol is its usage count. */
40
41 /* List of all abbrev-table name symbols:
42 symbols whose values are abbrev tables. */
43
44 Lisp_Object Vabbrev_table_name_list;
45
46 /* The table of global abbrevs. These are in effect
47 in any buffer in which abbrev mode is turned on. */
48
49 Lisp_Object Vglobal_abbrev_table;
50
51 /* The local abbrev table used by default (in Fundamental Mode buffers) */
52
53 Lisp_Object Vfundamental_mode_abbrev_table;
54
55 /* Set nonzero when an abbrev definition is changed */
56
57 int abbrevs_changed;
58
59 int abbrev_all_caps;
60
61 /* Non-nil => use this location as the start of abbrev to expand
62 (rather than taking the word before point as the abbrev) */
63
64 Lisp_Object Vabbrev_start_location;
65
66 /* Buffer that Vabbrev_start_location applies to */
67 Lisp_Object Vabbrev_start_location_buffer;
68
69 /* The symbol representing the abbrev most recently expanded */
70
71 Lisp_Object Vlast_abbrev;
72
73 /* A string for the actual text of the abbrev most recently expanded.
74 This has more info than Vlast_abbrev since case is significant. */
75
76 Lisp_Object Vlast_abbrev_text;
77
78 /* Character address of start of last abbrev expanded */
79
80 int last_abbrev_point;
81
82 /* Hook to run before expanding any abbrev. */
83
84 Lisp_Object Vpre_abbrev_expand_hook, Qpre_abbrev_expand_hook;
85 \f
86 DEFUN ("make-abbrev-table", Fmake_abbrev_table, Smake_abbrev_table, 0, 0, 0,
87 doc: /* Create a new, empty abbrev table object. */)
88 ()
89 {
90 return Fmake_vector (make_number (59), make_number (0));
91 }
92
93 DEFUN ("clear-abbrev-table", Fclear_abbrev_table, Sclear_abbrev_table, 1, 1, 0,
94 doc: /* Undefine all abbrevs in abbrev table TABLE, leaving it empty. */)
95 (table)
96 Lisp_Object table;
97 {
98 int i, size;
99
100 CHECK_VECTOR (table, 0);
101 size = XVECTOR (table)->size;
102 abbrevs_changed = 1;
103 for (i = 0; i < size; i++)
104 XVECTOR (table)->contents[i] = make_number (0);
105 return Qnil;
106 }
107 \f
108 DEFUN ("define-abbrev", Fdefine_abbrev, Sdefine_abbrev, 3, 5, 0,
109 doc: /* Define an abbrev in TABLE named NAME, to expand to EXPANSION and call HOOK.
110 NAME must be a string.
111 EXPANSION should usually be a string.
112 To undefine an abbrev, define it with EXPANSION = nil.
113 If HOOK is non-nil, it should be a function of no arguments;
114 it is called after EXPANSION is inserted.
115 If EXPANSION is not a string, the abbrev is a special one,
116 which does not expand in the usual way but only runs HOOK.
117 COUNT, if specified, initializes the abbrev's usage-count
118 which is incremented each time the abbrev is used. */)
119 (table, name, expansion, hook, count)
120 Lisp_Object table, name, expansion, hook, count;
121 {
122 Lisp_Object sym, oexp, ohook, tem;
123 CHECK_VECTOR (table, 0);
124 CHECK_STRING (name, 1);
125
126 if (NILP (count))
127 count = make_number (0);
128 else
129 CHECK_NUMBER (count, 0);
130
131 sym = Fintern (name, table);
132
133 oexp = SYMBOL_VALUE (sym);
134 ohook = XSYMBOL (sym)->function;
135 if (!((EQ (oexp, expansion)
136 || (STRINGP (oexp) && STRINGP (expansion)
137 && (tem = Fstring_equal (oexp, expansion), !NILP (tem))))
138 &&
139 (EQ (ohook, hook)
140 || (tem = Fequal (ohook, hook), !NILP (tem)))))
141 abbrevs_changed = 1;
142
143 Fset (sym, expansion);
144 Ffset (sym, hook);
145 Fsetplist (sym, count);
146
147 return name;
148 }
149
150 DEFUN ("define-global-abbrev", Fdefine_global_abbrev, Sdefine_global_abbrev, 2, 2,
151 "sDefine global abbrev: \nsExpansion for %s: ",
152 doc: /* Define ABBREV as a global abbreviation for EXPANSION. */)
153 (abbrev, expansion)
154 Lisp_Object abbrev, expansion;
155 {
156 Fdefine_abbrev (Vglobal_abbrev_table, Fdowncase (abbrev),
157 expansion, Qnil, make_number (0));
158 return abbrev;
159 }
160
161 DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev, Sdefine_mode_abbrev, 2, 2,
162 "sDefine mode abbrev: \nsExpansion for %s: ",
163 doc: /* Define ABBREV as a mode-specific abbreviation for EXPANSION. */)
164 (abbrev, expansion)
165 Lisp_Object abbrev, expansion;
166 {
167 if (NILP (current_buffer->abbrev_table))
168 error ("Major mode has no abbrev table");
169
170 Fdefine_abbrev (current_buffer->abbrev_table, Fdowncase (abbrev),
171 expansion, Qnil, make_number (0));
172 return abbrev;
173 }
174
175 DEFUN ("abbrev-symbol", Fabbrev_symbol, Sabbrev_symbol, 1, 2, 0,
176 doc: /* Return the symbol representing abbrev named ABBREV.
177 This symbol's name is ABBREV, but it is not the canonical symbol of that name;
178 it is interned in an abbrev-table rather than the normal obarray.
179 The value is nil if that abbrev is not defined.
180 Optional second arg TABLE is abbrev table to look it up in.
181 The default is to try buffer's mode-specific abbrev table, then global table. */)
182 (abbrev, table)
183 Lisp_Object abbrev, table;
184 {
185 Lisp_Object sym;
186 CHECK_STRING (abbrev, 0);
187 if (!NILP (table))
188 sym = Fintern_soft (abbrev, table);
189 else
190 {
191 sym = Qnil;
192 if (!NILP (current_buffer->abbrev_table))
193 sym = Fintern_soft (abbrev, current_buffer->abbrev_table);
194 if (NILP (SYMBOL_VALUE (sym)))
195 sym = Qnil;
196 if (NILP (sym))
197 sym = Fintern_soft (abbrev, Vglobal_abbrev_table);
198 }
199 if (NILP (SYMBOL_VALUE (sym)))
200 return Qnil;
201 return sym;
202 }
203
204 DEFUN ("abbrev-expansion", Fabbrev_expansion, Sabbrev_expansion, 1, 2, 0,
205 doc: /* Return the string that ABBREV expands into in the current buffer.
206 Optionally specify an abbrev table as second arg;
207 then ABBREV is looked up in that table only. */)
208 (abbrev, table)
209 Lisp_Object abbrev, table;
210 {
211 Lisp_Object sym;
212 sym = Fabbrev_symbol (abbrev, table);
213 if (NILP (sym)) return sym;
214 return Fsymbol_value (sym);
215 }
216 \f
217 /* Expand the word before point, if it is an abbrev.
218 Returns 1 if an expansion is done. */
219
220 DEFUN ("expand-abbrev", Fexpand_abbrev, Sexpand_abbrev, 0, 0, "",
221 doc: /* Expand the abbrev before point, if there is an abbrev there.
222 Effective when explicitly called even when `abbrev-mode' is nil.
223 Returns the abbrev symbol, if expansion took place. */)
224 ()
225 {
226 register char *buffer, *p;
227 int wordstart, wordend;
228 register int wordstart_byte, wordend_byte, idx;
229 int whitecnt;
230 int uccount = 0, lccount = 0;
231 register Lisp_Object sym;
232 Lisp_Object expansion, hook, tem;
233 Lisp_Object value;
234
235 value = Qnil;
236
237 if (!NILP (Vrun_hooks))
238 call1 (Vrun_hooks, Qpre_abbrev_expand_hook);
239
240 wordstart = 0;
241 if (!(BUFFERP (Vabbrev_start_location_buffer)
242 && XBUFFER (Vabbrev_start_location_buffer) == current_buffer))
243 Vabbrev_start_location = Qnil;
244 if (!NILP (Vabbrev_start_location))
245 {
246 tem = Vabbrev_start_location;
247 CHECK_NUMBER_COERCE_MARKER (tem, 0);
248 wordstart = XINT (tem);
249 Vabbrev_start_location = Qnil;
250 if (wordstart < BEGV || wordstart > ZV)
251 wordstart = 0;
252 if (wordstart && wordstart != ZV)
253 {
254 wordstart_byte = CHAR_TO_BYTE (wordstart);
255 if (FETCH_BYTE (wordstart_byte) == '-')
256 del_range (wordstart, wordstart + 1);
257 }
258 }
259 if (!wordstart)
260 wordstart = scan_words (PT, -1);
261
262 if (!wordstart)
263 return value;
264
265 wordstart_byte = CHAR_TO_BYTE (wordstart);
266 wordend = scan_words (wordstart, 1);
267 if (!wordend)
268 return value;
269
270 if (wordend > PT)
271 wordend = PT;
272
273 wordend_byte = CHAR_TO_BYTE (wordend);
274 whitecnt = PT - wordend;
275 if (wordend <= wordstart)
276 return value;
277
278 p = buffer = (char *) alloca (wordend_byte - wordstart_byte);
279
280 for (idx = wordstart_byte; idx < wordend_byte; idx++)
281 {
282 /* ??? This loop needs to go by characters! */
283 register int c = FETCH_BYTE (idx);
284 if (UPPERCASEP (c))
285 c = DOWNCASE (c), uccount++;
286 else if (! NOCASEP (c))
287 lccount++;
288 *p++ = c;
289 }
290
291 if (VECTORP (current_buffer->abbrev_table))
292 sym = oblookup (current_buffer->abbrev_table, buffer,
293 wordend - wordstart, wordend_byte - wordstart_byte);
294 else
295 XSETFASTINT (sym, 0);
296 if (INTEGERP (sym) || NILP (SYMBOL_VALUE (sym)))
297 sym = oblookup (Vglobal_abbrev_table, buffer,
298 wordend - wordstart, wordend_byte - wordstart_byte);
299 if (INTEGERP (sym) || NILP (SYMBOL_VALUE (sym)))
300 return value;
301
302 if (INTERACTIVE && !EQ (minibuf_window, selected_window))
303 {
304 /* Add an undo boundary, in case we are doing this for
305 a self-inserting command which has avoided making one so far. */
306 SET_PT (wordend);
307 Fundo_boundary ();
308 }
309
310 Vlast_abbrev_text
311 = Fbuffer_substring (make_number (wordstart), make_number (wordend));
312
313 /* Now sym is the abbrev symbol. */
314 Vlast_abbrev = sym;
315 value = sym;
316 last_abbrev_point = wordstart;
317
318 if (INTEGERP (XSYMBOL (sym)->plist))
319 XSETINT (XSYMBOL (sym)->plist,
320 XINT (XSYMBOL (sym)->plist) + 1); /* Increment use count */
321
322 /* If this abbrev has an expansion, delete the abbrev
323 and insert the expansion. */
324 expansion = SYMBOL_VALUE (sym);
325 if (STRINGP (expansion))
326 {
327 SET_PT (wordstart);
328
329 del_range_both (wordstart, wordstart_byte, wordend, wordend_byte, 1);
330
331 insert_from_string (expansion, 0, 0, XSTRING (expansion)->size,
332 STRING_BYTES (XSTRING (expansion)), 1);
333 SET_PT (PT + whitecnt);
334
335 if (uccount && !lccount)
336 {
337 /* Abbrev was all caps */
338 /* If expansion is multiple words, normally capitalize each word */
339 /* This used to be if (!... && ... >= ...) Fcapitalize; else Fupcase
340 but Megatest 68000 compiler can't handle that */
341 if (!abbrev_all_caps)
342 if (scan_words (PT, -1) > scan_words (wordstart, 1))
343 {
344 Fupcase_initials_region (make_number (wordstart),
345 make_number (PT));
346 goto caped;
347 }
348 /* If expansion is one word, or if user says so, upcase it all. */
349 Fupcase_region (make_number (wordstart), make_number (PT));
350 caped: ;
351 }
352 else if (uccount)
353 {
354 /* Abbrev included some caps. Cap first initial of expansion */
355 int pos = wordstart_byte;
356
357 /* Find the initial. */
358 while (pos < PT_BYTE
359 && SYNTAX (*BUF_BYTE_ADDRESS (current_buffer, pos)) != Sword)
360 pos++;
361
362 /* Change just that. */
363 pos = BYTE_TO_CHAR (pos);
364 Fupcase_initials_region (make_number (pos), make_number (pos + 1));
365 }
366 }
367
368 hook = XSYMBOL (sym)->function;
369 if (!NILP (hook))
370 {
371 Lisp_Object expanded, prop;
372
373 /* If the abbrev has a hook function, run it. */
374 expanded = call0 (hook);
375
376 /* In addition, if the hook function is a symbol with a a
377 non-nil `no-self-insert' property, let the value it returned
378 specify whether we consider that an expansion took place. If
379 it returns nil, no expansion has been done. */
380
381 if (SYMBOLP (hook)
382 && NILP (expanded)
383 && (prop = Fget (hook, intern ("no-self-insert")),
384 !NILP (prop)))
385 value = Qnil;
386 }
387
388 return value;
389 }
390
391 DEFUN ("unexpand-abbrev", Funexpand_abbrev, Sunexpand_abbrev, 0, 0, "",
392 doc: /* Undo the expansion of the last abbrev that expanded.
393 This differs from ordinary undo in that other editing done since then
394 is not undone. */)
395 ()
396 {
397 int opoint = PT;
398 int adjust = 0;
399 if (last_abbrev_point < BEGV
400 || last_abbrev_point > ZV)
401 return Qnil;
402 SET_PT (last_abbrev_point);
403 if (STRINGP (Vlast_abbrev_text))
404 {
405 /* This isn't correct if Vlast_abbrev->function was used
406 to do the expansion */
407 Lisp_Object val;
408 int zv_before;
409
410 val = SYMBOL_VALUE (Vlast_abbrev);
411 if (!STRINGP (val))
412 error ("value of abbrev-symbol must be a string");
413 zv_before = ZV;
414 del_range_byte (PT_BYTE, PT_BYTE + STRING_BYTES (XSTRING (val)), 1);
415 /* Don't inherit properties here; just copy from old contents. */
416 insert_from_string (Vlast_abbrev_text, 0, 0,
417 XSTRING (Vlast_abbrev_text)->size,
418 STRING_BYTES (XSTRING (Vlast_abbrev_text)), 0);
419 Vlast_abbrev_text = Qnil;
420 /* Total number of characters deleted. */
421 adjust = ZV - zv_before;
422 }
423 SET_PT (last_abbrev_point < opoint ? opoint + adjust : opoint);
424 return Qnil;
425 }
426 \f
427 static void
428 write_abbrev (sym, stream)
429 Lisp_Object sym, stream;
430 {
431 Lisp_Object name;
432 if (NILP (SYMBOL_VALUE (sym)))
433 return;
434 insert (" (", 5);
435 XSETSTRING (name, XSYMBOL (sym)->name);
436 Fprin1 (name, stream);
437 insert (" ", 1);
438 Fprin1 (SYMBOL_VALUE (sym), stream);
439 insert (" ", 1);
440 Fprin1 (XSYMBOL (sym)->function, stream);
441 insert (" ", 1);
442 Fprin1 (XSYMBOL (sym)->plist, stream);
443 insert (")\n", 2);
444 }
445
446 static void
447 describe_abbrev (sym, stream)
448 Lisp_Object sym, stream;
449 {
450 Lisp_Object one;
451
452 if (NILP (SYMBOL_VALUE (sym)))
453 return;
454 one = make_number (1);
455 Fprin1 (Fsymbol_name (sym), stream);
456 Findent_to (make_number (15), one);
457 Fprin1 (XSYMBOL (sym)->plist, stream);
458 Findent_to (make_number (20), one);
459 Fprin1 (SYMBOL_VALUE (sym), stream);
460 if (!NILP (XSYMBOL (sym)->function))
461 {
462 Findent_to (make_number (45), one);
463 Fprin1 (XSYMBOL (sym)->function, stream);
464 }
465 Fterpri (stream);
466 }
467
468 DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,
469 Sinsert_abbrev_table_description, 1, 2, 0,
470 doc: /* Insert before point a full description of abbrev table named NAME.
471 NAME is a symbol whose value is an abbrev table.
472 If optional 2nd arg READABLE is non-nil, a human-readable description
473 is inserted. Otherwise the description is an expression,
474 a call to `define-abbrev-table', which would
475 define the abbrev table NAME exactly as it is currently defined. */)
476 (name, readable)
477 Lisp_Object name, readable;
478 {
479 Lisp_Object table;
480 Lisp_Object stream;
481
482 CHECK_SYMBOL (name, 0);
483 table = Fsymbol_value (name);
484 CHECK_VECTOR (table, 0);
485
486 XSETBUFFER (stream, current_buffer);
487
488 if (!NILP (readable))
489 {
490 insert_string ("(");
491 Fprin1 (name, stream);
492 insert_string (")\n\n");
493 map_obarray (table, describe_abbrev, stream);
494 insert_string ("\n\n");
495 }
496 else
497 {
498 insert_string ("(define-abbrev-table '");
499 Fprin1 (name, stream);
500 insert_string (" '(\n");
501 map_obarray (table, write_abbrev, stream);
502 insert_string (" ))\n\n");
503 }
504
505 return Qnil;
506 }
507 \f
508 DEFUN ("define-abbrev-table", Fdefine_abbrev_table, Sdefine_abbrev_table,
509 2, 2, 0,
510 doc: /* Define TABLENAME (a symbol) as an abbrev table name.
511 Define abbrevs in it according to DEFINITIONS, which is a list of elements
512 of the form (ABBREVNAME EXPANSION HOOK USECOUNT). */)
513 (tablename, definitions)
514 Lisp_Object tablename, definitions;
515 {
516 Lisp_Object name, exp, hook, count;
517 Lisp_Object table, elt;
518
519 CHECK_SYMBOL (tablename, 0);
520 table = Fboundp (tablename);
521 if (NILP (table) || (table = Fsymbol_value (tablename), NILP (table)))
522 {
523 table = Fmake_abbrev_table ();
524 Fset (tablename, table);
525 Vabbrev_table_name_list = Fcons (tablename, Vabbrev_table_name_list);
526 }
527 CHECK_VECTOR (table, 0);
528
529 for (; !NILP (definitions); definitions = Fcdr (definitions))
530 {
531 elt = Fcar (definitions);
532 name = Fcar (elt); elt = Fcdr (elt);
533 exp = Fcar (elt); elt = Fcdr (elt);
534 hook = Fcar (elt); elt = Fcdr (elt);
535 count = Fcar (elt);
536 Fdefine_abbrev (table, name, exp, hook, count);
537 }
538 return Qnil;
539 }
540 \f
541 void
542 syms_of_abbrev ()
543 {
544 DEFVAR_LISP ("abbrev-table-name-list", &Vabbrev_table_name_list,
545 doc: /* List of symbols whose values are abbrev tables. */);
546 Vabbrev_table_name_list = Fcons (intern ("fundamental-mode-abbrev-table"),
547 Fcons (intern ("global-abbrev-table"),
548 Qnil));
549
550 DEFVAR_LISP ("global-abbrev-table", &Vglobal_abbrev_table,
551 doc: /* The abbrev table whose abbrevs affect all buffers.
552 Each buffer may also have a local abbrev table.
553 If it does, the local table overrides the global one
554 for any particular abbrev defined in both. */);
555 Vglobal_abbrev_table = Fmake_abbrev_table ();
556
557 DEFVAR_LISP ("fundamental-mode-abbrev-table", &Vfundamental_mode_abbrev_table,
558 doc: /* The abbrev table of mode-specific abbrevs for Fundamental Mode. */);
559 Vfundamental_mode_abbrev_table = Fmake_abbrev_table ();
560 current_buffer->abbrev_table = Vfundamental_mode_abbrev_table;
561 buffer_defaults.abbrev_table = Vfundamental_mode_abbrev_table;
562
563 DEFVAR_LISP ("last-abbrev", &Vlast_abbrev,
564 doc: /* The abbrev-symbol of the last abbrev expanded. See `abbrev-symbol'. */);
565
566 DEFVAR_LISP ("last-abbrev-text", &Vlast_abbrev_text,
567 doc: /* The exact text of the last abbrev expanded.
568 nil if the abbrev has already been unexpanded. */);
569
570 DEFVAR_INT ("last-abbrev-location", &last_abbrev_point,
571 doc: /* The location of the start of the last abbrev expanded. */);
572
573 Vlast_abbrev = Qnil;
574 Vlast_abbrev_text = Qnil;
575 last_abbrev_point = 0;
576
577 DEFVAR_LISP ("abbrev-start-location", &Vabbrev_start_location,
578 doc: /* Buffer position for `expand-abbrev' to use as the start of the abbrev.
579 nil means use the word before point as the abbrev.
580 Calling `expand-abbrev' sets this to nil. */);
581 Vabbrev_start_location = Qnil;
582
583 DEFVAR_LISP ("abbrev-start-location-buffer", &Vabbrev_start_location_buffer,
584 doc: /* Buffer that `abbrev-start-location' has been set for.
585 Trying to expand an abbrev in any other buffer clears `abbrev-start-location'. */);
586 Vabbrev_start_location_buffer = Qnil;
587
588 DEFVAR_PER_BUFFER ("local-abbrev-table", &current_buffer->abbrev_table, Qnil,
589 doc: /* Local (mode-specific) abbrev table of current buffer. */);
590
591 DEFVAR_BOOL ("abbrevs-changed", &abbrevs_changed,
592 doc: /* Set non-nil by defining or altering any word abbrevs.
593 This causes `save-some-buffers' to offer to save the abbrevs. */);
594 abbrevs_changed = 0;
595
596 DEFVAR_BOOL ("abbrev-all-caps", &abbrev_all_caps,
597 doc: /* *Set non-nil means expand multi-word abbrevs all caps if abbrev was so. */);
598 abbrev_all_caps = 0;
599
600 DEFVAR_LISP ("pre-abbrev-expand-hook", &Vpre_abbrev_expand_hook,
601 doc: /* Function or functions to be called before abbrev expansion is done.
602 This is the first thing that `expand-abbrev' does, and so this may change
603 the current abbrev table before abbrev lookup happens. */);
604 Vpre_abbrev_expand_hook = Qnil;
605 Qpre_abbrev_expand_hook = intern ("pre-abbrev-expand-hook");
606 staticpro (&Qpre_abbrev_expand_hook);
607
608 defsubr (&Smake_abbrev_table);
609 defsubr (&Sclear_abbrev_table);
610 defsubr (&Sdefine_abbrev);
611 defsubr (&Sdefine_global_abbrev);
612 defsubr (&Sdefine_mode_abbrev);
613 defsubr (&Sabbrev_expansion);
614 defsubr (&Sabbrev_symbol);
615 defsubr (&Sexpand_abbrev);
616 defsubr (&Sunexpand_abbrev);
617 defsubr (&Sinsert_abbrev_table_description);
618 defsubr (&Sdefine_abbrev_table);
619 }