2

I am trying to parse C++ headers to delete any #ifdef inside a enum. i needed this because a headerParser module I am using has this bug of skipping any enum with #ifdef in it.

I have a shell script which collects the file and prepares it. then one python script is called to generate final output. The python file is generic, so I need to do the "#ifdef" block cleaning inside shell script only.

the text section looks like:

  typedef enum fixedsample
{
element 1,
element 2,
element 3,
#ifdef XYZ
element 4,
element 5,
#endif
} FIXEDNAME;

I do not need the elements inside ifdef, so need to delete this. Also the enum name "fixedsample" and "FIXEDNAME" is true for any file, no variation will be there.

Can awk be used for this purpose? Any help is highly appriciated.

EDIT: "typedef enum ConstantName" and "}CONSTANT;" will be present in all files. so the #ifdef needs to be searched inside that block only. No other #ifdef will be removed.

1
  • It is possible to write an awk script that will work with your example input, but without seeing the rest of the header file it is impossible to tell if it will work under all conditions. What should happen with the #ifdef in other places? Is the #ifdef always written in exactly the same style? (indentation, different whitespace or if defined(XYZ)...) Is the enum always declared in combination with typedef? Is typedef enum somename always in one single line? Please edit your question to add more details. You might be able to use the preprocessor remove the #ifdef block.
    – Bodo
    Commented Aug 13, 2019 at 11:18

2 Answers 2

4

awk can do this with ranges and a flag, as an example:

awk '/enum fixedsample/,/} FIXEDNAME/ { e=1 } e && /^#ifdef/,/^#endif/ { next } { e=0; print }' foo.hpp

The sed version doesn't even need a flag, just nest the ranges, so each #ifdef ... #endif range inside the enum ... } range gets deleted:

sed '/enum fixedsample/,/} FIXEDNAME/{; /^#ifdef/,/^#endif/d; }' foo.hpp

In your actual version you should use more precise patterns to reduce the chances of false positives.

4
  • Very interesting, I never tried to use a range inside a range in sed. Does this work with every sed? Then you can do it even more straight forward: sed '/enum fixedsample/,/} FIXEDNAME/{/^#ifdef/,/^#endif/d;}'
    – Philippos
    Commented Aug 13, 2019 at 15:03
  • @Philippos edited to use your more elegant version, thank you! Also I tested on the mac sed which is the freebsd sed, and it also works. Commented Aug 13, 2019 at 19:52
  • There is always something new to learn, thank you!
    – Philippos
    Commented Aug 13, 2019 at 21:31
  • I used the sed version. It worked perfectly. thanks @RafaelKitover Commented Aug 14, 2019 at 10:28
1

It's almost never a good idea to mess around with regular expressions in any language syntax. It is highly fragile and will end in chaos for the slightest reason like an #ifdef line commented out. Fixing a buggy parser with another potentially buggy parser is ... at least strange.

If you understood the problem, you may continue reading.

In some cases this may work to remove the whole #ifdef block (btw, sure you want to treat it like not defined?):

sed '/ enum /,/}/!b
  /#ifdef/!b
  :loop
  N
  /#endif/!bloop
  d' file.h

Explanation:

  • / enum /,/}/!b leave all lines outside the enum-}-range untouched
  • /#ifdef/!b also leave everything inside untouch until #ifdef
  • :loop yes, once we met the #ifdef, we need to loop
  • N Now we start to append lines ...
  • /#endif/!bloop until we found the #endif
  • Then delete all we collected between #ifdef and #endif we collected
2
  • I understood the concern. But it may not be applicable to this case as there is very limited variation with this files. I only needed this because just for few files the automation is breaking. Regarding the concern with deleting #ifdef, majority of them is #ifdef 0 and others are just renaming same enum for a particular #ifdef SOMEFLAG. Removing those will not cause a issue for my case. Commented Aug 14, 2019 at 6:22
  • 1
    Fine. If I didn't believe there were cases where you can use a text processor for this kind of task, I would not have posted the solution. I just want to make sure, you (and future readers) know what they are doing. Now, all three given solutions should work for you, but I have to admit the sed solution by Rafael is the most straight forward, easiest to understand and most elegant solution, so I recommend to use that one and accept his answer.
    – Philippos
    Commented Aug 14, 2019 at 6:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .