App-sh2p
view release on metacpan or search on metacpan
lib/App/sh2p.pod view on Meta::CPAN
Shell functions can only return values between 0 and 255. A common technique
for returning a string is to 'echo' or 'print' the string to STDOUT, then
call the function in back-ticks (or $(...)), which, in a decent shell, should
not produce a child process. This is inappropriate in Perl and the subroutine
return value should be revised. This cannot reasonably be automated (that is to say
I haven't figured it out yet).
=head3 Writing dir/name.here
See 'Here documents' (below)
=head3 Heredoc replaced by simple redirection
See 'Here documents' (below)
=head3 No conversion routine for <name>
=head3 Pipeline detected
=head3 trap signal calling sh2p_signal_handler
Comment that a signal handler has been invoked. See trap below.
=head3 Subshell: subshell list
Subshells should not create a child process if possible, and alterations to the environment
should not affect the 'parent'. Shells do that using an environment stack, sh2p does it using
'local'. However there are other implications, so the generated code should be inspected.
=head3 Using $PWD is unsafe: use Cwd::getcwd
The environment variable PWD is set when the shell built-in 'cd' is called.
This variable is only used by the shell and not reliable in any other language.
=head2 Unitialised variable
The shell defaults uninitialised variables to an empty string or zero. The conversion
does not emulate this, but leaves them as undef. The rational is that unitialised
variables are undesirable and should be fixed.
=head2 Here documents
These work in the shell by writing a temporary file and
then reading it. We use a similar method here, except the
directory used is taken from the environment variable SH2P_HERE_DIR.
If that is not set then the current directory is used.
The heredoc data is extracted from the script and written to a file named
label.here, where 'label' is the label used to identify the heredoc.
With the 'read' command, the file is read by subroutines appended to the generated script.
With heredoc's from builtins, we attempt to use simple redirection but manual intervention is required.
Currently external programs reading from a heredoc require manual intervention.
Heredocs embedded inside back-ticks (or $(..)) produce a mess (some shells have
problems with this as well).
=head2 External programs and built-ins
It is tempting to substitute Perl built-ins for external programs like chmod, rm,
and so on. However the return codes are different and require a different testing
regime. Therefore these are identified by an INSPECT message.
=head2 Functions
Functions declared externally and loaded dynamically or via '.' will not be known.
These will generally be seen as unknown commands and default to an external program,
called using system or back-ticks. However they may be declared in your script
using 'autoload' (or 'typedef -fu'), which will register them as functions with sh2p.
A function name embedded in a variable and then called using that variable will not
be detected as such and will be treated as an external command.
The 'functions' alias, and 'typedef -f', will generate code to give a list of the
subroutines in the main:: namespace (symbol table) at runtime. This will include any
imported names from external modules, and is unconnected with those known at conversion time.
Note that the value of $0 inside functions differs between shell versions. In sh2p
$0 is retained to be the name of the current run unit (program), which is the POSIX
behaviour.
The Bash specific variable FUNCNAME is converted to 'caller(0))[3]'.
There are two different syntax conventions commonly used with functions:
name () { ... } # POSIX (Bourne) syntax
function name { ... } # non-POSIX (Korn) syntax
Bash and Korn shells support both, however they differ in operation when it comes to variable scope.
As an extension to the POSIX standard, Bash and Korn shells allow local
variables to be declared using typeset, declare (Bash), or local. This is mirrored in
Perl by the 'my' perfix. Any variables not so declared are globals.
However there are issues with this. POSIX never supported this, so the POSIX
shell syntax should not support it either. Both Bash and ksh88 (the most common) do support the
declaration of local variables in both forms of syntax. Ksh93 "fixed" it by not supporting it
in the Bourne syntax ('typedef var' has no effect), but supporting it in the non-POSIX shell syntax only.
Added to that, very few people know about the capability anyway!
A similar mix exists when dealing with signal handling and the 'trap' command.
=head2 Variable scope
If the variable is new (top-down parsing) it is declared with 'my', otherwise we assume it is a global.
The current state of block nesting is tracked, so the definition of a "new" variable is one which
has not been declared in this, or a higher-level, block. This can be problematic if a variable is
used for the first time in an inner block.
For example:
case "$1" in
--new)
NEW=1
;;
--update)
NEW=0
;;
*)
echo "Usage: $0 --new|--update config-file"
exit 1
;;
( run in 0.691 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )