Program name: Difference between revisions

From Rosetta Code
Content added Content deleted
(Added Io)
Line 312: Line 312:
<lang factor>#! /usr/bin/env factor
<lang factor>#! /usr/bin/env factor


USING: namespaces io command-line ;
USING: io math.parser ;
IN: scriptname
IN: scriptedmain


: main ( -- ) script get print ;
: meaning-of-life ( -- n ) 42 ;

: main ( -- ) meaning-of-life "Main: The meaning of life is " write number>string print ;


MAIN: main</lang>
MAIN: main</lang>

Revision as of 01:53, 10 October 2011

Task
Program name
You are encouraged to solve this task according to the task description, using any language you may know.

The task is to programmatically obtain the name used to invoke the program. (For example determine whether the user ran "python hello.py", or "python hellocaller.py", a program importing the code from "hello.py".)

Sometimes a multiline shebang is necessary in order to provide the script name to a language's internal ARGV.

Examples from GitHub.

Ada

Being a compiled language, Ada has difficulties accessing source code filenames. But it is easy to access the executable's filename, using the function Command_Name defined in Ada.Command_Line: <lang Ada>with Ada.Command_Line, Ada.Text_IO;

procedure Command_Name is begin

  Ada.Text_IO.Put_Line(Ada.Command_Line.Command_Name);

end Command_Name;</lang>

AutoHotkey

<lang AutoHotkey> MsgBox, % A_ScriptName </lang>

BASIC

Many BASICs -- notably older DOS BASICs, and especially DOS MS BASICs -- do not provide any way to retrieve the program's name.

FreeBASIC

Unlike most MS BASICs, FreeBASIC provides a parsed version of COMMAND$ (called as COMMAND$(n)). COMMAND$(0) is the program's name: <lang qbasic>appname = COMMAND$(0)</lang>

Additionally, FreeBASIC also provides an analog of C's argc/argv[], called __FB_ARGC__ and __FB_ARGV__. __FB_ARGV__ can be used to get the program's name like this: <lang qbasic>appname = *__FB_ARGV__(0)</lang>

See also #PowerBASIC, #Visual Basic.

C

It might not be very useful for a C program to access source filenames, because C code must be compiled into an executable, and anything could have happened to the source file after the compilation. However, C can access the executable's name in argv[0].

  • argv[0] might be the name of an executable in the PATH, or it might be an absolute or relative path to the executable. At least with Unix, the parent process can set argv[0] to any string, so argv[0] might not be the real name. It is best to pretend that argv[0] has the correct value, but mind that argv[0] might not be an actual file.

<lang c>#include <stdio.h>

int main(int argc, char **argv) { printf("Executable: %s\n", argv[0]);

return 0; }</lang>

To get the source information about some part of code, use compiler defined macros. Most compilers support them or some variation of. <lang c>#include <stdio.h>

int main() { printf("This code was in file %s in function %s, at line %d\n",\ __FILE__, __FUNCTION__, __LINE__); return 0; }</lang>

BSD

BSD provides two more ways to get the program's name.

  1. __progname is the filename from argv[0] (so if argv[0] is a path, then __progname is only the filename). No header file declares __progname, so programs must declare extern char __progname; to use it.
  2. p_comm always gives the real filename of the executable, even if argv[0] has a different name. p_comm is a field in the process information. Tools like ps(1) and top(1) use p_comm, but almost no other program uses p_comm, because the API is so difficult.

Build the next program with make myname LDLIBS=-lkvm

Library: BSD libc
Works with: OpenBSD version 4.9

<lang c>/* myname.c */

  1. include <sys/param.h>
  2. include <sys/sysctl.h> /* struct kinfo_proc2 */
  3. include <err.h>
  4. include <fcntl.h> /* O_RDONLY */
  5. include <kvm.h>
  6. include <limits.h> /* _POSIX2_LINE_MAX */
  7. include <stdio.h>

int main(int argc, char **argv) { extern char *__progname; /* from crt0.o */

struct kinfo_proc2 *procs; kvm_t *kd; int cnt; char errbuf[_POSIX2_LINE_MAX];

printf("argv[0]: %s\n", argv[0]); printf("__progname: %s\n", __progname);

kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf); if (kd == NULL) errx(1, "%s", errbuf); procs = kvm_getproc2(kd, KERN_PROC_PID, getpid(), sizeof procs[0], &cnt); if (procs == NULL) errx(1, "%s", kvm_geterr(kd)); if (cnt != 1) errx(1, "impossible");

printf("p_comm: %s\n", procs[0].p_comm);

kvm_close(kd); return 0; }</lang>

The program can have three different names!

$ perl -e 'exec {"./myname"} "/nobin/fakename"' 
argv[0]: /nobin/fakename
__progname: fakename
p_comm: myname

Windows

GetModuleFileName, from the Win32 API, provides the correct path to the current executable file.

Library: Win32

<lang c>#include <windows.h>

  1. include <stdlib.h>
  2. include <wchar.h>

/*

* Returns the path to the current executable file, in a newly
* allocated buffer. Use free() to free it.
*/

wchar_t * exepath(void) { wchar_t *buf, *newbuf; long blen, flen;

/* * Most paths fit in MAX_PATH == 260 characters, but very * long UNC paths might require a larger buffer. */ buf = NULL; for (blen = MAX_PATH; 1; blen += MAX_PATH) { /* Enlarge buffer. */ newbuf = realloc(buf, blen * sizeof buf[0]); if (newbuf == NULL) { free(buf); return NULL; } buf = newbuf;

flen = GetModuleFileNameW(NULL, buf, blen); if (flen == 0) { free(buf); return NULL; } if (flen < blen) return buf; } }

/*

* Print the path to this executable.
*/

int main() { wchar_t *path;

path = exepath(); if (path == NULL) { wprintf(L"Sorry, an error occured.\n"); return 1; }

wprintf(L"Path to executable: %ls\n", path);

free(path); return 0; }</lang>

Path to executable: C:\Users\kernigh\Documents\field\scratch.exe

C++

C++ has difficulty accessing source code filenames, because C code must be compiled into an executable. However, C++ can access the executable's filename.

<lang cpp>#include <iostream>

using namespace std;

int main(int argc, char **argv) { char *program = argv[0]; cout << "Program: " << program << endl;

return 0; }</lang>

C#

This effectively outputs the executable name, file path, and any arguments for the current program. <lang csharp>using System; namespace ProgramName { class Program { static void Main(string[] args) { Console.Write(Environment.CommandLine); } } }</lang> In a C# application with a reference to System.Windows.Forms, the following can be used to retrieve the executable name and arguments without the full path. <lang csharp>using System; namespace ProgramName { class Program { static void Main(string[] args) { // Extracts the filename from the full path System.IO.FileInfo exeInfo = new System.IO.FileInfo(System.Windows.Forms.Application.ExecutablePath); Console.Write(exeInfo.Name);

// Writes all arguments to the console foreach (string argument in args) { Console.Write(" " + argument); } } } }</lang>

Clojure

If the shebang is used to run the script directly, this prints the script name. Otherwise, it prints nil.

<lang clojure>":";exec clj -m `basename $0 .clj` $0 ${1+"$@"} ":";exit

(ns scriptname (:gen-class))

(defn -main [& args] (def program (nth args 0)) (println "Program:" program))</lang>

Common Lisp

Shebangs require a special tweak to ~/.clisprc.lisp.

<lang lisp>;;; Play nice with shebangs (set-dispatch-macro-character #\# #\!

(lambda (stream character n)
 (declare (ignore character n))
 (read-line stream nil nil t)
 nil))</lang>

<lang lisp>#!/bin/bash

  1. |

exec clisp -q -q $0 $0 ${1+"$@"} exit |#

Usage
./scriptname.lisp

(defun main (args)

(let ((program (car args)))
 (format t "Program: ~a~%" program)
 (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>

D

Will print name of executable. <lang d>import std.stdio;

void main(string[] args) {

   writeln(args[0]);	

}</lang>

Emacs Lisp

<lang lisp>:;exec emacs -batch -l $0 -f main $*

Shebang from John Swaby
http://www.emacswiki.org/emacs/EmacsScripts

(defun main ()

(let ((program (nth 2 command-line-args)))
 (message "Program: %s" program)))</lang>

Erlang

Erlang's macros hold information about the running module.

<lang erlang>-module(scriptname).

main(_) -> Program = ?FILE, io:format("Program: ~s~n", [Program]).</lang>

Euphoria

<lang euphoria>constant cmd = command_line() puts(1,cmd[2])</lang>

Factor

<lang factor>#! /usr/bin/env factor

USING: io math.parser ; IN: scriptedmain

meaning-of-life ( -- n ) 42 ;
main ( -- ) meaning-of-life "Main: The meaning of life is " write number>string print ;

MAIN: main</lang>

Go

Prints the executable's filename. <lang go>package main

import ("os"; "fmt")

func main() { program := os.Args[0] fmt.Println(program) }</lang>

Haskell

Haskell has an impure function for this.

<lang haskell>#!/usr/bin/env runhaskell

module ScriptName where

import System (getProgName)

main :: IO () main = do program <- getProgName putStrLn $ "Program: " ++ program</lang>

Icon and Unicon

<lang Icon>procedure main() write(&progname) # obtain and write out the program name from the keyword &progname end</lang>

Io

<lang io>#!/usr/bin/env io

program := System args at(0)

("Program: " .. program) println</lang>

J

<lang j> >0{ARGV</lang>

Java

On one hand, this task is trivial for Java. Java code is (usually) compiled into bytecode as class files. There is exactly one class file per class, named <class name>.class (regardless of what the original source files were called or how classes were organized in the source). One executes Java code by executing some class which contains a main method, by running the command java <class name> <possible arguments>. Hence, it is guaranteed that the "name" of the executable is the class name (possibly prepended by package names, using the usual Java dot notation); and this is known in the main method at the time the code is written because it is the very class that the main method is in. Hence, the complicated solutions listed in this section do not gain anything that is not already known by the programmer at the time the code is written.

However, it is tedious to hard-code the class names if you need to do this in a lot of Java programs. Thus, a more interesting task is to write a snippet of Java code which, without modification, can be copy-and-pasted into the main method of any class and retrieve the class name. This is not trivial because in Java there is no way to use this in a static method to get the class it's in. Listed below are several notable, commonly-cited solutions for this.

You can get the listing of the arguments to the java command through a system property. The first one is the name of the main class that was run. This depends on a system property named "sun.java.command", which might not exist on all Java virtual machines. <lang java>public class ScriptName { public static void main(String[] args) { String program = System.getProperty("sun.java.command").split(" ")[0]; System.out.println("Program: " + program); } }</lang>

An alternate solution is to create a dummy inner class, and then retrieve its enclosing class (which is the class the main method is in) through reflection: <lang java>public class ScriptName { public static void main(String[] args) { Class c = new Object(){}.getClass().getEnclosingClass(); System.out.println("Program: " + c.getName()); } }</lang>

A solution using the security manager: <lang java>public class ScriptName { public static void main(String[] args) { Class c = System.getSecurityManager().getClassContext()[0]; System.out.println("Program: " + c.getName()); } }</lang>

A solution using the stack trace (requires Java 1.5+): <lang java>public class ScriptName { public static void main(String[] args) { String program = Thread.currentThread().getStackTrace()[1].getClassName(); System.out.println("Program: " + program); } }</lang>

JavaScript

Works with: Node.js

Node.js has a global variable for this.

<lang javascript>#!/usr/bin/env node /*jslint nodejs:true */

function main() { var program = __filename; console.log("Program: " + program); }

if (!module.parent) { main(); }</lang>

LLVM

Like C, LLVM can use argv to access the executable's filename.

<lang sh>$ make llvm-as scriptname.ll llc scriptname.bc gcc -o scriptname scriptname.s ./scriptname Program: ./scriptname</lang>

Makefile

<lang make>all: scriptname.ll llvm-as scriptname.ll llc scriptname.bc gcc -o scriptname scriptname.s ./scriptname

clean: -rm scriptname -rm scriptname.s -rm scriptname.bc</lang>

<lang llvm>@msg_main = internal constant [13 x i8] c"Program: %s\0A\00"

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

define i32 @main(i32 %argc, i8** %argv) { %program = load i8** %argv call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([13 x i8]* @msg_main, i32 0, i32 0), i8* %program)

ret i32 0 }</lang>

Lua

Lua's arg is like C's argv.

<lang lua>#!/usr/bin/env lua

function main(arg) local program = arg[0] print("Program: " .. program) end

if type(package.loaded[(...)]) ~= "userdata" then main(arg) else module(..., package.seeall) end</lang>

newLISP

newLISP has a function, (main-args int) for this.

<lang lisp>#!/usr/bin/env newlisp

(let ((program (main-args 1)))

 (println (format "Program: %s" program))
 (exit))</lang>

OCaml

<lang ocaml>let _ = let program = Sys.argv.(0) in print_endline ("Program: " ^ program)</lang>

Octave

<lang octave>function main() program = program_name(); printf("Program: %s", program); endfunction

main();</lang>

Perl

<lang perl>#!/usr/bin/env perl

use strict; use warnings;

sub main { my $program = $0; print "Program: $program\n"; }

unless(caller) { main; }</lang>

Perl 6

In Perl 6, the name of the program being executed is in the special global variable $*PROGRAM_NAME. <lang perl6>say $*PROGRAM_NAME;</lang>

PHP

PHP has a global dictionary for this.

<lang php><?php $program = $_SERVER["SCRIPT_NAME"]; echo "Program: $program\n"; ?></lang>

PicoLisp

The function 'cmd' returns the command name. <lang PicoLisp>: (cmd) -> "/usr/bin/picolisp"</lang>

PowerBASIC

Previous versions of PowerBASIC (PB/Win 8 or older; PB/CC 4 or older) have to make an API call:

<lang powerbasic>#INCLUDE "Win32API.inc" '[...] DIM fullpath AS ASCIIZ * 260, appname AS STRING GetModulefullpathA 0, fullpath, 260 IF INSTR(fullpath, "\") THEN

   appname = MID$(fullpath, INSTR(-1, fullpath, "\") + 1)

ELSE

   appname = fullpath

END IF</lang>

Works with: PowerBASIC for Windows version 9
Works with: PowerBASIC Console Compiler version 5

Recent versions of PowerBASIC provide the EXE object; EXE.NAME$ returns the program's name, while EXE.NAMEX$ returns the program's name and extension. (EXE.EXTN$ returns the extension only.) So, to get the program's name, we do this: <lang powerbasic>appname = EXE.NAMEX$</lang>

Python

Python has at least two ways to get the script name: the traditional ARGV and the inspect module.

<lang python>#!/usr/bin/env python

import sys

def main(): program = sys.argv[0] print "Program: %s" % program

if __name__=="__main__": main()</lang>


<lang python>#!/usr/bin/env python

import inspect

def main(): program = inspect.getfile(inspect.currentframe()) print "Program: %s" % program

if __name__=="__main__": main()</lang>

R

R's syntax is complicated, but doable.

<lang R>#!/usr/bin/env Rscript

getProgram <- function(args) { sub("--file=", "", args[grep("--file=", args)]) }

args <- commandArgs(trailingOnly = FALSE) program <- getProgram(args)

cat("Program: ", program, "\n")

q("no")</lang>

REXX

The Rexx PARSE SOURCE instruction parses data describing the source of the program running. The language processor returns a string that does not change while the program is running. The source string contains operating system name, followed by either COMMAND, FUNCTION, SUBROUTINE, or METHOD, depending on whether the program was called as a host command or from a function call in an expression or using the CALL instruction or as a method of an object. These two tokens are followed by the complete path specification of the program file.

<lang REXX>/* Rexx */

Parse source . . pgmPath Say pgmPath </lang>

Output
$ rexx RProgramName.rex
/tmp/RProgramName.rex

REXX does not support the use of arg(0) to access the program name. A workaround is to use a shell wrapper script to obtain and provide the invocation name of the wrapper:

<lang sh>#!/bin/sh rexxbit.rexx $0 $*</lang>

Here is a rexx script that makes use of this:

<lang rexx>say "The program is called " arg(1)</lang>

Ruby

<lang ruby>#!/usr/bin/env ruby

puts "Path: #{$0}" puts "Name: #{File.basename $0}"</lang>

For example,

$ ruby script.rb                                                               
Path: script.rb
Name: script.rb
$ ruby ../rc/script.rb
Path: ../rc/script.rb
Name: script.rb
$ ruby -e 'load "script.rb"'
Path: -e
Name: -e

Scheme

Works with: Chicken Scheme

Getting the program name is tricky. When interpreted, the script name will be printed. When compiled, the executable name will be printed.

<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) (let ((prog (cdr (program)))) (display (format "Program: ~a\n" prog)) (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>

Seed7

The function path(PROGRAM) returns the path of the file executed. When the program is interpreted this is the path of the source file. When the program is compiled this is the path of the executable. The functions dir(PROGRAM) and file(PROGRAM) deliver the directory respectivly file name of the program path. <lang seed7>$ include "seed7_05.s7i";

const proc: main is func

 local
   var integer: i is 0;
 begin
   writeln("Program path:      " <& path(PROGRAM));
   writeln("Program directory: " <& dir(PROGRAM));
   writeln("Program file:      " <& file(PROGRAM));
 end func;</lang>

Output when the program is interpreted:

Program path:      /home/anyuser/seed7_5/prg/programname.sd7
Program directory: /home/anyuser/seed7_5/prg
Program file:      programname.sd7

Output when the program is compiled:

Program path:      /home/anyuser/seed7_5/prg/programname
Program directory: /home/anyuser/seed7_5/prg
Program file:      programname

Smalltalk

Note that this only works when run as "./scriptname.st", because the shebang must force the script name onto ARGV.

<lang smalltalk>"exec" "gst" "-f" "$0" "$0" "$@" "exit"

| program |

program := Smalltalk getArgv: 1.

Transcript show: 'Program: ', program; cr.</lang>

Standard ML

<lang sml>#!/usr/bin/env sml

let val program = CommandLine.name () in print ("Program: " ^ program ^ "\n") end;</lang>

Tcl

<lang tcl>#!/usr/bin/env tclsh

proc main {args} {

   set program $::argv0
   puts "Program: $program"

}

if {$::argv0 eq [info script]} {

   main {*}$::argv

}</lang>

UNIX Shell

Works with: Bourne Shell

<lang bash>#!/bin/sh

echo "Program: $0"</lang>

Visual Basic

Visual Basic provides the App object, which has a property called EXEName that contains the program's filename without the extension. (For most uses, this doesn't matter, but for code shared between, for example, a program and a screensaver, it can be important.) So, if a program is called "MyVBapp.exe", retreiving the value of App.EXEName would look like this: <lang vb>appname = App.EXEName 'appname = "MyVBapp"</lang>

Alternately, Visual Basic can make an API call: <lang vb>Declare Function GetModuleFileName Lib "kernel32" Alias "GetModuleFileNameA" (ByVal hModule As Long, ByVal lpFileName As String, ByVal nSize As Long) As Long Dim fullpath As String * 260, appname As String, namelen As Long namelen = GetModuleFileName (0, fullpath, 260) fullpath = Left$(fullpath, namelen) If InStr(fullpath, "\") Then

   appname = Mid$(fullpath, InStrRev(fullpath, "\") + 1)

Else

   appname = fullpath

End If</lang>