Editing/Redefining a Constant String: Yes I'm aware of the contradiction - c-preprocessor

I am attempting to change a constant variables value, yes I am aware of the contradiction of what I am doing but there is a method to my madness.
You see I am writing in a language very similar to C/C++ called 4dm but it doesn't allow any code outside of functions so I am trying to overcome this by using pre-processor commands. The reason is so I can achieve a form of specialisation in the language. The first step of this involves being able to edit a constant string.
Even though this is a different language, the preprocessor operates in exactly the same way as C and C++ compilers:
#define MY_STR "abc"
#define CONCAT(s) \
#define TEMP MY_STR \ // store MY_STR in TEMP_STR
#undef MY_STR \ // undefine MY_STR
#define MY_STR TEMP s // redefine MY_STR so it contains the old value plus the new one
CONCAT(def)
printf("%s\n", MY_STR); // should hopefully print out "abc def"
The following is a simple attempt at concatenating a string but I get a compile error saying MY_STR is not defined any ideas how to fix this?
#define MY_STR abc
#define TEMP MY_STR
#undef MY_STR
#define MY_STR TEMP def
void test()
{
print(MY_STR);
}

In your first example, you're trying to expand a macro into a #define preprocessor command. You can't do that; the preprocessor produces C code (or whatever), and the various things that look like preprocessor directives in the macro expansion will actually not be preprocessor directives. That will produce an error, because # in a macro definition is the "stringify" operator, which must be followed by a macro parameter.
(Also, the \ must be at the end of the line. You can't follow it with a comment.)
In your second example, When you write:
#define TEMP MY_STR
that's exactly what it does: it defines the macro TEMP as having the value MY_STR (not the macro expansion of MY_STR, just the six-character token MY_STR.
After that, you
#define MY_STR TEMP def
That defines the macro MY_STR as the two tokens TEMP and def.
Then you expand MY_STR:
print(MY_STR);
which causes it to be replaced with TEMP def. The expansion is run through the macro processor again, which causes TEMP to be replaced with MY_STR. That's run through the macro processor again, but this time MY_STR is not expanded because you cannot expand a macro within an expansion of that macro. So this time it stays as MY_STR, and you end up with:
print(MY_STR def);
MY_STR is not defined (a macro is not a definition), so the compiler complains that MY_STR is not defined.

A good compiler will put a string constant in a block that will be marked as write protected, and any attempt to modify it will result in some kind of OS exception.
That's not what you're doing here though - you're defining a new string in terms of the old string. That would work in C and C++, and presumably works in your language as well.
Since you're defining your own language, you would know better than us how it will react!

About what you're trying to achieve with CONCAT, § 6.10.3.4 ¶3 of the C99 standard says (partial quote):
The resulting completely macro-replaced preprocessing token sequence is not processed as a preprocessing directive even if it resembles one

Related

C Macro expansion within a macro

While testing a C software, I'd like to use macros to generate function calls. Using codewarrior 5.2 (very old) compiler -because I don't have choice, I don't know if this is standard behavior.
in macros.h
#define RUNTEST(i) \
testcase_index = i; \
__PREFIX__##_testCase_##i()
in test_foo.c
#include "macros.h"
#define __PREFIX__ foo
RUNTEST(10);
Apparently __PREFIX__ is not expanded, and preprocessor generates a call to __PREFIX___testcase_10(), which of course will fail at linking time.
Copying everything in the same file doesn't seem to change anything.
Is there a simple way out?
Alternative
I also tried #define __PREFIX__() foo to force macro expansion. In that case, it almost works, and now generates foo _testcase_10() (with a space), which of course won't compile.
I've done a simplified version of your question here (without assigning to the testcase index):
.h:
#define PASTER(x, y) x##_testCase_##y
#define EVAL(x, y) PASTER(x, y)
#define RUNTEST(i) EVAL(__PREFIX__, i)
.c
#define __PREFIX__ foo
// whatever
RUNTEST(1);
Explanation:
From the C standard:
6.10.3.1 Argument substitution
After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place. A parameter in the replacement list, unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is replaced by the corresponding argument after all macros contained therein have been expanded. Before being substituted, each argument’s preprocessing tokens are completely macro replaced as if they formed the rest of the preprocessing file; no other preprocessing tokens are available.
So now that we have this, I'll walk through the expansion of RUNTEST(1):
EVAL(__PREFIX__, i)
PASTER(foo, 1)
foo##_testCase_##1
foo_testCase_1

Do function like macros need a mandatory parentheses? I am confused after referring the GCC cpp manual

Here is what confuses me:
To define a function-like macro, you use the same '#define' directive, but you put a pair of parentheses immediately after the macro name.
I believe this is to make the code stand out for people other than the author of the program. Like other rules of CAPS for macro names. But the following is where I get confused:
A function-like macro is only expanded if its name appears with a pair of parentheses after it. If you write just the name, it is left alone.
I disagreed instantly after reading it. And gcc -E verified that in the following code
#define FUNC display()
void display()
{
printf("Display\n");
}
int main()
{
FUNC;
return 0;
}
The pre-processed output shows the content of the main() function as expected:
int main()
{
display();
return 0;
}
So what am I missing here? The pre-processor is for tokenizing the source, the macro expansion is a token and the above code was processed that way, the pre-processor isn't supposed to check anything or verify anything, it just dumps tokens. In that case what is the gcc manual trying to convey.
I am learning C programming, so I might be misunderstanding it a great deal as it frequently happens, I searched for a proper explanation and finally resorted to asking here. Please help me with this.
When you define:
#define FUNC display()
FUNC is not a function-like macro; it is an object-like macro that expands to a function call.
A function-like macro looks like:
#define FUNC() display()
Now you must write FUNC() to invoke it. Or, more frequently, it will have arguments:
#define MIN(x, y) ((x) > (y) ? (x) : (y))
and that can be invoked with:
int min = MIN(sin(p), cos(q));
with cautions about the number of times the arguments are expanded.
See also getc() as macro and C standard library function definition. It includes the standard's explanation of why it is important that the simple name of a function-like macro without a following open parenthesis is not expanded, which is what the quote from the GCC manual is telling you.
When a function-like macro is defined, the open parenthesis must 'touch' the macro name:
#define function_like(a) …
#define object_like (…)
Because there's a space after object_like, the open parenthesis is part of the replacement text, not the start of an argument list. When the function-like macro is invoked, there may be spaces between the macro name and the argument list:
function_like (x) // Valid invocation of function_like macro.
However, if you wrote:
int (function_like)(double a) { return asin(a) + 2 * atanh(a); }
this is not an invocation of the function-like macro because the token after function_like is not an open parenthesis.
There are two kinds of macros. They differ mostly in what they look like when they are used. Object-like macros resemble data objects when used, function-like macros resemble function calls.
You may define any valid identifier as a macro, even if it is a C keyword. The preprocessor does not know anything about keywords. This can be useful if you wish to hide a keyword such as const from an older compiler that does not understand it. However, the preprocessor operator can never be defined as a macro, and C++'s named operators cannot be macros when you are compiling C++.

Function-like C macro without parentheses

I have encountered the following debug macro in an embedded device codebase:
extern void DebugPrint(uint8_t *s);
#define DEBUG_MSG(x) do { PRINT_CURRENT_TIME; \
DebugPrint x ; } while(0)
Since there are no parentheses around x in the macro body (at the DebugPrint x part), all calls to this macro (all over the codebase) add another set of parentheses around strings:
DEBUG_MSG(("some debug text"));
Is there any reason to do this? Does it simplify optimizing away these calls in release builds, or something like that? Or is it just plain nonsense?
I thought perhaps there would be additional overloads of DebugPrint with more arguments, but there are none.
Here's a theory:
The preprocessor parses the arguments of a macro expansion in a way that mimics the compiler's expression parsing. In particular it parses terms in parentheses as a single argument.
So the DEBUG_MSG author's intention might have been to enforce the use of parentheses.
This might make sense when the DebugPrint print function would actually be a printf style variadic function. You could call the function with a single string literal or with a variable number of arguments:
DEBUG_MSG(("reached this point in code"));
DEBUG_MSG(("value of x = %i", x));
But this is pure speculation. Can't you just ask the author?
I believe that no. Macros are replaced by the compiler, so they have nothing to do with execution speeds. This:
#define MACRO(x) do_something(x)
MACRO("test");
Is no different than this
#define MACRO(x) do_something x
MACRO(("test"));
Since the compiler will replace them both with the same output:
do_something("test");
which will then compile to produce the same object code.

Double slash comment substituition within a macro

I am developing a PIC MCU program on an ansi-compliant compiler (Microchip XC8).
There are two operation modes, determined via macros during compilation time.
So that I don't want to duplicate one function-like macro due to one line of code, I would like to know if there is any way to write a macro such as
#define FOO //
so that when FOO is substituted it will actually cancel the rest of the line.
Writing a function instead of a macro is out of the question because the delay generated by function calls would disrupt the tight timings of my program (around some microseconds).
You can't make a macro expand to comment out the line, no. // in a macro definition is a comment following the definition, it's not expanded, and IIRC there's a rule saying that you cannot construct a // using token-pasting. Even if you can, expanding it doesn't mean that the macro starts a comment. Basically, you don't get to change the comment syntax using macros.
You could do:
#if DO_NOTHING_MODE
#define FOO(ARG1)
#else
#define FOO(ARG1) ARG1
#endif
and use it like:
#define FUNCTION_LIKE_MACRO(ARG1, ARG2) \
required line; \
FOO(optional line;) \
Although a more common idiom is to design the macro to accept an expression as its argument, rather than a whole line:
#if DO_NOTHING_MODE
#define FOO(ARG1) ((void)0)
#else
#define FOO(ARG1) (ARG1)
#endif
and use it like FOO(optional line);
Either way, if the macro argument has commas in it, then the caller needs to enclose them in parentheses FOO((1,2)), although in C99 you can avoid that by making FOO a variadic macro:
#define FOO(...) (__VA_ARGS__)
You can use the #ifndef directive to achieve the same effect:
#ifndef FOO
your_line_of_code
#endif
EDIT: #SteveJessop made me see I didn't pay attention to this sentence of the OP "I don't want to duplicate one function-like macro due to one line of code". Here is what could be done in that case, if duplicating the function-like macro is not wanted:
// When FOO is defined, BLA in FUNC macro is a no-operation (null statement)
#ifndef FOO
#define BLA() a++
#else
#define BLA()
#endif
#define FUNC() \
BLA(); \
b++;
Comments are removed from the source before macro replacement occurs, so there's no way to define a macro exactly like that. However, it is certainly possible to pass an additional parameter into the macro to specify which code it should generate, or conditionally define the macro depending on the mode for which you are compiling.
#define FOO(...) __VA_ARGS__
And then use FOO(your code here) instead of FOO your code here in the macro.
If your platform doesn't have C99, you can instead use
#define FOO(x) x
and just make sure the argument doesn't contain a , not enclosed in ().

Can I substitute __func__ into an identifier name in a C macro?

I'd like to write a C macro which takes this:
int foo() {
MY_MACRO
}
and expands it to this:
int foo() {
_macro_var_foo++;
}
I've found that I can't use __func__, because that doesn't actually get expanded in the macro; it's treated by the preprocessor like a variable.
Is there some way to get this to work?
The preprocessor doesn't know about functions, just source files and line numbers. At that stage it's not performing syntactical analysis, just textual analysis and substitutions. That's why __func__ is a magical variable instead of a magical macro like __FILE__ and __LINE__.
In the C99 standard, __func__ is given a special new category of 'predefined identifier' (in section 6.4.2.2 Predefined Identifiers):
The identifier __func__ shall be implicitly declared by the translator as if,
immediately following the opening brace of each function definition, the declaration
static const char __func__[] = "function-name";
appeared, where function-name is the name of the lexically-enclosing function
This means that it is out of the scope of the C preprocessor, which is not aware of function boundaries or function names. Further, it would expand to a string, which makes it inappropriate for embedding into a variable name.
The GCC (4.4.1) manual says in section 5.43 (Function Names as Strings):
These identifiers [meaning __func__, __FUNCTION__ and __PRETTY_FUNCTION__] are not preprocessor macros. In GCC 3.3 and earlier, in C only, __FUNCTION__ and __PRETTY_FUNCTION__ were treated as string literals; they could be used
to initialize char arrays, and they could be concatenated with other string literals. GCC
3.4 and later treat them as variables, like __func__. In C++, __FUNCTION__ and __PRETTY_FUNCTION__ have always been variables.
If there was a way to get the function name into a preprocessor cleanly, then it is probable that the documentation here would have cross-referenced it, if it did not define it.
Technically, the answer to your question is "yes", there is "some way". But I think you already knew that, and it's true that you cannot deal with this at the macro preprocessor level.
Sure, there is always a way, you just might need a really long tape on that Turing Machine.
I think you already know this, but for the record you can get the overall result you want with:
#define MY_MACRO f_dictionary(__func__, ADDONE);
So now, you just need to implement f_dictionary and an ADDONE op for it.
You can do this using token concatenation.
#define MY_MACRO(baz) _macro_var_##baz++;
#define FUNC_WRAPPER(bar)\
int bar()\
{\
MY_MACRO(bar)\
}
FUNC_WRAPPER(foo)
The output from gcc -E:
int foo(){ _macro_var_foo++;}
Version dealing with argument lists using variadic macros and x macros:
#define MY_MACRO(baz) _macro_var_##baz++;
#define FUNC_DEF(ret_type,bar,...)\
ret_type bar(__VA_ARGS__)\
{\
MY_MACRO(bar)\
FUNC_CONTENTS\
}
#define FUNC_CONTENTS\
printf("Do some stuff\n", s1, s2);
FUNC_DEF(int, foo, char *s1, char *s2)
#undef FUNC_CONTENT

Resources