js/vbs/html/hta and more hybrids and chimeras in cmd/bat

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
siberia-man
Posts: 208
Joined: 26 Dec 2013 09:28
Contact:

Re: js/vbs/html/hta and more hybrids and chimeras in cmd/bat

#61 Post by siberia-man » 23 Sep 2020 10:32

The latest to this moment version of the script.

What has been done

-- some cosmetic changes
-- improve slightly the argument processing
-- add hybridization for AutoIt, AutoHotKey and PHP
-- improve creation of the PowerShell chimera

The full list of supported languages and technologies

-- JavaScript
-- VBScript
-- Perl
-- Shell/Bash
-- PowerShell
-- Python
-- HTA
-- HTML
-- WSF
-- KixStart
-- AutoIt, AutoHotKey
-- PHP
-- Julia

Source code

Code: Select all

:: USAGE
::     cmdize name [...]
::
:: This tool converts a supported code into a batch file that can be 
:: executed without explicit invoking the executable engine. The script 
:: creates new file and places it under the same directory as the original 
:: one with the same name, replacing the original extension with ".bat". 
:: The content of the new file consists of the original file and the 
:: special header that being the "polyglot" and having some tricks to be a 
:: valid code in batch file and the wrapped code at the same time. 
::
:: FEATURES
:: It does comment on "Option Explicit" in VBScript.
:: "<?xml?>" declaration for wsf-files is expected.
:: "Option Explicit" and "<?xml?>" in a single line only are supported.
:: BOM is not supported at all.
::
:: It is possible to select an engine for JavaScript, VBScript and WSF via 
:: the command line options /E. If it is not pointed especially, CSCRIPT 
:: is used as the default engine for all JavaScript, VBScript and WSF 
:: files. Another valid engine is WSCRIPT. Additionally for JavaScript 
:: files it is possible to set another engine such as NodeJS, Rhino etc. 
:: The predefined option /E DEFAULT resets any previously set engines to 
:: the default value. 
::
:: SEE ALSO
:: Proceed the following links to learn more the origins
::
:: .js
:: http://forum.script-coding.com/viewtopic.php?pid=79210#p79210
:: http://www.dostips.com/forum/viewtopic.php?p=33879#p33879
:: https://gist.github.com/ildar-shaimordanov/88d7a5544c0eeacaa3bc
::
:: .vbs
:: http://www.dostips.com/forum/viewtopic.php?p=33882#p33882
:: http://www.dostips.com/forum/viewtopic.php?p=32485#p32485
::
:: .pl
:: For details and better support see "pl2bat.bat" from Perl distribution
::
:: .sh, .bash
:: http://forum.script-coding.com/viewtopic.php?id=11535
:: http://www.dostips.com/forum/viewtopic.php?f=3&t=7110#p46654
::
:: .ps1
:: http://blogs.msdn.com/b/jaybaz_ms/archive/2007/04/26/powershell-polyglot.aspx
:: http://stackoverflow.com/a/2611487/3627676
::
:: .py
:: http://stackoverflow.com/a/29881143/3627676
:: http://stackoverflow.com/a/17468811/3627676
::
:: .hta and .html?
:: http://forum.script-coding.com/viewtopic.php?pid=79322#p79322
::
:: .wsf
:: http://www.dostips.com/forum/viewtopic.php?p=33963#p33963
::
:: .kix
::
:: .au3, .a3x
::
:: .ahk
::
:: .php
::
:: .jl
:: https://github.com/JuliaLang/julia/blob/master/doc/src/base/punctuation.md
::
:: COPYRIGHTS
:: Copyright (c) 2014, 2015, 2016, 2018, 2020 Ildar Shaimordanov

@echo off

if "%~1" == "" (
	for /f "usebackq tokens=* delims=:" %%s in ( "%~f0" ) do (
		if /i "%%s" == "@echo off" goto :EOF
		echo:%%s
	)
	goto :EOF
)

setlocal

:cmdize.loop.begin
if "%~1" == "" goto :cmdize.loop.end

set "CMDIZE_ENGINE="

if /i "%~1" == "/e" (
	if /i not "%~2" == "default" set "CMDIZE_ENGINE=%~2"
	shift /1
	shift /1
)

if not exist "%~f1" (
	echo:%~n0: File not found: "%~1">&2
	goto :cmdize.loop.continue
)

findstr /i /r /c:"^:cmdize%~x1$" "%~f0" >nul || (
	echo:%~n0: Unsupported extension: "%~1">&2
	goto :cmdize.loop.continue
)

call :cmdize%~x1 "%~1" >"%~dpn1.bat"

:cmdize.loop.continue

shift

goto :cmdize.loop.begin
:cmdize.loop.end

goto :EOF

:: ========================================================================

:: Convert the javascript file. 
:: The environment variable %CMDIZE_ENGINE% allows to declare another 
:: engine (cscript, wscript, node etc). 
:: The default value is cscript.
:cmdize.js
if not defined CMDIZE_ENGINE set "CMDIZE_ENGINE=cscript"
set "CMDIZE_ENGINE_OPTS="
for %%e in ( "%CMDIZE_ENGINE%" ) do (
	if /i "%%~ne" == "cscript" set "CMDIZE_ENGINE_OPTS=//nologo //e:javascript"
	if /i "%%~ne" == "wscript" set "CMDIZE_ENGINE_OPTS=//nologo //e:javascript"
)

echo:0^</*! ::
echo:@echo off
echo:%CMDIZE_ENGINE% %CMDIZE_ENGINE_OPTS% "%%~f0" %%*
echo:goto :EOF */0;
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the vbscript file. 
:: The environment variable %CMDIZE_ENGINE% allows to declare another 
:: engine (cscript or wscript). 
:: The default value is cscript. 
:cmdize.vbs
if not defined CMDIZE_ENGINE set "CMDIZE_ENGINE=cscript"

copy /y nul + nul /a "%TEMP%\%~n0.$$" /a 1>nul
for /f "usebackq" %%s in ( "%TEMP%\%~n0.$$" ) do (
	echo:::'%%~s@echo off
	echo:::'%%~scscript //nologo //e:vbscript "%%~f0" %%*
	echo:::'%%~sgoto :EOF
)
del /q "%TEMP%\%~n0.$$"

rem type "%~f1"
for /f "tokens=1,* delims=]" %%r in ( 'find /n /v "" ^<"%~f1"' ) do (
	rem Filtering and commenting "Option Explicit". 
	rem This ugly code tries as much as possible to recognize and 
	rem comment this directive. It fails if "Option" and "Explicit" 
	rem are located on two neighbor lines, consecutively, one by one. 
	rem But it is too hard to imagine that there is someone who 
	rem practices such a strange coding style. 
	for /f "usebackq tokens=1,2" %%a in ( '%%s' ) do if /i "%%~a" == "Option" for /f "usebackq tokens=1,* delims=:'" %%i in ( 'x%%b' ) do if /i "%%~i" == "xExplicit" (
		echo:%~n0: Commenting Option Explicit in "%~1">&2
		echo:rem To prevent compilation error due to embedding into a batch file, 
		echo:rem the following line was commented automatically.
		set /p "=rem " <nul
	)
	echo:%%s
)
goto :EOF

:: ========================================================================

:: Convert the perl file.
:cmdize.pl
if /i "%CMDIZE_ENGINE%" == "cmd" (
	echo:@echo off
	echo:perl -x -S "%%~dpn0.pl" %%*
	goto :EOF
)

echo:@rem = '--*-Perl-*--
echo:@echo off
echo:perl -x -S "%%~f0" %%*
echo:goto :EOF
echo:@rem ';
echo:#!perl
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert Bourne shell and Bash scripts. 
:cmdize.sh
:cmdize.bash
echo:: ^<^< '____CMD____'
echo:@echo off
echo:bash "%%~f0" %%*
echo:goto :eof
echo:____CMD____
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the powershell file. 
:cmdize.ps1
echo:^<# :
echo:@echo off
echo:setlocal
echo:set "PS1_ARGS=%%*"
echo:powershell -NoLogo -NoProfile -Command "$a=($Env:PS1_ARGS|sls -Pattern '\"(.*?)\"(?=\s|$)|(\S+)' -AllMatches).Matches.Value|%%%%{$_ -Replace '^\"','' -Replace '\"$',''};$i=$input;iex $('$input=$i;$args=$a;rv i,a;'+((gc \"%%~f0\" ) -join [char]10))"
echo:rem powershell -NoLogo -NoProfile -Command "$a=($Env:PS1_ARGS|sls -Pattern '\"(.*?)\"(?=\s|$)|(\S+)' -AllMatches).Matches.Value|%%%%{$_ -Replace '^\"','' -Replace '\"$',''};$input|&{[ScriptBlock]::Create((gc \"%%~f0\" ) -join [char]10).Invoke(@(&{$args+$a}))}"
echo:goto :EOF
echo:#^>
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the python file.
:cmdize.py
:: Ascetic way is shorter but less flexible
:: Uncomment the following 3 lines if it is more preferrable
:: echo:@python -x "%%~f0" %%* ^& @goto :EOF
:: type "%~f1"
:: goto :EOF
echo:0^<0# : ^^
echo:"""
echo:@echo off
echo:python "%%~f0" %%*
echo:goto :EOF
echo:"""
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the html file. 
:: Supportable file extensions are .hta, .htm and .html. 
:cmdize.hta
:cmdize.htm
:cmdize.html
echo:^<!-- :
echo:@echo off
echo:start "" mshta "%%~f0" %%*
echo:goto :EOF
echo:--^>
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the wsf file. 
:: The environment variable %CMDIZE_ENGINE% allows to declare another 
:: engine (cscript or wscript). 
:: The default value is cscript.
:cmdize.wsf
if not defined CMDIZE_ENGINE set "CMDIZE_ENGINE=cscript"

for /f "usebackq tokens=1,2,* delims=?" %%a in ( "%~f1" ) do for /f "tokens=1,*" %%d in ( "%%b" ) do (
	rem We use this code to transform the "<?xml?>" declaration 
	rem located at the very beginning of the file to the "polyglot" 
	rem form to do it acceptable by the batch file.
	echo:%%a?%%d :
	echo:: %%e ?^>^<!--
	echo:@echo off
	echo:%CMDIZE_ENGINE% //nologo "%%~f0?.wsf" %%*
	echo:goto :EOF
	echo:: --%%c
	more +1 <"%~f1"
	goto :EOF
)
goto :EOF

:: ========================================================================

:: Comvert KiXtart file.
:cmdize.kix
echo:;@echo off
echo:;kix32 "%%~f0" %%*
echo:;goto :EOF
type "%~f1"

:: ========================================================================

:: Convert AutoIt file.
:cmdize.au3
:cmdize.a3x
echo:;@echo off
echo:;AutoIt3 "%%~f0" %%*
echo:;goto :EOF
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert AutoHotKey file.
:cmdize.ahk
echo:;@echo off
echo:;AutoHotKey "%%~f0" %%*
echo:;goto :EOF
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert PHP file.
:: PHP is supposed to be used as a scripting language in Web. So to avoid
:: possible conflicts with paths to dynamic libraries and to suppress HTTP
:: headers, we use two options "-n" and "-q", respectively.
:cmdize.php
echo:^<^?php/* :
echo:@echo off
echo:php -n -q "%%~f0" %%*
echo:goto :EOF
echo:*/ ?^>
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert Julia file.
:cmdize.jl
echo::"""
echo:@echo off
echo:julia "%%~f0" %%*
echo:goto :EOF
echo:"""
type "%~f1"
goto :EOF

:: ========================================================================

:: EOF
The actual version of the script is available here: https://github.com/ildar-shaimordanov/c ... cmdize.bat

siberia-man
Posts: 208
Joined: 26 Dec 2013 09:28
Contact:

Re: js/vbs/html/hta and more hybrids and chimeras in cmd/bat

#62 Post by siberia-man » 13 Feb 2021 07:49

What has been done

-- some improvements to the PowerShell chimera creation
-- support Ruby

The full list of supported languages and technologies

-- JavaScript
-- VBScript
-- Perl
-- Shell/Bash
-- PowerShell
-- Python
-- Ruby
-- HTA
-- HTML
-- WSF
-- KixStart
-- AutoIt, AutoHotKey
-- PHP
-- Julia

Source code

Code: Select all

:: USAGE
::     cmdize name [...]
::
:: This tool converts a supported code into a batch file that can be 
:: executed without explicit invoking the executable engine. The script 
:: creates new file and places it under the same directory as the original 
:: one with the same name, replacing the original extension with ".bat". 
:: The content of the new file consists of the original file and the 
:: special header that being the "polyglot" and having some tricks to be a 
:: valid code in batch file and the wrapped code at the same time. 
::
:: FEATURES
:: It does comment on "Option Explicit" in VBScript.
:: "<?xml?>" declaration for wsf-files is expected.
:: "Option Explicit" and "<?xml?>" in a single line only are supported.
:: BOM is not supported at all.
::
:: It is possible to select an engine for JavaScript, VBScript and WSF via 
:: the command line options /E. If it is not pointed especially, CSCRIPT 
:: is used as the default engine for all JavaScript, VBScript and WSF 
:: files. Another valid engine is WSCRIPT. Additionally for JavaScript 
:: files it is possible to set another engine such as NodeJS, Rhino etc. 
:: The predefined option /E DEFAULT resets any previously set engines to 
:: the default value. 
::
:: SEE ALSO
:: Proceed the following links to learn more the origins
::
:: .js
:: http://forum.script-coding.com/viewtopic.php?pid=79210#p79210
:: http://www.dostips.com/forum/viewtopic.php?p=33879#p33879
:: https://gist.github.com/ildar-shaimordanov/88d7a5544c0eeacaa3bc
::
:: .vbs
:: http://www.dostips.com/forum/viewtopic.php?p=33882#p33882
:: http://www.dostips.com/forum/viewtopic.php?p=32485#p32485
::
:: .pl
:: For details and better support see "pl2bat.bat" from Perl distribution
::
:: .sh, .bash
:: http://forum.script-coding.com/viewtopic.php?id=11535
:: http://www.dostips.com/forum/viewtopic.php?f=3&t=7110#p46654
::
:: .ps1
:: http://blogs.msdn.com/b/jaybaz_ms/archive/2007/04/26/powershell-polyglot.aspx
:: http://stackoverflow.com/a/2611487/3627676
::
:: .py
:: http://stackoverflow.com/a/29881143/3627676
:: http://stackoverflow.com/a/17468811/3627676
::
:: .rb
:: https://stackoverflow.com/questions/35094778
::
:: .hta and .html?
:: http://forum.script-coding.com/viewtopic.php?pid=79322#p79322
::
:: .wsf
:: http://www.dostips.com/forum/viewtopic.php?p=33963#p33963
::
:: .kix
::
:: .au3, .a3x
::
:: .ahk
::
:: .php
::
:: .jl
:: https://github.com/JuliaLang/julia/blob/master/doc/src/base/punctuation.md
::
:: COPYRIGHTS
:: Copyright (c) 2014-2021 Ildar Shaimordanov

@echo off

if "%~1" == "" (
	for /f "usebackq tokens=* delims=:" %%s in ( "%~f0" ) do (
		if /i "%%s" == "@echo off" goto :EOF
		echo:%%s
	)
	goto :EOF
)

setlocal

:cmdize.loop.begin
if "%~1" == "" goto :cmdize.loop.end

set "CMDIZE_ENGINE="

if /i "%~1" == "/e" (
	if /i not "%~2" == "default" set "CMDIZE_ENGINE=%~2"
	shift /1
	shift /1
)

if not exist "%~f1" (
	echo:%~n0: File not found: "%~1">&2
	goto :cmdize.loop.continue
)

findstr /i /r /c:"^:cmdize%~x1$" "%~f0" >nul || (
	echo:%~n0: Unsupported extension: "%~1">&2
	goto :cmdize.loop.continue
)

call :cmdize%~x1 "%~1" >"%~dpn1.bat"

:cmdize.loop.continue

shift

goto :cmdize.loop.begin
:cmdize.loop.end

goto :EOF

:: ========================================================================

:: Convert the javascript file. 
:: The environment variable %CMDIZE_ENGINE% allows to declare another 
:: engine (cscript, wscript, node etc). 
:: The default value is cscript.
:cmdize.js
if not defined CMDIZE_ENGINE set "CMDIZE_ENGINE=cscript"
set "CMDIZE_ENGINE_OPTS="
for %%e in ( "%CMDIZE_ENGINE%" ) do (
	if /i "%%~ne" == "cscript" set "CMDIZE_ENGINE_OPTS=//nologo //e:javascript"
	if /i "%%~ne" == "wscript" set "CMDIZE_ENGINE_OPTS=//nologo //e:javascript"
)

echo:0^</*! ::
echo:@echo off
echo:%CMDIZE_ENGINE% %CMDIZE_ENGINE_OPTS% "%%~f0" %%*
echo:goto :EOF */0;
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the vbscript file. 
:: The environment variable %CMDIZE_ENGINE% allows to declare another 
:: engine (cscript or wscript). 
:: The default value is cscript. 
:cmdize.vbs
if not defined CMDIZE_ENGINE set "CMDIZE_ENGINE=cscript"

copy /y nul + nul /a "%TEMP%\%~n0.$$" /a 1>nul
for /f "usebackq" %%s in ( "%TEMP%\%~n0.$$" ) do (
	echo:::'%%~s@echo off
	echo:::'%%~scscript //nologo //e:vbscript "%%~f0" %%*
	echo:::'%%~sgoto :EOF
)
del /q "%TEMP%\%~n0.$$"

rem type "%~f1"
for /f "tokens=1,* delims=]" %%r in ( 'find /n /v "" ^<"%~f1"' ) do (
	rem Filtering and commenting "Option Explicit". 
	rem This ugly code tries as much as possible to recognize and 
	rem comment this directive. It fails if "Option" and "Explicit" 
	rem are located on two neighbor lines, consecutively, one by one. 
	rem But it is too hard to imagine that there is someone who 
	rem practices such a strange coding style. 
	for /f "usebackq tokens=1,2" %%a in ( '%%s' ) do if /i "%%~a" == "Option" for /f "usebackq tokens=1,* delims=:'" %%i in ( 'x%%b' ) do if /i "%%~i" == "xExplicit" (
		echo:%~n0: Commenting Option Explicit in "%~1">&2
		echo:rem To prevent compilation error due to embedding into a batch file, 
		echo:rem the following line was commented automatically.
		set /p "=rem " <nul
	)
	echo:%%s
)
goto :EOF

:: ========================================================================

:: Convert the perl file.
:cmdize.pl
if /i "%CMDIZE_ENGINE%" == "cmd" (
	echo:@echo off
	echo:perl -x -S "%%~dpn0.pl" %%*
	goto :EOF
)

echo:@rem = '--*-Perl-*--
echo:@echo off
echo:perl -x -S "%%~f0" %%*
echo:goto :EOF
echo:@rem ';
echo:#!perl
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert Bourne shell and Bash scripts. 
:cmdize.sh
:cmdize.bash
echo:: ^<^< '____CMD____'
echo:@echo off
echo:bash "%%~f0" %%*
echo:goto :eof
echo:____CMD____
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the powershell file. 
:cmdize.ps1
echo:^<# :
echo:@echo off
echo:setlocal
echo:set "PS1_ARGS=%%*"
echo:powershell -NoLogo -NoProfile -Command "$a=($Env:PS1_ARGS|sls -Pattern '\"(.*?)\"(?=\s|$)|(\S+)' -AllMatches).Matches;if($a.length){$a=@($a|%%%%{$_.value -replace '^\"','' -replace '\"$',''})}else{$a=@()};$i=$input;iex $('$input=$i;$args=$a;rv i,a;'+(gc \"%%~f0\" -raw))"
echo:rem powershell -NoLogo -NoProfile -Command "$a=($Env:PS1_ARGS|sls -Pattern '\"(.*?)\"(?=\s|$)|(\S+)' -AllMatches).Matches;if($a.length){$a=@($a|%%%%{$_.value -replace '^\"','' -replace '\"$',''})}else{$a=@()};$input|&{[ScriptBlock]::Create((gc \"%%~f0\" -raw)).Invoke($a)}"
echo:goto :EOF
echo:#^>
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the python file.
:cmdize.py
:: Ascetic way is shorter but less flexible
:: Uncomment the following 3 lines if it is more preferrable
:: echo:@python -x "%%~f0" %%* ^& @goto :EOF
:: type "%~f1"
:: goto :EOF
echo:0^<0# : ^^
echo:"""
echo:@echo off
echo:python "%%~f0" %%*
echo:goto :EOF
echo:"""
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the ruby file.
:cmdize.rb
echo:@break #^^
echo:=begin
echo:@echo off
echo:ruby "%%~f0" %%*
echo:goto :EOF
echo:=end
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the html file. 
:: Supportable file extensions are .hta, .htm and .html. 
:cmdize.hta
:cmdize.htm
:cmdize.html
echo:^<!-- :
echo:@echo off
echo:start "" mshta "%%~f0" %%*
echo:goto :EOF
echo:--^>
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the wsf file. 
:: The environment variable %CMDIZE_ENGINE% allows to declare another 
:: engine (cscript or wscript). 
:: The default value is cscript.
:cmdize.wsf
if not defined CMDIZE_ENGINE set "CMDIZE_ENGINE=cscript"

for /f "usebackq tokens=1,2,* delims=?" %%a in ( "%~f1" ) do for /f "tokens=1,*" %%d in ( "%%b" ) do (
	rem We use this code to transform the "<?xml?>" declaration 
	rem located at the very beginning of the file to the "polyglot" 
	rem form to do it acceptable by the batch file.
	echo:%%a?%%d :
	echo:: %%e ?^>^<!--
	echo:@echo off
	echo:%CMDIZE_ENGINE% //nologo "%%~f0?.wsf" %%*
	echo:goto :EOF
	echo:: --%%c
	more +1 <"%~f1"
	goto :EOF
)
goto :EOF

:: ========================================================================

:: Comvert KiXtart file.
:cmdize.kix
echo:;@echo off
echo:;kix32 "%%~f0" %%*
echo:;goto :EOF
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert AutoIt file.
:cmdize.au3
:cmdize.a3x
echo:;@echo off
echo:;AutoIt3 "%%~f0" %%*
echo:;goto :EOF
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert AutoHotKey file.
:cmdize.ahk
echo:;@echo off
echo:;AutoHotKey "%%~f0" %%*
echo:;goto :EOF
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert PHP file.
:: PHP is supposed to be used as a scripting language in Web. So to avoid
:: possible conflicts with paths to dynamic libraries and to suppress HTTP
:: headers, we use two options "-n" and "-q", respectively.
:cmdize.php
echo:^<^?php/* :
echo:@echo off
echo:php -n -q "%%~f0" %%*
echo:goto :EOF
echo:*/ ?^>
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert Julia file.
:cmdize.jl
echo::"""
echo:@echo off
echo:julia "%%~f0" %%*
echo:goto :EOF
echo:"""
type "%~f1"
goto :EOF

:: ========================================================================

:: EOF

siberia-man
Posts: 208
Joined: 26 Dec 2013 09:28
Contact:

Re: js/vbs/html/hta and more hybrids and chimeras in cmd/bat

#63 Post by siberia-man » 03 Sep 2021 10:10

What has been done

-- fix handling with command line options for PowerShell chimera (when there is the only parameter, it has been stored as a string, not as an array)
-- remove auxiliary variables

Code: Select all

:: USAGE
::     cmdize name [...]
::
:: This tool converts a supported code into a batch file that can be 
:: executed without explicit invoking the executable engine. The script 
:: creates new file and places it under the same directory as the original 
:: one with the same name, replacing the original extension with ".bat". 
:: The content of the new file consists of the original file and the 
:: special header that being the "polyglot" and having some tricks to be a 
:: valid code in batch file and the wrapped code at the same time. 
::
:: FEATURES
:: It does comment on "Option Explicit" in VBScript.
:: "<?xml?>" declaration for wsf-files is expected.
:: "Option Explicit" and "<?xml?>" in a single line only are supported.
:: BOM is not supported at all.
::
:: It is possible to select an engine for JavaScript, VBScript and WSF via 
:: the command line options /E. If it is not pointed especially, CSCRIPT 
:: is used as the default engine for all JavaScript, VBScript and WSF 
:: files. Another valid engine is WSCRIPT. Additionally for JavaScript 
:: files it is possible to set another engine such as NodeJS, Rhino etc. 
:: The predefined option /E DEFAULT resets any previously set engines to 
:: the default value. 
::
:: SEE ALSO
:: Proceed the following links to learn more the origins
::
:: .js
:: http://forum.script-coding.com/viewtopic.php?pid=79210#p79210
:: http://www.dostips.com/forum/viewtopic.php?p=33879#p33879
:: https://gist.github.com/ildar-shaimordanov/88d7a5544c0eeacaa3bc
::
:: .vbs
:: http://www.dostips.com/forum/viewtopic.php?p=33882#p33882
:: http://www.dostips.com/forum/viewtopic.php?p=32485#p32485
::
:: .pl
:: For details and better support see "pl2bat.bat" from Perl distribution
::
:: .sh, .bash
:: http://forum.script-coding.com/viewtopic.php?id=11535
:: http://www.dostips.com/forum/viewtopic.php?f=3&t=7110#p46654
::
:: .ps1
:: http://blogs.msdn.com/b/jaybaz_ms/archive/2007/04/26/powershell-polyglot.aspx
:: http://stackoverflow.com/a/2611487/3627676
::
:: .py
:: http://stackoverflow.com/a/29881143/3627676
:: http://stackoverflow.com/a/17468811/3627676
::
:: .rb
:: https://stackoverflow.com/questions/35094778
::
:: .hta and .html?
:: http://forum.script-coding.com/viewtopic.php?pid=79322#p79322
::
:: .wsf
:: http://www.dostips.com/forum/viewtopic.php?p=33963#p33963
::
:: .kix
::
:: .au3, .a3x
::
:: .ahk
::
:: .php
::
:: .jl
:: https://github.com/JuliaLang/julia/blob/master/doc/src/base/punctuation.md
::
:: COPYRIGHTS
:: Copyright (c) 2014-2021 Ildar Shaimordanov

@echo off

if "%~1" == "" (
	for /f "usebackq tokens=* delims=:" %%s in ( "%~f0" ) do (
		if /i "%%s" == "@echo off" goto :EOF
		echo:%%s
	)
	goto :EOF
)

setlocal

:cmdize.loop.begin
if "%~1" == "" goto :cmdize.loop.end

set "CMDIZE_ENGINE="

if /i "%~1" == "/e" (
	if /i not "%~2" == "default" set "CMDIZE_ENGINE=%~2"
	shift /1
	shift /1
)

if not exist "%~f1" (
	echo:%~n0: File not found: "%~1">&2
	goto :cmdize.loop.continue
)

findstr /i /r /c:"^:cmdize%~x1$" "%~f0" >nul || (
	echo:%~n0: Unsupported extension: "%~1">&2
	goto :cmdize.loop.continue
)

call :cmdize%~x1 "%~1" >"%~dpn1.bat"

:cmdize.loop.continue

shift

goto :cmdize.loop.begin
:cmdize.loop.end

goto :EOF

:: ========================================================================

:: Convert the javascript file. 
:: The environment variable %CMDIZE_ENGINE% allows to declare another 
:: engine (cscript, wscript, node etc). 
:: The default value is cscript.
:cmdize.js
if not defined CMDIZE_ENGINE set "CMDIZE_ENGINE=cscript"
set "CMDIZE_ENGINE_OPTS="
for %%e in ( "%CMDIZE_ENGINE%" ) do (
	if /i "%%~ne" == "cscript" set "CMDIZE_ENGINE_OPTS=//nologo //e:javascript"
	if /i "%%~ne" == "wscript" set "CMDIZE_ENGINE_OPTS=//nologo //e:javascript"
)

echo:0^</*! ::
echo:@echo off
echo:%CMDIZE_ENGINE% %CMDIZE_ENGINE_OPTS% "%%~f0" %%*
echo:goto :EOF */0;
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the vbscript file. 
:: The environment variable %CMDIZE_ENGINE% allows to declare another 
:: engine (cscript or wscript). 
:: The default value is cscript. 
:cmdize.vbs
if not defined CMDIZE_ENGINE set "CMDIZE_ENGINE=cscript"

copy /y nul + nul /a "%TEMP%\%~n0.$$" /a 1>nul
for /f "usebackq" %%s in ( "%TEMP%\%~n0.$$" ) do (
	echo:::'%%~s@echo off
	echo:::'%%~scscript //nologo //e:vbscript "%%~f0" %%*
	echo:::'%%~sgoto :EOF
)
del /q "%TEMP%\%~n0.$$"

rem type "%~f1"
for /f "tokens=1,* delims=]" %%r in ( 'find /n /v "" ^<"%~f1"' ) do (
	rem Filtering and commenting "Option Explicit". 
	rem This ugly code tries as much as possible to recognize and 
	rem comment this directive. It fails if "Option" and "Explicit" 
	rem are located on two neighbor lines, consecutively, one by one. 
	rem But it is too hard to imagine that there is someone who 
	rem practices such a strange coding style. 
	for /f "usebackq tokens=1,2" %%a in ( '%%s' ) do if /i "%%~a" == "Option" for /f "usebackq tokens=1,* delims=:'" %%i in ( 'x%%b' ) do if /i "%%~i" == "xExplicit" (
		echo:%~n0: Commenting Option Explicit in "%~1">&2
		echo:rem To prevent compilation error due to embedding into a batch file, 
		echo:rem the following line was commented automatically.
		set /p "=rem " <nul
	)
	echo:%%s
)
goto :EOF

:: ========================================================================

:: Convert the perl file.
:cmdize.pl
if /i "%CMDIZE_ENGINE%" == "cmd" (
	echo:@echo off
	echo:perl -x -S "%%~dpn0.pl" %%*
	goto :EOF
)

echo:@rem = '--*-Perl-*--
echo:@echo off
echo:perl -x -S "%%~f0" %%*
echo:goto :EOF
echo:@rem ';
echo:#!perl
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert Bourne shell and Bash scripts. 
:cmdize.sh
:cmdize.bash
echo:: ^<^< '____CMD____'
echo:@echo off
echo:bash "%%~f0" %%*
echo:goto :eof
echo:____CMD____
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the powershell file. 
:cmdize.ps1
echo:^<# :
echo:@echo off
echo:setlocal
echo:set "PS1_ARGS=%%*"
echo:powershell -NoLogo -NoProfile -Command "$a=($Env:PS1_ARGS|sls -Pattern '\"(.*?)\"(?=\s|$)|(\S+)' -AllMatches).Matches;if($a.length){$a=@($a|%%%%{$_.value -replace '^\"','' -replace '\"$',''})}else{$a=@()};$i=$input;iex $('$input=$i;$args=$a;rv i,a;'+(gc \"%%~f0\" -raw))"
echo:rem powershell -NoLogo -NoProfile -Command "$a=($Env:PS1_ARGS|sls -Pattern '\"(.*?)\"(?=\s|$)|(\S+)' -AllMatches).Matches;if($a.length){$a=@($a|%%%%{$_.value -replace '^\"','' -replace '\"$',''})}else{$a=@()};$input|&{[ScriptBlock]::Create('rv a -scope script;'+(gc \"%%~f0\" -raw)).Invoke($a)}"
echo:goto :EOF
echo:#^>
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the python file.
:cmdize.py
:: Ascetic way is shorter but less flexible
:: Uncomment the following 3 lines if it is more preferrable
:: echo:@python -x "%%~f0" %%* ^& @goto :EOF
:: type "%~f1"
:: goto :EOF
echo:0^<0# : ^^
echo:"""
echo:@echo off
echo:python "%%~f0" %%*
echo:goto :EOF
echo:"""
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the ruby file.
:cmdize.rb
echo:@break #^^
echo:=begin
echo:@echo off
echo:ruby "%%~f0" %%*
echo:goto :EOF
echo:=end
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the html file. 
:: Supportable file extensions are .hta, .htm and .html. 
:cmdize.hta
:cmdize.htm
:cmdize.html
echo:^<!-- :
echo:@echo off
echo:start "" mshta "%%~f0" %%*
echo:goto :EOF
echo:--^>
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the wsf file. 
:: The environment variable %CMDIZE_ENGINE% allows to declare another 
:: engine (cscript or wscript). 
:: The default value is cscript.
:cmdize.wsf
if not defined CMDIZE_ENGINE set "CMDIZE_ENGINE=cscript"

for /f "usebackq tokens=1,2,* delims=?" %%a in ( "%~f1" ) do for /f "tokens=1,*" %%d in ( "%%b" ) do (
	rem We use this code to transform the "<?xml?>" declaration 
	rem located at the very beginning of the file to the "polyglot" 
	rem form to do it acceptable by the batch file.
	echo:%%a?%%d :
	echo:: %%e ?^>^<!--
	echo:@echo off
	echo:%CMDIZE_ENGINE% //nologo "%%~f0?.wsf" %%*
	echo:goto :EOF
	echo:: --%%c
	more +1 <"%~f1"
	goto :EOF
)
goto :EOF

:: ========================================================================

:: Comvert KiXtart file.
:cmdize.kix
echo:;@echo off
echo:;kix32 "%%~f0" %%*
echo:;goto :EOF
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert AutoIt file.
:cmdize.au3
:cmdize.a3x
echo:;@echo off
echo:;AutoIt3 "%%~f0" %%*
echo:;goto :EOF
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert AutoHotKey file.
:cmdize.ahk
echo:;@echo off
echo:;AutoHotKey "%%~f0" %%*
echo:;goto :EOF
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert PHP file.
:: PHP is supposed to be used as a scripting language in Web. So to avoid
:: possible conflicts with paths to dynamic libraries and to suppress HTTP
:: headers, we use two options "-n" and "-q", respectively.
:cmdize.php
echo:^<^?php/* :
echo:@echo off
echo:php -n -q "%%~f0" %%*
echo:goto :EOF
echo:*/ ?^>
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert Julia file.
:cmdize.jl
echo::"""
echo:@echo off
echo:julia "%%~f0" %%*
echo:goto :EOF
echo:"""
type "%~f1"
goto :EOF

:: ========================================================================

:: EOF

siberia-man
Posts: 208
Joined: 26 Dec 2013 09:28
Contact:

Re: js/vbs/html/hta and more hybrids and chimeras in cmd/bat

#64 Post by siberia-man » 11 Oct 2021 12:27

Few days ago I accepted the PR titled as "Specify "find" command":
Users (like me) who have UNIX tools in their PATH variable might call a different find.exe which will break this script. Therefore prepending "%SYSTEMROOT%\System32" makes the call to find.exe unambiguous.
This action inspired me for some improvements. Finally, I added many improvements:

-- went away of using "find" in favor of "findstr"
-- improved processing the "/E" option
-- improved еру description
-- unified the bi-lingual prolog creation
-- added the "/L" option to display the list of supported file types
-- improved handling with WSF-files
-- improved handling with VBS-files

Code: Select all

:: USAGE
::     cmdize name [...]
::
:: This tool converts a script into a batch file allowing to use the
:: script like regular programs and batch scripts without invoking an
:: executable engine explicitly and just typing the script name without
:: extension. The resulting batch file is placed next to the original
:: script.
::
:: The new file consist of the body of the script prepended with the
:: special header (or prolog) being the "polyglot" and having some tricks
:: to be a valid code both for the batch and original script.
::
:: FEATURES
:: Use /L to display the list of supported file extensions and set of
:: applicable values for /E.
::
:: The tool looks for the directive "Option Explicit" and comments it
:: out while creating the batch file.
::
:: If "<?xml?>" is recognized as the first element of the wsf file,
:: it is parsed and modified to avoid execution error.
::
:: Both "Option Explicit" and "<?xml?>" are supported as placed on a
:: single line only.
::
:: BOM (Byte Order Mark) are not supported at all.
::
:: JavaScript, VBScript and WSF defaults an engine to CSCRIPT. Another
:: engine can be specified with the /E option. For example WSCRIPT for
:: those above or NODE for JavaScript. /E DEFAULT is the special option
:: that resets any previously set engines to the default value.
::
:: /E CMDONLY is for Perl only. It creates the pure batch file without
:: merging with the original Perl script. It can be useful in some
:: cases. The original Perl script and the newly created batch file
:: should be placed together and visible via PATH.
::
:: /E SHORT is for Python only. It creates ascetic prolog which is
:: shorter and less flexible.
::
:: SEE ALSO
:: Proceed the following links to learn more the origins
::
:: .js
:: http://forum.script-coding.com/viewtopic.php?pid=79210#p79210
:: http://www.dostips.com/forum/viewtopic.php?p=33879#p33879
:: https://gist.github.com/ildar-shaimordanov/88d7a5544c0eeacaa3bc
::
:: .vbs
:: http://www.dostips.com/forum/viewtopic.php?p=33882#p33882
:: http://www.dostips.com/forum/viewtopic.php?p=32485#p32485
::
:: .pl
:: For details and better support see "pl2bat.bat" from Perl distribution
::
:: .sh, .bash
:: http://forum.script-coding.com/viewtopic.php?id=11535
:: http://www.dostips.com/forum/viewtopic.php?f=3&t=7110#p46654
::
:: .ps1
:: http://blogs.msdn.com/b/jaybaz_ms/archive/2007/04/26/powershell-polyglot.aspx
:: http://stackoverflow.com/a/2611487/3627676
::
:: .py
:: http://stackoverflow.com/a/29881143/3627676
:: http://stackoverflow.com/a/17468811/3627676
::
:: .rb
:: https://stackoverflow.com/questions/35094778
::
:: .hta and .html?
:: http://forum.script-coding.com/viewtopic.php?pid=79322#p79322
::
:: .wsf
:: http://www.dostips.com/forum/viewtopic.php?p=33963#p33963
::
:: .kix
::
:: .au3, .a3x
::
:: .ahk
::
:: .php
::
:: .jl
:: https://github.com/JuliaLang/julia/blob/master/doc/src/base/punctuation.md
::
:: COPYRIGHTS
:: Copyright (c) 2014-2021 Ildar Shaimordanov

@echo off

if "%~1" == "" (
	for /f "usebackq tokens=* delims=:" %%s in ( "%~f0" ) do (
		if /i "%%s" == "@echo off" goto :EOF
		echo:%%s
	)
	goto :EOF
)

if /i "%~1" == "/L" (
	for /f "tokens=1,* delims=." %%x in ( 'findstr /i /r "^:cmdize[.][0-9a-z_][0-9a-z_]*\>" "%~f0"' ) do echo:.%%~y
	goto :EOF
)

setlocal

:cmdize_loop_begin
if "%~1" == "" goto :cmdize_loop_end

set "CMDIZE_ENGINE="

if /i "%~1" == "/e" (
	if /i not "%~2" == "default" set "CMDIZE_ENGINE=%~2"
	shift /1
	shift /1
)

if not exist "%~f1" (
	echo:%~n0: File not found: "%~1">&2
	goto :cmdize_loop_continue
)

findstr /i /b /l ":cmdize%~x1" "%~f0" >nul || (
	echo:%~n0: Unsupported extension: "%~1">&2
	goto :cmdize_loop_continue
)

call :cmdize%~x1 "%~1" >"%~dpn1.bat"

:cmdize_loop_continue

shift /1

goto :cmdize_loop_begin
:cmdize_loop_end

goto :EOF

:: ========================================================================

:: Convert the javascript file.
:: The environment variable %CMDIZE_ENGINE% allows to declare another
:: engine (cscript, wscript, node etc).
:: The default value is cscript.
:cmdize.js	[/e cscript|wscript|node|...]
if not defined CMDIZE_ENGINE set "CMDIZE_ENGINE=cscript"
for %%d in ( cscript wscript ) do for %%e in ( "%CMDIZE_ENGINE%" ) do if /i "%%d" == "%%~ne" set "CMDIZE_ENGINE=%CMDIZE_ENGINE% //nologo //e:javascript"

call :print-prolog "%CMDIZE_ENGINE%" "0</*! ::" "*/0;"
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the vbscript file.
:: The environment variable %CMDIZE_ENGINE% allows to declare another
:: engine (cscript or wscript).
:: The default value is cscript.
:cmdize.vbs	[/e cscript|wscript]
if not defined CMDIZE_ENGINE set "CMDIZE_ENGINE=cscript"

copy /y nul + nul /a "%TEMP%\%~n0.$$" /a 1>nul
for /f "usebackq" %%s in ( "%TEMP%\%~n0.$$" ) do (
	call :print-prolog "%CMDIZE_ENGINE% //nologo //e:vbscript" "" "" "::'%%~s"
)
del /q "%TEMP%\%~n0.$$"

for /f "tokens=1,* delims=:" %%r in ( 'findstr /n /r "^" "%~f1"' ) do (
	rem Filtering and commenting "Option Explicit".

	rem Weird and insane attempt to implement it using capabilities
	rem of batch scripting only.

	rem This ugly code tries as much as it can to recognize and
	rem comment out this directive. It's flexible enough to find
	rem the directive even the string contains an arbitrary amount
	rem of whitespaces. It fails if both "Option" and "Explicit"
	rem are located on different lines. But it's too hard to imagine
	rem that someone practices such a strange coding style.

	rem In the other hand, it still tries to recognize the rest of
	rem the line after the directive and put it to the next line,
	rem if it contains an executable code.

	if "%%s" == "" (
		echo:%%s
	) else for /f "tokens=1,*" %%a in ( "%%s" ) do if /i not "%%a" == "Option" (
		echo:%%s
	) else for /f "tokens=1,* delims=':	 " %%i in ( "%%b" ) do if /i not "%%i" == "Explicit" (
		echo:%%s
	) else (
		echo:%~n0: Commenting "Option Explicit" in "%~1">&2
		echo:rem To avoid compilation error due to embedding into a batch file,
		echo:rem the following line was commented out automatically.
		set /p "=rem " <nul

		if /i "%%b" == "Explicit" (
			rem Option Explicit
			echo:%%s
		) else for /f "tokens=1,* delims='" %%i in ( "%%b" ) do if /i "%%i" == "Explicit" (
			rem Option Explicit {QUOTE} ...
			echo:%%s
		) else for /f "tokens=1,* delims=:	 " %%i in ( "%%b" ) do if /i "%%i" == "Explicit" (
			rem Option Explicit {COLON|TAB|SPACE} ...
			echo:%%a %%i
			echo:%%j
		)
	)
)
goto :EOF

:: ========================================================================

:: Convert the perl file.
:cmdize.pl	[/e cmdonly]
if /i "%CMDIZE_ENGINE%" == "cmdonly" (
	echo:@echo off
	echo:perl -x -S "%%~dpn0.pl" %%*
	goto :EOF
)

call :print-prolog "perl -x -S" "@rem = '--*-Perl-*--" "@rem ';"
echo:#!perl
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert Bourne shell and Bash scripts.
:cmdize.sh
:cmdize.bash
call :print-prolog bash ": << '____CMD____'" "____CMD____"
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the powershell file.
:cmdize.ps1
echo:^<# :
echo:@echo off
echo:setlocal
echo:set "PS1_ARGS=%%*"
echo:powershell -NoLogo -NoProfile -Command "$a=($Env:PS1_ARGS|sls -Pattern '\"(.*?)\"(?=\s|$)|(\S+)' -AllMatches).Matches;if($a.length){$a=@($a|%%%%{$_.value -replace '^\"','' -replace '\"$',''})}else{$a=@()};$i=$input;iex $('$input=$i;$args=$a;rv i,a;'+(gc \"%%~f0\" -raw))"
echo:rem powershell -NoLogo -NoProfile -Command "$a=($Env:PS1_ARGS|sls -Pattern '\"(.*?)\"(?=\s|$)|(\S+)' -AllMatches).Matches;if($a.length){$a=@($a|%%%%{$_.value -replace '^\"','' -replace '\"$',''})}else{$a=@()};$input|&{[ScriptBlock]::Create('rv a -scope script;'+(gc \"%%~f0\" -raw)).Invoke($a)}"
echo:goto :EOF
echo:#^>
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the python file.
:cmdize.py	[/e short]
if /i "%CMDIZE_ENGINE%" == "short" (
	echo:@python -x "%%~f0" %%* ^& @goto :EOF
	type "%~f1"
	goto :EOF
)
echo:0^<0# : ^^
echo:"""
call :print-prolog python
echo:"""
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the ruby file.
:cmdize.rb
echo:@break #^^
call :print-prolog ruby "=begin" "=end"
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the html file.
:: Supportable file extensions are .hta, .htm and .html.
:cmdize.hta
:cmdize.htm
:cmdize.html
call :print-prolog "start "" mshta" "<!-- :" "-->"
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the wsf file.
:: The environment variable %CMDIZE_ENGINE% allows to declare another
:: engine (cscript or wscript).
:: The default value is cscript.
:cmdize.wsf	[/e cscript|wscript]
if not defined CMDIZE_ENGINE set "CMDIZE_ENGINE=cscript"

for /f "tokens=1,* delims=:" %%n in ( 'findstr /i /n /r "<?xml.*?>" "%~f1"' ) do for /f "tokens=1,2,* delims=?" %%a in ( "%%~o" ) do if %%~n neq 1 (
	echo:Incorrect XML declaration: it must be at the beginning of the script>&2
	exit /b 1
) else for /f "tokens=1,*" %%d in ( "%%b" ) do (
	rem We sure that the XML declaration is located on the first
	rem line of the script. Now we can transform it to the "polyglot"
	rem form acceptable by the batch file also.
	echo:%%a?%%d :
	echo:: %%e?^>^<!--

	call :print-prolog "%CMDIZE_ENGINE% //nologo" "" "" "" "?.wsf"

	echo:: --%%c
	more +1 <"%~f1"
	goto :EOF
)

call :print-prolog "%CMDIZE_ENGINE% //nologo" "<!-- :" "-->" "" "?.wsf"
type "%~f1"
goto :EOF

:: ========================================================================

:: Comvert KiXtart file.
:cmdize.kix
call :print-prolog kix32 "" "" ";"
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert AutoIt file.
:cmdize.au3
:cmdize.a3x
call :print-prolog AutoIt3 "" "" ";"
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert AutoHotKey file.
:cmdize.ahk
call :print-prolog AutoHotKey "" "" ";"
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert PHP file.
:: PHP is supposed to be used as a scripting language in Web. So to avoid
:: possible conflicts with paths to dynamic libraries and to suppress HTTP
:: headers, we use two options "-n" and "-q", respectively.
:cmdize.php
call :print-prolog "php -n -q" "<?php/* :" "*/ ?>"
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert Julia file.
:cmdize.jl
echo::"""
call :print-prolog julia
echo:"""
type "%~f1"
goto :EOF

:: ========================================================================

:: call :print-prolog engine
:: call :print-prolog engine tag1 tag2
:: call :print-prolog engine "" "" prefix
::
:: %1 - engine (the command to invoke the script)
:: %2 - opening tag (used to hide batch commands wrapping them within tags)
:: %3 - closing tag
:: %4 - prefix (used to hide batch commands in place)
:: %5 - "?.wsf" for wsf files only
:print-prolog
setlocal

set "tag=%~2"
if defined tag (
	setlocal enabledelayedexpansion
	echo:!tag!
	setlocal
)

echo:%~4@echo off
echo:%~4%~1 "%%~f0%~5" %%*
echo:%~4goto :EOF

set "tag=%~3"
if defined tag (
	setlocal enabledelayedexpansion
	echo:!tag!
	setlocal
)

endlocal
goto :EOF

:: ========================================================================

:: EOF
The latest version is here https://github.com/ildar-shaimordanov/c ... cmdize.bat

siberia-man
Posts: 208
Joined: 26 Dec 2013 09:28
Contact:

Re: js/vbs/html/hta and more hybrids and chimeras in cmd/bat

#65 Post by siberia-man » 25 Oct 2021 20:22

wsf, js: cosmetic changes
improve command line option processing
vbs: /w for creating vbs+wsf+bat alternative
ps1: shorten chimera for powershell

The latest version is here https://github.com/ildar-shaimordanov/c ... cmdize.bat

Code: Select all

:: USAGE
::     cmdize name [...]
::
:: This tool converts a script into a batch file allowing to use the
:: script like regular programs and batch scripts without invoking an
:: executable engine explicitly and just typing the script name without
:: extension. The resulting batch file is placed next to the original
:: script.
::
:: The new file consist of the body of the script prepended with the
:: special header (or prolog) being the "polyglot" and having some tricks
:: to be a valid code both for the batch and original script.
::
:: FEATURES
:: Use /L to display the list of supported file extensions and set of
:: applicable values for /E.
::
:: The tool looks for the directive "Option Explicit" and comments it
:: out while creating the batch file.
::
:: If "<?xml?>" is recognized as the first element of the wsf file,
:: it is parsed and modified to avoid execution error.
::
:: Both "Option Explicit" and "<?xml?>" are supported as placed on a
:: single line only.
::
:: BOM (Byte Order Mark) are not supported at all.
::
:: JavaScript, VBScript and WSF defaults an engine to CSCRIPT. Another
:: engine can be specified with the /E option. For example WSCRIPT for
:: those above or NODE for JavaScript. /E DEFAULT is the special option
:: that resets any previously set engines to the default value.
::
:: /E CMDONLY is for Perl only. It creates the pure batch file without
:: merging with the original Perl script. It can be useful in some
:: cases. The original Perl script and the newly created batch file
:: should be placed together and visible via PATH.
::
:: /E SHORT is for Python only. It creates ascetic prolog which is
:: shorter and less flexible.
::
:: /W enables WSF+BAT alternative for VBScript only.
::
:: SEE ALSO
:: Proceed the following links to learn more the origins
::
:: .js
:: http://forum.script-coding.com/viewtopic.php?pid=79210#p79210
:: http://www.dostips.com/forum/viewtopic.php?p=33879#p33879
:: https://gist.github.com/ildar-shaimordanov/88d7a5544c0eeacaa3bc
::
:: .vbs
:: http://www.dostips.com/forum/viewtopic.php?p=33882#p33882
:: http://www.dostips.com/forum/viewtopic.php?p=32485#p32485
::
:: .pl
:: For details and better support see "pl2bat.bat" from Perl distribution
::
:: .sh, .bash
:: http://forum.script-coding.com/viewtopic.php?id=11535
:: http://www.dostips.com/forum/viewtopic.php?f=3&t=7110#p46654
::
:: .ps1
:: http://blogs.msdn.com/b/jaybaz_ms/archive/2007/04/26/powershell-polyglot.aspx
:: http://stackoverflow.com/a/2611487/3627676
::
:: .py
:: http://stackoverflow.com/a/29881143/3627676
:: http://stackoverflow.com/a/17468811/3627676
::
:: .rb
:: https://stackoverflow.com/questions/35094778
::
:: .hta and .html?
:: http://forum.script-coding.com/viewtopic.php?pid=79322#p79322
::
:: .wsf
:: http://www.dostips.com/forum/viewtopic.php?p=33963#p33963
::
:: .kix
::
:: .au3, .a3x
::
:: .ahk
::
:: .php
::
:: .jl
:: https://github.com/JuliaLang/julia/blob/master/doc/src/base/punctuation.md
::
:: COPYRIGHTS
:: Copyright (c) 2014-2021 Ildar Shaimordanov

@echo off

if "%~1" == "" (
	for /f "usebackq tokens=* delims=:" %%s in ( "%~f0" ) do (
		if /i "%%s" == "@echo off" goto :EOF
		echo:%%s
	)
	goto :EOF
)

if /i "%~1" == "/L" (
	for /f "tokens=1,* delims=." %%x in ( 'findstr /i /r "^:cmdize[.][0-9a-z_][0-9a-z_]*\>" "%~f0"' ) do echo:.%%~y
	goto :EOF
)

setlocal

set "CMDIZE_ERROR=0"
set "CMDIZE_WRAP="
set "CMDIZE_ENGINE="

:cmdize_loop_begin
if "%~1" == "" exit /b %CMDIZE_ERROR%

if /i "%~1" == "/w" (
	set "CMDIZE_WRAP=1"
	shift /1
	goto :cmdize_loop_begin
)

if /i "%~1" == "/e" (
	if /i "%~2" == "default" (
		set "CMDIZE_ENGINE="
	) else (
		set "CMDIZE_ENGINE=%~2"
	)
	shift /1
	shift /1
	goto :cmdize_loop_begin
)

if not exist "%~f1" (
	shift /1
	set "CMDIZE_ERROR=1"
	call :warn File not found: "%~1"
	goto :cmdize_loop_begin
)

findstr /i /b /l ":cmdize%~x1" "%~f0" >nul || (
	shift /1
	set "CMDIZE_ERROR=1"
	call :warn Unsupported extension: "%~1"
	goto :cmdize_loop_begin
)

call :cmdize%~x1 "%~1" >"%~dpn1.bat"
shift /1
goto :cmdize_loop_begin

:: ========================================================================

:: Convert the javascript file.
:: The environment variable %CMDIZE_ENGINE% allows to declare another
:: engine (cscript, wscript, node etc).
:: The default value is cscript.
:cmdize.js	[/e cscript|wscript|cchakra|wchakra|ch|node|...]
if not defined CMDIZE_ENGINE set "CMDIZE_ENGINE=cscript"

for %%e in ( "%CMDIZE_ENGINE%" ) do for %%s in (
	"cscript cscript javascript"
	"wscript wscript javascript"
	"cchakra cscript {16d51579-a30b-4c8b-a276-0ff4dc41e755}"
	"wchakra wscript {16d51579-a30b-4c8b-a276-0ff4dc41e755}"
) do for /f "tokens=1,2,3" %%a in ( "%%~s" ) do if "%%~e" == "%%~a" (
	call :print-prolog "%%~b //nologo //e:%%~c" "0</*! ::" "*/0;"
	type "%~f1"
)

goto :EOF

:: ========================================================================

:: Convert the vbscript file.
:: The environment variable %CMDIZE_ENGINE% allows to declare another
:: engine (cscript or wscript).
:: The default value is cscript.
:cmdize.vbs	[/w] [/e cscript|wscript]
if not defined CMDIZE_ENGINE set "CMDIZE_ENGINE=cscript"

if defined CMDIZE_WRAP (
	call :print-script-wsf-bat "%~f1" vbscript
	goto :EOF
)

copy /y nul + nul /a "%TEMP%\%~n0.$$" /a 1>nul
for /f "usebackq" %%s in ( "%TEMP%\%~n0.$$" ) do (
	call :print-prolog "%CMDIZE_ENGINE% //nologo //e:vbscript" "" "" "::'%%~s"
)
del /q "%TEMP%\%~n0.$$"

for /f "tokens=1,* delims=:" %%r in ( 'findstr /n /r "^" "%~f1"' ) do (
	rem Filtering and commenting "Option Explicit".

	rem Weird and insane attempt to implement it using capabilities
	rem of batch scripting only.

	rem This ugly code tries as much as it can to recognize and
	rem comment out this directive. It's flexible enough to find
	rem the directive even the string contains an arbitrary amount
	rem of whitespaces. It fails if both "Option" and "Explicit"
	rem are located on different lines. But it's too hard to imagine
	rem that someone practices such a strange coding style.

	rem In the other hand, it still tries to recognize the rest of
	rem the line after the directive and put it to the next line,
	rem if it contains an executable code.

	if "%%s" == "" (
		echo:%%s
	) else for /f "tokens=1,*" %%a in ( "%%s" ) do if /i not "%%a" == "Option" (
		echo:%%s
	) else for /f "tokens=1,* delims=':	 " %%i in ( "%%b" ) do if /i not "%%i" == "Explicit" (
		echo:%%s
	) else (
		call :warn Commenting "Option Explicit" in "%~1"
		echo:rem To avoid compilation error due to embedding into a batch file,
		echo:rem the following line was commented out automatically.
		set /p "=rem " <nul

		if /i "%%b" == "Explicit" (
			rem Option Explicit
			echo:%%s
		) else for /f "tokens=1,* delims='" %%i in ( "%%b" ) do if /i "%%i" == "Explicit" (
			rem Option Explicit {QUOTE} ...
			echo:%%s
		) else for /f "tokens=1,* delims=:	 " %%i in ( "%%b" ) do if /i "%%i" == "Explicit" (
			rem Option Explicit {COLON|TAB|SPACE} ...
			echo:%%a %%i
			echo:%%j
		)
	)
)
goto :EOF

:: ========================================================================

:: Convert the perl file.
:cmdize.pl	[/e cmdonly]
if /i "%CMDIZE_ENGINE%" == "cmdonly" (
	echo:@echo off
	echo:perl -x -S "%%~dpn0.pl" %%*
	goto :EOF
)

call :print-prolog "perl -x -S" "@rem = '--*-Perl-*--" "@rem ';"
echo:#!perl
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert Bourne shell and Bash scripts.
:cmdize.sh
:cmdize.bash
call :print-prolog bash ": << '____CMD____'" "____CMD____"
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the powershell file.
:cmdize.ps1
echo:^<# :
echo:@echo off
echo:setlocal
echo:rem Any non-empty value changes the script invocation: the script is
echo:rem executed using ScriptBlock instead of Invoke-Expression as default.
echo:set "PS1_ISB="
echo:set "PS1_FILE=%%~f0"
echo:set "PS1_ARGS=%%*"
echo:powershell -NoLogo -NoProfile -Command "$a=($Env:PS1_ARGS|sls -Pattern '\"(.*?)\"(?=\s|$)|(\S+)' -AllMatches).Matches;$a=@(@(if($a.count){$a})|%%%%{$_.value -Replace '^\"','' -Replace '\"$',''});$f=gc $Env:PS1_FILE -Raw;if($Env:PS1_ISB){$input|&{[ScriptBlock]::Create('rv f,a -Scope Script;'+$f).Invoke($a)}}else{$i=$input;iex $('$input=$i;$args=$a;rv i,f,a;'+$f)}"
echo:goto :EOF
echo:#^>
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the python file.
:cmdize.py	[/e short]
if /i "%CMDIZE_ENGINE%" == "short" (
	echo:@python -x "%%~f0" %%* ^& @goto :EOF
	type "%~f1"
	goto :EOF
)
echo:0^<0# : ^^
echo:"""
call :print-prolog python
echo:"""
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the ruby file.
:cmdize.rb
echo:@break #^^
call :print-prolog ruby "=begin" "=end"
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the html file.
:: Supportable file extensions are .hta, .htm and .html.
:cmdize.hta
:cmdize.htm
:cmdize.html
call :print-prolog "start "" mshta" "<!-- :" "-->"
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert the wsf file.
:: The environment variable %CMDIZE_ENGINE% allows to declare another
:: engine (cscript or wscript).
:: The default value is cscript.
:cmdize.wsf	[/e cscript|wscript]
if not defined CMDIZE_ENGINE set "CMDIZE_ENGINE=cscript"

set "CMDIZE_ERROR="

for /f "tokens=1,* delims=:" %%n in ( 'findstr /i /n /r "<?xml.*?>" "%~f1"' ) do for /f "tokens=1,2,* delims=?" %%a in ( "%%~o" ) do for /f "tokens=1,*" %%d in ( "%%b" ) do (
	if %%n neq 1 set "CMDIZE_ERROR=1"
	if not "%%a" == "<" set "CMDIZE_ERROR=1"
	if defined CMDIZE_ERROR (
		call :warn Incorrect XML declaration: it must be at the beginning of the script
		exit /b 1
	)

	rem We sure that the XML declaration is located on the first
	rem line of the script. Now we can transform it to the "polyglot"
	rem form acceptable by the batch file also.

	rem <?xml...?>...

	rem <?xml :
	rem ...?><!-- :
	rem prolog
	rem : -->...

	echo:%%a?%%d :
	call :print-prolog "%CMDIZE_ENGINE% //nologo" ": %%e?><!-- :" ": --%%c" "" "?.wsf"

	for /f "tokens=1,* delims=:" %%a in ( 'findstr /n /r "^" "%~f1"' ) do (
		if %%a gtr 1 echo:%%b
	)
	goto :EOF
)

call :print-prolog "%CMDIZE_ENGINE% //nologo" "<!-- :" "-->" "" "?.wsf"
type "%~f1"
goto :EOF

:: ========================================================================

:: Comvert KiXtart file.
:cmdize.kix
call :print-prolog kix32 "" "" ";"
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert AutoIt file.
:cmdize.au3
:cmdize.a3x
call :print-prolog AutoIt3 "" "" ";"
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert AutoHotKey file.
:cmdize.ahk
call :print-prolog AutoHotKey "" "" ";"
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert PHP file.
:: PHP is supposed to be used as a scripting language in Web. So to avoid
:: possible conflicts with paths to dynamic libraries and to suppress HTTP
:: headers, we use two options "-n" and "-q", respectively.
:cmdize.php
call :print-prolog "php -n -q" "<?php/* :" "*/ ?>"
type "%~f1"
goto :EOF

:: ========================================================================

:: Convert Julia file.
:cmdize.jl
echo::"""
call :print-prolog julia
echo:"""
type "%~f1"
goto :EOF

:: ========================================================================

:warn
>&2 echo:%~n0: %*
goto :EOF

:: ========================================================================

:print-script-wsf-bat
for %%f in ( "%TEMP%\%~n1.wsf" ) do (
	call :print-script-wsf "%~f1" %~2 >"%%~ff"
	call :cmdize.wsf "%%~ff"
	del /f /q "%%~ff"
)
goto :EOF

:print-script-wsf
echo:^<?xml version="1.0" ?^>
echo:^<package^>^<job id="cmdized"^>^<script language="%~2"^>^<^![CDATA[
type "%~f1"
echo:]]^>^</script^>^</job^>^</package^>
goto :EOF

:: ========================================================================

:: call :print-prolog engine
:: call :print-prolog engine tag1 tag2
:: call :print-prolog engine "" "" prefix
::
:: %1 - engine (the command to invoke the script)
:: %2 - opening tag (used to hide batch commands wrapping them within tags)
:: %3 - closing tag
:: %4 - prefix (used to hide batch commands in place)
:: %5 - "?.wsf" for wsf files only
:print-prolog
setlocal

set "tag=%~2"
if defined tag (
	setlocal enabledelayedexpansion
	echo:!tag!
	setlocal
)

echo:%~4@echo off
echo:%~4%~1 "%%~f0%~5" %%*
echo:%~4goto :EOF

set "tag=%~3"
if defined tag (
	setlocal enabledelayedexpansion
	echo:!tag!
	setlocal
)

endlocal
goto :EOF

:: ========================================================================

:: EOF

Post Reply