2004-03-19  Juan Manuel Guerrero  <st001906@hrz1.hrz.tu-darmstadt.de>

	* quotearg.h: Add quoting styles for DOS and NT shells.  Add
	"default" pseudo-style.
	[DEFAULT_QUOTING_STYLE]: Now defaults to `default_quoting_style'.

	* quotearg.c [DEFAULT_OS_QUOTING_STYLE]: If not defined, make it
	default to `shell_quoting_style'.
	[DEFAULT_OS_QUOTING_STYLE_DCL]: Use if defined.
	(quoting_style_args): Add quoting styles for DOS and NT shells.
	Add "default" pseudo-style.
	(set_quoting_style): If S is `default_quoting_style', use whatever
	DEFAULT_OS_QUOTING_STYLE yields.
	(quotearg_buffer): Support quoting suitable for DOS and NT shells.

	* quotesys.c (quote_system_arg) [quote_system_arg_func]: If this
	hook for quoting `system' arguments on non-Posix platforms is
	defined, call it instead of the usual code.

	* pc/pc_quote.c: New file.
	(dos_nt_quoting): New function to determine the default quoting
	style suitable for the user shell on MS-DOS/MS-Windows systems.

	* pc/djgpp/config_h.sed: Define DEFAULT_OS_QUOTING_STYLE to be a
	call to `dos_nt_quoting', and define DEFAULT_OS_QUOTING_STYLE_DCL
	to declare its prototype.
	Define filename_char_eq to compare characters regardless of the
	letter-case.

	* addext.c (addext): Support numbered backups under DOS 8+3 file
	name limits.

	* backupfile.c (max_backup_version): Under HAVE_DOS_FILE_NAMES,
	don't give up on file names unless they are shorter than the
	original file's name.
	(version_number): Use filename_char_eq to compare file names on
	case-insensitive filesystems.  Support numbered backups under 8+3
	file name limits.



diff -apruNU5 patch-2.5.4.orig/addext.c patch-2.5.4.djgpp/addext.c
--- patch-2.5.4.orig/addext.c	1999-01-18 17:02:28.000000000 +0000
+++ patch-2.5.4.djgpp/addext.c	2004-03-16 01:49:08.000000000 +0000
@@ -80,19 +80,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 -apruNU5 patch-2.5.4.orig/backupfile.c patch-2.5.4.djgpp/backupfile.c
--- patch-2.5.4.orig/backupfile.c	1999-01-18 17:02:28.000000000 +0000
+++ patch-2.5.4.djgpp/backupfile.c	2004-03-16 01:29:42.000000000 +0000
@@ -21,10 +21,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 <argmatch.h>
 #include <backupfile.h>
 
 #include <stdio.h>
 #include <sys/types.h>
@@ -180,11 +190,15 @@ max_backup_version (const char *file, co
   highest_version = 0;
   file_name_length = strlen (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;
@@ -200,22 +214,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 -apruNU5 patch-2.5.4.orig/patch.c patch-2.5.4.djgpp/patch.c
--- patch-2.5.4.orig/patch.c	1999-08-30 06:20:08.000000000 +0000
+++ patch-2.5.4.djgpp/patch.c	2004-03-16 01:08:10.000000000 +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"))
diff -apruNU5 patch-2.5.4.orig/pc/pc_quote.c patch-2.5.4.djgpp/pc/pc_quote.c
--- patch-2.5.4.orig/pc/pc_quote.c	1970-01-01 00:00:00.000000000 +0000
+++ patch-2.5.4.djgpp/pc/pc_quote.c	1998-03-28 14:57:06.000000000 +0000
@@ -0,0 +1,104 @@
+/* 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>
+
+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 -apruNU5 patch-2.5.4.orig/quotearg.c patch-2.5.4.djgpp/quotearg.c
--- patch-2.5.4.orig/quotearg.c	1999-08-23 09:55:54.000000000 +0000
+++ patch-2.5.4.djgpp/quotearg.c	2004-03-18 23:10:56.000000000 +0000
@@ -25,10 +25,18 @@
 
 #include <sys/types.h>
 #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>
 #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
 # define ISASCII(c) 1
 #else
 # define ISASCII(c) isascii (c)
@@ -78,16 +86,19 @@ struct quoting_options
 };
 
 /* Names of quoting styles.  */
 char const *const quoting_style_args[] =
 {
+  "default",
   "literal",
   "shell",
   "shell-always",
   "c",
   "escape",
   "locale",
+  "dos-shell",
+  "nt-shell",
   0
 };
 
 /* Correspondences to quoting style names.  */
 enum quoting_style const quoting_style_vals[] =
@@ -125,10 +136,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.
@@ -160,10 +173,11 @@ quotearg_buffer (char *buffer, size_t bu
 		 struct quoting_options const *o)
 {
   unsigned char c;
   size_t i;
   size_t len = 0;
+  int quote_mark;
   char const *quote_string;
   size_t quote_string_len;
   struct quoting_options const *p = o ? o : &default_quoting_options;
   enum quoting_style quoting_style = p->style;
 #define STORE(c) \
@@ -176,49 +190,68 @@ quotearg_buffer (char *buffer, size_t bu
     while (0)
 
   switch (quoting_style)
     {
     case shell_quoting_style:
+    case dos_shell_quoting_style:
+    case nt_shell_quoting_style:
       if (! (argsize == (size_t) -1 ? arg[0] == '\0' : argsize == 0))
 	{
 	  switch (arg[0])
 	    {
 	    case '#': case '~':
-	      break;
+	      if (quoting_style == shell_quoting_style)
+		break;
 
+	      /* Fall through.  */
 	    default:
 	      for (i = 0; ; i++)
 		{
 		  if (argsize == (size_t) -1 ? arg[i] == '\0' : i == argsize)
 		    goto done;
 
 		  c = arg[i];
 
 		  switch (c)
 		    {
-		    case '\t': case '\n': case ' ':
-		    case '!': /* special in csh */
-		    case '"': case '$': case '&': case '\'':
-		    case '(': case ')': case '*': case ';':
-		    case '<': case '>': case '?': case '[': case '\\':
-		    case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
-		    case '`': case '|':
+		    case ' ': case '\t':
+		    case '<': case '>': case '|':
+		    case '"': case '\'':
+		    case '*': case '?': case '[':
+		    case '&': /* special in [4N]DOS.COM and in CMD.EXE */
+		    case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4
+				 and in [4N]DOS.COM  */
 		      goto needs_quoting;
+		    case '.': /* `...': special in DJGPP wildcard expansion */
+		      if (quoting_style != shell_quoting_style
+			  && arg[i+1] == '.' && arg[i+2] == '.'
+			  && strchr ("\\/", arg[i+3]))
+			goto needs_quoting;
+		    case '!': /* special in csh */
+		    case '$': case '`':
+		    case '(': case ')': case ';':
+		    case '\\': case '\n':
+		      if (quoting_style == shell_quoting_style)
+			goto needs_quoting;
+		    case '%':
+		      if (quoting_style == dos_shell_quoting_style)
+			goto needs_quoting;
 		    }
 
 		  if (p->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS)))
 		    goto needs_quoting;
 
 		  STORE (c);
 		}
 	    needs_quoting:;
 
+	      quote_mark = quoting_style == shell_quoting_style ? '\'' : '"';
 	      len = 0;
 	      break;
 	    }
 	}
-      /* Fall through.  */
+      break;
 
     case shell_always_quoting_style:
       STORE ('\'');
       quote_string = "'";
       quote_string_len = 1;
@@ -250,17 +283,26 @@ quotearg_buffer (char *buffer, size_t bu
       switch (quoting_style)
 	{
 	case literal_quoting_style:
 	  break;
 
+	case dos_shell_quoting_style:
+	  if (c == '%')	/* need to double it under DOS shells */
+	    {
+	      STORE (c);
+	      break;
+	    }
+	  
+	  /* Fall through.  */
+	case nt_shell_quoting_style:
 	case shell_quoting_style:
 	case shell_always_quoting_style:
-	  if (c == '\'')
+	  if (c == quote_mark)
 	    {
-	      STORE ('\'');
+	      STORE (quote_mark);
 	      STORE ('\\');
-	      STORE ('\'');
+	      STORE (quote_mark);
 	    }
 	  break;
 
 	case c_quoting_style:
 	case escape_quoting_style:
diff -apruNU5 patch-2.5.4.orig/quotearg.h patch-2.5.4.djgpp/quotearg.h
--- patch-2.5.4.orig/quotearg.h	1999-08-09 23:09:12.000000000 +0000
+++ patch-2.5.4.djgpp/quotearg.h	2004-03-17 01:41:46.000000000 +0000
@@ -18,21 +18,23 @@
 /* Written by Paul Eggert <eggert@twinsun.com> */
 
 /* 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 */
   };
 
-/* 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 -apruNU5 patch-2.5.4.orig/quotesys.c patch-2.5.4.djgpp/quotesys.c
--- patch-2.5.4.orig/quotesys.c	1998-03-15 14:44:46.000000000 +0000
+++ patch-2.5.4.djgpp/quotesys.c	2004-03-16 00:09:56.000000000 +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 */
 }
