Macro equivalence with nested macros in C - c

The following is taken from pngconf.h of libpng:
libpng version 1.6.3 - July 18, 2013
Copyright (c) 1998-2013 Glenn Randers-Pehrson
My question is, give the following macro preprocessors:
#ifndef PNG_FUNCTION
#define PNG_FUNCTION(type, name, args, attributes) attributes type name args
#endif
#ifndef PNG_EXPORTA
#define PNG_EXPORTA(ordinal, type, name, args, attributes)\
PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args), \
extern attributes)
#endif
#ifndef PNG_EXPORT_TYPE
#define PNG_EXPORT_TYPE(type) PNG_IMPEXP type
#endif
#ifndef PNGAPI
#define PNGAPI PNGCAPI
#endif
#define PNGCAPI __cdecl
#ifndef PNGARG
#define PNGARG(arglist) arglist
#endif
are the following equivalent?
#ifndef PNG_EXPORTA
#define PNG_EXPORTA(ordinal, type, name, args, attributes)\
PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args), \
extern attributes)
#endif
is equivalent to:
#ifndef PNG_EXPORTA
#define PNG_EXPORTA(ordinal, type, name, args, attributes)\
extern attributes PNG_EXPORT_TYPE(type) (PNGCAPI name) PNGARG(args)
#endif
which is finally equivalent to:
#ifndef PNG_EXPORTA
#define PNG_EXPORTA(ordinal, type, name, args, attributes)\
extern attributes PNG_IMPEXP type __cdecl name arglist
#endif

#OliverCharlesworth wrote:
Most compilers allow you to see the preprocessor output. For example, run GCC with the -E flag.
#lurker wrote:
On first glance, I would say the answer to the question of equivalence is "no". I think you inserted some commas where they didn't exist when you translated the PNG_FUNCTION macro. And welcome to the SO code parsing service. ;)
#JonathanLeffler wrote:
you have extern attributes, where you should have just extern attributes.

Related

Define a preprocessor macro with preprocessor comands

I'm using often a syntax like
#ifdef __cplusplus
extern "C"
#endif
void myCFunc();
so I tried to make a macro to have a syntax like
CFUNC(void myCFunc());
I'm not relly sure if it's something that can be done (can preprocessor execute its freshly generate code?)
The failed idea was something like
#define CFUNC(ARGUMENT) \
#ifdef __cplusplus \
extern "C" \
#endif \
ARGUMENT;
Is there a way make a macro that generates code for the preprocessor?
Thanks
You can define two different macros depending on the context:
#ifdef __cplusplus
#define CFUNC(ARGUMENT) extern "C" ARGUMENT;
#else
#define CFUNC(ARGUMENT) ARGUMENT;
#endif
CFUNC(FOO)
However, the common way to do this is the following. It includes the braces and can be used both in definitions and declarations.
#ifdef __cplusplus
#define EXTERN_C extern "C" {
#define EXTERN_C_END }
#else
#define EXTERN_C
#define EXTERN_C_END
#endif
EXTERN_C
void foo(void) { ... }
EXTERN_C_END
You can inverse #define and #ifdef:
#ifdef __cplusplus
#define CFUNC(ARGUMENT) \
extern "C" \
ARGUMENT;
#else
#define CFUNC(ARGUMENT) ARGUMENT;
#endif

#ifdef inside a #define?

I'm initializing an array of structures with the help of a define like this:
#define FLAGCODE(name) { #name, MNT_ ## name }
struct {
const char *name;
uint64_t flag;
} flagcodes[] = {
FLAGCODE(ACLS),
FLAGCODE(ASYNC),
...
This works nicely, and now I'd like to add a check, whether each flag (such as MNT_ACLS) is defined without inserting an #ifdef and #endif for each symbol by hand?
That is, I want the macro FLAGCODE(name) to expand into (an equivalent of):
#ifdef MNT_ ##name
{ # name, MNT_ ##name },
#endif
Exempli gratia, if name is NOATIME, the code shall become:
#ifdef MNT_NOATIME
{ "NOATIME", MNT_NOATIME },
#endif
Yes, I realize, that this would mean double pass through preprocessor, and so is unlikely to be possible -- without a custom code-generator... But still...
There is a solution but highly not recommended! You could do funny things with C-preprocessor (cf. Macro to replace nested for loops and links in the question). But I repeat it: Don't do it. It is a cpp abuse.
In two words, you have to create your own #ifdef with macro. In the code below, ISDEF is an "operator" to check if the flag is defined and #if has been redefined: IIF (To understand, all explanations are here: https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms)
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
#define COMMA ,
#define IIF(c) PRIMITIVE_CAT(IIF_, c)
#define IIF_0(t, ...) __VA_ARGS__
#define IIF_1(t, ...) t
#define CHECK_N(x, n, ...) n
#define CHECK(...) CHECK_N(__VA_ARGS__, 0,)
#define PROBE(x) x, 1,
#define ISDEF(x) CHECK(PRIMITIVE_CAT(ISDEF_, x))
#define ISDEF_ PROBE(~)
#define FLAGCODE(name) IIF(ISDEF(name))({ #name COMMA MNT_ ## name }COMMA)
#define ACLS
#define FLAGDEFINED
int main()
{
struct {
const char *name;
uint64_t flag;
} flagcodes[] = {
FLAGCODE(ACLS)
FLAGCODE(ASYNC)
FLAGCODE(FLAGDEFINED)
FLAGCODE(FLAGNOTDEFINED)
...
You could also do a list with your flags (cf. MAP part in http://jhnet.co.uk/articles/cpp_magic).
Enjoy but do not go overboard with preprocessor.
Following the very good comment of Chris Dodd,
1 : This tricks works if the flag is define as empty (#define FLAGDEFINED). It does not work with, for example, #define FLAGDEFINED 1 or #define FLAGDEFINED xxx.
2 : CPP_ prefix has been added and name is changed by CPP_FLAG
#define CPP_PRIMITIVE_CAT(CPP_a, ...) CPP_a ## __VA_ARGS__
#define CPP_COMMA ,
#define CPP_IIF(CPP_c) CPP_PRIMITIVE_CAT(CPP_IIF_, CPP_c)
#define CPP_IIF_0(CPP_t, ...) __VA_ARGS__
#define CPP_IIF_1(CPP_t, ...) CPP_t
#define CPP_CHECK_N(CPP_x, CPP_n, ...) CPP_n
#define CPP_CHECK(...) CPP_CHECK_N(__VA_ARGS__, 0,)
#define CPP_PROBE(CPP_x) CPP_x, 1,
#define CPP_ISDEF(CPP_x) CPP_CHECK(CPP_PRIMITIVE_CAT(CPP_ISDEF_, CPP_x))
#define CPP_ISDEF_ CPP_PROBE(~)
#define CPP_FLAGCODE(CPP_FLAG) CPP_IIF(CPP_ISDEF(CPP_FLAG))({ #CPP_FLAG CPP_COMMA MNT_ ## CPP_FLAG }CPP_COMMA)
#define ACLS
#define FLAGDEFINED

What does a #define directive without an argument do?

On Apple's opensource website, the entry for stdarg.h contains the following:
#ifndef _STDARG_H
#ifndef _ANSI_STDARG_H_
#ifndef __need___va_list
#define _STDARG_H
#define _ANSI_STDARG_H_
#endif /* not __need___va_list */
#undef __need___va_list
What do the #define statements do if there's nothing following their first argument?
There are sort of three possible "values" for an identifier in the preprocessor:
Undefined: we don't know about this name.
Defined, but empty: we know about this name, but it has no value.
Defined, with value: we know about this name, and it has a value.
The second, defined but empty, is often used for conditional compilation, where the test is simply for the definedness, but not the value, of an identifier:
#ifdef __cplusplus
// here we know we are C++, and we do not care about which version
#endif
#if __cplusplus >= 199711L
// here we know we have a specific version or later
#endif
#ifndef __cplusplus // or #if !defined(__cplusplus)
// here we know we are not C++
#endif
That's an example with a name that if it is defined will have a value. But there are others, like NDEBUG, which are usually defined with no value at all (-DNDEBUG on the compiler command line, usually).
They define a macro which expands to nothing. It's not very useful if you intended it to be used as a macro, but it's very useful when combined with #ifdef and friends—you can, for example, use it to create an include guard, so when you #include a file multiple times, the guarded contents are included only once.
You define something like:
#define _ANSI_STDARG_H_
so that, later you can check for:
#ifdef _ANSI_STDARG_H_

Defining a Function in C

I am new to C and have a maybe n00b question ...
Until now I thought a function is always defined as:
return_type function_name(function_arg_1 type, function_arg_1_name, ...)
But now I have found a C header file where a function is looking like this:
TIDY_EXPORT int TIDY_CALL tidyDetectedHtmlVersion( TidyDoc tdoc );
Which is more a:
i_do_not_know return_type i_do_not_know function_name(function_arg_1 type, function_arg_1_name)
The whole source can be seen at http://tidy.sourceforge.net/docs/api/tidy_8h-source.html
So what is "TIDY_EXPORT" and "TIDY_CALL" doing?
TIDY_EXPORT int TIDY_CALL are just modifiers to your function.
The function name is tidyDetectedHtmlVersion, it takes one parameter (tdoc) of type TidyDoc and returns an int.
TIDY_EXPORT is a macro defined in the platform.h file which defined as
00492 #if defined(_WIN32)
00493
00494 #if (defined(_USRDLL) || defined(_WINDLL)) && !defined(TIDY_EXPORT)
00495 #define TIDY_EXPORT __declspec( dllexport )
00496 #endif
which allows you to export the function when compiling the file as a library (e.g. dll)
As for TIDY_CALL, it's defined in the same file as:
00498 #ifndef TIDY_CALL
00499 #ifdef _WIN64
00500 # define TIDY_CALL __fastcall
00501 #else
00502 # define TIDY_CALL __stdcall
00503 #endif
00504 #endif
See this question for an explanation What is __stdcall?
TIDY_EXPORT and TIDY_CALL are macros. They are defined in platform.h.
In platform.h you have
#if (defined(_USRDLL) || defined(_WINDLL)) && !defined(TIDY_EXPORT)
#define TIDY_EXPORT __declspec( dllexport )
#endif
#ifndef TIDY_CALL
#ifdef _WIN64
#define TIDY_CALL __fastcall
#else
# define TIDY_CALL __stdcall
#endif
#endif
C is straightforward ... until macros get involved! Anything in ALL CAPS is probably a macro, which is a symbol which gets replaced with other text before compilation. That text can be defined to be anything, including an empty string. Luckily Doxygen has been used, so you can view the documentation http://tidy.sourceforge.net/docs/api/tidy_8h.html.
The file that is included:
#include "platform.h"
which you can read here, defines the macro.
For more info on macros in all their glory, read this.
TIDY_EXPORT is #defined as __declspec(dllexport) on Windows, to allow the function to be exported when Tidy is compiled as a DLL.
TIDY_CALL is a macro that expands to a platform-specific calling convention.
Both of these features are nonstandard extensions to the C language (which is why they are abstracted behind conditionally-compiled macros).
They are some macro defined somewere in your library. Do a text search in all the files and you probably finfd what they exactly defines. By using some paranormal diagnosys strategy I guess that TIDY export is some decoration to export the function from the library ( ie declspec(dllexport) in MS compilers, and TIDY_CALL specify the calling convention ( ie stdcall, pascal, and so on )
TIDY_CALL and so on are (It's my guess, but it's very probably) macros.
http://www.google.pl/search?sourceid=chrome&ie=UTF-8&q=macros+C%2B%2B#sclient=psy&hl=pl&source=hp&q=macros+C&aq=f&aqi=&aql=&oq=&pbx=1&fp=58c095358c87453c
They are macros, you can find them in the source code somewhere. TIDY_CALL for example is in platform.h
#ifndef TIDY_CALL
#ifdef _WIN64
# define TIDY_CALL __fastcall
#else
# define TIDY_CALL __stdcall
#endif
#endif

Possible to #if or #ifdef based on preprocessor-generated "thing"

I'm trying to engage in some C-preprocessor-only templating efforts in order to type-specialize some code. I've tried to boil it down a bit, so this example seems trivial and pointless, but the real challenge is getting the "include" blocking.
Say I have a "template" file, that gets #included from other source files that define T_ELEMENT_TYPE before including the template.
// Template file...
#ifndef T_ELEMENT_TYPE
#error #define T_ELEMENT_TYPE
#endif
#define PASTER(x,y) x ## y
#define EVALUATOR(x,y) PASTER(x,y)
#define SYMBOLNAME EVALUATOR(SymbolFor, T_ELEMENT_TYPE)
#ifndef SYMBOLNAMEISDEFINED
#define SYMBOLNAMEISDEFINED EVALUTOR(DEFINEDFOR, T_ELEMENT_TYPE)
int SYMBOLNAME(T_ELEMENT_TYPE arg)
{
// do something with arg
return 0;
}
#endif // Guard #ifdef
Then I want to include that template from multiple instantiation sites, but I only want the templated function to be generated ONCE per unique T_ELEMENT_TYPE (so as not to create duplicate symbols.) Like, say this:
// Template-using file...
#define T_ELEMENT_TYPE int
#include "Template.c"
#undef T_ELEMENT_TYPE
#define T_ELEMENT_TYPE float
#include "Template.c"
#undef T_ELEMENT_TYPE
#define T_ELEMENT_TYPE int
#include "Template.c"
#undef T_ELEMENT_TYPE
int someOtherFunc()
{
int foo = 42;
foo = SymbolForint(foo);
float bar = 42.0;
bar = SymbolForfloat(bar);
return foo;
}
So I'm looking for something I can use in the template code. I imagined it might look something like this (although this does not work):
// Template file...
#ifndef T_ELEMENT_TYPE
#error #define T_ELEMENT_TYPE
#endif
#define PASTER(x,y) x ## y
#define EVALUATOR(x,y) PASTER(x,y)
#define SYMBOLNAME EVALUATOR(SymbolFor, T_ELEMENT_TYPE)
#ifndef SYMBOLNAMEISDEFINED
#define SYMBOLNAMEISDEFINED EVALUTOR(DEFINEDFOR, T_ELEMENT_TYPE)
int SYMBOLNAME(T_ELEMENT_TYPE arg)
{
// do something with arg
return 0;
}
#endif // Guard #ifdef
This particular incantation blocks ALL multiple instantiations of the template, not just for different values of T_ELEMENT_TYPE.
Is there a trick I can use to get this effect? Or am I just off the C-Preprocessor reservation, so to speak?
I think you're off the reservation. The first "argument" to #define, the macro name, isn't subject to macro-expansion. So I don't think the preprocessor can define a different symbol according to the value of T_ELEMENT_TYPE. Neither can the preprocessor construct a "list" of already-seen types and check for existence in that.
So I think the include-guard will have to be outside the file:
#ifndef included_mytemplatefile_h_int
#undef T_ELEMENT_TYPE
#define T_ELEMENT_TYPE int
#include "mytemplatefile.h"
#define included_mytemplatefile_h_int
#endif
Alternatively, if your template file header only declares the function SymbolFor_int, instead of defining it, then multiple inclusion isn't harmful. You could have a normal include guard around the parts of the file that don't depend on the current value of T_ELEMENT_TYPE, including the definitions of PASTER, EVALUATOR, SYMBOLNAME. You'd need a separate template file containing definitions, which the program (rather than each translation unit) needs to have exactly once:
template_%.c :
echo "#define T_ELEMENT_TYPE $*" > $#
echo "#include \"mytemplatedefinitions.c\"" >> $#
Then add template_int.o to the list of files linked into your program.

Resources