diff options
author | Eli Zaretskii <[email protected]> | 2013-11-04 19:30:33 +0200 |
---|---|---|
committer | Eli Zaretskii <[email protected]> | 2013-11-04 19:30:33 +0200 |
commit | d0065ff1244871c9eb40420b88fc89f9f008b587 (patch) | |
tree | a869fa565b559c7b0a9390fd6045d7d827d001ec /src | |
parent | 7397c58760779a3aa83ff58164455761d77cd642 (diff) |
Fix bug #15260 with building and installing Emacs in non-ASCII directories.
src/xdisp.c (message3_nolog, message_with_string): Encode the string
before writing it to the terminal in a non-interactive session.
src/lread.c (openp): If both FILENAME and SUFFIX are unibyte, make
sure we concatenate them into a unibyte string.
src/fileio.c (make_temp_name): Encode PREFIX, and decode the
resulting temporary name before returning it to the caller.
(Fexpand_file_name): If NAME is pure-ASCII and DEFAULT_DIRECTORY
is a unibyte string, convert NAME to a unibyte string to ensure
that the result is also a unibyte string.
src/emacs.c (init_cmdargs): Use build_unibyte_string to make sure we
create unibyte strings from default paths and directory/file
names.
src/coding.h (ENCODE_FILE): Do not attempt to encode a unibyte
string.
src/callproc.c (init_callproc): Use build_unibyte_string to make
sure we create unibyte strings from default paths and
directory/file names.
src/buffer.c (init_buffer): Don't store default-directory of
*scratch* in multibyte form. The original problem which led to
that is described in
http://lists.gnu.org/archive/html/emacs-pretest-bug/2004-11/msg00532.html,
but it was solved long ago.
lisp/startup.el (normal-top-level): Move setting eol-mnemonic-unix,
eol-mnemonic-mac, eol-mnemonic-dos, and also setup of the locale
environment and decoding all of the default-directory's to here
from command-line.
(command-line): Decode also argv[0].
lisp/loadup.el: Error out if default-directory is a multibyte string
when we are dumping.
lisp/Makefile.in (emacs): Don't set LC_ALL=C.
leim/Makefile.in (RUN_EMACS): Don't set LC_ALL=C.
configure.ac: Don't disallow builds in non-ASCII directories.
Diffstat (limited to 'src')
-rw-r--r-- | src/ChangeLog | 31 | ||||
-rw-r--r-- | src/buffer.c | 9 | ||||
-rw-r--r-- | src/callproc.c | 6 | ||||
-rw-r--r-- | src/coding.h | 18 | ||||
-rw-r--r-- | src/emacs.c | 10 | ||||
-rw-r--r-- | src/fileio.c | 36 | ||||
-rw-r--r-- | src/lread.c | 18 | ||||
-rw-r--r-- | src/xdisp.c | 14 |
8 files changed, 107 insertions, 35 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 1c56a7c599..f6f4dc3ef8 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,34 @@ +2013-11-04 Eli Zaretskii <[email protected]> + + * xdisp.c (message3_nolog, message_with_string): Encode the string + before writing it to the terminal in a non-interactive session. + + * lread.c (openp): If both FILENAME and SUFFIX are unibyte, make + sure we concatenate them into a unibyte string. + + * fileio.c (make_temp_name): Encode PREFIX, and decode the + resulting temporary name before returning it to the caller. + (Fexpand_file_name): If NAME is pure-ASCII and DEFAULT_DIRECTORY + is a unibyte string, convert NAME to a unibyte string to ensure + that the result is also a unibyte string. + + * emacs.c (init_cmdargs): Use build_unibyte_string to make sure we + create unibyte strings from default paths and directory/file + names. + + * coding.h (ENCODE_FILE): Do not attempt to encode a unibyte + string. + + * callproc.c (init_callproc): Use build_unibyte_string to make + sure we create unibyte strings from default paths and + directory/file names. + + * buffer.c (init_buffer): Don't store default-directory of + 8scratch* in multibyte form. The original problem which led to + that is described in + http://lists.gnu.org/archive/html/emacs-pretest-bug/2004-11/msg00532.html, + but it was solved long ago. (Bug#15260) + 2013-11-04 Paul Eggert <[email protected]> Port to stricter C99 platforms. diff --git a/src/buffer.c b/src/buffer.c index e5a8af93cf..63198cd101 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -5349,13 +5349,10 @@ init_buffer (void) len++; } + /* At this moment, we still don't know how to decode the directory + name. So, we keep the bytes in unibyte form so that file I/O + routines correctly get the original bytes. */ bset_directory (current_buffer, make_unibyte_string (pwd, len)); - if (! NILP (BVAR (&buffer_defaults, enable_multibyte_characters))) - /* At this moment, we still don't know how to decode the - directory name. So, we keep the bytes in multibyte form so - that ENCODE_FILE correctly gets the original bytes. */ - bset_directory - (current_buffer, string_to_multibyte (BVAR (current_buffer, directory))); /* Add /: to the front of the name if it would otherwise be treated as magic. */ diff --git a/src/callproc.c b/src/callproc.c index d4b4a26ec3..2740779f51 100644 --- a/src/callproc.c +++ b/src/callproc.c @@ -1612,14 +1612,14 @@ init_callproc (void) Lisp_Object tem, tem1, srcdir; srcdir = Fexpand_file_name (build_string ("../src/"), - build_string (PATH_DUMPLOADSEARCH)); + build_unibyte_string (PATH_DUMPLOADSEARCH)); tem = Fexpand_file_name (build_string ("GNU"), Vdata_directory); tem1 = Ffile_exists_p (tem); if (!NILP (Fequal (srcdir, Vinvocation_directory)) || NILP (tem1)) { Lisp_Object newdir; newdir = Fexpand_file_name (build_string ("../etc/"), - build_string (PATH_DUMPLOADSEARCH)); + build_unibyte_string (PATH_DUMPLOADSEARCH)); tem = Fexpand_file_name (build_string ("GNU"), newdir); tem1 = Ffile_exists_p (tem); if (!NILP (tem1)) @@ -1646,7 +1646,7 @@ init_callproc (void) #ifdef DOS_NT Vshared_game_score_directory = Qnil; #else - Vshared_game_score_directory = build_string (PATH_GAME); + Vshared_game_score_directory = build_unibyte_string (PATH_GAME); if (NILP (Ffile_accessible_directory_p (Vshared_game_score_directory))) Vshared_game_score_directory = Qnil; #endif diff --git a/src/coding.h b/src/coding.h index 0472bec99d..5a921e4495 100644 --- a/src/coding.h +++ b/src/coding.h @@ -670,14 +670,16 @@ struct coding_system (code) = (s1 << 8) | s2; \ } while (0) -/* Encode the file name NAME using the specified coding system - for file names, if any. */ -#define ENCODE_FILE(name) \ - (! NILP (Vfile_name_coding_system) \ - ? code_convert_string_norecord (name, Vfile_name_coding_system, 1) \ - : (! NILP (Vdefault_file_name_coding_system) \ - ? code_convert_string_norecord (name, Vdefault_file_name_coding_system, 1) \ - : name)) +/* Encode the file name NAME using the specified coding system for + file names, if any. If NAME is a unibyte string, return NAME. */ +#define ENCODE_FILE(name) \ + (! STRING_MULTIBYTE (name) \ + ? name \ + : (! NILP (Vfile_name_coding_system) \ + ? code_convert_string_norecord (name, Vfile_name_coding_system, 1) \ + : (! NILP (Vdefault_file_name_coding_system) \ + ? code_convert_string_norecord (name, Vdefault_file_name_coding_system, 1) \ + : name))) /* Decode the file name NAME using the specified coding system diff --git a/src/emacs.c b/src/emacs.c index 928babb417..52d2e76dc8 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -393,7 +393,7 @@ init_cmdargs (int argc, char **argv, int skip_args, char *original_pwd) initial_argv = argv; initial_argc = argc; - raw_name = build_string (argv[0]); + raw_name = build_unibyte_string (argv[0]); /* Add /: to the front of the name if it would otherwise be treated as magic. */ @@ -427,7 +427,9 @@ init_cmdargs (int argc, char **argv, int skip_args, char *original_pwd) /* Emacs was started with relative path, like ./emacs. Make it absolute. */ { - Lisp_Object odir = original_pwd ? build_string (original_pwd) : Qnil; + Lisp_Object odir = + original_pwd ? build_unibyte_string (original_pwd) : Qnil; + Vinvocation_directory = Fexpand_file_name (Vinvocation_directory, odir); } @@ -2206,7 +2208,7 @@ decode_env_path (const char *evarname, const char *defalt) p = strchr (path, SEPCHAR); if (!p) p = path + strlen (path); - element = (p - path ? make_string (path, p - path) + element = (p - path ? make_unibyte_string (path, p - path) : build_string (".")); #ifdef WINDOWSNT /* Relative file names in the default path are interpreted as @@ -2216,7 +2218,7 @@ decode_env_path (const char *evarname, const char *defalt) element = Fexpand_file_name (Fsubstring (element, make_number (emacs_dir_len), Qnil), - build_string (emacs_dir)); + build_unibyte_string (emacs_dir)); #endif /* Add /: to the front of the name diff --git a/src/fileio.c b/src/fileio.c index a1dcb72b4e..884af25f9f 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -732,8 +732,8 @@ static unsigned make_temp_name_count, make_temp_name_count_initialized_p; Lisp_Object make_temp_name (Lisp_Object prefix, bool base64_p) { - Lisp_Object val; - int len, clen; + Lisp_Object val, encoded_prefix; + int len; printmax_t pid; char *p, *data; char pidbuf[INT_BUFSIZE_BOUND (printmax_t)]; @@ -767,12 +767,11 @@ make_temp_name (Lisp_Object prefix, bool base64_p) #endif } - len = SBYTES (prefix); clen = SCHARS (prefix); - val = make_uninit_multibyte_string (clen + 3 + pidlen, len + 3 + pidlen); - if (!STRING_MULTIBYTE (prefix)) - STRING_SET_UNIBYTE (val); + encoded_prefix = ENCODE_FILE (prefix); + len = SBYTES (encoded_prefix); + val = make_uninit_string (len + 3 + pidlen); data = SSDATA (val); - memcpy (data, SSDATA (prefix), len); + memcpy (data, SSDATA (encoded_prefix), len); p = data + len; memcpy (p, pidbuf, pidlen); @@ -810,7 +809,7 @@ make_temp_name (Lisp_Object prefix, bool base64_p) { /* We want to return only if errno is ENOENT. */ if (errno == ENOENT) - return val; + return DECODE_FILE (val); else /* The error here is dubious, but there is little else we can do. The alternatives are to return nil, which is @@ -987,7 +986,26 @@ filesystem tree, not (expand-file-name ".." dirname). */) if (multibyte != STRING_MULTIBYTE (default_directory)) { if (multibyte) - default_directory = string_to_multibyte (default_directory); + { + unsigned char *p = SDATA (name); + + while (*p && ASCII_BYTE_P (*p)) + p++; + if (*p == '\0') + { + /* NAME is a pure ASCII string, and DEFAULT_DIRECTORY is + unibyte. Do not convert DEFAULT_DIRECTORY to + multibyte; instead, convert NAME to a unibyte string, + so that the result of this function is also a unibyte + string. This is needed during bootstraping and + dumping, when Emacs cannot decode file names, because + the locale environment is not set up. */ + name = make_unibyte_string (SSDATA (name), SBYTES (name)); + multibyte = 0; + } + else + default_directory = string_to_multibyte (default_directory); + } else { name = string_to_multibyte (name); diff --git a/src/lread.c b/src/lread.c index b42ac5908e..618b0cadb5 100644 --- a/src/lread.c +++ b/src/lread.c @@ -1500,7 +1500,8 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, for (tail = NILP (suffixes) ? list1 (empty_unibyte_string) : suffixes; CONSP (tail); tail = XCDR (tail)) { - ptrdiff_t fnlen, lsuffix = SBYTES (XCAR (tail)); + Lisp_Object suffix = XCAR (tail); + ptrdiff_t fnlen, lsuffix = SBYTES (suffix); Lisp_Object handler; /* Concatenate path element/specified name with the suffix. @@ -1511,7 +1512,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, ? 2 : 0); fnlen = SBYTES (filename) - prefixlen; memcpy (fn, SDATA (filename) + prefixlen, fnlen); - memcpy (fn + fnlen, SDATA (XCAR (tail)), lsuffix + 1); + memcpy (fn + fnlen, SDATA (suffix), 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: @@ -1521,7 +1522,18 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, 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 = make_string (fn, fnlen); + /* make_string has its own ideas on when to return a unibyte + string and when a multibyte string, but we know better. + We must have a unibyte string when dumping, since + file-name encoding is shaky at best at that time, and in + particular default-file-name-coding-system is reset + several times during loadup. We therefore don't want to + encode the file before passing it to file I/O library + functions. */ + if (!STRING_MULTIBYTE (filename) && !STRING_MULTIBYTE (suffix)) + string = make_unibyte_string (fn, fnlen); + else + string = make_string (fn, fnlen); handler = Ffind_file_name_handler (string, Qfile_exists_p); if ((!NILP (handler) || !NILP (predicate)) && !NATNUMP (predicate)) { diff --git a/src/xdisp.c b/src/xdisp.c index 9992fa4776..382f9e7a8e 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -9728,7 +9728,11 @@ message3_nolog (Lisp_Object m) putc ('\n', stderr); noninteractive_need_newline = 0; if (STRINGP (m)) - fwrite (SDATA (m), SBYTES (m), 1, stderr); + { + Lisp_Object s = ENCODE_SYSTEM (m); + + fwrite (SDATA (s), SBYTES (s), 1, stderr); + } if (cursor_in_echo_area == 0) fprintf (stderr, "\n"); fflush (stderr); @@ -9803,13 +9807,19 @@ message_with_string (const char *m, Lisp_Object string, int log) { if (m) { + /* ENCODE_SYSTEM below can GC and/or relocate the Lisp + String whose data pointer might be passed to us in M. So + we use a local copy. */ + char *fmt = xstrdup (m); + if (noninteractive_need_newline) putc ('\n', stderr); noninteractive_need_newline = 0; - fprintf (stderr, m, SDATA (string)); + fprintf (stderr, fmt, SDATA (ENCODE_SYSTEM (string))); if (!cursor_in_echo_area) fprintf (stderr, "\n"); fflush (stderr); + xfree (fmt); } } else if (INTERACTIVE) |