BATsh

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN


    - Script exit-code propagation and $? <-> %ERRORLEVEL% bridge.
      run() / run_string() / run_lines() now RETURN the script's final
      exit status: "exit 3" gives 3, "EXIT /B 5" gives 5, otherwise the
      status of the last command.  The modulino exits with that code
      (exit(BATsh->main(@ARGV))), so OS-level %ERRORLEVEL% / $? of
      "perl lib/BATsh.pm script.batsh" is the script's own status.
      At every CMD<->SH section boundary the status is mirrored both
      ways, so a failing SH command is visible as %ERRORLEVEL% in the
      next CMD section and vice versa.  New public accessor
      BATsh->last_status.  New sub main() handles --help, --version,
      -e 'source', and "-" (read script from STDIN, remaining arguments
      become %1../$1..).  EXIT with no code keeps the current
      ERRORLEVEL.  "exit N" now also ends the REPL.  NEW FILE
      bin/batsh.pl (EXE_FILES); installed as "batsh".

    - $(( )) arithmetic rewritten as a recursive-descent parser.
      Now supported: comparison and logical operators (result 0/1),
      assignment operators = += -= *= /= %= <<= >>= &= ^= |= (written
      back to the variable store), prefix/postfix ++ and --, the
      ternary ?: and comma operators, ** (right-associative), bitwise
      & ^ | ~ << >> (~ is signed: -v-1), hex 0x.. and octal 0..
      literals, and C-style truncation toward zero for / and %
      (-7/2 = -3, -7%2 = -1).  Errors warn and yield 0.  Fixed a
      here-document false positive on $((1<<4)) ("<<" inside $(( ))
      is no longer taken as a heredoc opener).

    - SH shell options set -e / -u / -x (and set -o errexit /
      nounset / xtrace; +e/+u/+x to turn off; options combinable as
      in "set -eux").  set -e stops the script with the failing
      command's status; if/while/until conditions and non-final
      members of && / || lists are exempt.  set -u makes expansion of
      an unset variable an error (warning + exit status 1;
      ${VAR:-default} is exempt).  set -x traces each simple command
      to STDERR with a "+ " prefix.  Options are reset at the start
      of each top-level run so "set -e" cannot leak into a later
      run() in the same process.  Limitations are documented in POD:
      -x traces the raw pre-expansion line (expanding a copy would
      run $(...) twice), and -u stops after the current command
      completes with the empty expansion.

    - NEW SH BUILTIN eval: one level of quote removal, concatenation,
      and re-execution with a second round of expansion (POSIX
      semantics).  Previously "eval" fell through to external-command
      execution and only worked by accident where /bin/sh handled it.

    - New tests: t/0016-exit-status.t, t/0017-sh-arith.t,
      t/0018-sh-set-options.t.

    - Fixed t/0016-exit-status.t (ES12-ES14) on real Windows: the
      child-process helpers used a single quoted shell string for
      system(), which cmd.exe re-wraps in an extra pair of double
      quotes and mis-parses ("filename, directory name, or volume
      label syntax is incorrect"). Rewritten to use LIST-form
      system() (bypasses the shell entirely) with STDIN/STDOUT
      redirected at the Perl level via dup/reopen instead of a
      shell "<"/">" string. lib/BATsh.pm itself was unaffected; this
      was a test-harness-only bug. Re-verified on Linux (16/16).

      Desk review of the Win32-specific code paths (no Windows host
      available in this environment): BATsh::SH::_bg_launch_decoded()
      uses system(1, $cmdline) (P_NOWAIT) to background a job on
      Win32; the success/failure check (defined $pid && $pid > 0)
      matches the documented Win32 system(1, ...) contract (PID on
      success, 0 on failure). t/0016's _run_child() LIST-form
      system($^X, "-I$lib", $pm, $prog, @args) calls CreateProcess
      directly and does not re-enter cmd.exe, so the original
      quote-re-wrapping failure mode cannot recur. _bg_tempfile()'s
      temp-directory selection already accounts for %TEMP%/%TMP% and
      backslash path separators. No logic defects found in review;
      confirmation on an actual Windows host (locale, path-length,
      %TEMP% permission variables that cannot be reviewed statically)
      remains pending.

    - CP932 (Shift_JIS) multibyte-safe execution: NEW MODULE BATsh::MB.
      A .batsh script written in CP932 -- the encoding of Japanese
      Windows -- now runs correctly even when its characters contain
      trail bytes that collide with ASCII shell metacharacters (the
      classic "dame-moji" / 0x5C problem). Affected characters are
      extremely common: SO (0x835C), HYOU (0x955C), NOH (0x945C) end
      in a backslash; PO (0x837C) in a pipe; CHI (0x8360) in a
      backtick; DA (0x835E) in the cmd.exe caret escape; and many
      trail bytes fall in a-z/A-Z where uc()/lc() corrupt them.

      Design: instead of teaching every byte-oriented scanner in
      BATsh::CMD / BATsh::SH about lead and trail bytes, the script
      text passes through a reversible GUARD TRANSFORM on input. Each
      two-byte character LEAD+TRAIL whose TRAIL is in the dangerous
      ASCII range 0x40-0x7E is rewritten to the three-byte form
      \x01 LEAD (TRAIL+0x80), which contains no ASCII bytes; a literal
      \x01 becomes \x01\x01, making the transform bijective. All
      existing parsing (caret escapes, pipelines, quotes, redirects,
      globs, case patterns, uc/lc variable handling, SETLOCAL
      snapshots, ...) is then automatically DBCS-safe with no scanner
      changes. The inverse transform is applied at the output
      boundaries only:

        print sinks   ECHO/echo/printf/SET display, prompts, _warn
        exec sinks    system() for external commands, background jobs,
                      FOR /F ('command') input pipes
        file sinks    redirect targets, CD/DIR/COPY/DEL/MOVE/MKDIR/
                      RMDIR/REN/TYPE paths, IF EXIST, test -e/-f/-d...,
                      glob patterns, here-document bodies, CALL/source
                      script filenames
        env sink      BATsh::Env::sync_to_env (raw bytes into %ENV)

      and input re-entry points guard incoming raw bytes again:
      SET /P and read line input, FOR /F file/command lines, $(...)
      and `...` captured output, glob results, Cwd for %CD%/PWD.

    - Encoding selection (BATsh::MB): 'auto' is the default -- a
      non-UTF-8 source containing bytes >= 0x80 is detected as CP932
      and the guard switches on (and then stays on for the process,
      because Env may hold guarded values; only an explicit
      set_encoding deactivates it). Pure-ASCII and well-formed UTF-8
      sources need no guarding and are byte-for-byte unaffected, so
      existing behaviour is preserved exactly. Explicit selection:

        BATsh->run($file, encoding => 'cp932');
        BATsh->run_string($src, encoding => 'sjis');
        BATsh->set_encoding('cp932');



( run in 0.757 second using v1.01-cache-2.11-cpan-9169edd2b0e )