emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] emacs/src ChangeLog fileio.c


From: Jason Rumney
Subject: [Emacs-diffs] emacs/src ChangeLog fileio.c
Date: Tue, 24 Mar 2009 14:14:55 +0000

CVSROOT:        /sources/emacs
Module name:    emacs
Changes by:     Jason Rumney <jasonr>   09/03/24 14:14:55

Modified files:
        src            : ChangeLog fileio.c 

Log message:
        (Fsubstitute_in_file_name): Always work on a copy.
        Calculate total size precisely.  Decode environment variables
        before substituting.  (Bug#38)

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/emacs/src/ChangeLog?cvsroot=emacs&r1=1.7448&r2=1.7449
http://cvs.savannah.gnu.org/viewcvs/emacs/src/fileio.c?cvsroot=emacs&r1=1.650&r2=1.651

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/emacs/emacs/src/ChangeLog,v
retrieving revision 1.7448
retrieving revision 1.7449
diff -u -b -r1.7448 -r1.7449
--- ChangeLog   24 Mar 2009 01:41:41 -0000      1.7448
+++ ChangeLog   24 Mar 2009 14:14:53 -0000      1.7449
@@ -1,3 +1,9 @@
+2009-03-24  Jason Rumney  <address@hidden>
+
+       * fileio.c (Fsubstitute_in_file_name): Always work on a copy.
+       Calculate total size precisely.  Decode environment variables
+       before substituting.  (Bug#38)
+
 2009-03-24  Kenichi Handa  <address@hidden>
 
        * font.c (find_font_encoding): Return Qnil for unsupported

Index: fileio.c
===================================================================
RCS file: /sources/emacs/emacs/src/fileio.c,v
retrieving revision 1.650
retrieving revision 1.651
diff -u -b -r1.650 -r1.651
--- fileio.c    19 Mar 2009 06:26:07 -0000      1.650
+++ fileio.c    24 Mar 2009 14:14:54 -0000      1.651
@@ -1629,11 +1629,14 @@
   unsigned char *target = NULL;
   int total = 0;
   int substituted = 0;
+  int multibyte;
   unsigned char *xnm;
   Lisp_Object handler;
 
   CHECK_STRING (filename);
 
+  multibyte = STRING_MULTIBYTE (filename);
+
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
   handler = Ffind_file_name_handler (filename, Qsubstitute_in_file_name);
@@ -1641,8 +1644,11 @@
     return call2 (handler, Qsubstitute_in_file_name, filename);
 
   nm = SDATA (filename);
-#ifdef DOS_NT
+  /* Always work on a copy of the string, in case GC happens during
+     decode of environment variables, causing the original Lisp_String
+     data to be relocated.  */
   nm = strcpy (alloca (strlen (nm) + 1), nm);
+#ifdef DOS_NT
   CORRECT_DIR_SEPS (nm);
   substituted = (strcmp (nm, SDATA (filename)) != 0);
 #endif
@@ -1655,9 +1661,7 @@
        again.  Important with filenames like "/home/foo//:/hello///there"
        which whould substitute to "/:/hello///there" rather than "/there".  */
     return Fsubstitute_in_file_name
-      (make_specified_string (p, -1, endp - p,
-                             STRING_MULTIBYTE (filename)));
-
+      (make_specified_string (p, -1, endp - p, multibyte));
 
   /* See if any variables are substituted into the string
      and find the total length of their values in `total' */
@@ -1703,8 +1707,16 @@
        /* Get variable value */
        o = (unsigned char *) egetenv (target);
        if (o)
-         { /* Eight-bit chars occupy upto 2 bytes in multibyte.  */
-           total += strlen (o) * (STRING_MULTIBYTE (filename) ? 2 : 1);
+         {
+           /* Don't try to guess a maximum length - UTF8 can use up to
+              four bytes per character.  This code is unlikely to run
+              in a situation that requires performance, so decoding the
+              env variables twice should be acceptable. Note that
+              decoding may cause a garbage collect.  */
+           Lisp_Object orig, decoded;
+           orig = make_unibyte_string (o, strlen (o));
+           decoded = DECODE_FILE (orig);
+           total += SBYTES (decoded);
            substituted = 1;
          }
        else if (*p == '}')
@@ -1762,21 +1774,22 @@
            *x++ = '$';
            strcpy (x, target); x+= strlen (target);
          }
-       else if (STRING_MULTIBYTE (filename))
-         {
-           /* If the original string is multibyte,
-              convert what we substitute into multibyte.  */
-           while (*o)
-             {
-               int c = *o++;
-               c = unibyte_char_to_multibyte (c);
-               x += CHAR_STRING (c, x);
-             }
-         }
        else
          {
-           strcpy (x, o);
-           x += strlen (o);
+           Lisp_Object orig, decoded;
+           int orig_length, decoded_length;
+           orig_length = strlen (o);
+           orig = make_unibyte_string (o, orig_length);
+           decoded = DECODE_FILE (orig);
+           decoded_length = SBYTES (decoded);
+           strncpy (x, SDATA (decoded), decoded_length);
+           x += decoded_length;
+
+           /* If environment variable needed decoding, return value
+              needs to be multibyte.  */
+           if (decoded_length != orig_length
+               || strncmp (SDATA (decoded), o, orig_length))
+             multibyte = 1;
          }
       }
 
@@ -1789,7 +1802,7 @@
        need to quote some $ to $$ first.  */
     xnm = p;
 
-  return make_specified_string (xnm, -1, x - xnm, STRING_MULTIBYTE (filename));
+  return make_specified_string (xnm, -1, x - xnm, multibyte);
 
  badsubst:
   error ("Bad format environment-variable substitution");




reply via email to

[Prev in Thread] Current Thread [Next in Thread]