]> code.delx.au - gnu-emacs/commitdiff
Add a new function w32-application-type
authorEli Zaretskii <eliz@gnu.org>
Sat, 27 Jun 2015 10:48:26 +0000 (13:48 +0300)
committerEli Zaretskii <eliz@gnu.org>
Sat, 27 Jun 2015 10:48:26 +0000 (13:48 +0300)
* src/w32proc.c (Fw32_application_type): New function.
; * etc/NEWS: Mention w32-application-type.

etc/NEWS
src/w32proc.c

index ae62e76a6dcf4168b024804e794c539d7b0d6bed..84636552973c23714d57024f7744ab135534ebef 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1114,6 +1114,10 @@ Pass '--without-ns' to configure to create an X11 build, the old default.
 
 ** OS X on PowerPC is no longer supported.
 
+---
+** The new function 'w32-application-type' returns the type of an
+MS-Windows application given the name of its executable program file.
+
 \f
 ----------------------------------------------------------------------
 This file is part of GNU Emacs.
index 1f633d834c274128a9aaff414eed995db0ae871f..b301fcf18abb215d832d5a77e7a6cd952b23d522 100644 (file)
@@ -1527,22 +1527,25 @@ waitpid (pid_t pid, int *status, int options)
 
 /* Implementation note: This function works with file names encoded in
    the current ANSI codepage.  */
-static void
+static int
 w32_executable_type (char * filename,
                     int * is_dos_app,
                     int * is_cygnus_app,
+                    int * is_msys_app,
                     int * is_gui_app)
 {
   file_data executable;
   char * p;
+  int retval = 0;
 
   /* Default values in case we can't tell for sure.  */
   *is_dos_app = FALSE;
   *is_cygnus_app = FALSE;
+  *is_msys_app = FALSE;
   *is_gui_app = FALSE;
 
   if (!open_input_file (&executable, filename))
-    return;
+    return -1;
 
   p = strrchr (filename, '.');
 
@@ -1560,7 +1563,8 @@ w32_executable_type (char * filename,
         extension, which is defined in the registry.  */
       p = egetenv ("COMSPEC");
       if (p)
-       w32_executable_type (p, is_dos_app, is_cygnus_app, is_gui_app);
+       retval = w32_executable_type (p, is_dos_app, is_cygnus_app, is_msys_app,
+                                     is_gui_app);
     }
   else
     {
@@ -1637,6 +1641,16 @@ w32_executable_type (char * filename,
                       *is_cygnus_app = TRUE;
                       break;
                     }
+                 else if (strncmp (dllname, "msys-", 5) == 0)
+                   {
+                     /* This catches both MSYS 1.x and MSYS2
+                        executables (the DLL name is msys-1.0.dll and
+                        msys-2.0.dll, respectively).  There's doesn't
+                        seem to be a reason to distinguish between
+                        the two, for now.  */
+                     *is_msys_app = TRUE;
+                     break;
+                   }
                 }
             }
        }
@@ -1644,6 +1658,7 @@ w32_executable_type (char * filename,
 
 unwind:
   close_file_data (&executable);
+  return retval;
 }
 
 static int
@@ -1702,7 +1717,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
   int arglen, numenv;
   pid_t pid;
   child_process *cp;
-  int is_dos_app, is_cygnus_app, is_gui_app;
+  int is_dos_app, is_cygnus_app, is_msys_app, is_gui_app;
   int do_quoting = 0;
   /* We pass our process ID to our children by setting up an environment
      variable in their environment.  */
@@ -1713,10 +1728,10 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
      argument being split into two or more. Arguments with wildcards
      are also quoted, for consistency with posix platforms, where wildcards
      are not expanded if we run the program directly without a shell.
-     Some extra whitespace characters need quoting in Cygwin programs,
+     Some extra whitespace characters need quoting in Cygwin/MSYS programs,
      so this list is conditionally modified below.  */
   char *sepchars = " \t*?";
-  /* This is for native w32 apps; modified below for Cygwin apps.  */
+  /* This is for native w32 apps; modified below for Cygwin/MSUS apps.  */
   char escape_char = '\\';
   char cmdname_a[MAX_PATH];
 
@@ -1777,15 +1792,17 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
   cmdname = cmdname_a;
   argv[0] = cmdname;
 
-  /* Determine whether program is a 16-bit DOS executable, or a 32-bit Windows
-     executable that is implicitly linked to the Cygnus dll (implying it
-     was compiled with the Cygnus GNU toolchain and hence relies on
-     cygwin.dll to parse the command line - we use this to decide how to
-     escape quote chars in command line args that must be quoted).
+  /* Determine whether program is a 16-bit DOS executable, or a 32-bit
+     Windows executable that is implicitly linked to the Cygnus or
+     MSYS dll (implying it was compiled with the Cygnus/MSYS GNU
+     toolchain and hence relies on cygwin.dll or MSYS DLL to parse the
+     command line - we use this to decide how to escape quote chars in
+     command line args that must be quoted).
 
      Also determine whether it is a GUI app, so that we don't hide its
      initial window unless specifically requested.  */
-  w32_executable_type (cmdname, &is_dos_app, &is_cygnus_app, &is_gui_app);
+  w32_executable_type (cmdname, &is_dos_app, &is_cygnus_app, &is_msys_app,
+                      &is_gui_app);
 
   /* On Windows 95, if cmdname is a DOS app, we invoke a helper
      application to start it by specifying the helper app as cmdname,
@@ -1845,10 +1862,10 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
       if (INTEGERP (Vw32_quote_process_args))
        escape_char = XINT (Vw32_quote_process_args);
       else
-       escape_char = is_cygnus_app ? '"' : '\\';
+       escape_char = (is_cygnus_app || is_msys_app) ? '"' : '\\';
     }
 
-  /* Cygwin apps needs quoting a bit more often.  */
+  /* Cygwin/MSYS apps need quoting a bit more often.  */
   if (escape_char == '"')
     sepchars = "\r\n\t\f '";
 
@@ -1866,7 +1883,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
       for ( ; *p; p++)
        {
          if (escape_char == '"' && *p == '\\')
-           /* If it's a Cygwin app, \ needs to be escaped.  */
+           /* If it's a Cygwin/MSYS app, \ needs to be escaped.  */
            arglen++;
          else if (*p == '"')
            {
@@ -2947,6 +2964,59 @@ If successful, the return value is t, otherwise nil.  */)
   return result;
 }
 
+DEFUN ("w32-application-type", Fw32_application_type,
+       Sw32_application_type, 1, 1, 0,
+       doc: /* Return the type of an MS-Windows PROGRAM.
+
+Knowing the type of an executable could be useful for formatting
+file names passed to it or for quoting its command-line arguments.
+
+PROGRAM should specify an executable file, including the extension.
+
+The value is one of the following:
+
+`dos'        -- a DOS .com program or some other non-PE executable
+`cygwin'     -- a Cygwin program that depends on Cygwin DLL
+`msys'       -- an MSYS 1.x or MSYS2 program
+`w32-native' -- a native Windows application
+`unknown'    -- a file that doesn't exist, or cannot be open, or whose
+                name is not encodable in the current ANSI codepage.
+
+Note that for .bat and .cmd batch files the function returns the type
+of their command interpreter, as specified by the \"COMSPEC\"
+environment variable.
+
+This function returns `unknown' for programs whose file names
+include characters not supported by the current ANSI codepage, as
+such programs cannot be invoked by Emacs anyway.  */)
+     (Lisp_Object program)
+{
+  int is_dos_app, is_cygwin_app, is_msys_app, dummy;
+  Lisp_Object encoded_progname;
+  char *progname, progname_a[MAX_PATH];
+
+  program = Fexpand_file_name (program, Qnil);
+  encoded_progname = ENCODE_FILE (program);
+  progname = SDATA (encoded_progname);
+  unixtodos_filename (progname);
+  filename_to_ansi (progname, progname_a);
+  /* Reject file names that cannot be encoded in the current ANSI
+     codepage.  */
+  if (_mbspbrk (progname_a, "?"))
+    return Qunknown;
+
+  if (w32_executable_type (progname_a, &is_dos_app, &is_cygwin_app,
+                          &is_msys_app, &dummy) != 0)
+    return Qunknown;
+  if (is_dos_app)
+    return Qdos;
+  if (is_cygwin_app)
+    return Qcygwin;
+  if (is_msys_app)
+    return Qmsys;
+  return Qw32_native;
+}
+
 #ifdef HAVE_LANGINFO_CODESET
 /* Emulation of nl_langinfo.  Used in fns.c:Flocale_info.  */
 char *
@@ -3541,6 +3611,9 @@ syms_of_ntproc (void)
 {
   DEFSYM (Qhigh, "high");
   DEFSYM (Qlow, "low");
+  DEFSYM (Qcygwin, "cygwin");
+  DEFSYM (Qmsys, "msys");
+  DEFSYM (Qw32_native, "w32-native");
 
   defsubr (&Sw32_has_winsock);
   defsubr (&Sw32_unload_winsock);
@@ -3548,6 +3621,7 @@ syms_of_ntproc (void)
   defsubr (&Sw32_short_file_name);
   defsubr (&Sw32_long_file_name);
   defsubr (&Sw32_set_process_priority);
+  defsubr (&Sw32_application_type);
   defsubr (&Sw32_get_locale_info);
   defsubr (&Sw32_get_current_locale_id);
   defsubr (&Sw32_get_default_locale_id);