#!/usr/bin/env python


##  BidiFile
##
class BidiFile:
  
  BUFSIZ = 4096
  
  def __init__(self, fname):
    self.fp = file(fname, 'r')
    self.buf = ''
    self.lineend = 0
    return
  
  def __reversed__(self):
    self.buf = ''
    while 1:
      line = self.readline_rev()
      if not line: break
      yield line
    return
  
  def __iter__(self):
    self.buf = ''
    return iter(self.fp)
  
  def close(self):
    self.fp.close()
    return
  
  def seek(self, pos, whence=0):
    self.buf = ''
    self.fp.seek(pos, whence)
    return
  
  def read(self, n=-1):
    self.buf = ''
    return self.fp.read(n)
  
  def readline(self):
    self.buf = ''
    return self.fp.readline()
  
  def read_rev(self, n=-1):
    self.buf = ''
    pos0 = self.fp.tell()
    pos1 = max(0, pos0-n)
    self.fp.seek(pos1)
    data = self.fp.read(pos0-pos1)
    self.fp.seek(pos1)
    return data
  
  def readline_rev(self):
    if not self.buf or self.lineend == 0:
      self.buf = self.read_rev(self.BUFSIZ)
      if not self.buf:
        return ''
      self.lineend = len(self.buf)
    line0 = self.lineend - 1
    linebuf = []
    while 1:
      try:
        line0 = self.buf.rindex('\n', 0, line0)+1
        line = self.buf[line0:self.lineend]
        self.lineend = line0
        line0 = self.lineend - 1
        break
      except ValueError:
        buf0 = self.buf
        self.buf = self.read_rev(self.BUFSIZ)
        if not self.buf:
          line = buf0[:self.lineend]
          break
        linebuf.insert(0, buf0[:self.lineend])
        self.lineend = len(self.buf)
        line0 = self.lineend
    return line + ''.join(linebuf)

# test
if __name__ == "__main__":
  import sys
  fp = BidiFile(sys.argv[1])
  fp.seek(0, 2)
  for line in reversed(fp):
    print repr(line)
