Avoid call to strlen in fast_c_string_match_ignore_case.
[bpt/emacs.git] / src / lread.c
index 7aba203..f74d44d 100644 (file)
@@ -26,10 +26,11 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <errno.h>
 #include <limits.h>    /* For CHAR_BIT.  */
 #include <setjmp.h>
+#include <stat-time.h>
 #include "lisp.h"
 #include "intervals.h"
-#include "buffer.h"
 #include "character.h"
+#include "buffer.h"
 #include "charset.h"
 #include "coding.h"
 #include <epaths.h>
@@ -44,6 +45,10 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "msdos.h"
 #endif
 
+#ifdef HAVE_NS
+#include "nsterm.h"
+#endif
+
 #include <unistd.h>
 #include <math.h>
 
@@ -154,10 +159,6 @@ static void readevalloop (Lisp_Object, FILE*, Lisp_Object, int,
                           Lisp_Object, Lisp_Object);
 static Lisp_Object load_unwind (Lisp_Object);
 static Lisp_Object load_descriptor_unwind (Lisp_Object);
-
-static void invalid_syntax (const char *) NO_RETURN;
-static void end_of_file_error (void) NO_RETURN;
-
 \f
 /* Functions that read one byte from the current source READCHARFUN
    or unreads one byte.  If the integer argument C is -1, it returns
@@ -601,18 +602,9 @@ read_filtered_event (int no_switch_frame, int ascii_required,
   /* Compute timeout.  */
   if (NUMBERP (seconds))
     {
-      EMACS_TIME wait_time;
-      int sec, usec;
       double duration = extract_float (seconds);
-
-      if (0 < duration)
-       duration_to_sec_usec (duration, &sec, &usec);
-      else
-       sec = usec = 0;
-
-      EMACS_GET_TIME (end_time);
-      EMACS_SET_SECS_USECS (wait_time, sec, usec);
-      EMACS_ADD_TIME (end_time, end_time, wait_time);
+      EMACS_TIME wait_time = EMACS_TIME_FROM_DOUBLE (duration);
+      end_time = add_emacs_time (current_emacs_time (), wait_time);
     }
 
 /* Read until we get an acceptable event.  */
@@ -914,7 +906,7 @@ safe_to_load_p (int fd)
 
       if (i >= nbytes
          || fast_c_string_match_ignore_case (Vbytecomp_version_regexp,
-                                             buf + i) < 0)
+                                             buf + i, nbytes - i) < 0)
        safe_p = 0;
     }
   if (safe_p)
@@ -1226,7 +1218,8 @@ Return t if the file exists and loads successfully.  */)
              SSET (efound, SBYTES (efound) - 1, 'c');
            }
 
-         if (result == 0 && s1.st_mtime < s2.st_mtime)
+         if (result == 0
+             && EMACS_TIME_LT (get_stat_mtime (&s1), get_stat_mtime (&s2)))
            {
              /* Make the progress messages mention that source is newer.  */
              newer = 1;
@@ -1489,36 +1482,26 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
         this path element/specified file name and any possible suffix.  */
       want_length = max_suffix_len + SBYTES (filename);
       if (fn_size <= want_length)
-       fn = (char *) alloca (fn_size = 100 + want_length);
+       fn = alloca (fn_size = 100 + want_length);
 
       /* Loop over suffixes.  */
       for (tail = NILP (suffixes) ? Fcons (empty_unibyte_string, Qnil) : suffixes;
           CONSP (tail); tail = XCDR (tail))
        {
-         ptrdiff_t lsuffix = SBYTES (XCAR (tail));
+         ptrdiff_t fnlen, lsuffix = SBYTES (XCAR (tail));
          Lisp_Object handler;
          int exists;
 
          /* Concatenate path element/specified name with the suffix.
             If the directory starts with /:, remove that.  */
-         if (SCHARS (filename) > 2
-             && SREF (filename, 0) == '/'
-             && SREF (filename, 1) == ':')
-           {
-             strncpy (fn, SSDATA (filename) + 2,
-                      SBYTES (filename) - 2);
-             fn[SBYTES (filename) - 2] = 0;
-           }
-         else
-           {
-             strncpy (fn, SSDATA (filename),
-                      SBYTES (filename));
-             fn[SBYTES (filename)] = 0;
-           }
-
-         if (lsuffix != 0)  /* Bug happens on CCI if lsuffix is 0.  */
-           strncat (fn, SSDATA (XCAR (tail)), lsuffix);
-
+         int prefixlen = ((SCHARS (filename) > 2
+                           && SREF (filename, 0) == '/'
+                           && SREF (filename, 1) == ':')
+                          ? 2 : 0);
+         fnlen = SBYTES (filename) - prefixlen;
+         memcpy (fn, SDATA (filename) + prefixlen, fnlen);
+         memcpy (fn + fnlen, SDATA (XCAR (tail)), lsuffix + 1);
+         fnlen += lsuffix;
          /* Check that the file exists and is not a directory.  */
          /* We used to only check for handlers on non-absolute file names:
                if (absolute)
@@ -1527,7 +1510,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
                  handler = Ffind_file_name_handler (filename, Qfile_exists_p);
             It's not clear why that was the case and it breaks things like
             (load "/bar.el") where the file is actually "/bar.el.gz".  */
-         string = build_string (fn);
+         string = make_string (fn, fnlen);
          handler = Ffind_file_name_handler (string, Qfile_exists_p);
          if ((!NILP (handler) || !NILP (predicate)) && !NATNUMP (predicate))
             {
@@ -1664,7 +1647,7 @@ readevalloop_1 (Lisp_Object old)
 /* Signal an `end-of-file' error, if possible with file name
    information.  */
 
-static void
+static _Noreturn void
 end_of_file_error (void)
 {
   if (STRINGP (Vload_file_name))
@@ -2032,7 +2015,7 @@ read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end)
 /* Signal Qinvalid_read_syntax error.
    S is error string of length N (if > 0)  */
 
-static void
+static _Noreturn void
 invalid_syntax (const char *s)
 {
   xsignal1 (Qinvalid_read_syntax, build_string (s));
@@ -2551,8 +2534,8 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
             build them using function calls.  */
          Lisp_Object tmp;
          tmp = read_vector (readcharfun, 1);
-         return Fmake_byte_code (ASIZE (tmp),
-                                 XVECTOR (tmp)->contents);
+         make_byte_code (XVECTOR (tmp));
+         return tmp;
        }
       if (c == '(')
        {
@@ -2635,13 +2618,12 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
 
              if (saved_doc_string_size == 0)
                {
-                 saved_doc_string = (char *) xmalloc (nskip + extra);
+                 saved_doc_string = xmalloc (nskip + extra);
                  saved_doc_string_size = nskip + extra;
                }
              if (nskip > saved_doc_string_size)
                {
-                 saved_doc_string = (char *) xrealloc (saved_doc_string,
-                                                       nskip + extra);
+                 saved_doc_string = xrealloc (saved_doc_string, nskip + extra);
                  saved_doc_string_size = nskip + extra;
                }
 
@@ -2904,8 +2886,7 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
                ptrdiff_t offset = p - read_buffer;
                if (min (PTRDIFF_MAX, SIZE_MAX) / 2 < read_buffer_size)
                  memory_full (SIZE_MAX);
-               read_buffer = (char *) xrealloc (read_buffer,
-                                                read_buffer_size * 2);
+               read_buffer = xrealloc (read_buffer, read_buffer_size * 2);
                read_buffer_size *= 2;
                p = read_buffer + offset;
                end = read_buffer + read_buffer_size;
@@ -2982,7 +2963,7 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
 
        /* If purifying, and string starts with \ newline,
           return zero instead.  This is for doc strings
-          that we are really going to find in etc/DOC.nn.nn  */
+          that we are really going to find in etc/DOC.nn.nn.  */
        if (!NILP (Vpurify_flag) && NILP (Vdoc_file_name) && cancel)
          return make_number (0);
 
@@ -3039,8 +3020,7 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
                  ptrdiff_t offset = p - read_buffer;
                  if (min (PTRDIFF_MAX, SIZE_MAX) / 2 < read_buffer_size)
                    memory_full (SIZE_MAX);
-                 read_buffer = (char *) xrealloc (read_buffer,
-                                                  read_buffer_size * 2);
+                 read_buffer = xrealloc (read_buffer, read_buffer_size * 2);
                  read_buffer_size *= 2;
                  p = read_buffer + offset;
                  end = read_buffer + read_buffer_size;
@@ -3070,8 +3050,7 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
              ptrdiff_t offset = p - read_buffer;
              if (min (PTRDIFF_MAX, SIZE_MAX) / 2 < read_buffer_size)
                memory_full (SIZE_MAX);
-             read_buffer = (char *) xrealloc (read_buffer,
-                                              read_buffer_size * 2);
+             read_buffer = xrealloc (read_buffer, read_buffer_size * 2);
              read_buffer_size *= 2;
              p = read_buffer + offset;
              end = read_buffer + read_buffer_size;
@@ -3095,18 +3074,17 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
                                          nbytes)
               : nbytes);
 
-         if (uninterned_symbol && ! NILP (Vpurify_flag))
-           name = make_pure_string (read_buffer, nchars, nbytes, multibyte);
-         else
-           name = make_specified_string (read_buffer, nchars, nbytes, multibyte);
+         name = ((uninterned_symbol && ! NILP (Vpurify_flag)
+                  ? make_pure_string : make_specified_string)
+                 (read_buffer, nchars, nbytes, multibyte));
          result = (uninterned_symbol ? Fmake_symbol (name)
                    : Fintern (name, Qnil));
 
          if (EQ (Vread_with_symbol_positions, Qt)
              || EQ (Vread_with_symbol_positions, readcharfun))
-           Vread_symbol_positions_list =
-             Fcons (Fcons (result, make_number (start_position)),
-                    Vread_symbol_positions_list);
+           Vread_symbol_positions_list
+             Fcons (Fcons (result, make_number (start_position)),
+                      Vread_symbol_positions_list);
          return result;
        }
       }
@@ -3520,7 +3498,7 @@ read_list (int flag, register Lisp_Object readcharfun)
               We don't use Fexpand_file_name because that would make
               the directory absolute now.  */
            elt = concat2 (build_string ("../lisp/"),
-                          Ffile_name_nondirectory (elt));
+                        Ffile_name_nondirectory (elt));
        }
       else if (EQ (elt, Vload_file_name)
               && ! NILP (elt)
@@ -3709,7 +3687,7 @@ intern_c_string (const char *str)
        with the extra copy.  */
     abort ();
 
-  return Fintern (make_pure_c_string (str), obarray);
+  return Fintern (make_pure_c_string (str, len), obarray);
 }
 \f
 DEFUN ("intern", Fintern, Sintern, 1, 2, 0,
@@ -3749,7 +3727,7 @@ it defaults to the value of `obarray'.  */)
       SET_SYMBOL_VAL (XSYMBOL (sym), sym);
     }
 
-  ptr = &XVECTOR (obarray)->contents[XINT (tem)];
+  ptr = &AREF (obarray, XINT(tem));
   if (SYMBOLP (*ptr))
     XSYMBOL (sym)->next = XSYMBOL (*ptr);
   else
@@ -3828,18 +3806,18 @@ OBARRAY defaults to the value of the variable `obarray'.  */)
 
   hash = oblookup_last_bucket_number;
 
-  if (EQ (XVECTOR (obarray)->contents[hash], tem))
+  if (EQ (AREF (obarray, hash), tem))
     {
       if (XSYMBOL (tem)->next)
-       XSETSYMBOL (XVECTOR (obarray)->contents[hash], XSYMBOL (tem)->next);
+       XSETSYMBOL (AREF (obarray, hash), XSYMBOL (tem)->next);
       else
-       XSETINT (XVECTOR (obarray)->contents[hash], 0);
+       XSETINT (AREF (obarray, hash), 0);
     }
   else
     {
       Lisp_Object tail, following;
 
-      for (tail = XVECTOR (obarray)->contents[hash];
+      for (tail = AREF (obarray, hash);
           XSYMBOL (tail)->next;
           tail = following)
        {
@@ -3878,7 +3856,7 @@ oblookup (Lisp_Object obarray, register const char *ptr, ptrdiff_t size, ptrdiff
   /* This is sometimes needed in the middle of GC.  */
   obsize &= ~ARRAY_MARK_FLAG;
   hash = hash_string (ptr, size_byte) % obsize;
-  bucket = XVECTOR (obarray)->contents[hash];
+  bucket = AREF (obarray, hash);
   oblookup_last_bucket_number = hash;
   if (EQ (bucket, make_number (0)))
     ;
@@ -3906,7 +3884,7 @@ map_obarray (Lisp_Object obarray, void (*fn) (Lisp_Object, Lisp_Object), Lisp_Ob
   CHECK_VECTOR (obarray);
   for (i = ASIZE (obarray) - 1; i >= 0; i--)
     {
-      tail = XVECTOR (obarray)->contents[i];
+      tail = AREF (obarray, i);
       if (SYMBOLP (tail))
        while (1)
          {
@@ -3950,7 +3928,7 @@ init_obarray (void)
   initial_obarray = Vobarray;
   staticpro (&initial_obarray);
 
-  Qunbound = Fmake_symbol (make_pure_c_string ("unbound"));
+  Qunbound = Fmake_symbol (build_pure_c_string ("unbound"));
   /* Set temporary dummy values to Qnil and Vpurify_flag to satisfy the
      NILP (Vpurify_flag) check in intern_c_string.  */
   Qnil = make_number (-1); Vpurify_flag = make_number (1);
@@ -3977,7 +3955,7 @@ init_obarray (void)
 
   DEFSYM (Qvariable_documentation, "variable-documentation");
 
-  read_buffer = (char *) xmalloc (size);
+  read_buffer = xmalloc (size);
   read_buffer_size = size;
 }
 \f
@@ -4074,62 +4052,110 @@ defvar_kboard (struct Lisp_Kboard_Objfwd *ko_fwd,
   SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)ko_fwd);
 }
 \f
+/* Check that the elements of Vload_path exist.  */
+
+static void
+load_path_check (void)
+{
+  Lisp_Object path_tail;
+
+  /* The only elements that might not exist are those from
+     PATH_LOADSEARCH, EMACSLOADPATH.  Anything else is only added if
+     it exists.  */
+  for (path_tail = Vload_path; !NILP (path_tail); path_tail = XCDR (path_tail))
+    {
+      Lisp_Object dirfile;
+      dirfile = Fcar (path_tail);
+      if (STRINGP (dirfile))
+        {
+          dirfile = Fdirectory_file_name (dirfile);
+          if (access (SSDATA (dirfile), 0) < 0)
+            dir_warning ("Warning: Lisp directory `%s' does not exist.\n",
+                         XCAR (path_tail));
+        }
+    }
+}
+
 /* Record the value of load-path used at the start of dumping
    so we can see if the site changed it later during dumping.  */
 static Lisp_Object dump_path;
 
+/* Compute the default Vload_path, with the following logic:
+   If CANNOT_DUMP:
+   use EMACSLOADPATH env-var if set; otherwise use PATH_LOADSEARCH,
+   prepending PATH_SITELOADSEARCH unless --no-site-lisp.
+   The remainder is what happens when dumping works:
+   If purify-flag (ie dumping) just use PATH_DUMPLOADSEARCH.
+   Otherwise use EMACSLOADPATH if set, else PATH_LOADSEARCH.
+
+   If !initialized, then just set both Vload_path and dump_path.
+   If initialized, then if Vload_path != dump_path, do nothing.
+   (Presumably the load-path has already been changed by something.
+   This can only be from a site-load file during dumping,
+   or because EMACSLOADPATH is set.)
+   If Vinstallation_directory is not nil (ie, running uninstalled):
+   If installation-dir/lisp exists and not already a member,
+   we must be running uninstalled.  Reset the load-path
+   to just installation-dir/lisp.  (The default PATH_LOADSEARCH
+   refers to the eventual installation directories.  Since we
+   are not yet installed, we should not use them, even if they exist.)
+   If installation-dir/lisp does not exist, just add dump_path at the
+   end instead.
+   Add installation-dir/leim (if exists and not already a member) at the front.
+   Add installation-dir/site-lisp (if !no_site_lisp, and exists
+   and not already a member) at the front.
+   If installation-dir != source-dir (ie running an uninstalled,
+   out-of-tree build) AND install-dir/src/Makefile exists BUT
+   install-dir/src/Makefile.in does NOT exist (this is a sanity
+   check), then repeat the above steps for source-dir/lisp,
+   leim and site-lisp.
+   Finally, add the site-lisp directories at the front (if !no_site_lisp).
+*/
+
 void
 init_lread (void)
 {
   const char *normal;
-  int turn_off_warning = 0;
-
-  /* Compute the default Vload-path, with the following logic:
-     If CANNOT_DUMP just use PATH_LOADSEARCH.
-     Else if purify-flag (ie dumping) start from PATH_DUMPLOADSEARCH;
-     otherwise start from PATH_LOADSEARCH.
-     If !initialized, then just set both Vload_path and dump_path.
-     If initialized, then if Vload_path != dump_path, do nothing.
-     (Presumably the load-path has already been changed by something.)
-     Also do nothing if Vinstallation_directory is nil.
-     Otherwise:
-       Remove site-lisp directories from the front of load-path.
-       Add installation-dir/lisp (if exists and not already a member),
-         at the front, and turn off warnings about missing directories
-         (because we are presumably running uninstalled).
-         If it does not exist, add dump_path at the end instead.
-       Add installation-dir/leim (if exists and not already a member)
-         at the front.
-       Add installation-dir/site-lisp (if !no_site_lisp, and exists
-         and not already a member) at the front.
-       If installation-dir != source-dir (ie running an uninstalled,
-         out-of-tree build) AND install-dir/src/Makefile exists BUT
-         install-dir/src/Makefile.in does NOT exist (this is a sanity
-         check), then repeat the above steps for source-dir/lisp,
-         leim and site-lisp.
-       Finally, add the previously removed site-lisp directories back
-       at the front (if !no_site_lisp).
-
-     We then warn about any of the load-path elements that do not
-     exist.  The only ones that might not exist are those from
-     PATH_LOADSEARCH, and perhaps dump_path.
-
-     Having done all this, we then throw it all away if purify-flag is
-     nil (ie, not dumping) and EMACSLOADPATH is set, and just
-     unconditionally use the latter value instead.
-     So AFAICS the only net results of all the previous steps will be
-     possibly to issue some irrelevant warnings.
-
-     FIXME? There's a case for saying that if we are running
-     uninstalled, the eventual installation directories should not yet
-     be included in load-path.
-  */
+
 #ifdef CANNOT_DUMP
+#ifdef HAVE_NS
+  const char *loadpath = ns_load_path ();
+#endif
+
   normal = PATH_LOADSEARCH;
-  Vload_path = decode_env_path (0, normal);
+#ifdef HAVE_NS
+  Vload_path = decode_env_path ("EMACSLOADPATH", loadpath ? loadpath : normal);
+#else
+  Vload_path = decode_env_path ("EMACSLOADPATH", normal);
+#endif
+
+  load_path_check ();
+
+  /* FIXME CANNOT_DUMP platforms should get source-dir/lisp etc added
+   to their load-path too, AFAICS.  I don't think we can tell the
+   difference between initialized and !initialized in this case,
+   so we'll have to do it unconditionally when Vinstallation_directory
+   is non-nil.  */
+#ifdef HAVE_NS
+  /* loadpath already includes the app-bundle's site-lisp.  */
+  if (!no_site_lisp && !egetenv ("EMACSLOADPATH") && !loadpath)
+#else
+  if (!no_site_lisp && !egetenv ("EMACSLOADPATH"))
+#endif
+    {
+      Lisp_Object sitelisp;
+      sitelisp = decode_env_path (0, PATH_SITELOADSEARCH);
+      if (! NILP (sitelisp)) Vload_path = nconc2 (sitelisp, Vload_path);
+    }
 #else
   if (NILP (Vpurify_flag))
-    normal = PATH_LOADSEARCH;
+    {
+      normal = PATH_LOADSEARCH;
+      /* If the EMACSLOADPATH environment variable is set, use its value.
+         This doesn't apply if we're dumping.  */
+      if (egetenv ("EMACSLOADPATH"))
+        Vload_path = decode_env_path ("EMACSLOADPATH", normal);
+    }
   else
     normal = PATH_DUMPLOADSEARCH;
 
@@ -4138,184 +4164,158 @@ init_lread (void)
      the source directory, instead of the path of the installed elisp
      libraries.  However, if it appears that Vload_path has already been
      changed from the default that was saved before dumping, don't
-     change it further.  */
+     change it further.  Changes can only be due to EMACSLOADPATH, or
+     site-lisp files that were processed during dumping.  */
   if (initialized)
     {
-      if (! NILP (Fequal (dump_path, Vload_path)))
+      if (NILP (Fequal (dump_path, Vload_path)))
+        {
+          /* Do not make any changes, just check the elements exist.  */
+          /* Note: --no-site-lisp is ignored.
+             I don't know what to do about this.  */
+          load_path_check ();
+        }
+      else
        {
+#ifdef HAVE_NS
+         const char *loadpath = ns_load_path ();
+         Vload_path = decode_env_path (0, loadpath ? loadpath : normal);
+#else
          Vload_path = decode_env_path (0, normal);
-         if (no_site_lisp || !NILP (Vinstallation_directory))
+#endif
+         if (!NILP (Vinstallation_directory))
            {
-             Lisp_Object tem, tem1, sitelisp;
-
-             /* Remove "site-lisp" dirs from front of path temporarily
-                and store them in sitelisp, then conc them on at the
-                end so they're always first in path.
-                Note that this won't work if you used a
-                --enable-locallisppath element that does not happen
-                to contain "site-lisp" in its name.
-             */
-             sitelisp = Qnil;
-             while (1)
-               {
-                 tem = Fcar (Vload_path);
-                 tem1 = Fstring_match (build_string ("site-lisp"),
-                                       tem, Qnil);
-                 if (!NILP (tem1))
-                   {
-                     Vload_path = Fcdr (Vload_path);
-                     sitelisp = Fcons (tem, sitelisp);
-                   }
-                 else
-                   break;
-               }
-
-             if (!NILP (Vinstallation_directory))
-               {
-                 /* Add to the path the lisp subdir of the
-                    installation dir, if it exists.  */
-                 tem = Fexpand_file_name (build_string ("lisp"),
-                                          Vinstallation_directory);
-                 tem1 = Ffile_exists_p (tem);
-                 if (!NILP (tem1))
-                   {
-                     if (NILP (Fmember (tem, Vload_path)))
-                       {
-                         turn_off_warning = 1;
-                         Vload_path = Fcons (tem, Vload_path);
-                       }
-                   }
-                 else
-                   /* That dir doesn't exist, so add the build-time
-                      Lisp dirs instead.  */
-                   Vload_path = nconc2 (Vload_path, dump_path);
-
-                 /* Add leim under the installation dir, if it exists.  */
-                 tem = Fexpand_file_name (build_string ("leim"),
-                                          Vinstallation_directory);
-                 tem1 = Ffile_exists_p (tem);
-                 if (!NILP (tem1))
-                   {
-                     if (NILP (Fmember (tem, Vload_path)))
-                       Vload_path = Fcons (tem, Vload_path);
-                   }
-
-                 /* Add site-lisp under the installation dir, if it exists.  */
-                 if (!no_site_lisp)
-                   {
-                     tem = Fexpand_file_name (build_string ("site-lisp"),
-                                              Vinstallation_directory);
-                     tem1 = Ffile_exists_p (tem);
-                     if (!NILP (tem1))
-                       {
-                         if (NILP (Fmember (tem, Vload_path)))
-                           Vload_path = Fcons (tem, Vload_path);
-                       }
-                   }
-
-                 /* If Emacs was not built in the source directory,
-                    and it is run from where it was built, add to load-path
-                    the lisp, leim and site-lisp dirs under that directory.  */
-
-                 if (NILP (Fequal (Vinstallation_directory, Vsource_directory)))
-                   {
-                     Lisp_Object tem2;
-
-                     tem = Fexpand_file_name (build_string ("src/Makefile"),
-                                              Vinstallation_directory);
-                     tem1 = Ffile_exists_p (tem);
-
-                     /* Don't be fooled if they moved the entire source tree
-                        AFTER dumping Emacs.  If the build directory is indeed
-                        different from the source dir, src/Makefile.in and
-                        src/Makefile will not be found together.  */
-                     tem = Fexpand_file_name (build_string ("src/Makefile.in"),
-                                              Vinstallation_directory);
-                     tem2 = Ffile_exists_p (tem);
-                     if (!NILP (tem1) && NILP (tem2))
-                       {
-                         tem = Fexpand_file_name (build_string ("lisp"),
-                                                  Vsource_directory);
-
-                         if (NILP (Fmember (tem, Vload_path)))
-                           Vload_path = Fcons (tem, Vload_path);
-
-                         tem = Fexpand_file_name (build_string ("leim"),
-                                                  Vsource_directory);
-
-                         if (NILP (Fmember (tem, Vload_path)))
-                           Vload_path = Fcons (tem, Vload_path);
-
-                         if (!no_site_lisp)
-                           {
-                             tem = Fexpand_file_name (build_string ("site-lisp"),
-                                                      Vsource_directory);
-
-                             if (NILP (Fmember (tem, Vload_path)))
-                               Vload_path = Fcons (tem, Vload_path);
-                           }
-                       }
-                   } /* Vinstallation_directory != Vsource_directory */
-               }     /* if Vinstallation_directory */
-             if (!NILP (sitelisp) && !no_site_lisp)
-               Vload_path = nconc2 (Fnreverse (sitelisp), Vload_path);
-           } /* if Vinstallation_directory || no_site_lisp */
-       }     /* if dump_path == Vload_path */
+             Lisp_Object tem, tem1;
+
+              /* Add to the path the lisp subdir of the installation
+                 dir, if it exists.  Note: in out-of-tree builds,
+                 this directory is empty save for Makefile.  */
+              tem = Fexpand_file_name (build_string ("lisp"),
+                                       Vinstallation_directory);
+              tem1 = Ffile_exists_p (tem);
+              if (!NILP (tem1))
+                {
+                  if (NILP (Fmember (tem, Vload_path)))
+                    {
+                      /* We are running uninstalled.  The default load-path
+                         points to the eventual installed lisp, leim
+                         directories.  We should not use those now, even
+                         if they exist, so start over from a clean slate.  */
+                      Vload_path = Fcons (tem, Qnil);
+                    }
+                }
+              else
+                /* That dir doesn't exist, so add the build-time
+                   Lisp dirs instead.  */
+                Vload_path = nconc2 (Vload_path, dump_path);
+
+              /* Add leim under the installation dir, if it exists. */
+              tem = Fexpand_file_name (build_string ("leim"),
+                                       Vinstallation_directory);
+              tem1 = Ffile_exists_p (tem);
+              if (!NILP (tem1))
+                {
+                  if (NILP (Fmember (tem, Vload_path)))
+                    Vload_path = Fcons (tem, Vload_path);
+                }
+
+              /* Add site-lisp under the installation dir, if it exists.  */
+              if (!no_site_lisp)
+                {
+                  tem = Fexpand_file_name (build_string ("site-lisp"),
+                                           Vinstallation_directory);
+                  tem1 = Ffile_exists_p (tem);
+                  if (!NILP (tem1))
+                    {
+                      if (NILP (Fmember (tem, Vload_path)))
+                        Vload_path = Fcons (tem, Vload_path);
+                    }
+                }
+
+              /* If Emacs was not built in the source directory,
+                 and it is run from where it was built, add to load-path
+                 the lisp, leim and site-lisp dirs under that directory.  */
+
+              if (NILP (Fequal (Vinstallation_directory, Vsource_directory)))
+                {
+                  Lisp_Object tem2;
+
+                  tem = Fexpand_file_name (build_string ("src/Makefile"),
+                                           Vinstallation_directory);
+                  tem1 = Ffile_exists_p (tem);
+
+                  /* Don't be fooled if they moved the entire source tree
+                     AFTER dumping Emacs.  If the build directory is indeed
+                     different from the source dir, src/Makefile.in and
+                     src/Makefile will not be found together.  */
+                  tem = Fexpand_file_name (build_string ("src/Makefile.in"),
+                                           Vinstallation_directory);
+                  tem2 = Ffile_exists_p (tem);
+                  if (!NILP (tem1) && NILP (tem2))
+                    {
+                      tem = Fexpand_file_name (build_string ("lisp"),
+                                               Vsource_directory);
+
+                      if (NILP (Fmember (tem, Vload_path)))
+                        Vload_path = Fcons (tem, Vload_path);
+
+                      tem = Fexpand_file_name (build_string ("leim"),
+                                               Vsource_directory);
+
+                      if (NILP (Fmember (tem, Vload_path)))
+                        Vload_path = Fcons (tem, Vload_path);
+
+                      if (!no_site_lisp)
+                        {
+                          tem = Fexpand_file_name (build_string ("site-lisp"),
+                                                   Vsource_directory);
+
+                          if (NILP (Fmember (tem, Vload_path)))
+                            Vload_path = Fcons (tem, Vload_path);
+                        }
+                    }
+                } /* Vinstallation_directory != Vsource_directory */
+
+           } /* if Vinstallation_directory */
+
+          /* Check before adding the site-lisp directories.
+             The install should have created them, but they are not
+             required, so no need to warn if they are absent.
+             Or we might be running before installation.  */
+          load_path_check ();
+
+          /* Add the site-lisp directories at the front.  */
+#ifdef HAVE_NS
+          /* loadpath already includes the app-bundle's site-lisp.  */
+          if (!no_site_lisp && !loadpath)
+#else
+          if (!no_site_lisp)
+#endif
+            {
+              Lisp_Object sitelisp;
+              sitelisp = decode_env_path (0, PATH_SITELOADSEARCH);
+              if (! NILP (sitelisp)) Vload_path = nconc2 (sitelisp, Vload_path);
+            }
+       } /* if dump_path == Vload_path */
     }
   else                          /* !initialized */
     {
-      /* NORMAL refers to the lisp dir in the source directory.  */
-      /* We used to add ../lisp at the front here, but
-        that caused trouble because it was copied from dump_path
-        into Vload_path, above, when Vinstallation_directory was non-nil.
-        It should be unnecessary.  */
+      /* NORMAL refers to PATH_DUMPLOADSEARCH, ie the lisp dir in the
+         source directory.  We used to add ../lisp (ie the lisp dir in
+         the build directory) at the front here, but that caused trouble
+        because it was copied from dump_path into Vload_path, above,
+        when Vinstallation_directory was non-nil.  It should not be
+         necessary, since in out of tree builds lisp/ is empty, save
+         for Makefile.  */
       Vload_path = decode_env_path (0, normal);
       dump_path = Vload_path;
+      /* No point calling load_path_check; load-path only contains essential
+         elements from the source directory at this point.  They cannot
+         be missing unless something went extremely (and improbably)
+         wrong, in which case the build will fail in obvious ways.  */
     }
 #endif  /* CANNOT_DUMP */
 
-#if (!(defined (WINDOWSNT) || (defined (HAVE_NS))))
-  /* When Emacs is invoked over network shares on NT, PATH_LOADSEARCH is
-     almost never correct, thereby causing a warning to be printed out that
-     confuses users.  Since PATH_LOADSEARCH is always overridden by the
-     EMACSLOADPATH environment variable below, disable the warning on NT.  */
-
-  /* HAVE_NS also uses EMACSLOADPATH.  */
-
-  /* Warn if dirs in the *standard* path don't exist.  */
-  if (!turn_off_warning)
-    {
-      Lisp_Object path_tail;
-
-      for (path_tail = Vload_path;
-          !NILP (path_tail);
-          path_tail = XCDR (path_tail))
-       {
-         Lisp_Object dirfile;
-         dirfile = Fcar (path_tail);
-         if (STRINGP (dirfile))
-           {
-             dirfile = Fdirectory_file_name (dirfile);
-              /* Do we really need to warn about missing site-lisp dirs?
-                 It's true that the installation should have created
-                 them and added subdirs.el, but it's harmless if they
-                 are not there.  */
-             if (access (SSDATA (dirfile), 0) < 0)
-               dir_warning ("Warning: Lisp directory `%s' does not exist.\n",
-                            XCAR (path_tail));
-           }
-       }
-    }
-#endif /* !(WINDOWSNT || HAVE_NS) */
-
-  /* If the EMACSLOADPATH environment variable is set, use its value.
-     This doesn't apply if we're dumping.  */
-#ifndef CANNOT_DUMP
-  if (NILP (Vpurify_flag)
-      && egetenv ("EMACSLOADPATH"))
-#endif
-    Vload_path = decode_env_path ("EMACSLOADPATH", normal);
-
   Vvalues = Qnil;
 
   load_in_progress = 0;
@@ -4376,7 +4376,8 @@ to find all the symbols in an obarray, use `mapatoms'.  */);
 
   DEFVAR_LISP ("values", Vvalues,
               doc: /* List of values of all expressions which were read, evaluated and printed.
-Order is reverse chronological.  */);
+                      Order is reverse chronological.  */);
+  XSYMBOL (intern ("values"))->declared_special = 0;
 
   DEFVAR_LISP ("standard-input", Vstandard_input,
               doc: /* Stream for read to get input from.
@@ -4394,7 +4395,7 @@ defined, although they may be in the future.
 
 The positions are relative to the last call to `read' or
 `read-from-string'.  It is probably a bad idea to set this variable at
-the toplevel; bind it instead. */);
+the toplevel; bind it instead.  */);
   Vread_with_symbol_positions = Qnil;
 
   DEFVAR_LISP ("read-symbol-positions-list", Vread_symbol_positions_list,
@@ -4409,7 +4410,7 @@ symbol from the position where `read' or `read-from-string' started.
 
 Note that a symbol will appear multiple times in this list, if it was
 read multiple times.  The list is in the same order as the symbols
-were read in. */);
+were read in.  */);
   Vread_symbol_positions_list = Qnil;
 
   DEFVAR_LISP ("read-circle", Vread_circle,
@@ -4427,8 +4428,8 @@ otherwise to default specified by file `epaths.h' when Emacs was built.  */);
 This list should not include the empty string.
 `load' and related functions try to append these suffixes, in order,
 to the specified file name if a Lisp suffix is allowed or required.  */);
-  Vload_suffixes = Fcons (make_pure_c_string (".elc"),
-                         Fcons (make_pure_c_string (".el"), Qnil));
+  Vload_suffixes = Fcons (build_pure_c_string (".elc"),
+                         Fcons (build_pure_c_string (".el"), Qnil));
   DEFVAR_LISP ("load-file-rep-suffixes", Vload_file_rep_suffixes,
               doc: /* List of suffixes that indicate representations of \
 the same file.
@@ -4561,7 +4562,7 @@ from the file, and matches them against this regular expression.
 When the regular expression matches, the file is considered to be safe
 to load.  See also `load-dangerous-libraries'.  */);
   Vbytecomp_version_regexp
-    = make_pure_c_string ("^;;;.\\(in Emacs version\\|bytecomp version FSF\\)");
+    = build_pure_c_string ("^;;;.\\(in Emacs version\\|bytecomp version FSF\\)");
 
   Qlexical_binding = intern ("lexical-binding");
   staticpro (&Qlexical_binding);