2011-05-14  Juan Manuel Guerrero <juan.guerrero@gmx.de>

	* lib/isdir.c [__DJGPP__]: Include <unistd.h> for access declaration.
	(isdir) [__DJGPP__]: Use access to determinate if given path is an
	existing directory.

	* src/dosbuf.c:  No longer include config.h.
	[__DJGPP__]: Include pc.h for ScreenGetCursor prototype.
	(restore_blink_bit, screen_puts, msdos_screen_write, djgpp_grep_startup)
	[__DJGPP__]: New functions to support colorization without requiring
	ANSI.SYS driver (or its work-alike) to be loaded.  
	(msdos_screen_write): Added support to decode and execute erase part
	of the line to the right escape sequence (ESC-[K), that is used to
	initialize and finish SGR escape sequences.

	* src/main.c [__DJGPP__]: New macro IS_TERMINAL defined.  If compiled
	with DJGPP do not check for the term environment variable to decided
	which value should color_option have.
	(main): Use CANONICALIZE_PATH, STRIP_FULL_PATH_AND_EXTENSION and
	IS_TERMINAL.

	* src/system.h [DJGPP, __DJGPP_MINOR__]: For DJGPP 2.03 define macros
	to handle dir eacces bug.
	[HAVE_DOS_FILE_NAMES]: New macro STRIP_FULL_PATH_AND_EXTENSION to strip
	path and extension from argv[0].  Is no-op for all other systems.
	New macro CANONICALIZE_PATH.  Is no-op for all other systems.
	[is_EISDIR]: Check if is_EISDIR is defined before unconditionaly
	defining is_EISDIR.









diff -aprNU5 grep-2.8.orig/lib/isdir.c grep-2.8/lib/isdir.c
--- grep-2.8.orig/lib/isdir.c	2011-01-03 20:55:38 +0000
+++ grep-2.8/lib/isdir.c	2011-05-14 19:27:24 +0000
@@ -17,17 +17,30 @@
 
 #include <config.h>
 
 #include "isdir.h"
 
+#ifdef __DJGPP__
+# include <unistd.h>
+#endif
 #include <sys/types.h>
 #include <sys/stat.h>
 
 /* If PATH is an existing directory or symbolic link to a directory,
    return nonzero, else 0.  */
 int
 isdir (const char *path)
 {
   struct stat stats;
 
+#ifdef __DJGPP__
+  /*
+   *  Computation of stat is very expensive.
+   *  To determinate if PATH is an existing
+   *  directory, access on DOS platforms is
+   *  mostly a fast system call.
+   */
+  return (access (path, D_OK) == 0);
+#else
   return stat (path, &stats) == 0 && S_ISDIR (stats.st_mode);
+#endif
 }
diff -aprNU5 grep-2.8.orig/src/dosbuf.c grep-2.8/src/dosbuf.c
--- grep-2.8.orig/src/dosbuf.c	2011-01-26 21:02:40 +0000
+++ grep-2.8/src/dosbuf.c	2011-05-14 19:29:02 +0000
@@ -15,23 +15,24 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
    02110-1301, USA.  */
 
 /* Messy DOS-specific code for correctly treating binary, Unix text
-   and DOS text files.
+   and DOS text files, and for emulating a Posix terminal driver
+   wrt SGR (a.k.a. ANSI) color escape sequences.
 
    This has several aspects:
 
      * Guessing the file type (unless the user tells us);
      * Stripping CR characters from DOS text files (otherwise regex
        functions won't work correctly);
      * Reporting correct byte count with -b for any kind of file.
+     * Redirecting output with ANSI color commands to direct screen
+       writes.
 
 */
 
-#include <config.h>
-
 typedef enum {
   UNKNOWN, DOS_BINARY, DOS_TEXT, UNIX_TEXT
 } File_type;
 
 struct dos_map {
@@ -196,5 +197,347 @@ dossified_pos (off_t byteno)
         out_map_idx--;
     }
 
   return byteno + dos_pos_map[out_map_idx].add;
 }
+
+#ifdef __DJGPP__
+/*  Screen write redirection.  We need this to support colorization
+    without requiring ANSI.SYS driver (or its work-alike) to be loaded.
+
+    This function uses the DJGPP filesystem extensions mechanism.  It is
+    installed as a handler for handle-based functions (read/write/close)
+    for the standard output (but actually only handles writes, only if
+    the standard output is connected to the terminal, and only if user
+    asked for colorization).  When a buffer is written to the screen by
+    low-level functions of the DJGPP C library, our handler will be
+    called.  For any request that doesn't require colored screen writes
+    we return a zero to the caller, in which case the caller will handle
+    the output in the usual way (by eventually calling DOS).
+
+    When colorization *is* required, the buffer is written directly to
+    the screen while converting the ANSI escape sequences into calls to
+    DJGPP conio functions which change text attributes.  A non-zero value is
+    then returned to the caller to signal that the output has been handled.
+*/
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <unistd.h>
+#include <conio.h>
+#include <sys/fsext.h>
+#include <go32.h> /* for `_dos_ds' */
+#include <sys/farptr.h>
+#include <pc.h> /* for `ScreenGetCursor' */
+
+static int norm_blink = -1, cur_blink = -1;
+static unsigned char norm_attr = 0, cur_attr = 0;
+static int isatty_stdout = -1;
+static size_t leftover = 0;
+
+/* Restore the BIOS blinking bit to its original value.  Called at exit.  */
+static void
+restore_blink_bit (void)
+{
+  if (cur_blink != norm_blink)
+    {
+      if (norm_blink > 0)
+        blinkvideo ();
+      else
+        intensevideo ();
+    }
+}
+
+/* Write a buffer to the screen video memory.  This expands the TAB
+   characters to the appropriate number of spaces, and also does TRT
+   with null characters and other non-printable characters, if
+   any.  */
+static void
+screen_puts (char *buf, char *buf_end)
+{
+  register char *p = buf, *q = p;
+  int row, col;
+  unsigned char c;
+
+  while (p < buf_end)
+    {
+      if (*p < ' ')
+        {
+          switch (*p)
+            {
+              case '\b':
+              case '\r':
+              case '\n':
+                /* nothing: cputs already does TRT with these */
+                break;
+              case '\t':
+                *p = '\0';
+                cputs (q);
+                ScreenGetCursor (&row, &col);
+                for (cputs (" "), col += 1; col % 8; col++)
+                  cputs (" ");
+                q = p + 1;
+                *p = '\t';
+                break;
+              default:
+                c = *p;
+                *p = '\0';
+                cputs (q);
+                cputs ("^");
+                putch (c | 0x40);
+                q = p + 1;
+                *p = c;
+                break;
+            }
+        }
+      p++;
+    }
+  /* Output whatever is left.  */
+  cputs (q);
+}
+
+#define ESC '\033'
+#define IS_SGR(s) (((s)[1] == '[') && ((s)[2] == 'm'))
+#define IS_EL(s)  (((s)[1] == '[') && ((s)[2] == 'K'))
+
+/* Screen writes redirector function.  */
+static int
+msdos_screen_write (__FSEXT_Fnumber func, int *retval, va_list rest_args)
+{
+  static char *cbuf = NULL;
+  static size_t cbuf_len = 0;
+  /* Only dark colors mentioned here, so that bold has visible effect.  */
+  static enum COLORS screen_color[] = {
+    BLACK,
+    RED,
+    GREEN,
+    BROWN,
+    BLUE,
+    MAGENTA,
+    CYAN,
+    LIGHTGRAY
+  };
+  char *anchor, *p_next;
+  unsigned char fg, bg;
+
+  int handle;
+  char *buf, *buf_end;
+  size_t buflen;
+
+  /* Avoid direct screen writes unless colorization was actually requested.
+     Otherwise, we will break programs that catch I/O from their children.  */
+  handle = va_arg (rest_args, int);
+  if (!color_option || func != __FSEXT_write ||
+       !(handle == STDOUT_FILENO ? isatty_stdout : isatty (handle)))
+    return 0;
+
+  buf = va_arg (rest_args, char *);
+  if (!buf)
+    {
+      errno = EINVAL;
+      *retval = -1;
+      return 1;
+    }
+
+  /* Allocate a sufficiently large buffer to hold the output.  */
+  buflen = va_arg (rest_args, size_t);
+  if (!cbuf)
+    {
+      struct text_info txtinfo;
+
+      cbuf_len = buflen + 1;
+      cbuf = (char *)xmalloc (cbuf_len);
+      gettextinfo (&txtinfo);
+      norm_attr = txtinfo.attribute; /* save the original text attribute */
+      cur_attr = norm_attr;
+      /* Does it normally blink when bg has its 3rd bit set?  */
+      norm_blink = (_farpeekb (_dos_ds, 0x465) & 0x20) ? 1 : 0;
+      cur_blink = norm_blink;
+    }
+  else if (buflen >= cbuf_len)
+    {
+      cbuf_len = buflen + 1 + leftover;
+      cbuf = (char *)xrealloc (cbuf, cbuf_len);
+    }
+  memcpy (cbuf + leftover, buf, buflen);
+  buf_end = cbuf + buflen + leftover;
+  *buf_end = '\0';
+
+  /* Current text attributes are used as baseline.  */
+  fg = cur_attr & 15;
+  bg = (cur_attr >> 4) & 15;
+
+  /* Walk the buffer, writing text directly to video RAM,
+     changing color attributes when an escape sequence is seen.  */
+  for (anchor = p_next = cbuf;
+       (p_next = memchr (p_next, ESC, buflen - (p_next - cbuf))) != 0; )
+    {
+      char *p = p_next;
+
+      /* If some chars seen since the last escape sequence,
+         write it out to the screen using current text attributes.  */
+      if (p > anchor)
+        {
+          *p = '\0'; /* `cputs' needs ASCIIZ string */
+          screen_puts (anchor, p);
+          *p = ESC; /* restore the ESC character */
+          anchor = p;
+        }
+
+      /* Handle the null escape sequence (ESC-[m), which is used to
+         restore the original color. */
+      if (IS_SGR(p))
+        {
+          textattr (norm_attr);
+          p += 3;
+          anchor = p_next = p;
+          continue;
+        }
+
+      /* Handle the erase in line to the right escape sequence (ESC-[K). */
+      if (IS_EL(p))
+        {
+          clreol();
+          p += 3;
+          anchor = p_next = p;
+          continue;
+        }
+
+      if (p[1] == '[') /* "Esc-[" sequence */
+        {
+          p += 2; /* get past "Esc-[" sequence */
+          p_next = p;
+          while (*p != 'm') /* `m' ends the escape sequence */
+            {
+              char *q;
+              long code = strtol (p, &q, 10);
+
+              if (!*q)
+                {
+                  /* Incomplete escape sequence.  Remember the part
+                     we've seen for the next time.  */
+                  leftover = q - anchor;
+                  if (leftover >= cbuf_len)
+                    {
+                      cbuf_len += 1 + leftover;
+                      cbuf = (char *)xrealloc (cbuf, cbuf_len);
+                    }
+                  strcpy (cbuf, anchor);
+                  *retval = buflen; /* that's a lie, but we have to! */
+                  return 1;
+                }
+
+              /* 
+                 Sanity checks:
+
+                 q > p unless p doesn't point to a number;
+                 SGR codes supported by ANSI.SYS are between 0 and 49;
+                 Each SGR code ends with a `;' or an `m'.
+
+                 If any of the above is violated, we just ignore the bogon.
+              */
+              if (q == p || code > 49 || code < 0 || (*q != 'm' && *q != ';'))
+                {
+                  p_next = q;
+                  break;
+                }
+              if (*q == ';') /* more codes to follow */
+                q++;
+
+              /* Convert ANSI codes to color fore- and background.  */
+              switch (code)
+                {
+                  case 0: /* all attributes off */
+                    fg = norm_attr & 15;
+                    bg = (norm_attr >> 4) & 15;
+                    break;
+                  case 1: /* intensity on */
+                    fg |= 8;
+                    break;
+                  case 4: /* underline on */
+                    fg |= 8; /* we can't, so make it bold instead */
+                    break;
+                  case 5: /* blink */
+                    if (cur_blink != 1)
+                      {
+                        blinkvideo (); /* ensure we are'nt in bright bg mode */
+                        cur_blink = 1;
+                      }
+                    bg |= 8;
+                    break;
+                  case 7: /* reverse video */
+                    {
+                      unsigned char t = fg;
+                      fg = bg;
+                      bg = t;
+
+                      /* If it was blinking before, let it blink after.  */
+                      if (fg & 8)
+                        bg |= 8;
+
+                      /* If the fg was bold, let the background be bold.  */
+                      if ((t & 8) && cur_blink != 0)
+                        {
+                          intensevideo ();
+                          cur_blink = 0;
+                        }
+                    }
+                    break;
+                  case 8: /* concealed on */
+                    fg = (bg & 7) | 8; /* make fg be like bg, only bright */
+                    break;
+                  case 30: case 31: case 32: case 33: /* foreground color */
+                  case 34: case 35: case 36: case 37:
+                    fg = (fg & 8) | (screen_color[code - 30] & 15);
+                    break;
+                  case 40: case 41: case 42: case 43: /* background color */
+                  case 44: case 45: case 46: case 47:
+                    bg = (bg & 8) | (screen_color[code - 40] & 15);
+                    break;
+                  case 39: /* default fg */
+                    fg = norm_attr & 15;
+                    break;
+                  case 49:
+                    bg = (norm_attr >> 4) & 15;
+                    break;
+                  default:
+                    p_next = q; /* ignore unknown codes */
+                    break;
+                }
+              p = q;
+            } /* while loop */
+
+          if (*p == 'm' && p > p_next)
+            {
+              /* They don't *really* want it invisible, do they?  */
+              if (fg == (bg & 7))
+                fg |= 8; /* make it concealed instead */
+
+              /* Construct the text attribute and set it.  */
+              cur_attr = (bg << 4) | fg;
+              textattr (cur_attr);
+              p_next = anchor = p + 1;
+            }
+          else
+            break;
+        }
+      else
+        p_next++;
+    }  /* for loop */
+
+  /* Output what's left in the buffer.  */
+  screen_puts (anchor, buf_end);
+  leftover = 0;
+  *retval = buflen;
+  return 1;
+}
+
+/* This is called before `main' to install our STDOUT redirector.  */
+static void __attribute__((constructor))
+djgpp_grep_startup (void)
+{
+  __FSEXT_set_function (STDOUT_FILENO, msdos_screen_write);
+  isatty_stdout = isatty (STDOUT_FILENO);
+  atexit (restore_blink_bit);
+}
+#endif  /* __DJGPP__ */
diff -aprNU5 grep-2.8.orig/src/main.c grep-2.8/src/main.c
--- grep-2.8.orig/src/main.c	2011-01-28 07:28:26 +0000
+++ grep-2.8/src/main.c	2011-05-14 19:45:54 +0000
@@ -53,10 +53,16 @@
 #define SEP_CHAR_REJECTED '-'
 #define SEP_STR_GROUP    "--"
 
 #define STREQ(a, b) (strcmp (a, b) == 0)
 
+#ifdef __DJGPP__
+# define IS_TERMINAL (isatty(STDOUT_FILENO))
+#else
+# define IS_TERMINAL (isatty(STDOUT_FILENO) && (t = getenv ("TERM")) && strcmp(t, "dumb"))
+#endif
+
 #define AUTHORS \
   proper_name ("Mike Haertel"), \
   _("others, see <http://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>")
 
 struct stats
@@ -1761,11 +1767,11 @@ main (int argc, char **argv)
   FILE *fp;
 
   exit_failure = EXIT_TROUBLE;
   initialize_main (&argc, &argv);
   set_program_name (argv[0]);
-  program_name = argv[0];
+  program_name = STRIP_FULL_PATH_AND_EXTENSION(argv[0]);
 
   keys = NULL;
   keycc = 0;
   with_filenames = 0;
   eolbyte = '\n';
@@ -2024,18 +2030,11 @@ main (int argc, char **argv)
           else
             show_help = 1;
         } else
           color_option = 2;
         if (color_option == 2)
-          {
-            char const *t;
-            if (isatty (STDOUT_FILENO) && (t = getenv ("TERM"))
-                && !STREQ (t, "dumb"))
-              color_option = 1;
-            else
-              color_option = 0;
-          }
+          color_option = (IS_TERMINAL) ? 1 : 0;
         break;
 
       case EXCLUDE_OPTION:
         if (!excluded_patterns)
           excluded_patterns = new_exclude ();
@@ -2167,11 +2166,11 @@ main (int argc, char **argv)
   if (optind < argc)
     {
         status = 1;
         do
         {
-          char *file = argv[optind];
+          char *file = CANONICALIZE_PATH(argv[optind]);
           if ((included_patterns || excluded_patterns)
               && !isdir (file))
             {
               if (included_patterns
                   && excluded_file_name (included_patterns, file))
diff -aprNU5 grep-2.8.orig/src/system.h grep-2.8/src/system.h
--- grep-2.8.orig/src/system.h	2011-01-26 21:02:40 +0000
+++ grep-2.8/src/system.h	2011-05-14 19:38:26 +0000
@@ -28,16 +28,63 @@
 #include "dirname.h"
 #include "minmax.h"
 
 #if O_BINARY
 # define HAVE_DOS_FILE_CONTENTS 1
+# if __DJGPP__ == 2
+#  if __DJGPP_MINOR__ < 4
+/* Has dir eacces bug.  */
+#   ifdef EISDIR
+#    define is_EISDIR(e, f) \
+       ((e) == EISDIR \
+        || ((e) == EACCES && isdir(f) && ((e) = EISDIR, 1)))
+#   else
+#    define is_EISDIR(e, f)  ((e) == EACCES && isdir (f))
+#   endif
+#  endif  /* __DJGPP_MINOR__ < 4  */
+
+# include <libc/unconst.h>
+# define CANONICALIZE_PATH(path)                   \
+  ({                                               \
+      if ((path))                                  \
+      {                                            \
+        char *_p = unconst((path), char *);        \
+        for (; *_p; _p++)                          \
+          if (*_p == '\\')                         \
+            *_p = '/';                             \
+      }                                            \
+      (path);                                      \
+  })
+# define IS_DIR_SEPARATOR(c)  ((c) == '/' || (c) == '\\' || (c) == ':')
+# define STRIP_FULL_PATH_AND_EXTENSION(file_name)  \
+  ({                                               \
+      char *_dst, *_src;                           \
+      _dst = _src = unconst((file_name), char *);  \
+      while (*_src++)                              \
+        ;                                          \
+      while ((_src - _dst) && (*--_src != '.'))    \
+        ;                                          \
+      for (*_src = '\0'; (_src - _dst); _src--)    \
+        if (IS_DIR_SEPARATOR(*_src))               \
+          break;                                   \
+      if (_src - _dst)                             \
+        while ((*_dst++ = *++_src))                \
+          ;                                        \
+      (file_name);                                 \
+  })
+# else  /* !__DJGPP__  */
+# define CANONICALIZE_PATH(path)                   (path)
+# define STRIP_FULL_PATH_AND_EXTENSION(file_name)  (file_name)
+# endif  /* !__DJGPP__  */
 #endif
 
-#ifdef EISDIR
-# define is_EISDIR(e, f) ((e) == EISDIR)
-#else
-# define is_EISDIR(e, f) 0
+#ifndef is_EISDIR
+# ifdef EISDIR
+#  define is_EISDIR(e, f)  ((e) == EISDIR)
+# else
+#  define is_EISDIR(e, f)  0
+# endif
 #endif
 
 #include <stdlib.h>
 #include <stddef.h>
 #include <limits.h>
