53 years by my count. Did something relevant happen in 1960? Maybe author is alluding to B?
Recursive macros in C, demystified (once the ugly crying stops)
81–90 of 90 posts
Re: Recursive macros in C, demystified (once the ugly crying stops)
#82The behavior of C macros is actually described by a piece of pseudocode from Dave Prosser and it is not in the standard: * https://www.spinellis.gr/blog/20060626/ * https://www.spinellis.gr/pubs/jrnl/2006-DDJ-Finessing/html/S... * https://gcc.gnu.org/legacy-ml/gcc-prs/2001-q1/msg00495.html
This is the best explanation I've seen so far: https://marc.info/?l=boost&m=118835769257658&w=2
Re: Recursive macros in C, demystified (once the ugly crying stops)
#83Earlier quoted context omitted.
I wonder how you like my vector: https://godbolt.org/z/97YGrbP9s (note, experimental library, but I see no fundamental issue).
that is amazing... I don't write C so I didn't dig too deep, but kudos for getting anything to work. Now you use need great documentation so we can figure out how to use it and what it supports without digging into the macros themselves. (tests would be good too, but maybe they are there and I didn't see them).
Re: Recursive macros in C, demystified (once the ugly crying stops)
#84Earlier quoted context omitted.
I played with a lot of preprocessor implementations and did my own (redesigned chibicc's expansion algorithm), not many of them even have paint-blue behavior exactly right (the standard text is vague, to me it was more "matching GCC's" than "conforming to standard").
That's interesting. I agree with you that the standards text is pretty vague. I think that's why other attempts to show how to do this kind of thing don't get deep enough on the semantics, and why I adopted a "try it and see" strategy. I do try to avoid this kind of thing unless necessary, so I don't have experience as to where the different compilers will fall down on different corner cases. I'd find it very interes…
[1] https://www.scs.stanford.edu/~dm/blog/va-opt.html#c-macro-ov...
Re: Recursive macros in C, demystified (once the ugly crying stops)
#85Can I use this technique to expand MACRO(a,b,c,…) into something like F(a,b,c…); G(a,b,c…)?
Okay, finally found some time to provide you with a fully annotated example of your original ask here, assuming you wanted to transform the arguments passed to F into IDs, and the arguments passed to G into strings (as seemed to be the case from the rest of the thread). https://c.godbolt.org/z/6zqx1dsn3 I've fully annotated it, so it might seem like more than it is. About half the macro code is from the original arti…
Re: Recursive macros in C, demystified (once the ugly crying stops)
#86Earlier quoted context omitted.
That's interesting. I agree with you that the standards text is pretty vague. I think that's why other attempts to show how to do this kind of thing don't get deep enough on the semantics, and why I adopted a "try it and see" strategy. I do try to avoid this kind of thing unless necessary, so I don't have experience as to where the different compilers will fall down on different corner cases. I'd find it very interes…
Examples from this article[1] frequently yield inconsistent result across implementations, particularly the ones that put parenthesis in macros, it is indeed a very corner-case-y thing to do though. [1] https://www.scs.stanford.edu/~dm/blog/va-opt.html#c-macro-ov...
I've noticed many people are still building on systems where the compiler is a bit older, and defaults to C11, even if it has support for C17, so perhaps that's the problem?
Re: Recursive macros in C, demystified (once the ugly crying stops)
#87> C has many advantages that have led to its longevity (60 years as perhaps the most important language). 53 years by my count. Did something relevant happen in 1960? Maybe author is alluding to B?
Re: Recursive macros in C, demystified (once the ugly crying stops)
#88Earlier quoted context omitted.
At least you can implement things like vector in C++. I challenge anyone to write the same for C macros. (this is semi-serious - if you get a full generic STL for C that is usable that would prevent a large number of bugs. The implementation can be as bad as you want, so long as the user API is not too difficult. Though note that I'm not a C programmer and so if there are better ways someone else is doing this I'm no…
I wonder how you like my vector: https://godbolt.org/z/97YGrbP9s (note, experimental library, but I see no fundamental issue).
Some of the stuff you're doing in the library I've also been doing recently, and has been working well, like using the string of the type name to allow for run-time checking of, what I would called "mixed" data (your variadic type). I've also done the same basic thing as your option type in a way that's closer to your sum type than the maybe type.
But I'd had enough problems trying to get something like your vector actually working that I'd given up, but I think now I'll build something at some point over the holidays. I think as I'm coming up to speed on the history of changes to _Generic that's partially due to the attempts before I had a C23 compiler, but even then, your code there is impressive-- both clear and clever.
I also have enough stuff passed via pointer that the option type for me needed to handle pointers differently-- I basically just have run-time code that does the null check at run time when set. At that point, there doesn't really need to be an 'is_set' type flag.
Re: Recursive macros in C, demystified (once the ugly crying stops)
#89Earlier quoted context omitted.
At least you can implement things like vector in C++. I challenge anyone to write the same for C macros. (this is semi-serious - if you get a full generic STL for C that is usable that would prevent a large number of bugs. The implementation can be as bad as you want, so long as the user API is not too difficult. Though note that I'm not a C programmer and so if there are better ways someone else is doing this I'm no…
I wonder how you like my vector: https://godbolt.org/z/97YGrbP9s (note, experimental library, but I see no fundamental issue).
Same thing would be for making it much easier to statically lay out fixed caches implemented via hashing, instead of inserting into them at start-up, etc.
Re: Recursive macros in C, demystified (once the ugly crying stops)
#90Ideally the result of processing a macro ("macro-replacement") would contain no further macros. But in order to disallow infinite loops during processing of a macro, the C standard specifies that names of macros that would be processed recursively are instead painted blue ("marked") so as to never be processed.
The technique in the article hinges on the fact that macro-replacement, as specified in the C standard, allows not only for the result of macro-replacement to contain these marked do-not-process macros, but also unmarked unprocessed macros. Specifically, such an unmarked unprocessed macro is a functional macro arising after processing a macro with an empty definition that separates the functional macro's name from its arguments.
The technique for achieving recrusive macros is to introduce a functional macro whose definition is the would-be recursive macro, and to replace each occurence of the name of the would-be recursive macro in its own defintion with the functional macro interrupted by an macro with an empty definition.
The result is an unmarked unprocessed recursive macro. Processing such a recursive macro, e.g. by including it as an argument to a macro, corresponds to taking one step of the recursion. Thus any pre-determined finite number of steps of a recurisvely defined macro can be performed.
For example, the would-be recursive macro of the article
#define _COUNT_ONE(x, ...) + 1 _COUNT_TOP(__VA_ARGS__)
#define _COUNT_TOP(...) __VA_OPT__(_COUNT_ONE(__VA_ARGS__))
#define COUNT(...) (_COUNT_TOP(__VA_ARGS__) + 0)
becomes
#define EMPTY
#define _COUNT_INDIRECT() _COUNT_ONE
#define _COUNT_ONE(x, ...) + 1 _COUNT_TOP(__VA_ARGS__)
#define _COUNT_TOP(...) __VA_OPT__(_COUNT_INDIRECT EMPTY()(__VA_ARGS__))
#define COUNT(...) (_COUNT_TOP(__VA_ARGS__) + 0)
To process the COUNT(...) macro 5 times, allowing it to count up to 5 variable arguments, nest it 5 levels deep as an argument to a macro.
#define EVAL1(...) __VA_ARGS__
#define EVAL5(...) EVAL1(EVAL1(EVAL1(EVAL1(EVAL1))))
EVAL5(COUNT(1,2,3))