Home > Back-end >  Regex change all old cast style to static_cast style in c file
Regex change all old cast style to static_cast style in c file

Time:06-02

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? enter image description here

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)));
  • Related