Converting to ALS 4 (Hook Method 7) Very Quickly With Regular Expressions -
[HLF]Southclaw - 17.07.2014
I just improved this
post a bit so I may as well post here as I'm sure someone can find it useful.
___
A while ago, I stumbled upon the
ALS 7 topic and I set out to convert SIF and SS to use this method but SS has 195 files alone, a search found 230 hooks
woah! I ain’t doing all those by hand!
Luckily,
Sublime Text supports
Regular Expression search and replace. So in this post, I will guide you through the regex queries needed to convert from the old ALS method to the new (faster) version.
Regular Expressions
If you're not familiar with Regular Expressions, they are
extremely useful! Especially when you want to search for patterns in code. But regex isn't just a neat text-editor feature, you can grab a library and embed regex functionality into a piece of software (there are libraries for a huge variety of languages)
even SA:MP!
Step 1. Identify the Differences
This is an old hook:
pawn Code:
public OnSomething()
{
return CallLocalFunction("lib_OnSomething", "");
}
#if defined _ALS_OnSomething
#undef OnSomething
#else
#define _ALS_OnSomething
#endif
#define OnSomething lib_OnSomething
forward lib_OnSomething();
And this is a new one:
pawn Code:
public OnSomething()
{
#if defined lib_OnSomething
return lib_OnSomething();
#else
return 0;
#endif
}
#if defined _ALS_OnSomething
#undef OnSomething
#else
#define _ALS_OnSomething
#endif
#define OnSomething lib_OnSomething
#if defined lib_OnSomething
forward lib_OnSomething();
#endif
There are two differences here:
Firstly, the return line returns an actual function call instead of CallLocalFunction (read the topic about ALS7 for why):
pawn Code:
return CallLocalFunction("lib_OnSomething", "");
becomes
pawn Code:
#if defined lib_OnSomething
return lib_OnSomething();
#else
return 0;
#endif
Secondly, the forward for the new callback is nested under a compile-time #if check:
pawn Code:
forward lib_OnSomething();
becomes
pawn Code:
#if defined lib_OnSomething
forward lib_OnSomething();
#endif
There is another thing to take into account here: hooked callbacks
may or may not have parameters. This means we need a regex query for catching either just an empty parameter format string or a full one with the parameters too. The parameters must be in a separate capture since those are all we need for the replacement:
pawn Code:
return CallLocalFunction("lib_OnSomething", "d", arg);
becomes
pawn Code:
#if defined lib_OnSomething
return lib_OnSomething(arg);
#else
return 0;
#endif
and
pawn Code:
forward lib_OnSomething(arg);
becomes
pawn Code:
#if defined lib_OnSomething
forward lib_OnSomething(arg);
#endif
Step 2. The Search Queries
The first part is the return of CallLocalFunction which is no longer needed as a simple compile time if check works.
This search regex will catch functions with or without parameters:
pawn Code:
return CallLocalFunction\("([A-Za-z_][A-Za-z_0-9]*)", (""\)|"[a-z]*", ([A-Za-z_0-9\, ]*)\));
The second part searches specifically for a 'forward' that followed a 'define' line because not all 'forward' lines are hooks.
pawn Code:
#define (On[A-Za-z_][A-Za-z_0-9]*) ([A-Za-z_]*_On[A-Za-z_0-9]*)
forward [A-Za-z_][A-Za-z_0-9]*\(([A-Za-z_0-9\, ]*)\);
You can test these out to ensure they work by just doing a simple regex search with ST2/Pawno/Notepad++
Step 3. The Replacements
RegEx has a feature called 'captures' which is used for search+replace. To define a capture field, part of the query is enclosed in brackets. Look at the above queries for example, the word after '#define' is the raw function name, this is captured using brackets and can be used in the replacement query.
Each capture is sequentially numbered and in the replacement query these captures can be inserted with a '$' followed by the number that identifies the capture you want to insert.
Note: these replacement queries were done in Sublime Text 2. In other editors, the indentation may be different.
Replacement 1: The return value
Search:
pawn Code:
return CallLocalFunction\("([A-Za-z_][A-Za-z_0-9]*)", (""\)|"[a-z]*", ([A-Za-z_0-9\, ]*)\));
Replace:
pawn Code:
#if defined $1
return $1($3);
#else
return 0;
#endif
The parameters use capture $3 since $2 actually surrounds the entire set of parameters including the format string and capture $3; pseudo-code example: 2:("dd", 3:(int1, int2)).
Replacement 2: The forwarding
Search:
pawn Code:
#define (On[A-Za-z_][A-Za-z_0-9]*) ([A-Za-z_]*_On[A-Za-z_0-9]*)
forward [A-Za-z_][A-Za-z_0-9]*\(([A-Za-z_0-9\, ]*)\);
Replace:
pawn Code:
#define $1 $2
#if defined $2
forward $2($3);
#endif
Conclusion
I may have made some mistakes here and it may not be compatible with all coding styles or hooking styles.
RegEx is a powerful tool though and if there are incompatibilities, play around with the expressions and reply to this post with fixes.
I hope this has helped you save hours or work manually converting to ALS 7!
Re: Converting to ALS 4 (Hook Method 7) Very Quickly With Regular Expressions -
Sn0wk - 29.07.2014
This is great idea!
Thank you, Southclaw