Difficulty with substring substitution

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

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

Difficulty with substring substitution

#1 Post by shodan » 06 Apr 2024 23:23

Hi,

I have a particularly thorny problem for you guys.

I am making a function which can modify batch file function calls.

I have identified 3 types of function calls and I need to change any one type to another.

Here are the name I gave to batch function calls

Internal function call

Code: Select all

Call :myfunction
External function call

Code: Select all

Call myfunction.bat
and function macrocall

Code: Select all

Call %:myfunction%
Because I am copying and combining multiple function in and out of batch files for maximum reusability.


Anyway, here is the actual problem


I have in memory the entire batchfile, line by line. Here is an particularly vexing example.

Code: Select all

set "textline=Call :myfunctiona some args & Call %:myfunctionb% some args & Call myfunctionc.bat some args & Call :myfunctiond some args && echo yes || echo no
What I want to do is find a replace function calls of a particular type and turn it into another type.

Example

Code: Select all

Call :ChangeInternalFunctionToExternal textline
Call :ChangeInternalFunctionToMacroCall textline 
Call :ChangeExternalFunctionToInternal textline
Call :ChangeExternalFunctionToMacroCall textline
Call :ChangeMacroCallFunctionToInternal textline
Call :ChangeMacroCallFunctionToExternal textline 
After :ChangeInternalFunctionToExternal

Code: Select all

textline=Call myfunctiona.bat some args & Call %:myfunctionb% some args & Call myfunctionc.bat some args & Call myfunctiond.bat some args && echo yes || echo no
After :ChangeInternalFunctionToMacroCall

Code: Select all

textline=Call %:myfunctiona% some args & Call %:myfunctionb% some args & Call myfunctionc.bat some args & Call %:myfunctiond% some args && echo yes || echo no
After :ChangeExternalFunctionToInternal

Code: Select all

textline=Call :myfunctiona some args & Call %:myfunctionb% some args & Call :myfunctionc some args & Call :myfunctiond some args && echo yes || echo no
After :ChangeExternalFunctionToMacroCall

Code: Select all

textline=Call :myfunctiona some args & Call %:myfunctionb% some args & Call %:myfunctionc% some args & Call :myfunctiond some args && echo yes || echo no
After :ChangeMacroCallFunctionToInternal

Code: Select all

textline=Call :myfunctiona some args & Call :myfunctionb some args & Call myfunctionc.bat some args & Call :myfunctiond some args && echo yes || echo no
After :ChangeMacroCallFunctionToExternal

Code: Select all

textline=Call :myfunctiona some args & Call myfunctionb.bat some args & Call myfunctionc.bat some args & Call :myfunctiond some args && echo yes || echo no
Based on the following answer by Aacini

https://stackoverflow.com/questions/510 ... batch-file

I tried the substring substitution trick, however, I am unsure if that is even possible due to the number of poison characters in the string

I tried a basic test

Code: Select all

@echo off
set "string=Call :myfunctiona & Call %:myfunctionb% & Call myfunctionc.bat & Call :myfunctiond && echo yes || echo no
set string
set "x=%string:Call :=" & set "substring=%"
set substring
set "x=%string:Call %=" & set "substring=%"
set substring
set "x=%string:Call =" & set "substring=%"
set substring
goto :eof
Unfortunately, the results as follows

Code: Select all

string=Call :myfunctiona & Call :myfunctionbmyfunctiond && echo yes || echo no
substring=myfunctionbmyfunctiond && echo yes || echo no
substring=myfunctionbmyfunctiond && echo yes || echo no
substring=:myfunctionbmyfunctiond && echo yes || echo no

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

Re: Difficulty with substring substitution

#2 Post by shodan » 06 Apr 2024 23:38

So I think I will need to break down the task further. But maybe there are shortcuts to be taken.

For now, here is what I imagine it might look like.

find internal call index and replace

Code: Select all

Loop through every character, look for following (case insensitive) 
Call :
return functionname = all characters after : until space or ampersand or pipe or greater than or less than characters
return index number of : and of terminating character minus one
replace string from index to terminator functionname.bat or %:functionname%
continue until end of string
find macrocall index and replace

Code: Select all

Loop through every character, look for following (case insensitive) 
Call %:
return functionname = all characters after %: until %
return index number of the first % and of terminating character of the last %
replace string from index to terminator functionname.bat or :functionname
continue until end of string
find external call index and replace

Code: Select all

Loop through every character, look for following (case insensitive) 
call 
there was a space at the end of call there
return functionname = all characters after the space, until .bat
if there was a space before .bat, it is a regular call, not a function call
return index number of the first character and of terminating .bat
replace string from index to .bat terminator :functionname or %:functionname%
continue until end of string

Post Reply