anchor.diff:  :#                  Avoid getting the PID if we have it already.              *
   :#   2016-11-07 JFL Updated the 10/19 errorlevel fix to work for DO and EXEC. *
   :#   2016-11-08 JFL Change back to using variable MAKE, required by nmake<=7.1*
  +:#   2016-12-13 JFL Any goal that begins with "list_" and that contains no .  *
  +:#		    or \ is assumed to be a pseudo-target not to be logged.   *
  +:#		    Added options -q and -Q to set the output capture manually.
  +:#   2016-12-16 JFL Updated the batch library framework.		      *
   :#                                                                            *
   :#          Copyright 2016 Hewlett Packard Enterprise Development LP         *
   :# Licensed under the Apache 2.0 license  www.apache.org/licenses/LICENSE-2.0 *
   :#*****************************************************************************
   
   setlocal EnableExtensions EnableDelayedExpansion
  -set "VERSION=2016-11-08"
  -set "SCRIPT=%~nx0"
  -set "SPATH=%~dp0" & set "SPATH=!SPATH:~0,-1!"
  -set "ARG0=%~f0"
  -set  ARGS=%*
  -
  -:# FOREACHLINE macro. (Change the delimiter to none to catch the whole lines.)
  +set "VERSION=2016-12-16"
  +set "SCRIPT=%~nx0"				&:# Script name
  +set "SPATH=%~dp0" & set "SPATH=!SPATH:~0,-1!"	&:# Script path, without the trailing \
  +set  "ARG0=%~f0"				&:# Script full pathname
  +set ^"ARGS=%*^"					&:# Argument line
  +
  +:# Initialize the most commonly used library components.
  +call :Library.Init
  +
  +:# Go process command-line arguments
  +goto Main
  +
  +:#----------------------------------------------------------------------------#
  +:#                                                                            #
  +:#  Function	    Library.Init					      #
  +:#                                                                            #
  +:#  Description     Initialize the most commonly used library components      #
  +:#                                                                            #
  +:#----------------------------------------------------------------------------#
  +
  +:Library.Init
  +:# Initialize this library modules definitions.
  +:# Each one depends on the preceding ones, so if you need one, you need all the preceding ones as well.
  +call :Call.Init			&:# Function calls and argument extraction
  +call :Macro.Init		&:# Inline macros generation
  +call :Debug.Init		&:# Debug routines
  +call :Exec.Init			&:# Conditional execution routines
  +
  +:# FOREACHLINE macro. (Changes the delimiter to none to catch the whole lines.)
   set FOREACHLINE=for /f "delims="
   
  -set "POPARG=call :PopArg"
  -call :Macro.Init
  -call :Debug.Init
  -call :Exec.Init
  -goto Main
  +:# HOME variable. For analogy with Unix systems.
  +if not defined HOME set "HOME=%HOMEDRIVE%%HOMEPATH%"
  +
  +goto :eof
   
   :#----------------------------------------------------------------------------#
   :#                                                                            #
  -:#  Function        PopArg                                                    #
  -:#                                                                            #
  -:#  Description     Pop the first arguments from %ARGS% into %ARG%            #
  -:#                                                                            #
  -:#  Arguments       %ARGS%	    Command line arguments                    #
  -:#                                                                            #
  -:#  Returns         %ARG%           The unquoted argument                     #
  +:#  Module	    Call						      #
  +:#                                                                            #
  +:#  Description     Manage function calls and argument extraction             #
  +:#                                                                            #
  +:#  Functions	    PopArg          Pop the first argument from %ARGS% into   #
  +:#				     %ARG% and %"ARG"%			      #
  +:#		    PopSimpleArg    Simpler and faster version, incompatible  #
  +:#                                   with ! or ^ characters in ARG values.    #
  +:#		    Prep2ExpandVars Prepare variables to return from the      #
  +:#		 		    local scope (with expansion on or off)    #
  +:#				    to a parent scope with expansion on.      #
  +:#		    PrepArgVars     Prepare variables containing pathnames    #
  +:#				    that will be passed as arguments.	      #
  +:#                                                                            #
  +:#  Macros	    %POPARG%        Pop one argument using :PopArg            #
  +:#                  %POPSARG%       Pop one argument using :PopSimpleArg      #
  +:#                  %LCALL%         Call a routine in this library, either    #
  +:#                                   locally, or from an outside script.      #
  +:#                  %XCALL%         Call an outside script routine, from      #
  +:#                                   another instance of that outside script. #
  +:#                  %XCALL@%        Idem, but with all args stored in one var.#
  +:#                                                                            #
  +:#  Variables	    %ARG%           The unquoted argument                     #
   :#                  %"ARG"%         The actual argument, possibly quoted      #
  -:#                                                                            #
  -:#  Notes 	    Works around the defect of the shift command, which       #
  -:#                  pops the first argument from the %* list, but does not    #
  -:#                  remove it from %*.                                        #
  -:#                                                                            #
  -:#                  Use an inner call to make sure the argument parsing is    #
  +:#                  %ARGS%	    Remaining command line arguments          #
  +:#                                                                            #
  +:#                  %CR%            An ASCII Carrier Return character '\x0D'  #
  +:#                  %LF%            An ASCII Line Feed character '\x0A'       #
  +:#                  %BS%            An ASCII Back Space character '\x08'      #
  +:#                  %FF%            An ASCII Form Feed character '\x0C'       #
  +:#                                                                            #
  +:#  Notes 	    PopArg works around the defect of the shift command,      #
  +:#                  which pops the first argument from the %* list, but does  #
  +:#                  not remove it from %*.                                    #
  +:#                  Also works around another defect with tricky characters   #
  +:#                  like ! or ^ being lost when variable expansion is on.     #
  +:#                                                                            #
  +:#                  Important: The performance of this routine is much better #
  +:#                  when invoked with variable expansion disabled. This is    #
  +:#                  due to the complex processing done to avoid issues with   #
  +:#                  tricky characters like ! or ^ when expansion is enabled.  #
  +:#                  If you're sure that NONE of the arguments contain such    #
  +:#                  tricky characters, then call :PopSimpleArg.               #
  +:#                                                                            #
  +:#                  Uses an inner call to make sure the argument parsing is   #
   :#                  done by the actual cmd.exe parser. This guaranties that   #
   :#                  arguments are split exactly as shift would have done.     #
   :#                                                                            #
   :#                  But call itself has a quirk, which requires a convoluted  #
   :#                  workaround to process the /? argument.                    #
  +:#                                                                            #
  +:#                  Known limitation: After using :PopArg, all consecutive    #
  +:#                  argument separators in %ARGS% are replaced by one space.  #
  +:#                  For example: "A==B" becomes "A B"                         #
  +:#                  This does not change the result of subsequent calls to    #
  +:#                  :PopArg, but this prevents from using the tail itself as  #
  +:#                  an argument. => Do not use :PopArg to get :Exec args!     #
   :#                                                                            #
   :#                  To do: Detect if the last arg has mismatched quotes, and  #
   :#                  if it does, append one.                                   #
   :#                  Right now such mismatched quotes will cause an error here.#
  -:#                  It is easily feasible to work around this, but this is    #
  -:#                  useless as passing back an invalid argument like this     #
  -:#                  will only cause more errors further down.                 #
  +:#                  Do not work around this error to only pass back the bad   #
  +:#                  argument, as this will only cause more errors further down#
   :#                                                                            #
   :#  History                                                                   #
   :#   2015-04-03 JFL Bug fix: Quoted args with an & inside failed to be poped. #
   :#   2015-07-06 JFL Bug fix: Call quirk prevented inner call from popping /?. #
  +:#   2016-11-18 JFL Fixed popping arguments containing % characters.          #
  +:#   2016-11-21 JFL Fixed popping quoted arguments containing &|<> characters.#
  +:#   2016-11-22 JFL Fixed popping arguments containing ^ characters.          #
  +:#   2016-11-24 JFL Updated %POPARG% to work with trick characters ! and ^ in #
  +:#                  delayed expansion mode. The old and faster version is now #
  +:#		    called %POPSARG%.                                         #
  +:#		    Added routine :Prep2ExpandVars allowing to pass any       #
  +:#		    tricky string across call or endlocal barriers.           #
  +:#   2016-12-01 JFL Added a %FF% Form Feed character variable.                #
   :#                                                                            #
   :#----------------------------------------------------------------------------#
   
  +call :Call.Init
  +goto Call.end
  +
  +:Call.Init
  +if not defined LCALL set "LCALL=call"	&:# Macro to call functions in this library
  +set "POPARG=%LCALL% :PopArg"
  +set "POPSARG=%LCALL% :PopSimpleArg"
  +
  +:# Mechanism for calling subroutines in a second external instance of the top script.
  +set ^"XCALL=call "!ARG0!" -call^"	&:# This is the top script's (or this lib's if called directly) ARG0
  +set ^"XCALL@=!XCALL! :CallVar^"		&:# Indirect call, with the label and arguments in a variable
  +
  +:# Define a LF variable containing a Line Feed ('\x0A')
  +set LF=^
  +%# The two blank lines here are necessary. #%
  +%# The two blank lines here are necessary. #%
  +
  +:# Define a CR variable containing a Carriage Return ('\x0D')
  +for /f %%a in ('copy /Z %COMSPEC% nul') do set "CR=%%a"
  +
  +:# Define a BS variable containing a BackSpace ('\x08')
  +:# Use prompt to store a  backspace+space+backspace into a DEL variable.
  +for /F "tokens=1 delims=#" %%a in ('"prompt #$H# & echo on & for %%b in (1) do rem"') do set "DEL=%%a"
  +:# Then extract the first backspace
  +set "BS=%DEL:~0,1%"
  +
  +:# Define a FF variable containing a Form Feed ('\x0C')
  +for /f %%A in ('cls') do set "FF=%%A"
  +
  +:# Define variables for problematic characters, that cause parsing issues.
  +:# Use the ASCII control character name, or the html entity name.
  +:# Warning: The excl and hat characters need different quoting depending on context.
  +set  "DEBUG.percnt=%%"	&:# One percent sign
  +set  "DEBUG.excl=^!"	&:# One exclamation mark
  +set  "DEBUG.hat=^"	&:# One caret, aka. circumflex accent, or hat sign
  +set ^"DEBUG.quot=""	&:# One double quote
  +set  "DEBUG.apos='"	&:# One apostrophe
  +set  "DEBUG.amp=&"	&:# One ampersand
  +set  "DEBUG.vert=|"	&:# One vertical bar
  +set  "DEBUG.gt=>"	&:# One greater than sign
  +set  "DEBUG.lt=<"	&:# One less than sign
  +set  "DEBUG.lpar=("	&:# One left parenthesis
  +set  "DEBUG.rpar=)"	&:# One right parenthesis
  +set  "DEBUG.lbrack=["	&:# One left bracket
  +set  "DEBUG.rbrack=]"	&:# One right bracket
  +set  "DEBUG.sp= "	&:# One space
  +set  "DEBUG.tab=	"	&:# One tabulation
  +set  "DEBUG.quest=?"	&:# One question mark
  +set  "DEBUG.ast=*"	&:# One asterisk
  +set  "DEBUG.cr=!CR!"	&:# One carrier return
  +set  "DEBUG.lf=!LF!"	&:# One line feed
  +set  "DEBUG.bs=!BS!"	&:# One backspace
  +set  "DEBUG.ff=!FF!"	&:# One form feed
  +goto :eof
  +
   :PopArg
  +if "!!"=="" goto :PopArg.Eon
  +:PopArg.Eoff
  +:PopSimpleArg :# Will corrupt result if expansion is on and ARG contains ^ or ! characters.
   :# Gotcha: The call parser first scans its command line for an unquoted /?.
   :# If it finds one anywhere on the command line, then it ignores the target label and displays call help.
   :# To work around that, we initialize %ARG% and %"ARG"% with an impossible combination of values.
   set "ARG=Yes"
   set ""ARG"=No"
  -call :PopArg.Helper %ARGS% >NUL 2>NUL &:# Output redirections ensure the call help is not actually output.
  +set "PopArg.ARGS="
  +if defined ARGS (
  +  setlocal EnableDelayedExpansion
  +  for /f "delims=" %%a in ("!ARGS:%%=%%%%!") do endlocal & set ^"PopArg.ARGS=%%a^"
  +)
  +call :PopArg.Helper %PopArg.ARGS% >NUL 2>NUL &:# Output redirections ensure the call help is not actually output.
   :# Finding that impossible combination now is proof that the call was not executed.
   :# In this case, try again with the /? quoted, to prevent the call parser from processing it.
   :# Note that we can not systematically do this /? enquoting, else it's "/?" that would break the call.
  -if "%ARG%"=="Yes" if [%"ARG"%]==[No] call :PopArg.Helper %ARGS:/?="/?"% 
  +if "%ARG%"=="Yes" if [%"ARG"%]==[No] call :PopArg.Helper %PopArg.ARGS:/?="/?"%
  +set "PopArg.ARGS="
   goto :eof
   :PopArg.Helper
  -set "ARG=%~1"	&:# Remove quotes from the argument
  -set ""ARG"=%1"	&:# The same with quotes, if any, should we need them
  +set "ARG=%~1"		&:# Remove quotes from the argument
  +set ^""ARG"=%1^"	&:# The same with quotes, if any, should we need them
  +if defined ARG set "ARG=%ARG:^^=^%"
  +if defined "ARG" set ^""ARG"=%"ARG":^^=^%^"
   :# Rebuild the tail of the argument line, as shift does not do it
   :# Never quote the set ARGS command, else some complex quoted strings break
   set ARGS=%2
   :PopArg.GetNext
   shift
  +if defined ARGS set ^"ARGS=%ARGS:^^=^%^"
   if [%2]==[] goto :eof
   :# Leave quotes in the tail of the argument line
   set ARGS=%ARGS% %2
   goto :PopArg.GetNext
   
  +:PopArg.Eon
  +setlocal DisableDelayedExpansion
  +call :PopArg
  +call :Prep2ExpandVars ARG ^""ARG"^" ARGS
  +setlocal EnableDelayedExpansion
  +for /f %%a in ("-!ARG!") do for /f %%b in ("-!"ARG"!") do for /f %%c in ("-!ARGS!") do (
  +  endlocal
  +  endlocal
  +  set "ARG=%%a"
  +  set "ARG=!ARG:~1!"
  +  set ^""ARG"=%%b^"
  +  set ^""ARG"=!"ARG":~1!^"
  +  set ^"ARGS=%%c^"
  +  set "ARGS=!ARGS:~1!"
  +)
  +goto :eof
  +
  +:# Prepare variables to return from the local scope (with expansion on or off) to a parent scope with expansion on
  +:Prep2ExpandVars VAR [VAR ...]
  +if "!!"=="" goto :Prep2ExpandVars.Eon
  +:Prep2ExpandVars.Eoff	:# The local scope has expansion off
  +setlocal EnableDelayedExpansion
  +set "VALUE=!%~1!"
  +call :Prep2ExpandVars.Eon VALUE
  +endlocal & set "%~1=%VALUE%"
  +if not [%2]==[] shift & goto :Prep2ExpandVars.Eoff
  +goto :eof
  +
  +:# Prepare variables, assuming the local scope itself has expansion on
  +:Prep2ExpandVars.Eon VAR [VAR ...]
  +if defined %1 (
  +  for %%e in (sp tab cr lf quot amp vert lt gt hat percnt) do ( :# Encode named character entities
  +    for %%c in ("!DEBUG.%%e!") do (
  +      set "%~1=!%~1:%%~c= DEBUG.%%e !"
  +    )
  +  )
  +  call set "%~1=%%%~1:^!= DEBUG.excl %%" 	& rem :# Encode exclamation points
  +  call set "%~1=%%%~1: =^!%%"			& rem :# Encode final expandable entities
  +)
  +if not [%2]==[] shift & goto :Prep2ExpandVars.Eon
  +goto :eof
  +
  +:# Prepare variables containing pathnames that will be passed as "arguments"
  +:PrepArgVars
  +set "%~1=!%~1:%%=%%%%!"				&:# Escape percent signs
  +if not [%2]==[] shift & goto :PrepArgVars
  +goto :eof
  +
  +:# Indirect call, with the label and arguments in a variable
  +:CallVar CMDVAR
  +call !%1:%%=%%%%!
  +exit /b
  +
  +:Call.end
  +
   :#----------------------------------------------------------------------------#
   :#                                                                            #
  -:#  Function        Inline macro functions                                    #
  +:#  Module          Macro						      #
   :#                                                                            #
   :#  Description     Tools for defining inline functions,                      #
   :#                  also known as macros by analogy with Unix shells macros   #
  
positive.code: goto :eof
  
  :Echo.Verbose
  %IF_VERBOSE% goto :Echo
  goto :Echo.Log
  
  :Echo.Debug
  %IF_DEBUG% goto :Echo
  goto :Echo.Log
  
  :Echo.Eval2DebugOut %*=String with variables that need to be evaluated first
  :# Must be called with delayed expansion on, so that !variables! within %* get expanded
  :Echo.2DebugOut	%*=String to output to the DEBUGOUT stream
  %>DEBUGOUT% echo.%INDENT%%*
  goto :eof
  
  :Echo.Eval2LogFile %*=String with variables that need to be evaluated first
  :# Must be called with delayed expansion on, so that !variables! within %* get expanded
  :Echo.2LogFile %*=String to output to the LOGFILE
  %>>LOGFILE% echo.%INDENT%%*
  goto :eof
  
  :# Echo and log variable values, indented at the same level as the debug output.
  
negative.code: if exist echo >&2 echo WARNING: The file "echo" in the current directory will cause problems. Please delete it and retry.
  :# Inherited variables from the caller: DEBUG, VERBOSE, INDENT, >DEBUGOUT
  :# Initialize other debug variables
  set "ECHO=%LCALL% :Echo"
  set "ECHOVARS=%LCALL% :EchoVars"
  :# The FUNCTION, UPVAR, and RETURN macros should work with delayed expansion on or off
  set MACRO.GETEXP=(if "%'!2%%'!2%"=="" (set MACRO.EXP=EnableDelayedExpansion) else set MACRO.EXP=DisableDelayedExpansion)
  set UPVAR=call set DEBUG.RETVARS=%%DEBUG.RETVARS%%
  