X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/ce1d7b61f12dcc1b67535b68d9b0655b45fcadb6..2bfa3d3e1fb347ba76bddf77f3e288049635821d:/src/lread.c diff --git a/src/lread.c b/src/lread.c index a64f083a5a..e02a91f755 100644 --- a/src/lread.c +++ b/src/lread.c @@ -1,6 +1,7 @@ /* Lisp parsing and input streams. -Copyright (C) 1985-1989, 1993-1995, 1997-2013 Free Software Foundation, Inc. +Copyright (C) 1985-1989, 1993-1995, 1997-2014 Free Software Foundation, +Inc. This file is part of GNU Emacs. @@ -212,7 +213,7 @@ readchar (Lisp_Object readcharfun, bool *multibyte) else { c = BUF_FETCH_BYTE (inbuffer, pt_byte); - if (! ASCII_BYTE_P (c)) + if (! ASCII_CHAR_P (c)) c = BYTE8_TO_CHAR (c); pt_byte++; } @@ -241,7 +242,7 @@ readchar (Lisp_Object readcharfun, bool *multibyte) else { c = BUF_FETCH_BYTE (inbuffer, bytepos); - if (! ASCII_BYTE_P (c)) + if (! ASCII_CHAR_P (c)) c = BYTE8_TO_CHAR (c); bytepos++; } @@ -323,7 +324,7 @@ readchar (Lisp_Object readcharfun, bool *multibyte) return c; if (multibyte) *multibyte = 1; - if (ASCII_BYTE_P (c)) + if (ASCII_CHAR_P (c)) return c; if (emacs_mule_encoding) return read_emacs_mule_char (c, readbyte, readcharfun); @@ -1029,6 +1030,10 @@ in `load-file-rep-suffixes'. If MUST-SUFFIX is non-nil, only the return value of `get-load-suffixes' is used, i.e. the file name is required to have a non-empty suffix. +When searching suffixes, this function normally stops at the first +one that exists. If the option `load-prefer-newer' is non-nil, +however, it tries all suffixes, and uses whichever file is the newest. + Loading a file records its definitions, and its `provide' and `require' calls, in an element of `load-history' whose car is the file name loaded. See `load-history'. @@ -1041,10 +1046,9 @@ Return t if the file exists and loads successfully. */) (Lisp_Object file, Lisp_Object noerror, Lisp_Object nomessage, Lisp_Object nosuffix, Lisp_Object must_suffix) { - FILE *stream; + FILE *stream = NULL; int fd; - int fd_index; - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); struct gcpro gcpro1, gcpro2, gcpro3; Lisp_Object found, efound, hist_file_name; /* True means we printed the ".el is newer" message. */ @@ -1080,8 +1084,10 @@ Return t if the file exists and loads successfully. */) { file = internal_condition_case_1 (Fsubstitute_in_file_name, file, Qt, load_error_handler); - if (NILP (file)) - return Qnil; + if (NILP (file)) { + dynwind_end (); + return Qnil; + } } else file = Fsubstitute_in_file_name (file); @@ -1129,7 +1135,7 @@ Return t if the file exists and loads successfully. */) } } - fd = openp (Vload_path, file, suffixes, &found, Qnil); + fd = openp (Vload_path, file, suffixes, &found, Qnil, load_prefer_newer); UNGCPRO; } @@ -1137,6 +1143,7 @@ Return t if the file exists and loads successfully. */) { if (NILP (noerror)) report_file_error ("Cannot open load file", file); + dynwind_end (); return Qnil; } @@ -1154,8 +1161,10 @@ Return t if the file exists and loads successfully. */) handler = Ffind_file_name_handler (found, Qt); else handler = Ffind_file_name_handler (found, Qload); - if (! NILP (handler)) - return call5 (handler, Qload, found, noerror, nomessage, Qt); + if (! NILP (handler)) { + dynwind_end (); + return call5 (handler, Qload, found, noerror, nomessage, Qt); + } #ifdef DOS_NT /* Tramp has to deal with semi-broken packages that prepend drive letters to remote files. For that reason, Tramp @@ -1174,15 +1183,10 @@ Return t if the file exists and loads successfully. */) #endif } - if (fd < 0) - { - /* Pacify older GCC with --enable-gcc-warnings. */ - IF_LINT (fd_index = 0); - } - else + if (fd >= 0) { - fd_index = SPECPDL_INDEX (); - record_unwind_protect_int (close_file_unwind, fd); + record_unwind_protect_ptr (close_file_ptr_unwind, &fd); + record_unwind_protect_ptr (fclose_ptr_unwind, &stream); } /* Check if we're stuck in a recursive load cycle. @@ -1252,29 +1256,36 @@ Return t if the file exists and loads successfully. */) #ifdef DOS_NT fmode = "rb"; #endif /* DOS_NT */ - result = stat (SSDATA (efound), &s1); - if (result == 0) - { - SSET (efound, SBYTES (efound) - 1, 0); - result = stat (SSDATA (efound), &s2); - SSET (efound, SBYTES (efound) - 1, 'c'); - } - if (result == 0 - && timespec_cmp (get_stat_mtime (&s1), get_stat_mtime (&s2)) < 0) - { - /* Make the progress messages mention that source is newer. */ - newer = 1; + /* openp already checked for newness, no point doing it again. + FIXME would be nice to get a message when openp + ignores suffix order due to load_prefer_newer. */ + if (!load_prefer_newer) + { + result = stat (SSDATA (efound), &s1); + if (result == 0) + { + SSET (efound, SBYTES (efound) - 1, 0); + result = stat (SSDATA (efound), &s2); + SSET (efound, SBYTES (efound) - 1, 'c'); + } - /* If we won't print another message, mention this anyway. */ - if (!NILP (nomessage) && !force_load_messages) - { - Lisp_Object msg_file; - msg_file = Fsubstring (found, make_number (0), make_number (-1)); - message_with_string ("Source file `%s' newer than byte-compiled file", - msg_file, 1); - } - } + if (result == 0 + && timespec_cmp (get_stat_mtime (&s1), get_stat_mtime (&s2)) < 0) + { + /* Make the progress messages mention that source is newer. */ + newer = 1; + + /* If we won't print another message, mention this anyway. */ + if (!NILP (nomessage) && !force_load_messages) + { + Lisp_Object msg_file; + msg_file = Fsubstring (found, make_number (0), make_number (-1)); + message_with_string ("Source file `%s' newer than byte-compiled file", + msg_file, 1); + } + } + } /* !load_prefer_newer */ UNGCPRO; } } @@ -1288,12 +1299,13 @@ Return t if the file exists and loads successfully. */) if (fd >= 0) { emacs_close (fd); - clear_unwind_protect (fd_index); + fd = -1; } val = call4 (Vload_source_file_function, found, hist_file_name, NILP (noerror) ? Qnil : Qt, (NILP (nomessage) || force_load_messages) ? Qnil : Qt); - return unbind_to (count, val); + dynwind_end (); + return val; } } @@ -1311,7 +1323,7 @@ Return t if the file exists and loads successfully. */) { #ifdef WINDOWSNT emacs_close (fd); - clear_unwind_protect (fd_index); + fd = -1; efound = ENCODE_FILE (found); stream = emacs_fopen (SSDATA (efound), fmode); #else @@ -1320,7 +1332,6 @@ Return t if the file exists and loads successfully. */) } if (! stream) report_file_error ("Opening stdio stream", file); - set_unwind_protect_ptr (fd_index, fclose_unwind, stream); if (! NILP (Vpurify_flag)) Vpreloaded_file_list = Fcons (Fpurecopy (file), Vpreloaded_file_list); @@ -1358,7 +1369,7 @@ Return t if the file exists and loads successfully. */) readevalloop (Qget_emacs_mule_file_char, stream, hist_file_name, 0, Qnil, Qnil, Qnil, Qnil); } - unbind_to (count, Qnil); + dynwind_end (); /* Run any eval-after-load forms for this file. */ if (!NILP (Ffboundp (Qdo_after_load_evaluation))) @@ -1413,7 +1424,7 @@ directories, make sure the PREDICATE function returns `dir-ok' for them. */) (Lisp_Object filename, Lisp_Object path, Lisp_Object suffixes, Lisp_Object predicate) { Lisp_Object file; - int fd = openp (path, filename, suffixes, &file, predicate); + int fd = openp (path, filename, suffixes, &file, predicate, false); if (NILP (predicate) && fd >= 0) emacs_close (fd); return file; @@ -1440,22 +1451,31 @@ static Lisp_Object Qdir_ok; nil is stored there on failure. If the file we find is remote, return -2 - but store the found remote file name in *STOREPTR. */ + but store the found remote file name in *STOREPTR. + + If NEWER is true, try all SUFFIXes and return the result for the + newest file that exists. Does not apply to remote files, + or if PREDICATE is specified. */ int openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, - Lisp_Object *storeptr, Lisp_Object predicate) + Lisp_Object *storeptr, Lisp_Object predicate, bool newer) { ptrdiff_t fn_size = 100; char buf[100]; char *fn = buf; - bool absolute = 0; + bool absolute; ptrdiff_t want_length; Lisp_Object filename; - struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6; - Lisp_Object string, tail, encoded_fn; + struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6, gcpro7; + Lisp_Object string, tail, encoded_fn, save_string; ptrdiff_t max_suffix_len = 0; int last_errno = ENOENT; + int save_fd = -1; + + /* The last-modified time of the newest matching file found. + Initialize it to something less than all valid timestamps. */ + struct timespec save_mtime = make_timespec (TYPE_MINIMUM (time_t), -1); CHECK_STRING (str); @@ -1466,14 +1486,13 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, SBYTES (XCAR (tail))); } - string = filename = encoded_fn = Qnil; - GCPRO6 (str, string, filename, path, suffixes, encoded_fn); + string = filename = encoded_fn = save_string = Qnil; + GCPRO7 (str, string, save_string, filename, path, suffixes, encoded_fn); if (storeptr) *storeptr = Qnil; - if (complete_filename_p (str)) - absolute = 1; + absolute = complete_filename_p (str); for (; CONSP (path); path = XCDR (path)) { @@ -1543,30 +1562,31 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, { Lisp_Object tmp = call1 (predicate, string); if (NILP (tmp)) - exists = 0; + exists = false; else if (EQ (tmp, Qdir_ok) || NILP (Ffile_directory_p (string))) - exists = 1; + exists = true; else { - exists = 0; + exists = false; last_errno = EISDIR; } } if (exists) { - /* We succeeded; return this descriptor and filename. */ - if (storeptr) - *storeptr = string; - UNGCPRO; - return -2; + /* We succeeded; return this descriptor and filename. */ + if (storeptr) + *storeptr = string; + UNGCPRO; + return -2; } } else { int fd; const char *pfn; + struct stat st; encoded_fn = ENCODE_FILE (string); pfn = SSDATA (encoded_fn); @@ -1597,7 +1617,6 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, } else { - struct stat st; int err = (fstat (fd, &st) != 0 ? errno : S_ISDIR (st.st_mode) ? EISDIR : 0); if (err) @@ -1611,12 +1630,39 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, if (fd >= 0) { - /* We succeeded; return this descriptor and filename. */ - if (storeptr) - *storeptr = string; - UNGCPRO; - return fd; + if (newer && !NATNUMP (predicate)) + { + struct timespec mtime = get_stat_mtime (&st); + + if (timespec_cmp (mtime, save_mtime) <= 0) + emacs_close (fd); + else + { + if (0 <= save_fd) + emacs_close (save_fd); + save_fd = fd; + save_mtime = mtime; + save_string = string; + } + } + else + { + /* We succeeded; return this descriptor and filename. */ + if (storeptr) + *storeptr = string; + UNGCPRO; + return fd; + } } + + /* No more suffixes. Return the newest. */ + if (0 <= save_fd && ! CONSP (XCDR (tail))) + { + if (storeptr) + *storeptr = save_string; + UNGCPRO; + return save_fd; + } } } if (absolute) @@ -1716,6 +1762,29 @@ end_of_file_error (void) xsignal0 (Qend_of_file); } +static Lisp_Object +readevalloop_eager_expand_eval (Lisp_Object val, Lisp_Object macroexpand) +{ + /* If we macroexpand the toplevel form non-recursively and it ends + up being a `progn' (or if it was a progn to start), treat each + form in the progn as a top-level form. This way, if one form in + the progn defines a macro, that macro is in effect when we expand + the remaining forms. See similar code in bytecomp.el. */ + val = call2 (macroexpand, val, Qnil); + if (EQ (CAR_SAFE (val), Qprogn)) + { + Lisp_Object subforms = XCDR (val); + val = Qnil; + for (; CONSP (subforms); subforms = XCDR (subforms)) + val = readevalloop_eager_expand_eval (XCAR (subforms), + macroexpand); + } + else + val = eval_sub (call2 (macroexpand, val, Qt)); + + return val; +} + /* UNIBYTE specifies how to set load_convert_to_unibyte for this invocation. READFUN, if non-nil, is used instead of `read'. @@ -1733,7 +1802,7 @@ readevalloop (Lisp_Object readcharfun, { register int c; register Lisp_Object val; - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; struct buffer *b = 0; bool continue_reading_p; @@ -1795,7 +1864,7 @@ readevalloop (Lisp_Object readcharfun, continue_reading_p = 1; while (continue_reading_p) { - ptrdiff_t count1 = SPECPDL_INDEX (); + dynwind_begin (); if (b != 0 && !BUFFER_LIVE_P (b)) error ("Reading from killed buffer"); @@ -1838,7 +1907,7 @@ readevalloop (Lisp_Object readcharfun, } if (c < 0) { - unbind_to (count1, Qnil); + dynwind_end (); break; } @@ -1879,12 +1948,13 @@ readevalloop (Lisp_Object readcharfun, start = Fpoint_marker (); /* Restore saved point and BEGV. */ - unbind_to (count1, Qnil); + dynwind_end (); /* Now eval what we just read. */ if (!NILP (macroexpand)) - val = call1 (macroexpand, val); - val = eval_sub (val); + val = readevalloop_eager_expand_eval (val, macroexpand); + else + val = eval_sub (val); if (printflag) { @@ -1903,7 +1973,7 @@ readevalloop (Lisp_Object readcharfun, UNGCPRO; - unbind_to (count, Qnil); + dynwind_end (); } DEFUN ("eval-buffer", Feval_buffer, Seval_buffer, 0, 5, "", @@ -1922,7 +1992,7 @@ DO-ALLOW-PRINT, if non-nil, specifies that `print' and related This function preserves the position of point. */) (Lisp_Object buffer, Lisp_Object printflag, Lisp_Object filename, Lisp_Object unibyte, Lisp_Object do_allow_print) { - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); Lisp_Object tem, buf; if (NILP (buffer)) @@ -1947,7 +2017,7 @@ This function preserves the position of point. */) specbind (Qlexical_binding, lisp_file_lexically_bound_p (buf) ? Qt : Qnil); readevalloop (buf, 0, filename, !NILP (printflag), unibyte, Qnil, Qnil, Qnil); - unbind_to (count, Qnil); + dynwind_end (); return Qnil; } @@ -1967,7 +2037,7 @@ This function does not move point. */) (Lisp_Object start, Lisp_Object end, Lisp_Object printflag, Lisp_Object read_function) { /* FIXME: Do the eval-sexp-add-defvars dance! */ - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); Lisp_Object tem, cbuf; cbuf = Fcurrent_buffer (); @@ -1984,7 +2054,8 @@ This function does not move point. */) !NILP (printflag), Qnil, read_function, start, end); - return unbind_to (count, Qnil); + dynwind_end (); + return Qnil; } @@ -2006,7 +2077,7 @@ STREAM or the value of `standard-input' may be: if (EQ (stream, Qt)) stream = Qread_char; if (EQ (stream, Qread_char)) - /* FIXME: ¿¡ When is this used !? */ + /* FIXME: ?! When is this used !? */ return call1 (intern ("read-minibuffer"), build_string ("Lisp expression: ")); @@ -2564,7 +2635,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) XSETPVECTYPE (XVECTOR (tmp), PVEC_SUB_CHAR_TABLE); return tmp; } - invalid_syntax ("#^^"); + invalid_syntax ("#^" "^"); } invalid_syntax ("#^"); } @@ -2607,9 +2678,10 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) /* Accept compiled functions at read-time so that we don't have to build them using function calls. */ Lisp_Object tmp; + struct Lisp_Vector *vec; tmp = read_vector (readcharfun, 1); - struct Lisp_Vector* vec = XVECTOR (tmp); - if (vec->header.size==0) + vec = XVECTOR (tmp); + if (vec->header.size == 0) invalid_syntax ("Empty byte-code object"); make_byte_code (vec); return tmp; @@ -2706,7 +2778,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) if (saved_doc_string_size == 0) { - saved_doc_string = xmalloc (nskip + extra); + saved_doc_string = xmalloc_atomic (nskip + extra); saved_doc_string_size = nskip + extra; } if (nskip > saved_doc_string_size) @@ -3235,58 +3307,52 @@ substitute_object_recurse (Lisp_Object object, Lisp_Object placeholder, Lisp_Obj /* Recurse according to subtree's type. Every branch must return a Lisp_Object. */ - switch (XTYPE (subtree)) + if (VECTORLIKEP (subtree)) { - case Lisp_Vectorlike: - { - ptrdiff_t i, length = 0; - if (BOOL_VECTOR_P (subtree)) - return subtree; /* No sub-objects anyway. */ - else if (CHAR_TABLE_P (subtree) || SUB_CHAR_TABLE_P (subtree) - || COMPILEDP (subtree) || HASH_TABLE_P (subtree)) - length = ASIZE (subtree) & PSEUDOVECTOR_SIZE_MASK; - else if (VECTORP (subtree)) - length = ASIZE (subtree); - else - /* An unknown pseudovector may contain non-Lisp fields, so we - can't just blindly traverse all its fields. We used to call - `Flength' which signaled `sequencep', so I just preserved this - behavior. */ - wrong_type_argument (Qsequencep, subtree); - - for (i = 0; i < length; i++) - SUBSTITUTE (AREF (subtree, i), - ASET (subtree, i, true_value)); - return subtree; - } - - case Lisp_Cons: - { - SUBSTITUTE (XCAR (subtree), - XSETCAR (subtree, true_value)); - SUBSTITUTE (XCDR (subtree), - XSETCDR (subtree, true_value)); - return subtree; - } - - case Lisp_String: - { - /* Check for text properties in each interval. - substitute_in_interval contains part of the logic. */ - - INTERVAL root_interval = string_intervals (subtree); - Lisp_Object arg = Fcons (object, placeholder); + ptrdiff_t i, length = 0; + if (BOOL_VECTOR_P (subtree)) + return subtree; /* No sub-objects anyway. */ + else if (CHAR_TABLE_P (subtree) || SUB_CHAR_TABLE_P (subtree) + || COMPILEDP (subtree) || HASH_TABLE_P (subtree)) + length = ASIZE (subtree) & PSEUDOVECTOR_SIZE_MASK; + else if (VECTORP (subtree)) + length = ASIZE (subtree); + else + /* An unknown pseudovector may contain non-Lisp fields, so we + can't just blindly traverse all its fields. We used to call + `Flength' which signaled `sequencep', so I just preserved this + behavior. */ + wrong_type_argument (Qsequencep, subtree); + + for (i = 0; i < length; i++) + SUBSTITUTE (AREF (subtree, i), + ASET (subtree, i, true_value)); + return subtree; + } + else if (CONSP (subtree)) + { + SUBSTITUTE (XCAR (subtree), + XSETCAR (subtree, true_value)); + SUBSTITUTE (XCDR (subtree), + XSETCDR (subtree, true_value)); + return subtree; + } + else if (STRINGP (subtree)) + { + /* Check for text properties in each interval. + substitute_in_interval contains part of the logic. */ - traverse_intervals_noorder (root_interval, - &substitute_in_interval, arg); + INTERVAL root_interval = string_intervals (subtree); + Lisp_Object arg = Fcons (object, placeholder); - return subtree; - } + traverse_intervals_noorder (root_interval, + &substitute_in_interval, arg); - /* Other types don't recurse any further. */ - default: return subtree; } + else + /* Other types don't recurse any further. */ + return subtree; } /* Helper function for substitute_object_recurse. */ @@ -3465,7 +3531,6 @@ read_vector (Lisp_Object readcharfun, bool bytecodeflag) ptrdiff_t i, size; Lisp_Object *ptr; Lisp_Object tem, item, vector; - struct Lisp_Cons *otem; Lisp_Object len; tem = read_list (1, readcharfun); @@ -3510,10 +3575,8 @@ read_vector (Lisp_Object readcharfun, bool bytecodeflag) if (!CONSP (item)) error ("Invalid byte code"); - otem = XCONS (item); bytestr = XCAR (item); item = XCDR (item); - free_cons (otem); } /* Now handle the bytecode slot. */ @@ -3530,9 +3593,7 @@ read_vector (Lisp_Object readcharfun, bool bytecodeflag) } } ASET (vector, i, item); - otem = XCONS (tem); tem = Fcdr (tem); - free_cons (otem); } return vector; } @@ -3778,7 +3839,7 @@ it defaults to the value of `obarray'. */) SET_SYMBOL_VAL (XSYMBOL (sym), sym); } - ptr = aref_addr (obarray, XINT(tem)); + ptr = aref_addr (obarray, XINT (tem)); if (SYMBOLP (*ptr)) set_symbol_next (sym, XSYMBOL (*ptr)); else @@ -3820,7 +3881,8 @@ DEFUN ("unintern", Funintern, Sunintern, 1, 2, 0, The value is t if a symbol was found and deleted, nil otherwise. NAME may be a string or a symbol. If it is a symbol, that symbol is deleted, if it belongs to OBARRAY--no other symbol is deleted. -OBARRAY defaults to the value of the variable `obarray'. */) +OBARRAY, if nil, defaults to the value of the variable `obarray'. +usage: (unintern NAME OBARRAY) */) (Lisp_Object name, Lisp_Object obarray) { register Lisp_Object string, tem; @@ -3890,7 +3952,8 @@ OBARRAY defaults to the value of the variable `obarray'. */) /* Return the symbol in OBARRAY whose names matches the string of SIZE characters (SIZE_BYTE bytes) at PTR. - If there is no such symbol in OBARRAY, return nil. + If there is no such symbol, return the integer bucket number of + where the symbol would be if it were present. Also store the bucket number in oblookup_last_bucket_number. */ @@ -3904,9 +3967,6 @@ oblookup (Lisp_Object obarray, register const char *ptr, ptrdiff_t size, ptrdiff obarray = check_obarray (obarray); obsize = ASIZE (obarray); - - /* This is sometimes needed in the middle of GC. */ - obsize &= ~ARRAY_MARK_FLAG; hash = hash_string (ptr, size_byte) % obsize; bucket = AREF (obarray, hash); oblookup_last_bucket_number = hash; @@ -4007,7 +4067,7 @@ init_obarray (void) DEFSYM (Qvariable_documentation, "variable-documentation"); - read_buffer = xmalloc (size); + read_buffer = xmalloc_atomic (size); read_buffer_size = size; } @@ -4016,21 +4076,12 @@ defsubr (struct Lisp_Subr *sname) { Lisp_Object sym, tem; sym = intern_c_string (sname->symbol_name); + SCM_NEWSMOB (sname->header.self, lisp_vectorlike_tag, sname); XSETPVECTYPE (sname, PVEC_SUBR); XSETSUBR (tem, sname); set_symbol_function (sym, tem); } -#ifdef NOTDEF /* Use fset in subr.el now! */ -void -defalias (struct Lisp_Subr *sname, char *string) -{ - Lisp_Object sym; - sym = intern (string); - XSETSUBR (XSYMBOL (sym)->function, sname); -} -#endif /* NOTDEF */ - /* Define an "integer variable"; a symbol whose value is forwarded to a C variable of type EMACS_INT. Sample call (with "xx" to fool make-docfile): DEFxxVAR_INT ("emacs-priority", &emacs_priority, "Documentation"); */ @@ -4128,10 +4179,6 @@ load_path_check (Lisp_Object lpath) } } -/* 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; - /* Return the default load-path, to be used if EMACSLOADPATH is unset. This does not include the standard site-lisp directories under the installation prefix (i.e., PATH_SITELOADSEARCH), @@ -4145,18 +4192,16 @@ static Lisp_Object dump_path; If purify-flag (ie dumping) just use PATH_DUMPLOADSEARCH. Otherwise use PATH_LOADSEARCH. - If !initialized, then just set dump_path and return PATH_DUMPLOADSEARCH. - If initialized, then if Vload_path != dump_path, return just Vload_path. - (Presumably the load-path has already been changed by something. - This can only be from a site-load file during dumping.) + If !initialized, then just return PATH_DUMPLOADSEARCH. + If initialized: 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. + If installation-dir/lisp does not exist, just add + PATH_DUMPLOADSEARCH at the end instead. 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, @@ -4165,7 +4210,7 @@ static Lisp_Object dump_path; check), then repeat the above steps for source-dir/lisp, site-lisp. */ static Lisp_Object -load_path_default (bool changed) +load_path_default (void) { Lisp_Object lpath = Qnil; const char *normal; @@ -4186,131 +4231,108 @@ load_path_default (bool changed) normal = NILP (Vpurify_flag) ? PATH_LOADSEARCH : PATH_DUMPLOADSEARCH; - /* In a dumped Emacs, we normally reset the value of Vload_path using - PATH_LOADSEARCH, since the value that was dumped uses lisp/ in - 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. Changes can only be due to site-lisp - files that were processed during dumping. */ - /* FIXME? AFAICS, it does not make sense to change load-path in a - dumped site-lisp file, so maybe we should just drop this check. - E.g., if you add an element to load-path, you are going to be - adding it to PATH_DUMPLOADSEARCH, which refers to the source directory. - This will make no sense (and may not still exist) in an installed Emacs. - And the only change it is sensible to make to load-path is to add - something to the front, which you should do with configure's - --enable-locallisppath option if you really want to have it dumped. */ if (initialized) { - if (changed || NILP (Fequal (dump_path, Vload_path))) - { - /* Do not make any changes. */ - return Vload_path; - } - else - { #ifdef HAVE_NS - const char *loadpath = ns_load_path (); - lpath = decode_env_path (0, loadpath ? loadpath : normal, 0); + const char *loadpath = ns_load_path (); + lpath = decode_env_path (0, loadpath ? loadpath : normal, 0); #else - lpath = decode_env_path (0, normal, 0); + lpath = decode_env_path (0, normal, 0); #endif - if (!NILP (Vinstallation_directory)) + if (!NILP (Vinstallation_directory)) + { + Lisp_Object tem, tem1; + + /* Add to the path the lisp subdir of the installation + dir, if it is accessible. Note: in out-of-tree builds, + this directory is empty save for Makefile. */ + tem = Fexpand_file_name (build_string ("lisp"), + Vinstallation_directory); + tem1 = Ffile_accessible_directory_p (tem); + if (!NILP (tem1)) { - Lisp_Object tem, tem1; + if (NILP (Fmember (tem, lpath))) + { + /* We are running uninstalled. The default load-path + points to the eventual installed lisp directories. + We should not use those now, even if they exist, + so start over from a clean slate. */ + lpath = list1 (tem); + } + } + else + /* That dir doesn't exist, so add the build-time + Lisp dirs instead. */ + { + Lisp_Object dump_path = + decode_env_path (0, PATH_DUMPLOADSEARCH, 0); + lpath = nconc2 (lpath, dump_path); + } - /* Add to the path the lisp subdir of the installation - dir, if it is accessible. Note: in out-of-tree builds, - this directory is empty save for Makefile. */ - tem = Fexpand_file_name (build_string ("lisp"), + /* 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_accessible_directory_p (tem); if (!NILP (tem1)) { if (NILP (Fmember (tem, lpath))) - { - /* We are running uninstalled. The default load-path - points to the eventual installed lisp directories. - We should not use those now, even if they exist, - so start over from a clean slate. */ - lpath = list1 (tem); - } + lpath = Fcons (tem, lpath); } - else - /* That dir doesn't exist, so add the build-time - Lisp dirs instead. */ - lpath = nconc2 (lpath, dump_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_accessible_directory_p (tem); - if (!NILP (tem1)) - { - if (NILP (Fmember (tem, lpath))) - lpath = Fcons (tem, lpath); - } - } + /* If Emacs was not built in the source directory, + and it is run from where it was built, add to load-path + the lisp and site-lisp dirs under that directory. */ - /* If Emacs was not built in the source directory, - and it is run from where it was built, add to load-path - the lisp 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); - if (NILP (Fequal (Vinstallation_directory, Vsource_directory))) + /* 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)) { - 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); + tem = Fexpand_file_name (build_string ("lisp"), + Vsource_directory); - if (NILP (Fmember (tem, lpath))) - lpath = Fcons (tem, lpath); + if (NILP (Fmember (tem, lpath))) + lpath = Fcons (tem, lpath); - if (!no_site_lisp) + if (!no_site_lisp) + { + tem = Fexpand_file_name (build_string ("site-lisp"), + Vsource_directory); + tem1 = Ffile_accessible_directory_p (tem); + if (!NILP (tem1)) { - tem = Fexpand_file_name (build_string ("site-lisp"), - Vsource_directory); - tem1 = Ffile_accessible_directory_p (tem); - if (!NILP (tem1)) - { - if (NILP (Fmember (tem, lpath))) - lpath = Fcons (tem, lpath); - } + if (NILP (Fmember (tem, lpath))) + lpath = Fcons (tem, lpath); } } - } /* Vinstallation_directory != Vsource_directory */ - - } /* if Vinstallation_directory */ + } + } /* Vinstallation_directory != Vsource_directory */ - } /* if dump_path == Vload_path */ + } /* if Vinstallation_directory */ } else /* !initialized */ { /* 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 + the build directory) at the front here, but that should not + be necessary, since in out of tree builds lisp/ is empty, save for Makefile. */ lpath = decode_env_path (0, normal, 0); - dump_path = lpath; } #endif /* !CANNOT_DUMP */ @@ -4322,27 +4344,26 @@ init_lread (void) { /* First, set Vload_path. */ - /* NB: Do not change Vload_path before calling load_path_default, - since it may check it against dump_path. - (This behavior could be changed.) */ + /* Ignore EMACSLOADPATH when dumping. */ +#ifdef CANNOT_DUMP + bool use_loadpath = true; +#else + bool use_loadpath = NILP (Vpurify_flag); +#endif - /* We explicitly ignore EMACSLOADPATH when dumping. */ - if (NILP (Vpurify_flag) && egetenv ("EMACSLOADPATH")) + if (use_loadpath && egetenv ("EMACSLOADPATH")) { - Lisp_Object elpath = decode_env_path ("EMACSLOADPATH", 0, 1); + Vload_path = decode_env_path ("EMACSLOADPATH", 0, 1); /* Check (non-nil) user-supplied elements. */ - load_path_check (elpath); + load_path_check (Vload_path); /* If no nils in the environment variable, use as-is. Otherwise, replace any nils with the default. */ - if (NILP (Fmemq (Qnil, elpath))) + if (! NILP (Fmemq (Qnil, Vload_path))) { - Vload_path = elpath; - } - else - { - Lisp_Object elem, default_lpath = load_path_default (0); + Lisp_Object elem, elpath = Vload_path; + Lisp_Object default_lpath = load_path_default (); /* Check defaults, before adding site-lisp. */ load_path_check (default_lpath); @@ -4370,15 +4391,9 @@ init_lread (void) } } /* Fmemq (Qnil, Vload_path) */ } - else /* Vpurify_flag || !EMACSLOADPATH */ + else { -#ifdef CANNOT_DUMP - bool changed = 0; -#else - bool changed = initialized && NILP (Fequal (dump_path, Vload_path)); -#endif - - Vload_path = load_path_default (changed); + Vload_path = load_path_default (); /* Check before adding site-lisp directories. The install should have created them, but they are not @@ -4386,16 +4401,14 @@ init_lread (void) Or we might be running before installation. */ load_path_check (Vload_path); - /* Add the site-lisp directories at the front, unless the - load-path has already been changed. - FIXME? Should we ignore changed here? */ - if (initialized && !no_site_lisp && !changed) + /* Add the site-lisp directories at the front. */ + if (initialized && !no_site_lisp) { Lisp_Object sitelisp; sitelisp = decode_env_path (0, PATH_SITELOADSEARCH, 0); if (! NILP (sitelisp)) Vload_path = nconc2 (sitelisp, Vload_path); } - } /* !Vpurify_flag && EMACSLOADPATH */ + } Vvalues = Qnil; @@ -4435,21 +4448,7 @@ dir_warning (char const *use, Lisp_Object dirname) void syms_of_lread (void) { - defsubr (&Sread); - defsubr (&Sread_from_string); - defsubr (&Sintern); - defsubr (&Sintern_soft); - defsubr (&Sunintern); - defsubr (&Sget_load_suffixes); - defsubr (&Sload); - defsubr (&Seval_buffer); - defsubr (&Seval_region); - defsubr (&Sread_char); - defsubr (&Sread_char_exclusive); - defsubr (&Sread_event); - defsubr (&Sget_file_char); - defsubr (&Smapatoms); - defsubr (&Slocate_file_internal); +#include "lread.x" DEFVAR_LISP ("obarray", Vobarray, doc: /* Symbol table for use by `intern' and `read'. @@ -4670,6 +4669,18 @@ variables, this must be set in the first line of a file. */); Vold_style_backquotes = Qnil; DEFSYM (Qold_style_backquotes, "old-style-backquotes"); + DEFVAR_BOOL ("load-prefer-newer", load_prefer_newer, + doc: /* Non-nil means `load' prefers the newest version of a file. +This applies when a filename suffix is not explicitly specified and +`load' is trying various possible suffixes (see `load-suffixes' and +`load-file-rep-suffixes'). Normally, it stops at the first file +that exists unless you explicitly specify one or the other. If this +option is non-nil, it checks all suffixes and uses whichever file is +newest. +Note that if you customize this, obviously it will not affect files +that are loaded before your customizations are read! */); + load_prefer_newer = 0; + /* Vsource_directory was initialized in init_lread. */ DEFSYM (Qcurrent_load_list, "current-load-list"); @@ -4694,8 +4705,6 @@ variables, this must be set in the first line of a file. */); DEFSYM (Qdir_ok, "dir-ok"); DEFSYM (Qdo_after_load_evaluation, "do-after-load-evaluation"); - staticpro (&dump_path); - staticpro (&read_objects); read_objects = Qnil; staticpro (&seen_list);