diff -aprNU5 patch-2.5.9.orig/addext.c patch-2.5.9/addext.c
--- patch-2.5.9.orig/addext.c	2003-05-18 05:30:52 +0000
+++ patch-2.5.9/addext.c	2006-02-07 23:01:22 +0000
@@ -95,19 +95,68 @@ addext (char *filename, char const *ext,
 
   if (HAVE_DOS_FILE_NAMES && slen_max <= 12)
     {
       /* Live within DOS's 8.3 limit.  */
       char *dot = strchr (s, '.');
+      size_t s_ext_len = 0;	/* length of existing extension in `s' */
+
       if (dot)
+	s_ext_len = slen - (dot + 1 - s);
+      else if (ext[0] == '.')
 	{
-	  slen -= dot + 1 - s;
-	  s = dot + 1;
-	  slen_max = 3;
+	  s[slen++] = '.';
+	  s[slen] = '\0';
+	  dot = s + slen - 1;
+	}
+
+      /* DOS doesn't allow more than a single dot.  */
+      if (ext[0] == '.')
+	{
+	  ext++;
+	  extlen--;
+	}
+
+      /* If EXT is "~N~" and there's not enough space to append it,
+	 lose the leading `~' so that we could salvage more of the
+	 original name ("foo.c" + ".~9~" -> "foo.c9~").  */
+      if (s_ext_len + extlen > 3 && ext[0] == '~' && extlen > 1)
+	{
+	  ext++;
+	  extlen--;
+	}
+      /* If there isn't enough space in the extension to append
+	 EXT, use the base part ("foo.c" + ".~99~" -> "foo99~").  */
+      if (!dot || extlen > 3)
+	{
+	  slen_max = 8;
+	  if (dot)
+	    slen = dot - s;
+	  if (extlen < slen_max)
+	    {
+	      if (slen + extlen > slen_max)
+		slen = slen_max - extlen;
+	    }
+	  /* Else give up and force using E.  We don't allow EXT to
+	     eat up all of the original filename's characters.  That
+	     is, "foo" + ".~3456789~" should NOT yield "3456789~".  */
+	  else if (dot)
+	    {
+	      slen_max = 3;
+	      extlen = 4;
+	      s = dot + 1;
+	      slen = s_ext_len;
+	    }
 	}
       else
-	slen_max = 8;
-      extlen = 9; /* Don't use EXT.  */
+	{
+	  /* Extension has enough space to append EXT.  */
+	  slen_max = 3;
+	  slen = s_ext_len;
+	  s = dot + 1;
+	  if (slen + extlen > slen_max)
+	    slen = slen_max - extlen;
+	}
     }
 
   if (slen + extlen <= slen_max)
     strcpy (s + slen, ext);
   else
diff -aprNU5 patch-2.5.9.orig/backupfile.c patch-2.5.9/backupfile.c
--- patch-2.5.9.orig/backupfile.c	2002-01-16 22:44:24 +0000
+++ patch-2.5.9/backupfile.c	2006-02-07 23:07:12 +0000
@@ -22,10 +22,20 @@
 
 #if HAVE_CONFIG_H
 # include <config.h>
 #endif
 
+#ifndef HAVE_DOS_FILE_NAMES
+# define HAVE_DOS_FILE_NAMES 0
+#endif
+
+#ifndef filename_char_eq
+# define filename_char_eq(c1,c2)  ((c1) == (c2))
+#else
+# include <ctype.h>
+#endif
+
 #include <stdio.h>
 #include <sys/types.h>
 #if HAVE_STRING_H
 # include <string.h>
 #else
@@ -189,11 +199,15 @@ max_backup_version (const char *file, co
   highest_version = 0;
   file_name_length = base_len (file);
 
   while ((dp = readdir (dirp)) != 0)
     {
-      if (!REAL_DIR_ENTRY (dp) || NLENGTH (dp) < file_name_length + 4)
+      if (!REAL_DIR_ENTRY (dp)
+	  /* Under DOS 8+3 file name limits, backup extensions
+	     may consume part of the original name.  */
+	  || (! HAVE_DOS_FILE_NAMES && NLENGTH (dp) < file_name_length + 4)
+	  || NLENGTH (dp) < file_name_length)
 	continue;
 
       this_version = version_number (file, dp->d_name, file_name_length);
       if (this_version > highest_version)
 	highest_version = this_version;
@@ -209,22 +223,34 @@ max_backup_version (const char *file, co
 
 static int
 version_number (const char *base, const char *backup, size_t base_length)
 {
   int version;
-  const char *p;
+  const char *s = base;
+  const char *s_end = base + base_length;
+  const char *p = backup;
 
   version = 0;
-  if (strncmp (base, backup, base_length) == 0
-      && backup[base_length] == '.'
-      && backup[base_length + 1] == '~')
-    {
-      for (p = &backup[base_length + 2]; ISDIGIT (*p); ++p)
-	version = version * 10 + *p - '0';
-      if (p[0] != '~' || p[1])
-	version = 0;
-    }
+
+  /* This could use `strncmp', but under HAVE_DOS_FILE_NAMES the two
+     files need not compare equal to the full extent of BASE_LENGTH.  */
+  if (! filename_char_eq (*p, *s))
+    return 0;
+  for ( ; s < s_end && filename_char_eq (*p, *s); p++, s++)
+    ;
+  if (p[0] == '.' && p[1] == '~')
+    p += 2;
+  else if (! HAVE_DOS_FILE_NAMES)
+    return 0;
+  else if (*p == '.')	/* the case of foo.99~ vs foo.c */
+    p++;
+
+  for ( ; ISDIGIT (*p); ++p)
+    version = version * 10 + *p - '0';
+  if (p[0] != '~' || p[1])
+    version = 0;
+
   return version;
 }
 #endif /* HAVE_DIR */
 
 static const char * const backup_args[] =
diff -aprNU5 patch-2.5.9.orig/patch.c patch-2.5.9/patch.c
--- patch-2.5.9.orig/patch.c	2003-05-20 13:55:02 +0000
+++ patch-2.5.9/patch.c	2006-04-05 23:27:22 +0000
@@ -133,11 +133,11 @@ main (int argc, char **argv)
 
     val = getenv ("QUOTING_STYLE");
     {
       int i = val ? argmatch (val, quoting_style_args, 0, 0) : -1;
       set_quoting_style ((struct quoting_options *) 0,
-			 i < 0 ? shell_quoting_style : (enum quoting_style) i);
+			 i < 0 ? DEFAULT_QUOTING_STYLE : (enum quoting_style) i);
     }
 
     posixly_correct = getenv ("POSIXLY_CORRECT") != 0;
     backup_if_mismatch = ! posixly_correct;
     patch_get = ((val = getenv ("PATCH_GET"))
@@ -1302,11 +1302,15 @@ similar (register char const *a, registe
 #if HAVE_MKTEMP && ! HAVE_DECL_MKTEMP && ! defined mktemp
 char *mktemp (char *);
 #endif
 
 #ifndef TMPDIR
-#define TMPDIR "/tmp"
+# if FILESYSTEM_BACKSLASH_IS_FILE_NAME_SEPARATOR
+#  define TMPDIR "c:"
+# else /* POSIX systems */
+#  define TMPDIR "/tmp"
+# endif
 #endif
 
 static char const *
 make_temp (char letter)
 {
diff -aprNU5 patch-2.5.9.orig/pc/pc_quote.c patch-2.5.9/pc/pc_quote.c
--- patch-2.5.9.orig/pc/pc_quote.c	1970-01-01 00:00:00 +0000
+++ patch-2.5.9/pc/pc_quote.c	2006-04-06 20:22:32 +0000
@@ -0,0 +1,105 @@
+/* pc_quote.c - quoting functions specific to PC environments
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+extern char *getenv();
+#endif
+
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifndef F_OK
+# define F_OK 0
+#endif
+
+#include <ctype.h>
+
+#include <quotearg.h>
+#include <backupfile.h>
+#include <dirname.h>
+
+struct shell_spec {
+  const char *name;
+  const size_t name_len;
+  const enum quoting_style style;
+};
+
+#include <stdio.h>
+
+/* Determine the default quoting style suitable for the user's shell.  */
+enum quoting_style
+dos_nt_quoting (void)
+{
+  /* Environment variables used to specify the user shell.  */
+  static char const *const shell_vars[] = {
+    "BASH", "SHELL", "COMSPEC", "ComSpec", 0
+  };
+
+  /* List of shells which don't support Unix-style shell_quoting_style.  */
+  static char const command_com[] = "COMMAND.COM";
+  static char const fordos_com[] = "4DOS.COM";
+  static char const ndos_com[] = "NDOS.COM";
+  static char const cmd_exe[] = "CMD.EXE";
+
+  static struct shell_spec const dos_nt_shells[] = {
+    {command_com, sizeof(command_com) - 1, dos_shell_quoting_style},
+    {fordos_com, sizeof(fordos_com) - 1, dos_shell_quoting_style},
+    {ndos_com, sizeof(ndos_com) - 1, dos_shell_quoting_style},
+    {cmd_exe, sizeof(cmd_exe) - 1, nt_shell_quoting_style},
+    {0, 0, 0}
+  };
+
+  const char *const *try_var = shell_vars;
+  char *shell = NULL;
+
+  while (*try_var
+	 && ((shell = getenv (*try_var)) == NULL
+	     /* Make sure it is indeed a name of an existing file.  */
+	     || access (shell, F_OK) == -1))
+    try_var++;
+
+  if (shell)
+    {
+      char *shell_base = base_name (shell);
+      size_t shell_base_len = strlen (shell_base);
+      const struct shell_spec *try_shell;
+
+      for (try_shell = dos_nt_shells; try_shell->name; try_shell++)
+	if (shell_base_len == try_shell->name_len)
+	  {
+	    const char *s = shell_base, *p = try_shell->name;
+
+	    for ( ; *s && *p && filename_char_eq (*s, *p); s++, p++)
+	      ;
+	    if (*s == '\0' && *p == '\0')
+	      return try_shell->style;
+	  }
+    }
+
+  /* All other shells are assumed to be Unix-like.  */
+  return shell_quoting_style;
+}
diff -aprNU5 patch-2.5.9.orig/quotearg.c patch-2.5.9/quotearg.c
--- patch-2.5.9.orig/quotearg.c	2002-11-23 06:45:48 +0000
+++ patch-2.5.9/quotearg.c	2006-04-06 18:55:12 +0000
@@ -23,10 +23,18 @@
 
 #include "quotearg.h"
 
 #include "xalloc.h"
 
+#ifndef DEFAULT_OS_QUOTING_STYLE
+# define DEFAULT_OS_QUOTING_STYLE shell_quoting_style
+#endif
+
+#ifdef DEFAULT_OS_QUOTING_STYLE_DCL
+ DEFAULT_OS_QUOTING_STYLE_DCL
+#endif
+
 #include <ctype.h>
 #include <errno.h>
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
@@ -92,10 +100,12 @@ char const *const quoting_style_args[] =
   "shell-always",
   "c",
   "escape",
   "locale",
   "clocale",
+  "dos-shell",
+  "nt-shell",
   0
 };
 
 /* Correspondences to quoting style names.  */
 enum quoting_style const quoting_style_vals[] =
@@ -135,10 +145,12 @@ get_quoting_style (struct quoting_option
 /* In O (or in the default if O is null),
    set the value of the quoting style to S.  */
 void
 set_quoting_style (struct quoting_options *o, enum quoting_style s)
 {
+  if (s == default_quoting_style)
+    s = DEFAULT_OS_QUOTING_STYLE;
   (o ? o : &default_quoting_options)->style = s;
 }
 
 /* In O (or in the default if O is null),
    set the value of the quoting options for character C to I.
@@ -346,10 +358,12 @@ quotearg_buffer_restyled (char *buffer, 
 	  break;
 
 	case '\'':
 	  switch (quoting_style)
 	    {
+	    case dos_shell_quoting_style:
+	    case nt_shell_quoting_style:
 	    case shell_quoting_style:
 	      goto use_shell_always_quoting_style;
 
 	    case shell_always_quoting_style:
 	      STORE ('\'');
@@ -375,10 +389,23 @@ quotearg_buffer_restyled (char *buffer, 
 	case 'o': case 'p': case 'q': case 'r': case 's': case 't':
 	case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
 	case '{': case '}':
 	  /* These characters don't cause problems, no matter what the
 	     quoting style is.  They cannot start multibyte sequences.  */
+	  switch (c)
+	    {
+	    case '.': /* `...': special in DJGPP wildcard expansion */
+	      if (quoting_style != shell_quoting_style
+	          && arg[i + 1] == '.' && arg[i + 2] == '.'
+	          && strchr ("\\/", arg[i + 3]))
+	        goto use_shell_always_quoting_style;
+	      break;
+	    case '%':
+	      if (quoting_style == dos_shell_quoting_style)  /* need to double it under DOS shells */
+	        STORE (c);
+	      break;
+	    }
 	  break;
 
 	default:
 	  /* If we have a multibyte sequence, copy it until we reach
 	     its end, find an error, or come back to the initial shift
diff -aprNU5 patch-2.5.9.orig/quotearg.h patch-2.5.9/quotearg.h
--- patch-2.5.9.orig/quotearg.h	2002-11-23 06:45:22 +0000
+++ patch-2.5.9/quotearg.h	2006-02-07 23:19:36 +0000
@@ -25,22 +25,24 @@
 # include <stddef.h>
 
 /* Basic quoting styles.  */
 enum quoting_style
   {
+    default_quoting_style,	/* --quoting-style=default */
     literal_quoting_style,	/* --quoting-style=literal */
     shell_quoting_style,	/* --quoting-style=shell */
     shell_always_quoting_style,	/* --quoting-style=shell-always */
     c_quoting_style,		/* --quoting-style=c */
     escape_quoting_style,	/* --quoting-style=escape */
+    dos_shell_quoting_style,	/* --quoting-style=dos-shell */
+    nt_shell_quoting_style,	/* --quoting-style=nt-shell */
     locale_quoting_style,	/* --quoting-style=locale */
     clocale_quoting_style	/* --quoting-style=clocale */
   };
 
-/* For now, --quoting-style=literal is the default, but this may change.  */
 # ifndef DEFAULT_QUOTING_STYLE
-#  define DEFAULT_QUOTING_STYLE literal_quoting_style
+#  define DEFAULT_QUOTING_STYLE default_quoting_style
 # endif
 
 /* Names of quoting styles and their corresponding values.  */
 extern char const *const quoting_style_args[];
 extern enum quoting_style const quoting_style_vals[];
diff -aprNU5 patch-2.5.9.orig/quotesys.c patch-2.5.9/quotesys.c
--- patch-2.5.9.orig/quotesys.c	1998-03-15 14:44:46 +0000
+++ patch-2.5.9/quotesys.c	2006-02-07 23:21:24 +0000
@@ -35,10 +35,16 @@ quote_system_arg (quoted, arg)
      char const *arg;
 {
   char const *a;
   size_t len = 0;
 
+  /* A hook for non-Posix platforms to define a quoting
+     scheme peculiar to their implementation of `system'.  */
+#ifdef quote_system_arg_func
+  return quote_system_arg_func (quoted, arg);
+#else
+
   /* Scan ARG, copying it to QUOTED if QUOTED is not null,
      looking for shell metacharacters.  */
 
   for (a = arg; ; a++)
     {
@@ -120,6 +126,7 @@ quote_system_arg (quoted, arg)
 
       if (quoted)
 	quoted[len] = c;
       len++;
     }
+#endif /* nonposix_quote_system_arg */
 }
