Functions to find "base" function and their aliases ( :GetBaseFunction :IsBaseFunction :IsFunctionAlias ... )

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
shodan
Posts: 89
Joined: 01 May 2023 01:49

Functions to find "base" function and their aliases ( :GetBaseFunction :IsBaseFunction :IsFunctionAlias ... )

#1 Post by shodan » 13 May 2024 18:37

Hi,
functions.zip
(24.62 KiB) Downloaded 534 times
I made simple to use helper function, to determine if a function is a "base" function or an alias.
Also to obtain a list of alias related to a specific base function.

First, what is a function

Code: Select all

:Hello
echo Hello,world
GoTo :EOF
Also, I have what I call the preamble and the post-script. This is text before the function label, and after the last function exit and to the next empty row which serves as the delimiter. Again, hello world as an example

Code: Select all

::Usage Call :Hello
::Prints Hello,world
::This is the preamble text
:Hello
echo Hello,world
GoTo :EOF
REM this is the post-script text
REM The text from the function label and the last exit, I call the function "body" text
Now, what is an alias ?
An alias if a function label, which is placed before the "base" function label and DOES NOT have an exit (continues into the base function without a goto or call ). Here you will probably set a mode switch to superficially change the internal logic of the function.

Here is an example alias for hello world

Code: Select all

::Usage Call :Hello
::Usage Call :Allo
:Allo
set _Hello_mode=french
:Hello
if not defined set _Hello_mode ( echo Hello,world )  else ( if "[%_Hello_mode%]" EQU "[french]" echo Salut,monde )
GoTo :EOF
Now my new functions

Code: Select all

::Usage Call :GetBasefunction BatchFile FunctionName ReturnVariable 
::Usage Call :GetFunctionAliases batchfile functionname returnvariable
::Usage Call IsBaseFunction BatchFile FunctionName optional ReturnVariable && echo Function is base function || echo function is not base function
::Usage Call IsFunctionAlias BatchFile FunctionName optional ReturnVariable && echo Function is alias || echo function is not alias


Relating to the above example you would use it as follows

GetBasefunction returns the name of the base function in the return variable, and the line number of the base function label in errorlevel

Code: Select all

Call :GetBasefunction %~dpnx0 Allo ReturnVariable
echo %errorlevel%
echo %ReturnVariable%
75
Hello
GetFunctionAliases, returns a list of aliases in the ReturnVariable for the provided base function name and errorleve contains the count of aliases returned

Code: Select all

Call :GetFunctionAliases %~dpnx0 hello returnvariable
echo %errorleve%
echo %returnvariable%
1
Allo
IsBaseFunction and IsFunctionAlias, will return true (0) or false (1) in errorleve, depending on whether the function is a base function or not
Optionally, you can put in a returnvariable and get "true" or "false" in that variable

Code: Select all

Call IsBaseFunction %~dpnx0 hello && echo Function is base function || echo function is not base function
Function is base function
Call IsBaseFunction %~dpnx0 allo && echo Function is base function || echo function is not base function
function is not base function
Call IsFunctionAlias %~dpnx0 hello && echo Function is alias || echo function is not alias
function is not alias
Call IsFunctionAlias %~dpnx0 allo returnvariable && echo Function is alias || echo function is not alias
Function is alias
echo %returnvariable%
true

In the provided files you will find a functionswitcher, which allows you to call the function, based on the name of the batch file.
"bfw" is a special name the batch file could have, in that case, it will call the function named in the first argument as well as shift the arguments

Code: Select all

@echo off
:setup
:main

for %%a in ( %* ) do ( for %%b in ( /h /? -h -? help --help ) do ( if "[%%a]" EQU "[%%b]" ( Call :%~n0-help & exit /b 1 ) ) )
for %%a in ( %* ) do ( if "[%%a]" EQU "[demo]" ( Call :%~n0-demo & exit /b 1 ) ) 
if "[%~1]" EQU "[]" ( echo %~n0 needs at least one argument & exit /b 1 )
if "[%~n0]" EQU "[bfw]" ( Call :ShiftedArgumentCaller %* ) else ( Call :%~n0 %* )

:end
exit /b %errorlevel%

The end result is you can have multiple copies of the same file, create symlinks to it with different name. This is a lot like the linux busybox utility, which performs many tasks in one executable.

The zip file, cannot have symlinks, so it has multiple copies of the same file with different names.
In practical terms, this means you can use it as follows

Testing IsBaseFunction and IsFunctionalias

Code: Select all

call IsBaseFunction.bat IsBaseFunction.bat IsBaseFunction && echo It is base function || echo it is not base function
It is base function

call IsBaseFunction.bat IsBaseFunction.bat isfunctionalias && echo It is base function || echo it is not base function
it is not base function

call IsFunctionalias.bat IsBaseFunction.bat isbasefunction && echo It is function alias || echo it is not function alias
it is not function alias

call IsFunctionalias.bat IsBaseFunction.bat isfunctionalias && echo It is function alias || echo it is not function alias
It is function alias
This demo function, will go through each functions and determine if it is a base function or an alias

Code: Select all

IsBaseFunction-demo.bat IsBaseFunction.bat
Function ShiftedArgumentCaller is a base function.
Function Hello is a base function.
Function PrintWithoutNewline is a base function.
Function GetFunctionAliases-demo is a base function.
Function IsBaseFunction-demo is a base function.
Function IsFunctionAlias is not a base function. Base function:IsBaseFunction
Function IsBaseFunction is a base function.
Function GetBaseFunction-demo is a base function.
Function GetBaseFunctionRow is not a base function. Base function:GetBaseFunction
Function GetBaseFunctionName is not a base function. Base function:GetBaseFunction
Function GetBaseFunction is a base function.
Function DoesFunctionHaveAliases is a base function.
Function GetFunctionAliases is a base function.
Function IsFile is a base function.
Function GetFunctionRows is a base function.
Function GetLabelRow is a base function.
Function GetFunctionExit is a base function.
Function GetFunctionPreambleRow is a base function.
Function GetFunctionPostscriptRow is a base function.
Function ClearVariablesByPrefix is a base function.
Function GetFunctionName is a base function.
Function GetBatchCore is a base function.
Function GetNextExitRow is a base function.
Function ListFunctions is a base function.
Function GetPreviousFunctionName is not a base function. Base function:GetPreviousFunctionRow
Function GetPreviousFunctionRow is a base function.
Function GetNextFunctionName is not a base function. Base function:GetNextFunctionRow
Function GetNextFunctionRow is a base function.
Function GetPreviousExitRow is a base function.
Function GetEOFrow is a base function.
Function countLines is a base function.
Function IsFunctionLabelExcluded is a base function.
Function GetPreviousEmptyRow is a base function.
Function GetNextEmptyRow is not a base function.
This next demo function, will do the same, but also output a list of the aliases (there can be more than one)

Code: Select all

GetFunctionAliases-demo.bat IsBaseFunction.bat
Test functions ShiftedArgumentCaller Hello PrintWithoutNewline GetFunctionAliases-demo IsBaseFunction-demo IsFunctionAlias IsBaseFunction GetBaseFunction-demo GetBaseFunctionRow GetBaseFunctionName GetBaseFunction DoesFunctionHaveAliases GetFunctionAliases IsFile GetFunctionRows GetLabelRow GetFunctionExit GetFunctionPreambleRow GetFunctionPostscriptRow ClearVariablesByPrefix GetFunctionName GetBatchCore GetNextExitRow ListFunctions GetPreviousFunctionName GetPreviousFunctionRow GetNextFunctionName GetNextFunctionRow GetPreviousExitRow GetEOFrow countLines IsFunctionLabelExcluded GetPreviousEmptyRow GetNextEmptyRow

Function ShiftedArgumentCaller is a base function.
Function Hello is a base function.
Function PrintWithoutNewline is a base function.
Function GetFunctionAliases-demo is a base function.
Function IsBaseFunction-demo is a base function.
Function IsFunctionAlias is not a base function. Base function:IsBaseFunction
Function IsBaseFunction is a base function.
Function IsBaseFunction has aliases
Function IsBaseFunction aliases: IsFunctionAlias
Function GetBaseFunction-demo is a base function.
Function GetBaseFunctionRow is not a base function. Base function:GetBaseFunction
Function GetBaseFunctionName is not a base function. Base function:GetBaseFunction
Function GetBaseFunction is a base function.
Function GetBaseFunction has aliases
Function GetBaseFunction aliases: GetBaseFunctionName GetBaseFunctionRow
Function DoesFunctionHaveAliases is a base function.
Function GetFunctionAliases is a base function.
Function IsFile is a base function.
Function GetFunctionRows is a base function.
Function GetLabelRow is a base function.
Function GetFunctionExit is a base function.
Function GetFunctionPreambleRow is a base function.
Function GetFunctionPostscriptRow is a base function.
Function ClearVariablesByPrefix is a base function.
Function GetFunctionName is a base function.
Function GetBatchCore is a base function.
Function GetNextExitRow is a base function.
Function ListFunctions is a base function.
Function GetPreviousFunctionName is not a base function. Base function:GetPreviousFunctionRow
Function GetPreviousFunctionRow is a base function.
Function GetPreviousFunctionRow has aliases
Function GetPreviousFunctionRow aliases: GetPreviousFunctionName
Function GetNextFunctionName is not a base function. Base function:GetNextFunctionRow
Function GetNextFunctionRow is a base function.
Function GetNextFunctionRow has aliases
Function GetNextFunctionRow aliases: GetNextFunctionName
Function GetPreviousExitRow is a base function.
Function GetEOFrow is a base function.
Function countLines is a base function.
Function IsFunctionLabelExcluded is a base function.
Function GetPreviousEmptyRow is a base function.
Function GetNextEmptyRow is not a base function.'"_DFHA_result=false"' is not recognized as an internal or external command,
operable program or batch file.
Function GetNextEmptyRow has aliases
The syntax of the command is incorrect.
Oops looks like GetFunctionAliases-demo still has a bug, I will post again when I fixed that !
functions.zip
(24.62 KiB) Downloaded 534 times
In the zip file you will find the following files
These are all the same file with different names

Code: Select all

GetFunctionAliases-demo.bat
IsBaseFunction.bat
IsBaseFunction-demo.bat
IsFunctionAlias.bat
And you will find this last file

Code: Select all

bfw.bat
This is my current "batchfile framework" file that I am working on. I deleted unneeded stuff to create the previous files for easier auditing.

For the current purpose you would use it as such

Code: Select all

call bfw IsBaseFunction bfw.bat IsBaseFunction && echo It is base function || echo it is not base function
It is base function

call bfw IsBaseFunction bfw.bat IsFunctionAlias && echo It is base function || echo it is not base function
it is not base function

call bfw IsFunctionAlias bfw.bat IsBaseFunction && echo It is function alias || echo it is not function alias
it is not function alias

call bfw IsFunctionAlias bfw.bat IsFunctionAlias && echo It is function alias || echo it is not function alias
It is function alias
Last edited by shodan on 13 May 2024 19:59, edited 1 time in total.

shodan
Posts: 89
Joined: 01 May 2023 01:49

Re: Functions to find "base" function and their aliases ( :GetBaseFunction :IsBaseFunction :IsFunctionAlias ... )

#2 Post by shodan » 13 May 2024 18:49

Here are the functions themselves

Code: Select all

::Usage Call :GetBasefunction BatchFile FunctionName ReturnVariable 
::returns row number of BaseFunction
:GetBaseFunctionRow
:GetBaseFunctionName
:GetBaseFunction
set "_GetBaseFunction_prefix=_GBF"
set "_GBF_BatchFile=%~1"
set "_GBF_FunctionName=%~2"
set "_GBF_Output=%~3"
Call :GetFunctionExit "%_GBF_BatchFile%" "%_GBF_FunctionName%" _GBF_FunctionExit
Call :GetPreviousFunctionName "%_GBF_BatchFile%" %_GBF_FunctionExit% %_GBF_Output%
Call :ClearVariablesByPrefix %_GetBaseFunction_prefix% _GetBaseFunction_prefix & exit /b %errorlevel%
Here the alias :GetBaseFunctionRow is not coded in

This function checks if the provided function name has aliases.
It does this by finding the base function, in case an alias was provided
Then it finds the previous empty row, this space is what I call the "function preamble"
Then it gets the previous functionname and if the line number is smaller than the "function preamble start row" it exits with true

Code: Select all

::Usage Call :DoesFunctionHaveAliases BatchFile FunctionName optional ReturnVariable && FunctionHasAliases || FunctionHasNoAlias
:DoesFunctionHaveAliases
set "_DoesFunctionHaveAliases_prefix=_DFHA"
set "_DFHA_InputFile=%~1"
set "_DFHA_FunctionName=%~2"
set "_DFHA_Output=%~3"
Call :GetBaseFunction "%_DFHA_InputFile%" "%_DFHA_FunctionName%" _DFHA_BaseFunctionName
if "[%_DFHA_FunctionName%]" EQU "[%_DFHA_BaseFunctionName%]" ( if defined _DFHA_Output set "%_DFHA_Output%=false" & exit /b 1 )
set /a _DFHA_CurrentRow=%errorlevel%
Call :GetFunctionPreambleRow "%_DFHA_InputFile%" "%_DFHA_CurrentRow%" _DFHA_BaseFunctionPreambleRow
Call :GetPreviousFunctionName "%_DFHA_InputFile%" %_DFHA_CurrentRow% _DFHA_PreviousFunctionName
set /a _DFHA_PreviousFunctionRow=%errorlevel%
set "_DFHA_result=true"
if %_DFHA_PreviousFunctionRow% LEQ %_DFHA_BaseFunctionPreambleRow% set "_DFHA_result=false"
if defined _DFHA_Output set "%_DFHA_Output%=%_DFHA_result%"
if "[%_DFHA_result%]" EQU "[true]" echo Function %_DFHA_FunctionName% has aliases
Call :ClearVariablesByPrefix %_GetFunctionAliases_prefix% _GetFunctionAliases_prefix & if "[%_DFHA_result%]" EQU "[true]" ( exit /b 0 ) else ( exit /b 1 )
I think I see there is a bug in this function.... it exits if functionname equals basefunctionname without checking for aliases at all ??

It should return 0 if there are no aliases and the count of aliases if there are, so I should rename this GetFunctionAliasCount
Also after GetBaseFunction gets called and if the provided function is the base function, it returns false (1)
Actually, now that I think of it, GetFunctionAliasCount should be an alias of DoesFunctionHaveAliases


The GetFunctionAliases is like DoesFunctionHaveAliases, but it loops through all GetPreviousFunctionName until it reaches the preamble start row
then returns the list of aliases

Code: Select all

::Usage Call :GetFunctionAliases batchfile functionname returnvariable
::returns number of aliases found, prints them if there is no return variable
:GetFunctionAliases
set "_GetFunctionAliases_prefix=_GFA"
set "_GFA_InputFile=%~1"
set "_GFA_FunctionName=%~2"
set "_GFA_Output=%~3"
set /a _GFA_Count=0
Call :GetBaseFunction "%_GFA_InputFile%" "%_GFA_FunctionName%" _GFA_BaseFunctionName
set /a _GFA_CurrentRow=%errorlevel%
Call :GetFunctionPreambleRow "%_GFA_InputFile%" "%_GFA_CurrentRow%" _GFA_BaseFunctionPreambleRow
:GetFunctionAliases-loop
Call :GetPreviousFunctionName "%_GFA_InputFile%" %_GFA_CurrentRow% _GFA_PreviousFunctionName
set /a _GFA_PreviousFunctionRow=%errorlevel%
if %_GFA_PreviousFunctionRow% EQU %_GFA_CurrentRow% GoTo :GetFunctionAliases-end
if %_GFA_PreviousFunctionRow% LEQ %_GFA_BaseFunctionPreambleRow% GoTo :GetFunctionAliases-end
set /a _GFA_Count+=1
set "_GFA_Buffer=%_GFA_Buffer% %_GFA_PreviousFunctionName%"
set /a _GFA_CurrentRow = _GFA_previousfunctionrow
GoTo :GetFunctionAliases-loop
:GetFunctionAliases-end
if defined _GFA_Output set "%_GFA_Output%=%_GFA_Buffer%"
if not defined _GFA_Output echo Function %_GFA_BaseFunctionName% aliases:%_GFA_Buffer%
Call :ClearVariablesByPrefix %_GetFunctionAliases_prefix% _GetFunctionAliases_prefix & exit /b %_GFA_Count%
IsBaseFunction and IsFunctionAlias are base and aliases themselves, making good test target for themselves
Simply calls GetBasefunction and returns appropriate boolean

Code: Select all

::Usage Call IsFunctionAlias BatchFile FunctionName ReturnVariable && Function is alias || function is not alias
::Usage Call IsBaseFunction BatchFile FunctionName ReturnVariable && Function is base function || function is not base function
:IsFunctionAlias BatchFile FunctionName
Set "_IBF_IsAlias=true"
:IsBaseFunction 
set "_IsBaseFunction_prefix=_IBF"
set "_IBF_InputFile=%~1"
set "_IBF_FunctionName=%~2"
set "_IBF_Output=%~3"
Call :GetBasefunction "%_IBF_InputFile%" "%_IBF_FunctionName%" _IBF_BaseFunction
if /i "[%_IBF_FunctionName%]" EQU "[%_IBF_BaseFunction%]" ( if defined _IBF_IsAlias ( set "_IBF_Result=false") else ( set "_IBF_Result=true" ) ) else ( if defined _IBF_IsAlias ( set "_IBF_Result=true") else ( set "_IBF_Result=false" ) )
if defined _IBF_Output set "%_IBF_Output%=%_IBF_Result%"
Call :ClearVariablesByPrefix %_IsBaseFunction_prefix% _IsBaseFunction_prefix & if "[%_IBF_Result%]" EQU "[true]" ( exit /b 0 ) else ( exit /b 1 )


now the demos, they get a list of all function labels and do the function routine on each

Code: Select all

:GetBaseFunction-demo
set "_GetBaseFunction_InputFile=%~1"
set "_GetBaseFunction_FunctionName=%~2"
Call :GetBasefunction "%_GetBaseFunction_InputFile%" "%_GetBaseFunction_FunctionName%" _GetBaseFunction_BaseFunction
echo base function name for :%_GetBaseFunction_FunctionName% is :%_GetBaseFunction_BaseFunction% at line %errorlevel%
GoTo :EOF

Code: Select all

::Usage Call :IsBaseFunction-demo BatchFile optional FunctionName 
:IsBaseFunction-demo
set "_IsBaseFunction_InputFile=%~1"
set "_IsBaseFunction_FunctionName=%~2"
if not defined _IsBaseFunction_InputFile set "_IsBaseFunction_InputFile=%~dpnx0"
if not defined _IsBaseFunction_FunctionName Call :ListFunctions "%_IsBaseFunction_InputFile%"  _IsBaseFunction_FunctionName 
for %%a in (%_IsBaseFunction_FunctionName%) do (
			Call :IsBaseFunction "%_IsBaseFunction_InputFile%" "%%a" _IsBaseFunction_IsBaseFunction && echo Function %%a is a base function. || call :PrintWithoutNewline Function %%a is not a base function. 
			if errorlevel 1 Call :GetBasefunction "%_IsBaseFunction_InputFile%" "%%a" _IsBaseFunction_BaseFunction
			if errorlevel 1 Call echo  Base function:%%_IsBaseFunction_BaseFunction%%
 )
Call :ClearVariablesByPrefix _IsBaseFunction
GoTo :EOF

Code: Select all

::Usage Call :GetFunctionAliases-demo BatchFile optional FunctionName 
:GetFunctionAliases-demo
REM echo on 
set "_GetFunctionAliases_InputFile=%~1"
set "_GetFunctionAliases_FunctionName=%~2"
if not defined _GetFunctionAliases_InputFile set "_GetFunctionAliases_InputFile=%~dpnx0"
if not defined _GetFunctionAliases_FunctionName Call :ListFunctions "%_GetFunctionAliases_InputFile%"  _GetFunctionAliases_FunctionName 
echo Test functions %_GetFunctionAliases_FunctionName%
echo.
for %%a in (%_GetFunctionAliases_FunctionName%) do (
			Call :IsBaseFunction "%_GetFunctionAliases_InputFile%" "%%a" _GetFunctionAliases_GetFunctionAliases && echo Function %%a is a base function. || call :PrintWithoutNewline Function %%a is not a base function. 
			if errorlevel 1 Call :GetBasefunction "%_GetFunctionAliases_InputFile%" "%%a" _GetFunctionAliases_BaseFunction
			if errorlevel 1 ( Call echo  Base function:%%_GetFunctionAliases_BaseFunction%%& ( echo false | find "true">nul) )
			if not errorlevel 1 ( Call :DoesFunctionHaveAliases "%_GetFunctionAliases_InputFile%" "%%a" && Call :GetFunctionAliases "%_GetFunctionAliases_InputFile%" "%%a" )
 )
Call :ClearVariablesByPrefix _GetFunctionAliases
REM Call :DoesFunctionHaveAliases BatchFile FunctionName optional ReturnVariable && FunctionHasAliases || FunctionHasNoAlias
GoTo :EOF

shodan
Posts: 89
Joined: 01 May 2023 01:49

Re: Functions to find "base" function and their aliases ( :GetBaseFunction :IsBaseFunction :IsFunctionAlias ... )

#3 Post by shodan » 13 May 2024 18:54

Here are a few more of the support functions within

I will revisit these when I present about the bfw batchfileframework officially

Code: Select all

:ShiftedArgumentCaller
set _ShiftedArgumentCaller_function=%~1
shift
set "_ShiftedArgumentCaller_function=" & GoTo :%_ShiftedArgumentCaller_function%
GoTo :EOF

Code: Select all

:PrintWithoutNewline
echo|set /p="%*"
GoTo :EOF

Code: Select all

::Usage Call :GetPreviousEmptyRow BatchFile StartRow optional OutputRow
:GetPreviousEmptyRow
set "_GPEW_previous="
for /f delims^=:^ tokens^=1 %%a in ('%SystemRoot%\System32\findstr /N "^$" "%~1"') do ( ( if %%a LSS %~2 set /a _GPEW_previous=%%a ) & if %%a GEQ %~2 ( GoTo :GetPreviousEmptyRow-exit-loop ) )
exit /b 0
:GetPreviousEmptyRow-exit-loop
if "[%~3]" NEQ "[]" call set "%~3=%_GPEW_previous%"
set "_GPEW_previous=" & exit /b %_GPEW_previous%

Code: Select all

::Usage Call :GetFunctionName File LineNumber OutputValue
:GetFunctionName
for /F "usebackq eol= tokens=1,2 delims=(&:=+ " %%i in (`^(type "%~1" ^| findstr /n /r /c:".*" ^| findstr /B /C:"%~2:" ^) 2^>nul`) do ( set "%~3=%%j" & exit /b 0 )
REM proposed alternative for /F "tokens=2 delims=(&:=+ " %%i in ('%SystemRoot%\System32\findstr.exe /n "" "%~1" ^| %SystemRoot%\System32\findstr.exe /B /C:"%~2:"') do set "%~3=%%i" & exit /b 0
exit /b 1

Code: Select all

::Usage Call :GetLabelRow BatchFile FunctionName optional OutputRow
:GetLabelRow
for /f delims^=:^ tokens^=1 %%a in ('%SystemRoot%\System32\findstr /I /N "^:%~2" "%~1" ^| findstr /I /V "::%~2[a-zA-Z0-9\-\/\?\!\@\%%\$\#\^\*\)\{\}\[\]\:\_]"') do ( if "[%~3]" NEQ "[]" set "%~3=%%a" & exit /b %%a )
exit /b 0

Code: Select all

::Usage Call :GetFunctionPreambleRow BatchFile FunctionNameOrRow optional OutputRow
:GetFunctionPreambleRow
Call :GetPreviousEmptyRow "%~1" "%~2" "%~3"
exit /b %errorlevel%

Code: Select all

::Usage Call :GetFunctionPostscriptRow BatchFile FunctionNameOrRow optional OutputRow
:GetFunctionPostscriptRow
Call :GetFunctionExit "%~1" "%~2" _GFPR_ExitRow
Call :GetNextEmptyRow "%~1" "%_GFPR_ExitRow%" "%~3"
set "_GFPR_ExitRow=" & exit /b %errorlevel%

Code: Select all

::Usage Call :GetEOFrow BatchFile FunctionName optional OutputRow
:GetEOFrow
for /f delims^=:^ tokens^=1 %%a in ('%SystemRoot%\System32\findstr /N /I /C:"EndOf_%~2" "%~1"') do ( if "[%~3]" NEQ "[]" set "%~3=%%a" & exit /b %%a )
exit /b 0

Code: Select all

::Usage Call :GetNextExitRow BatchFile StartRow optional OutputRow
:GetNextExitRow
for /f delims^=:^ tokens^=1 %%a in ('%SystemRoot%\System32\findstr /N /I /C:"goto :EOF" /C:"exit /B" "%~1"') do ( if %%a GTR %~2 ( if "[%~3]" NEQ "[]" set "%~3=%%a" & exit /b %%a ) )
exit /b 0

Code: Select all

::Usage Call :GetNextEmptyRow BatchFile StartRow optional OutputRow
:GetNextEmptyRow
for /f delims^=:^ tokens^=1 %%a in ('%SystemRoot%\System32\findstr /N "^$" "%~1"' ) do ( if %%a GTR %~2 ( if "[%~3]" NEQ "[]" set "%~3=%%a" & exit /b %%a ) )
Call :countLines _GetNextEmptyRow_lastrow "%~1"
set /a _GetNextEmptyRow_lastrow+=1
if "[%~3]" NEQ "[]" set "%~3=%_GetNextEmptyRow_lastrow%"
exit /b %_GetNextEmptyRow_lastrow%

Code: Select all

::Usage Call :GetPreviousExitRow BatchFile StartRow optional OutputRow
:GetPreviousExitRow
set "_GPER_previous="
for /f delims^=:^ tokens^=1 %%a in ('%SystemRoot%\System32\findstr /N /I /C:"goto :EOF" /C:"exit /B" "%~1"') do ( ( if %%a LSS %~2 set /a _GPER_previous=%%a ) & if %%a GEQ %~2 ( GoTo :GetPreviousExitRow-exit-loop ) )
:GetPreviousExitRow-exit-loop
if "[%~3]" NEQ "[]" call set "%~3=%_GPER_previous%"
set "_GPER_previous=" & exit /b %_GPER_previous%

Code: Select all

::Usage Call :GetNextFunctionName BatchFile StartRow optional OutputRow
::Usage Call :GetNextFunctionRow BatchFile StartRow optional OutputRow
:GetNextFunctionName
set "_GNFR_ReturnName=true"
:GetNextFunctionRow
set "_GetNextFunctionRow_prefix=_GNFR"
set "_GNFR_BatchFile=%~1"
set "_GNFR_StartRow=%~2"
set "_GNFR_Output=%~3"
:GetNextFunctionRow-args
for /f delims^=:^ tokens^=1 %%a in ('%SystemRoot%\System32\findstr /N "^:[^:]" "%_GNFR_BatchFile%"') do ( if %%a GTR %_GNFR_StartRow% ( set /a _GNFR_current=%%a & GoTo :GetNextFunctionRow-exit-loop ) )
Call :countLines _GNFR_current "%_GNFR_BatchFile%" 2>nul
set /a _GNFR_current-=1 & GoTo :GetNextFunctionRow-skip
:GetNextFunctionRow-exit-loop
Call :GetFunctionName "%~1" %_GNFR_current% _GNFR_current_FunctionName
Call :IsFunctionLabelExcluded _GNFR_current_FunctionName && ( set /a _GNFR_StartRow=%_GNFR_current% & GoTo :GetNextFunctionRow-args )
:GetNextFunctionRow-skip
if "[%_GNFR_Output%]" NEQ "[]" set "%_GNFR_Output%=%_GNFR_current%" 
if "[%_GNFR_Output%]" NEQ "[]" if "[%_GNFR_ReturnName%]" EQU "[true]" set "%_GNFR_Output%=%_GNFR_current_FunctionName%" 
Call :ClearVariablesByPrefix %_GetNextFunctionRow_prefix% _GetNextFunctionRow_prefix  & exit /b %_GNFR_current%

Code: Select all

::Usage Call :IsFunctionLabelExcluded FunctionLabel optional ExclusionList && IsExcluded || IsNotExcluded
:IsFunctionLabelExcluded
set "_IsFunctionLabelExcluded_prefix=_IFLE"
set /a _IFLE_exit=1
if defined %~1 call set _IFLE_input=%%%~1%%
if not defined _IFLE_input set "_IFLE_input=%~1"
set "_IFLE_input=%_IFLE_input:-= %"
set "_IFLE_input=%_IFLE_input::= %"
set "_IFLE_input=%_IFLE_input:)= %"
set "_IFLE_input=%_IFLE_input:(= %"
set "_IFLE_ExclusionList=%~2"
if "[%_IFLE_ExclusionList%]" EQU "[]" set "_IFLE_ExclusionList=main setup macro end loop loop2 loop3 loop4 skip skip1 skip2 skip2 skip3 skip4 test test1 test2 test3 cleanup argument params args next prev iteration pre post 0 1 2 3 4 5 6 7 8 9 subloop matchfound nomatch found index list arguments preamble test4 test5 test6 start reset"
for %%a in (%_IFLE_input%) do ( set _IFLE_last_token=%%a )
for %%a in (%_IFLE_ExclusionList%) do if %%a EQU %_IFLE_last_token% ( set /a _IFLE_exit=0 & GoTo :IsFunctionLabelExcluded-end ) 
if "[%_IFLE_input:~,6%]" EQU "[EndOF_]" ( set /a _IFLE_exit=0 & GoTo :IsFunctionLabelExcluded-end ) 
:IsFunctionLabelExcluded-end
Call :ClearVariablesByPrefix %_IsFunctionLabelExcluded_prefix% _IsFunctionLabelExcluded_prefix  & exit /b %_IFLE_exit%

Code: Select all

::Usage Call :GetFunctionExit BatchFile FunctionName or Row optional OutputRow
:GetFunctionExit
set "_GetFunctionExit_prefix=_GFE"
set "_GFE_BatchFile=%~1"
set "_GFE_Function=%~2"
set "_GFE_Output=%~3"
echo.%_GFE_Function%| findstr /r "[^0123456789]" >nul && ( set "_GFE_FunctionName=%_GFE_Function%" & Call :GetLabelRow "%_GFE_BatchFile%" %_GFE_Function% _GFE_Function ) || Call :GetFunctionName "%_GFE_BatchFile%" %_GFE_Function% _GFE_FunctionName
Call :GetNextExitRow "%_GFE_BatchFile%" %_GFE_Function% _GFE_FunctionNextExit
Call :GetNextFunctionRow "%_GFE_BatchFile%" %_GFE_FunctionNextExit% _GFE_FunctionNextFunction
Call :GetPreviousExitRow "%_GFE_BatchFile%" %_GFE_FunctionNextFunction% _GFE_FunctionExit
set /a _GFE_FunctionEOFExit=0 & Call :GetEOFrow "%_GFE_BatchFile%" %_GFE_FunctionName% _GFE_FunctionEOFExit
if %_GFE_FunctionEOFExit% GTR 0 set /a _GFE_FunctionExit=%_GFE_FunctionEOFExit%
if defined _GFE_Output set /a %_GFE_Output%=%_GFE_FunctionExit%
Call :ClearVariablesByPrefix %_GetFunctionExit_prefix% _GetFunctionExit_prefix & exit /b %_GFE_FunctionExit%

Code: Select all

::Usage Call :GetFunctionRows BatchFile FunctionName OutputObject
:GetFunctionRows
set "_GetFunctionRows_prefix=_GFR"
set "_GFR_BatchFile=%~1"
set "_GFR_FunctionName=%~2"
set "_GFR_OutputObject=%~3"
Set "%_GFR_OutputObject%.name=%_GFR_FunctionName%"
Call :GetLabelRow "%_GFR_BatchFile%" %_GFR_FunctionName% %_GFR_OutputObject%.start && exit /b 1
Call :GetFunctionExit "%_GFR_BatchFile%" %%%_GFR_OutputObject%.start%% %_GFR_OutputObject%.exit
Call :GetFunctionPreambleRow "%_GFR_BatchFile%" %%%_GFR_OutputObject%.start%% %_GFR_OutputObject%.preamble
Call :GetFunctionPostscriptRow "%_GFR_BatchFile%" %%%_GFR_OutputObject%.start%% %_GFR_OutputObject%.postscript
Call :ClearVariablesByPrefix %_GetFunctionRows_prefix% _GetFunctionRows_prefix  & GoTo :EOF

Post Reply