emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] trunk r114616: * src/fileio.c (Fsubstitute_in_file_name):


From: Stefan Monnier
Subject: [Emacs-diffs] trunk r114616: * src/fileio.c (Fsubstitute_in_file_name): Use substitute-env-in-file-name.
Date: Thu, 10 Oct 2013 21:42:48 +0000
User-agent: Bazaar (2.6b2)

------------------------------------------------------------
revno: 114616
revision-id: address@hidden
parent: address@hidden
committer: Stefan Monnier <address@hidden>
branch nick: trunk
timestamp: Thu 2013-10-10 17:42:38 -0400
message:
  * src/fileio.c (Fsubstitute_in_file_name): Use substitute-env-in-file-name.
  (Qsubstitute_env_in_file_name): New var.
  (syms_of_fileio): Define it.
  * lisp/env.el (substitute-env-in-file-name): New function.
  (substitute-env-vars): Extend the meaning of the optional arg.
modified:
  lisp/ChangeLog                 changelog-20091113204419-o5vbwnq5f7feedwu-1432
  lisp/env.el                    env.el-20091113204419-o5vbwnq5f7feedwu-445
  src/ChangeLog                  changelog-20091113204419-o5vbwnq5f7feedwu-1438
  src/fileio.c                   fileio.c-20091113204419-o5vbwnq5f7feedwu-210
=== modified file 'lisp/ChangeLog'
--- a/lisp/ChangeLog    2013-10-10 15:30:21 +0000
+++ b/lisp/ChangeLog    2013-10-10 21:42:38 +0000
@@ -1,3 +1,8 @@
+2013-10-10  Stefan Monnier  <address@hidden>
+
+       * env.el (substitute-env-in-file-name): New function.
+       (substitute-env-vars): Extend the meaning of the optional arg.
+
 2013-10-10  Eli Zaretskii  <address@hidden>
 
        * term/w32-win.el (dynamic-library-alist): Define separate lists

=== modified file 'lisp/env.el'
--- a/lisp/env.el       2013-01-02 16:13:04 +0000
+++ b/lisp/env.el       2013-10-10 21:42:38 +0000
@@ -1,4 +1,4 @@
-;;; env.el --- functions to manipulate environment variables
+;;; env.el --- functions to manipulate environment variables  -*- 
lexical-binding:t -*-
 
 ;; Copyright (C) 1991, 1994, 2000-2013 Free Software Foundation, Inc.
 
@@ -60,30 +60,46 @@
 (defconst env--substitute-vars-regexp
   "\\$\\(?:\\(?1:[[:alnum:]_]+\\)\\|{\\(?1:[^{}]+\\)}\\|\\$\\)")
 
-(defun substitute-env-vars (string &optional only-defined)
+(defun substitute-env-vars (string &optional when-undefined)
   "Substitute environment variables referred to in STRING.
 `$FOO' where FOO is an environment variable name means to substitute
 the value of that variable.  The variable name should be terminated
 with a character not a letter, digit or underscore; otherwise, enclose
 the entire variable name in braces.  For instance, in `ab$cd-x',
 `$cd' is treated as an environment variable.
-If ONLY-DEFINED is nil, references to undefined environment variables
-are replaced by the empty string; if it is non-nil, they are left unchanged.
+
+If WHEN-DEFINED is nil, references to undefined environment variables
+are replaced by the empty string; if it is a function, the function is called
+with the variable name as argument and should return the text with which
+to replace it or nil to leave it unchanged.
+If it is non-nil and not a function, references to undefined variables are
+left unchanged.
 
 Use `$$' to insert a single dollar sign."
   (let ((start 0))
     (while (string-match env--substitute-vars-regexp string start)
       (cond ((match-beginning 1)
-            (let ((value (getenv (match-string 1 string))))
-               (if (and (null value) only-defined)
+            (let* ((var (match-string 1 string))
+                    (value (getenv var)))
+               (if (and (null value)
+                        (if (functionp when-undefined)
+                            (null (setq value (funcall when-undefined var)))
+                          when-undefined))
                    (setq start (match-end 0))
-              (setq string (replace-match (or value "") t t string)
+                 (setq string (replace-match (or value "") t t string)
                        start (+ (match-beginning 0) (length value))))))
            (t
             (setq string (replace-match "$" t t string)
                   start (+ (match-beginning 0) 1)))))
     string))
 
+(defun substitute-env-in-file-name (filename)
+  (substitute-env-vars filename
+                       ;; How 'bout we lookup other tables than the env?
+                       ;; E.g. we could accept bookmark names as well!
+                       (if (memq system-type '(windows-nt ms-dos))
+                           (lambda (var) (getenv (upcase var)))
+                         t)))
 
 (defun setenv-internal (env variable value keep-empty)
   "Set VARIABLE to VALUE in ENV, adding empty entries if KEEP-EMPTY.

=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2013-10-10 19:26:13 +0000
+++ b/src/ChangeLog     2013-10-10 21:42:38 +0000
@@ -1,3 +1,9 @@
+2013-10-10  Stefan Monnier  <address@hidden>
+
+       * fileio.c (Fsubstitute_in_file_name): Use substitute-env-in-file-name.
+       (Qsubstitute_env_in_file_name): New var.
+       (syms_of_fileio): Define it.
+
 2013-10-10  Eli Zaretskii  <address@hidden>
 
        * xdisp.c (deep_copy_glyph_row): Assert that the 'used' counts of

=== modified file 'src/fileio.c'
--- a/src/fileio.c      2013-10-08 06:40:09 +0000
+++ b/src/fileio.c      2013-10-10 21:42:38 +0000
@@ -143,6 +143,8 @@
 /* Lisp function for recursively deleting directories.  */
 static Lisp_Object Qdelete_directory;
 
+static Lisp_Object Qsubstitute_env_in_file_name;
+
 #ifdef WINDOWSNT
 #endif
 
@@ -1664,10 +1666,8 @@
 those `/' is discarded.  */)
   (Lisp_Object filename)
 {
-  char *nm, *s, *p, *o, *x, *endp;
-  char *target = NULL;
-  ptrdiff_t total = 0;
-  bool substituted = 0;
+  char *nm, *p, *x, *endp;
+  bool substituted = false;
   bool multibyte;
   char *xnm;
   Lisp_Object handler;
@@ -1708,66 +1708,19 @@
     return Fsubstitute_in_file_name
       (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'.  */
-
-  for (p = nm; p != endp;)
-    if (*p != '$')
-      p++;
-    else
-      {
-       p++;
-       if (p == endp)
-         goto badsubst;
-       else if (*p == '$')
-         {
-           /* "$$" means a single "$".  */
-           p++;
-           total -= 1;
-           substituted = 1;
-           continue;
-         }
-       else if (*p == '{')
-         {
-           o = ++p;
-           p = memchr (p, '}', endp - p);
-           if (! p)
-             goto missingclose;
-           s = p;
-         }
-       else
-         {
-           o = p;
-           while (p != endp && (c_isalnum (*p) || *p == '_')) p++;
-           s = p;
-         }
-
-       /* Copy out the variable name.  */
-       target = alloca (s - o + 1);
-       memcpy (target, o, s - o);
-       target[s - o] = 0;
-#ifdef DOS_NT
-       strupr (target); /* $home == $HOME etc.  */
-#endif /* DOS_NT */
-
-       /* Get variable value.  */
-       o = egetenv (target);
-       if (o)
-         {
-           /* 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 = build_unibyte_string (o);
-           decoded = DECODE_FILE (orig);
-           total += SBYTES (decoded);
-           substituted = 1;
-         }
-       else if (*p == '}')
-         goto badvar;
-      }
+  /* See if any variables are substituted into the string.  */
+
+  if (!NILP (Ffboundp (Qsubstitute_env_in_file_name)))
+    {
+      Lisp_Object name
+       = (!substituted ? filename
+          : make_specified_string (nm, -1, endp - nm, multibyte));
+      Lisp_Object tmp = call1 (Qsubstitute_env_in_file_name, name);
+      CHECK_STRING (tmp);
+      if (!EQ (tmp, name))
+       substituted = true;
+      filename = tmp;
+    }
 
   if (!substituted)
     {
@@ -1778,73 +1731,9 @@
       return filename;
     }
 
-  /* If substitution required, recopy the string and do it.  */
-  /* Make space in stack frame for the new copy.  */
-  xnm = alloca (SBYTES (filename) + total + 1);
-  x = xnm;
-
-  /* Copy the rest of the name through, replacing $ constructs with values.  */
-  for (p = nm; *p;)
-    if (*p != '$')
-      *x++ = *p++;
-    else
-      {
-       p++;
-       if (p == endp)
-         goto badsubst;
-       else if (*p == '$')
-         {
-           *x++ = *p++;
-           continue;
-         }
-       else if (*p == '{')
-         {
-           o = ++p;
-           p = memchr (p, '}', endp - p);
-           if (! p)
-             goto missingclose;
-           s = p++;
-         }
-       else
-         {
-           o = p;
-           while (p != endp && (c_isalnum (*p) || *p == '_')) p++;
-           s = p;
-         }
-
-       /* Copy out the variable name.  */
-       target = alloca (s - o + 1);
-       memcpy (target, o, s - o);
-       target[s - o] = 0;
-
-       /* Get variable value.  */
-       o = egetenv (target);
-       if (!o)
-         {
-           *x++ = '$';
-           strcpy (x, target); x+= strlen (target);
-         }
-       else
-         {
-           Lisp_Object orig, decoded;
-           ptrdiff_t orig_length, decoded_length;
-           orig_length = strlen (o);
-           orig = make_unibyte_string (o, orig_length);
-           decoded = DECODE_FILE (orig);
-           decoded_length = SBYTES (decoded);
-           memcpy (x, SDATA (decoded), decoded_length);
-           x += decoded_length;
-
-           /* If environment variable needed decoding, return value
-              needs to be multibyte.  */
-           if (decoded_length != orig_length
-               || memcmp (SDATA (decoded), o, orig_length))
-             multibyte = 1;
-         }
-      }
-
-  *x = 0;
-
+  xnm = SSDATA (filename);
+  x = xnm + SBYTES (filename);
+  
   /* If /~ or // appears, discard everything through first slash.  */
   while ((p = search_embedded_absfilename (xnm, x)) != NULL)
     /* This time we do not start over because we've already expanded envvars
@@ -1862,14 +1751,9 @@
     }
   else
 #endif
-  return make_specified_string (xnm, -1, x - xnm, multibyte);
-
- badsubst:
-  error ("Bad format environment-variable substitution");
- missingclose:
-  error ("Missing \"}\" in environment-variable substitution");
- badvar:
-  error ("Substituting nonexistent environment variable \"%s\"", target);
+  return (xnm == SSDATA (filename)
+         ? filename
+         : make_specified_string (xnm, -1, x - xnm, multibyte));
 }
 
 /* A slightly faster and more convenient way to get
@@ -6108,6 +5992,7 @@
   DEFSYM (Qmove_file_to_trash, "move-file-to-trash");
   DEFSYM (Qcopy_directory, "copy-directory");
   DEFSYM (Qdelete_directory, "delete-directory");
+  DEFSYM (Qsubstitute_env_in_file_name, "substitute-env-in-file-name");
 
   defsubr (&Sfind_file_name_handler);
   defsubr (&Sfile_name_directory);


reply via email to

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