Reverse a File Back to the Win32 Shootout
Back to dada's perl lab

[The Original Shootout]   [NEWS]   [FAQ]   [Methodology]   [Platform Details]   [Acknowledgements]   [Scorecard]  
All Source For Reverse a File
reversefile.awka
# $Id: reversefile.gawk,v 1.2 2000/11/22 20:54:57 doug Exp $
# http://www.bagley.org/~doug/shootout/

BEGIN { delete ARGV }
{ x[NR] = $0 }
END { for (i = NR; i >= 1; i--)
    print x[i]
}
reversefile.bcc
/* -*- mode: c -*-
 * $Id: reversefile.gcc,v 1.9 2001/06/25 01:45:44 doug Exp $
 * http://www.bagley.org/~doug/shootout/
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXREAD 4096

int main(int argc, char *argv[]) {
    int nread, len = 0, size = (4 * MAXREAD);
    char *cp, *offset, *buf = malloc(size + 1);

    while (1) {
    if ((nread = read(0, (buf + len), MAXREAD)) > 0) {
        len += nread;
        if (MAXREAD > (size - len)) {
        size <<= 1;
        if (0 == (buf = realloc(buf, size + 1))) {
            fprintf(stderr, "realloc failed\n");
            exit(1);
        }
        }
    } else {
        if ( 0 == nread) break;
        if (-1 == nread) {
        perror("read");
        exit(1);
        }
    }    
    }
    offset = buf + len;
    *offset = 0;
    for (cp = offset; cp > buf; --cp) {
    if ('\n' == *cp) {
        *offset = 0;
        if (cp < offset)
        fputs(offset = cp+1, stdout);
    }
    }
    if (cp < offset) {
    *offset = 0;
    fputs(cp, stdout);
    }
    free(buf);
    return(0);
}
reversefile.bigforth
\ -*- mode: forth -*-
\ $Id: reversefile.bigforth,v 1.2 2001/06/24 22:53:06 doug Exp $
\ http://www.bagley.org/~doug/shootout/

\ Idea by albert@spenarnc.xs4all.nl (Albert van der Horst) in
\ news:<GFDtFA.Lwz.1.spenarn@spenarnc.xs4all.nl>

2000000 constant size \ maximum size of input
size allocate throw constant buf
4096 constant linesize
create line linesize 2 + allot

: revfile   >r
    line buf size + begin 
        1-
        line linesize r@ read-line throw
    while  \ !! handle line buf overflows
        >r #lf over c! 
        r@ - 2dup r> move 
    repeat
    drop nip 1+ buf size + over -  rdrop ;

stdin revfile type bye
reversefile.csharp
// $Id: reversefile.csharp,v 1.0 2002/11/29 10:31:00 dada Exp $
// http://dada.perl.it/shootout/
// 
// This is a straightforward *alternative* C# implementation.
// It'll be interesting to compare it to a fast C# implementation.
//
// contributed by Isaac Gouy

using System;
using System.Collections;

namespace LanguageShootout
{
    class reversefile
    {
        [STAThread]
        static void Main(string[] args)
        {
            Stack lines = new Stack();
            String line;
            while ( (line = Console.ReadLine()) != null ) lines.Push(line);

            System.Collections.IEnumerator items = lines.GetEnumerator();
            while ( items.MoveNext() ) Console.WriteLine( items.Current );
        }
    }
}

reversefile.cygperl
#!/usr/local/bin/perl
# $Id: reversefile.perl,v 1.4 2001/05/14 01:03:20 doug Exp $
# http://www.bagley.org/~doug/shootout/

undef($/);
print join("\n", reverse split(/\n/, <STDIN>)),"\n";
reversefile.delphi
program reversefile2;


uses Windows;
const MAX_READ = 4096;

// avoids using SysUtils and its initializations
function FileRead(Handle: THandle; var Buffer; Count: LongWord): Integer;
begin
  if not ReadFile(Handle, Buffer, Count, LongWord(Result), nil) then
    Result := -1;
end;

function FileWrite(Handle: THandle; const Buffer; Count: LongWord): Integer;
begin
  if not WriteFile(Handle, Buffer, Count, LongWord(Result), nil) then
    Result := -1;
end;

var buf: array of char;
    numRead: integer;
    inHandle,outHandle: THandle;
    filePos,i,e: cardinal;
begin
  inHandle:=GetStdHandle(STD_INPUT_HANDLE);
  outHandle:=GetStdHandle(STD_OUTPUT_HANDLE);
  setLength(buf, MAX_READ);
  numRead:=fileRead(inHandle,buf[0],MAX_READ);
  filePos:=0;
  while numRead>0 do begin
    inc(filePos,numRead);
    if integer(filePos)+MAX_READ-1>high(buf) then
      setLength(buf, (high(buf)+1)*2);

    numRead:=fileRead(inHandle,buf[filePos],MAX_READ);
  end;

  e:=filePos-1;
  for i:=filePos-2 downto 0 do
    if buf[i]=#10 then begin
      fileWrite(outHandle,buf[i+1],e-i);
      e:=i;
    end;
  fileWrite(outHandle,buf[0],e+1);
end.
reversefile.erlang
%%% -*- mode: erlang -*-
%%% $Id: reversefile.erlang,v 1.1 2001/05/15 08:05:58 doug Exp $
%%% http://www.bagley.org/~doug/shootout/

-module(reversefile).
-export([main/0, main/1]).
-export([init/0]).

main() -> main(['1']).
main(Args) ->
    init(),
    halt(0).

init() ->
    Port = open_port({fd, 1, 0}, [eof, {line, 128}]),
    printlist(rev(Port, [])).

rev(Port, Lines) ->
    receive
    {Port, {_, {_, Line}}} ->
        rev(Port, [Line|Lines]);
    {Port, eof} ->
        Lines
    end.

printlist([])     -> [];
printlist([H|T])  -> io:format("~s~n", [H]), printlist(T).
reversefile.fpascal
Program reversefile;
uses SysUtils, Classes;

var
    i, N : longint;
    list : TList;
    line : string;
    pline : pointer;    
begin
    list := TList.Create;
    While Not Eof(input) do
    begin
        Readln(input, line);
        Getmem(pline, Length(line)+1);
        Move(line, pline^, Length(line)+1);
        list.Add( pline );
    end;
    N := list.Count;
    For i := N-1 Downto 0 do WriteLn( string(list.items[i]^) );
end.
reversefile.gawk
# $Id: reversefile.gawk,v 1.2 2000/11/22 20:54:57 doug Exp $
# http://www.bagley.org/~doug/shootout/

BEGIN { delete ARGV }
{ x[NR] = $0 }
END { for (i = NR; i >= 1; i--)
    print x[i]
}
reversefile.gcc
/* -*- mode: c -*-
 * $Id: reversefile.gcc,v 1.9 2001/06/25 01:45:44 doug Exp $
 * http://www.bagley.org/~doug/shootout/
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define MAXREAD 4096

int main(int argc, char *argv[]) {
    int nread, len = 0, size = (4 * MAXREAD);
    char *cp, *offset, *buf = malloc(size + 1);

    while (1) {
    if ((nread = read(0, (buf + len), MAXREAD)) > 0) {
        len += nread;
        if (MAXREAD > (size - len)) {
        size <<= 1;
        if (0 == (buf = realloc(buf, size + 1))) {
            fprintf(stderr, "realloc failed\n");
            exit(1);
        }
        }
    } else {
        if ( 0 == nread) break;
        if (-1 == nread) {
        perror("read");
        exit(1);
        }
    }    
    }
    offset = buf + len;
    *offset = 0;
    for (cp = offset; cp > buf; --cp) {
    if ('\n' == *cp) {
        *offset = 0;
        if (cp < offset)
        fputs(offset = cp+1, stdout);
    }
    }
    if (cp < offset) {
    *offset = 0;
    fputs(cp, stdout);
    }
    free(buf);
    return(0);
}
reversefile.gforth
\ -*- mode: forth -*-
\ $Id: reversefile.gforth,v 1.1 2001/05/25 02:08:19 doug Exp $
\ http://www.bagley.org/~doug/shootout/

\ TBD - we still need to start the size at 4096 and grow only
\ when necessary.

variable size    2000000                  size !
variable sbuf    size @ allocate throw    sbuf !

10   constant  nl_ch
4096 constant  MAXREAD

: add_terminal_newline 
    dup c@ nl_ch <>
    if
    dup nl_ch swap c!
    1 +
    endif ;

: reversefile 
     nl_ch sbuf @ c!
    sbuf @ 1 +
    dup dup
    begin
        MAXREAD stdin read-file throw dup
    while
    \ add number of bytes read to current buffer position
    + dup
    \ now stack has start-of-buffer end-of-buffer addresses
    repeat
    drop
    \ stack: start-of-buffer end-of-buffer

    \ if input didn't end in a newline, then add one
    add_terminal_newline

    \ adjust end pointer
    2 -

    \ adjust start pointer
    swap 2 - swap

    \ now scan the buffer backwards, printing out the lines
    tuck
    -do
    \ stack: pointer to end of buffer
    i c@ nl_ch =
    if
        dup i 1 + swap i -
        stdout write-file throw
        drop
        i
    endif
    1 -loop
    ;

reversefile

bye \ th-th-that's all folks!
reversefile.ghc
-- $Id: reversefile.ghc,v 1.5 2001/02/26 17:18:27 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- from Julian Assange

main = interact $ unlines . reverse . lines
reversefile.guile
#!/usr/local/bin/guile \
-e main -s
!#

;;; $Id: reversefile.guile,v 1.4 2001/06/30 15:52:42 doug Exp $
;;; http://www.bagley.org/~doug/shootout/
;;; from Brad Knotwell

(define (main args)
  (let ((lines '()))
    (do ((line (read-line) (read-line)))
    ((eof-object? line) (map write-line lines))
      (set! lines (cons line lines)))))
reversefile.ici
// $Id: reversefile.ici,v 1.0 2003/01/03 12:14:00 dada Exp $
// http://dada.perl.it/shootout
//
// contributed by Tim Long

f = smash(getfile(), #[^\n]*\n#, "\\&");
r = array();
forall (l in f)
    rpush(r, l);
put(implode(r));

/*
 * This is probably more natural, but slower...
 */
/*
f = smash(getfile(), #[^\n]*\n#, "\\&");
while (nels(f))
    put(pop(f));
*/
reversefile.icon
# -*- mode: icon -*-
# $Id: reversefile.icon,v 1.1 2000/12/25 04:33:31 doug Exp $
# http://www.bagley.org/~doug/shootout/

# Author:   Ralph E. Griswold
# (http://www.cs.arizona.edu/icon/library/src/progs/revfile.icn)

procedure main()
   local lines
   lines := []
   every push(lines, !&input)
   every write(!lines)
end
reversefile.java
// $Id: reversefile.java,v 1.2 2001/05/31 22:41:04 doug Exp $
// http://www.bagley.org/~doug/shootout/
// author: Dirus@programmer.net

import java.io.*;
import java.util.*;

public class reversefile {
    public static void main(String[] args) {
        ArrayList al = new ArrayList(4096);

        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            String strLine;
            while((strLine = in.readLine()) != null)
                al.add(strLine);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }

        String strArray[] = new String[al.size()];
        al.toArray(strArray);

        for(int i = strArray.length - 1; i >= 0; i--)
            System.out.println(strArray[i]);
    }
}
reversefile.lcc
/* -*- mode: c -*-
 * $Id: reversefile.gcc,v 1.9 2001/06/25 01:45:44 doug Exp $
 * http://www.bagley.org/~doug/shootout/
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXREAD 4096

int main(int argc, char *argv[]) {
    int nread, len = 0, size = (4 * MAXREAD);
    char *cp, *offset, *buf = malloc(size + 1);

    while (1) {
    if ((nread = read(0, (buf + len), MAXREAD)) > 0) {
        len += nread;
        if (MAXREAD > (size - len)) {
        size <<= 1;
        if (0 == (buf = realloc(buf, size + 1))) {
            fprintf(stderr, "realloc failed\n");
            exit(1);
        }
        }
    } else {
        if ( 0 == nread) break;
        if (-1 == nread) {
        perror("read");
        exit(1);
        }
    }    
    }
    offset = buf + len;
    *offset = 0;
    for (cp = offset; cp > buf; --cp) {
    if ('\n' == *cp) {
        *offset = 0;
        if (cp < offset)
        fputs(offset = cp+1, stdout);
    }
    }
    if (cp < offset) {
    *offset = 0;
    fputs(cp, stdout);
    }
    free(buf);
    return(0);
}
reversefile.lua
#!/usr/local/bin/lua-- $Id: reversefile.lua,v 1.3 2001/05/14 01:52:38 doug Exp $
-- http://www.bagley.org/~doug/shootout/

local lines = {}
local w = write
nl = 0

gsub(read("*a"), "([^\n]+\n)", function (l)
    %lines[nl] = l
    nl = nl + 1
end)

nl = nl - 1
for i=nl,0,-1 do
    w(lines[i])
end
reversefile.lua5
#!/usr/local/bin/lua-- http://www.bagley.org/~doug/shootout/
-- contributed by Roberto Ierusalimschy

local lines = {}
local nl = 0

for l in io.lines() do
    nl = nl + 1
    lines[nl] = l
end

for i=nl,1,-1 do
    io.write(lines[i], "\n")
end

reversefile.mawk
# $Id: reversefile.mawk,v 1.1 2001/04/26 17:02:01 doug Exp $
# http://www.bagley.org/~doug/shootout/

BEGIN { delete ARGV }
{ x[NR] = $0 }
END { for (i = NR; i >= 1; i--)
    print x[i]
}
reversefile.mercury
% ---------------------------------------------------------------------------- %
% reversefile.m
% Ralph Becket <rbeck@microsoft.com>
% Tue Jan  9 11:39:27 GMT 2001
% vim: ts=4 sw=4 et tw=0 wm=0 ff=unix
%
% ---------------------------------------------------------------------------- %

:- module mytest.

:- interface.

:- import_module io.



:- pred main(io__state, io__state).
:- mode main(di, uo) is det.



:- implementation.



:- import_module string, list, require.



main -->
    read_file_reversed([], ReversedLines),
    io__write_list(ReversedLines, "", io__write_string).



:- pred read_file_reversed(list(string), list(string), io__state, io__state).
:- mode read_file_reversed(in, out, di, uo) is det.

read_file_reversed(RLs0, RLs) -->
    io__read_line_as_string(Result),
    (   { Result = ok(Line) },      read_file_reversed([Line | RLs0], RLs)
    ;   { Result = eof },           { RLs = RLs0 }
    ;   { Result = error(ErrNo) },  { error(io__error_message(ErrNo)) }
    ).
reversefile.mingw32
/* -*- mode: c -*-
 * $Id: reversefile.gcc,v 1.9 2001/06/25 01:45:44 doug Exp $
 * http://www.bagley.org/~doug/shootout/
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define MAXREAD 4096

int main(int argc, char *argv[]) {
    int nread, len = 0, size = (4 * MAXREAD);
    char *cp, *offset, *buf = malloc(size + 1);

    while (1) {
    if ((nread = read(0, (buf + len), MAXREAD)) > 0) {
        len += nread;
        if (MAXREAD > (size - len)) {
        size <<= 1;
        if (0 == (buf = realloc(buf, size + 1))) {
            fprintf(stderr, "realloc failed\n");
            exit(1);
        }
        }
    } else {
        if ( 0 == nread) break;
        if (-1 == nread) {
        perror("read");
        exit(1);
        }
    }    
    }
    offset = buf + len;
    *offset = 0;
    for (cp = offset; cp > buf; --cp) {
    if ('\n' == *cp) {
        *offset = 0;
        if (cp < offset)
        fputs(offset = cp+1, stdout);
    }
    }
    if (cp < offset) {
    *offset = 0;
    fputs(cp, stdout);
    }
    free(buf);
    return(0);
}
reversefile.ocaml
(*
 * $Id: reversefile.ocaml,v 1.11 2001/01/27 13:59:47 doug Exp $
 * http://www.bagley.org/~doug/shootout/
 *)







let size = 10000

let rec lect stack buf pos free =
  let nrd = input stdin buf pos free in
  if nrd = 0 then stack,buf,pos 
  else if nrd = free then 
    lect (buf :: stack) (String.create size) 0 size 
  else lect stack buf (pos+nrd) (free-nrd)

let output_buf (buf,len) = output stdout buf 0 len

let rec rev_write tail stack buf len pos =
  if pos = 0 then
    match stack with 
    | [] -> output stdout buf 0 len; List.iter output_buf tail
    | topbuf :: stack -> 
    let toplen = String.length topbuf in 
    rev_write ((buf,len) :: tail) stack topbuf toplen toplen
  else if buf.[pos-1] = '\n' then
    begin
      output stdout buf pos (len-pos);
      List.iter output_buf tail;
      rev_write [] stack buf pos (pos-1)
    end
  else rev_write tail stack buf len (pos-1)
    
let main =
  let stack,buf,length = 
    lect [] (String.create size) 0 size in
  rev_write [] stack buf length length
reversefile.ocamlb
(*
 * $Id: reversefile.ocaml,v 1.11 2001/01/27 13:59:47 doug Exp $
 * http://www.bagley.org/~doug/shootout/
 *)







let size = 10000

let rec lect stack buf pos free =
  let nrd = input stdin buf pos free in
  if nrd = 0 then stack,buf,pos 
  else if nrd = free then 
    lect (buf :: stack) (String.create size) 0 size 
  else lect stack buf (pos+nrd) (free-nrd)

let output_buf (buf,len) = output stdout buf 0 len

let rec rev_write tail stack buf len pos =
  if pos = 0 then
    match stack with 
    | [] -> output stdout buf 0 len; List.iter output_buf tail
    | topbuf :: stack -> 
    let toplen = String.length topbuf in 
    rev_write ((buf,len) :: tail) stack topbuf toplen toplen
  else if buf.[pos-1] = '\n' then
    begin
      output stdout buf pos (len-pos);
      List.iter output_buf tail;
      rev_write [] stack buf pos (pos-1)
    end
  else rev_write tail stack buf len (pos-1)
    
let main =
  let stack,buf,length = 
    lect [] (String.create size) 0 size in
  rev_write [] stack buf length length
reversefile.perl
#!/usr/local/bin/perl
# $Id: reversefile.perl,v 1.4 2001/05/14 01:03:20 doug Exp $
# http://www.bagley.org/~doug/shootout/

undef($/);
print join("\n", reverse split(/\n/, <STDIN>)),"\n";
reversefile.php
#!/usr/local/bin/php -f<?php
/*
 $Id: reversefile.php,v 1.1 2001/05/08 04:18:33 doug Exp $
 http://www.bagley.org/~doug/shootout/
*/
$fd = fopen("php://stdin", "r");
$lines = array();
while (!feof ($fd)) { array_push($lines, fgets($fd, 4096)); }
fclose($fd);
foreach (array_reverse($lines) as $line) print $line;
?>
reversefile.pike
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: reversefile.pike,v 1.4 2001/05/14 01:03:20 doug Exp $
// http://www.bagley.org/~doug/shootout/
// from: Fredrik Noring

void main() { write((reverse(Stdio.stdin.read()/"\n")*"\n")[1..]+"\n"); }
reversefile.pliant
# $Id: reversefile.pliant,v 1.0 2002/02/08 14:57:00 dada Exp $
# http://dada.perl.it/shootout/

module "/pliant/language/stream.pli"
module "/pliant/language/stream/pipe.pli"
module "/pliant/language/unsafe.pli"
module "/pliant/admin/file.pli"
module "/pliant/admin/asciifile.pli"

(gvar AsciiFile f) load "handle:0"
gvar Int l

for l f:size-1 0 step -1
    console f:l eol
reversefile.poplisp
;;; -*- mode: lisp -*-
;;; $Id: reversefile.cmucl,v 1.7 2001/09/09 01:31:40 doug Exp $
;;; http://www.bagley.org/~doug/shootout/
;;; from Bulent Murtezaoglu

(declaim (optimize (speed 3) (debug 0) (safety 0) (space 0) (compilation-speed 0)))

(defconstant BLOCKSIZE 4096)

(declaim (inline position-rev))
;; I wrote the the function below because the default cmucl image
;; doesn't seem to to have the inline expansion of position available
(defun position-rev (string end char)
  (declare (simple-string string) (fixnum end))
  (declare (inline char=))
  (loop for i from (1- end) downto 0
    do (when (char= (aref string i) char)
     (return-from position-rev i))))

  (declare (inline read-sequence write-string position-rev replace))
  (let ((fp 0)
    (bufsize BLOCKSIZE)
    (buf (make-string BLOCKSIZE)))
    (declare (fixnum bufsize) (simple-string buf))
    (loop for i fixnum = (read-sequence buf *standard-input*
    :start fp :end (+ fp BLOCKSIZE))
      until (= i fp) do
      (setq fp i)
      (when (>; (+ i BLOCKSIZE) bufsize)
    (setq bufsize (* 2 bufsize))
    (let ((tmpbuf (make-string bufsize)))
      (replace tmpbuf buf :start1 0 :end1 fp :start2 0 :end2 fp)
      (setq buf tmpbuf))))
    (loop for i = (1- fp) then j as j = (position-rev buf i #\Newline)
      do (write-string buf *standard-output* :start (if j (1+ j) 0) :end (1+ i))
      while j))
reversefile.python
#!/usr/local/bin/python
# $Id: reversefile.python,v 1.4 2001/05/09 00:47:40 doug Exp $
# http://www.bagley.org/~doug/shootout/
# from Brad Knotwell
# with help from Mark Baker

def main():
    from sys import stdin, stdout
    w = stdin.readlines()
    w.reverse()
    stdout.writelines(w)

main()
reversefile.rexx
A = 1
DO UNTIL LINES() = 0
    PARSE LINEIN L
    PUSH L
    A = A + 1
END
PULL
DO B = A-2 TO 1 BY -1
    PARSE PULL L
    SAY L
END
reversefile.ruby
#!/usr/local/bin/ruby
# -*- mode: ruby -*-
# $Id: reversefile.ruby,v 1.2 2000/11/27 03:39:26 doug Exp $
# http://www.bagley.org/~doug/shootout/

print STDIN.readlines().reverse()

reversefile.se
-- -*- mode: eiffel -*-
-- $Id: reversefile.se,v 1.3 2001/07/07 00:46:25 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- from Daniel F Moisset

class REVERSEFILE

creation make

feature

    make is
        local
            i: ITERATOR[STRING]
            ll_string: LINKED_LIST[STRING];
        do
            !!ll_string.make;
            from
                io.read_line
            until io.end_of_input loop
                ll_string.add_first(clone(io.last_string));
                io.read_line;
            end;
            i := ll_string.get_new_iterator
            from 
           i.start
        until i.is_off loop
                io.put_string (i.item);
                io.put_character('%N');
                i.next;
            end;
        end;

end -- class REVERSEFILE
reversefile.slang
% $Id: reversefile.slang,v 1.0 2003/01/03 14:02:00 dada Exp $
% http://dada.perl.it/shootout/
%
% contributed by John E. Davis

()=array_map (Int_Type, &fputs, fgetslines (stdin)[[-1:0:-1]], stdout);
reversefile.smlnj
(* -*- mode: sml -*-
 * $Id: reversefile.smlnj,v 1.4 2001/07/09 00:25:28 doug Exp $
 * http://www.bagley.org/~doug/shootout/
 * from Tom 7
 *)

structure Test : sig
    val main : (string * string list) -> OS.Process.status
end = struct

val bufsize = 4096
val rdbufsize = 4096

val stdout = Posix.FileSys.wordToFD 0w1
val stdin = Posix.FileSys.wordToFD 0w0

datatype block = END
               | MORE of int ref * Word8Array.array * block

val buff = Unsafe.Word8Array.create rdbufsize

fun out END = ()
  | out (MORE (ir as ref i, a, next)) =
  let in
    Posix.IO.writeArr (stdout, {buf=a, i=i, sz=NONE});
    out next
  end

fun rd (start, len, count, b) =
  if (start + len) >= count then 
    (* done with this block. 
       Copy from start to the end of the array into
       buff, then return the starting index into buff. *)
    let in
      Word8Array.copy {di=0,
                       dst=buff,
                       src=buff,
                       len=SOME len,
                       si=start};
      (b, len)
    end
  else
    if Unsafe.Word8Array.sub(buff, start + len) = 0w10 then
      
      case b of MORE(ir as ref i, a, _) =>
        if i > len then
            let in
              
              Word8Array.copy {di=i-len - 1,
                               dst=a,
                               len=SOME(len + 1),
                               si=start,
                               src=buff};
              ir := i - (len + 1);
              
              rd(start + len + 1, 0, count, b)
            end
          else 
            let
              
              val na = Unsafe.Word8Array.create bufsize
              val l = (len + 1) - i
            in
              
              Word8Array.copy {di=0,
                               dst=a,
                               len=SOME i,
                               si=(start + len + 1) - i,
                               src=buff};
              
              
              Word8Array.copy {di=bufsize - l,
                               dst=na,
                               len=SOME l,
                               si=start,
                               src=buff};
              ir := 0;
              rd(start + len + 1, 0, count, MORE(ref (bufsize - l), na, b))
            end
    else rd (start, len + 1, count, b)
    
fun loop (b, s) =
  let 
    val count = Posix.IO.readArr (stdin, 
                                  {buf=buff, i=s, sz=SOME (rdbufsize-s)})
    val (bb, bs) = rd (0, s, count + s, b)
  in
    case count of
      0 => out bb
    | _ => loop (bb, bs)
  end

fun main(name, args) =
    ( loop (MORE(ref bufsize, Unsafe.Word8Array.create bufsize, END), 0);
      OS.Process.success);

end

val _ = SMLofNJ.exportFn("reversefile", Test.main);
reversefile.tcl
#!/usr/local/bin/tclsh
# $Id: reversefile.tcl,v 1.5 2001/01/16 00:47:41 doug Exp $
# http://www.bagley.org/~doug/shootout/
# from: Miguel Sofer

proc main {} {
    set lines [split [read stdin] "\n"]
    
    fconfigure stdout -buffering full

    for {set i [expr {[llength $lines]-2}]} {$i >= 0} {incr i -1} {
        puts [lindex $lines $i]
    }
}

main
reversefile.vbscript
FileBlob = WScript.StdIn.ReadAll
Lines = Split(FileBlob, Chr(10))
For A = UBound(Lines) To LBound(Lines) Step -1
    If Len(Lines(A)) > 0 Then WScript.Echo Lines(A)
Next
reversefile.vc
/* -*- mode: c -*-
 * $Id: reversefile.gcc,v 1.9 2001/06/25 01:45:44 doug Exp $
 * http://www.bagley.org/~doug/shootout/
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXREAD 4096

int main(int argc, char *argv[]) {
    int nread, len = 0, size = (4 * MAXREAD);
    char *cp, *offset, *buf = malloc(size + 1);

    while (1) {
    if ((nread = read(0, (buf + len), MAXREAD)) > 0) {
        len += nread;
        if (MAXREAD > (size - len)) {
        size <<= 1;
        if (0 == (buf = realloc(buf, size + 1))) {
            fprintf(stderr, "realloc failed\n");
            exit(1);
        }
        }
    } else {
        if ( 0 == nread) break;
        if (-1 == nread) {
        perror("read");
        exit(1);
        }
    }    
    }
    offset = buf + len;
    *offset = 0;
    for (cp = offset; cp > buf; --cp) {
    if ('\n' == *cp) {
        *offset = 0;
        if (cp < offset)
        fputs(offset = cp+1, stdout);
    }
    }
    if (cp < offset) {
    *offset = 0;
    fputs(cp, stdout);
    }
    free(buf);
    return(0);
}
reversefile.vc++
// -*- mode: c++ -*-
// $Id: reversefile.g++,v 1.3 2001/07/06 13:19:30 doug Exp $
// http://www.bagley.org/~doug/shootout/

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

int main() {
    typedef vector<string> LINES;
    LINES l;
    char line[256];
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    while (cin.getline(line, 256)) {
        l.push_back(line);
    }
    for (LINES::reverse_iterator j = l.rbegin(); j != l.rend(); j++) {
    cout << (*j) << endl;
    }    
}
reversefile.vpascal
Program reversefile;
uses SysUtils, Classes;

var
    i, N : longint;
    list : TList;
    line : string;
    pline : pointer;    
begin
    list := TList.Create;
    While Not Eof(input) do
    begin
        Readln(input, line);
        Getmem(pline, Length(line)+1);
        Move(line, pline^, Length(line)+1);
        list.Add( pline );
    end;
    N := list.Count;
    For i := N-1 Downto 0 do WriteLn( string(list.items[i]^) );
end.