From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Kenichi Handa Newsgroups: gmane.emacs.devel Subject: Re: expand-file-name problem for eight-bit-control/graphic Date: Tue, 18 Mar 2003 22:24:50 +0900 (JST) Sender: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Message-ID: <200303181324.WAA28495@etlken.m17n.org> References: <200303130747.QAA21083@etlken.m17n.org> <200303180203.LAA27619@etlken.m17n.org> NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 (generated by SEMI 1.14.3 - "Ushinoya") Content-Type: text/plain; charset=US-ASCII X-Trace: main.gmane.org 1047994767 17548 80.91.224.249 (18 Mar 2003 13:39:27 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Tue, 18 Mar 2003 13:39:27 +0000 (UTC) Cc: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Tue Mar 18 14:39:22 2003 Return-path: Original-Received: from quimby.gnus.org ([80.91.224.244]) by main.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 18vHD4-0004Hq-00 for ; Tue, 18 Mar 2003 14:32:54 +0100 Original-Received: from monty-python.gnu.org ([199.232.76.173]) by quimby.gnus.org with esmtp (Exim 3.12 #1 (Debian)) id 18vHDL-0002C2-00 for ; Tue, 18 Mar 2003 14:33:11 +0100 Original-Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.10.13) id 18vHCi-0002ia-00 for emacs-devel@quimby.gnus.org; Tue, 18 Mar 2003 08:32:32 -0500 Original-Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.10.13) id 18vH82-0001mT-00 for emacs-devel@gnu.org; Tue, 18 Mar 2003 08:27:42 -0500 Original-Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.10.13) id 18vH7k-0001Zj-00 for emacs-devel@gnu.org; Tue, 18 Mar 2003 08:27:25 -0500 Original-Received: from tsukuba.m17n.org ([192.47.44.130]) by monty-python.gnu.org with esmtp (Exim 4.10.13) id 18vH5J-0000Bk-00; Tue, 18 Mar 2003 08:24:53 -0500 Original-Received: from fs.m17n.org (fs.m17n.org [192.47.44.2])h2IDOp917479; Tue, 18 Mar 2003 22:24:51 +0900 (JST) (envelope-from handa@m17n.org) Original-Received: from etlken.m17n.org (etlken.m17n.org [192.47.44.125]) h2IDOpA03442; Tue, 18 Mar 2003 22:24:51 +0900 (JST) Original-Received: (from handa@localhost) by etlken.m17n.org (8.8.8+Sun/3.7W-2001040620) id WAA28495; Tue, 18 Mar 2003 22:24:50 +0900 (JST) Original-To: rms@gnu.org In-reply-to: <200303180203.LAA27619@etlken.m17n.org> (message from Kenichi Handa on Tue, 18 Mar 2003 11:03:35 +0900 (JST)) User-Agent: SEMI/1.14.3 (Ushinoya) FLIM/1.14.2 (Yagi-Nishiguchi) APEL/10.2 Emacs/21.2.92 (sparc-sun-solaris2.6) MULE/5.0 (SAKAKI) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1b5 Precedence: list List-Id: Emacs development discussions. List-Help: List-Post: List-Subscribe: , List-Archive: List-Unsubscribe: , Errors-To: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Xref: main.gmane.org gmane.emacs.devel:12439 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:12439 I wrote: > But, at least, we can't use build_string and make_string > blindly to reconstruct a file name. So, how about the > attached change? I found that several other functions in fileio.c have the same problem as expand-file-name. They all do something like this: str = SDATA (filename); ... if (STRING_MULTIBYTE (filename)) return make_string (beg, p - beg); return make_unibyte_string (beg, p - beg); and make_string will return a unibyte string if FILENAME originally contains eight-bit-control/graphics. Another bug is in read-file-name. It doesn't decode homedir. Here's a new patch which replaces the previous one. I think this fix is important because nowadays people more often encounter, for instance, utf-8 filenames in latin-1 locale or vice versa. --- Ken'ichi HANDA handa@m17n.org *** fileio.c.~1.474.~ Tue Mar 18 09:59:02 2003 --- fileio.c Tue Mar 18 22:09:35 2003 *************** *** 235,240 **** --- 235,258 ---- Lisp_Object *, struct coding_system *)); static int e_write P_ ((int, Lisp_Object, int, int, struct coding_system *)); + static Lisp_Object build_file_name P_ ((const unsigned char *, int, int)); + + /* Return a string made from NBYTES bytes at P. If MULTIBYTE is + nonzero, the string is multibyte (it is assumed that the bytes are + in correct multibyte form). If MULTIBYTE is zero, the string is + unibyte. */ + + static Lisp_Object + build_file_name (const unsigned char *p, int nbytes, int multibyte) + { + int nchars; + + if (! multibyte) + return make_unibyte_string ((char *) p, nbytes); + nchars = multibyte_chars_in_text (p, nbytes); + return make_multibyte_string ((char *) p, nchars, nbytes); + } + void report_file_error (string, data) *************** *** 447,455 **** CORRECT_DIR_SEPS (beg); #endif /* DOS_NT */ ! if (STRING_MULTIBYTE (filename)) ! return make_string (beg, p - beg); ! return make_unibyte_string (beg, p - beg); } DEFUN ("file-name-nondirectory", Ffile_name_nondirectory, --- 465,471 ---- CORRECT_DIR_SEPS (beg); #endif /* DOS_NT */ ! return build_file_name (beg, p - beg, STRING_MULTIBYTE (filename)); } DEFUN ("file-name-nondirectory", Ffile_name_nondirectory, *************** *** 488,496 **** ) p--; ! if (STRING_MULTIBYTE (filename)) ! return make_string (p, end - p); ! return make_unibyte_string (p, end - p); } DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory, --- 504,510 ---- ) p--; ! return build_file_name (p, end - p, STRING_MULTIBYTE (filename)); } DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory, *************** *** 631,637 **** return call2 (handler, Qfile_name_as_directory, file); buf = (char *) alloca (SBYTES (file) + 10); ! return build_string (file_name_as_directory (buf, SDATA (file))); } /* --- 645,652 ---- return call2 (handler, Qfile_name_as_directory, file); buf = (char *) alloca (SBYTES (file) + 10); ! file_name_as_directory (buf, SDATA (file)); ! return build_file_name (buf, strlen (buf), STRING_MULTIBYTE (file)); } /* *************** *** 831,837 **** buf = (char *) alloca (SBYTES (directory) + 20); #endif directory_file_name (SDATA (directory), buf); ! return build_string (buf); } static char make_temp_name_tbl[64] = --- 846,852 ---- buf = (char *) alloca (SBYTES (directory) + 20); #endif directory_file_name (SDATA (directory), buf); ! return build_file_name (buf, strlen (buf), STRING_MULTIBYTE (directory)); } static char make_temp_name_tbl[64] = *************** *** 1275,1281 **** { #ifdef VMS if (index (nm, '/')) ! return build_string (sys_translate_unix (nm)); #endif /* VMS */ #ifdef DOS_NT /* Make sure directories are all separated with / or \ as --- 1290,1300 ---- { #ifdef VMS if (index (nm, '/')) ! { ! nm = sys_translate_unix (nm); ! return build_file_name (nm, strlen (nm), ! STRING_MULTIBYTE (name)); ! } #endif /* VMS */ #ifdef DOS_NT /* Make sure directories are all separated with / or \ as *************** *** 1286,1299 **** if (IS_DIRECTORY_SEP (nm[1])) { if (strcmp (nm, SDATA (name)) != 0) ! name = build_string (nm); } else #endif /* drive must be set, so this is okay */ if (strcmp (nm - 2, SDATA (name)) != 0) { ! name = make_string (nm - 2, p - nm + 2); SSET (name, 0, DRIVE_LETTER (drive)); SSET (name, 1, ':'); } --- 1305,1320 ---- if (IS_DIRECTORY_SEP (nm[1])) { if (strcmp (nm, SDATA (name)) != 0) ! name ! = build_file_name (nm, strlen (nm), STRING_MULTIBYTE (name)); } else #endif /* drive must be set, so this is okay */ if (strcmp (nm - 2, SDATA (name)) != 0) { ! name ! = build_file_name (nm, strlen (nm), STRING_MULTIBYTE (name)); SSET (name, 0, DRIVE_LETTER (drive)); SSET (name, 1, ':'); } *************** *** 1301,1307 **** #else /* not DOS_NT */ if (nm == SDATA (name)) return name; ! return build_string (nm); #endif /* not DOS_NT */ } } --- 1322,1328 ---- #else /* not DOS_NT */ if (nm == SDATA (name)) return name; ! return build_file_name (nm, strlen (nm), STRING_MULTIBYTE (name)); #endif /* not DOS_NT */ } } *************** *** 1670,1676 **** CORRECT_DIR_SEPS (target); #endif /* DOS_NT */ ! return make_string (target, o - target); } #if 0 --- 1691,1697 ---- CORRECT_DIR_SEPS (target); #endif /* DOS_NT */ ! return build_file_name (target, o - target, STRING_MULTIBYTE (name)); } #if 0 *************** *** 2101,2107 **** } #ifdef VMS ! return build_string (nm); #else /* See if any variables are substituted into the string --- 2122,2128 ---- } #ifdef VMS ! return build_file_name (nm, strlen (nm), STRING_MULTIBYTE (filename)); #else /* See if any variables are substituted into the string *************** *** 2244,2252 **** xnm = p; #endif ! if (STRING_MULTIBYTE (filename)) ! return make_string (xnm, x - xnm); ! return make_unibyte_string (xnm, x - xnm); badsubst: error ("Bad format environment-variable substitution"); --- 2265,2271 ---- xnm = p; #endif ! return build_file_name (xnm, x - xnm, STRING_MULTIBYTE (filename)); badsubst: error ("Bad format environment-variable substitution"); *************** *** 6023,6028 **** --- 6042,6048 ---- Lisp_Object val, insdef, tem; struct gcpro gcpro1, gcpro2; register char *homedir; + Lisp_Object decoded_homedir; int replace_in_history = 0; int add_to_history = 0; int count; *************** *** 6045,6069 **** CORRECT_DIR_SEPS (homedir); } #endif if (homedir != 0 && STRINGP (dir) ! && !strncmp (homedir, SDATA (dir), strlen (homedir)) ! && IS_DIRECTORY_SEP (SREF (dir, strlen (homedir)))) { ! dir = make_string (SDATA (dir) + strlen (homedir) - 1, ! SBYTES (dir) - strlen (homedir) + 1); ! SSET (dir, 0, '~'); } /* Likewise for default_filename. */ if (homedir != 0 && STRINGP (default_filename) ! && !strncmp (homedir, SDATA (default_filename), strlen (homedir)) ! && IS_DIRECTORY_SEP (SREF (default_filename, strlen (homedir)))) { default_filename ! = make_string (SDATA (default_filename) + strlen (homedir) - 1, ! SBYTES (default_filename) - strlen (homedir) + 1); ! SSET (default_filename, 0, '~'); } if (!NILP (default_filename)) { --- 6065,6093 ---- CORRECT_DIR_SEPS (homedir); } #endif + if (homedir != 0) + decoded_homedir + = DECODE_FILE (make_unibyte_string (homedir, strlen (homedir))); if (homedir != 0 && STRINGP (dir) ! && !strncmp (SDATA (decoded_homedir), SDATA (dir), ! SBYTES (decoded_homedir)) ! && IS_DIRECTORY_SEP (SREF (dir, SBYTES (decoded_homedir)))) { ! dir = Fsubstring (dir, make_number (SCHARS (decoded_homedir) + 1), Qnil); ! dir = concat2 (build_string ("~"), dir); } /* Likewise for default_filename. */ if (homedir != 0 && STRINGP (default_filename) ! && !strncmp (SDATA (decoded_homedir), SDATA (default_filename), ! SBYTES (decoded_homedir)) ! && IS_DIRECTORY_SEP (SREF (default_filename, SBYTES (decoded_homedir)))) { default_filename ! = Fsubstring (default_filename, ! make_number (SCHARS (decoded_homedir) + 1), Qnil); ! default_filename = concat2 (build_string ("~"), default_filename); } if (!NILP (default_filename)) {