[v2] RegExReplace callout with global variable Topic is solved

Report problems with documented functionality
quaritexa
Posts: 32
Joined: 09 Nov 2017, 21:03

[v2] RegExReplace callout with global variable

Post by quaritexa » 12 Feb 2022, 01:37

Code: Select all

replace(m, *) {
  global q
  q := %m.1%
}

q := "bug"
w := RegExReplace("#include %A_MyDocuments%\test", "%(A_\w+)%(?Creplace)", q)
;w -> #include bug\test

q := "                                                 "
w := RegExReplace("#include %A_MyDocuments%\test", "%(A_\w+)%(?Creplace)", q)
;w -> #include C:\Users\user\Documents\test
Why?

neogna2
Posts: 590
Joined: 15 Sep 2016, 15:44

Re: [v2] RegExReplace callout with global variable

Post by neogna2 » 12 Feb 2022, 08:46

Is (?Creplace) valid syntax for the NeedleRegEx parameter in RegExReplace()?

quaritexa
Posts: 32
Joined: 09 Nov 2017, 21:03

Re: [v2] RegExReplace callout with global variable

Post by quaritexa » 12 Feb 2022, 13:14

@neogna2
Yes

neogna2
Posts: 590
Joined: 15 Sep 2016, 15:44

Re: [v2] RegExReplace callout with global variable

Post by neogna2 » 13 Feb 2022, 07:11

@quaritexa: yeah sorry I misremembered the Callouts syntax. The issue seems to happen in v1 too. This v2 test shows some variation, don't know what the cause is.

Code: Select all

replace(m, *) {
    global q
    q := %m.1%
}

For Key, A_Val in [A_MyDocuments, A_Now, A_Language]
{
    w := ""
    For Key, Val in ["bug", "bu", "b"]
        Loop 20
        {
            q := StrReplace( Format("{:" A_Index "}", "") , " ", Val) ;return string that repeats Val A_Index times
            w .= A_Index ":  " RegExReplace("#include %A_Val%\test", "%(A_\w+)%(?Creplace)", q) "`n"
        }
    MsgBox w
    ;loop 1   to N   replaces with q (from before the callout)
    ;loop N+1 to end replaces with A_Val (q value set in callout)
    ;number N varies with both q and A_Val
}

Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: [v2] RegExReplace callout with global variable

Post by Helgef » 06 Apr 2022, 08:24

The reason there is no noticeable problem on the first call is that %m.1% in q := %m.1% doesn't fit in q's string buffer, so a new buffer is created. But on the second call, there is enough space in the buffer, so its content is just updated. The problem is that regexreplace didn't make a copy of the buffer so it sees the update.
Here is an example where there is enough space in the buffer on the first call,

Code: Select all

replace(m, *) {
  global q
  q := '+++'
}
q := "abc"
w := RegExReplace('123', "2(?Creplace)", q)
msgbox w
You can even change the haystack from the callout. I do not think it is worth the bother to fix this. In particular, it implies that we need to make copies of the inputs which in ~99.99999% of the time would be a waste. I think it should be sufficient to add a note in the documentation, stating that callout functions should avoid changing the input parameters of regexreplace (and regexmatch).

Cheers.

quaritexa
Posts: 32
Joined: 09 Nov 2017, 21:03

Re: [v2] RegExReplace callout with global variable

Post by quaritexa » 16 Aug 2022, 07:27

Another example:

Code: Select all

q := "                                                 "
path := "Ver %A_AhkVersion%, ID %A_ScriptHwnd%"
MsgBox RegExReplace(path, "%(A_\w*?)%(?Creplace)", q)
replace(m, *) {
  global q
  q := %m.1%
  q := StrLen(q)
}
Will show: Ver 2.0-beta.7, ID 5578266

But

Code: Select all

q := "                                                 "
path := "Ver %A_AhkVersion%, ID %A_ScriptHwnd%"
MsgBox RegExReplace(path, "%(A_\w*?)%(?Creplace)", q)
replace(m, *) {
  global q
  q := %m.1%
  q := StrLen(q)
  MsgBox q,,"T.001"
}
Will show: Ver 10, ID 8

Image

lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: [v2] RegExReplace callout with global variable  Topic is solved

Post by lexikos » 17 Aug 2022, 20:03

If any of the input parameters to a RegEx function is modified during a callout, the behaviour is undefined.
https://lexikos.github.io/v2/docs/misc/RegExCallout.htm#callout-functions

Post Reply

Return to “Bug Reports”