/* 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.
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++;
}
else
{
c = BUF_FETCH_BYTE (inbuffer, bytepos);
- if (! ASCII_BYTE_P (c))
+ if (! ASCII_CHAR_P (c))
c = BYTE8_TO_CHAR (c);
bytepos++;
}
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);
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'.
(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. */
{
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);
{
if (NILP (noerror))
report_file_error ("Cannot open load file", file);
+ dynwind_end ();
return Qnil;
}
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
#endif
}
- if (fd < 0)
+ if (fd >= 0)
{
- /* Pacify older GCC with --enable-gcc-warnings. */
- IF_LINT (fd_index = 0);
- }
- else
- {
- 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.
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;
}
}
{
#ifdef WINDOWSNT
emacs_close (fd);
- clear_unwind_protect (fd_index);
+ fd = -1;
efound = ENCODE_FILE (found);
stream = emacs_fopen (SSDATA (efound), fmode);
#else
}
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);
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)))
(Lisp_Object filename, Lisp_Object path, Lisp_Object suffixes, Lisp_Object predicate)
{
Lisp_Object file;
- int fd = openp (path, filename, suffixes, &file, predicate, 0);
+ int fd = openp (path, filename, suffixes, &file, predicate, false);
if (NILP (predicate) && fd >= 0)
emacs_close (fd);
return file;
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. */
+ 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, int newer)
+ 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;
+ 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;
- struct timespec save_mtime;
- int save_fd = 0;
+ 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);
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))
{
{
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 (fd >= 0)
{
- if (newer)
+ if (newer && !NATNUMP (predicate))
{
struct timespec mtime = get_stat_mtime (&st);
- if (!save_fd || timespec_cmp (save_mtime, mtime) < 0)
+ if (timespec_cmp (mtime, save_mtime) <= 0)
+ emacs_close (fd);
+ else
{
- if (save_fd) emacs_close (save_fd);
+ if (0 <= save_fd)
+ emacs_close (save_fd);
save_fd = fd;
save_mtime = mtime;
save_string = string;
}
- else emacs_close (fd);
}
else
{
}
/* No more suffixes. Return the newest. */
- if (newer && save_fd && ! CONSP (XCDR (tail)))
+ if (0 <= save_fd && ! CONSP (XCDR (tail)))
{
if (storeptr)
*storeptr = save_string;
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'.
{
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;
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");
}
if (c < 0)
{
- unbind_to (count1, Qnil);
+ dynwind_end ();
break;
}
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)
{
UNGCPRO;
- unbind_to (count, Qnil);
+ dynwind_end ();
}
DEFUN ("eval-buffer", Feval_buffer, Seval_buffer, 0, 5, "",
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))
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;
}
(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 ();
!NILP (printflag), Qnil, read_function,
start, end);
- return unbind_to (count, Qnil);
+ dynwind_end ();
+ return Qnil;
}
\f
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: "));
XSETPVECTYPE (XVECTOR (tmp), PVEC_SUB_CHAR_TABLE);
return tmp;
}
- invalid_syntax ("#^^");
+ invalid_syntax ("#^" "^");
}
invalid_syntax ("#^");
}
/* 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;
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)
/* 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. */
+ 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. */
- INTERVAL root_interval = string_intervals (subtree);
- Lisp_Object arg = Fcons (object, placeholder);
+ INTERVAL root_interval = string_intervals (subtree);
+ Lisp_Object arg = Fcons (object, placeholder);
- traverse_intervals_noorder (root_interval,
- &substitute_in_interval, arg);
+ traverse_intervals_noorder (root_interval,
+ &substitute_in_interval, arg);
- return subtree;
- }
-
- /* 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. */
ptrdiff_t i, size;
Lisp_Object *ptr;
Lisp_Object tem, item, vector;
- struct Lisp_Cons *otem;
Lisp_Object len;
tem = read_list (1, readcharfun);
if (!CONSP (item))
error ("Invalid byte code");
- otem = XCONS (item);
bytestr = XCAR (item);
item = XCDR (item);
- free_cons (otem);
}
/* Now handle the bytecode slot. */
}
}
ASET (vector, i, item);
- otem = XCONS (tem);
tem = Fcdr (tem);
- free_cons (otem);
}
return vector;
}
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
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;
\f
/* 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. */
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;
DEFSYM (Qvariable_documentation, "variable-documentation");
- read_buffer = xmalloc (size);
+ read_buffer = xmalloc_atomic (size);
read_buffer_size = size;
}
\f
{
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"); */
#ifdef CANNOT_DUMP
bool use_loadpath = true;
#else
- bool use_loadpath = !NILP (Vpurify_flag);
+ bool use_loadpath = NILP (Vpurify_flag);
#endif
if (use_loadpath && egetenv ("EMACSLOADPATH"))
}
} /* Fmemq (Qnil, Vload_path) */
}
- else /* Vpurify_flag || !EMACSLOADPATH */
+ else
{
Vload_path = load_path_default ();
sitelisp = decode_env_path (0, PATH_SITELOADSEARCH, 0);
if (! NILP (sitelisp)) Vload_path = nconc2 (sitelisp, Vload_path);
}
- } /* !Vpurify_flag && EMACSLOADPATH */
+ }
Vvalues = Qnil;
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'.
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. If this option is non-nil, it checks all suffixes and
-uses whichever file is newest.
+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;