#include "character.h"
#include "buffer.h"
#include "charset.h"
-#include "coding.h"
#include <epaths.h>
#include "commands.h"
#include "keyboard.h"
#ifdef MSDOS
#include "msdos.h"
+#if __DJGPP__ == 2 && __DJGPP_MINOR__ < 5
+# define INFINITY __builtin_inf()
+# define NAN __builtin_nan("")
+#endif
#endif
#ifdef HAVE_NS
{
FILE *stream;
int fd;
- int fd_index;
+ int fd_index UNINIT;
ptrdiff_t count = SPECPDL_INDEX ();
Lisp_Object found, efound, hist_file_name;
/* True means we printed the ".el is newer" message. */
#endif
}
- if (fd < 0)
- {
- /* Pacify older GCC with --enable-gcc-warnings. */
- IF_LINT (fd_index = 0);
- }
- else
+ if (0 <= fd)
{
fd_index = SPECPDL_INDEX ();
record_unwind_protect_int (close_file_unwind, fd);
specbind (Qold_style_backquotes, Qnil);
record_unwind_protect (load_warn_old_style_backquotes, file);
- if (suffix_p (found, ".elc") || (fd >= 0 && (version = safe_to_load_version (fd)) > 0))
+ int is_elc;
+ if ((is_elc = suffix_p (found, ".elc")) != 0
+ /* version = 1 means the file is empty, in which case we can
+ treat it as not byte-compiled. */
+ || (fd >= 0 && (version = safe_to_load_version (fd)) > 1))
/* Load .elc files directly, but not when they are
remote and have no handler! */
{
/* 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)
+ if (!load_prefer_newer && is_elc)
{
result = stat (SSDATA (efound), &s1);
if (result == 0)
for (; CONSP (path); path = XCDR (path))
{
+ ptrdiff_t baselen, prefixlen;
+
filename = Fexpand_file_name (str, XCAR (path));
if (!complete_filename_p (filename))
/* If there are non-absolute elts in PATH (eg "."). */
fn = SAFE_ALLOCA (fn_size);
}
+ /* Copy FILENAME's data to FN but remove starting /: if any. */
+ prefixlen = ((SCHARS (filename) > 2
+ && SREF (filename, 0) == '/'
+ && SREF (filename, 1) == ':')
+ ? 2 : 0);
+ baselen = SBYTES (filename) - prefixlen;
+ memcpy (fn, SDATA (filename) + prefixlen, baselen);
+
/* Loop over suffixes. */
for (tail = NILP (suffixes) ? list1 (empty_unibyte_string) : suffixes;
CONSP (tail); tail = XCDR (tail))
ptrdiff_t fnlen, lsuffix = SBYTES (suffix);
Lisp_Object handler;
- /* Concatenate path element/specified name with the suffix.
- If the directory starts with /:, remove that. */
- 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 (suffix), lsuffix + 1);
- fnlen += lsuffix;
+ /* Make complete filename by appending SUFFIX. */
+ memcpy (fn + baselen, SDATA (suffix), lsuffix + 1);
+ fnlen = baselen + 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)
MAX_MULTIBYTE_LENGTH, -1, 1);
}
-/* Hash table that maps Unicode character names to code points. */
-static Lisp_Object character_names;
-
-/* Length of the longest Unicode character name, in bytes. */
-static ptrdiff_t max_character_name_length;
-
-/* Initializes `character_names' and `max_character_name_length'.
- Called by `read_escape'. */
-void init_character_names ()
+/* Return the scalar value that has the Unicode character name NAME.
+ Raise 'invalid-read-syntax' if there is no such character. */
+static int
+character_name_to_code (char const *name, ptrdiff_t name_len)
{
- character_names = CALLN (Fmake_hash_table,
- QCtest, Qequal,
- /* Currently around 100,000 Unicode
- characters are defined. */
- QCsize, make_natnum (100000));
- const Lisp_Object get_property =
- Fsymbol_function (intern_c_string ("get-char-code-property"));
- ptrdiff_t length = 0;
- for (int i = 0; i <= MAX_UNICODE_CHAR; ++i)
+ /* For "U+XXXX", pass the leading '+' to string_to_number to reject
+ monstrosities like "U+-0000". */
+ Lisp_Object code
+ = (name[0] == 'U' && name[1] == '+'
+ ? string_to_number (name + 1, 16, false)
+ : call2 (Qchar_from_name, make_unibyte_string (name, name_len), Qt));
+
+ if (! RANGED_INTEGERP (0, code, MAX_UNICODE_CHAR)
+ || char_surrogate_p (XINT (code)))
{
- const Lisp_Object code = make_natnum (i);
- const Lisp_Object name = call2 (get_property, code, Qname);
- if (NILP (name)) continue;
- CHECK_STRING (name);
- length = max (length, SBYTES (name));
- Fputhash (name, code, character_names);
+ AUTO_STRING (format, "\\N{%s}");
+ AUTO_STRING_WITH_LEN (namestr, name, name_len);
+ xsignal1 (Qinvalid_read_syntax, CALLN (Fformat, format, namestr));
}
- max_character_name_length = length;
+
+ return XINT (code);
}
+/* Bound on the length of a Unicode character name. As of
+ Unicode 9.0.0 the maximum is 83, so this should be safe. */
+enum { UNICODE_CHARACTER_NAME_LENGTH_BOUND = 200 };
+
/* Read a \-escape sequence, assuming we already read the `\'.
If the escape sequence forces unibyte, return eight-bit char. */
c = READCHAR;
if (c != '{')
invalid_syntax ("Expected opening brace after \\N");
- if (NILP (character_names))
- init_character_names ();
- USE_SAFE_ALLOCA;
- char *name = SAFE_ALLOCA (max_character_name_length + 1);
+ char name[UNICODE_CHARACTER_NAME_LENGTH_BOUND + 1];
bool whitespace = false;
ptrdiff_t length = 0;
while (true)
end_of_file_error ();
if (c == '}')
break;
- if (! c_isascii (c))
- xsignal1 (Qinvalid_read_syntax,
- CALLN (Fformat,
- build_pure_c_string ("Non-ASCII character U+%04X"
- " in character name"),
- make_natnum (c)));
- /* We treat multiple adjacent whitespace characters as a
+ if (! (0 < c && c < 0x80))
+ {
+ AUTO_STRING (format,
+ "Invalid character U+%04X in character name");
+ xsignal1 (Qinvalid_read_syntax,
+ CALLN (Fformat, format, make_natnum (c)));
+ }
+ /* Treat multiple adjacent whitespace characters as a
single space character. This makes it easier to use
character names in e.g. multi-line strings. */
if (c_isspace (c))
{
- if (! whitespace)
- {
- whitespace = true;
- name[length++] = ' ';
- }
+ if (whitespace)
+ continue;
+ c = ' ';
+ whitespace = true;
}
else
- {
- whitespace = false;
- name[length++] = c;
- }
- if (length >= max_character_name_length)
+ whitespace = false;
+ name[length++] = c;
+ if (length >= sizeof name)
invalid_syntax ("Character name too long");
}
if (length == 0)
invalid_syntax ("Empty character name");
- name[length] = 0;
- const Lisp_Object lisp_name = make_unibyte_string (name, length);
- const Lisp_Object code =
- (length >= 3 && length <= 10 && name[0] == 'U' && name[1] == '+') ?
- /* Code point as U+N, where N is between 1 and 8 hexadecimal
- digits. */
- string_to_number (name + 2, 16, false) :
- Fgethash (lisp_name, character_names, Qnil);
- SAFE_FREE ();
- if (! RANGED_INTEGERP (0, code, MAX_UNICODE_CHAR))
- xsignal1 (Qinvalid_read_syntax,
- CALLN (Fformat,
- build_pure_c_string ("\\N{%s}"), lisp_name));
- return XINT (code);
+ name[length] = '\0';
+ return character_name_to_code (name, length);
}
default:
dir_warning (char const *use, Lisp_Object dirname)
{
static char const format[] = "Warning: %s '%s': %s\n";
- int access_errno = errno;
- fprintf (stderr, format, use, SSDATA (ENCODE_SYSTEM (dirname)),
- strerror (access_errno));
+ char *diagnostic = emacs_strerror (errno);
+ fprintf (stderr, format, use, SSDATA (ENCODE_SYSTEM (dirname)), diagnostic);
/* Don't log the warning before we've initialized!! */
if (initialized)
{
- char const *diagnostic = emacs_strerror (access_errno);
+ ptrdiff_t diaglen = strlen (diagnostic);
+ AUTO_STRING_WITH_LEN (diag, diagnostic, diaglen);
+ if (! NILP (Vlocale_coding_system))
+ {
+ Lisp_Object s
+ = code_convert_string_norecord (diag, Vlocale_coding_system, false);
+ diagnostic = SSDATA (s);
+ diaglen = SBYTES (s);
+ }
USE_SAFE_ALLOCA;
char *buffer = SAFE_ALLOCA (sizeof format - 3 * (sizeof "%s" - 1)
- + strlen (use) + SBYTES (dirname)
- + strlen (diagnostic));
+ + strlen (use) + SBYTES (dirname) + diaglen);
ptrdiff_t message_len = esprintf (buffer, format, use, SSDATA (dirname),
diagnostic);
message_dolog (buffer, message_len, 0, STRING_MULTIBYTE (dirname));
doc: /* List of directories to search for files to load.
Each element is a string (directory file name) or nil (meaning
`default-directory').
+This list is consulted by the `require' function.
Initialized during startup as described in Info node `(elisp)Library Search'.
Use `directory-file-name' when adding items to this path. However, Lisp
programs that process this list should tolerate directories both with
DEFSYM (Qrehash_size, "rehash-size");
DEFSYM (Qrehash_threshold, "rehash-threshold");
- character_names = Qnil;
- staticpro (&character_names);
+ DEFSYM (Qchar_from_name, "char-from-name");
}