2006-06-07  Juan M. Guerrero  <juan.guerrero@gmx.de>

	* sed/utils.h [O_BINARY]: New macro IS_SLASH to check if character is
	a directory separator for the particular OS.

	* sed/utils.c (follow_symlink): Use IS_SLASH and LAST_SLASH to detect
	directory separator character in the file name.

	* lib/getdelim.c (getdelim) [MSDOS]: For DOS-like systems strip the
	trailing CR.


2006-06-05  Juan M. Guerrero  <juan.guerrero@gmx.de>

	* lib/mbrtowc.c: If EILSEQ is not defined, define it to the value given
	by djdev204's errno.h.
	* lib/wcrtomb.c: If EILSEQ is not defined, define it to the value given
	by djdev204's errno.h.


2006-06-04  Juan M. Guerrero  <juan.guerrero@gmx.de>

	* doc/sed-in.tex: Add DJGPP port specific info about backup names when
	only SFN supports is available.


2006-06-02  Juan M. Guerrero  <juan.guerrero@gmx.de>

	* lib/set-mode-acl.c (set_acl) [__DJGPP__]: Include fcntl.h.  If only
	SFN is supported fchmod will fail with ENOSYS whhen trying to change
	the file mode.  Do not issue the error message.


2006-06-01  Juan M. Guerrero  <juan.guerrero@gmx.de>

	* sed/utils.h [O_BINARY]: New macro LFN_FILE_SYSTEM to check if
	the used file system supports LFN or only SFN.

	* sed/execute.c (get_backup_file_name) [MSDOS, __DJGPP__]: Use
	LFN_FILE_SYSTEM to check if only SFN support is available.  In
	that case generate a new and 8+3 conforming backup file name.


2006-05-30  Juan M. Guerrero  <juan.guerrero@gmx.de>

	* sed/execute.c (closedown): Close files to be renamed before
	issuing the rename() and not after.


2006-05-19  Juan M. Guerrero  <juan.guerrero@gmx.de>

	* sed/utils.h [O_BINARY]: New macro LAST_SLASH defined to check for the
	last slash or backslash as directory separator in the given filename.

	* sed/execute.c (open_next_file): Use LAST_SLASH.


2006-05-17  Juan M. Guerrero  <juan.guerrero@gmx.de>

	* sed/utils.c (ck_mkstemp) [MSDOS]: Check for the TEMP variable too
	before defaulting to P_tmpdir and test that the used tempdir really
	does exists before starting using it.

	* sed/utils.h [O_BINARY, __DJGPP__]: New macro IS_TMPDIR to check that
	the value passed really points to an existing directory to be used as
	tmpdir.  For no DJGPP system it defaults to the original sed code check.


2006-05-11  Juan M. Guerrero  <juan.guerrero@gmx.de>

	* sed/sed.h [O_BINARY]: Define macro
	SYSTEM_CALL_NEED_MULTIPLE_CMDS_ENABLING for non posix systems
	where for system() multiple, semicolon separated, commands must
	be explicitly enabled.
	[O_BINARY]: Declare the system_flags variable to change system()
	behaviour.

	* sed/sed.c (main) [SYSTEM_CALL_NEED_MULTIPLE_CMDS_ENABLING]: Set
	system_allow_multiple_cmds in the system_flags variable.

	* sed/execute.c	(dump_append_queue): Call set_read_mode.
	[O_BINARY]: Remove ^M, if before the newline, and ^Z, if
	immediately before EOF.
	(open_next_file): Call set_read_mode.

	* sed/utils.c [O_BINARY]: Include sys/stat.h and make sure S_ISCHR
	is defined.
	(set_read_mode): New function, switches a stream into binary mode.
	This is a no-op unless O_BINARY is defined.
        (is_a_device): New function, checks if the file pointer is associated
        to stdout.
	(ck_fwrite) [O_BINARY]: If we are writing to a character device,
	replace every ^Z character with an ASCII string "^Z".

	* sed/utils.h: Include fcntl.h.
	(O_BINARY, setmode): Define if O_BINARY is undefined.
	[O_BINARY]: Include io.h.
	(set_read_mode): Declare a prototype.

	* lib/regex_internal.h: Check if HAVE_ALLOCA_H defined before
	trying to include alloca.h.








diff -aprNU5 sed-4.2.orig/doc/sed-in.texi sed-4.2/doc/sed-in.texi
--- sed-4.2.orig/doc/sed-in.texi	2009-04-27 10:14:50 +0000
+++ sed-4.2/doc/sed-in.texi	2009-06-07 02:34:02 +0000
@@ -268,10 +268,31 @@ even to place backup copies of the origi
 directory (provided the directory already exists).
 
 If no extension is supplied, the original file is
 overwritten without making a backup.
 
+For the DJGPP port, if only SFN support is available, the backup
+file name will be truncated to the well known @code{8+3} length.
+This rule is followed: the suffix will remove as many characters
+as necessary from a potentially existing extension to fit into
+the 3 characters long space available for extensions; if a prefix
+is given, it will shift to the right as many as characters are
+necessary to fit into the 8 characters long space available for
+file names.  As example, the following command:
+
+@example
+sed -ibck_*_up s/foobar/raboof/ filename.txt
+@end example
+
+@noindent
+will produce a backup file for @code{filename.txt} with @code{bck_file._up}
+as backup file name.  As can be seen the suffix @code{_up} is 3
+characters long an overwrites the file name's extension @code{ext}
+completely.  The prefix @code{bck_} is 4 characters long and occupies
+the place of the first 4 characters of the file name, so that the last
+4 characters of the original file name are lost.
+
 @item -l @var{N}
 @itemx --line-length=@var{N}
 @opindex -l
 @opindex --line-length
 @cindex Line length, setting
diff -aprNU5 sed-4.2.orig/lib/getdelim.c sed-4.2/lib/getdelim.c
--- sed-4.2.orig/lib/getdelim.c	2009-01-20 08:31:12 +0000
+++ sed-4.2/lib/getdelim.c	2009-06-07 17:19:20 +0000
@@ -123,11 +123,18 @@ getdelim (char **lineptr, size_t *n, int
 
       (*lineptr)[cur_len] = i;
       cur_len++;
 
       if (i == delimiter)
-	break;
+        {
+#ifdef MSDOS
+	  /*  For DOS-like systems strip the trailing CR.  */
+	  if ((i = cur_len - 2) >= 0 && (*lineptr)[i] == '\r')
+	    (*lineptr)[i] = (*lineptr)[--cur_len];
+#endif
+	  break;
+        }
     }
   (*lineptr)[cur_len] = '\0';
   result = cur_len ? cur_len : result;
 
  unlock_return:
diff -aprNU5 sed-4.2.orig/lib/mbrtowc.c sed-4.2/lib/mbrtowc.c
--- sed-4.2.orig/lib/mbrtowc.c	2009-04-27 10:12:26 +0000
+++ sed-4.2/lib/mbrtowc.c	2009-06-07 02:34:02 +0000
@@ -28,10 +28,14 @@
 
 # include "localcharset.h"
 # include "streq.h"
 # include "verify.h"
 
+# ifndef EILSEQ
+#  define EILSEQ  41  /*  To match the value used in djdev204  */
+# endif
+
 
 verify (sizeof (mbstate_t) >= 4);
 
 static char internal_state[4];
 
diff -aprNU5 sed-4.2.orig/lib/regex_internal.h sed-4.2/lib/regex_internal.h
--- sed-4.2.orig/lib/regex_internal.h	2009-03-31 06:52:24 +0000
+++ sed-4.2/lib/regex_internal.h	2009-06-07 02:34:02 +0000
@@ -456,11 +456,13 @@ static unsigned int re_string_context_at
 #define re_string_length(pstr) ((pstr)->len)
 #define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx])
 #define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx))
 #define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx))
 
-#include <alloca.h>
+#if HAVE_ALLOCA_H
+# include <alloca.h>
+#endif
 
 #ifndef _LIBC
 # if HAVE_ALLOCA
 /* The OS usually guarantees only one guard page at the bottom of the stack,
    and a page size can be as small as 4096 bytes.  So we cannot safely
diff -aprNU5 sed-4.2.orig/lib/set-mode-acl.c sed-4.2/lib/set-mode-acl.c
--- sed-4.2.orig/lib/set-mode-acl.c	2008-12-22 09:53:14 +0000
+++ sed-4.2/lib/set-mode-acl.c	2009-06-07 02:34:02 +0000
@@ -24,10 +24,13 @@
 #include "acl-internal.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 
+#ifdef __DJGPP__
+# include <fcntl.h>
+#endif
 
 /* If DESC is a valid file descriptor use fchmod to change the
    file's mode to MODE on systems that have fchown. On systems
    that don't have fchown and if DESC is invalid, use chown on
    NAME instead.
@@ -483,8 +486,17 @@ qset_acl (char const *name, int desc, mo
 int
 set_acl (char const *name, int desc, mode_t mode)
 {
   int r = qset_acl (name, desc, mode);
   if (r != 0)
-    error (0, errno, _("setting permissions for %s"), quote (name));
+    {
+#ifdef __DJGPP__
+      /* If only SFN support available, DJGPP's fchmod will fail
+         with ENOSYS.  For DOS/WINDOWS this will not heard, so do
+         not confuse the user by issuing the error message. */
+      if (!_USE_LFN)
+        return 0;
+#endif
+      error (0, errno, _("setting permissions for %s"), quote (name));
+    }
   return r;
 }
diff -aprNU5 sed-4.2.orig/lib/wcrtomb.c sed-4.2/lib/wcrtomb.c
--- sed-4.2.orig/lib/wcrtomb.c	2008-12-22 09:54:20 +0000
+++ sed-4.2/lib/wcrtomb.c	2009-06-07 02:34:02 +0000
@@ -21,10 +21,14 @@
 #include <wchar.h>
 
 #include <errno.h>
 #include <stdlib.h>
 
+#ifndef EILSEQ
+# define EILSEQ  41  /*  To match the value given in djdev204  */
+#endif
+
 
 size_t
 wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
 {
   /* This implementation of wcrtomb on top of wctomb() supports only
diff -aprNU5 sed-4.2.orig/sed/execute.c sed-4.2/sed/execute.c
--- sed-4.2.orig/sed/execute.c	2009-04-30 08:43:02 +0000
+++ sed-4.2/sed/execute.c	2009-06-07 13:47:52 +0000
@@ -634,12 +634,56 @@ dump_append_queue()
 	     condition."  IEEE Std 1003.2-1992
 	     So, don't fail. */
 	  fp = ck_fopen(p->fname, read_mode, false);
 	  if (fp)
 	    {
+	      set_read_mode(fp);
 	      while ((cnt = ck_fread(buf, 1, sizeof buf, fp)) > 0)
-		ck_fwrite(buf, 1, cnt, output_file.fp);
+		{
+#ifdef O_BINARY
+		  /* Remove CRs from CR-LF pairs, and the trailing ^Z.  */
+		  register char *src = buf, *dest = buf;
+		  register size_t len = cnt;
+
+		  while (len--)
+		    {
+		      if (*src == '\r' || *src == 0x1a)
+			{
+			  if (!len)
+			    {
+			      if (getc(fp) != EOF)
+				{
+				  if (*src == '\r')
+				    {
+				      fseek(fp, -2L, SEEK_CUR);
+				      cnt--;
+				    }
+				  else
+				    {
+				      fseek(fp, -1L, SEEK_CUR);
+				      *dest++ = *src++;
+				    }
+				  break;
+				}
+			      else if (*src == 0x1a)
+				{
+				  cnt--;
+				  break;
+				}
+			    }
+			  else if (src[1] == '\n')
+			    {
+			      src++;
+			      len--;
+			      cnt--;
+			    }
+			}
+		      *dest++ = *src++;
+		    }
+#endif
+		  ck_fwrite(buf, 1, cnt, output_file.fp);
+		}
 	      ck_fclose(fp);
 	    }
 	}
     }
 
@@ -676,10 +720,84 @@ get_backup_file_name(name)
       p += name_length;
     }
 
   /* Tack on what's after the last asterisk */
   strcpy (p, old_asterisk);
+
+#if defined(MSDOS) && defined(__DJGPP__)
+  /* For file systems with limited file name length, like DOS,
+     the backup file name must be truncated to fullfill
+     with these limitations.  Only designed to work with a
+     DOS file system (8+3) */
+  if (!LFN_FILE_SYSTEM(backup) && !LFN_FILE_SYSTEM(name))
+    {
+      char *dot, *sfn_backup, *new_name, *extension, *prefix, *suffix;
+      int length, suffix_length;
+
+      /* Get the extension of the input file name */
+      new_name = xmalloc(name_length + 1);
+      strcpy(new_name, name);
+      if (extension = strrchr(new_name, '.'))
+        {
+          *extension = '\0';
+          extension++;
+        }
+
+      /* Get the prefix and the suffix for the backup file */
+      length = strlen(in_place_extension);
+      prefix = xmalloc(length + 1);
+      strcpy(prefix, in_place_extension);
+      asterisk = strchr(prefix, '*');
+      if (asterisk)
+        {
+          *asterisk = '\0';
+          asterisk++;
+          suffix = strrchr(asterisk, '*');
+          if (!suffix)
+            suffix = asterisk;
+        }
+      else
+        {
+          suffix = prefix;
+          prefix = NULL;
+        }
+      suffix_length = strlen(suffix);
+
+      /* Compute a SFN for the backup file name */
+      sfn_backup = xmalloc(8 + 1 + 3 + 1);
+      if (length = 0, prefix)
+        for (; (sfn_backup[length] = prefix[length]) && (length < 8); length++)
+          ;  /* Copy the prefix into the sfn backup file name */
+      for (backup_length = length, length = 0; (backup_length < 8) && (sfn_backup[backup_length] = new_name[length]); backup_length++, length++)
+        ;  /* Append the input file name to the sfn backup file name */
+      sfn_backup[backup_length++] = '.';
+      if (extension && (suffix_length < 3))
+        {
+          for (length = 0; (sfn_backup[backup_length] = extension[length]) && (length < 3); backup_length++, length++)
+            ;  /* Append the extension of the input file name to the sfn backup file name */
+          if ((suffix_length + length) > 3)
+            {
+              switch (length)
+                {
+                case 2:
+                  backup_length--;
+                  break;
+                case 3:
+                  backup_length -= suffix_length;
+                  break;
+                }
+            }
+        }
+      for (length = 0; (sfn_backup[backup_length] = suffix[length]) && (length < 3); backup_length++, length++)
+        ;  /* Append the suffix to the sfn backup file name */
+      sfn_backup[backup_length] = '\0';
+      xfree(backup);
+      xfree(new_name);
+      xfree(prefix);
+      backup = sfn_backup;
+    }
+#endif  /* MSDOS && __DJGPP__  */
   return backup;
 }
 
 /* Initialize a struct input for the named file. */
 static void open_next_file P_((const char *name, struct input *));
@@ -702,10 +820,12 @@ open_next_file(name, input)
       input->read_fn = read_always_fail; /* a redundancy */
       ++input->bad_count;
       return;
     }
 
+  set_read_mode (input->fp); /* for systems with text/binary schizophrenia */
+
   input->read_fn = read_file_line;
 
   if (in_place_extension)
     {
       int input_fd, output_fd;
@@ -717,11 +837,11 @@ open_next_file(name, input)
       else
         input->in_file_name = name;
 
       /* get the base name */
       tmpdir = ck_strdup(input->in_file_name);
-      if ((p = strrchr(tmpdir, '/')))
+      if ((p = LAST_SLASH(tmpdir)))
 	*(p + 1) = 0;
       else
 	strcpy(tmpdir, ".");
 
       if (isatty (fileno (input->fp)))
@@ -761,10 +881,18 @@ closedown(input)
 {
   input->read_fn = read_always_fail;
   if (!input->fp)
     return;
 
+  /*
+   *  For DOS/WINDOWS and all other OS with non-POSIX like file systems,
+   *  the file that shall be replaced/renamed by rename() must be closed
+   *  before the rename() call can be issued or the call will fail.
+   */
+  if (input->fp != stdin) /* stdin can be reused on tty and tape devices */
+    ck_fclose(input->fp);
+
   if (in_place_extension && output_file.fp != NULL)
     {
       const char *target_name;
       ck_fclose (output_file.fp);
 
@@ -778,11 +906,10 @@ closedown(input)
 
       ck_rename (input->out_file_name, target_name, input->out_file_name);
       free (input->out_file_name);
     }
 
-  ck_fclose (input->fp);
   input->fp = NULL;
 }
 
 /* Reset range commands so that they are marked as non-matching */
 static void reset_addresses P_((struct vector *));
diff -aprNU5 sed-4.2.orig/sed/sed.c sed-4.2/sed/sed.c
--- sed-4.2.orig/sed/sed.c	2009-04-27 10:09:42 +0000
+++ sed-4.2/sed/sed.c	2009-06-07 02:34:02 +0000
@@ -206,10 +206,19 @@ main(argc, argv)
 
   int opt;
   int return_code;
   const char *cols = getenv("COLS");
 
+#if SYSTEM_CALL_NEED_MULTIPLE_CMDS_ENABLING
+  /*
+   *  For some non posix systems where multiple cmds
+   *  separated by semicolon must be explicitly
+   *  enabled before calling system().
+   */
+  system_flags |= system_allow_multiple_cmds;
+#endif
+
   program_name = argv[0];
   initialize_main (&argc, &argv);
 #if HAVE_SETLOCALE
   /* Set locale according to user's wishes.  */
   setlocale (LC_ALL, "");
diff -aprNU5 sed-4.2.orig/sed/sed.h sed-4.2/sed/sed.h
--- sed-4.2.orig/sed/sed.h	2009-04-27 10:14:50 +0000
+++ sed-4.2/sed/sed.h	2009-06-07 02:34:02 +0000
@@ -277,5 +277,23 @@ extern bool is_utf8;
 #endif
 
 extern int brlen P_ ((int ch, mbstate_t *ps));
 extern void initialize_mbcs P_ ((void));
 
+#ifdef O_BINARY
+# if __DJGPP__
+   /*
+    *  For some non posix systems where multiple cmds
+    *  separated by semicolon must be explicitly
+    *  enabled before calling system().
+    */
+#  define SYSTEM_CALL_NEED_MULTIPLE_CMDS_ENABLING  1
+#  define system_flags   __system_flags
+#  define system_allow_multiple_cmds  __system_allow_multiple_cmds
+extern int __system_flags;
+# else /*  !__DJGPP_  */
+#  define SYSTEM_CALL_NEED_MULTIPLE_CMDS_ENABLING  0
+# endif
+#else /*  !O_BINARY  */
+  /*  posix  */
+# define SYSTEM_CALL_NEED_MULTIPLE_CMDS_ENABLING   0
+#endif
diff -aprNU5 sed-4.2.orig/sed/utils.c sed-4.2/sed/utils.c
--- sed-4.2.orig/sed/utils.c	2009-04-30 08:43:46 +0000
+++ sed-4.2/sed/utils.c	2009-06-07 02:34:02 +0000
@@ -145,10 +145,25 @@ register_open_file (fp, name, temp)
   p->name = ck_strdup(name);
   p->fp = fp;
   p->temp = false;
 }
 
+void
+set_read_mode (fp)
+  FILE *fp;
+{
+#ifdef O_BINARY
+  /* For systems that distinguish between text and binary files,
+     switch all input streams to binary mode.  This is so we get all
+     the characters from the file, instead of relying on the
+     misfeatures of the C library conversions (e.g., most of them drop
+     lone ^M characters, stop at the first ^Z character, etc.)  */
+  if (!isatty(fileno(fp)))
+    setmode(fileno(fp), O_BINARY);
+#endif
+}
+
 /* Panic on failing fopen */
 FILE *
 ck_fopen(name, mode, fail)
   const char *name;
   const char *mode;
@@ -199,21 +214,31 @@ ck_mkstemp (p_filename, tmpdir, base)
 {
   char *template;
   FILE *fp;
   int fd;
 
-  if (tmpdir == NULL)
+  if (IS_TMPDIR(tmpdir))
     tmpdir = getenv("TMPDIR");
-  if (tmpdir == NULL)
+  if (IS_TMPDIR(tmpdir))
     {
       tmpdir = getenv("TMP");
-      if (tmpdir == NULL)
+      if (IS_TMPDIR(tmpdir))
+	{
+#ifdef MSDOS
+	  tmpdir = getenv("TEMP");
+	  if (IS_TMPDIR(tmpdir))
+#endif
 #ifdef P_tmpdir
-	tmpdir = P_tmpdir;
+	    tmpdir = P_tmpdir;
 #else
-	tmpdir = "/tmp";
+# ifdef MSDOS
+	    tmpdir = ".";
+# else
+	    tmpdir = "/tmp";
+# endif
 #endif
+	}
     }
 
   template = xmalloc (strlen (tmpdir) + strlen (base) + 8);
   sprintf (template, "%s/%sXXXXXX", tmpdir, base);
 
@@ -225,23 +250,73 @@ ck_mkstemp (p_filename, tmpdir, base)
   fp = fdopen (fd, "w");
   register_open_file (fp, template, true);
   return fp;
 }
 
+#ifdef O_BINARY
+static int stdout_is_a_device;
+
+static int __inline__ is_a_device P_((FILE *fp));
+static int __inline__
+is_a_device(fp)
+  FILE *fp;
+{
+  struct stat st;
+
+  if (fp == stdout)
+    {
+      /* Warning!  This assumes stdout is never switched during the
+	 program's run!  */
+      if (stdout_is_a_device == -1
+	  && fstat(fileno(stdout), &st) == 0)
+	stdout_is_a_device = S_ISCHR(st.st_mode) != 0;
+      return stdout_is_a_device == 1;
+    }
+  else
+    return fstat(fileno(fp), &st) == 0 && S_ISCHR(st.st_mode);
+}
+#endif
+
 /* Panic on failing fwrite */
 void
 ck_fwrite(ptr, size, nmemb, stream)
   const VOID *ptr;
   size_t size;
   size_t nmemb;
   FILE *stream;
 {
   clearerr(stream);
-  if (size && fwrite(ptr, size, nmemb, stream) != nmemb)
-    panic(ngettext("couldn't write %d item to %s: %s",
-		   "couldn't write %d items to %s: %s", nmemb), 
-		nmemb, utils_fp_name(stream), strerror(errno));
+#ifdef O_BINARY
+  if (!size)
+    return;
+  if (is_a_device(stream))
+    {
+      char *p;
+      size_t left = nmemb * size;
+
+      /* Text-mode writes to character devices stop at the first ^Z
+	 character.  Repair this lossage.  */
+      while ((p = memchr(ptr, 0x1a, left)) != NULL)
+	{
+	  size_t this_write = p - (char *)ptr;
+
+	  if (fwrite(ptr, 1, this_write, stream) != this_write)
+	    break;
+	  fwrite("^Z", 1, 2, stream);
+	  left -= this_write + 1;
+	  ptr = (char *)ptr + this_write + 1;
+	}
+      if (p == NULL && fwrite(ptr, 1, left, stream) == left)
+	return;
+    }
+  else
+#endif
+  if (!size || fwrite(ptr, size, nmemb, stream) == nmemb)
+    return;
+  panic(ngettext("couldn't write %d item to %s: %s",
+		 "couldn't write %d items to %s: %s", nmemb), 
+	nmemb, utils_fp_name(stream), strerror(errno));
 }
 
 /* Panic on failing fread */
 size_t
 ck_fread(ptr, size, nmemb, stream)
@@ -372,11 +447,11 @@ follow_symlink(const char *fname)
       if (rc < 0)
 	panic (_("couldn't follow symlink %s: %s"), buf, strerror(errno));
       else
 	buf2 [rc] = '\0';
 
-      if (buf2[0] != '/' && (c = strrchr (buf, '/')) != NULL)
+      if (!IS_SLASH (buf2[0]) && LAST_SLASH (buf))
 	{
 	  /* Need to handle relative paths with care.  Reallocate buf1 and
 	     buf2 to be big enough.  */
 	  int len = c - buf + 1;
 	  if (len + rc + 1 > buf_size)
diff -aprNU5 sed-4.2.orig/sed/utils.h sed-4.2/sed/utils.h
--- sed-4.2.orig/sed/utils.h	2009-04-30 08:43:58 +0000
+++ sed-4.2/sed/utils.h	2009-06-07 02:34:02 +0000
@@ -18,12 +18,55 @@
 
 #include <stdio.h>
 
 #include "basicdefs.h"
 
+#include <fcntl.h>
+#ifndef O_BINARY
+# ifdef _O_BINARY
+#  define O_BINARY _O_BINARY
+#  define setmode  _setmode
+# endif
+#endif
+
+#ifdef O_BINARY
+# include <io.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# ifndef S_ISCHR
+#  define S_ISCHR(m)  (((m) & S_IFMT) == S_IFCHR)
+# endif
+# ifdef __DJGPP__
+#  include <crt0.h>
+extern int _crt0_startup_flags;
+#  define IS_TMPDIR(dirname)   ((dirname) == NULL || access((dirname), D_OK))
+# else
+#  define IS_TMPDIR(dirname)   ((dirname) == NULL)
+# endif
+# define IS_SLASH(C)           ((C) == '/' || (C) == '\\')
+# define LAST_SLASH(filename)           \
+  ({                                    \
+     char *_pb, *_ps;                   \
+     _pb = strrchr((filename), '\\');   \
+     _ps = strrchr((filename), '/');    \
+     if (!_pb && !_ps)                  \
+       _ps = strrchr((filename), ':');  \
+     else if (_pb > _ps) _ps = _pb;     \
+     _ps;                               \
+  })
+#else
+# define IS_SLASH(C)           ((C) == '/')
+# define IS_TMPDIR(dirname)    ((dirname) == NULL)
+# define LAST_SLASH(filename)  (strrchr((filename), '/'))
+#endif
+
+#define LFN_FILE_SYSTEM(filename)  (pathconf((filename), _PC_NAME_MAX) > 12)
+
+
 void panic P_((const char *str, ...));
 
+void set_read_mode P_((FILE *stream));
 FILE *ck_fopen P_((const char *name, const char *mode, int fail));
 FILE *ck_fdopen P_((int fd, const char *name, const char *mode, int fail));
 void ck_fwrite P_((const VOID *ptr, size_t size, size_t nmemb, FILE *stream));
 size_t ck_fread P_((VOID *ptr, size_t size, size_t nmemb, FILE *stream));
 void ck_fflush P_((FILE *stream));
