Remove `LISP_FLOAT_TYPE' and `standalone'.
[bpt/emacs.git] / src / abbrev.c
index e3f1faf..ca97637 100644 (file)
@@ -1,11 +1,11 @@
 /* Primitives for word-abbrev mode.
 /* Primitives for word-abbrev mode.
-   Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1993, 1996, 1998 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
+the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -15,16 +15,18 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 
 
-#include "config.h"
+#include <config.h>
 #include <stdio.h>
 #include <stdio.h>
-#undef NULL
 #include "lisp.h"
 #include "commands.h"
 #include "buffer.h"
 #include "window.h"
 #include "lisp.h"
 #include "commands.h"
 #include "buffer.h"
 #include "window.h"
+#include "charset.h"
+#include "syntax.h"
 
 /* An abbrev table is an obarray.
  Each defined abbrev is represented by a symbol in that obarray
 
 /* An abbrev table is an obarray.
  Each defined abbrev is represented by a symbol in that obarray
@@ -75,6 +77,9 @@ Lisp_Object Vlast_abbrev_text;
 
 int last_abbrev_point;
 
 
 int last_abbrev_point;
 
+/* Hook to run before expanding any abbrev.  */
+
+Lisp_Object Vpre_abbrev_expand_hook, Qpre_abbrev_expand_hook;
 \f
 DEFUN ("make-abbrev-table", Fmake_abbrev_table, Smake_abbrev_table, 0, 0, 0,
   "Create a new, empty abbrev table object.")
 \f
 DEFUN ("make-abbrev-table", Fmake_abbrev_table, Smake_abbrev_table, 0, 0, 0,
   "Create a new, empty abbrev table object.")
@@ -100,19 +105,23 @@ DEFUN ("clear-abbrev-table", Fclear_abbrev_table, Sclear_abbrev_table, 1, 1, 0,
 \f
 DEFUN ("define-abbrev", Fdefine_abbrev, Sdefine_abbrev, 3, 5, 0,
   "Define an abbrev in TABLE named NAME, to expand to EXPANSION and call HOOK.\n\
 \f
 DEFUN ("define-abbrev", Fdefine_abbrev, Sdefine_abbrev, 3, 5, 0,
   "Define an abbrev in TABLE named NAME, to expand to EXPANSION and call HOOK.\n\
-NAME and EXPANSION are strings.\n\
+NAME must be a string.\n\
+EXPANSION should usually be a string.\n\
 To undefine an abbrev, define it with EXPANSION = nil.\n\
 If HOOK is non-nil, it should be a function of no arguments;\n\
 To undefine an abbrev, define it with EXPANSION = nil.\n\
 If HOOK is non-nil, it should be a function of no arguments;\n\
-it is called after EXPANSION is inserted.")
+it is called after EXPANSION is inserted.\n\
+If EXPANSION is not a string, the abbrev is a special one,\n\
+ which does not expand in the usual way but only runs HOOK.\n\
+COUNT, if specified, initializes the abbrev's usage-count\n\
+which is incremented each time the abbrev is used.")
   (table, name, expansion, hook, count)
      Lisp_Object table, name, expansion, hook, count;
 {
   Lisp_Object sym, oexp, ohook, tem;
   CHECK_VECTOR (table, 0);
   CHECK_STRING (name, 1);
   (table, name, expansion, hook, count)
      Lisp_Object table, name, expansion, hook, count;
 {
   Lisp_Object sym, oexp, ohook, tem;
   CHECK_VECTOR (table, 0);
   CHECK_STRING (name, 1);
-  if (!NULL (expansion))
-    CHECK_STRING (expansion, 2);
-  if (NULL (count))
+
+  if (NILP (count))
     count = make_number (0);
   else
     CHECK_NUMBER (count, 0);
     count = make_number (0);
   else
     CHECK_NUMBER (count, 0);
@@ -122,11 +131,11 @@ it is called after EXPANSION is inserted.")
   oexp = XSYMBOL (sym)->value;
   ohook = XSYMBOL (sym)->function;
   if (!((EQ (oexp, expansion)
   oexp = XSYMBOL (sym)->value;
   ohook = XSYMBOL (sym)->function;
   if (!((EQ (oexp, expansion)
-        || (XTYPE (oexp) == Lisp_String && XTYPE (expansion) == Lisp_String
-            && (tem = Fstring_equal (oexp, expansion), !NULL (tem))))
+        || (STRINGP (oexp) && STRINGP (expansion)
+            && (tem = Fstring_equal (oexp, expansion), !NILP (tem))))
        &&
        (EQ (ohook, hook)
        &&
        (EQ (ohook, hook)
-        || (tem = Fequal (ohook, hook), !NULL (tem)))))
+        || (tem = Fequal (ohook, hook), !NILP (tem)))))
     abbrevs_changed = 1;
 
   Fset (sym, expansion);
     abbrevs_changed = 1;
 
   Fset (sym, expansion);
@@ -139,26 +148,26 @@ it is called after EXPANSION is inserted.")
 DEFUN ("define-global-abbrev", Fdefine_global_abbrev, Sdefine_global_abbrev, 2, 2,
   "sDefine global abbrev: \nsExpansion for %s: ",
   "Define ABBREV as a global abbreviation for EXPANSION.")
 DEFUN ("define-global-abbrev", Fdefine_global_abbrev, Sdefine_global_abbrev, 2, 2,
   "sDefine global abbrev: \nsExpansion for %s: ",
   "Define ABBREV as a global abbreviation for EXPANSION.")
-  (name, expansion)
-     Lisp_Object name, expansion;
+  (abbrev, expansion)
+     Lisp_Object abbrev, expansion;
 {
 {
-  Fdefine_abbrev (Vglobal_abbrev_table, Fdowncase (name),
+  Fdefine_abbrev (Vglobal_abbrev_table, Fdowncase (abbrev),
                  expansion, Qnil, make_number (0));
                  expansion, Qnil, make_number (0));
-  return name;
+  return abbrev;
 }
 
 DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev, Sdefine_mode_abbrev, 2, 2,
   "sDefine mode abbrev: \nsExpansion for %s: ",
   "Define ABBREV as a mode-specific abbreviation for EXPANSION.")
 }
 
 DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev, Sdefine_mode_abbrev, 2, 2,
   "sDefine mode abbrev: \nsExpansion for %s: ",
   "Define ABBREV as a mode-specific abbreviation for EXPANSION.")
-  (name, expansion)
-     Lisp_Object name, expansion;
+  (abbrev, expansion)
+     Lisp_Object abbrev, expansion;
 {
 {
-  if (NULL (current_buffer->abbrev_table))
+  if (NILP (current_buffer->abbrev_table))
     error ("Major mode has no abbrev table");
 
     error ("Major mode has no abbrev table");
 
-  Fdefine_abbrev (current_buffer->abbrev_table, Fdowncase (name),
+  Fdefine_abbrev (current_buffer->abbrev_table, Fdowncase (abbrev),
                  expansion, Qnil, make_number (0));
                  expansion, Qnil, make_number (0));
-  return name;
+  return abbrev;
 }
 
 DEFUN ("abbrev-symbol", Fabbrev_symbol, Sabbrev_symbol, 1, 2, 0,
 }
 
 DEFUN ("abbrev-symbol", Fabbrev_symbol, Sabbrev_symbol, 1, 2, 0,
@@ -173,19 +182,19 @@ The default is to try buffer's mode-specific abbrev table, then global table.")
 {
   Lisp_Object sym;
   CHECK_STRING (abbrev, 0);
 {
   Lisp_Object sym;
   CHECK_STRING (abbrev, 0);
-  if (!NULL (table))
+  if (!NILP (table))
     sym = Fintern_soft (abbrev, table);
   else
     {
       sym = Qnil;
     sym = Fintern_soft (abbrev, table);
   else
     {
       sym = Qnil;
-      if (!NULL (current_buffer->abbrev_table))
+      if (!NILP (current_buffer->abbrev_table))
        sym = Fintern_soft (abbrev, current_buffer->abbrev_table);
        sym = Fintern_soft (abbrev, current_buffer->abbrev_table);
-      if (NULL (XSYMBOL (sym)->value))
+      if (NILP (XSYMBOL (sym)->value))
        sym = Qnil;
        sym = Qnil;
-      if (NULL (sym))
+      if (NILP (sym))
        sym = Fintern_soft (abbrev, Vglobal_abbrev_table);
     }
        sym = Fintern_soft (abbrev, Vglobal_abbrev_table);
     }
-  if (NULL (XSYMBOL (sym)->value)) return Qnil;
+  if (NILP (XSYMBOL (sym)->value)) return Qnil;
   return sym;
 }
 
   return sym;
 }
 
@@ -198,7 +207,7 @@ then ABBREV is looked up in that table only.")
 {
   Lisp_Object sym;
   sym = Fabbrev_symbol (abbrev, table);
 {
   Lisp_Object sym;
   sym = Fabbrev_symbol (abbrev, table);
-  if (NULL (sym)) return sym;
+  if (NILP (sym)) return sym;
   return Fsymbol_value (sym);
 }
 \f
   return Fsymbol_value (sym);
 }
 \f
@@ -208,48 +217,67 @@ then ABBREV is looked up in that table only.")
 DEFUN ("expand-abbrev", Fexpand_abbrev, Sexpand_abbrev, 0, 0, "",
   "Expand the abbrev before point, if there is an abbrev there.\n\
 Effective when explicitly called even when `abbrev-mode' is nil.\n\
 DEFUN ("expand-abbrev", Fexpand_abbrev, Sexpand_abbrev, 0, 0, "",
   "Expand the abbrev before point, if there is an abbrev there.\n\
 Effective when explicitly called even when `abbrev-mode' is nil.\n\
-Returns t if expansion took place.")
+Returns the abbrev symbol, if expansion took place.")
   ()
 {
   register char *buffer, *p;
   ()
 {
   register char *buffer, *p;
-  register int wordstart, wordend, idx;
+  int wordstart, wordend;
+  register int wordstart_byte, wordend_byte, idx;
   int whitecnt;
   int uccount = 0, lccount = 0;
   register Lisp_Object sym;
   Lisp_Object expansion, hook, tem;
   int whitecnt;
   int uccount = 0, lccount = 0;
   register Lisp_Object sym;
   Lisp_Object expansion, hook, tem;
+  Lisp_Object value;
+
+  value = Qnil;
+
+  if (!NILP (Vrun_hooks))
+    call1 (Vrun_hooks, Qpre_abbrev_expand_hook);
 
 
-  if (XBUFFER (Vabbrev_start_location_buffer) != current_buffer)
+  wordstart = 0;
+  if (!(BUFFERP (Vabbrev_start_location_buffer)
+       && XBUFFER (Vabbrev_start_location_buffer) == current_buffer))
     Vabbrev_start_location = Qnil;
     Vabbrev_start_location = Qnil;
-  if (!NULL (Vabbrev_start_location))
+  if (!NILP (Vabbrev_start_location))
     {
       tem = Vabbrev_start_location;
       CHECK_NUMBER_COERCE_MARKER (tem, 0);
       wordstart = XINT (tem);
       Vabbrev_start_location = Qnil;
     {
       tem = Vabbrev_start_location;
       CHECK_NUMBER_COERCE_MARKER (tem, 0);
       wordstart = XINT (tem);
       Vabbrev_start_location = Qnil;
-      if (FETCH_CHAR (wordstart) == '-')
-       del_range (wordstart, wordstart + 1);
+      if (wordstart < BEGV || wordstart > ZV)
+       wordstart = 0;
+      if (wordstart && wordstart != ZV)
+       {
+         wordstart_byte = CHAR_TO_BYTE (wordstart);
+         if (FETCH_BYTE (wordstart_byte) == '-')
+           del_range (wordstart, wordstart + 1);
+       }
     }
     }
-  else
-    wordstart = scan_words (point, -1);
+  if (!wordstart)
+    wordstart = scan_words (PT, -1);
 
   if (!wordstart)
 
   if (!wordstart)
-    return Qnil;
+    return value;
 
 
+  wordstart_byte = CHAR_TO_BYTE (wordstart);
   wordend = scan_words (wordstart, 1);
   if (!wordend)
   wordend = scan_words (wordstart, 1);
   if (!wordend)
-    return Qnil;
+    return value;
+
+  if (wordend > PT)
+    wordend = PT;
 
 
-  if (wordend > point)
-    wordend = point;
-  whitecnt = point - wordend;
+  wordend_byte = CHAR_TO_BYTE (wordend);
+  whitecnt = PT - wordend;
   if (wordend <= wordstart)
   if (wordend <= wordstart)
-    return Qnil;
+    return value;
 
 
-  p = buffer = (char *) alloca (wordend - wordstart);
+  p = buffer = (char *) alloca (wordend_byte - wordstart_byte);
 
 
-  for (idx = wordstart; idx < point; idx++)
+  for (idx = wordstart_byte; idx < wordend_byte; idx++)
     {
     {
-      register int c = FETCH_CHAR (idx);
+      /* ??? This loop needs to go by characters!  */
+      register int c = FETCH_BYTE (idx);
       if (UPPERCASEP (c))
        c = DOWNCASE (c), uccount++;
       else if (! NOCASEP (c))
       if (UPPERCASEP (c))
        c = DOWNCASE (c), uccount++;
       else if (! NOCASEP (c))
@@ -257,74 +285,104 @@ Returns t if expansion took place.")
       *p++ = c;
     }
 
       *p++ = c;
     }
 
-  if (XTYPE (current_buffer->abbrev_table) == Lisp_Vector)
-    sym = oblookup (current_buffer->abbrev_table, buffer, p - buffer);
+  if (VECTORP (current_buffer->abbrev_table))
+    sym = oblookup (current_buffer->abbrev_table, buffer,
+                   wordend - wordstart, wordend_byte - wordstart_byte);
   else
   else
-    XFASTINT (sym) = 0;
-  if (XTYPE (sym) == Lisp_Int || NULL (XSYMBOL (sym)->value))
-    sym = oblookup (Vglobal_abbrev_table, buffer, p - buffer);
-  if (XTYPE (sym) == Lisp_Int || NULL (XSYMBOL (sym)->value))
-    return Qnil;
+    XSETFASTINT (sym, 0);
+  if (INTEGERP (sym) || NILP (XSYMBOL (sym)->value))
+    sym = oblookup (Vglobal_abbrev_table, buffer,
+                   wordend - wordstart, wordend_byte - wordstart_byte);
+  if (INTEGERP (sym) || NILP (XSYMBOL (sym)->value))
+    return value;
 
   if (INTERACTIVE && !EQ (minibuf_window, selected_window))
     {
 
   if (INTERACTIVE && !EQ (minibuf_window, selected_window))
     {
+      /* Add an undo boundary, in case we are doing this for
+        a self-inserting command which has avoided making one so far.  */
       SET_PT (wordend);
       Fundo_boundary ();
     }
       SET_PT (wordend);
       Fundo_boundary ();
     }
-  SET_PT (wordstart);
+
   Vlast_abbrev_text
     = Fbuffer_substring (make_number (wordstart), make_number (wordend));
   Vlast_abbrev_text
     = Fbuffer_substring (make_number (wordstart), make_number (wordend));
-  del_range (wordstart, wordend);
 
 
-  /* Now sym is the abbrev symbol. */
+  /* Now sym is the abbrev symbol.  */
   Vlast_abbrev = sym;
   Vlast_abbrev = sym;
+  value = sym;
   last_abbrev_point = wordstart;
 
   last_abbrev_point = wordstart;
 
-  if (XTYPE (XSYMBOL (sym)->plist) == Lisp_Int)
+  if (INTEGERP (XSYMBOL (sym)->plist))
     XSETINT (XSYMBOL (sym)->plist,
             XINT (XSYMBOL (sym)->plist) + 1);  /* Increment use count */
 
     XSETINT (XSYMBOL (sym)->plist,
             XINT (XSYMBOL (sym)->plist) + 1);  /* Increment use count */
 
+  /* If this abbrev has an expansion, delete the abbrev
+     and insert the expansion.  */
   expansion = XSYMBOL (sym)->value;
   expansion = XSYMBOL (sym)->value;
-  insert_from_string (expansion, 0, XSTRING (expansion)->size);
-  SET_PT (point + whitecnt);
-
-  if (uccount && !lccount)
+  if (STRINGP (expansion))
     {
     {
-      /* Abbrev was all caps */
-      /* If expansion is multiple words, normally capitalize each word */
-      /* This used to be if (!... && ... >= ...) Fcapitalize; else Fupcase
-        but Megatest 68000 compiler can't handle that */
-      if (!abbrev_all_caps)
-       if (scan_words (point, -1) > scan_words (wordstart, 1))
-         {
-           upcase_initials_region (make_number (wordstart),
-                                   make_number (point));
-           goto caped;
-         }
-      /* If expansion is one word, or if user says so, upcase it all. */
-      Fupcase_region (make_number (wordstart), make_number (point));
-    caped: ;
-    }
-  else if (uccount)
-    {
-      /* Abbrev included some caps.  Cap first initial of expansion */
-      int old_zv = ZV;
-      int old_pt = point;
-
-      /* Don't let Fcapitalize_word operate on text after point.  */
-      ZV = point;
       SET_PT (wordstart);
       SET_PT (wordstart);
-      Fcapitalize_word (make_number (1));
 
 
-      SET_PT (old_pt);
-      ZV = old_zv;
+      del_range_both (wordstart, wordstart_byte, wordend, wordend_byte, 1);
+
+      insert_from_string (expansion, 0, 0, XSTRING (expansion)->size,
+                         STRING_BYTES (XSTRING (expansion)), 1);
+      SET_PT (PT + whitecnt);
+
+      if (uccount && !lccount)
+       {
+         /* Abbrev was all caps */
+         /* If expansion is multiple words, normally capitalize each word */
+         /* This used to be if (!... && ... >= ...) Fcapitalize; else Fupcase
+            but Megatest 68000 compiler can't handle that */
+         if (!abbrev_all_caps)
+           if (scan_words (PT, -1) > scan_words (wordstart, 1))
+             {
+               Fupcase_initials_region (make_number (wordstart),
+                                        make_number (PT));
+               goto caped;
+             }
+         /* If expansion is one word, or if user says so, upcase it all. */
+         Fupcase_region (make_number (wordstart), make_number (PT));
+       caped: ;
+       }
+      else if (uccount)
+       {
+         /* Abbrev included some caps.  Cap first initial of expansion */
+         int pos = wordstart_byte;
+
+         /* Find the initial.  */
+         while (pos < PT_BYTE
+                && SYNTAX (*BUF_BYTE_ADDRESS (current_buffer, pos)) != Sword)
+           pos++;
+
+         /* Change just that.  */
+         pos = BYTE_TO_CHAR (pos);
+         Fupcase_initials_region (make_number (pos), make_number (pos + 1));
+       }
     }
 
   hook = XSYMBOL (sym)->function;
     }
 
   hook = XSYMBOL (sym)->function;
-  if (!NULL (hook))
-    call0 (hook);
+  if (!NILP (hook))
+    {
+      Lisp_Object expanded, prop;
+
+      /* If the abbrev has a hook function, run it.  */
+      expanded = call0 (hook);
+
+      /* In addition, if the hook function is a symbol with a a
+        non-nil `no-self-insert' property, let the value it returned
+        specify whether we consider that an expansion took place.  If
+        it returns nil, no expansion has been done.  */
 
 
-  return Qt;
+      if (SYMBOLP (hook)
+         && NILP (expanded)
+         && (prop = Fget (hook, intern ("no-self-insert")),
+             !NILP (prop)))
+       value = Qnil;
+    }
+
+  return value;
 }
 
 DEFUN ("unexpand-abbrev", Funexpand_abbrev, Sunexpand_abbrev, 0, 0, "",
 }
 
 DEFUN ("unexpand-abbrev", Funexpand_abbrev, Sunexpand_abbrev, 0, 0, "",
@@ -333,38 +391,45 @@ This differs from ordinary undo in that other editing done since then\n\
 is not undone.")
   ()
 {
 is not undone.")
   ()
 {
-  int opoint = point;
+  int opoint = PT;
   int adjust = 0;
   if (last_abbrev_point < BEGV
       || last_abbrev_point > ZV)
     return Qnil;
   SET_PT (last_abbrev_point);
   int adjust = 0;
   if (last_abbrev_point < BEGV
       || last_abbrev_point > ZV)
     return Qnil;
   SET_PT (last_abbrev_point);
-  if (XTYPE (Vlast_abbrev_text) == Lisp_String)
+  if (STRINGP (Vlast_abbrev_text))
     {
       /* This isn't correct if Vlast_abbrev->function was used
          to do the expansion */
       Lisp_Object val;
     {
       /* This isn't correct if Vlast_abbrev->function was used
          to do the expansion */
       Lisp_Object val;
-      XSET (val, Lisp_String, XSYMBOL (Vlast_abbrev)->value);
-      adjust = XSTRING (val)->size;
-      del_range (point, point + adjust);
-      insert_from_string (Vlast_abbrev_text, 0,
-                         XSTRING (Vlast_abbrev_text)->size);
-      adjust -= XSTRING (Vlast_abbrev_text)->size;
+      int zv_before;
+
+      val = XSYMBOL (Vlast_abbrev)->value;
+      if (!STRINGP (val))
+       error ("value of abbrev-symbol must be a string");
+      zv_before = ZV;
+      del_range_byte (PT_BYTE, PT_BYTE + STRING_BYTES (XSTRING (val)), 1);
+      /* Don't inherit properties here; just copy from old contents.  */
+      insert_from_string (Vlast_abbrev_text, 0, 0,
+                         XSTRING (Vlast_abbrev_text)->size,
+                         STRING_BYTES (XSTRING (Vlast_abbrev_text)), 0);
       Vlast_abbrev_text = Qnil;
       Vlast_abbrev_text = Qnil;
+      /* Total number of characters deleted.  */
+      adjust = ZV - zv_before;
     }
     }
-  SET_PT (last_abbrev_point < opoint ? opoint - adjust : opoint);
+  SET_PT (last_abbrev_point < opoint ? opoint + adjust : opoint);
   return Qnil;
 }
 \f
   return Qnil;
 }
 \f
-static
+static void
 write_abbrev (sym, stream)
      Lisp_Object sym, stream;
 {
   Lisp_Object name;
 write_abbrev (sym, stream)
      Lisp_Object sym, stream;
 {
   Lisp_Object name;
-  if (NULL (XSYMBOL (sym)->value))
+  if (NILP (XSYMBOL (sym)->value))
     return;
   insert ("    (", 5);
     return;
   insert ("    (", 5);
-  XSET (name, Lisp_String, XSYMBOL (sym)->name);
+  XSETSTRING (name, XSYMBOL (sym)->name);
   Fprin1 (name, stream);
   insert (" ", 1);
   Fprin1 (XSYMBOL (sym)->value, stream);
   Fprin1 (name, stream);
   insert (" ", 1);
   Fprin1 (XSYMBOL (sym)->value, stream);
@@ -375,13 +440,13 @@ write_abbrev (sym, stream)
   insert (")\n", 2);
 }
 
   insert (")\n", 2);
 }
 
-static
+static void
 describe_abbrev (sym, stream)
      Lisp_Object sym, stream;
 {
   Lisp_Object one;
 
 describe_abbrev (sym, stream)
      Lisp_Object sym, stream;
 {
   Lisp_Object one;
 
-  if (NULL (XSYMBOL (sym)->value))
+  if (NILP (XSYMBOL (sym)->value))
     return;
   one = make_number (1);
   Fprin1 (Fsymbol_name (sym), stream);
     return;
   one = make_number (1);
   Fprin1 (Fsymbol_name (sym), stream);
@@ -389,7 +454,7 @@ describe_abbrev (sym, stream)
   Fprin1 (XSYMBOL (sym)->plist, stream);
   Findent_to (make_number (20), one);
   Fprin1 (XSYMBOL (sym)->value, stream);
   Fprin1 (XSYMBOL (sym)->plist, stream);
   Findent_to (make_number (20), one);
   Fprin1 (XSYMBOL (sym)->value, stream);
-  if (!NULL (XSYMBOL (sym)->function))
+  if (!NILP (XSYMBOL (sym)->function))
     {
       Findent_to (make_number (45), one);
       Fprin1 (XSYMBOL (sym)->function, stream);
     {
       Findent_to (make_number (45), one);
       Fprin1 (XSYMBOL (sym)->function, stream);
@@ -397,13 +462,12 @@ describe_abbrev (sym, stream)
   Fterpri (stream);
 }
 
   Fterpri (stream);
 }
 
-DEFUN ("insert-abbrev-table-description",
-  Finsert_abbrev_table_description, Sinsert_abbrev_table_description,
-  1, 2, 0,
+DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,
+  Sinsert_abbrev_table_description, 1, 2, 0,
   "Insert before point a full description of abbrev table named NAME.\n\
 NAME is a symbol whose value is an abbrev table.\n\
   "Insert before point a full description of abbrev table named NAME.\n\
 NAME is a symbol whose value is an abbrev table.\n\
-If optional 2nd arg HUMAN is non-nil, a human-readable description is inserted.\n\
-Otherwise the description is an expression,\n\
+If optional 2nd arg READABLE is non-nil, a human-readable description\n\
+is inserted.  Otherwise the description is an expression,\n\
 a call to `define-abbrev-table', which would\n\
 define the abbrev table NAME exactly as it is currently defined.")
   (name, readable)
 a call to `define-abbrev-table', which would\n\
 define the abbrev table NAME exactly as it is currently defined.")
   (name, readable)
@@ -416,9 +480,9 @@ define the abbrev table NAME exactly as it is currently defined.")
   table = Fsymbol_value (name);
   CHECK_VECTOR (table, 0);
 
   table = Fsymbol_value (name);
   CHECK_VECTOR (table, 0);
 
-  XSET (stream, Lisp_Buffer, current_buffer);
+  XSETBUFFER (stream, current_buffer);
 
 
-  if (!NULL (readable))
+  if (!NILP (readable))
     {
       insert_string ("(");
       Fprin1 (name, stream);
     {
       insert_string ("(");
       Fprin1 (name, stream);
@@ -440,41 +504,38 @@ define the abbrev table NAME exactly as it is currently defined.")
 \f
 DEFUN ("define-abbrev-table", Fdefine_abbrev_table, Sdefine_abbrev_table,
        2, 2, 0,
 \f
 DEFUN ("define-abbrev-table", Fdefine_abbrev_table, Sdefine_abbrev_table,
        2, 2, 0,
-  "Define TABNAME (a symbol) as an abbrev table name.\n\
+  "Define TABLENAME (a symbol) as an abbrev table name.\n\
 Define abbrevs in it according to DEFINITIONS, which is a list of elements\n\
 of the form (ABBREVNAME EXPANSION HOOK USECOUNT).")
 Define abbrevs in it according to DEFINITIONS, which is a list of elements\n\
 of the form (ABBREVNAME EXPANSION HOOK USECOUNT).")
-  (tabname, defns)
-     Lisp_Object tabname, defns;
+  (tablename, definitions)
+     Lisp_Object tablename, definitions;
 {
   Lisp_Object name, exp, hook, count;
   Lisp_Object table, elt;
 
 {
   Lisp_Object name, exp, hook, count;
   Lisp_Object table, elt;
 
-  CHECK_SYMBOL (tabname, 0);
-  table = Fboundp (tabname);
-  if (NULL (table) || (table = Fsymbol_value (tabname), NULL (table)))
+  CHECK_SYMBOL (tablename, 0);
+  table = Fboundp (tablename);
+  if (NILP (table) || (table = Fsymbol_value (tablename), NILP (table)))
     {
       table = Fmake_abbrev_table ();
     {
       table = Fmake_abbrev_table ();
-      Fset (tabname, table);
-      Vabbrev_table_name_list =
-       Fcons (tabname, Vabbrev_table_name_list);
+      Fset (tablename, table);
+      Vabbrev_table_name_list = Fcons (tablename, Vabbrev_table_name_list);
     }
   CHECK_VECTOR (table, 0);
 
     }
   CHECK_VECTOR (table, 0);
 
-  for (;!NULL (defns); defns = Fcdr (defns))
+  for (; !NILP (definitions); definitions = Fcdr (definitions))
     {
     {
-      elt = Fcar (defns);
-      name = Fcar (elt);
-      elt = Fcdr (elt);
-      exp = Fcar (elt);
-      elt = Fcdr (elt);
-      hook = Fcar (elt);
-      elt = Fcdr (elt);
+      elt = Fcar (definitions);
+      name  = Fcar (elt);      elt = Fcdr (elt);
+      exp   = Fcar (elt);      elt = Fcdr (elt);
+      hook  = Fcar (elt);      elt = Fcdr (elt);
       count = Fcar (elt);
       Fdefine_abbrev (table, name, exp, hook, count);
     }
   return Qnil;
 }
 \f
       count = Fcar (elt);
       Fdefine_abbrev (table, name, exp, hook, count);
     }
   return Qnil;
 }
 \f
+void
 syms_of_abbrev ()
 {
   DEFVAR_LISP ("abbrev-table-name-list", &Vabbrev_table_name_list,
 syms_of_abbrev ()
 {
   DEFVAR_LISP ("abbrev-table-name-list", &Vabbrev_table_name_list,
@@ -520,7 +581,7 @@ Calling `expand-abbrev' sets this to nil.");
 Trying to expand an abbrev in any other buffer clears `abbrev-start-location'.");
   Vabbrev_start_location_buffer = Qnil;
 
 Trying to expand an abbrev in any other buffer clears `abbrev-start-location'.");
   Vabbrev_start_location_buffer = Qnil;
 
-  DEFVAR_PER_BUFFER ("local-abbrev-table", &current_buffer->abbrev_table,
+  DEFVAR_PER_BUFFER ("local-abbrev-table", &current_buffer->abbrev_table, Qnil,
     "Local (mode-specific) abbrev table of current buffer.");
 
   DEFVAR_BOOL ("abbrevs-changed", &abbrevs_changed,
     "Local (mode-specific) abbrev table of current buffer.");
 
   DEFVAR_BOOL ("abbrevs-changed", &abbrevs_changed,
@@ -532,6 +593,14 @@ This causes `save-some-buffers' to offer to save the abbrevs.");
     "*Set non-nil means expand multi-word abbrevs all caps if abbrev was so.");
   abbrev_all_caps = 0;
 
     "*Set non-nil means expand multi-word abbrevs all caps if abbrev was so.");
   abbrev_all_caps = 0;
 
+  DEFVAR_LISP ("pre-abbrev-expand-hook", &Vpre_abbrev_expand_hook,
+    "Function or functions to be called before abbrev expansion is done.\n\
+This is the first thing that `expand-abbrev' does, and so this may change\n\
+the current abbrev table before abbrev lookup happens.");
+  Vpre_abbrev_expand_hook = Qnil;
+  Qpre_abbrev_expand_hook = intern ("pre-abbrev-expand-hook");
+  staticpro (&Qpre_abbrev_expand_hook);
+
   defsubr (&Smake_abbrev_table);
   defsubr (&Sclear_abbrev_table);
   defsubr (&Sdefine_abbrev);
   defsubr (&Smake_abbrev_table);
   defsubr (&Sclear_abbrev_table);
   defsubr (&Sdefine_abbrev);