On 12 December 2010 Patrick Gundlach wrote:
> Hello Reinhard,
>
> > these are two different questions. First, the #! line works
> > everywhere except on Windows. It finds the interpreter (not your
> > script) in PATH. There is no reasonable alternative on Windows.
> > You have to associate filename extensions with interpreters in
> > the registry. If you are using TeX Live, you can start your
> > script from a wrapper instead.
>
> OK, thanks.
>
> > Try this:
> > -------------------------------------------------------
> > #!/usr/bin/env texlua
> >
> > dirname, filename = string.match(arg[0], '(.*[/\\])(.*)')
> >
> > print('dirname='..dirname)
> > print('filename='..filename)
> > -------------------------------------------------------
> >
> > it works as expected on Unix:
> >
>
> On every Unix? I once tried this with sh (echo $0) and if I
> remember correctly it gave me a relative path on solaris and an
> absolute path on linux.
Hi Patrick,
it depends on how you invoke the program. If you specify a path on
the command line, this path is used. It might be absolute or relative
to $PWD. For instance:
$ /usr/local/bin/testarg0.lua
dirname=/usr/local/bin/
$ ../../../../usr/local/bin/testarg0.lua
dirname=../../../../usr/local/bin/
If you don't specify a path, /usr/bin/env searches the binary in PATH.
$ testarg0.lua
dirname='/usr/local/bin/'
I assume that /usr/bin/env is available on all Unix systems. I've
read somewhere that some shells require a space after #! but it seems
that it's not required on the Unix supported by TeX Live.
I'm wondering why you prefer an absolute path. It actually doesn't
matter. You can write
dirname = string.match(arg[0], '(.*[/\\])(.*)')
package.path = dirname .. "../modules/"
require "mylib"
and mylib.lua will be found regardless whether the path to the program
is absolute or relative.
> > You will certainly get similar results in TeX Live
>
> I don't use TeXlive in this case, just one LuaTeX binary for luatex
> and texlua.
>
> > because the location of your script is determined by the wrapper,
> > and hence by kpathsea, which returns the full path. Please note
> > that dirname found by string.match() in the example above
> > contains the leading directory separator already and that
> > backslashes are supported too.
>
> So I assume from your answer that arg[0] in my lua skript is set by
> kpathsea, and it contains the full path. So I can find out where I
> am by looking at it?
Sorry, I was quite unprecise. kpathsea is only involved if the script
is launched by a wrapper and the wrappers are only for Windows. They
are needed because there are no symlinks on Windows and because we
have to set a few environment variables for the hidden Perl and
Ghostscript before launching a script.
If you want to provide a tiny distribution for several platforms, you
can steal some stuff from TeX Live. One nice thing is that, if you
use the wrappers, you don't have to put anything into the registry.
All you have to do is to add bin/win32 to PATH. The wrappers are
explained in detail in bin/win32/runscript.tlu.
There is one thing which can cause trouble. Sorry that it didn't come
earlier to my mind. Because runscript is mostly written in texlua, it
doesn't invoke Lua scripts as usual. For efficiency, it determines
the location of the script and then runs the Lua function dofile().
I don't know which impact this has on arg[0], but, if necessary, you
can always change runscript.tlu so that it invokes Lua scripts as it
invokes Perl scripts, i.e. with os.spawn(). It's advantageous, at
least, that the wrappers are written in a scripting language and can
easily be adapted. Below is an excerpt from runscript.tlu.
Regards,
Reinhard
Script wrappers in TeX Live on Windows
Rationale
Wrappers enable use of scripts on Windows as regular programs.
They are also required for some binary programs to set up the
right environment for them.
Batch scripts can be used for wrapping but they are not as universal
as binaries (there are some odd cases where they don't work) and
it is hard to make them robust and secure. Compiled binary wrappers
don't suffer from these problems but they are harder to write, debug
and maintain in comparison to scripts. For these reasons a hybrid
approach is taken that combines a binary stub with a launcher script.
Adding wrappers for user scripts
The script wrapping machinery is not limited to scripts shipped with
TeX Live. You can also use it for script programs from manually
installed packages, which should minimize the problems when using
them with TeX Live.
First, make sure that there is an interpreter program available on
your system for the script you want to use. Interpreters for Perl
and Lua are bundled with TeX Live, all others have to be installed
independently. Lua scripts are the most efficient to run, so if you
consider writing a new script, that would be the recommended choice.
The following script types and their file extensions are currently
supported and searched in that order:
Lua (.tlu;.texlua;.lua) -- included
Perl (.pl) -- included
Ruby (.rb) -- requires installation
Python (.py) -- requires installation
Tcl (.tcl) -- requires installation
Java (.jar) -- requires installation
VBScript (.vbs) -- part of Windows
JScript (.js) -- part of Windows
Batch (.bat;.cmd) -- part of Windows
Finally, Unix-style extensionless scripts are searched as last and
the interpreter program is established based on the she-bang (#!)
specification on the very first line of the script. This can be
an arbitrary program but it must be present on the search path.
Next, the script program needs to be installed somewhere below the
'scripts' directory under one of the TEXMF trees (consult the
documentation or texmf/web2c/texmf.cnf file for a list). You may
need to update the file search database afterwards with:
mktexlsr [TEXMFDIR]
It is also possible to use scripts that are outside of TEXMF hierarchy
by adjusting TEXMFSCRIPTS environment or kpathsea variable, see
kpathsea documentation for more information on setting its variables.
Test if the script can be located with:
kpsewhich --format=texmfscripts <script-name>.<ext>
This should output the full path to the script if everything is
properly installed and configured. If this test is successful,
the script can be run immediately with:
runscript <script-name> [script arguments]
If you prefer to call the script program simply by its name, copy
and rename bin/win32/runscript.exe to <script-name>.exe and put it
in bin/win32/ directory of your TeX Live installation or, if you
don't have the write permissions there, somewhere else on the search
path.]]
local docstr = [[
Wrapper structure
Wrappers consist of small binary stubs and a common texlua script.
The binary stubs are all the same, just different names (but CLI
and GUI stubs differ, see below, and GUI stubs are actually all
different due to different embedded icons).
The job of the binary stub is twofold: (a) call the texlua launcher
script 'runscript.tlu' from the same directory (or more precisely
from the directory containing 'runscript.dll') and (b) pass to it
argv[0] and the unparsed argument string as the last two arguments
(after adding a sentinel argument, which ends with a new line
character). Arbitrary C strings can be passed, because the script
is executed by linking with luatex.dll and calling the lua
interpreter internally rather than by spawning a new process.
There are two flavours of the binary stub: one for CLI programs
and another one for GUI programs. The GUI variant does not open
a console window nor does it block the command prompt if started
from there. It also uses a dialog box to display an error message
in addition to outputting to stderr.
The stubs are further split into a common DLL and EXE proxies
to it. This is for maintenance reasons - updates can be done by
replacement of a single DLL rather than all binary stubs.
The launcher script knows, which variant has been used to invoke it
based on the sentinel argument. The lack of this argument means
that it was invoked in a standard way, i.e. through texlua.exe.
All the hard work of locating a script/program to execute happens
in the launcher script. The located script/program is always
executed directly by spawning its interpreter (or binary) in a new
process. The system shell (cmd.exe) is never called (except for
batch scripts, of course). If the located script happens to be
a (tex)lua script, it is loaded and called internally from within
this script, i.e. no new process is spawned. Execution is done
using a protected call, so any compile or runtime errors are catched.
Source files
runscript.tlu launcher script for locating and dispatching
target scripts/programs
runscript_dll.c common DLL part of the binary stubs; locates and
calls the launcher script
runscript_exe.c EXE proxy to the common DLL for CLI mode stubs
wrunscript_exe.c EXE proxy to the common DLL for GUI mode stubs
--
----------------------------------------------------------------------------
Reinhard Kotucha Phone: +49-511-3373112
Marschnerstr. 25
D-30167 Hannover mailto:[email protected]
----------------------------------------------------------------------------
Microsoft isn't the answer. Microsoft is the question, and the answer is NO.
----------------------------------------------------------------------------
_______________________________________________
dev-luatex mailing list
[email protected]
http://www.ntg.nl/mailman/listinfo/dev-luatex