Using Miranda to build executable files
FIRST METHOD (using a `magic string')
Create a file (`prog' say) containing a normal miranda script, but with
the first two lines in the following form
#! /usr/bin/mira -exp
<expression>
The remainder of the file can be any legal miranda script, including
that it can be empty. Remember to give the file execute permission (by
saying `chmod +x prog'). When `prog' is executed the result will be
that the miranda expression `<expression>' is evaluated in the
environment defined by the rest of the script, and the results sent to
the standard output. Note that only a single expression is permitted,
and it must occur entirely on the second line of the file. The form of
the first line is rigid - the two initial characters must be `#!'
followed by the absolute pathname of the miranda interpreter. The flag
"-exp" is necessary and no other flags can be added.
A command of this form can take data from the terminal. The notation
`$-' can be used anywhere in the second and later lines of the file to
denote the list of characters taken from the standard input. (That is
`$-' behaves like a Miranda identifier of type [char].)
The command can be invoked with arguments, eg
prog pig 23
and the notation `$*' can be used in the script as a Miranda identifier
of type [[char]] denoting the argument list, with the convention that
the initial (zero'th) argument is the name of the command. So in this
case the value of `$*' would be
["prog","pig","23"]
Of course, if there are no arguments, `$*' will be a singleton list
containing just the command name.
Explanation
The line beginning `#!' is a standard UNIX incantation, called a `magic
string', indicating that the following pathname is to be used as a
command interpreter with the name of the file in which it occurs as its
argument (see under `execve' in section 2 of the UNIX manual). The flag
"-exp" advises the Miranda system to expect a special script, of the
above form, containing an expression to be evaluated as its second line.
[Notes
(1) In some versions of UNIX `execve' places a limit (typically 32
chars) on the total length of the `magic string'.
(2) Because the UNIX `execve' program permits at most one flag in a
magic string, it is not possible to give a `-lib' flag to mira in
conjunction with a `-exp' flag. This is a possible source of difficulty
if you keep the miralib directory at a non-standard place. One way
round this is to set the environment variable MIRALIB, instead of using
a `-lib' flag. See manual section on flags etc.]
Example
The following script is a Miranda version of the UNIX `cat' command -
if it is invoked without arguments it simply copies its standard input
to its standard output, otherwise it concatenates the contents of its
argument files to the standard output.
#! /usr/local/mira -exp
output
output = [Stdout $-], if tl $* = []
= [Stdout (concat(map read(tl $*)))], if badargs=[]
= [Stderr (concat(map errmess badargs))], otherwise
badargs = [f|f<-tl $*;~member(filemode f)'r']
errmess f = f++": cannot access\n"
See also the manual pages on input from UNIX files, output to UNIX
files, for the explanation of `read', `filemode', and the constructors
Stdout, Stderr etc.
The rule that Miranda source files must have names ending in ".m" does
not apply to scripts in this special form (in keeping with the UNIX
convention that the names of executable programs require no special
extension).
Reducing start-up time
A drawback of the way Miranda #! scripts are implemented is that such a
script is recompiled each time it is used - if the script is large this
can lead to an inconvenient delay each time the program is executed.
This can be minimised by placing as many as possible of the definitions
needed by the #! file in a separate script and %including them (see
section on library directives). These definitions will then not be
recompiled at each invocation, but retrieved from the corresponding
object code file.
Debugging stand-alone scripts
As an aid to debugging a variant flag is available:
#!/usr/bin/mira -log
<expression>
definitions...
The -log flag has the same effect as -exp but stderr is redirected to
file miralog/prog.err, where prog is the name of the script. The
redirection takes place if a miralog directory exists in the current
directory and the process running the Miranda script has write
permission to it. This is useful for debugging cgi scripts written in
Miranda, particularly in the not infrequent situation that they seem to
work fine from the command line but fail when invoked by an http call.
(You will need to create a directory miralog in cgi-bin and chown it to
apache, or whatever personality cgi scripts run as).
ALTERNATIVE METHOD (using a `here document')
Create a file ("prog' say) containing the following
mira [script] <> is in quotation marks, eg
mira [script] <<"!"
stuff
!
then no substitutions will take place inside the here-document.
The drawbacks of commands built in this way are two - (a) they have no
way of taking information from the terminal during execution (because
the here-document replaces the standard input) and (b) the method of
access to command line arguments is clumsy.