I am a newbie in regex, I try to write a C# application that replace all of old cast style of c file to static_cast style.
For example:
(void)memcpy(&a[0],(void * )hihi, (UBYTE) V_SIZE);
(void) memcpy((VOID*)abc, (const VOID*) dafa, (uint8)NUMBER_SIZE);
(void )memcpy(
(void *)p,
&abc, (uint8)DATE_SIZE);
I expect all of them should be
static_cast<void>(memcpy(&a[0], static_cast<void * >(hihi), static_cast<UBYTE>( V_SIZE)));
static_cast<void> memcpy(static_cast<VOID*>(abc), static_cast<const VOID*> (hihi), static_cast<uint8>(NUMBER_SIZE));
static_cast<void >memcpy(
static_cast<void *>(p),
&abc, static_cast<uint8>(DATE_SIZE));
I also investigate and try with this one
List<string> castTypeList = new List<string>
{"void", "void *", "UBYTE", "uint8", "VOID*", "uint8" };
// Fix qacpp-4.7.0-3080 This expression uses old style casts
// Only apply for cpp source file (.cpp)
if ((Path.GetExtension(sourceFile) == ".cpp"))
{
foreach (string e in castTypeList)
{
File.WriteAllText(sourceFile, Regex.Replace(
File.ReadAllText(sourceFile),
@"\(" e @"\)([^):;\r\n},]*)",
"static_cast<" e @">($1)"));
}
}
The result look good, but not perfect, some string can't match and replace (You can see below picture). Is there any better solution or better idea to handle it?
CodePudding user response:
Reliably matching old-style casts is impossible with a regex, because you can't tell for sure what's a type and what's not. As proof, consider this C file:
#include "somefile.h"
void f(sometype_t x) {
g((something)*x);
h((somethingelse)(x));
}
If something
is a type, then the line with it is a cast, but if it's a variable, then it isn't. Similarly, if somethingelse
is a type, then the line with it is a cast, but if it's a function, then it isn't. Further reading: https://en.wikipedia.org/wiki/Lexer_hack
CodePudding user response:
You can match and replace with the following pattern until no match is found:
(?i)\(\s*((?:const\s )?(?:u?(?:byte|int)\d*|void)(?:\s*\*)?)\s*\)\s*(\w (?:\((?>[^()] |(?<c>)\(|(?<-c>)\))*\))?)
See the regex demo.
In C#, you can use
var text = @"(void)memcpy(&a[0],(void * )hihi, (UBYTE) V_SIZE);\n(void) memcpy((VOID*)abc, (const VOID*) dafa, (uint8)NUMBER_SIZE);\n(void )memcpy(\n (void *)p,\n &abc, (uint8)DATE_SIZE)";
var pattern = @"(?i)\(\s*((?:const\s )?(?:u?(?:byte|int)\d*|void)(?:\s*\*)?)\s*\)\s*(\w (?:\((?>[^()] |(?<c>)\(|(?<-c>)\))*\))?)";
var tmp = string.Empty;
do
{
tmp = text;
text = Regex.Replace(text, pattern, "static_cast<$1>($2)");
}
while (text != tmp);
Console.WriteLine(text);
See the C# demo. Output:
static_cast<void>(memcpy(&a[0],static_cast<void *>(hihi), static_cast<UBYTE>(V_SIZE)));
static_cast<void>(memcpy(static_cast<VOID*>(abc), static_cast<const VOID*>(dafa), static_cast<uint8>(NUMBER_SIZE)));
static_cast<void>(memcpy(
static_cast<void *>(p),
&abc, static_cast<uint8>(DATE_SIZE)));