@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment
@goto :Batch

::JREPL.BAT by Dave Benham
::/History
::
::    2020-07-30 v8.6: Added options to /K, /R, and /MATCH to count the number
::                     of matches or rejects instead of printing them.
::                     Added the counter /JScript variable.
::                     Fixed /T Pig Latin example - $0 corrected to read $&
::    2020-02-29 v8.5: Added /EOL option to set the end of line terminator.
::                     Added the eol global jscript variable.
::                     Doc fix - No EOL if /RTN option specifies a :LineNumber.
::    2019-09-13 v8.4: Bug fix - /K,/R did not work with /EXC,/INC as of v8.0
::    2019-07-16 v8.3: Documentation correction - Binary data with null bytes may
::                     be read via ADO.
::    2019-06-05 v8.2: /RTN bug fix - preserve Unicode by using CHCP 65001/utf-8
::                     to transfer value to variable unless /XFILE used.
::    2019-05-19 v8.1: Add /VT to enable Virtual Terminal ANSI escape sequences.
::                     Code courtesy of DosTips user aGerman (Steffen).
::    2019-05-15 v8.0: Add /Hxxx options for highlighting matched/replaced text.
::                     Bug fix - /OFF was wrong when used with /P.
::                     Change - /OFF is now incompatible with /PREPL.
::                     Change - /PREPL may now be used with /K and /R.
::                     Doc fix - corrected syntax for /F [|NB] option.
::                     Doc fix - /OFF is for first match if used with /K.
::    2018-10-20 v7.15: Add a string literal syntax to the /INC and /EXC options.
::    2018-10-15 v7.14: Bug fix - User defined variables declared in /JBEG named
::                      str and/or obj were getting clobbered.
::                      Bug fix - Internal variable xbytes was visibile to user
::                      supplied JScript.
::    2018-07-19 v7.13: Bug fix - /INC and /EXC regex failed to match any
::                      line that immediately followed a prior block.
::                      Added ADO code to create XBYTES.DAT in case CERTUTIL is
::                      missing. Code courtesy of DosTips user aGerman (Steffen).
::    2018-07-18 v7.12: Fixed XBYTES.DAT creation cleanup bugs, and improved docs
::    2018-03-26 v7.11: Add support for /O "-|UTF-?|NB" (overwrite without BOM)
::    2018-03-14 v7.10: Now can block BOM in ADO output files by appending |NB
::                      to |CharSet in the /O option and OpenOutput() function.
::    2017-11-23 v7.9: Allow escape sequences with /T "" coupled with /XSEQ
::                     Added /PREPL option to augment /P behavior
::                     Bug fix - Force /L when /T "" used, as per documentation
::                     Bug fix - Allow /?charset/search to include non alpha
::    2017-11-13 v7.8: Added \x{nn-mm} and \x{nn-mm,CharSet} escape sequences
::                     Split /X into /XFILE and /XSEQ - /X implies both
::                     Add :FILE syntax for /K and /R to load searches from file
::                     Fixed /XSEQ escaped backslash bug with /INC, /EXC, AND /P
::    2017-10-24 v7.7: Fixed broken Microsoft documentation links
::                     Allow /O "-|CharSet"
::                     Fixed decode(Str[,CharSet]) bug when CharSet is undefined
::    2017-10-08 v7.6: Fixed /?Intro syntax help for /?Charset/[Query]
::    2017-10-08 v7.5: Added /?CHARSET and /?XREGEXP web page help options
::                     Added /?CHARSET/[query] List character sets help option
::                     Fixed ADO output.WriteLine() to use \r\n instead of \n
::                     Improved documentation: /EXC, /OFF, /U, /?HELP, decode()
::    2017-09-25 v7.4: Modified /X \xnn extended ASCII escape sequence to support
::                     any single byte character set.
::                     Added /X \x{nn,Charset} escape sequence.
::                     Added /XBYTES and /XBYTESOFF options.
::                     Modified decode() to support the new /X \xnn behavior.
::    2017-09-23 v7.3: Fixed /O - support for ADO input.
::    2017-09-23 v7.2: Improved documentation of new 7.0 features.
::                     Bug fix - /T FILE ADO support was broken
::    2017-09-08 v7.1: Bug fix - v7.0 failed if Find or Replace contained )
::    2017-09-08 v7.0: Added /XREG and /TFLAG for XRegExp regex support.
::                     Added /UTF for UTF-16LE support.
::                     Added /X support for the \u{N} unicode escape sequence.
::                     Added |CharSet syntax for file names to allow reading
::                     and writing via ADO with a specified character set.
::                     Exposed the fso FileSystemObject to user JScript.
::                     Augmented openOutput for Unicode and ADO support.
::    2017-08-25 v6.8: Added /X support for the \c caret escape sequence.
::                     Added /APP - append to the output file.
::                     Added the openOutput(file[,appendBoolean]) function.
::    2017-04-09 v6.7: Corrected /OFF /EXC & /INC documentation + spelling fixes.
::    2016-12-23 v6.6: Help correction: Fixed return codes in /?RETURN section.
::    2016-11-13 v6.5: Modify /X to consistently preserve extended ASCII.
::                     New option /RTN writes result to a variable.
::    2016-11-01 v6.4: Bug fix - v6.3 had inverted /EXC result.
::    2016-10-13 v6.3: Improved performance by dynamically generating main loop
::                     code based on chosen options.
::    2016-10-13 v6.2: Bug fix - /J, /JQ, /JMATCH, /JMATCHQ did not work with /P.
::    2016-10-08 v6.1: Bug fix - v6.0 broke /JBEG and /JLIB, all fixed.
::    2016-10-08 v6.0: Added /K - search and write matching lines.
::                     Added /R - search and write non-matching lines.
::                     Added /MATCH - search and write each match on a new line.
::                     Added /P - Pre-filter regex before normal search/replace.
::                     Added /PFLAG - set search flags for /P regex
::                     Added /JQ and /JMATCHQ as Quick forms of /J and /JMATCH.
::                     Augmented /INC and /EXC so can now specify lines by regex.
::                     Changed behavior - /V now applies to /INC and /EXC.
::                     Improved performance of /INC, /EXC, /T, /JBEGLN, /JENDLN.
::                     Added HISTORY and UPDATE topics to the help system.
::    2016-09-27 v5.2: Bug fix - Search & Replace now ignore /V if /T FILE used.
::                     Added a /T FILE example to the documentation.
::    2016-09-20 v5.1: Added the FILE alternative for the /T option.
::    2016-09-18 v5.0: Added the /U option for Unix line terminators of /n.
::    2016-08-04 v4.6: Fixed the /N documentation (repaired missing line)
::    2016-08-03 v4.5: Added /D option to specify delimiter for /N and /OFF.
::    2016-08-02 v4.4: Bug fix - /C count was wrong when last line did not end
::                     with new line. This also affected /INC and /EXC.
::    2016-07-30 v4.3: Added rpad() function and improved lpad()
::    2016-06-24 v4.2: Improved the /?Options help.
::    2016-06-23 v4.1: Added /T option examples to the help.
::                     Added ability to request help on a single option or topic.
::    2016-06-19 v4.0: Added the /INC and /EXC options.
::    2016-03-27 v3.8: Bug fix - Hide leaked global variables i, lib, libs, rtn2.
::                     Bug fix - Work around %~f0 bug when command is quoted.
::                     Bug fix - Use /OPTIONS instead of OPTIONS as a variable
::                     name within the option parser so that it is unlikely to
::                     collide with a user defined variable name.
::    2016-01-14 v3.7: Reworked error handling a bit.
::                     Bug fix - \xnn and \unnnn could fail in a regex search
::                     if result was a meta-character and /X option was used.
::    2015-07-15 v3.6: Added /?? option for paged help.
::    2015-06-12 v3.5: Bug fix for $n or $nn in replace string when /T is
::                     used without /J or /JMATCH or /L
::    2015-01-22 v3.4: Bug fix - Use /TEST instead of TEST as a variable name
::                     within the option parser so that it is unlikely to
::                     collide with a user defined variable name.
::    2014-12-24 v3.3: Bug fix for when /JMATCH is combined with /M or /S
::    2014-12-09 v3.2: Bug fix for /T without /JMATCH - fixed dynamic repl func
::                     Added GOTO at top for improved startup performance
::    2014-11-25 v3.1: Added /JLIB option
::                     Exception handler reports when regex is bad
::                     Fix /X bug with extended ASCII
::    2014-11-23 v3.0: Added /JBEGLN and /JENDLN options
::                     Added skip, quit, and lpad() global variables/functions
::                     Exception handler reports when error in user code
::    2014-11-21 v2.2: Bug fix for /T with /L option.
::    2014-11-20 v2.1: Bug fix for /T option when match is an empty string
::    2014-11-17 v2.0: Added /T (translate) and /C (count input lines) options
::    2014-11-14 v1.0: Initial release derived from REPL.BAT v6.2
::/
::============ Documentation ===========
::/INTRO
:::
:::JREPL  Search  Replace  [/Option  [Value]]...
:::JREPL  /?[?][Topic|/Option|CHARSET/[Query]|HELP]
:::
:::  Perform a global regular expression search and replace operation on
:::  each line of ASCII input from stdin and prints the result to stdout.
:::
:::  Each parameter may be optionally enclosed by double quotes. The double
:::  quotes are not considered part of the argument. The quotes are required
:::  if the parameter contains a batch token delimiter like space, tab, comma,
:::  semicolon. The quotes should also be used if the argument contains a
:::  batch special character like &, |, etc. so that the special character
:::  does not need to be escaped with ^.
:::
:::  Search  - By default, this is a case sensitive JScript (ECMA) regular
:::            expression expressed as a string.
:::
:::            JScript regex syntax documentation is available at
:::            https://msdn.microsoft.com/en-us/library/ae5bf541.aspx
:::
:::  Replace - By default, this is the string to be used as a replacement for
:::            each found search expression. Full support is provided for
:::            substitution patterns available to the JScript replace method.
:::
:::            For example, $& represents the portion of the source that matched
:::            the entire search pattern, $1 represents the first captured
:::            submatch, $2 the second captured submatch, etc. A $ literal
:::            can be escaped as $$.
:::
:::            An empty replacement string must be represented as "".
:::
:::            Replace substitution pattern syntax is fully documented at
:::            https://msdn.microsoft.com/en-US/library/efy6s3e6.aspx
:::
:::  Binary input with NULL bytes requires either the /M option, or the file
:::  must be read using ADO by appending the character set name to the file name.
:::  For example, if your input is ASCII containing null bytes, then you must
:::  use:   /F "input.txt" /M   or   /F "input.txt|ascii".
:::
:::  The meaning of extended ASCII byte codes >= 128 (0x80) is dependent on the
:::  active code page. Extended ASCII within arguments and variables may require
:::  the /XFILE option.
::/OPTIONS
:::
:::  Options:  Behavior may be altered by appending one or more options.
:::  The option names are case insensitive, and may appear in any order
:::  after the Replace argument.
:::
::      /A                      - write Altered lines only
::      /APP                    - Append results to the output file
::      /B                      - match Beginning of line
::      /C                      - Count number of source lines
::      /D                      - Delimiter for /N and /OFF
::      /E                      - match End of line
::      /EOL EndOfLineString    - set the End Of Line terminator
::      /EXC BlockList          - EXClude lines from selected blocks
::      /F InFile[|CharSet[|NB]]- read input from a File
::      /H                      - Highlight replaced or matched text
::      /HON HilightStart       - defines the string to start highlighting
::      /HOFF HilightEnd        - defines the string to stop highlighting
::      /HU                     - Underline replaced or matched text
::      /I                      - Ignore case
::      /INC BlockList          - INClude lines from selected blocks
::      /J                      - JScript replace expressions
::      /JBEG InitCode          - initialization JScript code
::      /JBEGLN NewLineCode     - line initialization JScript code
::      /JEND FinalCode         - finalization JScript code
::      /JENDLN EndLineCode     - line finalization JScript code
::      /JLIB FileList          - load file(s) of initialization code
::      /JMATCH                 - write matching JScript replacements only
::      /JMATCHQ                - new Quick form of /JMATCH
::      /JQ                     - new Quick form of /J
::      /K Context or Pre:Post  - search and Keep lines that match
::      /L                      - Literal search
::      /M                      - Multi-line mode
::      /MATCH                  - Search and print each match, one per line
::      /N MinWidth             - prefix output with liNe numbers
::      /O OutFile[|CharSet[|NB]]- write Output to a file
::      /OFF MinWidth           - add OFFsets to /K, /JMATCHQ, /MATCH output
::      /P Regex                - only search/replace strings that match a Regex
::      /PFLAG Flags            - set the /P regex Flags to "g", "gi", "" or "i"
::      /PREPL FilterReplCode   - selectively Search/Replace captured /P groups
::      /R Context or Pre:Post  - search and Reject lines that match
::      /RTN ReturnVar[:Line#]  - Return result in a variable
::      /S VarName              - Source is read from a variable
::      /T DelimChar or FILE    - Translate multiple search/replace pairs
::      /TFLAG Flags            - specify XRegExp flags for use with /T
::      /U                      - Unix line terminators (\n instead of \r\n)
::      /UTF                    - all input and output as UTF-16LE (BOM optional)
::      /V                      - use Variables for Search/Replace and code
::      /VT                     - enable Virtual Terminal ANSI escape sequences
::      /X                      - shorthand for combined /XFILE and /XSEQ
::      /XBYTES                 - force creation of new XBYTES.DAT
::      /XBYTESOFF              - force /XSEQ \xnn to be treated as Windows-1252
::      /XFILE                  - preserve extended ASCII in args via temp files
::      /XREG FileList          - adds XRegExp support to JREPL
::      /XSEQ                   - enable extended escape sequences
::/
:::      /A  - Only write altered lines. Unaltered lines are discarded.
:::            If the /S option is used, then write the result only if
:::            there was a change anywhere in the string. The /A option
:::            is incompatible with the /M option unless the /S option
:::            is also present.
:::
:::      /APP - Modify /O behavior to Append results to the output file.
:::
:::      /B  - The Search must match the Beginning of a line.
:::            Mostly used with literal searches.
:::
:::      /C  - Count the number of input lines and store the result in global
:::            variable cnt. This value can be useful in JScript code associated
:::            with any of the /Jxxx options.
:::
:::            This option is implicitly enabled if /INC or /EXC contains a
:::            negative value.
:::
:::            This option is incompatible with the /M and /S options.
:::
:::            If the input data is piped or redirected, then the data is first
:::            written to a temporary file, so processing does not start until
:::            the end-of-file is reached.
:::
:::      /D Delimiter
:::
:::            Specifies the Delimiter string to use after line numbers and/or
:::            byte offsets that are output due to the /N or /OFF options.
:::            The default value is a colon. The delimiter may be set to an
:::            empty string by using /D "".
:::
:::      /E  - The Search must match the End of a line.
:::            Mostly used with literal searches.
:::
:::      /EOL EndOfLineString
:::
:::            Write lines using EndOfLineString as the line terminator.
:::            Standard JScript escape sequences may be used.
:::            The default is "\r\n" (CarriageReturn LineFeed).
:::            The value may be set to an empty string to eliminate linefeeds
:::            from the output.
:::
:::            /EOL has no effect if the /M option is used unless /MATCH,
:::            /JMATCH, or /JMATCHQ is also used.
:::
:::            Note that /EOL does not affect input.ReadLine or output.WriteLine
:::            methods in user supplied JScript. ReadLine always accepts both
:::            \r\n and \n as line terminators. And WriteLine always terminates
:::            lines with \r\n.
:::
:::      /EXC BlockList
:::
:::            Exclude (do not search/replace) lines that appear within at least
:::            one block within BlockList. A block may be a single line, or a
:::            contiguous range of lines between a start and end line. The /EXC
:::            option is incompatible with /M and /S.
:::
:::            The syntax for specifying a BlockList is complex. Whitespace
:::            should not appear anywhere except for possibly within a Regex or
:::            String.
:::
:::              BlockList     = {Block}[,{Block}]...
:::              {Block}       = {SingleLine}|{LineRange}
:::              {SingleLine}  = {LineSpec}[{Offset}]
:::              {LineRange}   = {LineSpec}[{Offset}]:{EndLineSpec}[{Offset}]
:::              {LineSpec}    = [-]LineNumber|{Regex}[/]|{String}[/]
:::              {EndLineSpec} = [-]LineNumber|+Number|{Regex}|{String}
:::              {Regex}       = /Regex/[i|b|e]...
:::              {String}      = 'String'[i|b|e]...
:::              {Offset}      = +Number|-Number
:::
:::            A line may be identified by its LineNumber, or by a Regex that
:::            matches the line, or a String literal that is found in the line.
:::            Once identified, a line position may be adjusted forward or
:::            backward via the optional Offset.
:::
:::            A negative LineNumber is counted from the end of the file.
:::            So 1 is the first line of input, and -1 is the last line. The /C
:::            option is automatically activated if any block identifies a line
:::            via a negative line number.
:::
:::            A Block Regex uses mostly standard JScript syntax. Both a Regex
:::            and a String may use any of the escape sequences defined by the
:::            /XSEQ option, even if the /XSEQ option has not been set. Any /
:::            literal within a Regex must be escaped as \/. Any ' literal
:::            within a String must be escaped as ''.
:::
:::            A Regex or String may be followed by any combination of the
:::            following flags:
:::              i - Ignore case
:::              b - The search must match the beginning of a line
:::              e - The search must match the end of a line
:::            /EXC and /INC ignore the /I option.
:::
:::            A line or range start that is identified by a Regex or String may
:::            match multiple lines within the input. Only the first matching
:::            line is used if the Regex or String is terminated by an extra /.
:::
:::            A Line block or Range start that is identified by a Regex or
:::            String cannot have a negative Offset.
:::
:::            If the end of a Range is specified as + followed by a Number,
:::            then the Number is treated as an offset from the start of the
:::            Range (after any start Offset has been applied).
:::
:::            If the end of a Range is specified as a Regex or String, then the
:::            block end is the first line that matches after the beginning of
:::            the block. The extra / cannot be used with an end of Range Regex
:::            or String. The Offset must be greater than or equal to -1 if a 
:::            Regex or String is used. If the end of Range Regex or String is
:::            not found, then the block continues to the end of file.
:::
:::            Examples:
:::
:::              /EXC "1:5,10,-5:-1"
:::                 Exclude the first 5, 10th, and last 5 lines.
:::
:::              /EXC "/^:/"
:::                 Exclude all lines that begin with a colon
:::
:::              /EXC "/^Begin$/+1:/^End$/-1"
:::                 Exclude all lines that are after a "Begin" line, and before
:::                 the next "End" line. Multiple blocks may be excluded.
:::
:::              /EXC "/^DATA/i/:+10"
:::                 Exclude the first line that begins with DATA, ignoring case,
:::                 and exclude the next 10 lines as well.
:::
:::              /EXC "'[START]':'[STOP]'"
:::                 Exclude lines beginning with a line that contains the literal
:::                 [START] and ending with the next line that contains [STOP].
:::
:::              /EXC "'[START]'be:'[STOP]'be"
:::                 Exclude lines beginning with a [START] line (exact match)
:::                 and ending with the next [STOP] line (exact match).
:::
:::      /F InFile[|CharSet[|NB]]
:::
:::            Input is read from file InFile instead of stdin.
:::
:::            If |CharSet (internet character set name) is appended to InFile,
:::            then the file is opened via ADO using the specified CharSet value.
:::            JREPL still recognizes both \n and \r\n as input line terminators
:::            when using ADO. Both ADO and the CharSet must be available on the
:::            local system. Appending |NB to the |CharSet normally has no impact.
:::            The |NB No BOM flag is only useful when combined with /O -.
:::
:::            Note: Input containing null bytes cannot be read unless ADO is
:::                  used, or else the /M option must be used.
:::
:::      /H  - Highlight all replaced or matched text in the output using the
:::            strings defined by /HON and /HOFF.
:::
:::            /HON and /HOFF default to ANSI escape sequences that swap the
:::            foreground and background colors.
:::
:::            /HU may be a better option if the current COLOR does not match
:::            the console default.
:::
:::            Native support for ANSI escape sequences requires Windows 10 or
:::            higher. ANSI escape sequences only work on the Windows 10 console
:::            if the "Use legacy console" option is off in console properties.
:::
:::            In addition, one of the following must be used:
:::
:::             - The /VT option can be used to enable the escape sequences for
:::               a single JREPL run.
:::
:::            or
:::
:::             - The registry can have the following DWORD defined, which will
:::               enable escape sequences for all console applications.
:::                  [HKEY_CURRENT_USER\Console]
:::                  "VirtualTerminalLevel"=dword:00000001
:::
:::      /HON HighlightStart
:::
:::            Defines the string to start highlighting text, normally an ANSI
:::            escape sequence.
:::
:::            Default is \x1B[7m - Swap foreground and background colors.
:::
:::      /HOFF HighlightEnd
:::
:::            Defines the string to end highlighting text, normally an ANSI
:::            escape sequence.
:::
:::            Default is \x1B[0m - Return to the console default format.
:::
:::      /HU - Underline all replaced or matched text in the output using ANSI
:::            escape sequences.
:::
:::            This is the same as using /H with /HON=\x1B[4m and /HOFF=\x1B[24m
:::                 
:::      /I  - Ignore case when searching.
:::
:::      /INC BlockList
:::
:::            Only Include (search/replace) lines that appear within at least
:::            one block within BlockList. A block may be a single line, or a
:::            contiguous range of lines between a start and end line. The /INC
:::            option is incompatible with /M and /S.
:::
:::            A line within an /INC block is not included if it also appears
:::            within an /EXC block.
:::
:::            See the /EXC help for the syntax of a BlockList.
:::
:::            Examples:
:::
:::              /INC "1:5,10,-5:-1"
:::                 Include the first 5, 10th, and last 5 lines.
:::
:::              /INC "/^:/"
:::                 Include all lines that begin with a colon
:::
:::              /INC "/^Begin$/+1:/^End$/-1"
:::                 Include all lines that are after a "Begin" line, and before
:::                 the next "End" line. Multiple blocks may be included.
:::
:::              /INC "/^DATA/i/:+10"
:::                 Include the first line that begins with DATA, ignoring case,
:::                 and include the next 10 lines as well.
:::
:::              /INC "'[START]':'[STOP]'"
:::                 Include lines starting with a line that contains the literal
:::                 "[START]" and ending with the next line that contains "[STOP]".
:::
:::              /INC "'[START]'be:'[STOP]'be"
:::                 Include lines beginning with a "[START]" line (exact match)
:::                 and ending with the next "[STOP]" line (exact match).
:::
:::      /J  - A deprecated form of /JQ that is slow because the JScript code
:::            is executed via the eval() function each and every match. This
:::            form does not use $txt - The replace value is taken as the value
:::            of the last JScript expression within Replace.
:::
:::            This option is only preserved so as not to break existing scripts.
:::
:::      /JBEG InitCode
:::
:::            JScript inititialization code to run prior to loading any input.
:::            This is useful for initializing user defined variables for
:::            accumulating information across matches. The default code is an
:::            empty string.
:::
:::      /JBEGLN NewLineCode
:::
:::            JScript code to run at the beginning of each line, prior to
:::            performing any search on the line. The line content may be
:::            manipulated via the $txt variable. The default code is an empty
:::            string. This option is incompatible with the /M and /S options.
:::
:::      /JEND FinalCode
:::
:::            JScript termination code to run when there is no more input to
:::            read. This is useful for writing summarization results.
:::            The default code is an empty string.
:::
:::      /JENDLN EndLineCode
:::
:::            JScript code to run at the end of each line, after all matches
:::            on the line have been found, but before the result is printed.
:::            The final result can be modified via the $txt variable. Setting
:::            $txt to false discards the line without printing. The $txt value
:::            is ignored if the /JMATCH option has been used. The default
:::            code is an empty string. This option is incompatible with the
:::            /M and /S options.
:::
:::      /JLIB FileList
:::
:::            Specifies one or more files that contain libraries of JScript
:::            code to load before /JBEG is run. Multiple files are delimited
:::            by forward slashes (/). Useful for declaring global variables
:::            and functions in a way that is reusable.
:::
:::      /JMATCH - A deprecated form of /JMATCHQ that is slow because the JScript
:::            code is executed via the eval() function each and every match.
:::            This form does not use $txt - The replace value is taken as the
:::            value of the last JScript expression within Replace.
:::
:::            This option is only preserved so as not to break existing scripts.
:::
:::      /JMATCHQ - Write each Replace value on a new line, discarding all text
:::            that does not match the Search. The Replace argument is one or
:::            more JScript statements with access to the same $ variables
:::            available to the /JQ option. The code must store the final replace
:::            value in variable $txt. A $txt value of false indicates the match
:::            is to be ignored.
:::
:::            Note the trailing Q stands for Quick :-)
:::
:::      /JQ - The Replace argument is one or more JScript statements that
:::            define the replacement value, and possibly do more. The code
:::            must store the final replace value in variable $txt.
:::
:::            The following variables contain details about each match:
:::
:::              $0 is the substring that matched the Search
:::              $1 through $n are the captured submatch strings
:::              $off is the offset where the match occurred
:::              $src is the original source string
:::
:::            Note the trailing Q stands for Quick :-)
:::
:::      /K PreContext:PostContext[:FILE]
:::      /K Context[:FILE]
:::      /K COUNT[:FILE]
:::
:::            Keep matches - Search and write out lines that contain at least
:::            one match, without doing any replacement. The Replace argument is
:::            still required, but is ignored.
:::
:::            The integers PreContext and PostContext specify how many non-
:::            matching lines to write before the match, and after the match,
:::            respectively. If a single Context integer is given, then the same
:::            number of non-matching lines are written before and after.
:::            A Context of 0 writes only matching lines.
:::
:::            If the value of Context is COUNT, then matching lines are counted
:::            but not written, and the final match count is written at the end.
:::
:::            If :FILE is appended to the context, then the Search parameter
:::            specifies a file containing one or more search terms, one term
:::            per line. A line matches if any of the search terms are found
:::            witin the line. The file can be opened via ADO if |CharSet
:::            (internet character set name) is appended to the file name.
:::            Note: the /V option does not apply to Search if /K :FILE is used.
:::
:::            See /OFF and /N for how to prefix each kept line with the match
:::            byte offset and/or the line number.
:::
:::            /K is incompatible with /A, /J, /JQ, /JMATCH, /JMATCHQ, /M,
:::            /MATCH, /R, /S, and /T.
:::
:::      /L  - The Search is treated as a string literal instead of a
:::            regular expression. Also, all $ found in the Replace string
:::            are treated as $ literals.
:::
:::      /M  - Multi-line mode. The entire input is read and processed in one
:::            pass instead of line by line, thus enabling search for \n. This
:::            also enables preservation of the original line terminators.
:::            The /M option is incompatible with the /A option unless the /S
:::            option is also present.
:::
:::            Note: The /M option is one method to read binary data with null
:::                  bytes. The other option is to use ADO to read the file.
:::                  See the /F option for more info.
:::
:::      /MATCH - Search and write out each matching string on a new line,
:::            discarding any non-matching text. The Replace argument is
:::            usually ignored, but is still required. However, if the Replace
:::            value is "COUNT", then the matches are counted but not written,
:::            and the final match count is written at the end.
:::
:::            See /OFF and /N for how to prefix each match with the byte offset
:::            and/or the line number.
:::
:::            /MATCH is incompatible with /A, /J, /JQ, /JMATCH, /JMATCHQ,
:::            /K, /R and /T.
:::
:::      /N MinWidth
:::
:::            Precede each output line with the line number of the source line,
:::            followed by a delimiter (colon by default). The default delimiter
:::            can be overridden with the /D option.
:::
:::            Line 1 is the first line of the source.
:::
:::            The MinWidth value specifies the minimum number of digits to
:::            display. The default value is 0, meaning do not display the
:::            line number. A value of 1 displays the line numbers without any
:::            zero padding.
:::
:::            The /N option is ignored if the /M or /S option is used.
:::
:::      /O OutFile[|CharSet[|NB]]
:::
:::            Output is written to file OutFile instead of stdout. Any existing
:::            OutFile is overwritten unless the /APP option is also used.
:::
:::            If |CharSet (internet character set name) is appended to OutFile,
:::            then the file is opened via ADO using the specified CharSet value.
:::            The output line terminator still defaults to \r\n when using ADO,
:::            and may be changed to \n with the \U option. Both ADO and the
:::            CharSet must be available on the local system. Unicode files
:::            written by ADO have a BOM by default. Appending |NB (or |anyvalue)
:::            to the CharSet blocks the BOM from being written.
:::
:::            If /F InFile is also used, then an OutFile value of "-" overwrites
:::            the original InFile with the output. A value of "-" preserves the
:::            original input character set (and also any |NB No BOM indicator).
:::            A value of "-|" explicitly transforms the file into the machine
:::            default character set. A "-|CharSet[|NB]" value explicitly
:::            transforms the file into the specified character set. The output
:::            is first written to a temporary file with the same path and name,
:::            with .new appended. Upon completion, the temp file is moved to
:::            replace the InFile.
:::
:::            It is rarely useful, but /APP may be combined with /O -. But /APP
:::            cannot be combined with /O "-|CharSet".
:::
:::      /OFF MinWidth
:::
:::            Ignored unless /JMATCHQ, /JMATCH, /MATCH, or /K is used.
:::            Precede each line of output with the offset of the match within
:::            the original source string, followed by a delimiter (colon by
:::            default). The default delimiter can be overridden with the /D
:::            option. The offset follows the line number if the /N option is
:::            also used.
:::
:::            Offset 0 is the first character of the source string. The source
:::            string is normally the current line. But if the /M option is used
:::            then the source string is the entire file.
:::
:::            If used with /K, then the offset represents the first occurrence
:::            of the search string within the line.
:::
:::            The MinWidth value specifies the minimum number of digits to
:::            display. The default value is 0, meaning do not display the
:::            offset. A value of 1 displays the offsets without any zero
:::            padding.
:::
:::      /P FilterRegex
:::
:::            Only Search/Replace strings that match the Pre-filter regular
:::            expression FilterRegex. All escape sequences defined by /XSEQ are
:::            available to FilterRegex, even if /XSEQ has not been set.
:::
:::            FilterRegex is a global, case sensitive search by default.
:::            The behavior may be changed via the /PFLAG option.
:::
:::            By default, /P passes the entire matched filter string to the
:::            main Search/Replace routine. If your FilterRegex includes captured
:::            groups, then you can add the /PREPL option to selectively pass one
:::            or more captured groups instead.
:::
:::            The /P option ignores /I, but honors /M.
:::
:::            The /P option may be combined with /INC and/or /EXC, in which case
:::            /P is applied after lines have been included and/or excluded.
:::
:::            Within the main Search argument, ^ matches the beginning of the
:::            matched filter, and $ matches the end of the matched filter.
:::
:::            Example - Substitute X for each character within curly braces,
:::                      including the braces.
:::
:::               echo abc{xyz}def|jrepl . X /p "{.*?}"
:::
:::            result:
:::
:::               abcXXXXXdef
:::
:::            See /PREPL for an example showing how to preserve the enclosing
:::            braces.
:::
:::      /PFLAG Flags
:::
:::            Set the search flags to be used when defining the /P FilterRegex.
:::            Possible values are:
:::              "g"  - global, case sensitive (default)
:::              "gi" - global, ignore case
:::              ""   - first match only, case sensitive
:::              "i"  - first match only, ignore case
:::
:::            If the search is not global, then the first match of each line
:::            is used. If the /M option is used, then a non-global search uses
:::            only the first match of the entire input.
:::
:::            Note that the /P FilterRegex multiline mode is contolled by the
:::            /M option. The "m" flag cannot be used with /PFLAG.
:::
:::      /PREPL FilterReplaceCode
:::
:::            Specify a JScript expression FilterReplaceCode that controls
:::            what portion of the /P Pre-filter match is passed on to the main
:::            Search/Replace routine, and what portion is preserved as-is.
:::
:::            The expression is mostly standard JScript, and should evaluate to
:::            a string value. $0 is the entire Pre-filter match, and $1 through
:::            $N are the captured groups. The only non-standard syntax is the
:::            use of curly braces to indicate what string expression gets passed
:::            on to the main Search/Replace. Prior to executing the /P filter,
:::            each brace expression within /PREPL is transformed as follows:
:::
:::               {Expression}  -->  (Expression).replace(Search,Replace)
:::
:::            Any JScript is allowed within /PREPL, except string literals
:::            should not contain $, {, or }.
:::
:::            Using /P without /PREPL is the same as using /P with /PREPL "{$0}"
:::
:::            /PREPL cannot be used with /OFF.
:::
:::            Note that neither /V nor /XFILE apply to /PREPL.
:::
:::            Example - Substitute X for each character within curly braces,
:::                      excluding the braces.
:::
:::               echo abc{xyz}def|jrepl . X /p "({)(.*?)(})" /prepl "$1+{$2}+$3"
:::
:::            result:
:::
:::               abc{XXX}def
:::
:::      /R PreContext:PostContext[:FILE]
:::      /R Context[:FILE]
:::      /R COUNT[:FILE]
:::
:::            Reject matches - Search and write out lines that do not contain
:::            any matches, without doing any replacement. The Replace argument
:::            is still required, but is ignored.
:::
:::            The integers PreContext and PostContext specify how many matching
:::            lines to write before the non-match, and after the non-match,
:::            respectively. If a single Context integer is given, then the same
:::            number of matching lines are written before and after.
:::            A Context of 0 writes only non-matching lines.
:::
:::            If the value of Context is COUNT, then rejected lines are counted
:::            but not written, and the final reject count is written at the end.
:::
:::            If :FILE is appended to the context, then the Search parameter
:::            specifies a file containing one or more search terms, one term
:::            per line. A line is rejected if any of the search terms are found
:::            witin the line. The file can be opened via ADO if |CharSet
:::            (internet character set name) is appended to the file name.
:::            Note: the /V option does not apply to Search if /K :FILE is used.
:::
:::            See /N for how to prefix each rejected line with the line number.
:::
:::            /R is incomptaible with /A, /J, /JQ, /JMATCH, /JMATCHQ, /K, /M,
:::            /MATCH, /S, and /T.
:::
:::      /RTN ReturnVar[:[-]LineNumber]
:::
:::            Write the result to variable ReturnVar.
:::
:::            If the optional LineNumber is present, then only that specified
:::            line within the result set is returned. A LineNumber of 1 is the
:::            first line. A negative LineNumber is measured from the end of the
:::            result set, so -1 is the last line. /RTN always breaks lines at
:::            \r\n and \n - the /EOL value is ignored.
:::
:::            All byte codes except NULL (0x00) are preserved, regardless
:::            whether delayed expansion is enabled or not. An error is thrown
:::            and no value stored if the result contains NULL.
:::
:::            An error is thrown and no value stored if the value does not fit
:::            within a variable. The maximum returned length varies depending
:::            on the variable name and result content. The longest possible
:::            returned length is 8179 bytes.
:::
:::            The line terminator of the last match is suppressed if /MATCH,
:::            /JMATCH, or /JMATCHQ is used. There is also no line terminator
:::            if LineNumber is specified.
:::
:::            /RTN uses a temporary output file to transfer the result to the
:::            environment variable. By default the temporary file is written
:::            as UTF-8. But the file is written using the CSCRIPT default code
:::            page if the /XFILE option is used - the action may fail if the
:::            result contains a character that cannot be mapped to the CSCRIPT
:::            default code page.
:::
:::      /S VarName
:::
:::            The source is read from environment variable VarName instead
:::            of from stdin. Without the /M option, ^ anchors the beginning
:::            of the string, and $ the end of the string. With the /M option,
:::            ^ anchors the beginning of a line, and $ the end of a line.
:::
:::            The variable name must not begin with /.
:::
:::      /T DelimiterChar
:::      /T FILE
:::
:::            The /T option is very similar to the Oracle Translate() function,
:::            or the unix tr command, or the sed y command.
:::
:::            The Search represents a set of search expressions, and Replace
:::            is a like sized set of replacement expressions. Expressions are
:::            delimited by DelimiterChar (a single character). If DelimiterChar
:::            is an empty string, then each character is treated as its own
:::            expression. The /L option is implicitly set if DelimiterChar is
:::            empty. Normally escape sequences are interpreted after the search
:::            and replace strings are split into expressions. But if the
:::            DelimiterChar is empty and /XSEQ is used, then escape sequences
:::            are interpreted prior to the split at every character.
:::
:::            An alternate syntax is to specify the word FILE instead of a
:::            DelimiterChar, in which case the Search and Replace parameters
:::            specify files that contain the search and replace expressions,
:::            one expression per line. Each file can be opened via ADO if
:::            |CharSet (internet character set name) is appended to the file
:::            name. Note that the /V option does not apply to Search and Replace
:::            if /T FILE is used.
:::
:::            Each substring from the input that matches a particular search
:::            expression is translated into the corresponding replacement
:::            expression.
:::
:::            The search expressions may be regular expressions, possibly with
:::            captured groups. Note that each expression is itself converted into
:::            a captured group behind the scene, and the operation is performed
:::            as a single search/replace upon execution. So backreferences within
:::            each regex, and $n references within each replacement expression,
:::            must be adjusted accordingly. The total number of expressions plus
:::            captured groups must not exceed 99.
:::
:::            If an expression must include a delimiter, then an escape
:::            sequence must be used (not an issue if the FILE syntax is used).
:::
:::            Search expressions are tested from left to right. The left most
:::            matching expression takes precedence when there are multiple
:::            matching expressions.
:::
:::        Examples using /T:
:::
:::          ROT13 - Simple character substitution is achieved by setting the
:::          /T delimiter to an empty string. The search and replace strings
:::          must have identical length. The use of line continuation aligns
:::          the replace string directly below the search string, thus making
:::          it very easy to see exactly how each character will be translated.
:::          The "a" in the search string will be replaced by the "n" in the
:::          replace string. And you can see the symmetry in that the "n" will
:::          be replaced by "a".
:::
:::            echo The quick brown fox jumps over a lazy dog | jrepl^
:::             "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"^
:::             "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM"^
:::             /t ""
:::
:::            -- OUTPUT --
:::
:::            Gur dhvpx oebja sbk whzcf bire n ynml qbt
:::
:::          Simple string substitution - The /T option specifies that string
:::          expressions are delimited by a space. The /L option prevents "."
:::          from being interpreted as a regex wildcard character.
:::
:::            echo The blackbird flew through the blue sky. | jrepl^
:::             "black blue sky ." "blue black night !" /l /t " "
:::
:::            -- OUTPUT--
:::
:::            The bluebird flew through the black night!
:::
:::          Simple string substitution using FILE - This is the same as the
:::          prior example, except now the Search and Replace strings are in
:::          the following files:
:::
:::            find.txt          repl.txt
:::            --------          --------
:::            black             blue
:::            blue              black
:::            sky               night
:::            .                 !
:::
:::          The following command yields the same output as before:
:::
:::            echo The blackbird flew through the blue sky. | jrepl^
:::             find.txt repl.txt /l /t file
:::
:::          Pig Latin - This example shows how /T can be used with regular
:::          expressions, and it demonstrates how the numbering of captured
:::          groups must be adjusted. The /T delimiter is set to a space.
:::
:::          The first regex is captured as $1, and it matches words that begin
:::          with a consonant. The first captured group ($2) contains the initial
:::          sequence of consonants, and the second captured group ($3) contains
:::          the balance of the word. The corresponding replacement string moves
:::          $2 after $3, with a "-" in between, and appends "ay".
:::
:::          The second regex matches any word, and it is captured as $4 because
:::          the prior regex ended with group $3. Because the first regex matched
:::          all words that begin with consonants, the only thing the second
:::          regex can match is a word that begins with a vowel. The replacement
:::          string simply adds "-yay" to the end of $4. Note that $& could have
:::          been used instead of $4, and it would yield the same result.
:::
:::            echo Can you speak Pig Latin? | jrepl^
:::             "\b((?:qu(?=[aeiou])|[bcdfghj-np-twxz])+)([a-z']+)\b \b[a-z']+\b"^
:::             "$3-$2ay $4-yay" /t " " /i
:::
:::            -- OUTPUT --
:::
:::            an-Cay you-yay eak-spay ig-Pay atin-Lay?
:::
:::          Pig-Latin with proper capitalization - This is simply an extension
:::          of the prior example. The /JBEG option defines a fixCaps() function
:::          that checks if the translated word is all lower case, except for one
:::          capital letter after the "-". If so, then the initial letter is
:::          capitalized, and the remainder is converted to lower caae. The /JQ
:::          option treats the replacement strings as JScript expressions. The
:::          first replacement expression uses fixCaps() to properly restore case.
:::
:::            echo Can you speak Pig Latin? | jrepl^
:::             "\b((?:qu(?=[aeiou])|[bcdfghj-np-twxz])+)([a-z']+)\b \b[a-z']+\b"^
:::             "$txt=fixCaps($3+'-'+$2+'ay') $txt=$4+'-yay'"^
:::             /t " " /i /j /jbeg ^"^
:::             function fixCaps(str){^
:::               return str.search(/[a-z']+-[A-Z][a-z]*$/)==0 ?^
:::               str.substr(0,1).toUpperCase()+str.substr(1).toLowerCase() : str^
:::             }^"
:::
:::            -- OUTPUT --
:::
:::            An-cay you-yay eak-spay Ig-pay Atin-lay?
:::
:::      /TFLAG Flags
:::
:::            Used to specify XRegExp non-standard mode flags for use with /T.
:::            /TFLAG is ignored unless both /T and /XREG are used.
:::
:::      /U  - Write lines using a Unix line terminator \n instead of Windows
:::            terminator of \r\n. This is the same as using /EOL "\n".
:::            See /EOL help for more info.
:::
:::      /UTF - All input and output encodings are Unicode UTF-16 Little
:::            Endian (UTF-16LE). This includes stdin and stdout. The only
:::            exceptions are /JLIB and /XREG files, which are still read
:::            as ASCII.
:::
:::            The \xFF\xFE BOM is optional for input.
:::
:::            Output files will automatically have the \xFF\xFE BOM inserted.
:::            But stdout will not have the BOM.
:::
:::            Regular expression support of Unicode can be improved by using
:::            the /XREG option.
:::
:::            Variables are never written to temporary files (/XFILE is ignored)
:::            if /UTF is used.
:::
:::            Unfortunately, /UTF is incompatible with /RTN.
:::
:::      /V  - Search, Replace, /INC BlockList, /EXC BlockList, /P FilterRegex,
:::            /JBEG InitCode, /JBEGLN NewLineCode, /JEND FinalCode, and
:::            /JENDLN EndLineCode all represent the names of environment
:::            variables that contain the respective values. An undefined
:::            variable is treated as an empty string.
:::
:::            Variable names beginning with / are reserved for option storage
:::            and other internal uses. So user defined variables used with /V
:::            must not have a name that begins with /.
:::
:::      /VT - Enables Virtual Terminal processing of ANSI escape sequences for
:::            the current JREPL.bat process within the Windows 10 console. This
:::            option is not needed if the registry has HKEY_CURRENT_USER\Console
:::            "VirtualTerminalLevel" DWORD set to 1 in the registry.
:::
:::      /X  - Shorthand for combined /XFILE and /XSEQ.
:::
:::      /XBYTES - Force creation of a new XBYTES.DAT file for use by the /XSEQ
:::            option when decoding \xnn sequences.
:::
:::      /XBYTESOFF - Force JREPL to use pre v7.4 behavior where /XSEQ \xnn is
:::            always interpreted as Windows-1252.
:::
:::      /XFILE - Preserves extended ASCII characters that may appear within
:::            command line arguments and/or variables by first writing the
:::            values to temporary files within the %TEMP% directory. Extended
:::            ASCII values are byte codes >= 128 (0x80).
:::
:::            Temporary files may be needed when the cmd.exe active code page
:::            does not match the default code page used by the CSCRIPT engine.
:::            The default CSCRIPT code page is defined in the registry under
:::            \HKLM\SYSTEM\CurrentControlSet\Control\Nls\CodePage\ACP.
:::
:::            The temporary files are written using the cmd.exe active code page.
:::            The files are read using the CSCRIPT default code page. Extended
:::            ASCII output to the console may appear wrong, but output written
:::            to a file will be correct based on the cmd.exe active code page.
:::
:::            /XFILE is ignored (no temporary files written) if /UTF is used.
:::
:::      /XREG FileList
:::
:::            Adds support for XRegExp by loading the xregexp files specified
:::            in FileList before any /JLIB code is loaded. Multiple files are
:::            delimited by forward slashes (/). If FileList is simply a dot,
:::            then substitute the value of environment variable XREGEXP for
:::            the FileList.
:::
:::            The simplest option is to load "xregexp-all.js", but this
:::            includes all available XRegExp options and addons, some of which
:::            are unlikely to be useful to JREPL. Alternatively you can load
:::            only the specific modules you need, but they must be loaded in the
:::            correct order.
:::
:::            Once the XRegExp module(s) are loaded, all user supplied regular
:::            expressions are created using the XRegExp constructor rather than
:::            the standard RegExp constructor. Also, XRegExp.install('natives')
:::            is executed so that many standard regular expression methods are
:::            overridden by XRegExp methods.
:::
:::            /XREG requires XRegExp version 2.0.0 or 3.x.x. JREPL will not
:::            support version 4.x.x (when it is released) because v4.x.x
:::            is scheduled to drop support for XRegExp.install('natives'). 
:::
:::            One of the key features of XRegExp is that it extends the JScript
:::            regular expression syntax to support named capture groups, as in
:::            (?<name>anyCapturedExpression). Named backreference syntax in
:::            regular expressions is \k<name>. Named group syntax in Replace
:::            strings is ${name}, and in Replace JScript code the syntax is
:::            $0.name
:::
:::            The /T option is no longer limited to 99 capture groups when
:::            /XREG is used. However, /T replace expressions must reference a
:::            captured group by name if the capture index is 100 or above.
:::
:::            Every /T search expression is automatically given a capture group
:::            name of Tn, where n is the 0 based index of the /T expression.
:::
:::            XRegExp also adds support for non-standard mode flags:
:::                n - Explicit capture
:::                s - Dot matches all
:::                x - Free spacing and line comments
:::                A - Astral
:::            These flags can generally be applied by using (?flags) syntax
:::            at the begining of any regex. This is true for /P, /INC, /EXC,
:::            and most Find regular expressions. The one exception is /T doesn't
:::            support (?flags) at the beginning of the Find string. The /TFLAG
:::            option should be used to specify XRegExp flags for use with /T.
:::
:::            XRegExp also improves regular expression support for Unicode via
:::            \p{Category}, \p{Script}, \p{InBlock}, \p{Property} escape
:::            sequences, as well as the negated forms \P{...} and \p{^...}.
:::            Note that example usage on xregexp.com shows use of doubled back
:::            slashes like \\p{...}. But JREPL automatically does the doubling
:::            for you, so you should use \p{...} instead.
:::
:::            See xregexp.com for more information about the capabilities of
:::            XRegExp, and for links to download XRegExp.
:::
:::      /XSEQ - Enables extended escape sequences for both Search strings and
:::            Replacement strings, with support for the following sequences:
:::
:::            \\     -  Backslash
:::            \b     -  Backspace
:::            \c     -  Caret (^)
:::            \f     -  Formfeed
:::            \n     -  Newline
:::            \q     -  Quote (")
:::            \r     -  Carriage Return
:::            \t     -  Horizontal Tab
:::            \v     -  Vertical Tab
:::            \xnn   -  Extended ASCII byte code expressed as 2 hex digits nn.
:::                      The code is mapped to the correct Unicode code point,
:::                      depending on the chosen character set. If used within
:::                      a Find string, then the input character set is used. If
:::                      within a Replacement string, then the output character
:::                      set is used. If the selected character set is invalid or
:::                      not a single byte character set, then \xnn is treated as
:::                      a Unicode code point. Note that extended ASCII character
:::                      class ranges like [\xnn-\xnn] should not be used because
:::                      the intended range likely does not map to a contiguous
:::                      set of Unicode code points - use [\x{nn-mm}] instead.
:::            \x{nn-mm} - A range of extended ASCII byte codes for use within
:::                      a regular expression character class expression. The
:::                      The min value nn and max value mm are expressed as hex
:::                      digits. The range is automatically expanded into the
:::                      full set of mapped Unicode code points. The character
:::                      set mapping rules are the same as for \xnn.
:::            \x{nn,CharSet} - Same as \xnn, except explicitly uses CharSet
:::                      character set mapping.
:::            \x{nn-mm,CharSet} - Same as \x{nn-mm}, except explicitly uses
:::                      CharSet character set mapping.
:::            \unnnn -  Unicode code point expressed as 4 hex digits nnnn.
:::            \u{N}  -  Any Unicode code point where N is 1 to 6 hex digits
:::
:::            JREPL automatically creates an XBYTES.DAT file containing all 256
:::            possible byte codes. The XBYTES.DAT file is preferentially created
:::            in "%ALLUSERSPROFILE%\JREPL\" if at all possible. Otherwise the
:::            file is created in "%TEMP%\JREPL\" instead. JREPL uses the file
:::            to establish the correct \xnn byte code mapping for each character
:::            set. Once created, successive runs reuse the same XBYTES.DAT file.
:::            If the file gets corrupted, then use the /XBYTES option to force
:::            creation of a new XBYTES.DAT file. If JREPL cannot create the file
:::            for any reason, then JREPL silently defaults to using pre v7.4
:::            behavior where /XSEQ \xnn is interpreted as Windows-1252. Creation
:::            of XBYTES.DAT requires either CERTUTIL.EXE or ADO. It is possible
:::            that both may be missing from an XP machine.
:::
:::            Without the /XSEQ option, only standard JSCRIPT escape sequences
:::            \\, \b, \f, \n, \r, \t, \v, \xnn, \unnnn are available for the
:::            search strings. And the \xnn sequence represents a unicode
:::            code point, not extended ASCII.
:::
:::            Extended escape sequences are supported even when the /L option
:::            is used. Both Search and Replace support all of the extended
:::            escape sequences if both the /XSEQ and /L options are combined.
:::
:::            Extended escape sequences are not applied to JScript code when
:::            using any of the /Jxxx options. Use the decode() function if
:::            extended escape sequences are needed within the code.
:::
::/JSCRIPT
:::
:::  The following global JScript variables/objects/functions are available for
:::  use in JScript code associated with the /Jxxx options. User code may safely
:::  declare additional variables/objects/functions because all other internal
:::  objects used by JREPL are hidden behind an opaque _g object.
:::
:::      ln     - Within /JBEGLN, /JENDLN, and Replace code = current line number
:::               Within /JBEG code = 0
:::               Within /JEND code = total number of lines read.
:::               This value is always 0 if the /M or /S option is used.
:::
:::      cnt    - The total number of lines in the input. The value is undefined
:::               unless the /C option is used.
:::
:::      counter - A general purpose counter that is initialized to 0. This
:::               variable is used by /K COUNT and /R COUNT to track the number
:::               of kept/rejected lines, and by /MATCH with a "COUNT" replace
:::               value to track the number of matches.
:::
:::      skip   - If true, do not search/replace any more lines until the value
:::               becomes false. /JBEGLN and /JENDLN code are still executed for
:::               each line, regardless. If set to true while in the midst of
:::               searching a line, then that search will continue to the end of
:::               the current line.
:::
:::               The default value is false.
:::
:::               This variable has no impact if the /M or /S options is used.
:::
:::               Note that this variable operates independently of the /INC
:::               and /EXC options.
:::
:::      quit   - If true, then do not read any more lines of input. The current
:::               line is still processed to completion, and /JEND code is still
:::               executed afterward.
:::
:::               The default value is false.
:::
:::               This variable has no impact if the /M or /S options is used.
:::
:::      env('varName')
:::
:::               Access to environment variable named varName.
:::
:::      decode( String [,CharSet] )
:::
:::               Decodes extended escape sequences within String as defined by
:::               the /XSEQ option, and returns the result. CharSet specifies the
:::               single byte character set to use for \xnn escape sequences.
:::               If CharSet is 'input', then the character set of the input is
:::               used. If CharSet is 'output', then the character set of the
:::               output is used. If CharSet is 'default' or undefined, then the
:::               default character set for the machine is used. Otherwise,
:::               CharSet should be a valid internet character set name understood
:::               by the machine. If the selected character set is invalid or not
:::               a single byte character set, then \xnn is treated as a Unicode
:::               code point.
:::
:::               All backslashes within String must be escaped an extra time to
:::               use this function in your code.
:::
:::               Examples:
:::                  quote literal:       decode('\\q','output')
:::                  extended ASCII(128): decode('\\x80','output')
:::                  backslash literal:   decode('\\\\','output')
:::
:::               This function is only needed if you use any \q, \c, or \u{N}
:::               escape sequences, or \xnn escape sequence for extended ASCII.
:::               
:::      lpad( value, padString )
:::      lpad( value, length [,padString] )
:::
:::               Used to left pad a value to a minimum width string. If the
:::               value already has string width >= the desired length, then no
:::               change is made. Otherwise it left pads the value with the
:::               characters of the pad string to the desired length. If only
:::               padString is specified, then the value is padded to the length
:::               of padString. If length is specified with a padString, then
:::               padString is replicated as needed to get the desired length.
:::               If length is specified without padString, then spaces are used
:::               for the padString.
:::
:::               Examples:
:::                  lpad(15,'    ')        returns '  15'
:::                  lpad(15,4)             returns '  15'
:::                  lpad(15,'0000')        returns '0015'
:::                  lpad(15,4,'0')         returns '0015'
:::                  lpad(19011,4,'0')      returns '19011'
:::                  lpad('A','. . . . .')  returns '. . . . .A'
:::                  lpad('A',9,'. ')       returns '. . . . .A'
:::                  lpad('AB','. . . . .') returns '. . . . AB'
:::                  lpad('AB',9,'. ')      returns '. . . . AB'
:::
:::      rpad( value, padString )
:::      rpad( value, length [,padString] )
:::
:::               Used to right pad a value to a minimum width string. If the
:::               value already has string width >= the desired length, then no
:::               change is made. Otherwise it right pads the value with the
:::               characters of the pad string to the desired length. If only
:::               padString is specified, then the value is padded to the length
:::               of padString. If length is specified with a padString, then
:::               padString is replicated as needed to get the desired length.
:::               If length is specified without padString, then spaces are used
:::               for the padString.
:::
:::               Examples:
:::                  rpad('hello','          ')  returns 'hello     '
:::                  rpad('hello',10)            returns 'hello     '
:::                  rpad('hello',' . . . . .')  returns 'hello. . .'
:::                  rpad('hello',10,' .')       returns 'hello. . .'
:::                  rpad('hell',' . . . . .')   returns 'hell . . .'
:::                  rpad('hell',10,' .')        returns 'hell . . .'
:::                  rpad('hello',2)             returns 'hello'
:::
:::      inc( [blockNum] )
:::
:::               A boolean function that returns true or false.
:::
:::               Returns true if the current line appears within the specified
:::               /INC blockNum. A blockNum of 0 specifies the first /INC block.
:::
:::               If blockNum is not specified, then returns true if the current
:::               line appears within any /INC block.
:::
:::      exc( [blockNum] )
:::
:::               A boolean function that returns true or false.
:::
:::               Returns true if the current line appears within the specified
:::               /EXC blockNum. A blockNum of 0 specifies the first /EXC block.
:::
:::               If blockNum is not specified, then returns true if the current
:::               line appears within any /EXC block.
:::
:::      fso    - An instantiation of the FileSystemObject object.
:::
:::      input  - The TextStream object from which input is read.
:::               This may be stdin or a file.
:::
:::               If the file was opened by ADO with |CharSet, then input is
:::               an object that partially emulates a TextStream object, with
:::               a private ADO Stream doing the actual work. The following
:::               public members are available to the ADO object:
:::
:::                 Property           Method
:::                 -------------      ----------
:::                 AtEndOfStream      Read
:::                                    ReadLine  (line terminator \n or \r\n)
:::                                    SkipLine  (line terminator \n or \r\n)
:::                                    Write
:::                                    WriteLine (line terminator always \r\n)
:::                                    Close
:::
:::      output - The TextStream object to which the output is written.
:::               This may be stdout or a file. If /RTN is used, then the output
:::               is first written to a temporary file before it is read and
:::               stored in the return variable.
:::
:::               If the file was opened by ADO with |CharSet, then output is
:::               an object that partially emulates a TextStream object (see the
:::               input object).
:::
:::      stdin  - Equivalent to WScript.StdIn
:::
:::      stdout - Equivalent to WScript.StdOut
:::
:::      stderr - Equivalent to WScript.StdErr
:::
:::      openOutput( fileName[|CharSet[|NB]] [,appendBoolean [,utfBoolean]] )
:::
:::               Open a new TextStream object for writing and assign it to the
:::               output variable. If appendBoolean is truthy, then open the file
:::               for appending.
:::
:::               If |CharSet is appended to the fileName, then open the file
:::               using ADO and the specified internet character set name. The
:::               output variable will be set to an object that partially
:::               emulates a TextStream object (see the input object). Unicode
:::               written by ADO will have a BOM by default. The BOM is blocked
:::               by appending |NB (or |anyValue) to the CharSet.
:::
:::               If utfBoolean is truthy, then output is encoded as unicode
:::               (UTF-16LE). The unicode file will automatically have the BOM
:::               unless opened for appending. The utfBoolean argument is ignored
:::               if |CharSet is also specified.
:::
:::               If fileName is falsey, then output is written to stdout.
:::
:::               All subsequent output will be written to the new destination.
:::
:::               Any prior output file is automatically closed.
:::
:::      eol    - The line terminator used when writing output lines. This is the
:::               same value set by the /EOL option.
:::
:::  See the /JQ option help for info about local $ variables that may be used
:::  within replacement code when using /JQ or /JMATCHQ.
::/HELP
:::
:::  Help is available by supplying a single argument beginning with /? or /??:
:::
:::      /?        - Writes all available help to stdout.
:::      /??       - Same as /? except uses MORE for pagination.
:::
:::      /?Topic   - Writes help about the specified topic to stdout.
:::                  Valid topics are:
:::
:::                    INTRO   - Basic syntax and default behavior
:::                    OPTIONS - Brief summary of all options
:::                    JSCRIPT - JREPL objects available to user JScript
:::                    RETURN  - All possible return codes
:::                    VERSION - Display the version of JREPL.BAT
:::                    HISTORY - A summary of all releases
:::                    HELP    - Lists all methods of getting help
:::
:::                  Example: List a summary of all available options
:::
:::                     jrepl /?options
:::
:::      /?WebTopic - Opens up a web page within your browser about a topic.
:::                  Valid web topics are:
:::
:::                    REGEX   - Microsoft regular expression documentation
:::                    REPLACE - Microsoft Replace method documentation
:::                    UPDATE  - DosTips release page for JREPL.BAT
:::                    CHARSET - List of possible character set names for ADO I/O
:::                              Some character sets may not be installed
:::                    XREGEXP - xRegExp.com home page (extended regex docs)
:::
:::      /?/Option - Writes detailed help about the specified /Option to stdout.
:::
:::                  Example: Display paged help about the /T option
:::
:::                     jrepl /??/t
:::
:::      /?CHARSET/[Query] - List all character set names for use with ADO I/O
:::                  that are installed on this computer. Optionally restrict
:::                  the list to names that contain Query. Wildcards * and ? may
:::                  be used within Query. The default Query is an empty string,
:::                  meaning list all available character sets. The list is
:::                  generated via reg.exe.
:::
:::                  Examples:
:::
:::                     jrepl /??charset/    - Paged list of all available names
:::                     jrepl /?charset/utf  - List of names containing "utf"
::/RETURN
:::
:::  Possible ERRORLEVEL Return Codes:
:::
:::      If /? was used, and no other argument
:::          0 = Only possible return
:::
:::      If /MATCH, /JMATCH, /JMATCHQ, /K, and /R were not used
:::          0 = At least one change was made
:::          1 = No change was made
:::          2 = Invalid call syntax or incompatible options
:::          3 = JScript runtime error
:::
:::      If /MATCH, /JMATCH, /JMATCHQ, /K, or /R was used
:::          0 = At least one line was written
:::          1 = No line was written
:::          2 = Invalid call syntax or incompatible options
:::          3 = JScript runtime error
::/VERSION
:::
:::  JREPL.BAT version 8.6 was written by Dave Benham, and originally posted at
:::  http://www.dostips.com/forum/viewtopic.php?f=3&t=6044
::/

============= :Batch portion ===========
@echo off
setlocal disableDelayedExpansion

:: Process Help
if .%2 equ . call :help "%~1" && exit /b 0 || call :exitErr "Insufficient arguments"

:: Define options
set ^"/options= /A: /APP: /B: /C: /D:":" /DBUG: /E: /EOL:"\r\n" /EXC:"" /F:"" /H: /HON:"\x1B[7m" /HOFF:"\x1B[0m"^
                /HU: /I: /INC:"" /J: /JBEG:"" /JBEGLN:"" /JEND:"" /JENDLN:"" /JLIB:"" /JMATCH: /JMATCHQ: /JQ:^
                /K:"" /L: /M: /MATCH: /N:0 /O:"" /OFF:0 /P:"" /PFLAG:"g" /PREPL:"" /R:"" /RTN:"" /S:""^
                /T:"none" /TFLAG:"" /U: /UTF: /V: /VT: /X: /XBYTES: /XBYTESOFF: /XFILE: /XSEQ: /XREG:"" ^"
:: Set default option values
for %%O in (%/options%) do for /f "tokens=1,* delims=:" %%A in ("%%O") do set "%%A=%%~B"

:: Get options
:loop
if not "%~3"=="" (
  set "/test=%~3"
  setlocal enableDelayedExpansion
  if "!/test:~0,1!" neq "/" call :exitErr "Too many arguments"
  set "/test=!/options:*%~3:=! "
  if "!/test!"=="!/options! " (
      endlocal
      call :exitErr "Invalid option %~3"
  ) else if "!/test:~0,1!"==" " (
      endlocal
      set "%~3=1"
  ) else (
      endlocal
      set "%~3=%~4"
      shift /3
  )
  shift /3
  goto :loop
)

:: Validate options
if defined /M if defined /A if not defined /S                                      call :exitErr "/M cannot be used with /A without /S"
if "%/O%" equ "-" if not defined /F                                                call :exitErr "Output = - but Input file not specified"
if defined /F if defined /S                                                        call :exiterr "/S cannot be used with /F"
if defined /F for %%A in ("%/F%") do for %%B in ("%/O%") do if "%%~fA" equ "%%~fB" call :exitErr "Output file cannot match Input file"
if defined /RTN if defined /O                                                      call :exitErr "/O and /RTN are mutually exclusive"
if defined /RTN if defined /UTF                                                    call :exitErr "/UTF and /RTN are mutually exclusive"
if "%/EXC%%/INC%%/C%%/JBEGLN%%/JENDLN%" neq "" if "%/M%%/S%" neq ""                call :exitErr "/C, /INC, /EXC, /JBEGLN, and /JENDLN cannot be used with /M or /S"
for /f "tokens=2" %%A in ("%/J% %/JQ% %/JMATCH% %/JMATCHQ% %/K% %/R% %/MATCH%") do call :exitErr "/J, /JQ, /JMATCH, /JMATCHQ, /MATCH, /K and /R are all mutually exclusive"
if "%/K%%/R%" neq "" if "%/A%%/M%%/S%%/T%" neq "none"                              call :exitErr "/K, /R cannot be used with /A, /M, /S or /T"
if defined /MATCH if "%/A%%/T%" neq "none"                                         call :exitErr "/MATCH cannot be used with /A or /T"
for /f delims^=giGI^ eol^= %%A in ("%/PFLAG%") do                                  call :exitErr "Invalid /PFLAG value"
if "%/OFF%" neq "0" if defined /PREPL                                              call :exitErr "/PREPL cannot be used with /OFF"
for /f "delims=| eol=| tokens=2*" %%A in ("%/APP%|%/O%x") do if %%A==- if .%%B neq . call :exitErr "/APP cannot be combined with /O - with CharSet"

:: Transform options
if "%/XREG%"=="." (set /XREG=%XREGEXP%)
if defined /X set "/XFILE=1" & set "/XSEQ=1"
if defined /MATCH set "/JMATCHQ=1"
if defined /JMATCHQ set "/JMATCH=1"
if defined /JMATCH set "/J=1"
if defined /JQ set "/J=1"
if "%/JMATCH%%/K%" equ "" set "/OFF=0"
if defined /UTF set "/UTF=//u" & set "/XFILE="
if not defined /T set "/L=1"
if "%/M%%/S%" neq "" set "/N=0"
if defined /U set "/EOL=\n"
if defined /HU (
  set "/H=1"
  set "/HON=\x1B[4m"
  set "/HOFF=\x1B[24m"
)
if defined /R set "/H="
if defined /RTN (
  setlocal enableDelayedExpansion
  for /f "eol=: delims=: tokens=1,2" %%A in ("!/RTN!") do (
    endlocal
    set "/RTN=%%A"
    set "/RTN_LINE=%%B"
  )
)

if defined /XBYTESOFF set "/XBYTES=" & goto :endXBytes
if defined /XBYTES set "/XBYTES=" & goto :createXBytes
for %%F in (
  "%ALLUSERSPROFILE%\JREPL\XBYTES.DAT"
  "%TEMP%\JREPL\XBYTES.DAT"
  "%TMP%\JREPL\XBYTES.DAT"
) do if "%%~zF" equ "256" set "/XBYTES=%%~fF" & goto :endXBytes

:createXBytes
:: Attempt to create XBYTES.DAT via CERTUTIL. If able to write to the JREPL
:: subdirectory, but unable to create correct file, then pass task to JScript.
for %%F in (
  "%ALLUSERSPROFILE%"
  "%TEMP%"
  "%TMP%"
) do if %%F neq "" for %%F in ("%%~F\JREPL\XBYTES.DAT") do (
  del %%F
  md "%%~dpF"
  (  >"%%~dpnF.HEX" (
    for %%A in (0 1 2 3 4 5 6 7 8 9 A B C D E F) do for %%B in (0 1 2 3 4 5 6 7 8 9 A B C D E F) do echo %%A%%B
  )) && (
    set "/XBYTES=%%~fF"
    certutil.exe -f -decodehex "%%~dpnF.HEX" "%%~fF"
    for %%G in (%%F) do if "%%~zG" neq "256" del %%F
    del "%%~dpnF.HEX"
    goto :endXBytes
  )
) >nul 2>nul
:endXBytes

set ^"/FIND=%1"
set ^"/REPL=%2"
call :GetScript /SCRIPT
set "/LOCK="

set "/FindReplVar="
if defined /UTF (
  set "/FindReplVar=1"
  set "/FIND2=%/FIND:"=%"
  set "/REPL2=%/REPL:"=%"
  set "/FIND=/FIND2"
  set "/REPL=/REPL2"
  goto :noLock
)
if defined /V if /i "%/T%" neq "FILE" set "/FindReplVar=1"
if defined /XFILE if /i "%/T%" neq "FILE" set "/FindReplVar=1"
if defined /RTN goto :lock
if not defined /XFILE goto :noLock
if defined /FindReplVar goto :lock
if not defined /JBEG if not defined /JBEGLN if not defined /JEND if not defined /JENDLN if not defined /INC if not defined /EXC if not defined /P if not defined /S goto :noLock

:lock
setlocal enableDelayedExpansion
set "/LOCK=jrepl.bat.!date:\=-!_!time::=.!_!random!.temp"
set "/LOCK=!/LOCK:/=-!"
for /f "delims=" %%F in ("!temp!\!/LOCK::=-!") do (
  endlocal
  set "/LOCK=%%~fF"
)
if defined /RTN (
  set "/CHCP="
  if not defined /XFILE for /f "tokens=2 delims=:." %%P in ('chcp') do (
    chcp 65001 >nul 2>nul && (
      set "/CHCP=%%P"
      chcp %%P >nul 2>nul
    )
  )
  if defined /CHCP (set "/O=%/LOCK%.RTN|utf-8|nb") else set "/O=%/LOCK%.RTN"
)
9>&2 2>nul (
  8>"%/LOCK%" (
    2>&9 (
      if defined /XFILE (
        setlocal enableDelayedExpansion
        if defined /S call :writeVar S
        if defined /V (
          if defined /FindReplVar (
            call :writeVar FIND
            call :writeVar REPL
          )
          if defined /JBEG   call :writeVar JBEG
          if defined /JBEGLN call :writeVar JBEGLN
          if defined /JEND   call :writeVar JEND
          if defined /JENDLN call :writeVar JENDLN
          if defined /INC    call :writeVar INC
          if defined /EXC    call :writeVar EXC
          if defined /P      call :writeVar P
        ) else (
          if defined /FindReplVar (
            (echo(!/FIND:^"=!) >"!/LOCK!.FIND"
            (echo(!/REPL:^"=!) >"!/LOCK!.REPL"
          )
          if defined /JBEG (echo(!/JBEG!) >"!/LOCK!.JBEG"
          if defined /JBEGLN (echo(!/JBEGLN!) >"!/LOCK!.JBEGLN"
          if defined /JEND (echo(!/JEND!) >"!/LOCK!.JEND"
          if defined /JENDLN (echo(!/JENDLN!) >"!/LOCK!.JENDLN"
          if defined /INC (echo(!/INC!) >"!/LOCK!.INC"
          if defined /EXC (echo(!/EXC!) >"!/LOCK!.EXC"
          if defined /P (echo(!/P!) >"!/LOCK!.P"
        )
        endlocal
      )
      call :execute
    )
  )
  if errorlevel 3 (del "%/LOCK%*"&exit /b 3)
  if errorlevel 1 (del "%/LOCK%*"&(call)) else del "%/LOCK%*"
  if "%/RTN%" equ "" exit /b
) || goto :lock

:writeVar
for /f delims^=^ eol^= %%A in ("!/%1!") do (echo(!%%A!) >"!/LOCK!.%1"
exit /b

:noLock
call :execute
exit /b %errorlevel%

:execute
cscript.exe //E:JScript //nologo %/UTF% "%/SCRIPT%" %/FIND% %/REPL%
if not defined /RTN exit /b %errorlevel%

::returnVar
if errorlevel 3 exit /b %errorlevel%
if defined /CHCP chcp 65001 >nul 2>nul
set "/ERR=%errorlevel%"
set "/NORMAL="
for /f "usebackq delims=" %%A in ("%/LOCK%.RTN") do (
  if not defined /NORMAL (
    set "/NORMAL=%%A"
  ) else set "/DELAYED=%%A"
)
chcp %/CHCP% >nul 2>nul
for /f %%2 in (
  'copy /z "%/SCRIPT%" nul' %= This generates CR =%
) do for %%1 in (^"^
%= This generates quoted LF =%
^") do for /f "tokens=1,2" %%3 in (^"%% "") do (
  (goto) 2>nul
  (goto) 2>nul
  if "^!^" equ "^!" (
    set "%/RTN%=%/DELAYED:~1%"!
  ) else (
    set "%/RTN%=%/NORMAL:~1%"
  )
  if %/ERR% equ 0 (call ) else (call)
)

:GetScript
set "%1=%~f0"
exit /b

:help
setlocal
set "help=%~1"
setlocal enableDelayedExpansion
if "!help:~0,2!" neq "/?" exit /b 1
set "noMore=1"
set "help=!help:~2!"
if defined help if "!help:~0,1!" equ "?" (
  set "noMore="
  set "help=!help:~1!"
)
for /f "delims=" %%A in ("/!help!") do if /i "%%~pA" equ "\CharSet\" ( %= /?CHARSET/ =%
  echo(
  if defined noMore (
    for /f "delims=" %%F in ('reg query HKCR\MIME\Database\Charset /k /f "%%~nxA"') do echo %%~nF
  ) else (
    (cmd /c "for /f "delims=" %%F in ('reg query HKCR\MIME\Database\Charset /k /f "%%~nxA"') do @echo %%~nF") | more /e
  )
  exit /b 0
)
if defined help if "!help:~0,2!" equ "/?" set "help=help"
for /f "delims=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/ eol=a" %%A in ("!help!") do (
  echo(
  echo Invalid /? option
  exit /b 0
)
if /i "!help!" equ "regex" (
    explorer "https://msdn.microsoft.com/en-us/library/ae5bf541.aspx"
    exit /b 0
) else if /i "!help!" equ "replace" (
    explorer "https://msdn.microsoft.com/en-US/library/efy6s3e6.aspx"
    exit /b 0
) else if /i "!help!" equ "update" (
    explorer "http://www.dostips.com/forum/viewtopic.php?f=3&t=6044"
    exit /b 0
) else if /i "!help!" equ "charset" (
    explorer "https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756.aspx"
    exit /b 0
) else if /i "!help!" equ "xregexp" (
    explorer "http:xregexp.com"
    exit /b 0
) else if "!help!" equ "" ( %= /? =%
    set "find=^:::(.*)"
    set "repl=$1"
    set ^"cmd="%~f0" find repl /v /a /f "%~f0"^"
) else if "!help:~0,1!" equ "/" (   %= /?/Option =%
    set "find=^:::(.*)"
    set "repl=$txt=$1"
    set "help=!help:/=\/!"
    set "inc=/^^::: {6}!help!(?= |$)/i/:/^^::: {6}\/(?^!!help:~2!(?= |$))|^^::\//i-1"
    set "help=!help:\/=/!"
    set ^"cmd=echo(^&call "%~f0" find repl /v /jmatchq /inc inc /f "%~f0"^|^|echo Help not found for option %help%^"
) else ( %= /?Topic =%
    set "find=^:::?(.*)"
    set "repl=$txt=$1"
    set "inc=/^^::\/!help:/=\/!$/i/+1:/^^::\//-1"
    set ^"cmd="%~f0" find repl /v /jmatchq /inc inc /f "%~f0"^|^|(echo(^&echo Help not found for topic %help%^)^"
)
if defined noMore (
  setlocal
  set "pathext=."
  call %cmd%
) else (%cmd%) | more /e
exit /b 0

:exitErr
>&2 (
  echo ERROR: %~1.
  echo   Use JREPL /? or JREPL /?? to get help.
  (goto) 2>nul
  exit /b 2
)


************* JScript portion **********/
var _g=new Object();
_g.loc='';
_g.objSh=WScript.CreateObject("WScript.Shell");
try {
  var env=_g.objSh.Environment("Process"),
      cnt,
      counter=0,
      ln=0,
      skip=false,
      quit=false,
      fso,
      stdin=WScript.StdIn,
      stdout=WScript.Stdout,
      stderr=WScript.Stderr,
      output,
      input;
  if (env('/VT')!='') _g.objExec=_g.objSh.Exec("powershell.exe -nop -ep Bypass -c \"exit\"");
  _g.ForReading=1;
  _g.ForWriting=2;
  _g.ForAppending=8;
  _g.FileFormat = env('/UTF') ? -1 : 0;
  _g.TemporaryFolder=2;
  fso = new ActiveXObject("Scripting.FileSystemObject");
  _g.inFile=env('/F');
  _g.inFileA=_g.inFile.split('|');
  _g.outFile=env('/O');
  _g.outFileA=_g.outFile.split('|');
  if (_g.outFileA[0]=='-') {
    if (_g.outFileA[1]===undefined) {_g.outFileA[1]=_g.inFileA[1]; _g.outFileA[2]=_g.inFileA[2];}
    _g.outFile = _g.inFileA[0]+'.new'+(_g.outFileA[1]?'|'+_g.outFileA[1]:'')+(_g.outFileA[2]?'|'+_g.outFileA[2]:'');
    if (env('/APP')) fso.CopyFile( _g.inFileA[0], _g.inFileA[0]+'.new', true );
  }
  _g.tempFile='';
  _g.delim=env('/D');
  _g.loc=" defining EOL"
  eol=eval('"'+env('/EOL')+'"');
  _g.loc="";

  _g.ADOStream = function( name, mode, format, noBom) {
    var that = this;
    var bomSize = 0;
    try {
      var stream = WScript.CreateObject("ADODB.Stream");
    } catch(ex) {
      throw new Error(215,'ADO unavailable');
    }
    try {
      stream.CharSet = format;
    } catch(ex) {
      throw new Error(215,'ADO character set "'+format+'" is invalid or unavailable');
    }
    stream.LineSeparator = (mode==_g.ForReading) ? 10 : -1;
    stream.Open();
    if (mode !== _g.ForReading && noBom) {
      stream.WriteText("");
      stream.Position = bomSize = stream.Size;
    }
    switch (mode) {
      case _g.ForReading:
        stream.LoadFromFile(name);
        break;
      case _g.ForAppending:
        stream.LoadFromFile(name);
        stream.Position = stream.Size;
      case _g.ForWriting:
        break;
      default:
        throw new Error(215, 'Invalid file mode');
    }
    this.AtEndOfStream = stream.EOS;

    this.ReadLine = function() {
      if (mode!=_g.ForReading) throw new Error(215, 'Bad file mode');
      var str = stream.ReadText(-2);
      that.AtEndOfStream = stream.EOS;
      return str.slice(-1)=='\r' ? str.slice(0,-1) : str;
    }

    this.Read = function(size) {
      if (mode!=_g.ForReading) throw new Error(215, 'Bad file mode');
      var str = stream.ReadText(size)
      that.AtEndOfStream = stream.EOS;
      return str;
    }

    this.SkipLine = function() {
      if (mode!=_g.ForReading) throw new Error(215, 'Bad file mode');
      stream.SkipLine();
      that.AtEndOfStream = stream.EOS;
    }

    this.Write = function(str) {
      if (mode==_g.ForReading) throw new Error(215, 'Bad file mode');
      stream.WriteText(str);
    }

    this.WriteLine = function(str) {
      if (mode==_g.ForReading) throw new Error(215, 'Bad file mode');
      stream.WriteText(str,1);
    }

    this.Close = function() {
      if (mode!==_g.ForReading){
        if (bomSize) {
          var noBomStream = WScript.CreateObject("ADODB.Stream");
          noBomStream.Type = 1;
          noBomStream.Mode = 3;
          noBomStream.Open();
          stream.Position = bomSize;
          stream.CopyTo(noBomStream);
          noBomStream.SaveToFile( name, 2 );
          noBomStream.Flush();
          noBomStream.Close();
          noBomStream = null;
        } else stream.SaveToFile( name, 2 );
      }
      stream.Close();
      stream=null;
    }
  }

  _g.openInput = function( fileName ) {
    var file;
    if (fileName) {
      file = fileName.split('|');
      if (file[1]) {
        file = new _g.ADOStream( file[0], _g.ForReading, file[1], file[2] );
        return file;
      }
      else return fso.OpenTextFile( fileName, _g.ForReading, false, _g.FileFormat );
    }
    else return stdin;
  }

  _g.charMap = new Object();
  _g.readVar = function( val, ref, ext ) {
    var input, buf=1024;
    if (!env('/XFILE') || !val) return (ref && val) ? env(val) : val;
    _g.loc=' reading '+env('/LOCK')+ext;
    input=fso.OpenTextFile( env('/LOCK')+ext, _g.ForReading );
    val='';
    while (!input.AtEndOfStream) {
      val+=input.Read(buf);
      buf*=2;
    }
    input.Close();
    _g.loc=''
    return val.slice(0,-2);
  }

  _g.xbytes = env('/XBYTES');
  if (_g.xbytes && !(fso.FileExists(_g.xbytes))) try {
    // Unable to create file with CERTUTIL, so now try with ADO
    var Stream=WScript.CreateObject('ADODB.Stream'),
        Node=WScript.CreateObject('Microsoft.XMLDOM').createElement('e');
    Node.dataType='bin.base64';
    Node.text='AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4v'
    + 'MDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5f'
    + 'YGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6P'
    + 'kJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/'
    + 'wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v'
    + '8PHy8/T19vf4+fr7/P3+/w==';
    Stream.Type=1;
    Stream.Open();
    Stream.Write(Node.nodeTypedValue);
    Stream.SaveToFile(_g.xbytes);
  } catch(e) {
    _g.xbytes = '';
  }
  var decode = _g.xbytes ?
    // Default dynamic character set decode() for v7.4 and beyond
    function(str, charSet, searchSwitch) {
      function u(codeUnit) {return '\\u'+lpad(codeUnit.toString(16),4,'0');}
      function xToUTF16(byte,charSet) {
        if (typeof _g.charMap[charSet]==='undefined') {
          if (charSet=='default' && _g.utf) {
            _g.charMap[charSet]=false
          } else {
            var stream = _g.openInput( _g.xbytes+(charSet=='default'?'':'|'+charSet) );
            try {
              _g.charMap[charSet] = stream.Read(256);
              stream.Close();
              if (_g.charMap[charSet].length!=256) _g.charMap[charSet]=false;
            } catch(e) {
              _g.charMap[charSet]=false;
            }
          }
        }
        return  u( _g.charMap[charSet] ? _g.charMap[charSet].charCodeAt(byte) : byte );
      }
      function xRange(min,max,charSet) {
        var str='', i;
        for (i=min; i<=max; i++ ) str+=xToUTF16(i,charSet);
        return str;
      }
      function uToUTF16(codePoint) {
        if (codePoint <= 0xFFFF) return u(codePoint);
        codePoint -= 0x10000;
        return u(0xD800|(codePoint>>10)) + u(0xDC00|(codePoint&1023));
      }
      if (charSet===undefined) charSet='default';
      if (charSet=='input') charSet = _g.inFileA[1] ? _g.inFileA[1] : 'default';
      if (charSet=='output') charSet = _g.outFileA[1] ? _g.outFileA[1] : 'default';
      return str.replace(
        /\\(?:\\|b|c|f|n|q|r|t|v|x([0-9a-fA-F]{2})|x\{([0-9a-fA-F]{2}),([^}]+)}|u[0-9a-fA-F]{4}|u\{([0-9a-fA-F]+)\}|x\{([0-9a-fA-F]{2})-([0-9a-fA-F]{2})(?:,([^}]+))?})/g,
        function($0,$1,$2,$3,$4,$5,$6,$7) {
          if ($0=='\\q') return '"';
          if ($0=='\\c') return '^';
          if ($1) $0=xToUTF16(parseInt($1,16),charSet);
          if ($2) $0=xToUTF16(parseInt($2,16),$3);
          if ($4) $0=uToUTF16(parseInt($4,16));
          if ($5) $0=xRange(parseInt($5,16),parseInt($6,16),($7?$7:charSet));
          return searchSwitch===false ? $0 : eval('"'+$0+'"');
        }
      );
    }
    : // Pre-v7.4 decode() that assumes Windows-1252, only used if XBYTES.DAT not available or disabled.
    function(str, ignore, searchSwitch) {
      function toUTF16(codePoint) {
        function u(codeUnit) {return '\\u'+lpad(codeUnit.toString(16),4,'0');}
        if (codePoint <= 0xFFFF) return u(codePoint);
        codePoint -= 0x10000;
        return u(0xD800|(codePoint>>10)) + u(0xDC00|(codePoint&1023));
      }
      str=str.replace(
        /\\(\\|b|c|f|n|q|r|t|v|x80|x82|x83|x84|x85|x86|x87|x88|x89|x8[aA]|x8[bB]|x8[cC]|x8[eE]|x91|x92|x93|x94|x95|x96|x97|x98|x99|x9[aA]|x9[bB]|x9[cC]|x9[dD]|x9[eE]|x9[fF]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|u\{([0-9a-fA-F]+)\}|x\{([0-9a-fA-F]{2}),[^}]+\})/g,
        function($0,$1,$2,$3) {
          if ($3) {
            $1='x'+$3;
            $0='\\'+$1;
          }
          switch ($1.toLowerCase()) {
            case 'q':   return '"';
            case 'c':   return '^';
            case 'x80': return '\u20AC';
            case 'x82': return '\u201A';
            case 'x83': return '\u0192';
            case 'x84': return '\u201E';
            case 'x85': return '\u2026';
            case 'x86': return '\u2020';
            case 'x87': return '\u2021';
            case 'x88': return '\u02C6';
            case 'x89': return '\u2030';
            case 'x8a': return '\u0160';
            case 'x8b': return '\u2039';
            case 'x8c': return '\u0152';
            case 'x8e': return '\u017D';
            case 'x91': return '\u2018';
            case 'x92': return '\u2019';
            case 'x93': return '\u201C';
            case 'x94': return '\u201D';
            case 'x95': return '\u2022';
            case 'x96': return '\u2013';
            case 'x97': return '\u2014';
            case 'x98': return '\u02DC';
            case 'x99': return '\u2122';
            case 'x9a': return '\u0161';
            case 'x9b': return '\u203A';
            case 'x9c': return '\u0153';
            case 'x9d': return '\u009D';
            case 'x9e': return '\u017E';
            case 'x9f': return '\u0178';
            default:    if ($2) $0=toUTF16(parseInt($2,16));
                        return searchSwitch===false ? $0 : eval('"'+$0+'"');
          }
        }
      );
      return str;
    }
  ;

  _g.getCount = function() {
    if (cnt>=0) return;
    cnt=0;
    if (_g.inFile=='') {
      _g.tempFile=fso.GetSpecialFolder(_g.TemporaryFolder).path+'\\'+fso.GetTempName();
      _g.inFile=_g.tempFile;
      var output=fso.OpenTextFile(_g.tempFile,_g.ForWriting,true,_g.FileFormat);
      while (!input.AtEndOfStream) {
        output.WriteLine(input.ReadLine());
        cnt++
      }
      output.Close();
    } else {
      while (!input.AtEndOfStream) {
        input.SkipLine();
        cnt++;
      }
      input.Close();
    }
    input = _g.openInput(_g.inFile);
  }

  _g.loc=' opening input file';
  input = _g.openInput(_g.inFile);
  _g.loc='';

  if (env('/C')) _g.getCount();

  openOutput( _g.outFile, env('/APP'), _g.FileFormat );

  if (env('/XREG')) {
    _g.loc=' while loading /XREG library';
    _g.libs=env('/XREG').split('/');
    for (_g.i=0; _g.i<_g.libs.length; _g.i++) {
      _g.lib=fso.OpenTextFile(_g.libs[_g.i],_g.ForReading);
      if (!_g.lib.AtEndOfStream) eval(_g.lib.ReadAll());
      _g.lib.Close();
    }
    _g.loc=' while initializing /XREG library';
    _g.newRegExp = function(pattern,flags){ return new XRegExp(pattern,flags); }
    XRegExp.install('natives');
    _g.loc='';
    _g.XRegExp = true;
  } else {
    _g.newRegExp = function(pattern,flags){ return new RegExp(pattern,flags); }  
    _g.XRegExp = false;
  }  

  if (env('/JLIB')) {
    _g.loc=' while loading /JLIB code';
    _g.libs=env('/JLIB').split('/');
    for (_g.i=0; _g.i<_g.libs.length; _g.i++) {
      _g.lib=fso.OpenTextFile(_g.libs[_g.i],_g.ForReading);
      if (!_g.lib.AtEndOfStream) eval(_g.lib.ReadAll());
      _g.lib.Close();
    }
    _g.loc='';
  }

  _g.loc=' in /JBEG code';
  eval( _g.readVar( env('/JBEG'), env('/V'), '.JBEG' ) );
  _g.loc='';

  _g.defineObjectInternal=function(){
    _g.loc=' while defining '+_g.defineObjectObj;
    eval(_g.defineObjectStr);
    _g.loc='';
  }
  _g.defineObject=function(str,obj) {
    _g.defineObjectStr=str;
    _g.defineObjectObj=obj;
    _g.defineObjectInternal();
  }

  _g.main=function() {
    _g.rtn=1;
    var args=WScript.Arguments;
    var search =  env('/FindReplVar') ? _g.readVar( args.Item(0), env('/V')||env('/UTF'), '.FIND' ) : args.Item(0);
    var replace = env('/FindReplVar') ? _g.readVar( args.Item(1), env('/V')||env('/UTF'), '.REPL' ) : args.Item(1);
    var hiLite=env('/H')!='';
    var hiLiteOn=eval('"'+env('/HON')+'"');
    var hiLiteOff=eval('"'+env('/HOFF')+'"');
    var multi=env('/M')!='';
    var literal=env('/L')!='';
    var alterations=env('/A')!='';
    var srcVar=env('/S');
    var jexpr=env('/J')!='';
    var jmatch=env('/JMATCH')!='';
    var jmatchq=env('/JMATCHQ')!='';
    var jquick=env('/JQ')!='';
    var translate=env('/T');
    var filter = _g.readVar( env('/P'), env('/V'), '.P' );
    var keep, reject, context, krfile=false, krcount=false;
    var rtnVar=env('/RTN');
    if (reject=env('/R')) {
      if (!/^(\d+(:\d+)?|COUNT)(:FILE)?$/i.test(reject)) throw new Error(209, 'Invalid /R Context');
      context = reject.toUpperCase().split(':')
      krfile=(context[context.length-1]=='FILE');
      if (context[0]=='COUNT') {
        context[0]=context[1]=0;
        krcount=true;
      } else {
        context[0]=Number(context[0]);
        context[1]=(context.length==1 || context[1]=='FILE')?context[0]:Number(context[1]);
      }
    }
    if (keep=env('/K')) {
      //if (!/^\d+(:\d+)?(:FILE)?$/i.test(keep)) throw new Error(208, 'Invalid /K Context');
      if (!/^(\d+(:\d+)?|COUNT)(:FILE)?$/i.test(keep)) throw new Error(208, 'Invalid /K Context');
      context = keep.toUpperCase().split(':')
      krfile=(context[context.length-1]=='FILE');
      if (context[0]=='COUNT'){
        context[0]=context[1]=0;
        krcount=true;
      } else {
        context[0]=Number(context[0]);
        context[1]=(context.length==1 || context[1]=='FILE')?context[0]:Number(context[1]);
      }
    }
    var options = (keep||reject)?"":"g";
    _g.begLn = _g.readVar( env('/JBEGLN'), env('/V'), '.JBEGLN' );
    _g.endLn = _g.readVar( env('/JENDLN'), env('/V'), '.JENDLN' );

    _g.incBlock = new Array();
    _g.excBlock = new Array();
    _g.incBlock.dynamic = false;
    _g.excBlock.dynamic = false;
    var blockMatch,
        blockSearch = /(?:(-?\d+)|(?:\/((?:\\\/|[^/])+)\/|'((?:''|[^'])+)')([ibe]*)(\/)?)([+-]\d+)?(:(?:(-?\d+)|(\+\d+)|(?:\/((?:\\\/|[^/])+)\/|'((?:''|[^'])+)')([ibe]*))([+-]\d+)?)?(?:,(?=.)|$)?|(.+)/g;
    /*                    1            2                   3               4       5     6         7    8       9            1                   1               1        1                         1
                                                                                                                             0                   1               2        3                         4
        line or range begin
          spec
            1 = line number
            2 = regex
              4 = i|b|e flags
              5 = singleton
            3 = string
              4 = i|b|e flags
              5 = singleton
          6 = offset
        7 = range end
          spec
            8 = line number
            9 = offset from range begin
            10 = regex
              12 = i|b|e flags
            11 = string
              12 = i|b|e flags
          13 = offset
        14 = error
    */
    _g.Block = function(match) {
      if (match[14]) throw new Error(210, 'Invalid block syntax');
      this.offset=match[6]?Number(match[6]):0;
      if (match[1]) {
        this.type='lineNum';
        if ((this.spec=Number(match[1])) < 0) _g.getCount();
        this.lineNum=this.spec+this.offset+(this.spec<0?cnt+1:0);
      } else {
        this.type='regex';
        this.spec=_g.newRegExp( (match[4].search('b')+1?'^':'') + (
            match[2] ? decode(match[2],'input',false) :
            decode(match[3].replace(/''/g,"'"),'input',true).replace(/([.^$*+?()[{\\|])/g,"\\$1")
          ) + (match[4].search('e')+1?'$':''),
          match[4].search('i')+1?'i':''
        );
        this.spec.singleton=match[5]?true:false;
        this.lineNum=void 0;
        if (this.offset<0) throw new Error(211, 'Regex/String offset cannot be negative');
      }
      if (match[7]) {
        this.endOffset=Number(match[13]);
        if (match[8]) {
          this.endType='lineNum';
          if ((this.endSpec=Number(match[8])) < 0) _g.getCount();
          this.endLineNum=this.endSpec+this.endOffset+(this.endSpec<0?cnt+1:0);
        } else if (match[9]) {
          this.endType='offset';
          this.endSpec=Number(match[9]);
          this.endLineNum=this.lineNum+this.endSpec+this.endOffset;
        } else {
          this.endType='regex';
          this.endSpec=_g.newRegExp( (match[12].search('b')+1?'^':'') + (
              match[10] ? decode(match[10],'input',false) :
              decode(match[11].replace(/''/g,"'"),'input',true).replace(/([.^$*+?()[{\\|])/g,"\\$1")
            ) + (match[12].search('e')+1?'$':''),
            match[12].search('i')+1?'i':''
          );
          this.endLineNum=void 0;
          if (this.endOffset<-1) throw new Error(212, 'End-range Regex/String offset cannot be less than -1');
        }
      } else {
         this.endType=void 0;
         this.endSpec=void 0;
         this.endLineNum=this.lineNum;
      }
    }
    _g.setBlocks = function(blocks,str) {
      if (blocks.dynamic==true) {
        for (var i=0; i<blocks.length; i++) {
          var block = blocks[i];
          if (ln>block.endLineNum && block.type=='regex' && !block.spec.singleton)
            block.lineNum=block.endLineNum=void 0;
          if (!block.lineNum && block.spec.test(str)) {
            block.lineNum = ln+block.offset;
            if (!block.endLineNum) {
              if (!block.endType)
                block.endLineNum=block.lineNum;
              else if (block.endType=='offset')
                block.endLineNum=block.lineNum+block.endSpec+block.endOffset;
            }
          }
          if (!block.endLineNum && ln>block.lineNum && block.endSpec.test(str))
            block.endLineNum = ln+block.endOffset;
        }
      }
    }
    var str = _g.readVar( env('/INC'), env('/V'), '.INC' );
    while ( (blockMatch=blockSearch.exec(str)) !== null ) {
      _g.loc=' while parsing /INC block['+_g.incBlock.length+']';
      var block = new _g.Block(blockMatch);
      _g.incBlock.dynamic=(_g.incBlock.dynamic || block.type=='regex' || block.endType=='regex');
      _g.incBlock.push(block);
    }
    str = _g.readVar( env('/EXC'), env('/V'), '.EXC' );
    while ( (blockMatch=blockSearch.exec(str)) !== null ) {
      _g.loc=' while parsing /EXC block['+_g.excBlock.length+']';
      var block = new _g.Block(blockMatch);
      _g.excBlock.dynamic=(_g.excBlock.dynamic || block.type=='regex' || block.endType=='regex');
      _g.excBlock.push(new _g.Block(blockMatch));
    }
    _g.loc='';

    if (multi) options+='m';
    if (env('/MATCH')) {
      if (replace.toUpperCase()=='COUNT') {
        replace='$txt=false;counter++;';
        krcount=true;
      } else replace='$txt=$0';
    }
    _g.krcount=krcount;
    if (_g.begLn) _g.defineObject("_g.begLn=function($txt){_g.loc=' in /JBEGLN code';"+_g.begLn+";_g.loc='';return $txt;}",'/JBEGLN code');
    if (_g.endLn) _g.defineObject("_g.endLn=function($txt){_g.loc=' in /JENDLN code';"+_g.endLn+";_g.loc='';return $txt;}",'/JENDLN code');
    if (env('/I')) options+='i';

    var lnWidth=parseInt(env('/N'),10),
        offWidth=parseInt(env('/OFF'),10);
    if (lnWidth<0) lnWidth = 0;
    if (offWidth<0) offWidth = 0;
    _g.lnPrefix=lnWidth>0;
    _g.offPrefix=offWidth>0;
    var lnPad=lnWidth>0?'"'+(Array(lnWidth+1).join('0'))+'"':'',
        offPad=offWidth>0?'"'+(Array(offWidth+1).join('0'))+'"':'',
        xcnt=0, test,
        filterMatchOffset = offWidth>0&&filter!='' ? '+_g.filterMatchOffset' : '';

    function writeMatch(str,ln,lnPad,off,offPad) {
      return 'if('+str+'!==false){_g.rtn=0;output.Write('
           + (lnWidth==0 ? '' : 'lpad('+ln+','+lnPad+')+_g.delim+')
           + (offWidth==0 ? '' : 'lpad('+off+','+offPad+')+_g.delim+')
           + str+'+eol);}';
    }

    if (env('/VT')!='') while (_g.objExec.Status == 0) WScript.Sleep(50);

    if (translate=='none') {  // Normal
      if (hiLite && !krcount && (keep||reject)) options+='g';
      if (krfile) { // Load KEEP or REJECT File
        _g.loc=' loading '+(keep?'/K':'/R')+' Search file';
        var f = _g.openInput(search);
        search='';
        while (!f.AtEndOfStream) {
          str=f.ReadLine();
          if (env('/XSEQ')) str=decode(str,'input',literal);
          if (literal) str=str.replace(/([.^$*+?()[{\\|])/g,"\\$1");
          if (env('/B')) str="^"+str;
          if (env('/E')) str=str+"$";
          search+=(search?'|':'')+str;
        }
        f.Close();
      } else { // Load Normal Search
        if (env('/XSEQ')) {
          if (!jexpr) replace=decode(replace,'output');
          search=decode(search,'input',literal);
        }
        if (literal) {
          search=search.replace(/([.^$*+?()[{\\|])/g,"\\$1");
          if (!jexpr) replace=replace.replace(/\$/g,"$$$$");
        }
        if (env('/B')) search="^"+search;
        if (env('/E')) search=search+"$";
        _g.loc=' in Search regular expression';
      }
      search=_g.newRegExp(search,options);
      _g.loc='';
      if (keep||reject){
        jquick=jexpr=(krcount || hiLite || filter!='');
        replace = krcount ? '$txt=false;counter++;' : jquick ? '$txt=$0;if(_g.matchOffset==null)_g.matchOffset=$off'+filterMatchOffset+';' : '$&';
      }
      if (jexpr) {
        _g.loc=' in Search regular expression';
        test=_g.newRegExp('.|'+search,options);
        _g.loc='';
        'x'.replace(test,function(){xcnt=arguments.length-2; return '';});
        _g.replFunc='_g.replFunc=function($0';
        for (var i=1; i<xcnt; i++) _g.replFunc+=',$'+i;
        _g.replFunc+=',$off,$src){_g.loc=" in Replace code";';
        if (jquick||jmatchq) {
          _g.replFunc+='var $txt;'+replace+';';
          if (hiLite) _g.replFunc+='$txt="'+hiLiteOn+'"+$txt+"'+hiLiteOff+'";';
          _g.replFunc+=
            jmatch ? writeMatch('$txt','ln',lnPad,'$off'+filterMatchOffset,offPad)+'_g.loc="";return $0;}'
                   : '_g.loc="";return $txt;}';
        } else {
          var jstr = 'eval(_g.replace)';
          if (hiLite) jstr = '"'+hiLiteOn+'"+'+jstr+'+"'+hiLiteOff+'"';
          _g.replFunc+=
            jmatch ? writeMatch(jstr,'ln',lnPad,'$off'+filterMatchOffset,offPad)+'_g.loc="";return $0;}'
                   : '_g.rtn2='+jstr+';_g.loc="";return _g.rtn2;}';
        }
        _g.defineObject(_g.replFunc,'/J or /JMATCH code');
        _g.replace = replace;
      } else {
        _g.replace = hiLite ? hiLiteOn + replace + hiLiteOff : replace;
      }
    } else {                         // /T
      if (translate.toLowerCase()=='file') {
        var f
        _g.loc=' loading /T Search file';
        f = _g.openInput(search);
        search=[];
        while (!f.AtEndOfStream) search[search.length]=f.ReadLine();
        f.Close();
        _g.loc=' loading /T Replace file';
        f = _g.openInput(replace);
        replace=[];
        while (!f.AtEndOfStream) replace[replace.length]=f.ReadLine();
        f.Close();
        _g.loc='';
      } else {
        if (translate.length>1) throw new Error(203, 'Invalid /T delimiter');
        if (translate.length==0 && env('/XSEQ')) {
          search=decode(search,'input',literal);
          replace=decode(replace,'output');
        }
        search=search.split(translate);
        var replace=replace.split(translate);
      }
      if (search.length>99 && !_g.XRegExp) throw new Error(202, '/T expression count exceeds 99');
      if (search.length!=replace.length) throw new Error(201, 'Mismatched search and replace /T expressions');
      var j=1;
      if (!jexpr) jquick=1;
      if (jquick) _g.replace='';
      else _g.replace=[];
      for (var i=0; i<search.length; i++) {
        if (env('/XSEQ')) search[i]=decode(search[i],'input',literal);
        if (literal) {
          search[i]=search[i].replace(/([.^$*+?()[{\\|])/g,"\\$1");
        } else {
          _g.loc=' in Search regular expression';
          test=_g.newRegExp('.|'+search[i],options+(_g.XRegExp?env('/TFLAG'):''));
          _g.loc='';
          'x'.replace(test,function(){xcnt=arguments.length-3;return '';});
        }
        if (j+xcnt>99 && !_g.XRegExp) throw new Error(202, '/T expressions + captured expressions exceeds 99');
        if (env('/B')) search[i]="^"+search[i];
        if (env('/E')) search[i]=search[i]+"$";
        if (_g.XRegExp) search[i]="?<T"+i+">"+search[i];
        if (jquick|jmatchq) {
          if (!jexpr) {
            replace[i]="'" + (env('/XSEQ')==''?replace[i]:decode(replace[i],'output')).replace(/[\\']/g,"\\$&") + "'";
            replace[i]=replace[i].replace(/\n/g, "\\n");
            replace[i]=replace[i].replace(/\r/g, "\\r");
            if (!literal) {
              if (_g.XRegExp) {
                replace[i]='$txt='+replace[i].replace(
                  /\$([$&`0]|\\'|\{0\}|(\d)(\d)?|\{((\d)(\d)?)\}|\{([^}]+)\})/g,
                  function($0,$1,$2,$3,$4,$5,$6,$7){
                    return ($1=="$") ? "$":
                           ($1=="&" || $1=="0" || $1=="{0}") ? "'+$0+'":
                           ($1=="`") ? "'+$src.substr(0,$off)+'":
                           ($1=="\\'") ? "'+$src.substr($off+$0.length)+'":
                           ($7) ? "'+$0."+$7+"+'":
                           (Number($1)-j<=xcnt && Number($1)>=j) ? "'+"+$0+"+'":
                           (Number($2)-j<=xcnt && Number($2)>=j) ? "'+$"+$2+"+'"+$3:
                           (Number($4)-j<=xcnt && Number($4)>=j) ? "'+$"+$4+"+'":
                           (Number($5)-j<=xcnt && Number($5)>=j) ? "'+$"+$5+"+'"+$6:
                           $0;
                  }
                );
              } else {
                replace[i]='$txt='+replace[i].replace(
                  /\$([$&`0]|\\'|(\d)(\d)?)/g,
                  function($0,$1,$2,$3){
                    return ($1=="$") ? "$":
                           ($1=="&") ? "'+$0+'":
                           ($1=="`") ? "'+$src.substr(0,$off)+'":
                           ($1=="\\'") ? "'+$src.substr($off+$0.length)+'":
                           (Number($1)-j<=xcnt && Number($1)>=j) ? "'+"+$0+"+'":
                           (Number($2)-j<=xcnt && Number($2)>=j) ? "'+$"+$2+"+'"+$3:
                           $0;
                  }
                );
              }
            } else replace[i]='$txt='+replace[i];
          }
          _g.replace+='if(arguments['+j+']!==undefined){'+replace[i]+';}';
        } else {
          _g.replace[j]=replace[i];
        }
        j+=xcnt+1;
      }
      search='('+search.join(')|(')+')';
      _g.loc=' in Search regular expression';
      search=_g.newRegExp( search, options+(_g.XRegExp?env('/TFLAG'):'') );
      _g.loc='';
      _g.replFunc='_g.replFunc=function($0';
      for (var i=1; i<j; i++) _g.replFunc+=',$'+i;
      _g.replFunc+=',$off,$src){_g.loc=" in Replace code";';
      if (jquick||jmatchq) {
        _g.replFunc+='var $txt;'+_g.replace;
        if (hiLite) _g.replFunc+='$txt="'+hiLiteOn+'"+$txt+"'+hiLiteOff+'";';
        _g.replFunc+=(
           jmatch ? writeMatch('$txt','ln',lnPad,'$off'+filterMatchOffset,offPad)+'_g.loc="";return $0;}'
                  : '_g.loc="";return $txt;}' );
      } else {
        var jstr = 'eval(_g.replace[_g.i])';
        if (hiLite) jstr = '"'+hiLiteOn+'"+'+jstr+'+"'+hiLiteOff+'"';
        _g.replFunc+='for(_g.i=1;_g.i<arguments.length-2;_g.i++)if(arguments[_g.i]!==undefined)'+ (
           jmatch ? writeMatch(jstr,'ln',lnPad,'$off'+filterMatchOffset,offPad)+'_g.loc="";return $0;}'
                  : '{_g.rtn2='+jstr+';_g.loc="";return _g.rtn2;}}' );
      }
      _g.defineObject(_g.replFunc,'/J or /JMATCH code');
      jexpr=true;
    }

    var str1, str2;
    var repl=jexpr?_g.replFunc:_g.replace;

    if (filter!='') {
      if (env('/PREPL')) {
        _g.defineObject(
          '_g.filterReplace=function(){ return '
            + env('/PREPL').replace(/\$(\d+)/g,'arguments[$1]')
            .replace(/{([^}]*)}/g,'($1).replace(_g.search,_g.filterReplace2)')
            +';}'
          ,'/PREPL'
        );
      } else if (offWidth>0) {
        _g.filterReplace=function(str) {
          _g.filterMatchOffset = arguments[arguments.length-2];
          return str.replace(_g.search,_g.filterReplace2);
        }
      } else {
        _g.filterReplace=function(str) {
          return str.replace(_g.search,_g.filterReplace2);
        }
      }
      _g.loc=' in /P FilterRegex';
      filter = _g.newRegExp( decode(filter,'input',false), env('/PFLAG').toLowerCase()+(env('/M')?'m':'') );
      _g.loc='';
      _g.search=search;
      search=filter;
      _g.filterReplace2=repl;
      repl=_g.filterReplace;
    }

    if (srcVar) {
      str1=_g.readVar( srcVar, srcVar, '.S' );
      str2=str1.replace(search,repl);
      if (str1!=str2) _g.rtn=0;
      if (!jmatch && (!alterations || str1!=str2)) output.Write(str2+(multi?'':eol));
    } else if (multi){
      var buf=1024;
      str1="";
      while (!input.AtEndOfStream) {
        str1+=input.Read(buf);
        buf*=2;
      }
      str2=str1.replace(search,repl);
      if (!jmatch) output.Write(str2);
      if (str1!=str2) _g.rtn=0;
    } else if (keep||reject){
      var match, arr, filterResult, post, pre=new Array();
      var cmd='while(!input.AtEndOfStream&&!quit){match=reject;str1=input.ReadLine();';
      if ( _g.incBlock.length || _g.excBlock.length || lnWidth
           || _g.begLn || _g.endLn || env(env('/V')?env('/JEND'):'/JEND')
         ) cmd+='ln++;';
      if (_g.incBlock.dynamic) cmd+='_g.setBlocks(_g.incBlock,str1);';
      if (_g.excBlock.dynamic) cmd+='_g.setBlocks(_g.excBlock,str1);';
      if (_g.begLn) cmd+='str1=_g.begLn(str1);';
      if (jquick) cmd+='_g.matchOffset=null;';
      str1='';str2='if(';
      if (_g.incBlock.length) {str1+=str2+'inc()';str2='&&';}
      if (_g.excBlock.length) {str1+=str2+'!exc()';str2='&&';}
      if (_g.begLn||_g.endLn||jexpr||env(env('/V')?env('/JBEG'):'/JBEG')) {str1+=str2+'!skip';}
      if (str1) cmd+=str1+')';
      if (jquick) {
        cmd+='{str1=str1.replace(search,repl);match=_g.matchOffset!=null?!reject:reject;}';
      } else {
        cmd+='if ((arr=search.exec(str1))!==null){match=!reject;_g.matchOffset=arr.index}';
      }
      if (_g.endLn) cmd += 'str1=_g.endLn(str1);';
      cmd+='if (str1!==false && match) {_g.rtn=0;';
      if (context[0]) cmd+='while(pre.length){str2=pre.pop();'+writeMatch('str2','ln-pre.length-1',lnPad,'""',offWidth)+'}';
      cmd+=writeMatch('str1','ln',lnPad,'_g.matchOffset',offPad);
      if (context[1]) cmd+='post=context[1];}else if(post-->0){'+writeMatch('str1','ln',lnPad,'""',offWidth);
      if (context[0]) cmd+='}else{pre.unshift(str1);if(pre.length>context[0])pre.pop();';
      cmd+='}}';
      if (env('/DBUG')) output.WriteLine(cmd);
      else eval(cmd);
    } else {
      var cmd='while(!input.AtEndOfStream&&!quit){str2=str1=input.ReadLine();';
      if ( _g.incBlock.length || _g.excBlock.length || lnWidth
           || _g.begLn || _g.endLn|| jexpr || env(env('/V')?env('/JEND'):'/JEND')
         ) cmd+='ln++;';
      if (_g.incBlock.dynamic) cmd+='_g.setBlocks(_g.incBlock,str2);';
      if (_g.excBlock.dynamic) cmd+='_g.setBlocks(_g.excBlock,str2);';
      if (_g.begLn) cmd+='str2=_g.begLn(str2);';
      str1='';str2='if(';
      if (_g.incBlock.length) {str1+=str2+'inc()';str2='&&';}
      if (_g.excBlock.length) {str1+=str2+'!exc()';str2='&&';}
      if (_g.begLn||_g.endLn||jexpr||env(env('/V')?env('/JBEG'):'/JBEG')) {str1+=str2+'!skip';}
      if (str1) cmd+=str1+')';
      cmd+='str2=str2.replace(search,repl);';
      if (_g.endLn) cmd+='str2=_g.endLn(str2);';
      if (!jmatch) {
        str1='';str2='if(';
        if (_g.endLn||jexpr) {str1+=str2+'str2!==false';str2='&&';}
        if (alterations) {str1+=str2+'str1!=str2';}
        if (str1) cmd+=str1+')';
        cmd+='output.Write('+(lnWidth>0?'lpad(ln,'+lnPad+')+_g.delim+':'')+'str2+eol);';
        cmd+='if (str1!=str2) _g.rtn=0;';
      }
      cmd+='}'
      if (env('/DBUG')) output.WriteLine(cmd);
      else eval(cmd);
    }
  }

  _g.main();

  _g.loc=' in /JEND code';
  eval( _g.readVar( env('/JEND'), env('/V'), '.JEND' ) );
  _g.loc='';
  if (_g.krcount) output.WriteLine(counter);
  if (_g.inFile) input.Close();
  if (_g.outFile) output.Close();
  if (_g.outFileA[0]=='-') {
    fso.GetFile(_g.inFileA[0]).Delete();
    fso.GetFile(_g.inFileA[0]+'.new').Move(_g.inFileA[0]);
  }
  if (_g.tempFile) fso.GetFile(_g.tempFile).Delete();


  if (env('/RTN')) {
    _g.rtnVar = function() {
      var val, str1, str2, buf=1024, arr, n;
      input=_g.openInput(_g.outFile)
      val='';
      while (!input.AtEndOfStream) {
        val+=input.Read(buf);
        buf*=2;
      }
      input.Close();
      if (env('/RTN_LINE')&&(n=parseInt(env('/RTN_LINE')))) {
        arr=val.split(/\r?\n/);
        n = n>0 ? n-1 : arr.length+n;
        val = typeof arr[n]==='undefined' ? '' : arr[n];
      } else if ((env('/MATCH')||env('/JMATCH')||env('/JMATCHQ'))&&eol&&val.slice(-eol.length)===eol){
        val=val.slice(0,-eol.length);
      }
      output=null;
      openOutput(_g.outFile, "", 0 );
      str1='x'+val.replace(/%/g,'%3').replace(/\n/mg,'%~1').replace(/\r/mg,'%2').replace(/"/g,'%4');
      str2=str1.replace(/[!^]/g,'^$&');
      if (str2.length + env('/RTN').length > 8181) throw new Error(213, 'Result too long to fit within variable');
      if (str2.indexOf('\x00')>=0) throw new Error(214, 'Null bytes (0x00) cannot be returned in a variable');
      output.WriteLine(str1);
      output.WriteLine(str2);
      output.Close();
    }
    _g.rtnVar();
  }

  WScript.Quit(_g.rtn);
} catch(e) {
  WScript.Stderr.WriteLine("JScript runtime error"+_g.loc+": "+e.message);
  WScript.Quit(3);
}

function lpad( val, arg2, arg3 ) {
  var rtn=val.toString(), len, pad, cnt;
  if (typeof arg2 === "string") {
    pad = arg2;
    len = arg2.length;
  } else {
    len = arg2;
    pad = arg3 ? arg3 : '                                                  ';
    while (pad.length < len) pad+=pad;
  }
  return (rtn.length<len) ? pad.slice(0,len-rtn.length)+rtn : rtn;
}

function rpad( val, arg2, arg3 ) {
  var rtn=val.toString(), len, pad, cnt;
  if (typeof arg2 === "string") {
    pad = arg2;
    len = arg2.length;
  } else {
    len = arg2;
    pad = typeof arg3 === "string" ? arg3 : '                                                  ';
    while (pad.length < len) pad+=pad;
  }
  return (rtn.length<pad.length) ? rtn+pad.slice(rtn.length-len) : rtn;
}

function inc(n) {
  for (var i=n?n:0, end=n?n+1:_g.incBlock.length; i<end; i++) {
    var block = _g.incBlock[i];
    if (ln>=block.lineNum && ln<=(block.endLineNum?block.endLineNum:ln)) return true;
  }
  return (_g.incBlock.length==0);
}

function exc(n) {
  for (var i=n?n:0, end=n?n+1:_g.excBlock.length; i<end; i++) {
    var block = _g.excBlock[i];
    if (ln>=block.lineNum && ln<=(block.endLineNum?block.endLineNum:ln)) return true;
  }
  return false;
}

function openOutput( fileName, append, utf ) {
  _g.loc=' opening output file';
  if (output && output!==stdout) output.Close();
  if (fileName) {
    var file = fileName.split('|');
    if (file[1]) output=new _g.ADOStream( file[0], append?_g.ForAppending:_g.ForWriting, file[1], file[2] );
    else output=fso.OpenTextFile( fileName, append?_g.ForAppending:_g.ForWriting, true, utf?-1:0 );
  }
  else output=stdout;
  _g.loc='';
}
