The Scriptometer tries to measure whether a programming language can be easily used for SOP (Script-Oriented Programming). A script is here a command line program, mostly used in a terminal. (more scripting stuff (GUI, web...) could be added...)

For this:

Suggestions and comments welcome (including spelling, grammatical and stylistic corrections :)

Scriptometer Overall Scores

  sh  RubyPerlChPythonPHPPikeTclJudoScript Awk REXXmerdEOCamlLuaSchemeJavaScriptCommonLispHaskellVBScriptPrologErlangJScheme  C  SmalltalkJavaC#
Score15114814813312512011411110910810210199999694868483838274746863119

conflict of interest warning: the author of this page is also the author of merd, so some things may be unintentionally subconsciously biased.

merd is mostly vapourware and a dead project.

Tools

  sh   Ruby  Perl   Ch  Python PHP  Pike  Tcl JudoScript Awk  REXX  merd   E  OCaml Lua SchemeJavaScriptCommonLispHaskellVBScriptPrologErlangJScheme  C  Smalltalk Java   C#  
Implementationbash
2.05
Ruby
1.6.7
Perl
5.6.0
Ch
4.0
CPython
2.4
PHP
5
Pike
7.5.1
Tcl
8.3
JudoScript
0.9
gawk
3.1.1
Regina
3.3


OCaml 3.07 + Extlib
1.1
Lua
4.0
guile
1.4
NJS
0.2.5
sbcl
0.9.2
ghc
6.6
VBScript
SWI-Prolog
5.6.x
sae-r9b-1

tcc
0.9.12
GNU
Smalltalk

1.95
gcj
3.2
mono
0.15
compilation and execution in one command
(20 points)
XXXXXXXXXXXXXXXXXXXXXXXXX  
shebang aware (#!)
(15 points)
XXXXXXXXXXXXXXXXX XXXXXX   
program can be passed
on command line
(5 points)
XXXXXXX  X XX XXXXX        
interactive interpreter (REPL)
(5 points)
XXXXXXXX   XXXXX XXXXX  X  
debugger
(5 points)
 XXXX        X   X XX  X X 
full interpreter in debugger
(5 points)
 XXXX            X XX      
execution tracer (a la "sh -x")
(2 points)
XXX X X   X      X         
Score4757575557454740354037454545454540424550504035402550

Program Lengths by Language

Typical SOP (Script-Oriented Programming) tasks


(contiguous spaces count as one character)
(the length of the "smallest" program is partially removed in the length of other programs)
shRubyPerlChPythonPHPPikeTclJudoScriptAwkREXXmerdEOCamlLuaSchemeJavaScriptCommonLispHaskellVBScriptPrologErlangJSchemeCSmalltalkJavaC#
smallest00000000000000000016051402006834
hello world1618212019122018162917212227192529262926333925692511588
argv71217172928142111231020282613382734653311143129239102116
env10161910352016158312724773219344134489246514269538224122
test file exists1630242357393036324846463447TD3351559310554103646962151111
test file readable1630242354393938344837393541503352887012960105666966154176
formatting3739423737524949264735395262506355599753916760105101155125
system44656067100778280619410670231967710691186167145216159TD129116446404
sed in place222416939310519315871166335TD193177TDTDTD441250TD830379379431TD586TD
compile what must be157150253332315315372379TD243485TD532799TDTDTD1007500TD685904917TDTD923TD
grep303281244TD477421TD822TD439936TDTD1032TDTDTD1401TDTDTDTD1078TDTDTDTD
Score10491917868756771746865565454514946423833323439283869
TD = "TODO"

Collected Information

Here is the various information collected for each programming language

Programs

the smallest running program doing nothing
sh<empty>
Ruby<empty>
Perl<empty>
Ch<empty>
Python<empty>
PHP<empty>
Pike<empty>
Tcl<empty>
JudoScript<empty>
Awk<empty>
REXX<empty>
merd<empty>
E<empty>
OCaml<empty>
Lua<empty>
Scheme<empty>
JavaScript<empty>
CommonLisp<empty>
Haskell
main = putStr ""
VBScript<empty>
Prolog
main.
Erlang
main(_) -> ok
JScheme<empty>
C
main() { return 0; }
Smalltalk<empty>
Java
public class smallest { public static void main(String[] args) { } }
C#
class z { static void Main() { } }

print a simple string on stdout
sh
echo Hello World
Ruby
puts "Hello World"
Perl
print "Hello World\n"
Ch
puts("Hello World");
Python
print "Hello World"
PHP
Hello World
Pike
return "Hello World"
Tcl
puts "Hello World"
JudoScript
. "Hello World";
Awk
BEGIN { print "Hello World" }
REXX
say "Hello World"
merd
"Hello World".println
E
println("Hello World")
OCaml
print_endline "Hello World"
Lua
print "Hello world"
Scheme
(display "Hello World\n")
JavaScript
System.print("Hello World\n")
CommonLisp
(format t "Hello world~%")
Haskell
main = putStrLn "Hello World"
VBScript
Wscript.echo "Hello World"
Prolog
main :- write('Hello World'), nl.
Erlang
main(_) -> io:fwrite("hello world\n").
JScheme
(display "Hello World\n")
C
#include <stdio.h>
main() {
    puts("Hello World");
    return 0;
}
Smalltalk
'Hello World' displayNl !
Java
public class hello_world {
  public static void main(String[] args) {
    System.out.println("Hello World");
  }
}
C#
class z {
   static void Main() {
      System.Console.WriteLine("Hello World");
   }
}

access command line parameters (no segmentation fault accepted, nor silent exception, so some languages must explicitly check the presence of the argument)
sh
echo $1
Ruby
puts ARGV[0]
Perl
% perl -le 'print $ARGV[0]'
Ch
echo $(_argv[1]);
Python
import sys; print sys.argv[1]
PHP
<?= "{$_SERVER[argv][1]}\n";
Pike
return argv[0]
Tcl
puts [lindex $argv 0]
JudoScript
. $args[0];
Awk
BEGIN { print ARGV[1] }
REXX
say ARG(1)
merd
Sys::args[0].println
E
println(interp.getArgs()[0])
OCaml
print_endline Sys.argv.(1)
Lua
print(arg[1])
Scheme
(format #t "~A\n" (cadr command-line))
JavaScript
System.print(ARGS[1], "\n")
CommonLisp
(write-line (second *posix-argv*))
Haskell
import System
main = do l <- getArgs
          putStrLn (head l)
VBScript
Wscript.echo Wscript.Arguments(0)
Prolog
main :- current_prolog_flag(argv, CmdLine),
        append(_, [--, Arg1|_], CmdLine),
        write(Arg1), nl.
Erlang
main([Arg|_]) -> io:format("~s~n", [Arg]).
JScheme
(print ARGS)
C
#include <stdio.h>
main(int n, char **argv) {
    if (n > 1) puts(argv[1]);
    return 0;
}
Smalltalk
(Smalltalk arguments) at: 1 displayNl !
Java
public class argv {
  public static void main(String[] args) {
    System.out.println(args[0]);
  }
}
C#
class z {
   static void Main(string[] args) {
      if (args.Length > 0) System.Console.WriteLine(args[0]);
   }
}

access environment variable
sh
echo $HOME
Ruby
puts ENV["HOME"]
Perl
% perl -le 'print $ENV{HOME}'
Ch
echo $HOME
Python
import os; print os.environ["HOME"]
PHP
<?= "$_ENV[HOME]\n";
Pike
return env->HOME
Tcl
puts $env(HOME)
JudoScript
. #home;
Awk
BEGIN { print ENVIRON["HOME"] }
REXX
say VALUE("HOME", , SYSTEM)
merd
Sys::env{"HOME"}.println
E
# Only when run on Java1.5
println(<unsafe:java.lang.System>.getenv("HOME"))
OCaml
print_endline(Sys.getenv "HOME")
Lua
print(getenv"HOME")
Scheme
(format #t "~A\n" (getenv "HOME"))
JavaScript
System.print(System.getenv("HOME"), "\n")
CommonLisp
(write-line (posix-getenv "HOME"))
Haskell
import System
main = getEnv "HOME" >>= putStrLn
VBScript
Set s = WScript.CreateObject("WScript.Shell")
Wscript.echo s.Environment("PROCESS")("HOME")
Prolog
main :- getenv('HOME', Home), write(Home), nl.
Erlang
main(_) -> io:format("~s~n", [os:getenv("HOME")]).
JScheme
(load "using/run.scm")
(define getvar
  (let ((table (Properties.)))
    (for-each*
     (lambda (r) (let ((it (.split r "=")))
                   (.put table (vector-ref it 0) (vector-ref it 1))))
     (BufferedReader (inputReader 
          (if (.startsWith ( os.name") "Windows")
              (run (cmd cmd /c set))
              (run (cmd /bin/sh set))))))
    (lambda (name) (.get table name))))
(print (getvar "HOME"))
C
#include <stdlib.h>
main() {
    char *s = getenv("HOME");
    if (s) puts(s);
    return 0;
}
Smalltalk
(Smalltalk getenv: 'HOME') displayNl !
Java
import java.io.*;

public class env {
    public static void main(String[] args) {
	System.out.println(System.getenv("HOME"));
    }
    // NB: System.getenv was re-introduced in JDK 1.5, 
    //     and is not yet in gcj
}
C#
using System;

class z {
    static void Main() {
	Console.WriteLine(Environment.GetEnvironmentVariable("HOME"));
    }
}

return exit code error (non zero) if a file does not exist
sh
[ -e /etc/mtab ]
Ruby
test ?e, "/etc/mtab" or exit 1
Perl
-e "/etc/mtab" or exit 1
Ch
access("/etc/mtab", 0);
Python
import os, sys
sys.exit(not os.path.exists("/etc/mtab"))
PHP
<? file_exists("/etc/mtab") or exit(1);
Pike
return !file_stat("/etc/mtab")
Tcl
exit [expr ![file exists /etc/mtab]]
JudoScript
exit(!"/etc/mtab".fileExists());
Awk
BEGIN { if (system("[ -e /etc/mtab ]")) exit 1 }
REXX
exit STREAM(ARG(1), 'C', 'QUERY EXISTS') == ""
merd
Sys::exit(1) if not File::exists?("/etc/mtab")
E
require(<file:/etc/mtab>.exists())
OCaml
if not(Sys.file_exists "/etc/mtab") then exit 1
Scheme
(exit (access? "/etc/mtab" F_OK))
JavaScript
if (!new File("/etc/mtab").exists()) System.exit(1)
CommonLisp
(unless (probe-file "/etc/mtab") (quit :unix-status 1))
Haskell
import Directory
import System
main = catch (getPermissions "/etc/mtab") (\_ -> exitFailure)
VBScript
Set f = CreateObject("Scripting.FileSystemObject")
if not f.FileExists("/etc/mtab") then wscript.quit(1)
Prolog
main :- exists_file('/etc/mtab') -> halt(0) ; halt(1).
Erlang
main(_) ->
    case filelib:is_file("/etc/mtab") of
        true -> ok;
	_ -> erlang:halt(1)
    end.
JScheme
(if (not (.exists (java.io.File. "/etc/mtab"))) (System.exit 1))
C
#include <unistd.h>
main() {
    return access("/etc/mtab", F_OK);
}
Smalltalk
(File exists: '/etc/mtab') ifFalse: [ ObjectMemory quit: 1 ] !
Java
import java.io.*;

public class exists {
  public static void main(String[] args) {
      System.exit((new File("/etc/mtab")).exists() ? 0 : 1);
  }
}
C#
public class z {
    static int Main() {
	return (new System.IO.FileInfo("/etc/mtab")).Exists ? 0 : 1;
    }
}

return exit code error (non zero) if a file is not readable
sh
[ -r /etc/mtab ]
Ruby
test ?r, "/etc/mtab" or exit 1
Perl
-r "/etc/mtab" or exit 1
Ch
access("/etc/mtab", 4);
Python
import sys
try: open("/etc/mtab")
except: sys.exit(1)
PHP
<? is_readable("/etc/mtab") or exit(1);
Pike
return !!catch(Stdio.File("/etc/mtab"))
Tcl
exit [expr ![file readable /etc/mtab]]
JudoScript
exit(!"/etc/mtab".fileReadable());
Awk
BEGIN { if (system("[ -r /etc/mtab ]")) exit 1 }
REXX
exit \STREAM(ARG(1), 'C', 'READABLE')
merd
File::open("/etc/mtab") or Sys::exit(1)
E
require(<file:/etc/mtab>.canRead())
OCaml
try open_in("/etc/mtab") with _ -> exit 1
Lua
if not openfile("/etc/mtab", "r") then exit(1) end
Scheme
(exit (access? "/etc/mtab" R_OK))
JavaScript
if (!new File("/etc/mtab").open("r")) System.exit(1)
CommonLisp
(require :sb-posix)
(unless (sb-posix:access "/etc/mtab" r-ok)
  (quit :unix-status 1))
Haskell
import System
main = catch (readFile "/etc/mtab") (\_ -> exitFailure)
VBScript
On Error Resume Next
Set f = CreateObject("Scripting.FileSystemObject")
if f.GetFile("file2.txt") = Nothing then wscript.quit(1)
Prolog
main :- access_file('/etc/mtab', read) -> halt(0) ; halt(1).
Erlang
main(_) ->
    case file:read_file("/etc/mtab") of
        {ok, _} -> ok;
	_ -> erlang:halt(1)
    end.
JScheme
(if (not (.canWrite (java.io.File. "/etc/mtab"))) (System.exit 1))
C
#include <unistd.h>
main() {
    return access("/etc/mtab", R_OK);
}
Smalltalk
(File isReadable: '/etc/mtab') ifFalse: [ ObjectMemory quit: 1 ] !
Java
import java.io.*;

public class readable {
  public static void main(String[] args) {
      System.exit((new File("/etc/mtab")).canRead() ? 0 : 1);
  }
}
C#
public class z {
    static int Main() {
	try {
	    (new System.IO.FileInfo("/etc/mtab")).OpenRead();
	    return 0;
	} catch(System.Exception ex) {
	    return 1;
	}
    }
}

print integers in a simple formatted string
sh
a=1; b=2; echo "$a + $b = $[$a + $b]"
Ruby
a=1; b=2; puts "#{a} + #{b} = #{a + b}"
Perl
% perl -le '$a=1; $b=2; print "$a + $b = ", $a + $b'
Ch
int a=1, b=2; 
echo $a + $b = $(a+b)
Python
a=1; b=2; print a, '+', b ,'=', a + b
PHP
<? $a=1; $b=2; echo "$a + $b = " . ($a + $b) . "\n";
Pike
int a=1, b=2; write("%d + %d = %d", a, b, a + b);
Tcl
set a 1; set b 2; puts "$a + $b = [expr $a + $b]"
JudoScript
. a=1," + ",b=2," = ",a+b;
Awk
BEGIN { a=1; b=2; print a " + " b " = " a + b }
REXX
a = 1 ; b = 2 ; say "a + b =" a + b
merd
a=1; b=2; "{a} + {b} = {a + b}".println
E
def a := 1
def b := 2
println(`$a + $b = ${a + b}`)
OCaml
let a, b = 1, 2 in
Printf.printf "%d + %d = %d\n" a b (a + b)
Lua
a=1; b=2; print(a .. " + " .. b .. " = " .. a + b)
Scheme
(let ((a 1) (b 2))
  (format #t "~A + ~A = ~A\n" a b (+ a b)))
JavaScript
a=1; b=2; System.print(a, " + ", b, " = ", a + b, "\n")
CommonLisp
(let ((a 1) (b 2)) (format t "~a + ~a = ~a~%" a b (+ a b)))
Haskell
main = putStrLn $ show a ++ " + " ++ show b ++ " = " ++ show(a + b) 
    where a=1
          b=2
VBScript
a=1 : b=2
WScript.echo a & " + " & b & " = " & a + b
Prolog
main :- A is 1, B is 2, Result is A + B, 
        format('~d + ~d = ~d\n', [A, B, Result]).
Erlang
main(_) -> A = 1, B = 2, io:fwrite("~p + ~p = ~p~n", [A, B, A+B]).
JScheme
(let ((a 1)
      (b 2))
  (print {[a] + [b] = [(+ a b)]}))
C
#include <stdio.h>
main() {
    int a=1, b=2;
    printf("%d + %d = %d\n", a, b, a + b);
    return 0;
}
Smalltalk
| a b |
a:=1.
b:=2.
(a printString, ' + ', b printString, ' = ', (a + b) printString)
   displayNl !
Java
public class formatting {
  public static void main(String[] args) {
    int a=1, b=2;
    System.out.println("" + a + " + " + b + " = " + (a + b));
  }
}
C#
class z {
   static void Main() {
      int a=1, b=2;
      System.Console.WriteLine("{0} + {1} = {2}", a, b, a + b);
   }
}

call an external program and check the return value
sh
false || echo "false failed" 1>&2; echo done
Ruby
system "false" or $stderr.puts "false failed"; system "echo done"
Perl
system "false" and warn "false failed\n"; system "echo done"
Ch
if (system("false")) fprintf(stderr, "false failed\n");
echo done;
Python
import os, sys
if os.system("false"):
    sys.stderr.write("false failed\n")
os.system("echo done")
PHP
<? system("false") or fwrite(STDERR, "false failed\n"); 
system("echo done");
Pike
Process.system("false") && werror("false failed\n");
Process.system("echo done");
Tcl
if {[catch {exec false}]} {puts stderr "false failed"}
exec echo >@ stdout done
JudoScript
exec <r> 'false'; if (r) . "false failed"; exec 'echo done';
Awk
BEGIN { 
  if (system("false")) print "false failed" > "/dev/stderr" 
  system("echo done")
}
REXX
address SYSTEM "false"
if RC == 0 then ; call LINEOUT 'STDERR', "false failed"
address SYSTEM "echo done"
merd
Sys::system("false") or warn("false failed"); Sys::system("echo done")
E
def runFalse := makeCommand("/bin/false")
def runEcho := makeCommand("/bin/true")
def ok := try {
     runFalse()
     true
} catch ex {
     stderr.println("false failed")
     false
}
if (ok) {
     println(runEcho("done")[0])
}
OCaml
if Sys.command "false" != 0 then prerr_endline("false failed");
ignore(Sys.command "echo done")
Lua
if execute "false" ~= 0 then _ALERT "false failed\n" end
execute "echo done"
Scheme
(if (not (= (system "false") 0)) 
  (display "false failed\n" (current-error-port)))
(system "echo done")
JavaScript
if (System.system("false") != 0) System.error("false failed\n")
System.system("echo done")
CommonLisp
(unless 
  (zerop (process-exit-code (run-program "false" nil :search t)))
  (format *error-output* "false failed~%"))
(run-program "echo" '("done") :search t :output *standard-output*)
Haskell
import System
import IO
import Monad
main = 
    do ret <- system "false"
       when (ret /= ExitSuccess) (hPutStrLn stderr "false failed")
       system "echo done"
VBScript
Set s = CreateObject("WScript.Shell")
Set e = s.Exec("false")
If e.exitCode > 0 Then wscript.stderr.writeline "false failed"
s.Exec("echo done")
Prolog
main :- shell('false', Status),
        (Status \= 0 ->
              current_stream(2, _, StdErr),
              format(StdErr, 'false failed~n', [])
           ;
              true),
        shell('echo done', _).
Erlang
main(_) ->
    case os:cmd("false; echo $?") of
         [$0|_] -> ok;
         _ -> io:fwrite("false failed~n")
    end,
    io:fwrite(os:cmd("echo done")).
C
#include <stdio.h>
main() {
    if (system("false")) fprintf(stderr, "false failed\n");
    system("echo done");
    return 0;
}
Smalltalk
(Smalltalk system: 'false') = 0
  ifFalse: [ stderr display: 'false failed' ; nl ].
Smalltalk system: 'echo done' !
Java
import java.io.*;
public class system {
  public static void main(String[] args) throws Exception {
    if (Runtime.getRuntime().exec("false").waitFor() != 0)
      System.err.println("false failed");
  
    BufferedReader input = new BufferedReader(new InputStreamReader(
        Runtime.getRuntime().exec("echo done").getInputStream()
    ));
    String line;
    while ((line = input.readLine()) != null)
      System.out.println(line);
  }
}
C#
using System;
using System.Diagnostics;

public class z {
    static void Main() {
	Process proc = new Process();
	proc.EnableRaisingEvents = false;

	proc.StartInfo.FileName = "false";
	proc.Start();
	proc.WaitForExit();
	if (proc.ExitCode != 0) Console.Error.WriteLine("false failed");

	proc.StartInfo.FileName = "echo";
	proc.StartInfo.Arguments = "done";
	proc.Start();
	proc.WaitForExit();
    }
}

remove #-comments from a file (modifying the file, i.e. in place)
sh
sed -i -e "s/#.*//" $1
Ruby
% ruby -pi -e '$_.sub!(/#.*/, "")'
Perl
% perl -pi -e "s/#.*//"
Ch
char *tmp=tmpnam(NULL);
sed 's/#.*//' < $(_argv[1]) > $tmp
cp -f $tmp $(_argv[1])
rm -f $tmp
Python
import fileinput, re

for s in fileinput.input(inplace = 1):
    print re.sub("#.*", "", s),
PHP
<?
$f = $_SERVER[argv][1];
file_put_contents($f, 
    preg_replace("/#.*/", '', file_get_contents($f)));
Pike
int main(int n, array args) {
   array r = ({});
   foreach(Stdio.read_file(args[1]) / "\n", string x) {
     sscanf(x, "%s#", x);
     r += ({x});
   }
   Stdio.write_file(args[1], r*"\n");
}
Tcl
set f [lindex $argv 0]
set fd [open $f r]
regsub -all {#[^\n]*\n} [read $fd] {} contents
close $fd
set fd [open $f w]
puts -nonewline $fd $contents
close $fd
JudoScript
getFileAsString(#args[0]).replaceAll('#.*', '').writeToFile(#args[0]);
Awk
BEGIN { 
  if (!("mktemp /tmp/sed.XXXXXX" | getline tmp)) exit 1
}
{ sub("#.*", ""); print >> tmp }
END {
  system("cp -f " tmp " " ARGV[1])
  system("rm -f " tmp)
}
REXX
call rxFuncAdd 'sysLoadFuncs', 'rexxUtil', 'sysLoadFuncs'
call sysLoadFuncs

fin = ARG(1) ; fout = RANDOM() || ".tmp"
do while LINES(fin) > 0
  call LINEOUT fout, CHANGESTR("#", LINEIN(fin), "")
end
call STREAM fin, 'C', 'CLOSE' ; call STREAM fout, 'C', 'CLOSE'

call sysFileDelete fin ; call sysMoveObject fout, fin
call sysDropFuncs
E
def f := <file: interp.getArgs()[0]>
var text := ""
for line in f {
     if (line =~ `@left#@right`) {
         text += left + "\n"
     } else {
         text += line
     }
}
f.setText(text)
OCaml
let l = Std.input_list (open_in Sys.argv.(1)) in
let f = open_out Sys.argv.(0) in
List.iter (fun l -> output_string f 
 ((Str.replace_first (Str.regexp "#.*") "" l) ^"\n")) l;;
CommonLisp
(defun remove-hash-comments (path)
  (let ((lines (with-open-file (inf path :direction :input)
                 (loop for line = (read-line inf nil nil)
                       while line
                       collect line))))
    (with-open-file (ouf path
                         :direction :output
                         :if-exists :supersede)
      (dolist (line lines)
        (write-line (subseq line 0 (position #\# line)) ouf)))))
Haskell
import System
import System.IO
import Monad
import Control.Exception

c = unlines . map (takeWhile (/= '#')) . lines
fop f n = do l <- fmap f (readFile n)
             evaluate (length l)
             writeFile n l

main = getArgs >>= (fop c) . head
Prolog
main :-
  getUserArg(1, File),
  atom_concat(File, '.tmp', TmpFile),
  strip_comments_from_file(File, TmpFile),
  delete_file(File),
  rename_file(TmpFile, File).

strip_comments_from_file(FileIn, FileOut) :-
  open(FileIn, read, In, [type(binary)]), 
  open(FileOut, write, Out, [type(binary)]),
  process_lines(In, Out),
  close(In), close(Out).

process_lines(In, _) :- at_end_of_stream(In), !.

process_lines(In, Out) :-
  read_line_to_codes(In, Line),
  partition(Line, 35, Prefix, _),
  format(Out, '~s~n', [Prefix]),
  !, process_lines(In, Out).

partition(ListIn, Element, Prefix, Suffix) :-
  (member(Element, ListIn) ->
    append(Prefix, [Element|Suffix], ListIn)
  ;
    Prefix = ListIn, Suffix = []).

getUserArg(N, Arg) :-
  current_prolog_flag(argv, Cmdline),
  append(_, [--|Args], Cmdline),
  nth1(N, Args, Arg).
Erlang
main([F|_]) ->
     {ok, B} = file:read_file(F),
     Lines = string:tokens(erlang:binary_to_list(B), "\n"),
     Not_comment = fun ($#) -> false; (_) -> true end,
     New = lists:map(
         fun(Line) ->
               L = lists:takewhile(Not_comment, Line),
               L ++ "\n"
         end,
         Lines
     ),
     file:write_file(F, erlang:list_to_binary(New)).
JScheme
(load "using/run.scm")
(import "java.io.File")
(let ((file (vector-ref ARGS 1)))
  (let ((out (File.createTempFile "foo" "bar")))
    (print out)
    (call-with-output-file out
      (lambda (s)
        (for-each* 
            (lambda (r) (.println s (.replaceFirst r "#.*" "")))
            (BufferedReader (File. file)))
        (.close s)))
    (.renameTo out (File. file))))
C
#include <stdio.h>
#include <unistd.h>
main (int argc, char **argv)
{
 FILE *f;
 int c=1, t=0, i=0;
 if (argc-c)
  {
   f=fopen(argv[c],"r+");
   while (c) switch (c=getc(f))
    {
    case '#' : if (!t) { t=1,i-=2; break; }
    case '\n' : if (t) { t=0; break; }
    default : if (t==1) { i--; break; }
         fseek(f,i-1,1);
         putc(c++,f);
         fseek(f,-i,1);
    }
   truncate(argv[1],ftell(f)+i);
  }
 return 0;
}
Java
import java.io.*;

public class uncomment {
    public static void main(String[] args) {
	try {
	    FileReader fr = new FileReader(args[0]);
	    BufferedReader br = new BufferedReader(fr);

	    File f = new File(args[0] + ".tmp");
	    FileWriter fw = new FileWriter(f);

	    String line = "";
	    while ((line = br.readLine()) != null) {
		int pos = line.indexOf('#');
		if (pos > -1) line = line.substring(0,pos);
		fw.write(line + '\n');
	    }
	    fr.close();
	    fw.close();
	    f.renameTo(new File(args[0]));
	} catch(Exception ex) {
	    ex.printStackTrace();
	}
    }
}

find and compile .c files into .o when the .o is old or absent
sh
for c in `find -name "*.c"`; do
  o=`echo $c | sed 's/.c$/.o/'`
  if [ "$c" -nt "$o" ]; then
    echo "compiling $c to $o"
    gcc -c -o "$o" "$c"
  fi
done
Ruby
Dir['**/*.c'].each{|c|
  o = c.sub('.c$', '.o')
  if test ?>, c, o then
    puts "compiling #{c} to #{o}"
    system("gcc", "-c", "-o", o, c)
  end
}
Perl
use File::Find;

find({ no_chdir => 1, 
       wanted => sub {
           if (($o = $_) =~ s/\.c$/.o/ 
               && -M $_ <= -M $o) {
               print "compiling $_ to $o\n";
               system qw(gcc -c -o), $o, $_;
           }
} }, '.');
Ch
#include <sys/stat.h>

string_t c, o;
struct stat cstat, ostat;
foreach (c; `find / -name "*.c"`) {
          o=`echo $c | sed 's/.c$/.o/'`;
          stat(o, &ostat);
          stat(c, &cstat);
          if (ostat.st_mtime  > cstat.st_mtime) { 
            echo "compiling $c to $o";
            gcc -c -o "$o" "$c";
          }
}
Python
from os import *
from fnmatch import *

for dir, _, files in walk('.'):
    for f in filter(files, '*.c'):
        c = path.join(dir, f)
        o = c[0:-2] + '.o'
        if not path.exists(o) or stat(c)[9] > stat(o)[9]:
            print 'compiling', c, 'to', o
            system("gcc -c -o '%s' '%s'" % (o, c))
PHP
<?
function doit($p) {
    foreach (glob($p . '/*', GLOB_ONLYDIR) as $d) doit($d);
    foreach (glob($p . '/*.c') as $c) {
        $o = substr($c, 0, -1) . 'o';
        if (filemtime($o) < filemtime($c)) {
            echo "compiling $c to $o\n";
            system("gcc -c -o $o $c");
        }
    }
}
doit('.');
Pike
int main() {
  object i = Filesystem.Traversion(".");
  foreach (i; string d; string c) {
     if (!has_suffix(c, ".c")) continue;
     c = d+c;
     string o = c;
     o[-1] = 'o';
     object s = file_stat(o);
     if (s && i->stat()->mtime < s->mtime) continue;
     write("compiling %s to %s\n", c, o);
     Process.Process(({"gcc", "-c", "-o", o, c}))->wait();
  }
}
Tcl
proc doit {dir} {
    foreach f [glob -nocomplain $dir/*] {
        if [file isdir $f] {
            doit $f
        } elseif { 
            [regsub \\.c$ $f .o o] && !( 
               [file exists $o] && 
               [file mtime $o] > [file mtime $f]
            ) } {
                puts "compiling $f to $o"
                exec gcc -c -o $o $f
        }
    }
}

doit .
Awk
BEGIN { 
  while ("find -name '*.c'" | getline) {
    c = $0
    sub(/.c$/, ".o")
    if (system(sprintf("[ %s -nt %s ]", c, $0)) == 0) {
      print "compiling", c, "to", $0
      system(sprintf("gcc -c -o '%s' '%s'", $0, c))
    }
  }    
}
REXX
call rxFuncAdd 'sysLoadFuncs', 'rexxUtil', 'sysLoadFuncs'
call sysLoadFuncs

call sysFileTree '*.c', 'cfilelist.', 'sf'

do i = 1 for cfilelist.0
  cfilelist.i = WORD(cfilelist.i, 5)
  ofile = LEFT(cfilelist.i, LASTPOS(".c", cfilelist.i) - 1) || ".o"
  otime = STREAM(ofile, 'C', 'QUERY TIMESTAMP')
  if otime < STREAM(cfilelist.i, 'C', 'QUERY TIMESTAMP') then do
    say "compiling" cfilelist.i "to" ofile
    address SYSTEM "gcc -c -o" cfilelist.i ofile
  end
end

call sysDropFuncs
E
def runGcc := makeCommand("c:/cygwin/bin/gcc.exe")
def leaves := <import:org.erights.e.tools.files.leaves>

for c in leaves(<file:.>) {
     if (c.getPath() =~ `@base.c`) {
         def tmp := <file: `$base.o`>
         if (!tmp.exists() || tmp.lastModified() < c.lastModified()) {
             println(`compiling $base.c to $base.o`)
             try {
                 runGcc("-c", `$base.c`, "-o", `$base.o`)
             } catch ex {
                 stderr.println(`$base.c failed with $ex`)
             }
         }
     }
}
OCaml
open Unix

let listdir dir =
  let rec listdir_ hdir =
    try
      let s = readdir hdir in
      if s = "." || s = ".." then
        listdir_ hdir
      else 
        s :: listdir_ hdir
    with End_of_file -> []
  in
  let hdir = opendir dir in
  let l = listdir_ hdir in
  closedir hdir ;
  l

let rec doit dir =
  List.iter (fun s ->
    let f = Filename.concat dir s in
    if (lstat f).st_kind = S_DIR then
      doit f
    else if Filename.check_suffix f ".c" then
      let o = Filename.chop_extension f ^ ".o" in
      if not (Sys.file_exists o && 
              (stat o).st_mtime > (stat f).st_mtime) then
        let cmd = Printf.sprintf "gcc -c -o '%s' '%s'" o f in
        print_endline ("compiling " ^ f ^ " to " ^ o) ;
        ignore (Sys.command cmd)
  ) (listdir dir)
;;
doit(".")
CommonLisp
(defun find-files-by-type (dir type)
  (mapcan (lambda (path)
            (cond
              ((null (pathname-name path))
               (find-files-by-type path type))
              ((string= (pathname-type path) type)
               (list path))
              (t
               nil)))
          (directory (make-pathname :name :wild
                                    :type :wild
                                    :defaults (truename dir))))))

(defun compile-older-files (dir)
  (dolist (c-path (find-files-by-type dir "c"))
    (let* ((c-name (namestring c-path))
           (o-path (make-pathname :type "o" :defaults c-path))
           (o-name (namestring o-path)))
      (when (or (not (probe-file o-path))
                (< (file-write-date o-path) (file-write-date c-path)))
        (format t "Compiling ~a to ~a~%" c-name o-name)
        (run-program "gcc"
                     (list "-c" "-o" o-name c-name)
                     :output *standard-output*
                     :search t)))))
Haskell
import System
import System.IO
import System.Directory
import Data.List
import Control.Monad

gmt = getModificationTime
op f = do catch (do ct <- gmt f; ot <- gmt o;
                    when (ct > ot) comp)
                (\_ -> comp)
 where o = take (length f - 2) f ++ ".o"
       comp = do putStrLn ("Compiling "++f++" to "++o)
                 system ("gcc -c -o "++o++" "++f)

main = do files <- getCurrentDirectory >>= getDirectoryContents
          mapM_ op $ filter (".c"`isSuffixOf`) files
Prolog
main :-
  expand_file_name('*.c', CFiles),
  forall(member(CFile, CFiles),
	(sub_atom(CFile, 0, _, 2, BaseName),
	 atom_concat(BaseName, '.o', ObjFile),
	 (should_compile(CFile, ObjFile) 
            -> compile(CFile, ObjFile) ; true))).

should_compile(SrcFile, ObjFile) :-
  (exists_file(ObjFile) ->
    time_file(SrcFile, SrcTime), 
    time_file(ObjFile, ObjTime), 
    ObjTime < SrcTime
  ;
    true).

compile(SrcFile, ObjFile) :-
  concat_atom(['gcc -c "', SrcFile, '" -o "', ObjFile, '"'], '', Cmd),
  format('compiling ~w to ~w\n', [SrcFile, ObjFile]),
  trap(Cmd, _).

trap(Cmd, Output) :-
  open(pipe(Cmd), read, Input),
  read_line_to_codes(Input, Output),
  close(Input).
Erlang
main(_) ->
      Fun = fun (Cfile, Acc) ->
		  [$c | File] = lists:reverse(Cfile),
		  Ofile = lists:reverse([$o | File]),
		  case is_compile_time(Cfile, Ofile) of
		      true ->
		          io:format("compiling ~s to ~s~n", [Cfile, Ofile]),
			  os:cmd(io_lib:format("gcc -c -o ~s ~s~n", [Ofile, Cfile])),
			  [Ofile | Acc];
		      false -> Acc
		  end
	  end,
     Regexp = regexp:sh_to_awk("*.c"),
     cc_recurse('.', Regexp, Fun).

is_compile_time(C, O) ->
     case filelib:is_file(O) of
	true -> filelib:last_modified(C) > filelib:last_modified(O);
	false -> true
     end.

cc_recurse(Directory, Regexp, CC_Fun) ->
     catch filelib:fold_files(Directory, Regexp, false, CC_Fun, []),
     {ok, Files} = file:list_dir(Directory),
     lists:foreach(
         fun (Subdir) -> cc_recurse(Subdir, Regexp, CC_Fun) end,
         lists:filter(fun (File) -> filelib:is_dir(File) end, Files)
     ).
JScheme
(import "java.io.File")
(define (s->o srcDir classDir fromtype totype)
  ;; Source file to object file converter.
  (lambda (file)
    (let ((f (.toString (relativize srcDir file))))
      (File. classDir
        (string-append (.substring f 0
                          (- (.length f) (.length fromtype)))
                       totype)))))

(define (needsUpdate? s->o)
  (lambda (jf)
    ;; Does .java file jf need to be recompiled?
    (let ((cf (s->o jf)))
      (or (not (.exists cf)) 
          (<= (.lastModified cf) (.lastModified jf))))))

(let* ((dir (java.io.File. "."))
      (s->o (s->o dir dir ".c" ".o"))
      (update? (needsUpdate? s->o)))
  (for-each (lambda (c)
              (if (update? c)
                  (let ((o (s->o c)))
                    (display {compiling [c] to [o]\n})
                    (out (run (cmd gcc -c -o ,c ,o))))))
            (files* (java.io.File. ".") (isFile ".c"))))
Java
import java.io.*;

public class compile {
  public static void main(String[] args) {
      filter ft = new filter();
      if (args.length > 0) {
          File f = new File(args[0]);
          File[] cs = f.listFiles(ft);
	  for (int i = 0; i < cs.length; i++) tryFile(cs[i]);
      }
  }

  static void tryFile(File c) {
      String o = c.toString().replaceAll(".c$", ".o");
      File tmp = new File(o);
      if (!tmp.exists() || 
          tmp.lastModified() < c.lastModified()) {
          System.out.println("compiling " + 
                             c.toString() + " to " + o);
          String cmd = "gcc -c " + c.toString() + " -o " + o;
	  try {
	      java.lang.Runtime.getRuntime().exec(cmd);
          } catch(Exception ex) { ex.printStackTrace(); }
      }
  }
}

class filter implements FileFilter
{
  public filter() { }
  public boolean accept(File f) {
      return f.toString().endsWith(".c");
  }
}

grep with -F -i -h handling, usage, grep'ing many files
sh
opts=''
while [ -n "$1" ]; do
    case $1 in
        -i) opts="-i $opts" ;;
        -F) opts="-F $opts" ;;
        -h) h=1 ;;
        *) break ;;
    esac
    shift
done

if [ $# = 0 ] || [ -n "$h" ]; then
    echo "usage: grep [-F] [-i] regexp [files...]"
    exit 1
fi

r=$1
shift

grep $opts $r "$@"
Ruby
require 'getopts'
getopts('Fih')

ARGV.empty? || $OPT_h and 
  (puts "usage: grep [-F] [-i] regexp [files...]"; exit 1)

r = ARGV.shift
r = Regexp.quote(r) if $OPT_F
r = /#{r}/i if $OPT_i

prefix = ARGV.size > 1

while gets
  print prefix ? "#{ARGF}:" : '', $_ if $_ =~ /#{r}/
end
Perl
use Getopt::Std;
getopts('Fih', \%h);

!@ARGV || $h{h} and die "usage: grep [-F] [-i] regexp [files...]\n";

$r = ($h{i} && '(?i)') . shift;
$r = "\Q$r" if $h{F};
$prefix = @ARGV > 1;

while (<>) {
    print $prefix && "$ARGV:", $_ if /$r/o;
}
Python
import getopt, sys, fileinput, re

opts, args = getopt.getopt(sys.argv[1:], 'hiF')
opts = [ x[0] for x in opts ]

if not args or '-h' in opts:
    print >> sys.stderr, "usage: grep [-F] [-i] regexp [files...]"
    sys.exit(1)

r, files = args[0], args[1:]

if '-F' in opts:
    r = re.sub("\W", lambda i: "\\" + i.group(0), r)

if '-i' in opts:
    re = re.compile(r, re.I)
else:
    re = re.compile(r)
  
for s in fileinput.input(files):
    if re.search(s):
        print s,
PHP
<?
$args = array_slice($_SERVER[argv], 1);

while ($o = array_shift($args)) {
    if (ereg('^-[ihF]$', $o)) $$o{1} = $o{1}; 
    else break;
}

if (!$o || @$h)
    die("usage: grep [-F] [-i] regexp [files...]\n");

if (empty($args))
    $args []= 'php://stdin';

$r = $F ? preg_quote($o, '/') : $o;

foreach ($args as $f) {
    foreach (preg_grep("/$r/$i", file($f)) as $l)
        echo count($args) > 1 ? "$f:$l" : $l; 
Tcl
set i 0
set F 0
set ind 0
set usage 1
foreach s $argv {
    if { "$s" == "-i" } { 
        set i 1 
    } elseif { "$s" == "-F" } { 
        set F 1 
    } elseif { "$s" == "-h" } { 
        incr usage
    } {
        incr usage -1
        break
    }
    incr ind
}

if $usage {
    puts stderr {usage: grep [-F] [-i] regexp [files...]}
    exit 1
}

set re [lindex $argv $ind]
incr ind
set files [lrange $argv $ind end]

if $i { set re (?i)$re }
if $F { set re (?q)$re }

set nb [llength $files]

proc grep { prefix fd re } {
    while {[gets $fd s] >= 0} {
        if [regexp $re $s] { puts $prefix$s }
    }
}

if { $nb == 0 } {
    grep "" stdin $re
} {
    set prefix ""
    foreach f $files {
        if { $nb > 1 } { set prefix $f: }
        set fd [open $f]
        grep $prefix $fd $re
        close $fd
    }
}
Awk
function usage() {
  print "usage: grep [-F] [-i] regexp [files...]" > "/dev/stderr"
  exit 1
}

BEGIN {
  for (i = 1; i < ARGC; i++) {
    s = ARGV[i]
    ARGV[i] = ""
         if (s == "-h") usage()
    else if (s == "-i") IGNORECASE = 1
    else if (s == "-F") F = 1
    else break
  }
  if (i == ARGC) usage()
  re = s
  prefix = i + 2 < ARGC
}

{
  if (F ? index($0, re) : match($0, re))
    print (prefix ? (FILENAME ":") : "") $0
}
REXX
call rxFuncAdd 'reLoadFuncs', 'rexxRE', 'reLoadFuncs'
call reLoadFuncs

cmdline = ARG(1) ; opt = "" ; regexp = "" ; filelist = ""

do while cmdline <> ""
  parse var cmdline token cmdline
  if LEFT(token, 1) == "-" then
    if TRANSLATE(token) == "-H" | VERIFY(token, "-iF") \= 0 then
      call usage ; else ; opt = opt || CHANGESTR("-", token, "")
  else ; if regexp == "" then
    regexp = token
  else
    filelist = filelist token
end

/* 'F' not recognised by 'reComp'; just remove it */
opt = CHANGESTR("F", opt, "")
if POS("i", opt) > 0 then ; opt = "" ; else ; opt = "c"

cre = reComp(regexp, opt)

do while filelist <> ""
  parse var filelist file filelist
  do while LINES(file) > 0
    if reExec(cre, LINEIN(file), 'match.') then
      call LINEOUT , file || ":" || match.!match
  end
end

call reFree cre ; call reDropFuncs ; exit 0

usage :
  say "usage: grep [-h] | [-F|-i] regexp [files...]"
  call reDropFuncs ; exit 1
OCaml
open List

let rec iter_lines f fd =
  try
    f (input_line fd) ; iter_lines f fd
  with End_of_file -> ()

let _ = 
  let i, fixed, usage = ref false, ref false, ref false in

  Arg.parse [ "-i", Arg.Set i, "" ; 
              "-F", Arg.Set fixed, "" ;
              "-h", Arg.Set usage, "" ;
            ] (fun _ -> ()) "" ;
  match filter (fun s -> s.[0] <> '-') (Array.to_list Sys.argv) with
  | _ :: r :: files when not !usage ->
      let r = if !fixed then Str.quote r else r in
      let re = (if !i then Str.regexp_case_fold else Str.regexp) r in
      let prefix = length files > 1 in

      iter (fun (name, fd) ->
        iter_lines (fun s ->
          try 
            let _ = Str.search_forward re s 0 in
            print_endline ((if prefix then name ^ ":" else "") ^ s)
          with Not_found -> ()
        ) fd
      ) (if files = [] then 
           ["", stdin] 
         else
           map (fun s -> s, open_in s) files)

  | _ ->
      prerr_endline "usage: grep [-F] [-i] regexp [files...]" ;
      exit 1
CommonLisp
(require :asdf)
(require :cl-ppcre)

(defun grep (pattern files &key (no-case nil) (fixed-strings nil))
  (let ((scanner (cl-ppcre:create-scanner
                  (if fixed-strings
                      (cl-ppcre:quote-meta-chars pattern)
                      pattern)
                  :case-insensitive-mode no-case))
        (prefix-p (> (length files) 1)))
    (dolist (path files)
      (with-open-file (inf path :direction :input)
        (loop for line = (read-line inf nil nil)
              while line
              when (cl-ppcre:scan scanner line)
              do (format t "~@[~a:~]~a~%"
                         (when prefix-p
                           (pathname-name path))
                           line))))))
(defun parse-args (argv)
  (let ((flags nil)
        (args nil))
    (dolist (arg argv)
      (if (eql (char arg 0) #\-)
          (push arg flags)
          (push arg args)))
    (values (nreverse flags) (nreverse args))))
 
(multiple-value-bind (flags args)
    (parse-args (rest *posix-argv*))
  ;; Handle help flag
  (when (or (null args)
            (member "-h" flags :test #'string=))
    (format *error-output*
            "Usage: grep [-h] [-i] [-F] <pattern> <path> ...~%")
    (quit :unix-status 1))
  ;; Do grep
  (grep (first args) (rest args)
        :no-case (member "-i" flags :test #'string=)
        :fixed-strings (member "-F" flags :test #'string=)))
JScheme
(load "using/run.scm")
(define (any p xs) 
    (and (pair? xs) (or (p (car xs)) (any p (cdr xs)))))

(define (forLines f files)
    (for-each 
        (lambda (file) (for-each* f (BufferedReader (File. file))))
        files))

(define (show x) (display x) (newline))

(define (grep-F -i re files)
  (let ((lines (vector->list (.split re "\n")))
        (f (if -i .equalsIgnoreCase .equals)))
    (forLines 
        (lambda (r) (if (any (lambda (p) (f p r)) lines) (show r)))
        files)))

(define (grep re files)
  (let ((p (Pattern.compile re)))
    (forLines (lambda (r) (if (.find (.matcher p r)) (show r)))
              files)))

(let* ((args (cdr (vector->list ARGS)))
       (-F (member "-F" args))
       (-i (member "-i" args))
       (-h (member "-h" args))
       (args (filter (lambda (a) (not (.startsWith a "-"))) args))
       (re (if -i {[(?i)][(car args)]} (car args)))
       (files (cdr args)))
  (cond ((or -h (null? args))
         (display {usage: grep [-F] [-i] regexp file ...\n}))
        (-F (grep-F -i re files))
        (else (grep re files))))

Tools

run from stdin

sh
sh
Ruby
ruby
Perl
perl
Ch
ch
Python
python
PHP
php
Tcl
tclsh
REXX
rexx
merd
merd
E
rune -
Lua
lua
CommonLisp
sbcl --noinform
Erlang
escript
JScheme
runscheme

run from cmdline

sh
sh -c %s
Ruby
ruby -e %s
Perl
perl -e %s
Ch
ch -c %s
Python
python -c %s
PHP
php -r %s
Pike
pike -e %s
Awk
awk %s
merd
merd -e %s
E
rune -src %s
Lua
lua -e %s
Scheme
guile -c %s
JavaScript
ngs-js -e %s
CommonLisp
sbcl --noinform -eval %s
Haskell
ghc -e %s

run from file

sh
sh %s
Ruby
ruby %s
Perl
perl %s
Ch
ch %s
Python
python %s
PHP
php %s
Pike
pike %s
Tcl
tclsh %s
JudoScript
java judo %s
Awk
awk -f %s --
REXX
rexx %s
merd
merd %s
E
rune %s
OCaml
ocaml -I `ocamlc -where`/extlib str.cma unix.cma extLib.cma %s
Lua
lua -f %s
Scheme
guile -s %s
JavaScript
ngs-js %s
CommonLisp
sbcl --noinform -load %s
Haskell
runghc %s
VBScript
cscript //nologo %s
Prolog
pl -q -t halt -g main -s %s -- 
Erlang
escript %s
C
tcc %s
Smalltalk
gst -Q %s -a
Java
gcj %s --main=%s && ./a.out
C#
mcs %s && mint %s.exe

file extension

sh
.sh
Ruby
.rb
Perl
.pl
Ch
.ch
Python
.py
PHP
.php
Pike
.pike
Tcl
.tcl
JudoScript
.judo
Awk
.awk
REXX
.rex or .rexx
merd
.me
E
.e
OCaml
.ml
Lua
.lua
Scheme
.scm
JavaScript
.js
CommonLisp
.lisp
Haskell
.hs
VBScript
.vbs
Prolog
.pl or .pro
Erlang
.erl
JScheme
.scm
C
.c
Smalltalk
.st
Java
.java
C#
.cs

interactive interpreter

sh
sh
Ruby
irb
Perl
perl -de 1
Ch
ch
Python
python
PHP
php -a
Pike
pike
Tcl
tclsh
merd
merd
E
rune
OCaml
ocaml
Lua
lua
Scheme
umb-scheme
CommonLisp
sbcl
Haskell
ghci
VBScript
cscript //X 1
Prolog
pl
Erlang
erl
Smalltalk
gst

verbose execution

sh
sh -x
Ruby
ruby -r tracer
Perl
perl -d:Trace
Python
python -m trace -t
Pike
pike -t1
REXX
rexx -ti %s
CommonLisp
sbcl --noinform -eval '(trace)'

debugger

Ruby
ruby -r debug %s
Perl
perl -d %s
Ch
_debug =1
parse foo.ch
run
Python
python -m pdb %s
OCaml
ocamldebug %s (nice go-back-time feature)
CommonLisp
<builtin>
VBScript
cscript //X
Prolog
use debug/0
C
gdb (arguments must be passed separately)
Java
gdb

Related Pages

Translations

Small snippets

Various

Credits


Pixel
This document is licensed under GFDL (GNU Free Documentation License).

Automatically generated from this file.