NAME
    Win32::CommandLine - Retrieve and reparse the Win32 command line

VERSION
         $Win32::CommandLine::VERSION = "0.947_1";

SYNOPSIS
         @ARGV = Win32::CommandLine::argv() if eval { require Win32::CommandLine; };

            _or_

         use Win32::CommandLine qw( command_line );
         my $commandline = command_line();
         ...

DESCRIPTION
    This module is used to reparse the Win32 command line, automating better
    quoting, command substitution, and globbing of the command line.
    Globbing is full bash POSIX compatible globbing. With the use of the
    companion script ("xx.bat"), and "doskey" for macro aliasing, you can
    add fully implemented, bash compatible, string quoting/expansion and
    file globbing to *any* Win32 executable.

    This module is compatible with both "cmd.exe" and "4nt/tcc/tcmd" shells,
    and can be used to add better parsing and bash glob expansion to *any*
    external command (by using the included "xx.bat" batch script).

  "CMD.EXE"
         doskey type=call xx type $*
         type [a-c]*.pl

         doskey perl=call xx perl $*
         perl -e 'print "test"'     &@:: would otherwise FAIL

         @:: print all directories in current directory
         xx echo $(" ls -ALp --quoting-style=c --color=no . | grep --color=no "[\\/]$" ")

         @:: print all files (non-directories) in current directory
         xx echo $(" ls -ALp --quoting-style=shell --color=no . | grep --color=no -v "[\\/]$" ")  [print all files in CWD]

  "4NT/TCC/TCMD"
         alias type=call xx type
         type [a-c]*.pl

         alias perl=call xx perl
         perl -e 'print "test"'     &@:: would otherwise FAIL

    Note that bash-compatible globbing and argument expansion are supplied,
    including command substitution. Glob patterns may also contain
    meta-notations, such as '"a[bc]*"' or '"foo.{bat,pl,exe,o}"'.

  Command line string/character expansion
         '...'    literal (no escapes and no globbing within quotes)
         "..."    literal (no escapes and no globbing within quotes) (see *NOTE-1)
         $'...'   string including all ANSI C string escapes (see *NOTE-2); no globbing within quotes
         $"..."   literal (no escapes and no globbing within quotes) [same as "..."]
         $( ... ) command substitution (see *NOTE-3)
         $("...") command substitution (quotes removed; see *NOTE-4)

    NOTE-1: DOS character escape sequences (such as "\"") are parsed prior
    to being put into the command line and, so, are valid and still
    (unavoidably) interpreted within double-quotes.

    NOTE-2: ANSI C string escapes are "\a, \b, \e, \f, \n, \r, \t, \v, \\,
    \', \", \[0-9]{1,3}, \x[0-9a-fA-F]{1,2}, \c[@A-Z[\\\]^_`?]"; all other
    escaped characters are left in place without transformation ("\<x> =>
    \<x>").

    NOTE-3: Command substitution replaces the "$(...)" argument with the
    standard output of that argument's execution. Command substitution
    strings are not, themselves, automatically expanded; use "$(xx
    *COMMAND*)" to trigger expansion of the subshell command line.

    NOTE-4: "$("...")" is present to enable delayed DOS/Windows
    interpretation of redirection & continuation characters. This allows
    redirection & continuation characters to be used within the subshell
    command string.

    URLref: [bash ANSI-C Quoting]
    <http://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.ht
    ml> @@ <http://www.webcitation.org/66M8skmP8>

  GLOB META CHARACTERS
         \           Quote the next metacharacter
         []          Character class
         {}          Multiple pattern
         *           Match any string of characters
         ?           Match any single character
         ~           Current user home directory
         ~USERNAME   Home directory of USERNAME
         ~TEXT       Environment variable named ~TEXT (aka $ENV{~TEXT}) [overrides ~USERNAME expansion]

    The multiple pattern metanotation '"a{b,c,d}e"' is a shorthand for '"abe
    ace ade"'. Left to right order is preserved, with results of matches
    being sorted separately at a low level to preserve this order.

INSTALLATION
    To install this module, run the following commands:

         perl Build.PL
         perl Build
         perl Build test
         perl Build install

    This is minor modification of the usual perl build idiom. This version
    is portable across multiple platforms.

    Alternatively, the standard make idiom is also available (although it is
    deprecated):

         perl Makefile.PL
         make
         make test
         make install

    (On Windows platforms, you should use "nmake"or "dmake", instead of
    "make".)

    Note that the Makefile.PL script is just a pass-through, and
    Module::Build is still ultimately required for installation. Makefile.PL
    will throw an exception if Module::Build is missing from your current
    installation. "cpan" will notify the user of the build prerequisites
    (and install them for the build, if it is setup to do so [see the cpan
    configuration option "build_requires_install_policy"]).

    PPM installation bundles should also be available in the standard PPM
    repositories (i.e. ActiveState, trouchelle.com
    [<http://trouchelle.com/ppm/package.xml>]).

    Note: On ActivePerl installations, '"./Build install"' will do a full
    installation using "ppm" (see ppm). During the installation, a PPM
    package is constructed locally and then subsequently used for the final
    module install. This allows for uninstalls (using '"ppm uninstall
    ""*MODULE*"' and also keeps local HTML documentation current.

INTERFACE
  "command_line( ): $"
    *   [out] : the original command line for the process, as a string

     my $commandline = command_line();

    Use the Win32 API to recapture the original command line for the current
    process.

  "argv( [\%options] ): @"
    *   [in] : (optional) reference to hash containing function options

    *   [out] : returns a new argument array (which can replace @ARGV)

     @ARGV = argv();

    Reparse & glob-expand the original command line, returning a new
    argument array (which is a drop-in replacement for @ARGV).

  "parse( $ [,\%options ] ): @"
    *   [in] : string argument to parse/glob-expand

    *   [in] : (optional) reference to hash containing function options

    *   [out] : returns an argument array

     my @argv_new = parse( command_line() );

    Parse & glob-expand a string argument; returns the results of
    parsed/expanded argument as an array.

  Function Options ( "\%options" )
        my %options = (
            remove_exe_prefix => 1,     # = 0/<true> [default = true]       # if true, remove all initial args up to and including the exe name from the @args array
            dosquote => 0,              # = 0/<true>/'all' [default = 0]    # if true, convert all non-globbed ARGS to DOS/Win32 CLI compatible tokens (escaping internal quotes and quoting whitespace and special characters)
            dosify => 0,                # = 0/<true>/'all' [default = 0]    # if true, convert all _globbed_ ARGS to DOS/Win32 CLI compatible tokens (escaping internal quotes and quoting whitespace and special characters); 'all' => do so for for _all_ ARGS which are determined to be files
            unixify => 0,               # = 0/<true>/'all' [default = 0]    # if true, convert all _globbed_ ARGS to UNIX path style; 'all' => do so for for _all_ ARGS which are determined to be files
            nullglob => defined($ENV{nullglob}) ? $ENV{nullglob} : 0,       # = 0/<true> [default = 0]  # if true, patterns which match no files are expanded to a null string (no token), rather than the pattern itself  ## $ENV{nullglob} (if it exists) overrides the default
            glob => 1,                  # = 0/<true> [default = true]       # when true, globbing is performed
            ## TODO: rework this ... need carp/croak on unbalanced quotes/subshells (? carp_ub_quotes, carp_ub_shells, carp = 0/1/warn/carp/die/croak)
            croak_unbalanced => 1,      # = 0/true/'quotes'/'subshells' [default = true] # if true, croak for unbalanced command line quotes or subshell blocks (takes precedence over carp_unbalanced)
            carp_unbalanced => 1,       # = 0/true/'quotes'/'subshells' [default = true] # if true, carp for unbalanced command line quotes or subshell blocks
            ## ToDO: add globstar option
            );

SUBROUTINES/METHODS
RATIONALE
    This began as a simple need to work-around the less-than-stellar
    "COMMAND.COM"/"CMD.EXE" command line parser, just to accomplish more
    `correct` quotation interpretation. It then grew into a small odyssey:
    learning XS and how to create a perl module, learning the perl build
    process and creating a customized build script/environment, researching
    tools and developing methods for revision control and versioning,
    learning and creating perl testing processes, and finally learning about
    PAUSE and perl publishing practices. And, somewhere in the middle,
    adding some of the "bash" shell magic to the CMD shell (and,
    additionally, making it compatible with the excellent [and free] TCC-LE
    shell from JPSoft [find that at <http://jpsoft.com>]).

    Some initial attempts were made using "Win32::API" and "Inline::C". For
    example, a "Win32::API" attempt [which caused GPFs]:

      @rem = '--*-Perl-*--
      @echo off
      if "%OS%" == "Windows_NT" goto WinNT
      perl -x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9
      goto endofperl
      :WinNT
      perl -x -S %0 %*
      if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto endofperl
      if %errorlevel% == 9009 echo You do not have Perl in your PATH.
      if errorlevel 1 goto script_failed_so_exit_with_non_zero_val 2>nul
      goto endofperl
      @rem ';
      #!/usr/bin/perl -w
      #line 15
      #
      use Win32::API;
      #
      Win32::API->Import("kernel32", "LPTSTR GetCommandLine()");
      my $string = pack("Z*", GetCommandLine());
      #
      print "string[".length($string)."] = '$string'\n";
      # ------ padding --------------------------------------------------------------------------------------
      __END__
      :endofperl

    Unfortunately, "Win32::API" and "Inline::C" were shown to be too fragile
    at the time (in 2007). "Win32::API" caused occasional (but reproducible)
    GPFs, and "Inline::C" was shwon to be very brittle on Win32 systems
    (i.e, not compensating for paths with embedded strings). [ See
    <http://www.perlmonks.org/?node_id=625182> for a more full explanation
    of the problem and initial attempts at a solution. ]

    So, an initial XS solution was implemented. And from that point, the
    lure of "bash"-like command line parsing led inexorably to the full
    implementation. The parsing logic is unfortunately still complex, but
    seems to be holding up well under testing.

IMPLEMENTATION and INTERNALS
    This is a list of internal XS functions (brief descriptions will be
    added at a later date):

      SV * _wrap_GetCommandLine() // [XS] Use C and Win32 API to get the command line
      HANDLE _wrap_CreateToolhelp32Snapshot ( dwFlags, th32ProcessID )
      bool _wrap_Process32First ( hSnapshot, lppe )
      bool _wrap_Process32Next ( hSnapshot, lppe )
      bool _wrap_CloseHandle ( hObject )
      // Pass useful CONSTANTS back to perl
      int _const_MAX_PATH ()
      HANDLE _const_INVALID_HANDLE_VALUE ()
      DWORD _const_TH32CS_SNAPPROCESS ()
      // Pass useful sizes back to Perl (for testing) */
      unsigned int _info_SIZEOF_HANDLE ()
      unsigned int _info_SIZEOF_DWORD ()
      // Pass PROCESSENTRY32 structure info back to Perl
      SV * _info_PROCESSENTRY32 ()

DIAGNOSTICS
    Pending documentation...

CONFIGURATION AND ENVIRONMENT
    "Win32::CommandLine" requires no configuration files or environment
    variables.

  OPTIONAL Environment Variables
    "NULLGLOB" - override the default glob expansion behavior for empty
    matches
         $ENV{NULLGLOB} = 1; # undef/0 | <true>

        Default glob expansion, as in bash, expands glob patterns which
        match nothing into the glob pattern itself. Use $ENV{NULLGLOB} to
        override this default behavior.

        Analogous to the bash command '"shopt -s nullglob"', when
        $ENV{NULLGLOB} is set to a true (non-NULL, non-zero) value, a glob
        expansion which matches nothing will expand to the null string (aka,
        "q{}").

        Note: the default glob expansion behavior can also be modified
        programmatically via the function option, "nullglob", when passed to
        the argv() and parse() functions. This option, when passed to
        "argv()" or "parse()", will override both the default behavior *and*
        the $ENV{NULLGLOB} setting.

DEPENDENCIES
    "Win32::CommandLine" requires "Carp::Assert" for internal error checking
    and warnings.

    The optional modules "Win32", "Win32::Security::SID", and
    "Win32::TieRegistry" are recommended to allow full glob tilde expansions
    for user home directories (eg, "~administrator" expands to
    "C:\Users\Administrator"). Expansion of the single tilde ("~") has a
    backup implementation based on %ENV variables, and therefore will still
    work even without the optional modules.

INCOMPATIBILITIES
    None reported.

BUGS AND LIMITATIONS
    Please report any bugs or feature requests to
    "bug-Win32-CommandLine@rt.cpan.org", or through the web interface at
    <http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Win32-CommandLine>. The
    developers will be notified, and you'll automatically be notified of
    progress on your bug as any changes are made.

  Operational Notes
    IMPORTANT NOTE: Special shell characters (shell redirection [ '|', '<',
    "'"'> ] and continuation '&') must be DOUBLE-quoted to escape shell
    interpretation (eg, "foo | bar"). The shell does initial parsing and
    redirection/continuation (stripping away everything after I/O
    redirection and continuation characters) before any process can get a
    look at the command line. So, the special shell characters can only be
    hidden from shell interpretation by quoting them with double-quote
    characters.

    "%<X>" is also replaced by the corresponding %ENV variable by the shell
    before handing the command line off to the OS. So, "%%" must be used to
    place single %'s in the command line (eg, "perl -e "use
    Win32::CommandLine; %%x = Win32::CommandLine::_home_paths(); for (sort
    keys %%x) { print qq{$_ => $x{$_}\n}; }"").

    Brackets ('{' and '}') and braces ('[' and ']') must be quoted (single
    or double quotes) to be matched literally. This may be a gotcha for some
    users, although if the filename has internal spaces, tab expansion of
    filenames for the standard Win32 shell (cmd.exe) or 4NT/TCC/TCMD will
    automatically surround the entire path with spaces (which corrects the
    issue).

    Some programs may expect their arguments to maintain their surrounding
    quotes, but argv() parsing only quotes arguments which require it to
    maintain equivalence for shell parsing (i.e., those containing spaces,
    special characters, etc). And, since single quotes have no special
    meaning to the shell, all arguments which require quoting for correct
    shell interpretation will be quoted with double-quote characters, even
    if they were originally quoted with single-quotes. Neither of these
    issues should be a problem for programs using Win32::CommandLine, but
    may be an issue for 'legacy' applications which have their command line
    expanded with "xx.bat".

    Be careful with backslashed quotes within quoted strings. Note that
    "foo\" is an unbalanced string containing a double quote. Place the
    backslash outside of the quotation ("foo"\) or use a double backslash
    within ("foo\\") to include the backslash it in the parsed token.
    However, backslashes ONLY need to be doubled when placed prior to a
    quotation mark ("foo\bar" will work as expected).

  Bugs
    No bugs have been reported.

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

         perldoc Win32::CommandLine

    You can also look for further information at:

    *   CPAN

            <https://metacpan.org/search?q=Win32-CommandLine>

            <http://search.cpan.org/dist/Win32-CommandLine>

            <http://kobesearch.cpan.org/dist/Win32-CommandLine>

    *   CPAN Ratings

            <http://cpanratings.perl.org/dist/Win32-CommandLine>

    *   RT: CPAN's request tracker (aka buglist)

            <http://rt.cpan.org/Public/Dist/Display.html?Name=Win32-CommandL
            ine>

    *   CPANTESTERS: Test results

            <http://www.cpantesters.org/show/Win32-CommandLine.html>

    *   CPANTS: CPAN Testing Service

            "[kwalitee]"
            <http://cpants.perl.org/dist/kwalitee/Win32-CommandLine>

            "[ used by]"
            <http://cpants.perl.org/dist/used_by/Win32-CommandLine>

TODO
    Expand and polish the documentation. Add argument/option explanations
    and examples for interface functions.

TESTING
    For additional testing, set the following environment variables to a
    true value ("true" in the perl sense, meaning non-NULL, non-ZERO value):

    TEST_AUTHOR
        Perform distribution correctness and quality tests, which are
        essential prior to a public release.

    TEST_FRAGILE
        Perform tests which have a specific (i.e., fragile) execution
        context (eg, network tests to named hosts). These are tests that
        must be coddled with specific execution contexts or set up on
        specific machines to complete correctly.

    TEST_SIGNATURE
        Verify signature is present and correct for the distribution.

    TEST_ALL
        Perform ALL (non-FRAGILE) additional/optional tests. Given the
        likelyhood of test failures without special handling, tests marked
        as 'FRAGILE' are still NOT performed unless TEST_FRAGILE is also
        true. Additionally, note that the 'build testall' command can be
        used as an equivalent to setting TEST_ALL to true temporarily, for
        the duration of the build, followed by a 'build test'.

LICENSE AND COPYRIGHT
     Copyright (c) 2007-2013, Roy Ivy III <rivy[at]cpan[dot]org>. All rights reserved.

    This module is free software; you can redistribute it and/or modify it
    under the Perl Artistic License v2.0 (see
    <http://opensource.org/licenses/artistic-license-2.0.php>).

DISCLAIMER OF WARRANTY
     THIS 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.

     [REFER TO THE FULL LICENSE FOR EXPLICIT DEFINITIONS OF ALL TERMS.]

ACKNOWLEDGEMENTS
    Thanks to BrowserUK and syphilis (aka SISYPHUS on CPAN) for some helpful
    ideas (including an initial XS starting point for the module) during a
    discussion on PerlMonks (see
    <http://www.perlmonks.org/?node_id=625182>).

AUTHOR
    Roy Ivy III <rivy[at]cpan[dot]org>

