I found a new form of "#define" in C but I don't understand what it means. This is source code:
#define OPT_SET_INT(s, l, v, h, i) { OPTION_SET_INT, (s), (l), (v), NULL, \
(h), PARSE_OPT_NOARG, NULL, (i) }
This is the definition of OPTION_SET_INT:
enum parse_opt_type {
/* special types */
OPTION_END,
OPTION_ARGUMENT,
OPTION_GROUP,
OPTION_NUMBER,
/* options with no arguments */
OPTION_BIT,
OPTION_NEGBIT,
OPTION_COUNTUP,
OPTION_SET_INT,
OPTION_SET_PTR,
OPTION_CMDMODE,
/* options with arguments (usually) */
OPTION_STRING,
OPTION_INTEGER,
OPTION_CALLBACK,
OPTION_LOWLEVEL_CALLBACK,
OPTION_FILENAME
};
It is in parse-option.h in this repository:
https://github.com/git/git
Thanks.
There's nothing special about this whatsoever. Everything after the macro name (and parenthesis) gets plopped in-place verbatim, with the exception of the macro parameters, which are replaced.
In this case, the macro is used to populate one entry in an array of struct option.
E.g. In some C file you might have:
struct option options[] = {
OPT_SET_INT(foo, bar, snap, crackle, pop),
OPT_SET_INT(somethingelse, runningout, offake, names, forthis),
};
which becomes:
struct option options[] = {
{ OPTION_SET_INT, foo, bar, snap, NULL, crackle, PARSE_OPT_NOARG, NULL, pop },
{ OPTION_SET_INT, somethingelse, runningout, offake, NULL, names, PARSE_OPT_NOARG, NULL, forthis},
};
(note the \ in the macro definition is escaping the newline, so that the definition can span multiple lines).
See GCC Macro Expansion for more information.
Related
In this Modern C video there's a trick that allows to postpone execution of a code until the block/scope exits. It's used as follows:
int main()
{
int foo=0, bar;
const char *etc = "Some code before defer";
defer(profile_begin(), profile_end())
{
/* Some code, which will be automatically
* preceded by call to profile_begin() and
* followed by run of profile_end().*/
foo++;
bar = 1;
}
etc = "Some code after defer";
foo = bar + 1;
}
Implementation from the video:
#define macro_var_line(name) concat(name, __LINE__)
#define defer(start,end) for( \
int macro_var_line(done) = (start,0); \
!macro_var_line(done); \
(macro_var_line(done) += 1), end)
It's pretty simply implemented. What might be confusing is the macro_var_line(name) macro. Its purpose is to simply ensure that a temporary variable will have a unique, "obfuscated" name by adding current line number to it (of where defer is called).
However the problem is that one cannot pass code to start snippet that declares new variables, because it is pasted in the for() comma operator that uses int type (the int macro_var_line(done) = …). So it's not possible to, eg.:
defer(FILE *f = fopen("log.txt","a+"), fclose(f))
{
fprintf(f,"Some message, f=%p",f);
}
I would want to have such macro, capable of declaring new vars in start snippet. Is it achievable with standard C99, C11 or maybe some GCC extensions?
UPDATE: I've found a solution utilizing GCC nested functions. Basically, the { bblock } that's following the defer() macro becomes nested function body. And it's possible to forward declare the nested function and invoke it from before the block, i.e.:
#define defer(start,end) \
auto void var_line(routine) (void); \
start; \
/* Invoke above predeclared void routine_123(void) function */ \
var_line(routine)(); \
end; \
/* Define the nested function */ \
void var_line(routine) (void)
UPDATE2: Here's an elegant version which:
runs first leading statements as start and the last one as the end code,
runs the very first statement in its own for()/declarative space,
runs the block properly via an if(cond == 0) check/block start up.
#define defer(...) \
for (int var_line(cond) = 0; var_line(cond) == 0; ) \
for (FIRST_ARG(__VA_ARGS__); var_line(cond) == 0; ) \
for (SKIP_LAST_ARG(SKIP_FIRST_ARG(__VA_ARGS__)); \
var_line(cond) == 0; \
var_line(cond) += 1 ) \
for (int var_line(cond_int) = 0; \
var_line(cond_int) <= 1; \
var_line(cond_int) += 1 ) \
if (var_line(cond_int) == 1) \
{ \
LAST_ARG(__VA_ARGS__); \
} else if (var_line(cond_int) == 0)
As I expressed in comments, my recommendation is to avoid using such a thing in the first place. Whatever your video might have said or implied, the prevailing opinion among modern C programmers is that macro usage should be minimized. Variable-like macros should generally represent context-independent constant values, and function-like macros are usually better implemented as actual functions. That's not to say that all macro use must be avoided, but most modern C professionals look poorly on complex macros, and your defer() is complex enough to qualify.
Additionally, you do yourself no favors by trying to import the style and idioms of other languages into C. The common idioms of each language become established because they work well for that language, not, generally, because they have inherent intrinsic value. I advise you to learn C and the idioms that C programmers use, as opposed to how to write C code that looks like Go.
With that said, let's consider your defer() macro. You write,
However the problem is that one cannot pass code to start snippet that declares new variables
, but in fact the restriction is stronger than that. Because the macro uses the start argument in a comma expression (start,0), it needs to be an expression itself. Declarations or complete statements of any kind are not allowed. That's only indirectly related to that expression appearing in the first clause of a for statement's control block. (The same applies to the end argument, too.)
It may also be important to note that the macro expands to code that fails evaluate the end expression if execution of the associated statement terminates by branching out of the block via a return or goto statement, or by executing a function that does not return, such as exit() or longjmp(). Additionally, unlike with Go's defer, the end expression is evaluated in full after the provided statement -- no part of it is evaluated before, which might surprise a Go programmer. These are characteristics of the options presented below, too.
If you want to pass only the start and end as macro arguments, and you want to allow declarations to appear in start, then you could do this:
// Option 1
#define defer(start,end) start; for( \
int macro_var_line(done) = 0; \
!done; \
(macro_var_line(done) += 1), (end))
That moves start out of the for statement in the macro's replacement text, to a position where arbitrary C code may appear. Do note, however, that any variable declarations will then be scoped to the innermost containing block.
If you want to limit the scope of your declarations then there is also this alternative and variations on it, which I find much more straightforward than the original:
// Option 2
#define defer(start, end, body) { start; body end; }
You would use that like so:
defer(FILE *f = fopen("log.txt","a+"), fclose(f), // argument list continues ...
fprintf(f,"Some message, f=%p",f);
);
That is somewhat tuned to your particular example, in that it assumes that the body is given as a sequence of zero or more complete statements (which can include blocks, flow-control statements, etc). As you can see, it also requires the body to be passed as a macro argument instead of appearing after the macro invocation, but I consider that an advantage, because it facilitates recognizing the point where the deferred code kicks in.
You can simulate defer by using the __attribute__((cleanup(...))) feature of GCC and Clang. Also see this SO question about freeing a variable.
For instance:
// the following are some utility functions and macros
#define defer(fn) __attribute__((cleanup(fn)))
void cleanup_free(void* p) {
free(*((void**) p));
}
#define defer_free defer(cleanup_free)
void cleanup_file(FILE** fp) {
if (*fp == NULL) { return; }
fclose(*fp);
}
#define defer_file defer(cleanup_file)
// here's our code:
void foo(void) {
// here's some memory allocation
defer_free int* arr = malloc(sizeof(int) * 10);
if (arr == NULL) { return; }
// some file opening
defer_file FILE* fp1 = fopen("file1.txt", "rb");
if (fp1 == NULL) { return; }
// other file opening
defer_file FILE* fp2 = fopen("file2.txt", "rb");
if (fp2 == NULL) { return; }
// rest of the code
}
There is actually an effort in the standard's committee to standardize a defer feature. The paper proposal also comes with a reference implementation. The idea is to propose such a feature that may be implemented with the least compiler magic possible.
If all goes to plan, that feature could even be rebase on lambdas, if we get these into C23 in time.
You could use a trick from "Smart Template Container for C". See link.
#define c_autovar(declvar, ...) for (declvar, *_c_ii = NULL; !_c_ii; ++_c_ii, __VA_ARGS__)
Basically you declare a variable and hijack it's type to form a NULL pointer. This pointer is used as a guard to ensure that the loop is executed only once.
Incrementing NULL pointer is likely Undefined Behavior because the standard only allows to form a pointer pointing just after an object and NULL points to no object. However, it's likely run everywhere.
I guess you could get rid of UB by adding a global variable:
int defer_guard;
And setting the guard pointer to a pointer to defer_guard in the increment statement.
extern int defer_guard;
#define defer_var(declvar, cleanup) \
for (declvar, *_c_ii = NULL; \
!_c_ii; \
_c_ii = (void*)&defer_guard, cleanup)
It will work fine when invoked as:
defer_var(FILE *f = fopen("log.txt","a+"), fclose(f))
{
fprintf(f,"Some message, f=%p",f);
}
EDIT
Actually it is possible to derive a macro that will accept both expression and declaration as start. One must use two for loops instead of one.
#define DEFER(start, end) \
for (int _done = 0; !_done;) \
for (start; !(_done++); end)
int main() {
DEFER(FILE *f = fopen("log.txt","a+"), fclose(f)) {
fprintf(f,"Some message, f=%p", (void*)f);
}
FILE *f;
DEFER(f = fopen("log.txt","a+"), fclose(f)) {
fprintf(f,"Some message, f=%p", (void*)f);
}
return 0;
}
//#define newScope(string, scopeType) ({ \
intrprtr.scope = realloc(intrprtr.scope, intrprtr.scope_layer*sizeof(struct Scope)); \
strncpy(intrprtr.scope[intrprtr.scope_layer-1].string, (string), 255); \
intrprtr.scope[intrprtr.scope_layer-1].scopeType = (scopeType); \
})
//newScope(string, objScope); // <-- wanted to use macro but it doesn't work. I don't get it
intrprtr.scope = realloc(intrprtr.scope, intrprtr.scope_layer*sizeof(struct Scope));
strncpy(intrprtr.scope[intrprtr.scope_layer-1].string, string, 255);
intrprtr.scope[intrprtr.scope_layer-1].scopeType = objScope; // <-- this worked
I wanted the code to be more readable, so I used a macro to wrap us to code. I got the following error if I used the macro.
src/parser.c:114:30: error: no member named 'objScope' in 'struct Scope'
newScope(string, objScope); // <-- wanted to use macro but it doesn't work. I don't get it
~~~~~~~~~~~~~~~~~^~~~~~~~~
src/parser.c:109:48: note: expanded from macro 'newScope'
intrprtr.scope[intrprtr.scope_layer-1].scopeType = (scopeType); \
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
I did not get this error if I write the code explicitly.
Here is the declaration of intrprtr (in parser.h that I included in parser.c)
typedef struct{
FILE* file;
char cur_file_name[255];
int line_num;
struct Scope {
char string[255];
enum ScopeType { msgScope, objScope, codeBlock, func } scopeType;
}*scope;
int scope_layer;
}Intrprtr;
extern Intrprtr intrprtr;
According to my understanding, when I passed objScope to second argument of newScope macro, scopeType should expand to objScope. i.e.
intrprtr.scope[intrprtr.scope_layer-1].scopeType = objScope;
That no member error doesn't make any sense to me especially when intrprtr.scope[intrprtr.scope_layer-1].scopeType = objScope; actually worked. Can someone explain this for me? Thanks
In the replacement tokens intrprtr.scope[intrprtr.scope_layer-1].scopeType = (scopeType);, the scopeType token is replaced by the corresponding macro argument, objScope, both times it appears, but you want the first one to be a literal member name scopeType, not to be replaced.
Change the macro parameter name to something that is not otherwise used in the replacement tokens.
So you can dynamically define a method with its own name like this:
#define test(name) void name() { print("#name"); }
Then you can call it like:
test(foo);
foo();
I'm wondering though if you can make a "callback"-style form, like this:
#define test(name, body) void name() { print(#name); body(); }
Where it invokes a body that is defined as sort of a "block" like this:
test(dosomething, {
int a = add(1, 1);
assert(a == 2);
})
But more than that, I would like to pass a callback for async functions to say they are complete, like this:
test(dosomething, { (done)
int a = add(1, 1);
assert(a == 2);
done();
})
In addition, I am defining these outside of the main, so it would be defined in the same scope as a normal function. Because of that, the tests aren't going to automatically run. They need to be iterated over. As such, they probably need to be pushed into an array of some sort. So wondering how that could be done, if macros allow you to sort of capture stuff into an array, or to build up an enum one #define at a time.
#define test(name, body) void name() { \
print(#name); \
} \
\
TESTS[CURRENT_TEST++] = &name \ // push the test into a TESTS array.
So then in main you can iterate over them:
int
main() {
iterate over TESTS...
}
To summarize, I am wondering how to #define this at the file body level (i.e. not in main, but at the level of functions):
void afunction() { printf("Foo"); }
test(dosomething, { (done)
int a = add(1, 1);
assert(a == 2);
done();
})
void anotherfunction() { printf("Bar"); }
such that I can iterate over the tests in main.
This suggests blocks are possible in macros.
Looks like you're building some sort of mini test framework using the c preprocessor.
There's a caveat for the bodies; to the C preprocessor, curly brackets and square brackets are just tokens. Parenthesized expressions are recognized (i.e., parentheses are matched), and commas are recognized as delimiters. So for example, this macro invocation:
test(dosomething, { int a = add(1, 1); assert(a == 2); })
...has two arguments despite having two commas (because the second comma is "hugged" in a parenthesized set), but that's a bit misleading. This invocation:
test(dosomething, { enum { red, green, blue }; assert(red+1==green); })
...has four arguments: 1: dosomething, 2: { enum { red, 3: green, and 4: blue }; assert(red+1==green); }. If you're going to do this, you probably want to cover cases like this... there are basic strategies: (a) hug the body in parentheses (you can unwrap it in expansion), or (b) use variadic macros.
They need to be iterated over.
Sounds like a job for x-macros (below I'll be using the parameterized-macro flavor of x-macros).
But more than that, I would like to pass a callback for async functions to say they are complete, like this:
...you can't add an argument in the middle, but the braces don't have to be part of this (they don't help anyway, since the preprocessor ignores them). So for the above, we probably want to pick the hug option. That leaves your invocations looking like this:
test(dosomething, (int a=add(1,1); assert(a==2);), done)
However, since we're ripping the curly braces out, we can put them in arbitrary places in our expansion and do arbitrary things in between. Since I'm guessing you want the same kind of async thing going on, we could just put that thing in the expansion that generates the definition rather as an argument.
Here's roughly what it would look like, using a parameterized macro version of x-macros, and applying an async on expansion (using semaphores to demonstrate how arbitrary this could be):
#define APPLY_TEST_MACROS(macro) \
macro(test_add, (int a=add(1,1); assert(a==2); )) \
macro(test_sub, (int a=sub(5,2); assert(a==3); )) \
macro(test_mul, (int a=mul(3,4); assert(a==12); ))
#define UNWRAP(...) __VA_ARGS__
#define MAKE_ASYNC_SEM(NAME_, BODY_) \
void NAME_() { \
sem_wait(&test_sem_ctl); print(#NAME_); sem_post(&test_sem_ctl); \
UNWRAP BODY_ \
sem_wait(&test_sem_ctl); \
if (0==--tests_remaining) sem_post(&test_sem_done); \
sem_post(&test_sem_ctl); \
}
#define COUNT_TESTS(NAME_, BODY_) +1
sem_t test_sem_ctl;
sem_t test_sem_done;
void init_semaphores() {
sem_init(&test_sem_ctl, 0, 1);
sem_init(&test_sem_done, 0, 0);
}
// iterate over tests to count them
unsigned int tests_remaining = APPLY_TEST_MACROS(COUNT_TESTS);
// define the tests
APPLY_TEST_MACROS(MAKE_ASYNC_SEM)
...and so forth (I'm stopping here because the idea is to convey the idea, not code it for you). The x-macro layout allows you to iterate in the preprocessor, so you can do something like spawn a thread per test; you could also just use this same approach to build an array of test functions if, say, you want to feed your tests to a thread pool.
I would like to force a functions parameters to accept only specific definitions. For example, consider #define OUTPUT 1, #define INPUT 0 and void restrictedFunction(int parameter); .
How would I force restrictedFunction(int parameter) to accept only OUTPUT or INPUT?
I would also like to take into consideration that another definition may have the same value, for example, #define LEFT 1 and #define RIGHT 0.
So in this case I would like restrictedFunction(int parameter) to be able to accept only OUTPUT and INPUT specifically.
typedef enum { INPUT = 0, OUTPUT = 1 } IO_Type;
void restrictedFunction(IO_Type parameter) { ... }
It doesn't absolutely force the use of the values (the compiler will let someone write restrictedFunction(4)), but it is about as good as you'll get.
If you truly want to force the correct type, then:
typedef enum { INPUT = 0, OUTPUT = 1 } IO_Type;
typedef struct { IO_Type io_type } IO_Param;
void restrictedFunction(IO_Param parameter) { ... }
In C99 or later, you could call that with:
restrictedFunction((IO_Param){ INPUT });
This is a compound literal, creating a structure on the fly. It is not entirely clear that the structure type really buys you very much, but it will force the users to think a little and may improve the diagnostics from the compiler when they use it wrong (but they can probably use restrictedFunction((IO_Param){ 4 }); still).
What this means is that your restrictedFunction() code should be ready to validate the argument:
void restrictedFunction(IO_Type io_type)
{
switch (io_type)
{
case INPUT:
...do input handling...
break;
case OUTPUT:
...do output handling...
break;
default:
assert(io_type != INPUT && io_type != OUTPUT);
...or other error handling...
break;
}
}
You could use an enum.
typedef enum TrafficDirection { INPUT = 0, OUTPUT = 1 } TrafficDirection;
restrictedFunction(TrafficDirection direction);
of course, this isn't perfect. You can still pass any int to it as long as you use a cast.
restrictedFunction((TrafficDirection) 4);
You don't get quite as much protection as you might like, but you can do:
enum func_type { INPUT, OUTPUT };
void restrictedFunction( enum func_type parameter );
You can use a wrapper to validate the argument:
#define restrictedFunction(x) do { \
static_assert((x) == INPUT || (x) == OUTPUT); \
assert(!strcmp(#x, "INPUT") || !strcmp(#x, "OUTPUT")); \
restrictedFunction(x); \
} while(0)
Notes:
This assumes restrictedFunction() returns a void. If it returns a value which you actually use, you'll need something like gcc's compound statement http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html. Or--better--you can use BUILD_BUG_ON_ZERO (see What is ":-!!" in C code?), which I keep forgetting about, because it doesn't seem to work with C++.
The do ... while(0) is to "swallow the semi-colon"; not really relevant here.
static_assert() is a compile-time assert; there are many variants available. Here is a link to one, https://stackoverflow.com/a/9059896/318716, if you don't have your own handy.
assert() is the standard run-time assert.
With gcc 4.1.2, and my version of static_assert(), you can replace the run-time assert() with a compile-time assert when the two !strcmp()'s are replaced with ==; see example below. I haven't tested this with other compilers.
x is only used once in the macro expansion, since the first four references are only used at compile-time.
When your actually define your function, you'll have to add parentheses to disable the macro expansion, as in:
void (restrictedFunction)(int x){ ... }
Also, if your code has a special case (whose code doesn't?) where you need to call restrictedFunction() with the argument foo, you'll need to write:
(restrictedFunction)(foo);
Here is a complete example, which puts a wrapper around the standard library function exit():
#include <stdlib.h>
#define CONCAT_TOKENS(a, b) a ## b
#define EXPAND_THEN_CONCAT(a,b) CONCAT_TOKENS(a, b)
#define ASSERT(e) enum{EXPAND_THEN_CONCAT(ASSERT_line_,__LINE__) = 1/!!(e)}
#define ASSERTM(e,m) enum{EXPAND_THEN_CONCAT(m##_ASSERT_line_,__LINE__)=1/!!(e)}
#define exit(x) do { \
ASSERTM((x) == EXIT_SUCCESS || (x) == EXIT_FAILURE, value); \
ASSERTM(#x == "EXIT_SUCCESS" || #x == "EXIT_FAILURE", symbol); \
exit(x); \
} while(0)
int main(void) {
exit(EXIT_SUCCESS); // good
exit(EXIT_FAILURE); // good
exit(0); // bad
exit(3); // doubly bad
}
If I try to compile it, I get:
gcc foo.c -o foo
foo.c: In function 'main':
foo.c:17: error: enumerator value for 'symbol_ASSERT_line_17' is not an integer constant
foo.c:18: warning: division by zero
foo.c:18: error: enumerator value for 'value_ASSERT_line_18' is not an integer constant
foo.c:18: error: enumerator value for 'symbol_ASSERT_line_18' is not an integer constant
As already said by the headline, I get a compile error I seem to be unable to fix:
error: redefinition of 'tinygecko_notebook_get_type'
note: previous definition of 'tinygecko_notebook_get_type' was here
Where error points to this line (the first of this codes snippet):
GType
tinygecko_notebook_get_type (void)
{
static GType type = 0;
if (type == 0) {
static const GTypeInfo info = {
sizeof (TinygeckoNotebookClass), /* size of class struct */
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc)tinygecko_notebook_class_init, /* class_init */
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (TinygeckoNotebook),
0, /* n_preallocs */
(GInstanceInitFunc)tinygecko_notebook_init /* instance_init */
};
type = g_type_register_static (GTK_TYPE_NOTEBOOK, "TinygeckoNotebook", &info, 0);
}
return type;
}
and the note line points to the type setup
G_DEFINE_TYPE (TinygeckoNotebook, tinygecko_notebook, GTK_TYPE_NOTEBOOK);
Both snippets are located within the .c file (the note line is above the error line).
Help appreciated.. I am confused. Why should that gtk+ macro redefine a function which I have to setup for own gobject based class initalizer and finalizer (if they exist) (in this case based on GtkNotebook).
G_DEFINE_TYPE is a shortcut to allow you to avoid writing the get_type function. So you don't want to use G_DEFINE_TYPE if you're implementing the get_type function by hand.
In this case I don't notice anything special in your handcoded implementation, looks like just the usual boilerplate, so you can probably just delete it and use G_DEFINE_TYPE.
There are also variants of G_DEFINE_TYPE such as G_DEFINE_TYPE_WITH_CODE, G_DEFINE_ABSTRACT_TYPE, G_DEFINE_TYPE_EXTENDED, etc. that let you deviate from pure boilerplate a bit and still avoid doing it all by hand.