The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Batch::Interpreter - interpreter for CMD.EXE batch files

VERSION

Version 0.01

SYNOPSIS use Batch::Interpreter;

        open my $fh, '<:crlf', $ARGV[0]
                or die "$ARGV[0]: $!";

        my $rc = Batch::Interpreter->new(
                locale => 'de_DE',
                # more settings, see below
        )->run({}, [ <$fh> ], @ARGV);

METHODS

->new(%settings)

Create an instance of the class, which can be custimized with the following parameters (values for keys of %settings):

Customization and Behavior

filenames => $self->default_filenames

A Hash with the mapping of emulated filenames to host filenames, the default likely contains the entry NUL => '/dev/null'.

mountpoints => []

Mapping of emulated mount points (in most cases: drives) to host directories. The entries are scanned in order. Example: 'D:\' => '/mnt/data'.

remote_names => []

Mapping of emulated directories to remote names, for prompt $M.

extension_handlers => $self->builtin_extension_handlers

The list of handlers for file extensions. See chapter 'Extension Handlers' for the call interface.

internal_commands => $self->builtin_internal_commands

The list of handlers for internal commands, i.e. commands handled by CMD.EXE. See chapter 'Command Handlers' for the call interface.

external_commands => $self->builtin_external_commands

The list of handlers for external commands, i.e. command line tools. See chapter 'Command Handlers' for the call interface.

locale

The locale, see chapter LOCALES.

Interpreter State

echo => 1

State of the ECHO setting, 0 = OFF, 1 = ON.

exit_value => 0

%ERRORLEVEL%.

extensions => 1

State of SETLOCAL ENABLEEXTENSIONS / DISABLEEXTENSIONS, 0 = DISABLE, 1 = ENABLE. .

Extensions are always enabled, but the state variable is maintained correctly.

delayedexpansion => 1

State of SETLOCAL ENABLEDELAYEDEXPANSION / DISABLEDELAYEDEXPANSION, 0 = DISABLE, 1 = ENABLE.

vars => {}

The values of the environment variables. Due to the case insensitivity all keys are in CAPS, while the real case of the variable names is stored in varcases under the same key.

varcases => { map((uc $_ => $_), keys %{$self->{vars}}), %{$self->default_variable_cases} }

See vars.

Defaults and Constants

version_string => __PACKAGE__." $VERSION"

The string for prompt $V and the ver command.

default_drive => 'C'

The default drive. Per default a mountpoint for this drive is generated.

default_pathext => '.COM;.EXE;.BAT'

The default, if %PATHEXT% is unset.

User Interface

terminal => undef

An optional instance of Term::ReadLine or any other class that supports the ->readline($prompt) method.

Tracing and Verbosity

dump_parse_tree => undef

Dump parse tree of parsed command before execution.

verbose_system => undef

Print command lines before calling system() for external commands.

->run($attr, $lines, @arg)

Run the interpreter. If given, $lines is an ArrayRef of the lines of the script, else the commands are read from the terminal (as set in the contructor). The arguments of the script can be passed in @arg. Per default the arguments have to be unquoted, like in perl's @ARGV -- in this case a realistically looking quoting is added internally.

$attr has the keys

quoted_arguments => undef

Set to true, if @arg contains quoted arguments. In this case the values in @arg have to be quoted like under the emulated system. Specifically, they have to look like the return value of the internal function next_token(), i.e. trailing blanks are mandatory for all but the last argument. In this case the arguments can be used as-is.

CUSTOMIZATION

Extension Handlers

Extension handlers are CodeRefs, that are called with the arguments:

        my $ret = $handler->($self, $command, \@arg, $qcommand, \@qarg);

$self is the interpreter instance, $command is the name of the command (i.e. the key the handler was found under in the handler hash), @arg is the array of unquoted command line arguments. $$qcommand and @qarg and $args are the raw forms of $command and @arg, i.e. the quoted command and arguments, which are most likely not needed in the handler. $command is resolved via the %PATH%, while $qcommand is not.

The code has to return an empty list (to do nothing) or a list with the name of the interpreter and the arguments that lead to the interpretation of $command (likely including $command itself), which is prepended to @arg and @qarg in the calling code.

Command Handlers

Command handlers are CodeRefs, that are called with the arguments:

        my $ret = $handler->($self, $command, \@arg, \@qarg, $args);

$self is the interpreter instance, $command is the name of the command (i.e. the key the handler was found under in the handler hash), @arg is the array of unquoted command line arguments. @qarg and $args are the raw forms of @arg, namely the quoted arguments and the unsplit command line, which are most likely not needed in the handler.

The handler can:

Execute the command and return a numeric exit code or the value 'keep' to keep the %ERRORLEVEL% unchanged, or return a string beginning with the word 'error' to signal an error.

If the handler culminates in calling an external program, it will likely be based on the methods $self->unc2sys($path), $self->unc2sys_arg($path) and $self->run_external_command($attr, $exe, @arg), which are documented elsewhere in this document.

Optionally change the contents of @arg (and @qarg, if finished is not set) and return a HashRef with the following keys:
type

Must be 'rewrite'.

command

Return a new $command to restart the handler search.

Locales

The locale class has to implement the following methods:

->format_date($year, $month, $day)

Format a date for %DATE%, prompt $D, and the date command.

->format_time_short($hour, $min)

Format a time for the time command.

->format_time($hour, $min, $sec, $sec100)

Format a time for %TIME%, and prompt $T.

->format_file_timedate($year, $month, $day, $hour, $min)

Format a file timestamp for the dir command.

->format_file_timedate_for($year, $month, $day, $hour, $min)

Format a file timestamp for for %I in (...) do echo %~tI

->get_string($category, $key)

Get a localized version of string $key in category $category. The only implemented category is 'message'.

METHODS TO BE CALLED FROM COMMAND HANDLERS

->unc2sys($path)

Translates an emulated path into a host path.

Convert path separators from \ to / and apply the filename and mountpoint translation rules, return the result.

Bug: the path is not actually UNC, though that _may_ work through mountpoint translation.

->sys2unc($path)

Translates a host path into an emulated path.

Convert path separators from / to \ and apply the filename and mountpoint translation rules, return the result.

Bug: the path is not actually UNC, though that _may_ work through mountpoint translation.

->unc2sys_arg($arg)

Translates an emulated command line argument into a host command line argument.

Paths are found in the argument by crude heuristics, which are subject to change. The actual translation is done with ->unc2sys($arg).

->run_external_command($attr, $exe, @arg)

Runs the external program $exe with command line arguments @arg and an optionally changed environment, while optionally translating the input and output text format, and return a result compatible with the Command Handler interface.

$attr supports the following keys:

add_to_env A hash of additional environment variables that will be set temporarily while calling the program.
flip_stdin Convert the newlines of STDIN from crlf to the host format.
flip_stdout Convert the newlines of STDOUT from the host format to crlf.
flip_stderr Convert the newlines of STDERR from the host format to crlf.

AUTHOR

Ralf Neubauer, <ralf at strcmp.de>

BUGS

Please report any bugs or feature requests to bug-batch-interpreter at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Batch-Interpreter. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Batch::Interpreter

You can also look for information at:

ACKNOWLEDGEMENTS

LICENSE AND COPYRIGHT

Copyright 2016 Ralf Neubauer.

This program is free software; you can redistribute it and/or modify it under the terms of the the Artistic License (2.0). You may obtain a copy of the full license at:

http://www.perlfoundation.org/artistic_license_2_0

Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license.

If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license.

This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder.

This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed.

Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.