Fix glitch in scrolling_window (backport from trunk).
[bpt/emacs.git] / src / data.c
index 9796b64..79ae01f 100644 (file)
@@ -1,13 +1,14 @@
 /* Primitive operations on Lisp data types for GNU Emacs Lisp interpreter.
    Copyright (C) 1985, 1986, 1988, 1993, 1994, 1995, 1997, 1998, 1999, 2000,
-                 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+                 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+                 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+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 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,22 +16,22 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 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
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
 #include <config.h>
 #include <signal.h>
 #include <stdio.h>
+#include <setjmp.h>
 #include "lisp.h"
 #include "puresize.h"
-#include "charset.h"
+#include "character.h"
 #include "buffer.h"
 #include "keyboard.h"
 #include "frame.h"
 #include "syssignal.h"
 #include "termhooks.h"  /* For FRAME_KBOARD reference in y-or-n-p. */
+#include "font.h"
 
 #ifdef STDC_HEADERS
 #include <float.h>
@@ -46,16 +47,6 @@ Boston, MA 02110-1301, USA.  */
 #endif
 #endif
 
-/* Work around a problem that happens because math.h on hpux 7
-   defines two static variables--which, in Emacs, are not really static,
-   because `static' is defined as nothing.  The problem is that they are
-   here, in floatfns.c, and in lread.c.
-   These macros prevent the name conflict.  */
-#if defined (HPUX) && !defined (HPUX8)
-#define _MAXLDBL data_c_maxldbl
-#define _NMAXLDBL data_c_nmaxldbl
-#endif
-
 #include <math.h>
 
 #if !defined (atof)
@@ -96,6 +87,9 @@ Lisp_Object Qprocess;
 static Lisp_Object Qcompiled_function, Qbuffer, Qframe, Qvector;
 static Lisp_Object Qchar_table, Qbool_vector, Qhash_table;
 static Lisp_Object Qsubrp, Qmany, Qunevalled;
+Lisp_Object Qfont_spec, Qfont_entity, Qfont_object;
+
+Lisp_Object Qinteractive_form;
 
 static Lisp_Object swap_in_symval_forwarding P_ ((Lisp_Object, Lisp_Object));
 
@@ -114,10 +108,12 @@ Lisp_Object
 wrong_type_argument (predicate, value)
      register Lisp_Object predicate, value;
 {
-  /* If VALUE is not even a valid Lisp object, abort here
-     where we can get a backtrace showing where it came from.  */
-  if ((unsigned int) XGCTYPE (value) >= Lisp_Type_Limit)
-    abort ();
+  /* If VALUE is not even a valid Lisp object, we'd want to abort here
+     where we can get a backtrace showing where it came from.  We used
+     to try and do that by checking the tagbits, but nowadays all
+     tagbits are potentially valid.  */
+  /* if ((unsigned int) XTYPE (value) >= Lisp_Type_Limit)
+   *   abort (); */
 
   xsignal2 (Qwrong_type_argument, predicate, value);
 }
@@ -188,9 +184,9 @@ for example, (type-of 1) returns `integer'.  */)
      (object)
      Lisp_Object object;
 {
-  switch (XGCTYPE (object))
+  switch (XTYPE (object))
     {
-    case Lisp_Int:
+    case_Lisp_Int:
       return Qinteger;
 
     case Lisp_Symbol:
@@ -215,26 +211,32 @@ for example, (type-of 1) returns `integer'.  */)
       abort ();
 
     case Lisp_Vectorlike:
-      if (GC_WINDOW_CONFIGURATIONP (object))
+      if (WINDOW_CONFIGURATIONP (object))
        return Qwindow_configuration;
-      if (GC_PROCESSP (object))
+      if (PROCESSP (object))
        return Qprocess;
-      if (GC_WINDOWP (object))
+      if (WINDOWP (object))
        return Qwindow;
-      if (GC_SUBRP (object))
+      if (SUBRP (object))
        return Qsubr;
-      if (GC_COMPILEDP (object))
+      if (COMPILEDP (object))
        return Qcompiled_function;
-      if (GC_BUFFERP (object))
+      if (BUFFERP (object))
        return Qbuffer;
-      if (GC_CHAR_TABLE_P (object))
+      if (CHAR_TABLE_P (object))
        return Qchar_table;
-      if (GC_BOOL_VECTOR_P (object))
+      if (BOOL_VECTOR_P (object))
        return Qbool_vector;
-      if (GC_FRAMEP (object))
+      if (FRAMEP (object))
        return Qframe;
-      if (GC_HASH_TABLE_P (object))
+      if (HASH_TABLE_P (object))
        return Qhash_table;
+      if (FONT_SPEC_P (object))
+       return Qfont_spec;
+      if (FONT_ENTITY_P (object))
+       return Qfont_entity;
+      if (FONT_OBJECT_P (object))
+       return Qfont_object;
       return Qvector;
 
     case Lisp_Float:
@@ -436,11 +438,11 @@ DEFUN ("byte-code-function-p", Fbyte_code_function_p, Sbyte_code_function_p,
 }
 
 DEFUN ("char-or-string-p", Fchar_or_string_p, Schar_or_string_p, 1, 1, 0,
-       doc: /* Return t if OBJECT is a character (an integer) or a string.  */)
+       doc: /* Return t if OBJECT is a character or a string.  */)
      (object)
      register Lisp_Object object;
 {
-  if (INTEGERP (object) || STRINGP (object))
+  if (CHARACTERP (object) || STRINGP (object))
     return Qt;
   return Qnil;
 }
@@ -768,7 +770,7 @@ Value, if non-nil, is a list \(interactive SPEC).  */)
   fun = cmd;
   while (SYMBOLP (fun))
     {
-      Lisp_Object tmp = Fget (fun, intern ("interactive-form"));
+      Lisp_Object tmp = Fget (fun, Qinteractive_form);
       if (!NILP (tmp))
        return tmp;
       else
@@ -814,25 +816,29 @@ Value, if non-nil, is a list \(interactive SPEC).  */)
    `cyclic-variable-indirection' if SYMBOL's chain of variable
    indirections contains a loop.  */
 
-Lisp_Object
+struct Lisp_Symbol *
 indirect_variable (symbol)
-     Lisp_Object symbol;
+     struct Lisp_Symbol *symbol;
 {
-  Lisp_Object tortoise, hare;
+  struct Lisp_Symbol *tortoise, *hare;
 
   hare = tortoise = symbol;
 
-  while (XSYMBOL (hare)->indirect_variable)
+  while (hare->indirect_variable)
     {
-      hare = XSYMBOL (hare)->value;
-      if (!XSYMBOL (hare)->indirect_variable)
+      hare = XSYMBOL (hare->value);
+      if (!hare->indirect_variable)
        break;
 
-      hare = XSYMBOL (hare)->value;
-      tortoise = XSYMBOL (tortoise)->value;
+      hare = XSYMBOL (hare->value);
+      tortoise = XSYMBOL (tortoise->value);
 
-      if (EQ (hare, tortoise))
-       xsignal1 (Qcyclic_variable_indirection, symbol);
+      if (hare == tortoise)
+       {
+         Lisp_Object tem;
+         XSETSYMBOL (tem, symbol);
+         xsignal1 (Qcyclic_variable_indirection, tem);
+       }
     }
 
   return hare;
@@ -849,7 +855,7 @@ variable chain of symbols.  */)
      Lisp_Object object;
 {
   if (SYMBOLP (object))
-    object = indirect_variable (object);
+    XSETSYMBOL (object,  indirect_variable (XSYMBOL (object)));
   return object;
 }
 
@@ -864,7 +870,6 @@ do_symval_forwarding (valcontents)
      register Lisp_Object valcontents;
 {
   register Lisp_Object val;
-  int offset;
   if (MISCP (valcontents))
     switch (XMISCTYPE (valcontents))
       {
@@ -879,11 +884,10 @@ do_symval_forwarding (valcontents)
        return *XOBJFWD (valcontents)->objvar;
 
       case Lisp_Misc_Buffer_Objfwd:
-       offset = XBUFFER_OBJFWD (valcontents)->offset;
-       return PER_BUFFER_VALUE (current_buffer, offset);
+       return PER_BUFFER_VALUE (current_buffer,
+                                XBUFFER_OBJFWD (valcontents)->offset);
 
       case Lisp_Misc_Kboard_Objfwd:
-       offset = XKBOARD_OBJFWD (valcontents)->offset;
         /* We used to simply use current_kboard here, but from Lisp
            code, it's value is often unexpected.  It seems nicer to
            allow constructions like this to work as intuitively expected:
@@ -895,7 +899,8 @@ do_symval_forwarding (valcontents)
            last-command and real-last-command, and people may rely on
            that.  I took a quick look at the Lisp codebase, and I
            don't think anything will break.  --lorentey  */
-       return *(Lisp_Object *)(offset + (char *)FRAME_KBOARD (SELECTED_FRAME ()));
+       return *(Lisp_Object *)(XKBOARD_OBJFWD (valcontents)->offset
+                               + (char *)FRAME_KBOARD (SELECTED_FRAME ()));
       }
   return valcontents;
 }
@@ -922,13 +927,15 @@ store_symval_forwarding (symbol, valcontents, newval, buf)
        case Lisp_Misc_Intfwd:
          CHECK_NUMBER (newval);
          *XINTFWD (valcontents)->intvar = XINT (newval);
-         if (*XINTFWD (valcontents)->intvar != XINT (newval))
-           error ("Value out of range for variable `%s'",
-                  SDATA (SYMBOL_NAME (symbol)));
+         /* This can never happen since intvar points to an EMACS_INT
+            which is at least large enough to hold a Lisp_Object.
+             if (*XINTFWD (valcontents)->intvar != XINT (newval))
+              error ("Value out of range for variable `%s'",
+                  SDATA (SYMBOL_NAME (symbol))); */
          break;
 
        case Lisp_Misc_Boolfwd:
-         *XBOOLFWD (valcontents)->boolvar = NILP (newval) ? 0 : 1;
+         *XBOOLFWD (valcontents)->boolvar = !NILP (newval);
          break;
 
        case Lisp_Misc_Objfwd:
@@ -968,12 +975,13 @@ store_symval_forwarding (symbol, valcontents, newval, buf)
        case Lisp_Misc_Buffer_Objfwd:
          {
            int offset = XBUFFER_OBJFWD (valcontents)->offset;
-           Lisp_Object type;
+           Lisp_Object type = XBUFFER_OBJFWD (valcontents)->slottype;
 
-           type = PER_BUFFER_TYPE (offset);
-           if (! NILP (type) && ! NILP (newval)
-               && XTYPE (newval) != XINT (type))
-             buffer_slot_type_mismatch (offset);
+           if (!(NILP (type) || NILP (newval)
+                 || (XINT (type) == LISP_INT_TAG
+                     ? INTEGERP (newval)
+                     : XTYPE (newval) == XINT (type))))
+             buffer_slot_type_mismatch (newval, XINT (type));
 
            if (buf == NULL)
              buf = current_buffer;
@@ -1011,26 +1019,23 @@ void
 swap_in_global_binding (symbol)
      Lisp_Object symbol;
 {
-  Lisp_Object valcontents, cdr;
-
-  valcontents = SYMBOL_VALUE (symbol);
-  if (!BUFFER_LOCAL_VALUEP (valcontents))
-    abort ();
-  cdr = XBUFFER_LOCAL_VALUE (valcontents)->cdr;
+  Lisp_Object valcontents = SYMBOL_VALUE (symbol);
+  struct Lisp_Buffer_Local_Value *blv = XBUFFER_LOCAL_VALUE (valcontents);
+  Lisp_Object cdr = blv->cdr;
 
   /* Unload the previously loaded binding.  */
   Fsetcdr (XCAR (cdr),
-          do_symval_forwarding (XBUFFER_LOCAL_VALUE (valcontents)->realvalue));
+          do_symval_forwarding (blv->realvalue));
 
   /* Select the global binding in the symbol.  */
   XSETCAR (cdr, cdr);
-  store_symval_forwarding (symbol, valcontents, XCDR (cdr), NULL);
+  store_symval_forwarding (symbol, blv->realvalue, XCDR (cdr), NULL);
 
   /* Indicate that the global binding is set up now.  */
-  XBUFFER_LOCAL_VALUE (valcontents)->frame = Qnil;
-  XBUFFER_LOCAL_VALUE (valcontents)->buffer = Qnil;
-  XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame = 0;
-  XBUFFER_LOCAL_VALUE (valcontents)->found_for_buffer = 0;
+  blv->frame = Qnil;
+  blv->buffer = Qnil;
+  blv->found_for_frame = 0;
+  blv->found_for_buffer = 0;
 }
 
 /* Set up the buffer-local symbol SYMBOL for validity in the current buffer.
@@ -1053,8 +1058,12 @@ swap_in_symval_forwarding (symbol, valcontents)
       || (XBUFFER_LOCAL_VALUE (valcontents)->check_frame
          && ! EQ (selected_frame, XBUFFER_LOCAL_VALUE (valcontents)->frame)))
     {
-      if (XSYMBOL (symbol)->indirect_variable)
-       symbol = indirect_variable (symbol);
+      struct Lisp_Symbol *sym = XSYMBOL (symbol);
+      if (sym->indirect_variable)
+       {
+         sym = indirect_variable (sym);
+         XSETSYMBOL (symbol, sym);
+       }
 
       /* Unload the previously loaded binding.  */
       tem1 = XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr);
@@ -1106,31 +1115,7 @@ find_symbol_value (symbol)
   if (BUFFER_LOCAL_VALUEP (valcontents))
     valcontents = swap_in_symval_forwarding (symbol, valcontents);
 
-  if (MISCP (valcontents))
-    {
-      switch (XMISCTYPE (valcontents))
-       {
-       case Lisp_Misc_Intfwd:
-         XSETINT (val, *XINTFWD (valcontents)->intvar);
-         return val;
-
-       case Lisp_Misc_Boolfwd:
-         return (*XBOOLFWD (valcontents)->boolvar ? Qt : Qnil);
-
-       case Lisp_Misc_Objfwd:
-         return *XOBJFWD (valcontents)->objvar;
-
-       case Lisp_Misc_Buffer_Objfwd:
-         return PER_BUFFER_VALUE (current_buffer,
-                                    XBUFFER_OBJFWD (valcontents)->offset);
-
-       case Lisp_Misc_Kboard_Objfwd:
-         return *(Lisp_Object *)(XKBOARD_OBJFWD (valcontents)->offset
-                                 + (char *)FRAME_KBOARD (SELECTED_FRAME ()));
-       }
-    }
-
-  return valcontents;
+  return do_symval_forwarding (valcontents);
 }
 
 DEFUN ("symbol-value", Fsymbol_value, Ssymbol_value, 1, 1, 0,
@@ -1160,7 +1145,7 @@ DEFUN ("set", Fset, Sset, 2, 2, 0,
 
 static int
 let_shadows_buffer_binding_p (symbol)
-     Lisp_Object symbol;
+     struct Lisp_Symbol *symbol;
 {
   volatile struct specbinding *p;
 
@@ -1168,10 +1153,10 @@ let_shadows_buffer_binding_p (symbol)
     if (p->func == NULL
        && CONSP (p->symbol))
       {
-       Lisp_Object let_bound_symbol = XCAR (p->symbol);
-       if ((EQ (symbol, let_bound_symbol)
-            || (XSYMBOL (let_bound_symbol)->indirect_variable
-                && EQ (symbol, indirect_variable (let_bound_symbol))))
+       struct Lisp_Symbol *let_bound_symbol = XSYMBOL (XCAR (p->symbol));
+       if ((symbol == let_bound_symbol
+            || (let_bound_symbol->indirect_variable
+                && symbol == indirect_variable (let_bound_symbol)))
            && XBUFFER (XCDR (XCDR (p->symbol))) == current_buffer)
          break;
       }
@@ -1218,14 +1203,14 @@ set_internal (symbol, newval, buf, bindflag)
       int idx = PER_BUFFER_IDX (offset);
       if (idx > 0
          && !bindflag
-         && !let_shadows_buffer_binding_p (symbol))
+         && !let_shadows_buffer_binding_p (XSYMBOL (symbol)))
        SET_PER_BUFFER_VALUE_P (buf, idx, 1);
     }
   else if (BUFFER_LOCAL_VALUEP (valcontents))
     {
       /* valcontents is a struct Lisp_Buffer_Local_Value.   */
       if (XSYMBOL (symbol)->indirect_variable)
-       symbol = indirect_variable (symbol);
+       XSETSYMBOL (symbol, indirect_variable (XSYMBOL (symbol)));
 
       /* What binding is loaded right now?  */
       current_alist_element
@@ -1240,9 +1225,9 @@ set_internal (symbol, newval, buf, bindflag)
          || buf != XBUFFER (XBUFFER_LOCAL_VALUE (valcontents)->buffer)
          || (XBUFFER_LOCAL_VALUE (valcontents)->check_frame
              && !EQ (selected_frame, XBUFFER_LOCAL_VALUE (valcontents)->frame))
-         || (BUFFER_LOCAL_VALUEP (valcontents)
-             && EQ (XCAR (current_alist_element),
-                    current_alist_element)))
+         /* Also unload a global binding (if the var is local_if_set). */
+         || (EQ (XCAR (current_alist_element),
+                 current_alist_element)))
        {
          /* The currently loaded binding is not necessarily valid.
             We need to unload it, and choose a new binding.  */
@@ -1260,14 +1245,14 @@ set_internal (symbol, newval, buf, bindflag)
            {
              /* This buffer still sees the default value.  */
 
-             /* If the variable is a Lisp_Some_Buffer_Local_Value,
+             /* If the variable is not local_if_set,
                 or if this is `let' rather than `set',
                 make CURRENT-ALIST-ELEMENT point to itself,
                 indicating that we're seeing the default value.
                 Likewise if the variable has been let-bound
                 in the current buffer.  */
              if (bindflag || !XBUFFER_LOCAL_VALUE (valcontents)->local_if_set
-                 || let_shadows_buffer_binding_p (symbol))
+                 || let_shadows_buffer_binding_p (XSYMBOL (symbol)))
                {
                  XBUFFER_LOCAL_VALUE (valcontents)->found_for_buffer = 0;
 
@@ -1301,6 +1286,9 @@ set_internal (symbol, newval, buf, bindflag)
          XBUFFER_LOCAL_VALUE (valcontents)->frame = selected_frame;
        }
       innercontents = XBUFFER_LOCAL_VALUE (valcontents)->realvalue;
+
+      /* Store the new value in the cons-cell.  */
+      XSETCDR (XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr), newval);
     }
 
   /* If storing void (making the symbol void), forward only through
@@ -1310,24 +1298,6 @@ set_internal (symbol, newval, buf, bindflag)
   else
     store_symval_forwarding (symbol, innercontents, newval, buf);
 
-  /* If we just set a variable whose current binding is frame-local,
-     store the new value in the frame parameter too.  */
-
-  if (BUFFER_LOCAL_VALUEP (valcontents))
-    {
-      /* What binding is loaded right now?  */
-      current_alist_element
-       = XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr);
-
-      /* If the current buffer is not the buffer whose binding is
-        loaded, or if there may be frame-local bindings and the frame
-        isn't the right one, or if it's a Lisp_Buffer_Local_Value and
-        the default binding is loaded, the loaded binding may be the
-        wrong one.  */
-      if (XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame)
-       XSETCDR (current_alist_element, newval);
-    }
-
   return newval;
 }
 \f
@@ -1432,7 +1402,7 @@ for this variable.  */)
        {
          struct buffer *b;
 
-         for (b = all_buffers; b; b = b->next)
+         for (b = all_buffers; b; b = b->header.next.buffer)
            if (!PER_BUFFER_VALUE_P (b, idx))
              PER_BUFFER_VALUE (b, offset) = value;
        }
@@ -1516,34 +1486,39 @@ The function `default-value' gets the default value and `set-default' sets it.
      register Lisp_Object variable;
 {
   register Lisp_Object tem, valcontents, newval;
+  struct Lisp_Symbol *sym;
 
   CHECK_SYMBOL (variable);
-  variable = indirect_variable (variable);
+  sym = indirect_variable (XSYMBOL (variable));
 
-  valcontents = SYMBOL_VALUE (variable);
-  if (XSYMBOL (variable)->constant || KBOARD_OBJFWDP (valcontents))
-    error ("Symbol %s may not be buffer-local", SDATA (SYMBOL_NAME (variable)));
+  valcontents = sym->value;
+  if (sym->constant || KBOARD_OBJFWDP (valcontents))
+    error ("Symbol %s may not be buffer-local", SDATA (sym->xname));
 
   if (BUFFER_OBJFWDP (valcontents))
     return variable;
   else if (BUFFER_LOCAL_VALUEP (valcontents))
-    newval = valcontents;
+    {
+      if (XBUFFER_LOCAL_VALUE (valcontents)->check_frame)
+       error ("Symbol %s may not be buffer-local", SDATA (sym->xname));
+      newval = valcontents;
+    }
   else
     {
       if (EQ (valcontents, Qunbound))
-       SET_SYMBOL_VALUE (variable, Qnil);
+       sym->value = Qnil;
       tem = Fcons (Qnil, Fsymbol_value (variable));
       XSETCAR (tem, tem);
       newval = allocate_misc ();
       XMISCTYPE (newval) = Lisp_Misc_Buffer_Local_Value;
-      XBUFFER_LOCAL_VALUE (newval)->realvalue = SYMBOL_VALUE (variable);
+      XBUFFER_LOCAL_VALUE (newval)->realvalue = sym->value;
       XBUFFER_LOCAL_VALUE (newval)->buffer = Fcurrent_buffer ();
       XBUFFER_LOCAL_VALUE (newval)->frame = Qnil;
       XBUFFER_LOCAL_VALUE (newval)->found_for_buffer = 0;
       XBUFFER_LOCAL_VALUE (newval)->found_for_frame = 0;
       XBUFFER_LOCAL_VALUE (newval)->check_frame = 0;
       XBUFFER_LOCAL_VALUE (newval)->cdr = tem;
-      SET_SYMBOL_VALUE (variable, newval);
+      sym->value = newval;
     }
   XBUFFER_LOCAL_VALUE (newval)->local_if_set = 1;
   return variable;
@@ -1573,13 +1548,16 @@ Instead, use `add-hook' and specify t for the LOCAL argument.  */)
      register Lisp_Object variable;
 {
   register Lisp_Object tem, valcontents;
+  struct Lisp_Symbol *sym;
 
   CHECK_SYMBOL (variable);
-  variable = indirect_variable (variable);
+  sym = indirect_variable (XSYMBOL (variable));
 
-  valcontents = SYMBOL_VALUE (variable);
-  if (XSYMBOL (variable)->constant || KBOARD_OBJFWDP (valcontents))
-    error ("Symbol %s may not be buffer-local", SDATA (SYMBOL_NAME (variable)));
+  valcontents = sym->value;
+  if (sym->constant || KBOARD_OBJFWDP (valcontents)
+      || (BUFFER_LOCAL_VALUEP (valcontents)
+         && (XBUFFER_LOCAL_VALUE (valcontents)->check_frame)))
+    error ("Symbol %s may not be buffer-local", SDATA (sym->xname));
 
   if ((BUFFER_LOCAL_VALUEP (valcontents)
        && XBUFFER_LOCAL_VALUE (valcontents)->local_if_set)
@@ -1600,7 +1578,7 @@ Instead, use `add-hook' and specify t for the LOCAL argument.  */)
       XSETCAR (tem, tem);
       newval = allocate_misc ();
       XMISCTYPE (newval) = Lisp_Misc_Buffer_Local_Value;
-      XBUFFER_LOCAL_VALUE (newval)->realvalue = SYMBOL_VALUE (variable);
+      XBUFFER_LOCAL_VALUE (newval)->realvalue = sym->value;
       XBUFFER_LOCAL_VALUE (newval)->buffer = Qnil;
       XBUFFER_LOCAL_VALUE (newval)->frame = Qnil;
       XBUFFER_LOCAL_VALUE (newval)->local_if_set = 0;
@@ -1608,9 +1586,10 @@ Instead, use `add-hook' and specify t for the LOCAL argument.  */)
       XBUFFER_LOCAL_VALUE (newval)->found_for_frame = 0;
       XBUFFER_LOCAL_VALUE (newval)->check_frame = 0;
       XBUFFER_LOCAL_VALUE (newval)->cdr = tem;
-      SET_SYMBOL_VALUE (variable, newval);
+      sym->value = newval;
     }
   /* Make sure this buffer has its own value of symbol.  */
+  XSETSYMBOL (variable, sym);  /* Propagate variable indirections.  */
   tem = Fassq (variable, current_buffer->local_var_alist);
   if (NILP (tem))
     {
@@ -1620,7 +1599,7 @@ Instead, use `add-hook' and specify t for the LOCAL argument.  */)
       find_symbol_value (variable);
 
       current_buffer->local_var_alist
-        = Fcons (Fcons (variable, XCDR (XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (variable))->cdr)),
+        = Fcons (Fcons (variable, XCDR (XBUFFER_LOCAL_VALUE (sym->value)->cdr)),
                 current_buffer->local_var_alist);
 
       /* Make sure symbol does not think it is set up for this buffer;
@@ -1628,7 +1607,7 @@ Instead, use `add-hook' and specify t for the LOCAL argument.  */)
       {
        Lisp_Object *pvalbuf;
 
-       valcontents = SYMBOL_VALUE (variable);
+       valcontents = sym->value;
 
        pvalbuf = &XBUFFER_LOCAL_VALUE (valcontents)->buffer;
        if (current_buffer == XBUFFER (*pvalbuf))
@@ -1641,9 +1620,9 @@ Instead, use `add-hook' and specify t for the LOCAL argument.  */)
      for this buffer now.  If C code modifies the variable before we
      load the binding in, then that new value will clobber the default
      binding the next time we unload it.  */
-  valcontents = XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (variable))->realvalue;
+  valcontents = XBUFFER_LOCAL_VALUE (sym->value)->realvalue;
   if (INTFWDP (valcontents) || BOOLFWDP (valcontents) || OBJFWDP (valcontents))
-    swap_in_symval_forwarding (variable, SYMBOL_VALUE (variable));
+    swap_in_symval_forwarding (variable, sym->value);
 
   return variable;
 }
@@ -1656,11 +1635,12 @@ From now on the default value will apply in this buffer.  Return VARIABLE.  */)
      register Lisp_Object variable;
 {
   register Lisp_Object tem, valcontents;
+  struct Lisp_Symbol *sym;
 
   CHECK_SYMBOL (variable);
-  variable = indirect_variable (variable);
+  sym = indirect_variable (XSYMBOL (variable));
 
-  valcontents = SYMBOL_VALUE (variable);
+  valcontents = sym->value;
 
   if (BUFFER_OBJFWDP (valcontents))
     {
@@ -1680,7 +1660,7 @@ From now on the default value will apply in this buffer.  Return VARIABLE.  */)
     return variable;
 
   /* Get rid of this buffer's alist element, if any.  */
-
+  XSETSYMBOL (variable, sym);  /* Propagate variable indirection.  */
   tem = Fassq (variable, current_buffer->local_var_alist);
   if (!NILP (tem))
     current_buffer->local_var_alist
@@ -1691,7 +1671,7 @@ From now on the default value will apply in this buffer.  Return VARIABLE.  */)
      forwarded objects won't work right.  */
   {
     Lisp_Object *pvalbuf, buf;
-    valcontents = SYMBOL_VALUE (variable);
+    valcontents = sym->value;
     pvalbuf = &XBUFFER_LOCAL_VALUE (valcontents)->buffer;
     XSETBUFFER (buf, current_buffer);
     if (EQ (buf, *pvalbuf))
@@ -1707,6 +1687,9 @@ From now on the default value will apply in this buffer.  Return VARIABLE.  */)
 
 /* Lisp functions for creating and removing buffer-local variables.  */
 
+/* Obsolete since 22.2.  NB adjust doc of modify-frame-parameters
+   when/if this is removed.  */
+
 DEFUN ("make-variable-frame-local", Fmake_variable_frame_local, Smake_variable_frame_local,
        1, 1, "vMake Variable Frame Local: ",
        doc: /* Enable VARIABLE to have frame-local bindings.
@@ -1723,33 +1706,37 @@ The only way to create a frame-local binding for VARIABLE in a frame
 is to set the VARIABLE frame parameter of that frame.  See
 `modify-frame-parameters' for how to set frame parameters.
 
-Buffer-local bindings take precedence over frame-local bindings.  */)
+Note that since Emacs 23.1, variables cannot be both buffer-local and
+frame-local any more (buffer-local bindings used to take precedence over
+frame-local bindings).  */)
      (variable)
      register Lisp_Object variable;
 {
   register Lisp_Object tem, valcontents, newval;
+  struct Lisp_Symbol *sym;
 
   CHECK_SYMBOL (variable);
-  variable = indirect_variable (variable);
+  sym = indirect_variable (XSYMBOL (variable));
 
-  valcontents = SYMBOL_VALUE (variable);
-  if (XSYMBOL (variable)->constant || KBOARD_OBJFWDP (valcontents)
+  valcontents = sym->value;
+  if (sym->constant || KBOARD_OBJFWDP (valcontents)
       || BUFFER_OBJFWDP (valcontents))
-    error ("Symbol %s may not be frame-local", SDATA (SYMBOL_NAME (variable)));
+    error ("Symbol %s may not be frame-local", SDATA (sym->xname));
 
   if (BUFFER_LOCAL_VALUEP (valcontents))
     {
-      XBUFFER_LOCAL_VALUE (valcontents)->check_frame = 1;
+      if (!XBUFFER_LOCAL_VALUE (valcontents)->check_frame)
+       error ("Symbol %s may not be frame-local", SDATA (sym->xname));
       return variable;
     }
 
   if (EQ (valcontents, Qunbound))
-    SET_SYMBOL_VALUE (variable, Qnil);
+    sym->value = Qnil;
   tem = Fcons (Qnil, Fsymbol_value (variable));
   XSETCAR (tem, tem);
   newval = allocate_misc ();
   XMISCTYPE (newval) = Lisp_Misc_Buffer_Local_Value;
-  XBUFFER_LOCAL_VALUE (newval)->realvalue = SYMBOL_VALUE (variable);
+  XBUFFER_LOCAL_VALUE (newval)->realvalue = sym->value;
   XBUFFER_LOCAL_VALUE (newval)->buffer = Qnil;
   XBUFFER_LOCAL_VALUE (newval)->frame = Qnil;
   XBUFFER_LOCAL_VALUE (newval)->local_if_set = 0;
@@ -1757,7 +1744,7 @@ Buffer-local bindings take precedence over frame-local bindings.  */)
   XBUFFER_LOCAL_VALUE (newval)->found_for_frame = 0;
   XBUFFER_LOCAL_VALUE (newval)->check_frame = 1;
   XBUFFER_LOCAL_VALUE (newval)->cdr = tem;
-  SET_SYMBOL_VALUE (variable, newval);
+  sym->value = newval;
   return variable;
 }
 
@@ -1770,6 +1757,7 @@ BUFFER defaults to the current buffer.  */)
 {
   Lisp_Object valcontents;
   register struct buffer *buf;
+  struct Lisp_Symbol *sym;
 
   if (NILP (buffer))
     buf = current_buffer;
@@ -1780,9 +1768,10 @@ BUFFER defaults to the current buffer.  */)
     }
 
   CHECK_SYMBOL (variable);
-  variable = indirect_variable (variable);
+  sym = indirect_variable (XSYMBOL (variable));
+  XSETSYMBOL (variable, sym);
 
-  valcontents = SYMBOL_VALUE (variable);
+  valcontents = sym->value;
   if (BUFFER_LOCAL_VALUEP (valcontents))
     {
       Lisp_Object tail, elt;
@@ -1817,6 +1806,7 @@ BUFFER defaults to the current buffer.  */)
 {
   Lisp_Object valcontents;
   register struct buffer *buf;
+  struct Lisp_Symbol *sym;
 
   if (NILP (buffer))
     buf = current_buffer;
@@ -1827,9 +1817,10 @@ BUFFER defaults to the current buffer.  */)
     }
 
   CHECK_SYMBOL (variable);
-  variable = indirect_variable (variable);
+  sym = indirect_variable (XSYMBOL (variable));
+  XSETSYMBOL (variable, sym);
 
-  valcontents = SYMBOL_VALUE (variable);
+  valcontents = sym->value;
 
   if (BUFFER_OBJFWDP (valcontents))
     /* All these slots become local if they are set.  */
@@ -1859,14 +1850,15 @@ If the current binding is global (the default), the value is nil.  */)
      register Lisp_Object variable;
 {
   Lisp_Object valcontents;
+  struct Lisp_Symbol *sym;
 
   CHECK_SYMBOL (variable);
-  variable = indirect_variable (variable);
+  sym = indirect_variable (XSYMBOL (variable));
 
   /* Make sure the current binding is actually swapped in.  */
   find_symbol_value (variable);
 
-  valcontents = XSYMBOL (variable)->value;
+  valcontents = sym->value;
 
   if (BUFFER_LOCAL_VALUEP (valcontents)
       || BUFFER_OBJFWDP (valcontents))
@@ -1893,7 +1885,7 @@ DEFUN ("terminal-local-value", Fterminal_local_value, Sterminal_local_value, 2,
 If SYMBOL is not a terminal-local variable, then return its normal
 value, like `symbol-value'.
 
-TERMINAL may be a terminal id, a frame, or nil (meaning the
+TERMINAL may be a terminal object, a frame, or nil (meaning the
 selected frame's terminal device).  */)
   (symbol, terminal)
      Lisp_Object symbol;
@@ -1912,7 +1904,7 @@ DEFUN ("set-terminal-local-value", Fset_terminal_local_value, Sset_terminal_loca
 If VARIABLE is not a terminal-local variable, then set its normal
 binding, like `set'.
 
-TERMINAL may be a terminal id, a frame, or nil (meaning the
+TERMINAL may be a terminal object, a frame, or nil (meaning the
 selected frame's terminal device).  */)
   (symbol, terminal, value)
      Lisp_Object symbol;
@@ -2015,8 +2007,7 @@ or a byte-code object.  IDX starts at 0.  */)
        return make_number ((unsigned char) SREF (array, idxval));
       idxval_byte = string_char_to_byte (array, idxval);
 
-      c = STRING_CHAR (SDATA (array) + idxval_byte,
-                      SBYTES (array) - idxval_byte);
+      c = STRING_CHAR (SDATA (array) + idxval_byte);
       return make_number (c);
     }
   else if (BOOL_VECTOR_P (array))
@@ -2031,104 +2022,16 @@ or a byte-code object.  IDX starts at 0.  */)
     }
   else if (CHAR_TABLE_P (array))
     {
-      Lisp_Object val;
-
-      val = Qnil;
-
-      if (idxval < 0)
-       args_out_of_range (array, idx);
-      if (idxval < CHAR_TABLE_ORDINARY_SLOTS)
-       {
-         if (! SINGLE_BYTE_CHAR_P (idxval))
-           args_out_of_range (array, idx);
-         /* For ASCII and 8-bit European characters, the element is
-             stored in the top table.  */
-         val = XCHAR_TABLE (array)->contents[idxval];
-         if (NILP (val))
-           {
-             int default_slot
-               = (idxval < 0x80 ? CHAR_TABLE_DEFAULT_SLOT_ASCII
-                  : idxval < 0xA0 ? CHAR_TABLE_DEFAULT_SLOT_8_BIT_CONTROL
-                  : CHAR_TABLE_DEFAULT_SLOT_8_BIT_GRAPHIC);
-             val = XCHAR_TABLE (array)->contents[default_slot];
-           }
-         if (NILP (val))
-           val = XCHAR_TABLE (array)->defalt;
-         while (NILP (val))    /* Follow parents until we find some value.  */
-           {
-             array = XCHAR_TABLE (array)->parent;
-             if (NILP (array))
-               return Qnil;
-             val = XCHAR_TABLE (array)->contents[idxval];
-             if (NILP (val))
-               val = XCHAR_TABLE (array)->defalt;
-           }
-         return val;
-       }
-      else
-       {
-         int code[4], i;
-         Lisp_Object sub_table;
-         Lisp_Object current_default;
-
-         SPLIT_CHAR (idxval, code[0], code[1], code[2]);
-         if (code[1] < 32) code[1] = -1;
-         else if (code[2] < 32) code[2] = -1;
-
-         /* Here, the possible range of CODE[0] (== charset ID) is
-           128..MAX_CHARSET.  Since the top level char table contains
-           data for multibyte characters after 256th element, we must
-           increment CODE[0] by 128 to get a correct index.  */
-         code[0] += 128;
-         code[3] = -1;         /* anchor */
-
-       try_parent_char_table:
-         current_default = XCHAR_TABLE (array)->defalt;
-         sub_table = array;
-         for (i = 0; code[i] >= 0; i++)
-           {
-             val = XCHAR_TABLE (sub_table)->contents[code[i]];
-             if (SUB_CHAR_TABLE_P (val))
-               {
-                 sub_table = val;
-                 if (! NILP (XCHAR_TABLE (sub_table)->defalt))
-                   current_default = XCHAR_TABLE (sub_table)->defalt;
-               }
-             else
-               {
-                 if (NILP (val))
-                   val = current_default;
-                 if (NILP (val))
-                   {
-                     array = XCHAR_TABLE (array)->parent;
-                     if (!NILP (array))
-                       goto try_parent_char_table;
-                   }
-                 return val;
-               }
-           }
-         /* Reaching here means IDXVAL is a generic character in
-            which each character or a group has independent value.
-            Essentially it's nonsense to get a value for such a
-            generic character, but for backward compatibility, we try
-            the default value and parent.  */
-         val = current_default;
-         if (NILP (val))
-           {
-             array = XCHAR_TABLE (array)->parent;
-             if (!NILP (array))
-               goto try_parent_char_table;
-           }
-         return val;
-       }
+      CHECK_CHARACTER (idx);
+      return CHAR_TABLE_REF (array, idxval);
     }
   else
     {
       int size = 0;
       if (VECTORP (array))
-       size = XVECTOR (array)->size;
+       size = XVECTOR_SIZE (array);
       else if (COMPILEDP (array))
-       size = XVECTOR (array)->size & PSEUDOVECTOR_SIZE_MASK;
+       size = XVECTOR_SIZE (array) & PSEUDOVECTOR_SIZE_MASK;
       else
        wrong_type_argument (Qarrayp, array);
 
@@ -2155,7 +2058,7 @@ bool-vector.  IDX starts at 0.  */)
 
   if (VECTORP (array))
     {
-      if (idxval < 0 || idxval >= XVECTOR (array)->size)
+      if (idxval < 0 || idxval >= XVECTOR_SIZE (array))
        args_out_of_range (array, idx);
       XVECTOR (array)->contents[idxval] = newelt;
     }
@@ -2176,45 +2079,8 @@ bool-vector.  IDX starts at 0.  */)
     }
   else if (CHAR_TABLE_P (array))
     {
-      if (idxval < 0)
-       args_out_of_range (array, idx);
-      if (idxval < CHAR_TABLE_ORDINARY_SLOTS)
-       {
-         if (! SINGLE_BYTE_CHAR_P (idxval))
-           args_out_of_range (array, idx);
-         XCHAR_TABLE (array)->contents[idxval] = newelt;
-       }
-      else
-       {
-         int code[4], i;
-         Lisp_Object val;
-
-         SPLIT_CHAR (idxval, code[0], code[1], code[2]);
-         if (code[1] < 32) code[1] = -1;
-         else if (code[2] < 32) code[2] = -1;
-
-         /* See the comment of the corresponding part in Faref.  */
-         code[0] += 128;
-         code[3] = -1;         /* anchor */
-         for (i = 0; code[i + 1] >= 0; i++)
-           {
-             val = XCHAR_TABLE (array)->contents[code[i]];
-             if (SUB_CHAR_TABLE_P (val))
-               array = val;
-             else
-               {
-                 Lisp_Object temp;
-
-                 /* VAL is a leaf.  Create a sub char table with the
-                    initial value VAL and look into it.  */
-
-                 temp = make_sub_char_table (val);
-                 XCHAR_TABLE (array)->contents[code[i]] = temp;
-                 array = temp;
-               }
-           }
-         XCHAR_TABLE (array)->contents[code[i]] = newelt;
-       }
+      CHECK_CHARACTER (idx);
+      CHAR_TABLE_SET (array, idxval, newelt);
     }
   else if (STRING_MULTIBYTE (array))
     {
@@ -2223,7 +2089,7 @@ bool-vector.  IDX starts at 0.  */)
 
       if (idxval < 0 || idxval >= SCHARS (array))
        args_out_of_range (array, idx);
-      CHECK_NUMBER (newelt);
+      CHECK_CHARACTER (newelt);
 
       nbytes = SBYTES (array);
 
@@ -2258,38 +2124,19 @@ bool-vector.  IDX starts at 0.  */)
        args_out_of_range (array, idx);
       CHECK_NUMBER (newelt);
 
-      if (XINT (newelt) < 0 || SINGLE_BYTE_CHAR_P (XINT (newelt)))
-       SSET (array, idxval, XINT (newelt));
-      else
+      if (XINT (newelt) >= 0 && ! SINGLE_BYTE_CHAR_P (XINT (newelt)))
        {
-         /* We must relocate the string data while converting it to
-            multibyte.  */
-         int idxval_byte, prev_bytes, new_bytes;
-         unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *p0 = workbuf, *p1;
-         unsigned char *origstr = SDATA (array), *str;
-         int nchars, nbytes;
-         USE_SAFE_ALLOCA;
-
-         nchars = SCHARS (array);
-         nbytes = idxval_byte = count_size_as_multibyte (origstr, idxval);
-         nbytes += count_size_as_multibyte (origstr + idxval,
-                                            nchars - idxval);
-         SAFE_ALLOCA (str, unsigned char *, nbytes);
-         copy_text (SDATA (array), str, nchars, 0, 1);
-         PARSE_MULTIBYTE_SEQ (str + idxval_byte, nbytes - idxval_byte,
-                              prev_bytes);
-         new_bytes = CHAR_STRING (XINT (newelt), p0);
-         allocate_string_data (XSTRING (array), nchars,
-                               nbytes + new_bytes - prev_bytes);
-         bcopy (str, SDATA (array), idxval_byte);
-         p1 = SDATA (array) + idxval_byte;
-         while (new_bytes--)
-           *p1++ = *p0++;
-         bcopy (str + idxval_byte + prev_bytes, p1,
-                nbytes - (idxval_byte + prev_bytes));
-         SAFE_FREE ();
-         clear_string_char_byte_cache ();
+         int i;
+
+         for (i = SBYTES (array) - 1; i >= 0; i--)
+           if (SREF (array, i) >= 0x80)
+             args_out_of_range (array, newelt);
+         /* ARRAY is an ASCII string.  Convert it to a multibyte
+            string, and try `aset' again.  */
+         STRING_SET_MULTIBYTE (array);
+         return Faset (array, idx, newelt);
        }
+      SSET (array, idxval, XINT (newelt));
     }
 
   return newelt;
@@ -2474,7 +2321,7 @@ NUMBER may be an integer or a floating point number.  */)
     }
 
   if (sizeof (int) == sizeof (EMACS_INT))
-    sprintf (buffer, "%d", XINT (number));
+    sprintf (buffer, "%d", (int) XINT (number));
   else if (sizeof (long) == sizeof (EMACS_INT))
     sprintf (buffer, "%ld", (long) XINT (number));
   else
@@ -2506,11 +2353,11 @@ digit_to_number (character, base)
 DEFUN ("string-to-number", Fstring_to_number, Sstring_to_number, 1, 2, 0,
        doc: /* Parse STRING as a decimal number and return the number.
 This parses both integers and floating point numbers.
-It ignores leading spaces and tabs.
+It ignores leading spaces and tabs, and all trailing chars.
 
 If BASE, interpret STRING as a number in that base.  If BASE isn't
 present, base 10 is used.  BASE must be between 2 and 16 (inclusive).
-If the base used is not 10, floating point is not recognized.  */)
+If the base used is not 10, STRING is always parsed as integer.  */)
      (string, base)
      register Lisp_Object string, base;
 {
@@ -2545,7 +2392,7 @@ If the base used is not 10, floating point is not recognized.  */)
   else if (*p == '+')
     p++;
 
-  if (isfloat_string (p) && b == 10)
+  if (isfloat_string (p, 1) && b == 10)
     val = make_float (sign * atof (p));
   else
     {
@@ -3016,208 +2863,208 @@ syms_of_data ()
 {
   Lisp_Object error_tail, arith_tail;
 
-  Qquote = intern ("quote");
-  Qlambda = intern ("lambda");
-  Qsubr = intern ("subr");
-  Qerror_conditions = intern ("error-conditions");
-  Qerror_message = intern ("error-message");
-  Qtop_level = intern ("top-level");
-
-  Qerror = intern ("error");
-  Qquit = intern ("quit");
-  Qwrong_type_argument = intern ("wrong-type-argument");
-  Qargs_out_of_range = intern ("args-out-of-range");
-  Qvoid_function = intern ("void-function");
-  Qcyclic_function_indirection = intern ("cyclic-function-indirection");
-  Qcyclic_variable_indirection = intern ("cyclic-variable-indirection");
-  Qvoid_variable = intern ("void-variable");
-  Qsetting_constant = intern ("setting-constant");
-  Qinvalid_read_syntax = intern ("invalid-read-syntax");
-
-  Qinvalid_function = intern ("invalid-function");
-  Qwrong_number_of_arguments = intern ("wrong-number-of-arguments");
-  Qno_catch = intern ("no-catch");
-  Qend_of_file = intern ("end-of-file");
-  Qarith_error = intern ("arith-error");
-  Qbeginning_of_buffer = intern ("beginning-of-buffer");
-  Qend_of_buffer = intern ("end-of-buffer");
-  Qbuffer_read_only = intern ("buffer-read-only");
-  Qtext_read_only = intern ("text-read-only");
-  Qmark_inactive = intern ("mark-inactive");
-
-  Qlistp = intern ("listp");
-  Qconsp = intern ("consp");
-  Qsymbolp = intern ("symbolp");
-  Qkeywordp = intern ("keywordp");
-  Qintegerp = intern ("integerp");
-  Qnatnump = intern ("natnump");
-  Qwholenump = intern ("wholenump");
-  Qstringp = intern ("stringp");
-  Qarrayp = intern ("arrayp");
-  Qsequencep = intern ("sequencep");
-  Qbufferp = intern ("bufferp");
-  Qvectorp = intern ("vectorp");
-  Qchar_or_string_p = intern ("char-or-string-p");
-  Qmarkerp = intern ("markerp");
-  Qbuffer_or_string_p = intern ("buffer-or-string-p");
-  Qinteger_or_marker_p = intern ("integer-or-marker-p");
-  Qboundp = intern ("boundp");
-  Qfboundp = intern ("fboundp");
-
-  Qfloatp = intern ("floatp");
-  Qnumberp = intern ("numberp");
-  Qnumber_or_marker_p = intern ("number-or-marker-p");
-
-  Qchar_table_p = intern ("char-table-p");
-  Qvector_or_char_table_p = intern ("vector-or-char-table-p");
-
-  Qsubrp = intern ("subrp");
-  Qunevalled = intern ("unevalled");
-  Qmany = intern ("many");
-
-  Qcdr = intern ("cdr");
+  Qquote = intern_c_string ("quote");
+  Qlambda = intern_c_string ("lambda");
+  Qsubr = intern_c_string ("subr");
+  Qerror_conditions = intern_c_string ("error-conditions");
+  Qerror_message = intern_c_string ("error-message");
+  Qtop_level = intern_c_string ("top-level");
+
+  Qerror = intern_c_string ("error");
+  Qquit = intern_c_string ("quit");
+  Qwrong_type_argument = intern_c_string ("wrong-type-argument");
+  Qargs_out_of_range = intern_c_string ("args-out-of-range");
+  Qvoid_function = intern_c_string ("void-function");
+  Qcyclic_function_indirection = intern_c_string ("cyclic-function-indirection");
+  Qcyclic_variable_indirection = intern_c_string ("cyclic-variable-indirection");
+  Qvoid_variable = intern_c_string ("void-variable");
+  Qsetting_constant = intern_c_string ("setting-constant");
+  Qinvalid_read_syntax = intern_c_string ("invalid-read-syntax");
+
+  Qinvalid_function = intern_c_string ("invalid-function");
+  Qwrong_number_of_arguments = intern_c_string ("wrong-number-of-arguments");
+  Qno_catch = intern_c_string ("no-catch");
+  Qend_of_file = intern_c_string ("end-of-file");
+  Qarith_error = intern_c_string ("arith-error");
+  Qbeginning_of_buffer = intern_c_string ("beginning-of-buffer");
+  Qend_of_buffer = intern_c_string ("end-of-buffer");
+  Qbuffer_read_only = intern_c_string ("buffer-read-only");
+  Qtext_read_only = intern_c_string ("text-read-only");
+  Qmark_inactive = intern_c_string ("mark-inactive");
+
+  Qlistp = intern_c_string ("listp");
+  Qconsp = intern_c_string ("consp");
+  Qsymbolp = intern_c_string ("symbolp");
+  Qkeywordp = intern_c_string ("keywordp");
+  Qintegerp = intern_c_string ("integerp");
+  Qnatnump = intern_c_string ("natnump");
+  Qwholenump = intern_c_string ("wholenump");
+  Qstringp = intern_c_string ("stringp");
+  Qarrayp = intern_c_string ("arrayp");
+  Qsequencep = intern_c_string ("sequencep");
+  Qbufferp = intern_c_string ("bufferp");
+  Qvectorp = intern_c_string ("vectorp");
+  Qchar_or_string_p = intern_c_string ("char-or-string-p");
+  Qmarkerp = intern_c_string ("markerp");
+  Qbuffer_or_string_p = intern_c_string ("buffer-or-string-p");
+  Qinteger_or_marker_p = intern_c_string ("integer-or-marker-p");
+  Qboundp = intern_c_string ("boundp");
+  Qfboundp = intern_c_string ("fboundp");
+
+  Qfloatp = intern_c_string ("floatp");
+  Qnumberp = intern_c_string ("numberp");
+  Qnumber_or_marker_p = intern_c_string ("number-or-marker-p");
+
+  Qchar_table_p = intern_c_string ("char-table-p");
+  Qvector_or_char_table_p = intern_c_string ("vector-or-char-table-p");
+
+  Qsubrp = intern_c_string ("subrp");
+  Qunevalled = intern_c_string ("unevalled");
+  Qmany = intern_c_string ("many");
+
+  Qcdr = intern_c_string ("cdr");
 
   /* Handle automatic advice activation */
-  Qad_advice_info = intern ("ad-advice-info");
-  Qad_activate_internal = intern ("ad-activate-internal");
+  Qad_advice_info = intern_c_string ("ad-advice-info");
+  Qad_activate_internal = intern_c_string ("ad-activate-internal");
 
-  error_tail = Fcons (Qerror, Qnil);
+  error_tail = pure_cons (Qerror, Qnil);
 
   /* ERROR is used as a signaler for random errors for which nothing else is right */
 
   Fput (Qerror, Qerror_conditions,
        error_tail);
   Fput (Qerror, Qerror_message,
-       build_string ("error"));
+       make_pure_c_string ("error"));
 
   Fput (Qquit, Qerror_conditions,
-       Fcons (Qquit, Qnil));
+       pure_cons (Qquit, Qnil));
   Fput (Qquit, Qerror_message,
-       build_string ("Quit"));
+       make_pure_c_string ("Quit"));
 
   Fput (Qwrong_type_argument, Qerror_conditions,
-       Fcons (Qwrong_type_argument, error_tail));
+       pure_cons (Qwrong_type_argument, error_tail));
   Fput (Qwrong_type_argument, Qerror_message,
-       build_string ("Wrong type argument"));
+       make_pure_c_string ("Wrong type argument"));
 
   Fput (Qargs_out_of_range, Qerror_conditions,
-       Fcons (Qargs_out_of_range, error_tail));
+       pure_cons (Qargs_out_of_range, error_tail));
   Fput (Qargs_out_of_range, Qerror_message,
-       build_string ("Args out of range"));
+       make_pure_c_string ("Args out of range"));
 
   Fput (Qvoid_function, Qerror_conditions,
-       Fcons (Qvoid_function, error_tail));
+       pure_cons (Qvoid_function, error_tail));
   Fput (Qvoid_function, Qerror_message,
-       build_string ("Symbol's function definition is void"));
+       make_pure_c_string ("Symbol's function definition is void"));
 
   Fput (Qcyclic_function_indirection, Qerror_conditions,
-       Fcons (Qcyclic_function_indirection, error_tail));
+       pure_cons (Qcyclic_function_indirection, error_tail));
   Fput (Qcyclic_function_indirection, Qerror_message,
-       build_string ("Symbol's chain of function indirections contains a loop"));
+       make_pure_c_string ("Symbol's chain of function indirections contains a loop"));
 
   Fput (Qcyclic_variable_indirection, Qerror_conditions,
-       Fcons (Qcyclic_variable_indirection, error_tail));
+       pure_cons (Qcyclic_variable_indirection, error_tail));
   Fput (Qcyclic_variable_indirection, Qerror_message,
-       build_string ("Symbol's chain of variable indirections contains a loop"));
+       make_pure_c_string ("Symbol's chain of variable indirections contains a loop"));
 
-  Qcircular_list = intern ("circular-list");
+  Qcircular_list = intern_c_string ("circular-list");
   staticpro (&Qcircular_list);
   Fput (Qcircular_list, Qerror_conditions,
-       Fcons (Qcircular_list, error_tail));
+       pure_cons (Qcircular_list, error_tail));
   Fput (Qcircular_list, Qerror_message,
-       build_string ("List contains a loop"));
+       make_pure_c_string ("List contains a loop"));
 
   Fput (Qvoid_variable, Qerror_conditions,
-       Fcons (Qvoid_variable, error_tail));
+       pure_cons (Qvoid_variable, error_tail));
   Fput (Qvoid_variable, Qerror_message,
-       build_string ("Symbol's value as variable is void"));
+       make_pure_c_string ("Symbol's value as variable is void"));
 
   Fput (Qsetting_constant, Qerror_conditions,
-       Fcons (Qsetting_constant, error_tail));
+       pure_cons (Qsetting_constant, error_tail));
   Fput (Qsetting_constant, Qerror_message,
-       build_string ("Attempt to set a constant symbol"));
+       make_pure_c_string ("Attempt to set a constant symbol"));
 
   Fput (Qinvalid_read_syntax, Qerror_conditions,
-       Fcons (Qinvalid_read_syntax, error_tail));
+       pure_cons (Qinvalid_read_syntax, error_tail));
   Fput (Qinvalid_read_syntax, Qerror_message,
-       build_string ("Invalid read syntax"));
+       make_pure_c_string ("Invalid read syntax"));
 
   Fput (Qinvalid_function, Qerror_conditions,
-       Fcons (Qinvalid_function, error_tail));
+       pure_cons (Qinvalid_function, error_tail));
   Fput (Qinvalid_function, Qerror_message,
-       build_string ("Invalid function"));
+       make_pure_c_string ("Invalid function"));
 
   Fput (Qwrong_number_of_arguments, Qerror_conditions,
-       Fcons (Qwrong_number_of_arguments, error_tail));
+       pure_cons (Qwrong_number_of_arguments, error_tail));
   Fput (Qwrong_number_of_arguments, Qerror_message,
-       build_string ("Wrong number of arguments"));
+       make_pure_c_string ("Wrong number of arguments"));
 
   Fput (Qno_catch, Qerror_conditions,
-       Fcons (Qno_catch, error_tail));
+       pure_cons (Qno_catch, error_tail));
   Fput (Qno_catch, Qerror_message,
-       build_string ("No catch for tag"));
+       make_pure_c_string ("No catch for tag"));
 
   Fput (Qend_of_file, Qerror_conditions,
-       Fcons (Qend_of_file, error_tail));
+       pure_cons (Qend_of_file, error_tail));
   Fput (Qend_of_file, Qerror_message,
-       build_string ("End of file during parsing"));
+       make_pure_c_string ("End of file during parsing"));
 
-  arith_tail = Fcons (Qarith_error, error_tail);
+  arith_tail = pure_cons (Qarith_error, error_tail);
   Fput (Qarith_error, Qerror_conditions,
        arith_tail);
   Fput (Qarith_error, Qerror_message,
-       build_string ("Arithmetic error"));
+       make_pure_c_string ("Arithmetic error"));
 
   Fput (Qbeginning_of_buffer, Qerror_conditions,
-       Fcons (Qbeginning_of_buffer, error_tail));
+       pure_cons (Qbeginning_of_buffer, error_tail));
   Fput (Qbeginning_of_buffer, Qerror_message,
-       build_string ("Beginning of buffer"));
+       make_pure_c_string ("Beginning of buffer"));
 
   Fput (Qend_of_buffer, Qerror_conditions,
-       Fcons (Qend_of_buffer, error_tail));
+       pure_cons (Qend_of_buffer, error_tail));
   Fput (Qend_of_buffer, Qerror_message,
-       build_string ("End of buffer"));
+       make_pure_c_string ("End of buffer"));
 
   Fput (Qbuffer_read_only, Qerror_conditions,
-       Fcons (Qbuffer_read_only, error_tail));
+       pure_cons (Qbuffer_read_only, error_tail));
   Fput (Qbuffer_read_only, Qerror_message,
-       build_string ("Buffer is read-only"));
+       make_pure_c_string ("Buffer is read-only"));
 
   Fput (Qtext_read_only, Qerror_conditions,
-       Fcons (Qtext_read_only, error_tail));
+       pure_cons (Qtext_read_only, error_tail));
   Fput (Qtext_read_only, Qerror_message,
-       build_string ("Text is read-only"));
+       make_pure_c_string ("Text is read-only"));
 
-  Qrange_error = intern ("range-error");
-  Qdomain_error = intern ("domain-error");
-  Qsingularity_error = intern ("singularity-error");
-  Qoverflow_error = intern ("overflow-error");
-  Qunderflow_error = intern ("underflow-error");
+  Qrange_error = intern_c_string ("range-error");
+  Qdomain_error = intern_c_string ("domain-error");
+  Qsingularity_error = intern_c_string ("singularity-error");
+  Qoverflow_error = intern_c_string ("overflow-error");
+  Qunderflow_error = intern_c_string ("underflow-error");
 
   Fput (Qdomain_error, Qerror_conditions,
-       Fcons (Qdomain_error, arith_tail));
+       pure_cons (Qdomain_error, arith_tail));
   Fput (Qdomain_error, Qerror_message,
-       build_string ("Arithmetic domain error"));
+       make_pure_c_string ("Arithmetic domain error"));
 
   Fput (Qrange_error, Qerror_conditions,
-       Fcons (Qrange_error, arith_tail));
+       pure_cons (Qrange_error, arith_tail));
   Fput (Qrange_error, Qerror_message,
-       build_string ("Arithmetic range error"));
+       make_pure_c_string ("Arithmetic range error"));
 
   Fput (Qsingularity_error, Qerror_conditions,
-       Fcons (Qsingularity_error, Fcons (Qdomain_error, arith_tail)));
+       pure_cons (Qsingularity_error, Fcons (Qdomain_error, arith_tail)));
   Fput (Qsingularity_error, Qerror_message,
-       build_string ("Arithmetic singularity error"));
+       make_pure_c_string ("Arithmetic singularity error"));
 
   Fput (Qoverflow_error, Qerror_conditions,
-       Fcons (Qoverflow_error, Fcons (Qdomain_error, arith_tail)));
+       pure_cons (Qoverflow_error, Fcons (Qdomain_error, arith_tail)));
   Fput (Qoverflow_error, Qerror_message,
-       build_string ("Arithmetic overflow error"));
+       make_pure_c_string ("Arithmetic overflow error"));
 
   Fput (Qunderflow_error, Qerror_conditions,
-       Fcons (Qunderflow_error, Fcons (Qdomain_error, arith_tail)));
+       pure_cons (Qunderflow_error, Fcons (Qdomain_error, arith_tail)));
   Fput (Qunderflow_error, Qerror_message,
-       build_string ("Arithmetic underflow error"));
+       make_pure_c_string ("Arithmetic underflow error"));
 
   staticpro (&Qrange_error);
   staticpro (&Qdomain_error);
@@ -3288,24 +3135,30 @@ syms_of_data ()
   staticpro (&Qad_activate_internal);
 
   /* Types that type-of returns.  */
-  Qinteger = intern ("integer");
-  Qsymbol = intern ("symbol");
-  Qstring = intern ("string");
-  Qcons = intern ("cons");
-  Qmarker = intern ("marker");
-  Qoverlay = intern ("overlay");
-  Qfloat = intern ("float");
-  Qwindow_configuration = intern ("window-configuration");
-  Qprocess = intern ("process");
-  Qwindow = intern ("window");
-  /* Qsubr = intern ("subr"); */
-  Qcompiled_function = intern ("compiled-function");
-  Qbuffer = intern ("buffer");
-  Qframe = intern ("frame");
-  Qvector = intern ("vector");
-  Qchar_table = intern ("char-table");
-  Qbool_vector = intern ("bool-vector");
-  Qhash_table = intern ("hash-table");
+  Qinteger = intern_c_string ("integer");
+  Qsymbol = intern_c_string ("symbol");
+  Qstring = intern_c_string ("string");
+  Qcons = intern_c_string ("cons");
+  Qmarker = intern_c_string ("marker");
+  Qoverlay = intern_c_string ("overlay");
+  Qfloat = intern_c_string ("float");
+  Qwindow_configuration = intern_c_string ("window-configuration");
+  Qprocess = intern_c_string ("process");
+  Qwindow = intern_c_string ("window");
+  /* Qsubr = intern_c_string ("subr"); */
+  Qcompiled_function = intern_c_string ("compiled-function");
+  Qbuffer = intern_c_string ("buffer");
+  Qframe = intern_c_string ("frame");
+  Qvector = intern_c_string ("vector");
+  Qchar_table = intern_c_string ("char-table");
+  Qbool_vector = intern_c_string ("bool-vector");
+  Qhash_table = intern_c_string ("hash-table");
+
+  DEFSYM (Qfont_spec, "font-spec");
+  DEFSYM (Qfont_entity, "font-entity");
+  DEFSYM (Qfont_object, "font-object");
+
+  DEFSYM (Qinteractive_form, "interactive-form");
 
   staticpro (&Qinteger);
   staticpro (&Qsymbol);
@@ -3426,10 +3279,12 @@ syms_of_data ()
   DEFVAR_LISP ("most-positive-fixnum", &Vmost_positive_fixnum,
               doc: /* The largest value that is representable in a Lisp integer.  */);
   Vmost_positive_fixnum = make_number (MOST_POSITIVE_FIXNUM);
+  XSYMBOL (intern_c_string ("most-positive-fixnum"))->constant = 1;
 
   DEFVAR_LISP ("most-negative-fixnum", &Vmost_negative_fixnum,
               doc: /* The smallest value that is representable in a Lisp integer.  */);
   Vmost_negative_fixnum = make_number (MOST_NEGATIVE_FIXNUM);
+  XSYMBOL (intern_c_string ("most-negative-fixnum"))->constant = 1;
 }
 
 SIGTYPE
@@ -3441,15 +3296,7 @@ arith_error (signo)
      must reestablish each time */
   signal (signo, arith_error);
 #endif /* USG */
-#ifdef VMS
-  /* VMS systems are like USG.  */
-  signal (signo, arith_error);
-#endif /* VMS */
-#ifdef BSD4_1
-  sigrelse (SIGFPE);
-#else /* not BSD4_1 */
   sigsetmask (SIGEMPTYMASK);
-#endif /* not BSD4_1 */
 
   SIGNAL_THREAD_CHECK (signo);
   xsignal0 (Qarith_error);