C preprocessor using the closing bracket of a parent macro - c

I have this code which works:
#include <stdio.h>
#define A(x) x B
#define B(x) C(x,
#define C(x,y) y x)
int main( void ) {
printf( A("1") ("2") "3" );
}
It prints 132 (the point of the A macro is to swap the thing which follows its parameters in brackets with everything after that until another closing bracket)
But if I use that within another macro:
#define Z(x) x
printf( Z( A("1") ("2") "3" ) );
I get the compile error "Unterminated function-like macro invocation".
I realise that this happens because the compiler is trying to process the arguments of Z independently, but I need to use its closing bracket as a marker. Is there a way I can make this work within macros? Changing the calling syntax isn't really an option.
p.s. Before I get any responses talking about what an awful thing this is to do, rest assured: this is not for real code. It is a problem which came up while making a toy program which uses define to simulate a new language inside C.

The easiest way to see what's going on is to change the test case a little.
#define A(x) x B
#define B(x) C(x,
#define C(x,y) y x] /* note close square bracket instead of close paren */
Y(A(1)(2)3)
preprocesses to Y(1 3 2]. This is because an intermediate stage of expansion looked like
Y(1 C(2,3)
at which point C ate the close paren that appeared to belong to Y in the original text and replaced it with a close bracket.
Now, what happens differently if A(1)(2)3 is inside a macro argument?
#define Z(x) x
Z(A(1)(2)3)
Because of argument prescan, the analogous intermediate stage of expansion is not
Z(1 C(2,3)
but rather
1 C(2,3
with Z squirrelled away on a hidden "pending expansions" stack. The preprocessor is, in effect, enforcing the textual appearance that that final close paren belongs to Z, and C is not allowed to borrow it.
The least-invasive way I can think of to achieve your original goal is
#define _A(x) x B
#define B(x) C(x,
#define C(x,y) y x)
#define Z(x) ZZ((_##x))
#define ZZ(x) ZZZ x
#define ZZZ(x) [x]
Z(A(1)(2)3)
preprocesses to [1 3 2]. We use the token paste operator to prevent Z's argument from being prescanned, so we can add a temporary extra set of parentheses for use by C. ZZ and ZZZ then strip them off again. The catch is that it's an error if you don't paste x with something, so we have to add a leading underscore to the definition of A, and it will be an error if the first token of Z's argument is ever not something that can be token-pasted after an underscore.
You might want to consider using M4 instead of trying to shoehorn this into the C preprocessor.

eclipse cdt is excellent to debug your questions. for eclipse, just hover over a macro to get started. here is detialed info on it:
C/C++ Software Development with Eclipse >> 2.1.7. Macro Expansion
for your second macro, eclipse shows the following:
int main (void) {
printf( Z( A("1") ("2") "3" ) );
}
Spotting the Error
Notice in the expansion #3 C("2", "3" just 'disappears. I take this as CDT's way of saying 'unterminated argument list'. Whatever the case for it disappearing, this is the method I prefer to take when debugging macros.
Using this tool makes it clear that in Expansion#2 (third image) we have an unterminated set of brackets, thus locating the error.
Understanding a Solution
After fiddling around a bit using this tool, I think this is what you were after:
printf( Z( (A("1") ("2") "3") ) );
yields (using gcc -E main.c -c)
printf( ("1" "3" "2") );

This is about the order in which the macros are processed. The simplest solution is to add additional parentheses around the Z argument.
printf( Z( (A("1")("2") "3")) );

Related

Expand pragma to a comment (for doxygen)

Comments are usually converted to a single white-space before the preprocesor is run. However, there is a compelling use case.
#pragma once
#ifdef DOXYGEN
#define DALT(t,f) t
#else
#define DALT(t,f) f
#endif
#define MAP(n,a,d) \
DALT ( COMMENT(| n | a | d |) \
, void* mm_##n = a \
)
/// Memory map table
/// | name | address | description |
/// |------|---------|-------------|
MAP (reg0 , 0 , foo )
MAP (reg1 , 8 , bar )
In this example, when the DOXYGEN flag is set, I want to generate doxygen markup from the macro. When it isn't, I want to generate the variables. In this instance, the desired behaviour is to generate comments in the macros. Any thoughts about how?
I've tried /##/ and another example with more indirection
#define COMMENT SLASH(/)
#define SLASH(s) /##s
neither work.
In doxygen it is possible to run commands on the sources before they are fed into the doxygen kernel. In the Doxyfile there are some FILTER possibilities. In this case: INPUT_FILTER the line should read:
INPUT_FILTER = "sed -e 's%^ *MAP *(\([^,]*\),\([^,]*\),\([^)]*\))%/// | \1 | \2 | \3 |%'"
Furthermore the entire #if construct can disappear and one, probably, just needs:
#define MAP(n,a,d) void* mm_##n = a
The ISO C standard describes the output of the preprocessor as a stream of preprocessing tokens, not text. Comments are not preprocessing tokens; they are stripped from the input before tokenization happens. Therefore, within the standard facilities of the language, it is fundamentally impossible for preprocessing output to contain comments or anything that resembles them.
In particular, consider
#define EMPTY
#define NOT_A_COMMENT_1(text) /EMPTY/EMPTY/ text
#define NOT_A_COMMENT_2(text) / / / text
NOT_A_COMMENT_1(word word word)
NOT_A_COMMENT_2(word word word)
After translation phase 4, both the fourth and fifth lines of the above will both become the six-token sequence
[/][/][/][word][word][word]
where square brackets indicate token boundaries. There isn't any such thing as a // token, and therefore there is nothing you can do to make the preprocessor produce one.
Now, the ISO C standard doesn't specify the behavior of doxygen. However, if doxygen is reusing a preprocessor that came with someone's C compiler, the people who wrote that preprocessor probably thought textual preprocessor output should be, above all, an accurate reflection of the token sequence that the "compiler proper" would receive. That means it will forcibly insert spaces where necessary to make separate tokens remain separate. For instance, with test.c the above example,
$ gcc -E test.c
...
/ / / word word word
/ / / word word word
(I have elided some irrelevant chatter above the output we're interested in.)
If there is a way around this, you are most likely to find it in the doxygen manual. There might, for instance, be configuration options that teach it that certain macros should be understood to define symbols, and what symbols those are, and what documentation they should have.

C code after preprocessor

This is an exercise taken by a book. The question is what is the output of this code.
This code prints always "N is undefined", but I don't know why. The command "#undef N" is after the function f. Then, why the output is always "N is undefined"?
#define N 100
void f(void);
int main(void)
{
f();
#ifdef N
#undef N
#endif
return 0;
}
void f(void)
{
#if defined(N)
printf("N is %d\n", N);
#else
printf("N is undefined\n");
#endif
}
The point of this exercise is to demonstrate that preprocessor's control flow is completely separate from the control flow of your program.
#if/#undef directives are processed in the order that they appear in the text of your program. They are processed only once at compile time; the decision to define or undefine a preprocessor variable cannot be reconsidered at runtime.
That's why the fact that f executes before #if/#undef line of the main is irrelevant. You can change the output of this program only by moving f to a position in file before main.
If you run the compiler with the -E flag (for gcc at least) it'll show you what the code you're actually compiling is.
You'll see that the preprocessor doesn't follow the code execution - it performs its actions in the order that they appear in the file.
Then the compiler takes the resulting code and f just has the one call to printf in it that says N isn't defined.
The C preprocessor goes through your code line by line. As such, it is wrong to assume the #undef happens after the function f() because of the function call. Instead, it happens before your definition of function f().
To understand this, you have to distinguish between the preprocessor (line by line) and the control flow (follows function calls).
Because the preprocessors instructions run in the "physycal" order, line after line.
Think about it something is executed before actual compilation, in a such way your code be clear, only with plain C code for the compiler.

simple script or commands to *substitute* stray "\\n" with "\n"

alright, i understand that the title of this topic sounds a bit gibberish... so i'll try to explain it as clearly as i can...
this is related to this previous post (an approach that's been verified to work):
multipass a source code to cpp
-- which basically asks the cpp to preprocess the code once before starting the gcc compile build process
take the previous post's sample code:
#include <stdio.h>
#define DEF_X #define X 22
int main(void)
{
DEF_X
printf("%u", X);
return 1;
}
now, to be able to freely insert the DEF_X anywhere, we need to add a newline
this doesn't work:
#define DEF_X \
#define X 22
this still doesn't work, but is more likely to:
#define DEF_X \n \
#define X 22
if we get the latter above to work, thanks to C's free form syntax and constant string multiline concatenation, it works anywhere as far as C/C++ is concerned:
"literal_str0" DEF_X "literal_str1"
now when cpp preprocesses this:
# 1 "d:/Projects/Research/tests/test.c"
# 1 "<command-line>"
# 1 "d:/Projects/Research/test/test.c"
# 1 "c:\\mingw\\bin\\../lib/gcc/mingw32/4.7.2/../../../../include/stdio.h" 1 3
# 19 "c:\\mingw\\bin\\../lib/gcc/mingw32/4.7.2/../../../../include/stdio.h" 3
# 1 "c:\\mingw\\bin\\../lib/gcc/mingw32/4.7.2/../../../../include/_mingw.h" 1 3
# 32 "c:\\mingw\\bin\\../lib/gcc/mingw32/4.7.2/../../../../include/_mingw.h" 3=
# 33 "c:\\mingw\\bin\\../lib/gcc/mingw32/4.7.2/../../../../include/_mingw.h" 3
# 20 "c:\\mingw\\bin\\../lib/gcc/mingw32/4.7.2/../../../../include/stdio.h" 2 3
ETC_ETC_ETC_IGNORED_FOR_BREVITY_BUT_LOTS_OF_DECLARATIONS
int main(void)
{
\n #define X 22
printf("%u", X);
return 1;
}
we have a stray \n in our preprocessed file. so now the problem is to get rid of it....
now, the unix system commands aren't really my strongest suit. i've compiled dozens of packages in linux and written simple bash scripts that simply enter multiline commands (so i don't have to type them every time or keep pressing the up arrow and choose the correct command successions). so i don`t know the finer points of stream piping and their arguments.
having said that, i tried these commands:
cpp $MY_DIR/test.c | perl -p -e 's/\\n/\n/g' > $MY_DIR/test0.c
gcc $MY_DIR/test0.c -o test.exe
it works, it removes that stray \n.
ohh, as to using perl rather than sed, i'm just more familiar with perl's variant to regex... it's more consistent in my eyes.
anyways, this has the nasty side effect of eating up any \n in the file (even in string literals)... so i need a script or a series of commands to:
remove a \n if:
if it is not inside a quote -- so this won't be modified: "hell0_there\n"
not passed to a function call (inside the argument list)
this is safe as one can never pass a single \n, which is neither a keyword nor an identifier.
if i need to "stringify" an expression with \n, i can simply call a function macro QUOTE_VAR(token). so that encapsulates all instances that \n would have to be treated as a string.
this should cover all cases that \n should be substituted... at least for my own coding conventions.
really, i would do this if i could manage it on my own... but my skills in regex is extremely lacking, only using it in for simple substitutions.
The better way is to replace \n if it occurs in the beginning of line.
The following command should do the work:
sed -e 's/\s*\\n/\n/g'
or occurs before #
sed -e 's/\\n\s*#/\n#/g'
or you can reverse the order of preprocessing and substitute DEF_X with your own tool before C preprocessor.

gcc c error: expected ')' before numeric constant

Hi I have been trying to port LWIP to a new arm device. When compiling the code i get the error message:
"lwip/lwip-1.4.0/src/include/lwip/memp_std.h:35:23: error: expected ')' before numeric constant"
When I go to this file this and below this several similar macros is what I find on that line:
LWIP_MEMPOOL(RAW_PCB, MEMP_NUM_RAW_PCB, sizeof(struct raw_pcb), "RAW_PCB")
If I remove the need for this macro with a define to deactivate the RAW functionality the error moves to the next LWIP_MEMPOL() macro.
The define it seems to want to put a ')' in front of is defined as this:
#define MEMP_NUM_RAW_PCB 1
The RAW_PCB is not defined but is "combined with MEMP_" to create an element in an enum.
I have tried to complie the whole ting with the -E option to get human redable object files and see if i can find any open '(' around the areas where MEMP_RAW_PCB apears and the substitution of MEMP_NUM_RAW_PCB to 1 but I have not found any by manual inspection yet.
Are there any suggestions on what can be going on here or what more I can do or look for to find the cause of the error?
I should maybe add that so far I don't call on any of the LWIP code from main() or any of the functions used in main().
I solved it with:
#ifndef MEMP_STD_H_
#define MEMP_STD_H_
... // memp_std.h codes ...
#endif //#ifndef MEMP_STD_H_
The error suggests you have unbalanced parentheses. The code you have provided thus far does not indicate where this problem is, but since ) is expected, it probably means the error is actually in the lines of code preceding the one you have shown.
Examine the code preceding the line you have shown (perhaps after using gcc -E) to check to see if all the parentheses are balanced.
If you're defining it with the dash-D option, it will generate the 1 by default, e.g.:
gcc -D 'MAX(A,B) ((A) < (B)? (B) : (A))' ...
Generates:
#define MAX(A,B) ((A) < (B)? (B) : (A)) 1
And you get the error: expected ‘)’ before numeric constant message at the line where the substitution occurs because of that trailing 1, e.g.:
int maxval = MAX(i,j);
// generates: int maxval = ((i) < (j)? (j) : (i)) 1;
Conversely, if you use the assignment operator to explicitly define the value, it will generate it the way you expected. E.g.:
int maxval = MAX(i,j);
// generates: int maxval = ((i) < (j)? (j) : (i));

look for a API/function which is like assert() without abort in C

the assert() function can print the error and where the error happens, but it will also abort the function.
I want to have a assert() function without aborting. I only hope to print the error, the name of the file where error happens, etc.
is there such a API or source snippets in C?
thanks!
Cunit has an assert that will either be fatal (quits) or not (will continue).
http://cunit.sourceforge.net/doc/writing_tests.html#tests
So if I'm reading this right, your question is basically "How do I print the file name and line number?"
Simple, use
__FILE__, __LINE__
If you want, create your own macro like
#define MY_ASSERT(x) if(x) printf("Assertion! Line: %d File: %s \n", __LINE__, __FILE__)
THere are other useful predefined macros too. http://gcc.gnu.org/onlinedocs/gcc-3.1/cpp/Standard-Predefined-Macros.html
First of all lets see what assert is
the documentation says
assert() is implemented as a macro
and now lets see the actual implementation of assert
something like this
((x = 0) ? (void) (0) : __assert_fail ("x = 0", "t.c", 9, __PRETTY_FUNCTION__));
well in your case you may not want the expression below
__assert_fail ("x = 0", "t.c", 9, __PRETTY_FUNCTION__))
now what we can do here now is
something like this
#define MY_ASSERT(expr) \
(expr ? (void) (0) : printf("something"));
int main(int argc, char *argv[]){
MY_ASSERT(argc == 0)
}
hope this helps
This is called an exception, and it is a construct that is available in languages like C++ with an optimized implementation. With exceptions, you can exit any function anywhere you want, and end up anywhere up the call stack, without a single memory leak. Of course, this will require you code to be exception safe.
In C, you'd need to hack around with goto, setjmp, longjmp, which would basically be a bad version of C++ exceptions.
See e.g. http://en.cppreference.com/w/cpp/language/exceptions

Resources