Modulinos

From Rosetta Code
Modulinos is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

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 cannot do scripted main, because main() is implicitly included by another program, test.c, even when scriptedmain.h is empty.

The following example will not work with another program, test.c, due to duplicate main() functions at compile time.

<lang c>#include "scriptedmain.h"

  1. include <stdio.h>
  2. 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++ programs cannot do scripted main, because main() is implicitly included by another program, test.c, even when scriptedmain.h is empty.

The following example will not work with another program, test.c, due to duplicate main() functions at compile time.

<lang cpp>#include <iostream>

  1. 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

  1. |

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

  1. |

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, but not for compiled scripts. This is because the primary script must be a module Main, creating a name conflict.

<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>

LLVM

LLVM has scripted main by default.

<lang llvm>@msg_directory = internal constant [15 x i8] c"Directory: %s\0A\00" @msg_program = internal constant [13 x i8] c"Program: %s\0A\00" @msg_argc = internal constant [20 x i8] c"Number of Args: %d\0A\00" @msg_arg = internal constant [10 x i8] c"Arg = %s\0A\00"

declare i32 @printf(i8* noalias nocapture, ...) declare i8* @getcwd(i8*, i32)

define i32 @main(i32 %argc, i8** %argv) { %cwd = alloca [1024 x i8]

%cwd_ptr = getelementptr inbounds [1024 x i8]* %cwd, i32 0, i32 0

call i8* @getcwd(i8* %cwd_ptr, i32 1024)

call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @msg_directory, i32 0, i32 0), i8* %cwd_ptr)

%program_ptr = getelementptr inbounds i8** %argv, i32 0

%program = load i8** %program_ptr

call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([13 x i8]* @msg_program, i32 0, i32 0), i8* %program)

call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([20 x i8]* @msg_argc, i32 0, i32 0), i32 %argc)

%i = alloca i32 store i32 0, i32* %i br label %for_args

for_args:

%i_val = load i32* %i

%arg_ptr = getelementptr inbounds i8** %argv, i32 %i_val %arg = load i8** %arg_ptr call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @msg_arg, i32 0, i32 0), i8* %arg)

%new_i_val = add i32 %i_val, 1 store i32 %new_i_val, i32* %i

%more_args = icmp slt i32 %new_i_val, %argc br i1 %more_args, label %for_args, label %end_for_args

end_for_args:

ret i32 0 }</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 }

  1. From Dennis Williamson
  2. http://stackoverflow.com/questions/2683279/#2687092

if $_ == $0 ; then main fi</lang>