#include <config.h>
-#include <stdio.h>
+#include "sysstdio.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include "keyboard.h"
#include "frame.h"
#include "termhooks.h"
-#include "coding.h"
#include "blockinput.h"
#ifdef MSDOS
It must be set to nil before all top-level calls to read0. */
static Lisp_Object read_objects;
-/* List of descriptors now open for Fload. */
-static Lisp_Object load_descriptor_list;
-
/* File for get_file_char to read from. Use by load. */
static FILE *instream;
Lisp_Object, Lisp_Object,
Lisp_Object, Lisp_Object);
static Lisp_Object load_unwind (Lisp_Object);
-static Lisp_Object load_descriptor_unwind (Lisp_Object);
\f
/* Functions that read one byte from the current source READCHARFUN
or unreads one byte. If the integer argument C is -1, it returns
ptrdiff_t pt_byte = BUF_PT_BYTE (inbuffer);
+ if (! BUFFER_LIVE_P (inbuffer))
+ return -1;
+
if (pt_byte >= BUF_ZV_BYTE (inbuffer))
return -1;
return STRING_CHAR (buf);
}
+#define FROM_FILE_P(readcharfun) \
+ (EQ (readcharfun, Qget_file_char) \
+ || EQ (readcharfun, Qget_emacs_mule_file_char))
+
static void
skip_dyn_bytes (Lisp_Object readcharfun, ptrdiff_t n)
{
- if (EQ (readcharfun, Qget_file_char)
- || EQ (readcharfun, Qget_emacs_mule_file_char))
+ if (FROM_FILE_P (readcharfun))
{
block_input (); /* FIXME: Not sure if it's needed. */
fseek (instream, n, SEEK_CUR);
}
}
+static void
+skip_dyn_eof (Lisp_Object readcharfun)
+{
+ if (FROM_FILE_P (readcharfun))
+ {
+ block_input (); /* FIXME: Not sure if it's needed. */
+ fseek (instream, 0, SEEK_END);
+ unblock_input ();
+ }
+ else
+ while (READCHAR >= 0);
+}
+
/* Unread the character C in the way appropriate for the stream READCHARFUN.
If the stream is a user function, call it with the char as argument. */
{
unread_char = c;
}
- else if (EQ (readcharfun, Qget_file_char)
- || EQ (readcharfun, Qget_emacs_mule_file_char))
+ else if (FROM_FILE_P (readcharfun))
{
unread_char = c;
}
end_time = add_emacs_time (current_emacs_time (), wait_time);
}
-/* Read until we get an acceptable event. */
+ /* Read until we get an acceptable event. */
retry:
do
- val = read_char (0, 0, 0, (input_method ? Qnil : Qt), 0,
+ val = read_char (0, Qnil, (input_method ? Qnil : Qt), 0,
NUMBERP (seconds) ? &end_time : NULL);
while (INTEGERP (val) && XINT (val) == -2); /* wrong_kboard_jmpbuf */
if (BUFFERP (val))
goto retry;
- /* switch-frame events are put off until after the next ASCII
+ /* `switch-frame' events are put off until after the next ASCII
character. This is better than signaling an error just because
the last characters were typed to a separate minibuffer frame,
for example. Eventually, some code which can deal with
{
bool rv = 0;
enum {
- NOMINAL, AFTER_FIRST_DASH, AFTER_ASTERIX,
+ NOMINAL, AFTER_FIRST_DASH, AFTER_ASTERIX
} beg_end_state = NOMINAL;
bool in_file_vars = 0;
if (fd >= 0)
{
emacs_close (fd);
- stream = fopen (SSDATA (efound), fmode);
+ stream = emacs_fopen (SSDATA (efound), fmode);
}
else
stream = NULL;
}
record_unwind_protect (load_unwind, make_save_pointer (stream));
- record_unwind_protect (load_descriptor_unwind, load_descriptor_list);
specbind (Qload_file_name, found);
specbind (Qinhibit_file_name_operation, Qnil);
- load_descriptor_list
- = Fcons (make_number (fileno (stream)), load_descriptor_list);
specbind (Qload_in_progress, Qt);
instream = stream;
}
return Qnil;
}
-
-static Lisp_Object
-load_descriptor_unwind (Lisp_Object oldlist)
-{
- load_descriptor_list = oldlist;
- return Qnil;
-}
-
-/* Close all descriptors in use for Floads.
- This is used when starting a subprocess. */
-
-void
-close_load_descs (void)
-{
-#ifndef WINDOWSNT
- Lisp_Object tail;
- for (tail = load_descriptor_list; CONSP (tail); tail = XCDR (tail))
- emacs_close (XFASTINT (XCAR (tail)));
-#endif
-}
\f
static bool
complete_filename_p (Lisp_Object pathname)
/* Search for a file whose name is STR, looking in directories
in the Lisp list PATH, and trying suffixes from SUFFIX.
- On success, returns a file descriptor. On failure, returns -1.
+ On success, return a file descriptor (or 1 or -2 as described below).
+ On failure, return -1 and set errno.
SUFFIXES is a list of strings containing possible suffixes.
The empty suffix is automatically added if the list is empty.
PREDICATE non-nil means don't open the files,
just look for one that satisfies the predicate. In this case,
- returns 1 on success. The predicate can be a lisp function or
+ return 1 on success. The predicate can be a lisp function or
an integer to pass to `access' (in which case file-name-handlers
are ignored).
but store the found remote file name in *STOREPTR. */
int
-openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *storeptr, Lisp_Object predicate)
+openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
+ Lisp_Object *storeptr, Lisp_Object predicate)
{
ptrdiff_t fn_size = 100;
char buf[100];
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
Lisp_Object string, tail, encoded_fn;
ptrdiff_t max_suffix_len = 0;
+ int last_errno = ENOENT;
CHECK_STRING (str);
if ((!NILP (handler) || !NILP (predicate)) && !NATNUMP (predicate))
{
bool exists;
+ last_errno = ENOENT;
if (NILP (predicate))
exists = !NILP (Ffile_readable_p (string));
else
{
Lisp_Object tmp = call1 (predicate, string);
- exists = !NILP (tmp)
- && (EQ (tmp, Qdir_ok)
- || NILP (Ffile_directory_p (string)));
+ if (NILP (tmp))
+ exists = 0;
+ else if (EQ (tmp, Qdir_ok)
+ || NILP (Ffile_directory_p (string)))
+ exists = 1;
+ else
+ {
+ exists = 0;
+ last_errno = EISDIR;
+ }
}
if (exists)
/* Check that we can access or open it. */
if (NATNUMP (predicate))
- fd = (((XFASTINT (predicate) & ~INT_MAX) == 0
- && (faccessat (AT_FDCWD, pfn, XFASTINT (predicate),
+ {
+ fd = -1;
+ if (INT_MAX < XFASTINT (predicate))
+ last_errno = EINVAL;
+ else if (faccessat (AT_FDCWD, pfn, XFASTINT (predicate),
AT_EACCESS)
== 0)
- && ! file_directory_p (pfn))
- ? 1 : -1);
+ {
+ if (file_directory_p (pfn))
+ last_errno = EISDIR;
+ else
+ fd = 1;
+ }
+ }
else
{
- struct stat st;
fd = emacs_open (pfn, O_RDONLY, 0);
- if (0 <= fd
- && (fstat (fd, &st) != 0 || S_ISDIR (st.st_mode)))
+ if (fd < 0)
+ last_errno = errno;
+ else
{
- emacs_close (fd);
- fd = -1;
+ struct stat st;
+ int err = (fstat (fd, &st) != 0 ? errno
+ : S_ISDIR (st.st_mode) ? EISDIR : 0);
+ if (err)
+ {
+ last_errno = err;
+ emacs_close (fd);
+ fd = -1;
+ }
}
}
}
UNGCPRO;
+ errno = last_errno;
return -1;
}
if (EQ (stream, Qt))
stream = Qread_char;
if (EQ (stream, Qread_char))
- return Fread_minibuffer (build_string ("Lisp expression: "), Qnil);
+ /* FIXME: ¿¡ When is this used !? */
+ return call1 (intern ("read-minibuffer"),
+ build_string ("Lisp expression: "));
return read_internal_start (stream, Qnil, Qnil);
}
while (c == '0');
}
- while (-1 <= (digit = digit_to_number (c, radix)))
+ while ((digit = digit_to_number (c, radix)) >= -1)
{
if (digit == -1)
valid = 0;
if (c == '@')
{
enum { extra = 100 };
- ptrdiff_t i, nskip = 0;
+ ptrdiff_t i, nskip = 0, digits = 0;
/* Read a decimal integer. */
while ((c = READCHAR) >= 0
{
if ((STRING_BYTES_BOUND - extra) / 10 <= nskip)
string_overflow ();
+ digits++;
nskip *= 10;
nskip += c - '0';
+ if (digits == 2 && nskip == 0)
+ { /* We've just seen #@00, which means "skip to end". */
+ skip_dyn_eof (readcharfun);
+ return Qnil;
+ }
}
if (nskip > 0)
/* We can't use UNREAD here, because in the code below we side-step
nskip--;
else
UNREAD (c);
-
+
if (load_force_doc_strings
- && (EQ (readcharfun, Qget_file_char)
- || EQ (readcharfun, Qget_emacs_mule_file_char)))
+ && (FROM_FILE_P (readcharfun)))
{
/* If we are supposed to force doc strings into core right now,
record the last string that we skipped,
state = 0;
leading_digit = digit_to_number (*cp, base);
- if (0 <= leading_digit)
+ if (leading_digit >= 0)
{
state |= LEAD_INT;
do
++cp;
- while (0 <= digit_to_number (*cp, base));
+ while (digit_to_number (*cp, base) >= 0);
}
if (*cp == '.')
{
/* If the number uses integer and not float syntax, and is in C-language
range, use its value, preferably as a fixnum. */
- if (0 <= leading_digit && ! float_syntax)
+ if (leading_digit >= 0 && ! float_syntax)
{
uintmax_t n;
{
if (NILP (Vdoc_file_name))
/* We have not yet called Snarf-documentation, so assume
- this file is described in the DOC-MM.NN file
+ this file is described in the DOC file
and Snarf-documentation will fill in the right value later.
For now, replace the whole list with 0. */
doc_reference = 1;
{
if (doc_reference == 1)
return make_number (0);
- if (doc_reference == 2)
+ if (doc_reference == 2 && INTEGERP (XCDR (val)))
{
+ char *saved = NULL;
+ file_offset saved_position;
/* Get a doc string from the file we are loading.
If it's in saved_doc_string, get it from there.
&& pos < (saved_doc_string_position
+ saved_doc_string_length))
{
- ptrdiff_t start = pos - saved_doc_string_position;
- ptrdiff_t from, to;
-
- /* Process quoting with ^A,
- and find the end of the string,
- which is marked with ^_ (037). */
- for (from = start, to = start;
- saved_doc_string[from] != 037;)
- {
- int c = saved_doc_string[from++];
- if (c == 1)
- {
- c = saved_doc_string[from++];
- if (c == 1)
- saved_doc_string[to++] = c;
- else if (c == '0')
- saved_doc_string[to++] = 0;
- else if (c == '_')
- saved_doc_string[to++] = 037;
- }
- else
- saved_doc_string[to++] = c;
- }
-
- return make_unibyte_string (saved_doc_string + start,
- to - start);
+ saved = saved_doc_string;
+ saved_position = saved_doc_string_position;
}
/* Look in prev_saved_doc_string the same way. */
else if (pos >= prev_saved_doc_string_position
&& pos < (prev_saved_doc_string_position
+ prev_saved_doc_string_length))
{
- ptrdiff_t start =
- pos - prev_saved_doc_string_position;
+ saved = prev_saved_doc_string;
+ saved_position = prev_saved_doc_string_position;
+ }
+ if (saved)
+ {
+ ptrdiff_t start = pos - saved_position;
ptrdiff_t from, to;
/* Process quoting with ^A,
and find the end of the string,
which is marked with ^_ (037). */
for (from = start, to = start;
- prev_saved_doc_string[from] != 037;)
+ saved[from] != 037;)
{
- int c = prev_saved_doc_string[from++];
+ int c = saved[from++];
if (c == 1)
{
- c = prev_saved_doc_string[from++];
- if (c == 1)
- prev_saved_doc_string[to++] = c;
- else if (c == '0')
- prev_saved_doc_string[to++] = 0;
- else if (c == '_')
- prev_saved_doc_string[to++] = 037;
+ c = saved[from++];
+ saved[to++] = (c == 1 ? c
+ : c == '0' ? 0
+ : c == '_' ? 037
+ : c);
}
else
- prev_saved_doc_string[to++] = c;
+ saved[to++] = c;
}
- return make_unibyte_string (prev_saved_doc_string
- + start,
+ return make_unibyte_string (saved + start,
to - start);
}
else
load_in_progress = 0;
Vload_file_name = Qnil;
-
- load_descriptor_list = Qnil;
-
Vstandard_input = Qt;
Vloads_in_progress = Qnil;
}
DEFSYM (Qload_in_progress, "load-in-progress");
DEFVAR_LISP ("after-load-alist", Vafter_load_alist,
- doc: /* An alist of expressions to be evalled when particular files are loaded.
-Each element looks like (REGEXP-OR-FEATURE FORMS...).
+ doc: /* An alist of functions to be evalled when particular files are loaded.
+Each element looks like (REGEXP-OR-FEATURE FUNCS...).
REGEXP-OR-FEATURE is either a regular expression to match file names, or
a symbol \(a feature name).
When `load' is run and the file-name argument matches an element's
REGEXP-OR-FEATURE, or when `provide' is run and provides the symbol
-REGEXP-OR-FEATURE, the FORMS in the element are executed.
+REGEXP-OR-FEATURE, the FUNCS in the element are called.
An error in FORMS does not undo the load, but does prevent execution of
the rest of the FORMS. */);
/* Vsource_directory was initialized in init_lread. */
- load_descriptor_list = Qnil;
- staticpro (&load_descriptor_list);
-
DEFSYM (Qcurrent_load_list, "current-load-list");
DEFSYM (Qstandard_input, "standard-input");
DEFSYM (Qread_char, "read-char");