Is there a way to 'expand' the #define directive? - c++

I have a lot of "stupid" #define in a project and I want to remove them. Unfortunately, I can't do a simple search and replace, since the #define is parameterized. For example:
#define FHEADGRP( x ) bool _process_grp##x( grp_id_t , unsigned char )
This is used to generate headers of a couple of functions. I would like to somehow do the same thing as the preprocessor does - replace each call of the macro by its result (with correct parameters inserted. I hope you understand what I want to do.
I found out that with Visual Studio, one can get the preprocessed intermediate files with the /P option. Unfortunately, this does not help me, since the file is "polluted" with thousands of other lines and with all #defines expanded. I do not want to do this, I just want to expand some of the macros and preferably do it in my IDE (which is Visual Studio). Is there any way how to achieve this?

You can normally get the output of the preprocessor with gcc -E (assuming you're using gcc of course, though other compiler tend to have the same feature).
Of course, processing that file to automatically expand the #define's into other text is not a trivial task. I'd probably write a shell script (or Perl since it's a lot better at massaging text in my opinion) to automate the task.
In Visual Studio, you can use /P to perform the same operation. This can be set in the IDE according to this page.

Yes, there is - since you're using Visual Studio.
The Visual Studio IDE has a powerful search & replace mechanism. You seem to assume it can only handle literal strings. It can do more. Hit Ctrl-Shift-H for a global search and replace. In the "Find options", select "Use: Wildcards".
Now replace FHEADGRP(*) by bool _process_grp\1( grp_id_t , unsigned char )
The wildcard is *, and \1 is the backreference.
[edit]
Macros work on the tokenized source, but Search&Replace works on characters. This can cause a slight problem. Consider the cases FHEADGRP(Foo) and FHEADGRP( Foo ). For a C macro, they're equivalent, but in the second case the backreference will expand to Foo - with spaces.
The workaround is to use regexes, in particular replace FHEADGRP\(:b*(.*):b*\) with bool _process_grp\0( grp_id_t , unsigned char ). I find that the VS2005 implementation is a bit buggy; for instance the simple ? expression fails to match a single space. But the example above should work.

Uh I would advise you to use sed, http://www.gnu.org/software/sed/, or another regex tool.

Related

Indexing string literals for c++ project

I have a huge c++ project and I find myself rgrep-ing for patterns that I know are in string literals. Is there a way to get clang or xtags or cscope or whatever to build a file with a mapping of each string literal in the project to the file and line where it was found?
I don't know of a way to make cscope or friends to do this. You could almost certainly write a custom Starscope extractor that would do this, if you don't mind writing a dozen or so lines of Ruby (starscope: https://github.com/eapache/starscope, adding an extractor: https://github.com/eapache/starscope/blob/master/doc/LANGUAGE_SUPPORT.md#how-to-add-another-language)
Alternatively it may just be enough to use something like ag instead, which is grep-like but generally a lot faster: https://github.com/ggreer/the_silver_searcher

Regular Expression for whole world

First of all, I use C# 4.0 to parse the code of a VB6 application.
I have some old VB6 code and about 500+ copies of it. And I use a regular expression to grab all kinds of global variables from the code. The code is described as "Yuck" and some poor victim still has to support this. So I'm hoping to help this poor sucker a bit by generating overviews of specific constants. (And yes, it should be rewritten but it ain't broke, so...)
This is a sample of a code line I need to match, in this case all boolean constants:
Public Const gDemo = False 'Is this a demo version
And this is the regular expression I use at this moment:
Public\s+Const\s+g(?'Name'[a-zA-Z][a-zA-Z0-9]*)\s+=\s+(?'Value'[0-9]*)
And I think it too is yuckie, since the * at the end of the boolean group. But if I don't use it, it will only return 'T' or 'F'. I want the whole word.
Is this the proper RegEx to use as solution or is there an even nicer-looking option?
FYI, I use similar regexs to find all string constants and all numeric constants. Those work just fine. And basically the same .BAS file is used for all 50 copies but with different values for all these variables. By parsing all files, we have a good overview of how every version is configured.
And again, yes, we need to rebuild the whole project from scratch since it becomes harder to maintain these days. But it works and we need the manpower for other tasks. It just needs the occasional tweaks...
You can use: Public\s+Const\s+g(?<Name>[a-zA-Z][a-zA-Z0-9]*)\s+=\s+(?<Value>False|True)
demo

How to find move constructors in codebase using grep or an IDE?

I want to find move constructors in codebase of a large c++ project. Simply grepping for "&&" doesn't work, because it matches a lot of 'logical and' operators.
Any way to grep more precisely for move constructors?
Any way to search for move constructors using Visual Studio (on Windows) or XCode (on Mac)?
Looks like a job for regular expressions. In Visual Studio, press ctrl+F. In the search pop-up window, activate the option "Use regular expressions" (or press alt+E, when the search line is active). Then type the following expression:
\b\w+\s*[\(]\s*(const)*\s*(volatile)*\s*\w+\s*[&][&]\s*[\)]
It will find any string of the form:
class_name(class_name&&)
class_name(const class_name&&)
class_name(volatile class_name&&)
class_name(const volatile class_name&&)
as specified in:
http://en.cppreference.com/w/cpp/language/move_constructor
The expression works also if there is any number of whitespaces between class_name, parentheses and keywords like const etc.
If you want it to work also for named variables, e.g.:
class_name(class_name&& variable_name)
it's enough to modify it slightly:
\b(\w+)\s*[\(]\s*(const)*\s*(volatile)*\s*\1\s*[&][&]\s*\w*\s*[\)]
EDIT: As an answer to the OP's request, I've modified the above regex in such a way that it uses backreference now. The '\1' means "Find the same expression that was captured by the first expression grouped in parentheses" - the first such expression is (\w+), which is the first 'class_name' in the examplary move constructors above. This ensures that there is the same string on both sides of this guy: '('. To sum it up: one additional pair of parentheses, '\1' and magic happens.
Interesting thing is that Microsoft doesn't mention that VS supports backreferences.
More information about regular expressions in Visual Studio can be found here:
http://msdn.microsoft.com/en-us/library/2k3te2cs.aspx

Complicated multi-argument #define macro for strings

I'm working on a project and have a problem that I believe can be solved with macros, but given the nature of the issue I don't have the experience to write one myself.
Here's what I would expect as input and output of the #define macro:
Inputting code such as this
printf(foobar(Hello World.));
Should result in the preprocessor producing code that reads:
printf((char *)(std::string("")+'H'+'e'+'l'+'l'+'o'+' '+'W'+'o'+'r'+'l'+'d'+'.').c_str());
I'm assuming something this complicated is possible, and I hope one of you guys can help me out.
I NEED IT TO BE A MACRO, I DO NOT want a string constant anywhere.
The only solution I can think of is to run your code through a suitable script (probably just some light awk), that does the substitution before your code reaches the pre-compiler.
Depending on your environment you could do this as a "Pre-Build Event" in Visual Studio, or just add a step directly into your makefile.
Uh, I fear it is impossible (unless I don't know something).
I believe there is no macro to split a given input token (e.g. Hello) into characters building it (H e l l o)
There were some attempts to do such thing, but I fear it is not exactly what you need:
C++: Can a macro expand "abc" into 'a', 'b', 'c'?
"More powerful precompiler" ?
Try this topic: Replacements for the C preprocessor
Macros are basically substitution or addition of strings.
You could do this with a pre-processor of your own, but the standard pre-processor won't split strings into component parts.
How about this:
Put all these (assuming there is more than one) 'macros' in a separate file. Write a program that translates them into the expansion you require and then include THAT file in your c program? You could then make the expansion program part of your make file so it's always up to date.
Using a separate file makes the expansion program much easier than parsing a c/c++ file.
Since you're looking for a narrow, direct answer to your question and without suggestions, here goes:
This is impossible. You must find a different solution to whatever it is you're trying to achieve.
Have you tried:
#define toString(x) #x
You can use it after like this:
printf("%s", toString(hello world));
Don't try to use printf directly with the string because you can have format specifier in the string.
printf(toString(hello world)); //wrong, you can have for example %d in the string

Search and replace with regular expressions under Visual Studio 2003

I have a large C++ code base that I'm doing some refactoring on where a number of functions have become redundant, and hence should be removed. So I would like to replace
MyFunc(Param)
with
Param
where Param could be a literal value, variable, function call etc... From the online help I gathered that the search parameters should be
MyFunc/({+}/(
and the replace parameters simply
/1
But this gives me a syntax error in my pattern. I'm new to search and replace with regex under visual studio. Can the above be easily achieved? I've had a look at similar questions on this site, which suggest I'm roughly on the right track, but seem to be missing something.
Edit: If you can answer the above, how about if it is part of a class deference, e.g.
MyClass.MyFunc(Param)
or
MyClass->MyFunc(Param)
(FWIW, I also picked up a copy of VisualAssist in the hope it could do this but it doesn't appear to be able to handle this situation).
Second edit: Thanks to Joe for the correct response, but for anyone else using this approach, beware of some pitfalls,
MyFunc(MyArray[MyOtherFunc(x)])
ends up as
MyArray[MyOtherFunc(x])
and
MyFunc((SomeType)x)
ends up as
(SomeTypex)
Once you do a search to check what you get prior to doing a search and replace, make sure you keep modified files open in case you need to undo, and backup your source files before starting, this works well enough. Even with the pitfalls listed, still a huge time saver.
Try this instead:
Find = MyFunc\({[^\)]*}\)
Replace = \1
Your slashes are the wrong way around and the expression in the parenthesis ({+}) is invalid.
This won't work for parameters that contain function calls or other uses of parentheses - the balanced bracket matching problem isn't solveable using regular expressions.