The C Preprocessor is a fairly simple-minded text substitution program, and I don't think it is going to be able to do what you need and produce compile-time constant strings if it is absolutely impossible to change the DEFAULT_NETWORK_TOKEN_KEY
macro.
Transforming the 'array' notation is particularly difficult — in fact, the precondition of not changing the array defining macro probably means it is impossible.
If it is possible to define new macros and redefine DEFAULT_NETWORK_TOKEN_KEY
so that it produces the same value as it always did, then you can get to the result you want.
To illustrate, note that you can write:
#define x { 3, 45, 5, 49}
#define f4(a,b,c,d) #a " - " #b ":" #c "/" #d
#define y(z) f4(z)
y(x)
When pre-processed, that produces:
"{ 3" " - " "45" ":" "5" "/" "49}"
Note that the braces are parts of the argument strings. Now, if you can do:
#define DEFAULT_NETWORK_TOKEN_KEY_VALUES 3, 6, 5, 100
#define DEFAULT_NETWORK_TOKEN_KEY { DEFAULT_NETWORK_TOKEN_KEY_VALUES}
(where I'm preserving your asymmetric spacing, though I don't think that's really necessary), then you can use:
#define NETTOKENKEY(a,b,c,d) "[" #a "." #b "." #c "." #d "]"
#define GENNETTOKENKEY(z) NETTOKENKEY(z)
GENNETTOKENKEY(DEFAULT_NETWORK_TOKEN_KEY_VALUES)
to get the string "[3.6.5.100]" (for the values in my example).
Getting rid of the space between the v
and the 1.4
is relatively easy:
#define STRINGIZER(arg) #arg
#define STR_VALUE(arg) STRINGIZER(arg)
#define AP_VERSION_STR "#AP started v" STR_VALUE(_VERSION_)
AP_VERSION_STR
Piecing these together yields:
#define AP_NETVERSION_STR "#AP started " \
GENNETTOKENKEY(DEFAULT_NETWORK_TOKEN_KEY_VALUES) \
" v" STR_VALUE(_VERSION_)
static const char version[] = AP_NETVERSION_STR;
If you want a '\r'
on the end, add "\r"
to the end of the AP_NETVERSION_STR macro definition. String concatenation is very useful!
But, this is predicated on being able to 'change' the definition of DEFAULT_NETWORK_TOKEN_KEY
so that it is amenable to being formatted like this. Without that change, I don't think you can do it.
Testing is necessary!
#define _VERSION_ 1.4
#define DEFAULT_NETWORK_TOKEN_KEY_VALUES 3, 6, 5, 100
#define DEFAULT_NETWORK_TOKEN_KEY { DEFAULT_NETWORK_TOKEN_KEY_VALUES}
#define NETTOKENKEY(a,b,c,d) "[" #a "." #b "." #c "." #d "]"
#define GENNETTOKENKEY(z) NETTOKENKEY(z)
GENNETTOKENKEY(DEFAULT_NETWORK_TOKEN_KEY_VALUES)
#define STRINGIZER(arg) #arg
#define STR_VALUE(arg) STRINGIZER(arg)
#define AP_VERSION_STR "#AP started v" STR_VALUE(_VERSION_)
AP_VERSION_STR
#define AP_NETVERSION_STR "#AP started " \
GENNETTOKENKEY(DEFAULT_NETWORK_TOKEN_KEY_VALUES) \
" v" STR_VALUE(_VERSION_)
AP_NETVERSION_STR
When run through gcc -E
, the mildly sanitized output (blank lines and #line
controls removed) is what we need:
"[" "3" "." "6" "." "5" "." "100" "]"
"#AP started v" "1.4"
"#AP started " "[" "3" "." "6" "." "5" "." "100" "]" " v" "1.4"