--- a/toys/posix/grep.c	2013-12-09 00:56:05.000000000 +0530
+++ b/toys/posix/grep.c	2013-12-10 09:14:14.144860445 +0530
@@ -1,10 +1,13 @@
 /* grep.c - print lines what match given regular expression
  *
  * Copyright 2013 CE Strake <strake888 at gmail.com>
+ * Modified by:
+ * Copyright 2013 Bilal Qureshi <bilal.jmi@gmail.com>
+ * Copyright 2013 Kyungwan Han <asura321@gmail.com>
  *
  * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/grep.html
 
-USE_GREP(NEWTOY(grep, "EFHabhinorsvwclqe*f*m#x[!wx][!EFw]", TOYFLAG_BIN))
+USE_GREP(NEWTOY(grep, "EFHabhinorsvwclqe*f*m#B#<0x[!wx][!EFw]", TOYFLAG_BIN))
 USE_GREP(OLDTOY(egrep, grep, OPTSTR_grep, TOYFLAG_BIN))
 USE_GREP(OLDTOY(fgrep, grep, OPTSTR_grep, TOYFLAG_BIN))
 
@@ -12,7 +15,7 @@
   bool "grep"
   default y
   help
-    usage: grep [-EFivwcloqsHbhn] [-m MAX] [-e REGEX]... [-f REGFILE] [FILE]...
+    usage: grep [-EFivwcloqsHbhn] [-m MAX] [-B N] [-e REGEX]... [-f REGFILE] [FILE]...
 
     Show lines matching regular expressions. If no -e, first argument is
     regular expression to match. With no files (or "-" filename) read stdin.
@@ -26,6 +29,7 @@
     -i  case insensitive         -m  stop after this many lines matched
     -r  recursive (on dir)       -v  invert match
     -w  whole word (implies -E)  -x  whole line
+    -B N  Print N lines of leading context
 
     display modes: (default: matched line)
     -c  count of matching lines  -l  show matching filenames
@@ -42,19 +46,82 @@
 #include <regex.h>
 
 GLOBALS(
+  long bval;
   long m;
   struct arg_list *f;
   struct arg_list *e;
 
   struct arg_list *regex;
+  long bcount;
+  int separator;
+  struct double_list *dlist;
 )
 
+struct finfo {
+  char *line;
+  char *fname;
+  int line_no;
+};
+
+static void free_node(struct double_list *node)
+{
+  struct finfo *data = (struct finfo *)node->data;
+
+  free(data->line);
+  free(data->fname);
+  free(node);
+}
+
+static struct double_list *pop_node()
+{
+  if (!TT.dlist) return NULL;
+  --TT.bcount;
+  return dlist_pop(&TT.dlist);
+}
+
+static void push_node(struct finfo *f)
+{
+  struct finfo *data = xzalloc(sizeof(struct finfo));
+
+  data->line = xmsprintf("%s", f->line);
+  data->fname = xmsprintf("%s", f->fname);
+  data->line_no = f->line_no;
+  dlist_add(&TT.dlist, (char*)data);
+
+  if (++TT.bcount > TT.bval) {
+    struct double_list *dlist;
+
+    if ((dlist = pop_node()) ) free_node(dlist);
+  }
+}
+
+static void print_dlist()
+{
+  struct double_list *dlist;
+
+  while ((dlist = pop_node())) {
+    struct finfo *data = (struct finfo *)dlist->data;
+
+    if (toys.optflags & FLAG_H) printf("%s-", data->fname);
+    if (toys.optflags & FLAG_n) printf("%d-", data->line_no);
+    xprintf("%s\n", data->line);
+    free_node(dlist);
+  }
+}
+
+static void clear_dlist()
+{
+  struct double_list *dlist;
+
+  while ((dlist = pop_node())) free_node(dlist);
+}
+
 static void do_grep(int fd, char *name)
 {
   FILE *file = fdopen(fd, "r");
   long offset = 0;
-  int lcount = 0, mcount = 0, which = toys.optflags & FLAG_w ? 2 : 0;
-
+  struct finfo f;
+  int lcount = 0, mcount = 0, llc = 0, which = toys.optflags & FLAG_w ? 2 : 0;
   if (!fd) name = "(standard input)";
 
   if (!file) {
@@ -109,7 +176,7 @@
         } else rc = 1;
       } else {
         rc = regexec((regex_t *)toybuf, start, 3, matches,
-                     start==line ? 0 : REG_NOTBOL);
+            start==line ? 0 : REG_NOTBOL);
         skip = matches[which].rm_eo;
       }
 
@@ -144,25 +211,40 @@
           break;
 
       if (!(toys.optflags & FLAG_c)) {
+        if ((toys.optflags & FLAG_B) && TT.separator && 
+            TT.bval < (lcount - llc-1)) printf("--\n");
+        if (!(toys.optflags & FLAG_o) && (toys.optflags & FLAG_B)) 
+          print_dlist();
         if (toys.optflags & FLAG_H) printf("%s:", name);
         if (toys.optflags & FLAG_n) printf("%d:", lcount);
         if (toys.optflags & FLAG_b)
           printf("%ld:", offset + (start-line) +
               ((toys.optflags & FLAG_o) ? matches[which].rm_so : 0));
-        if (!(toys.optflags & FLAG_o)) xputs(line);
+        if (!(toys.optflags & FLAG_o)) {
+          if (toys.optflags & FLAG_B) {
+            xputs(line);
+            TT.separator = 1;
+          } else xputs(line);
+        }
         else {
           xprintf("%.*s\n", matches[which].rm_eo - matches[which].rm_so,
-                  start + matches[which].rm_so);
+              start + matches[which].rm_so);
+          TT.separator = 1;
         }
+        llc = lcount;
       }
 
       start += skip;
       if (!(toys.optflags & FLAG_o) || !*start) break;
     }
+    if ((toys.optflags & FLAG_B) && !mmatch) {
+      f.fname = name;
+      f.line = line;
+      f.line_no = lcount; 
+      push_node(&f);
+    }
     offset += len;
-
     free(line);
-
     if (mmatch) mcount++;
     if ((toys.optflags & FLAG_m) && mcount >= TT.m) break;
   }
@@ -174,6 +256,7 @@
 
   // loopfiles will also close the fd, but this frees an (opaque) struct.
   fclose(file);
+  if (toys.optflags & FLAG_B) clear_dlist();
 }
 
 static void parse_regex(void)
