summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pygments/lexers/shell.py326
-rw-r--r--tests/examplefiles/batchfile.bat49
-rw-r--r--tests/examplefiles/example.bat205
3 files changed, 494 insertions, 86 deletions
diff --git a/pygments/lexers/shell.py b/pygments/lexers/shell.py
index 1bbfd7a7..0a89aeaa 100644
--- a/pygments/lexers/shell.py
+++ b/pygments/lexers/shell.py
@@ -11,7 +11,8 @@
import re
-from pygments.lexer import Lexer, RegexLexer, do_insertions, bygroups, include
+from pygments.lexer import Lexer, RegexLexer, do_insertions, bygroups, \
+ include, default, this, using, words
from pygments.token import Punctuation, \
Text, Comment, Operator, Keyword, Name, String, Number, Generic
from pygments.util import shebang_matches
@@ -229,46 +230,297 @@ class BatchLexer(RegexLexer):
flags = re.MULTILINE | re.IGNORECASE
+ _nl = r'\n\x1a'
+ _punct = r'&<>|'
+ _ws = r'\t\v\f\r ,;=\xa0'
+ _space = r'(?:(?:(?:\^[%s])?[%s])+)' % (_nl, _ws)
+ _keyword_terminator = (r'(?=(?:\^[%s]?)?[%s+./:[\\\]]|[%s%s(])' %
+ (_nl, _ws, _nl, _punct))
+ _token_terminator = r'(?=\^?[%s]|[%s%s])' % (_ws, _punct, _nl)
+ _start_label = r'((?:(?<=^[^:])|^[^:]?)[%s]*)(:)' % _ws
+ _label = r'(?:(?:[^%s%s%s+:^]|\^[%s]?[\w\W])*)' % (_nl, _punct, _ws, _nl)
+ _label_compound = (r'(?:(?:[^%s%s%s+:^)]|\^[%s]?[^)])*)' %
+ (_nl, _punct, _ws, _nl))
+ _number = r'(?:-?(?:0[0-7]+|0x[\da-f]+|\d+)%s)' % _token_terminator
+ _opword = r'(?:equ|geq|gtr|leq|lss|neq)'
+ _string = r'(?:"[^%s"]*"?)' % _nl
+ _variable = (r'(?:(?:%%(?:\*|(?:~[a-z]*(?:\$[^:]+:)?)?\d|'
+ r'[^%%:%s]+(?::(?:~(?:-?\d+)?(?:,(?:-?\d+)?)?|(?:[^%%%s^]|'
+ r'\^[^%%%s])[^=%s]*=(?:[^%%%s^]|\^[^%%%s])*)?)?%%))|'
+ r'(?:\^?![^!:%s]+(?::(?:~(?:-?\d+)?(?:,(?:-?\d+)?)?|(?:'
+ r'[^!%s^]|\^[^!%s])[^=%s]*=(?:[^!%s^]|\^[^!%s])*)?)?\^?!))' %
+ (_nl, _nl, _nl, _nl, _nl, _nl, _nl, _nl, _nl, _nl, _nl, _nl))
+ _core_token = r'(?:(?:(?:\^[%s]?)?[^%s%s%s])+)' % (_nl, _nl, _punct, _ws)
+ _core_token_compound = r'(?:(?:(?:\^[%s]?)?[^%s%s%s)])+)' % (_nl, _nl,
+ _punct, _ws)
+ _token = r'(?:[%s]+|%s)' % (_punct, _core_token)
+ _token_compound = r'(?:[%s]+|%s)' % (_punct, _core_token_compound)
+ _stoken = (r'(?:[%s]+|(?:%s|%s|%s)+)' %
+ (_punct, _string, _variable, _core_token))
+
+ def _make_begin_state(compound, _core_token=_core_token,
+ _core_token_compound=_core_token_compound,
+ _keyword_terminator=_keyword_terminator,
+ _nl=_nl, _punct=_punct, _string=_string,
+ _space=_space, _start_label=_start_label,
+ _stoken=_stoken, _token_terminator=_token_terminator,
+ _variable=_variable, _ws=_ws):
+ rest = '(?:%s|%s|[^"%%%s%s%s])*' % (_string, _variable, _nl, _punct,
+ ')' if compound else '')
+ rest_of_line = r'(?:(?:[^%s^]|\^[%s]?[\w\W])*)' % (_nl, _nl)
+ rest_of_line_compound = r'(?:(?:[^%s^)]|\^[%s]?[^)])*)' % (_nl, _nl)
+ set_space = r'((?:(?:\^[%s]?)?[^\S\n])*)' % _nl
+ suffix = ''
+ if compound:
+ _keyword_terminator = r'(?:(?=\))|%s)' % _keyword_terminator
+ _token_terminator = r'(?:(?=\))|%s)' % _token_terminator
+ suffix = '/compound'
+ return [
+ ((r'\)', Punctuation, '#pop') if compound else
+ (r'\)((?=\()|%s)%s' % (_token_terminator, rest_of_line),
+ Comment.Single)),
+ (r'(?=%s)' % _start_label, Text, 'follow%s' % suffix),
+ (_space, using(this, state='text')),
+ include('redirect%s' % suffix),
+ (r'[%s]+' % _nl, Text),
+ (r'\(', Punctuation, 'root/compound'),
+ (r'@+', Punctuation),
+ (r'((?:for|if|rem)(?:(?=(?:\^[%s]?)?/)|(?:(?!\^)|'
+ r'(?<=m))(?:(?=\()|%s)))(%s?%s?(?:\^[%s]?)?/(?:\^[%s]?)?\?)' %
+ (_nl, _token_terminator, _space,
+ _core_token_compound if compound else _core_token, _nl, _nl),
+ bygroups(Keyword, using(this, state='text')),
+ 'follow%s' % suffix),
+ (r'(goto%s)(%s(?:\^[%s]?)?/(?:\^[%s]?)?\?%s)' %
+ (_keyword_terminator, rest, _nl, _nl, rest),
+ bygroups(Keyword, using(this, state='text')),
+ 'follow%s' % suffix),
+ (words(('assoc', 'break', 'cd', 'chdir', 'cls', 'color', 'copy',
+ 'date', 'del', 'dir', 'dpath', 'echo', 'endlocal', 'erase',
+ 'exit', 'ftype', 'keys', 'md', 'mkdir', 'mklink', 'move',
+ 'path', 'pause', 'popd', 'prompt', 'pushd', 'rd', 'ren',
+ 'rename', 'rmdir', 'setlocal', 'shift', 'start', 'time',
+ 'title', 'type', 'ver', 'verify', 'vol'),
+ suffix=_keyword_terminator), Keyword, 'follow%s' % suffix),
+ (r'(call)(%s?)(:)' % _space,
+ bygroups(Keyword, using(this, state='text'), Punctuation),
+ 'call%s' % suffix),
+ (r'call%s' % _keyword_terminator, Keyword),
+ (r'(for%s(?!\^))(%s)(/f%s)' %
+ (_token_terminator, _space, _token_terminator),
+ bygroups(Keyword, using(this, state='text'), Keyword),
+ ('for/f', 'for')),
+ (r'(for%s(?!\^))(%s)(/l%s)' %
+ (_token_terminator, _space, _token_terminator),
+ bygroups(Keyword, using(this, state='text'), Keyword),
+ ('for/l', 'for')),
+ (r'for%s(?!\^)' % _token_terminator, Keyword, ('for2', 'for')),
+ (r'(goto%s)(%s?)(:?)' % (_keyword_terminator, _space),
+ bygroups(Keyword, using(this, state='text'), Punctuation),
+ 'label%s' % suffix),
+ (r'(if(?:(?=\()|%s)(?!\^))(%s?)((?:/i%s)?)(%s?)((?:not%s)?)(%s?)' %
+ (_token_terminator, _space, _token_terminator, _space,
+ _token_terminator, _space),
+ bygroups(Keyword, using(this, state='text'), Keyword,
+ using(this, state='text'), Keyword,
+ using(this, state='text')), ('(?', 'if')),
+ (r'rem(((?=\()|%s)%s?%s?.*|%s%s)' %
+ (_token_terminator, _space, _stoken, _keyword_terminator,
+ rest_of_line_compound if compound else rest_of_line),
+ Comment.Single, 'follow%s' % suffix),
+ (r'(set%s)%s(/a)' % (_keyword_terminator, set_space),
+ bygroups(Keyword, using(this, state='text'), Keyword),
+ 'arithmetic%s' % suffix),
+ (r'(set%s)%s((?:/p)?)%s((?:(?:(?:\^[%s]?)?[^"%s%s^=%s]|'
+ r'\^[%s]?[^"=])+)?)((?:(?:\^[%s]?)?=)?)' %
+ (_keyword_terminator, set_space, set_space, _nl, _nl, _punct,
+ ')' if compound else '', _nl, _nl),
+ bygroups(Keyword, using(this, state='text'), Keyword,
+ using(this, state='text'), using(this, state='variable'),
+ Punctuation),
+ 'follow%s' % suffix),
+ default('follow%s' % suffix)
+ ]
+
+ def _make_follow_state(compound, _label=_label,
+ _label_compound=_label_compound, _nl=_nl,
+ _space=_space, _start_label=_start_label,
+ _token=_token, _token_compound=_token_compound,
+ _ws=_ws):
+ suffix = '/compound' if compound else ''
+ state = []
+ if compound:
+ state.append((r'(?=\))', Text, '#pop'))
+ state += [
+ (r'%s([%s]*)(%s)(.*)' %
+ (_start_label, _ws, _label_compound if compound else _label),
+ bygroups(Text, Punctuation, Text, Name.Label, Comment.Single)),
+ include('redirect%s' % suffix),
+ (r'(?=[%s])' % _nl, Text, '#pop'),
+ (r'\|\|?|&&?', Punctuation, '#pop'),
+ include('text')
+ ]
+ return state
+
+ def _make_arithmetic_state(compound, _nl=_nl, _punct=_punct,
+ _string=_string, _variable=_variable, _ws=_ws):
+ op = r'=+\-*/!~'
+ state = []
+ if compound:
+ state.append((r'(?=\))', Text, '#pop'))
+ state += [
+ (r'0[0-7]+', Number.Oct),
+ (r'0x[\da-f]+', Number.Hex),
+ (r'\d+', Number.Integer),
+ (r'[(),]+', Punctuation),
+ (r'([%s]|%%|\^\^)+' % op, Operator),
+ (r'(%s|%s|(\^[%s]?)?[^()%s%%^"%s%s%s]|\^[%s%s]?%s)+' %
+ (_string, _variable, _nl, op, _nl, _punct, _ws, _nl, _ws,
+ r'[^)]' if compound else r'[\w\W]'),
+ using(this, state='variable')),
+ (r'(?=[\x00|&])', Text, '#pop'),
+ include('follow')
+ ]
+ return state
+
+ def _make_call_state(compound, _label=_label,
+ _label_compound=_label_compound):
+ state = []
+ if compound:
+ state.append((r'(?=\))', Text, '#pop'))
+ state.append((r'(:?)(%s)' % (_label_compound if compound else _label),
+ bygroups(Punctuation, Name.Label), '#pop'))
+ return state
+
+ def _make_label_state(compound, _label=_label,
+ _label_compound=_label_compound, _nl=_nl,
+ _punct=_punct, _string=_string, _variable=_variable):
+ state = []
+ if compound:
+ state.append((r'(?=\))', Text, '#pop'))
+ state.append((r'(%s?)((?:%s|%s|\^[%s]?%s|[^"%%^%s%s%s])*)' %
+ (_label_compound if compound else _label, _string,
+ _variable, _nl, r'[^)]' if compound else r'[\w\W]', _nl,
+ _punct, r')' if compound else ''),
+ bygroups(Name.Label, Comment.Single), '#pop'))
+ return state
+
+ def _make_redirect_state(compound,
+ _core_token_compound=_core_token_compound,
+ _nl=_nl, _punct=_punct, _stoken=_stoken,
+ _string=_string, _space=_space,
+ _variable=_variable, _ws=_ws):
+ stoken_compound = (r'(?:[%s]+|(?:%s|%s|%s)+)' %
+ (_punct, _string, _variable, _core_token_compound))
+ return [
+ (r'((?:(?<=[%s%s])\d)?)(>>?&|<&)([%s%s]*)(\d)' %
+ (_nl, _ws, _nl, _ws),
+ bygroups(Number.Integer, Punctuation, Text, Number.Integer)),
+ (r'((?:(?<=[%s%s])(?<!\^[%s])\d)?)(>>?|<)(%s?%s)' %
+ (_nl, _ws, _nl, _space, stoken_compound if compound else _stoken),
+ bygroups(Number.Integer, Punctuation, using(this, state='text')))
+ ]
+
tokens = {
- 'root': [
- # Lines can start with @ to prevent echo
- (r'^\s*@', Punctuation),
- (r'^(\s*)(rem\s.*)$', bygroups(Text, Comment)),
- (r'".*?"', String.Double),
- (r"'.*?'", String.Single),
- # If made more specific, make sure you still allow expansions
- # like %~$VAR:zlt
- (r'%%?[~$:\w]+%?', Name.Variable),
- (r'::.*', Comment), # Technically :: only works at BOL
- (r'\b(set)(\s+)(\w+)', bygroups(Keyword, Text, Name.Variable)),
- (r'\b(call)(\s+)(:\w+)', bygroups(Keyword, Text, Name.Label)),
- (r'\b(goto)(\s+)(\w+)', bygroups(Keyword, Text, Name.Label)),
- (r'\b(set|call|echo|on|off|endlocal|for|do|goto|if|pause|'
- r'setlocal|shift|errorlevel|exist|defined|cmdextversion|'
- r'errorlevel|else|cd|md|del|deltree|cls|choice)\b', Keyword),
- (r'\b(equ|neq|lss|leq|gtr|geq)\b', Operator),
- include('basic'),
- (r'.', Text),
+ 'root': _make_begin_state(False),
+ 'follow': _make_follow_state(False),
+ 'arithmetic': _make_arithmetic_state(False),
+ 'call': _make_call_state(False),
+ 'label': _make_label_state(False),
+ 'redirect': _make_redirect_state(False),
+ 'root/compound': _make_begin_state(True),
+ 'follow/compound': _make_follow_state(True),
+ 'arithmetic/compound': _make_arithmetic_state(True),
+ 'call/compound': _make_call_state(True),
+ 'label/compound': _make_label_state(True),
+ 'redirect/compound': _make_redirect_state(True),
+ 'variable-or-escape': [
+ (_variable, Name.Variable),
+ (r'%%%%|\^[%s]?(\^!|[\w\W])' % _nl, String.Escape)
],
- 'echo': [
- # Escapes only valid within echo args?
- (r'\^\^|\^<|\^>|\^\|', String.Escape),
- (r'\n', Text, '#pop'),
- include('basic'),
- (r'[^\'"^]+', Text),
+ 'string': [
+ (r'"', String.Double, '#pop'),
+ (_variable, Name.Variable),
+ (r'\^!|%%', String.Escape),
+ (r'[^"%%^%s]+|[%%^]' % _nl, String.Double),
+ default('#pop')
],
- 'basic': [
- (r'".*?"', String.Double),
- (r"'.*?'", String.Single),
- (r'`.*?`', String.Backtick),
- (r'-?\d+', Number),
- (r',', Punctuation),
- (r'=', Operator),
- (r'/\S+', Name),
- (r':\w+', Name.Label),
- (r'\w:\w+', Text),
- (r'([<>|])(\s*)(\w+)', bygroups(Punctuation, Text, Name)),
+ 'sqstring': [
+ include('variable-or-escape'),
+ (r'[^%]+|%', String.Single)
],
+ 'bqstring': [
+ include('variable-or-escape'),
+ (r'[^%]+|%', String.Backtick)
+ ],
+ 'text': [
+ (r'"', String.Double, 'string'),
+ include('variable-or-escape'),
+ (r'[^"%%^%s%s%s\d)]+|.' % (_nl, _punct, _ws), Text)
+ ],
+ 'variable': [
+ (r'"', String.Double, 'string'),
+ include('variable-or-escape'),
+ (r'[^"%%^%s]+|.' % _nl, Name.Variable)
+ ],
+ 'for': [
+ (r'(%s)(in)(%s)(\()' % (_space, _space),
+ bygroups(using(this, state='text'), Keyword,
+ using(this, state='text'), Punctuation), '#pop'),
+ include('follow')
+ ],
+ 'for2': [
+ (r'\)', Punctuation),
+ (r'(%s)(do%s)' % (_space, _token_terminator),
+ bygroups(using(this, state='text'), Keyword), '#pop'),
+ (r'[%s]+' % _nl, Text),
+ include('follow')
+ ],
+ 'for/f': [
+ (r'(")((?:%s|[^"])*?")([%s%s]*)(\))' % (_variable, _nl, _ws),
+ bygroups(String.Double, using(this, state='string'), Text,
+ Punctuation)),
+ (r'"', String.Double, ('#pop', 'for2', 'string')),
+ (r"('(?:%s|[\w\W])*?')([%s%s]*)(\))" % (_variable, _nl, _ws),
+ bygroups(using(this, state='sqstring'), Text, Punctuation)),
+ (r'(`(?:%s|[\w\W])*?`)([%s%s]*)(\))' % (_variable, _nl, _ws),
+ bygroups(using(this, state='bqstring'), Text, Punctuation)),
+ include('for2')
+ ],
+ 'for/l': [
+ (r'-?\d+', Number.Integer),
+ include('for2')
+ ],
+ 'if': [
+ (r'((?:cmdextversion|errorlevel)%s)(%s)(\d+)' %
+ (_token_terminator, _space),
+ bygroups(Keyword, using(this, state='text'),
+ Number.Integer), '#pop'),
+ (r'(defined%s)(%s)(%s)' % (_token_terminator, _space, _stoken),
+ bygroups(Keyword, using(this, state='text'),
+ using(this, state='variable')), '#pop'),
+ (r'(exist%s)(%s%s)' % (_token_terminator, _space, _stoken),
+ bygroups(Keyword, using(this, state='text')), '#pop'),
+ (r'(%s%s?)(==)(%s?%s)' % (_stoken, _space, _space, _stoken),
+ bygroups(using(this, state='text'), Operator,
+ using(this, state='text')), '#pop'),
+ (r'(%s%s)(%s)(%s%s)' % (_number, _space, _opword, _space, _number),
+ bygroups(using(this, state='arithmetic'), Operator.Word,
+ using(this, state='arithmetic')), '#pop'),
+ (r'(%s%s)(%s)(%s%s)' % (_stoken, _space, _opword, _space, _stoken),
+ bygroups(using(this, state='text'), Operator.Word,
+ using(this, state='text')), '#pop')
+ ],
+ '(?': [
+ (_space, using(this, state='text')),
+ (r'\(', Punctuation, ('#pop', 'else?', 'root/compound')),
+ default('#pop')
+ ],
+ 'else?': [
+ (_space, using(this, state='text')),
+ (r'else%s' % _token_terminator, Keyword, '#pop'),
+ default('#pop')
+ ]
}
diff --git a/tests/examplefiles/batchfile.bat b/tests/examplefiles/batchfile.bat
deleted file mode 100644
index 5cdc625c..00000000
--- a/tests/examplefiles/batchfile.bat
+++ /dev/null
@@ -1,49 +0,0 @@
-rem this is a demo file.
-@rem
-@echo off
-
-call c:\temp.bat somearg
-call :lab somearg
-rem This next one is wrong in the vim lexer!
-call c:temp.bat
-
-echo "Hi!"
-echo hi
-echo on
-echo off
-echo.
-@echo off
-if exist *.log echo The log file has arrived.
-rem These are all escapes, also done incorrectly by the vim lexer
-echo ^^ ^> ^< ^|
-
-x=beginning
-setlocal
-x = new text
-endlocal
-
-echo testrem x
-echo test rem x
-
-for %%var in (*.jpg) do echo %%var
-for /D %%var in (a b c) do echo %%var
-for /R C:\temp %%var in (*.jpg) do iexplore.exe %%var
-rem Vim has this one wrong too.
-for /L %%var in (10,-1,1) do echo %%var
-for /F %%var in ("hi!") do echo %%var
-for /F "eol=c,skip=1,usebackq" %%var in (`command`) do echo %%var %~l %~fl %~dl %~pl %~nl %~xl %~sl %~al %~tl %~zl %~$PATH:l %~dpl %~dp$PATH:l %~ftzal
-
-echo some file ?! > somefile.txt
-
-set PATH=%PATH%;c:\windows
-
-goto answer%errorlevel%
- :answer0
- echo Hi it's zero
- :answer1
- echo New
-
-if exist a del a
-else echo A is missing!
-
-
diff --git a/tests/examplefiles/example.bat b/tests/examplefiles/example.bat
new file mode 100644
index 00000000..bf27673c
--- /dev/null
+++ b/tests/examplefiles/example.bat
@@ -0,0 +1,205 @@
+@ @@ echo off
+::This is an example of the Windows batch language.
+
+setlocal EnableDelayedExpansion
+(cls)
+set/a^
+_te^
+sts^
+=0,^
+_"pa"^
+ssed=0^
+0
+set,/a title= Batch test
+title=%,/a title%
+echo^ %~nx0,^ the>,con comprehensive testing suite
+ver
+echo(
+
+if cmdextversion 2 goto =)
+goto :fail
+
+ :)
+echo Starting tests at:
+date/t & time/t
+echo(
+
+if '%*'=='--help' (
+ echo Usage: %~nx0 [--help]
+ echo --help: Display this help message and quit.
+ shift
+ goto :exit comment) else rem
+
+(call :comments)
+call ::io+x
+call:control:x
+call::internal x
+
+:exit
+if /i !_tests!==!_passed! (
+ color 02
+) else if !*==* (
+ color c
+ if not defined _exit^
+Code set _exit^
+Code=1
+)
+set _percentage=NaN
+if defined _tests (
+ if !_tests! neq 0 (set/a_percentage=100*_passed/_tests)
+)
+echo(
+if !_percentage!==NaN ( echo(There were no tests^^! & color e
+) else ( echo Tests passed: %_passed%/%_tests% (%_percentage%%%^) )
+pause
+color
+title
+endlocal
+exit /b %_exitCode%
+
+x:fail
+rem This should never happen.
+echo Internal error 1>& 269105>>&2
+set /a _exitCode=0x69+(0105*1000)
+break
+goto :exit
+
+:comments
+(rem )/?
+)
+rem "comment^
+(rem.) & set /a _tests+=1
+(rem) & goto :fail
+(rem. ) & (rem. comment ) & echo Test %_tests%: Comments
+rem )
+)
+)|comment
+)(
+:: comment
+goto :comments^^1:comment
+:comments^^1 comment
+if(1==1) goto :comments^
+^1
+rem^ /?
+rem ^
+^
+goto :comments^
+2+comment
+goto :fail
+:comments2
+rem >^
+if 1==1 (goto :comments3)
+:comments3)
+goto :fail
+:comments3
+rem comment^
+goto:fail
+rem.comment comment^
+goto fail
+rem "comment comment"^
+goto fail
+rem comment comment^
+set /a _passed+=1
+GOTO :EOF
+goto :fail
+
+:IO
+SET /A _tests+=1 & Echo Test !_tests:*!==^!: I/O
+verify on
+pushd .
+if exist temp echo temp already exists. & goto :eof
+md temp
+cd temp
+mkdir 2>nul temp
+chdir temp
+>cd echo Checking drive...
+>>cd echo must be C or else this won't work
+for /f "tokens=* usebackq" %%G in ("cd
+) do (<nul set /p="%%G ")
+echo(
+DEL cd
+if not "%cd:~0,3%"=="C:\" (
+ call call echo Wrong drive (should be C^):
+ vol
+ goto :test)
+>test0^
+.bat echo rem Machine-generated; do not edit
+call echo set /a _passed+=1 >>test0.bat
+type test0.bat >"test 1.bat
+ren "test 1.bat" test2.bat
+rename test2.bat test.bat
+caLL ^
+C:test
+del test.bat 2>nul
+2>NUL erase test0.bat
+popd
+rd temp\temp
+rmdir temp
+VERIFY OFF
+goto:eof
+
+:control
+set /a _tests+=1
+echo Test %_tests%: Control statements
+set "_iterations=0">nul
+for %%G in (,+,,-,
+) do @(
+ for /l %%H in (,-1;;-1 -3,) do (
+ for /f tokens^=1-2^,5 %%I in ("2 %%H _ _ 10") do (
+ for /f "tokens=1 usebackq" %%L in ( `echo %%G%%J ``` `
+` ` ) do ( for /f "tokens=2" %%M in ('echo ' %%L0 '
+' ' ) do ( set /a _iterations+=(%%M%%M^)
+ )
+ )
+ )
+ )
+)
+if exist %~nx0 if not exist %~nx0 goto :fail
+if exist %~nx0 (
+ if not exist %~nx0 goto :fail
+) else (
+ if exist %~nx0 goto :fail
+)
+if /i %_iterations% gtr -2 (
+ if /i %_iterations% geq -1 (
+ if /i %_iterations% lss 1 (
+ if /i %_iterations% leq 0 (
+ if /i %_iterations% equ 0 (
+ if 1 equ 01 (
+ if 1 neq "01" (
+ if "1" neq 01 (
+ set /a _passed+=1))))))))
+) comment
+goto :eof
+
+:internal
+set /a _tests+=1
+echo Test %_tests%: Internal commands
+keys on
+mklink 2>nul
+>nul path %path%
+>nul dpath %dpath%
+if not defined prompt prompt $P$G
+prompt !prompt:~!rem/ $H?
+echo on
+rem/?
+@echo off
+rem(/?>nul
+rem )/? >nul
+(rem (/?) >nul
+rem /?>nul
+rem^/?>nul
+if/?>nul || if^/^?>nul || if /?>nul || if x/? >nul
+for/?>nul && for^/^?>nul && for /?>nul && for x/? >nul && for /?x >nul
+goto/?>nul && goto^/? && goto^ /? && goto /^
+? && goto /?>nul && goto:/? >nul && goto ) /? ) >nul && (goto /? )>nul
+=set+;/p extension'),=.bat
+for /f "tokens=2 delims==" %%G in ( 'assoc %+;/p extension'),%'
+ ) do (
+ assoc 2>nul %+;/p extension'),:*.=.%=%%G
+ ftype 1>nul %%G
+) &>nul ver
+if errorlevel 0 if not errorlevel 1 set /a _passed+=1
+goto :eof
+:/?
+goto :fail