Fabee
Fabee

Reputation: 11

Extract Macro from HeaderFile with C#

I am trying to extract a macro-name and the code behind it with a regex and want to save them together in a dic! The header files I want to scan look something like this:

#define TEST_MAKRO (ival)    \
{                            \
   somevalue = ival;         \
}
#define TEST_MAKRO2 (ival1, ival2, retval)    \
{                            \
   retval = ival1 + ival2;   \      
}
#define TEST_MASK 0x123 \

Now I´m trying to match the #define (without param) and the whole #define till } like this:

string makroexp1 = @"(#define+(\s)+[^()]*)";
string makroexp2 = @"define+(.*\\\n)+(\})";

string[] lines = File.ReadAllLines(path);
string temporarystring = "";
foreach (string line in lines)
{
   temporarystring += line;
   temporarystring += "\n";
}
foreach (Match makroname in Regex.Matches(temporarystring, makroexp1)){
   //somehow add to dictonary (this should be the key)
}
foreach (Match replacement in Regex.Matches(temporarystring, makroexp2)){
   //add to dictionary (this should be the value of the corresponding key)
}

It actually kinda works (matches) but I cannot find a good way to add them together ... something like:

makrodic.Add(makroname.Value, replacement.Value) 

doens´t work obv :/

Upvotes: 1

Views: 130

Answers (3)

Fabee
Fabee

Reputation: 11

Thanks for the help guys, my final solution looks like this! (thanks @Wiktor Stribiżew)

string makroexp = @"#define\s+(\w+).*\\(?:\s*{((?:.*\\\s+)*)})?";

string[] lines = File.ReadAllLines(Path.GetFullPath(....));
string temporarystring = "";

string[] keys = new string[0];
string[] values = new string[0];

foreach (string line in lines)
{
    temporarystring += line;
    temporarystring += "\n";
}


try
{
    makrodic.Add(makro.Groups[1].Value, makro.Groups[2].Value);
}
catch
{
    //Already added
}

Upvotes: 0

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 627607

Use

@"#define\s+(\w+).*\\(?:\s*{((?:.*\\\s+)*)})?"

See the regex demo

Then, match.Groups[1].Value is the name (TEST_MAKRO) and the match.Groups[2].Value is the contents.

Details:

  • #define - a literal substring
  • \s+ - 1 or more whitespaces
  • (\w+) - Group 1 matching one or more word chars
  • .*\\ - any 0+ chars other than a newline as many as possible up to the last \ on a line that is followed with...
  • (?:\s*{((?:.*\\\s+)*)})? - an optional non-capturing group matching a sequence of:
    • \s* - 0+ whitespaces
    • { - a {
    • ((?:.*\\\s+)*) - Group 2: 0+ sequences of:
      • .* - any 0+ chars other than a newline as many as possible
      • \\ - a \ symbol
      • \s+ - 1+ whitespaces
    • } - a }

enter image description here

Upvotes: 1

vasek
vasek

Reputation: 2849

Maybe this gives you a good starting point (needs tuning for one-line macros):

        var macros = new Dictionary<string, string>();
        var regex = new Regex(@"#define +(\w+).*\n\{([^\{\}]+)\}");

        foreach (Match m in regex.Matches(File.ReadAllText(path)))
        {
            macros[m.Groups[1].ToString()] = m.Groups[2].ToString();
        }

Upvotes: 0

Related Questions