Modulinos
It is useful to be able to execute a main() function only when a program is run directly. This is a central feature in programming scripts; the feature is called scripted main.
Examples from GitHub.
C
C programs have scripted main by default; as long as main() is not included in the header file, this program's (empty) API is accessible by other C code.
scriptedmain.h is blank; it is included in order to show that if another C file, test.c, includes scriptedmain, scriptedmain's main() is not executed.
<lang c>#include "scriptedmain.h"
- include <stdio.h>
- include <unistd.h>
int main(int argc, char **argv) { char cwd[1024]; getcwd(cwd, sizeof(cwd));
printf("Directory: %s\n", cwd);
printf("Program: %s\n", argv[0]);
printf("Number of Args: %d\n", argc);
int i; for (i = 0; i < argc; i++) { printf("Arg: %s\n", argv[i]); }
return 0; }</lang>
C++
C++ has scripted main by default.
<lang cpp>#include <iostream>
- include <unistd.h>
using namespace std;
int main(int argc, char **argv) { char cwd[1024]; getcwd(cwd, sizeof(cwd));
cout << "Directory: " << cwd << endl;
cout << "Program: " << argv[0] << endl;
cout << "Number of Args: " << argc << endl;
int i; for (i = 0; i < argc; i++) { cout << "Arg: " << argv[i] << endl; }
return 0; }</lang>
Chicken Scheme
Chicken Scheme has the {{{ -ss }}} flag for the interpreter, but compiled Chicken Scheme programs do not have scripted main unless the behavior is added manually to the code.
<lang scheme>#!/bin/bash
- |
exec csi -ss $0 ${1+"$@"} exit |#
(use posix) (require-extension srfi-1) ; lists (require-extension srfi-13) ; strings
(define (main args) (display (format "Directory: ~a\n" (current-directory)))
(display (format "Program: ~a\n" (cdr (program))))
(display (format "Number of Args: ~a\n" (length args)))
(map (lambda (x) (display (format "Arg: ~a\n" x))) args)
(exit))
(define (program) (if (string=? (car (argv)) "csi") (let ((s-index (list-index (lambda (x) (string-contains x "-s")) (argv)))) (if (number? s-index) (cons 'interpreted (list-ref (argv) (+ 1 s-index))) (cons 'unknown ""))) (cons 'compiled (car (argv)))))
(if (equal? (car (program)) 'compiled) (main (cdr (argv))))</lang>
Common Lisp
Common Lisp has few standards for POSIX operation. Shebangs and command line arguments are hacks.
In CLISP, this code only works for ./scriptedmain.lisp.
<lang lisp>#!/bin/bash
- |
exec clisp -q -q $0 $0 ${1+"$@"} exit |#
- Usage
- ./scriptedmain.lisp
- With help from Rainer Joswig
- http://www.math.utexas.edu/pipermail/maxima/2007/006523.html
(defun main (args)
(format t "Directory: ~a~%" #+clisp (ext:cd) #+lucid (working-directory) #+allegro (excl:current-directory) #+sbcl (progn *default-pathname-defaults*) #+(or :cmucl :scl) (ext:default-directory) #+lispworks (hcl:get-working-directory) )
(format t "Program: ~a~%" (car args))
(format t "Number of Args: ~a~%" (length args))
(loop for arg in args do (format t "Arg: ~a~%" arg)) (quit))
- With help from Francois-Rene Rideau
- http://tinyurl.com/cli-args
(let ((args
#+clisp ext:*args* #+sbcl sb-ext:*posix-argv* #+clozure (ccl::command-line-arguments) #+gcl si:*command-args* #+ecl (loop for i from 0 below (si:argc) collect (si:argv i)) #+cmu extensions:*command-line-strings* #+allegro (sys:command-line-arguments) #+lispworks sys:*line-arguments-list* ))
(if (member (pathname-name *load-truename*) args :test #'(lambda (x y) (search x y :test #'equalp))) (main args)))</lang>
Emacs Lisp
Emacs has scripted main, though older versions require an obscure shebang syntax.
<lang lisp>:;exec emacs -batch -l $0 -f scripted-main $*
- Shebang from John Swaby
- http://www.emacswiki.org/emacs/EmacsScripts
(defun scripted-main ()
(message "Directory: %s" default-directory)
(message "Program: %s" (nth 2 command-line-args))
(message "Number of Args: %d" (length command-line-args)) (mapcar (lambda (x) (message "Arg: %s" x)) command-line-args))</lang>
Erlang
Erlang has scripted main by default.
<lang erlang>-module(scriptedmain). -import(lists, [map/2]).
main(Args) -> io:format("Directory: ~s~n", [filename:absname("")]), io:format("Program: ~s~n", [?FILE]), io:format("Number of Args: ~w~n", [length(Args)]), map (fun(Arg) -> io:format("Arg: ~s~n", [Arg]) end, Args).</lang>
Haskell
Haskell has scripted main by default.
<lang haskell>#!/usr/bin/env runhaskell
module ScriptedMain where
import System.Directory (getCurrentDirectory) import System (getProgName, getArgs) import Control.Monad (mapM_)
main :: IO () main = do directory <- getCurrentDirectory program <- getProgName args <- getArgs
putStrLn $ "Directory: " ++ directory putStrLn $ "Program: " ++ program putStrLn $ "Number of Args: " ++ (show . length) args mapM_ (\x -> putStrLn $ "Arg: " ++ x) args</lang>
J
Probably the simplest way to achive what I imagine "scripted main" to be, in J, involves the use of the Immex Phrase. Here, just before the script ends, you define the "main" which would take control if the script was used as a stand alone program.
Here is an example "scripted main" program, using this approach:
<lang j>NB. example "scripted main" code, saved as sm.ijs myName=: 'My name is George' 9!:29]1 9!:27'smoutput myName'</lang>
Here is an example consumer, which is another "scripted main" program:
<lang j>NB. example "alternate main" code require'sm.ijs' 9!:29]1 9!:27'smoutput length: ,":#myName'</lang>
Here is another example consumer. This example is library code, without any main:
<lang j>NB. example "non main" library code require'sm.ijs' 9!:29]0 reversed=:|.myName</lang>
Java
Java has scripted main by default.
<lang java>public class ScriptedMain {
public static void main(String[] args) { System.out.println("Directory: " + ScriptedMain.class.getProtectionDomain().getCodeSource().getLocation().getPath());
System.out.println("Program: " + ScriptedMain.class.getName());
System.out.println("Number of Args: " + args.length);
for (int i = 0; i < args.length; i++) { System.out.println("Arg: " + args[i]); } }
}</lang>
Lua
Lua has scripted main by default, using an obscure syntax (an ellipsis of all things).
<lang lua>#!/usr/bin/env lua
os = require("os")
function main(arg) print("Directory: " .. os.execute("pwd"))
print("Program: " .. debug.getinfo(1).source)
print("Number of Args: " .. #arg)
for i,a in ipairs(arg) do print("Arg: " .. a) end
end
if type(package.loaded[(...)]) ~= "userdata" then main(arg) else module(..., package.seeall) end</lang>
newLISP
newLISP lacks scripted main, but the feature is easily added.
<lang lisp>#!/usr/bin/env newlisp
(context 'SCRIPTED-MAIN)
(define (main) (println "Directory: " (real-path))
(println "Program: " (main-args 1))
(println "Number of Args: " (length (main-args)))
(map (lambda (x) (println "Arg: " x)) (main-args))
(exit))
(if (find "scriptedmain" (main-args 1)) (main))
(context MAIN)</lang>
Octave/MATLAB
Octave and MATLAB have scripted main by default, because only the first function listed in a program are importable by other programs. The scriptedmain() function is just filler.
<lang matlab>#!/usr/bin/env octave -qf
function scriptedmain() endfunction
function main() printf("Directory: %s\n", pwd()); printf("Program: %s\n", program_name()); printf("Number of Args: %d\n", nargin);
args = argv();
for i = 1:nargin printf("Arg: %s\n", args{i}); endfor
endfunction
main();</lang>
Perl
Perl has scripted main.
<lang perl>#!/usr/bin/env perl
use strict; use Cwd qw(getcwd);
sub main { print "Dirctory: " . getcwd . "\n";
print "Program: $0\n";
print "Number of Args: " . ($#ARGV + 1) . "\n";
foreach my $i (0 .. $#ARGV) { print "Arg: $ARGV[$i]\n"; } }
unless(caller) { main; }</lang>
PHP
PHP does not have scripted main, but the feature is easily added with a regular expression.
<lang php><?php function main($args) { echo "Directory: " . getcwd() . "\n";
echo "Program: " . $_SERVER["SCRIPT_NAME"] . "\n";
echo "Number of Args: " . count($args) . "\n";
foreach($args as $arg) { echo "Arg: $arg\n"; } }
if (preg_match("/scriptedmain/", $_SERVER["SCRIPT_NAME"])) { main($argv); } ?></lang>
Python
Python has scripted main.
<lang python>#!/usr/bin/env python
import os, sys
def main(): print "Directory: " + os.getcwd()
print "Program: " + sys.argv[0]
print "Number of Args: %d" % len(sys.argv)
for arg in sys.argv: print "Arg: " + arg
if __name__=="__main__": main()</lang>
R
R does not have scripted main, but the feature is easily added with regular expressions.
<lang R>#!/usr/bin/Rscript
getProgram <- function(args) { sub("--file=", "", args[grep("--file=", args)]) }
main <- function(program, args) { cat("Directory: ", getwd(), "\n")
cat("Program: ", program, "\n")
cat("Number of Args: ", length(args), "\n")
for (arg in args) { cat("Arg: ", arg, "\n") } }
args <- commandArgs(trailingOnly = FALSE) program <- getProgram(args)
if (length(program) > 0 && length(grep("scriptedmain", program)) > 0) { main(program, args) }
q("no")</lang>
Ruby
Ruby has scripted main by default.
<lang ruby>#!/usr/bin/env ruby
def main puts "Directory: #{Dir.pwd}"
puts "Program: #{$0}"
puts "Number of Args: #{ARGV.length}"
ARGV.each { |arg| puts "Arg: #{arg}" } end
if __FILE__ == $0 main end</lang>
Tcl
<lang tcl>proc main {args} {
puts "Directory: [pwd]" puts "Program: $::argv0" puts "Number of args: [llength $args]" foreach arg $args {puts "Arg: $arg"}
}
if {$::argv0 eq [info script]} {
main {*}$::argv
}</lang>
UNIX Shell
Bash has scripted main.
<lang sh>#!/usr/bin/env sh
main() { echo "Directory: " `pwd`
echo "Program: $0"
echo "Number of Args: $#"
for arg in $*; do echo "Arg: $arg" done }
- From Dennis Williamson
- http://stackoverflow.com/questions/2683279/#2687092
if $_ == $0 ; then main fi</lang>