I need to code an automata, and I bumped into this old need of a computed goto (ala fortran4 :) )
I need to code this in a portable ansi-C.
I want to stay away from the "don't do that", away from longjmp/setjmp, away from embedded ASM(), away from non ansi-C extensions.
Does anyone know how to do this?
Like I said in a comment, despite your plea to not use anything other than goto, standard C has nothing to offer.
Design your state appropriately, and pass a pointer to it to the handler functions for them to modify. That way the handler can setup the next function to call. Something like this:
struct state;
typedef void state_func(struct state*);
#define NULL_ACTION_ADDRESS (state_func*)0
struct state {
state_func *action;
int value1;
int value2;
};
#define INIT_STATE { initial_action, -1, -1}
state_func initial_action;
state_func handle_a;
state_func handle_b;
int main(void) {
struct state s = INIT_STATE;
while(s.action != NULL_ACTION_ADDRESS) {
(*s.action)(&s);
}
return 0;
}
void initial_action(struct state* ps) {
ps->action = &handle_a;
}
void handle_a(struct state* ps) {
ps->action = &handle_b;
}
void handle_b(struct state* ps) {
ps->action = NULL_ACTION_ADDRESS;
}
I think I got it, I reviewed all the various threads on this topics and I started to agree that that there where no ansi C solutions, yet I found an way to do this that fit my needs. All solution I saw on stackoverflow where based on the idea to 'get' the addr of a label, then stuff it into a table, then index this table and goto, this is both with gcc/clang non ansi extension or the asm extension.
I gave it another try tonite and got this.
In an include file named cgoto.h I have this
#ifndef CGOTO_dcl
#define CGOTO_dcl(N) int CGOTO_##N
#define CGOTO_LE(l) l,
#define CGOTO_LG(l) case l:goto l;
#define CGOTO_def(N) \
if(0){typedef enum {N(CGOTO_LE)} N; CGOTO_##N: switch(CGOTO_##N)\
{N(CGOTO_LG) default:CGOTO_##N=0;goto CGOTO_##N;}}
#define CGOTO(N,i) CGOTO_##N=i; goto CGOTO_##N;
#endif
The usage is like this
#include <stdio.h>
#include "cgoto.h"
int f(int x)
{ //...
CGOTO_dcl(gtb);
//...
# define gtb(L) L(l0) L(l1) L(l2)
CGOTO_def(gtb);
//...
CGOTO(gtb,x);
l0: printf("error\n");
return(0);
//...
l1:return(11);
l2:return(22);
l3:return(33);
}
int main()
{ printf("f(0)=%d f(1)=%d f(2)=%d,f(3)=%d\n",f(0),f(1),f(2),f(3));
}
In this implementation, the cost of jumping is 2 jumps and a switch() that is sequential, then optimisable. So this is reasonably performing compared to function call, a little less performing than &&label solution at the cost of portability.
With this implementation, labels code (semantic actions) are not confined into a switch() so we can implement jump table with shared semantic actions.
The index is assigned to a local goto_table_index, making the function using this re-entrant (multi threadable), though the optimiser can remove altogether this temp assignment.
The 1st Label in a jump table is 'special' (on this implementation) in the sense that it catch index out of bound, the first label is the 'error' label. If your code is bullet proof, i.e there is no way you can get an out of bound index, then the 1st label has not particular semantic.
CGOTO_dcl(gtb);
Declare the jump table 'gtb' own index as an auto integer so reentrant.
# define gtb(L) L(l0) L(l1) L(l2)
CGOTO_def(gtb);
Define a jump table named gtb, labels can be entered/removed with L(label) so it is pretty convenient, and this is symbolic by nature, i.e the labels are name with a meaning. With #define as a switch() case, labels addition/suppression often mean #define renumbering that is a problem.
The #define can be separated from the CGOTO_def() but it make more sense to keep them together. The CGOTO_def() though got to be placed after the function local declaration as it contain a switch() that is code.
A uniq jump table can be used in multiple place in the function.
CGOTO(gtb,x);
...
CGOTO(gtb,y);
A label may be entered in multiple jump table
# define gtb1(L) L(l0) L(l1) L(l2)
CGOTO_def(gtb1);
# define gtb2(L) L(l0) L(l4) L(l5)
CGOTO_def(gtb2);
So all in all, this may looks ugly, yet, the jump table definition though 2 line the #define and the CGOTO_def() is manageable and practical, semi performant, and portable.
We are back to FTN4 :)
Cheers,
Phi
Related
I work with old C project and should make there several changes
It has lots of macros....
The function calls are defined there as
#define myFunc(arg) myBaseFunc(arg)
bool myBaseFunc is a function, actually there are several myBaseFunc
(its a kind of polymorphism)
I need to add some check of arguments correctness to myFunc
Actually the project has :
#define checkArg(arg) {\
// lot of code
}
I can`t change checkArg implementation
1) I thought to //
/*It is not correct if I do `if(myFunc(arg))`*/
#define myFunc(arg)\
checkArg(arg)\
myBaseFunc(arg)
2)I thought to
/*It is better...but compiler doesn`t like code block `{}` inside`if(myFunc(arg))`*/
#define myFunc(arg)(\
checkArg(arg),\
myBaseFunc(arg))
Is there a workaround for this case
A possible solution is to check the arg before it is passed to the base function. That works however only if there's only a single argument.
#define myFunc(arg) myBaseFunc(checkArg(arg))
Your checkArg function(s) must be changed so that they return the same value they got as parameter, e.g.
int checkArg(int value) {
... test stuff
return value;
}
I think It is possible like this, but you need to know argument type:
int main_check_function(void* data) { // <= this type need to be type of functions.
checkArg(data);
return (myBaseFunc(data));
}
#define myFunc(arg) (main_check_function(arg))
Although as I told, it is limited to knowing type. I just added a function to project to check your code by running checkArg() and then running myBaseFunc(). This approach is simple, but it has that big drawback.
On linux's kernel we can find this piece of code in linux/sched.h, when I saw it some doubts came to my mind:
Why using define to create functions? Why not using the normal return-type function-name(par1, par2) {} style?
What is the point with the do {} while(0)?
#define set_special_state(state_value)
do {
unsigned long flags;
raw_spin_lock_irqsave(¤t->pi_lock, flags);
current->state = (state_value);
raw_spin_unlock_irqrestore(¤t->pi_lock, flags);
} while (0)
#endif
This isn't a "function", it's a preprocessor macro.
Sometimes one must use macros to do things that the C language itself doesn't support (usually generating code). This doesn't look like one of those cases though, and should probably be a static inline function. Pergaps the Git history would explain why it is the way it is.
do { ... } while (0) is a common method for swallowing the semicolon which follows a call to a C-function-looking macro like this one.
Functions are usually preferrable because they provide type checking and aren't error prone to things like double evaluation, but macros are more powerful, since they allow you to work at the text/token level.
do{}while(0) is to make an invoked macro grammatically behave like a void-returning function call.
You might think a plain pair of curlies would do that but that doesn't work
with if-else
#define macro_with_curlies() { }
if(x) macro_with_curlies(); else { }
//expands to: if(x) { }; /*else is illegal after the semicolon*/ else { }
I was wondering if it is possible to create something like an array of macros.
I've implemented the following code which works:
struct led_cmds_
{
ioport_pin_t *commands[LED_COUNT] ;
};
struct led_cmds_ the_led_cmd_ ;
void populate() {
the_led_cmd_.commands[0] = SPECIFICPIN(0);
}
and in main:
int main(void)
{
//.....
populate();
LED_On(the_led_cmd_.commands[0]);
}
SPECIFICPIN(x) is macro defined as:
#define SPECIFICPIN(X) (LED##X##_PIN)
What I was hoping for is a way to is a way to do something like this:
#define ioport_pin_t* ARR_LED[LED_COUNT] \
for (int j = 0; j < LED_COUNT; j++) ARR_LED[j] = SPECIFICPIN(j);
and then only need to call the following when I want to use the specific pin
LED_On(ARR_LED[some_number])
when I try to do that I get an ARR_LED undeclared (first use in this function) error.
When I try to call SPECIFICPIN(x) where x is an int iterator in a for loop for example, I get an error saying something like 'LEDx_PIN' undeclared...
You need to work on your terminology. An array of macros is not possible. Macros are no data type, but rather pure text replacement before your program is actually compiled.
I guess " populate an array using macros " is what you want to do. But it is not possible to do that in a compile-time loop - What you seem to want to achieve with your ioport_pin_t macro attempt. Macros do not have the capability to expand to more instances of text elements than you have initially given. There is no such feature as looping at compile time through macro expansions and do repetitive expansion of macros.
Your for loop loops at run-time, while the macro is being expanded at compile-time. Once you have made yourself aware what is done by the preprocessor what is done by the compiler, and what is done at run-time by the finished program, you will see that will not work.
Something like
#define P(X) {(LED##X##_PIN)}
ioport_pin_t *commands[LED_COUNT] = {
P(0), P(1), P(2),......}
#undefine P
Would be the closest thing possible to what you seem to want. Note the main use of the pre-processor is not to save you typing effort - You would be better off using copy & paste in your editor, achieve the same thing and have clearer code.
An array as tofro's answer is the way to go. However in cases that couldn't be solved simply with an array then there's another way with switch
#define SPECIFICPIN(X) (LED##X##_PIN)
void setpin(int pin, int value)
{
switch (pin)
{
case 1:
SPECIFICPIN(1) = value;
doSomething(); // if needed
break;
case x: ...
default: ...
}
}
It's common practice in C to use:
#define FOO() do { /* body */ } while (0)
While this is fine, it's also possible to do:
#define FOO() { /* body */ }((void)0)
{...}((void)0) has many of the same benefits: you can't accidentally merge logic, and a ; is required at the end of the line, so odd expressions like this don't go by un-noticed: FOO() else {...}.
The only difference I've noticed is it means you need to use braces in if-statements.
if (a)
FOO();
else
BAR();
Must be written as:
if (a) {
FOO();
} else {
BAR();
}
Other then this quirk, it seems to work well, preventing the same kinds of problems do/while method is typically used for.
Are there any significant differences between the 2 methods?
Said differently, if you see a code-base using {...}((void)0), are practical reasons to switch to using do{..}while(0), besides the one difference already noted?
The practical difference is exactly what you pointed out.
The do { ... } while (0) idiom means that the macro can be used in any context that requires a statement.
Your suggested idiom { ... } ((void)0) can be used safely in most contexts that require an expression -- but it can fail if it's used in an unbraced if statement.
I can think of no good reason to use an unfamiliar idiom that almost always works, when there's a well known idiom that always works.
One difference is you can use break with #define FOO() do { /* body */ } while (0) but not with #define FOO() { /* body */ }(void)0.
Let's say you are inside a function, say hello(), and doing something in #define FOO() do { /*some device operation */ } while (0) but some error occurred so you no longer want to proceed with that device but there are other statements in function hello() you want to execute, let's say for another device.
So if you use second statement then you will do return most probably which will exit out of hello() but if you use the first statement you can happily break and do some operation in same function hello() for another device.
Being a C novice I would like to hear what Macro "define"s developers are using. I've been thinking about putting these in a header to skip verbosity I've become used to:
#define TS_ typedef struct {
#define _TS(x) } x;
#define I(x)_ { int i; for ( i = 1; i <= x; i++ ) {
#define _I } }
Can I add \n \t etc within these macros? As I would like to pass on my sourcecode minus the extra include:
#define TS_ typedef struct {\n
#define _TS(x) } x;\n
#define I(x)_ { int i;\n\tfor ( i = 1; i <= x; i++ ) {\n
#define _I \t}\n}\n
Would these work?
ie: Can I use the proprocessor to replace my sourcecode with my personal include to formatted source without the include ?
Links to good preprocessor tips and tricks also appreciated.
Before you get started, do not use macro names that begin with an underscore - these are reserved for compiler and standard library writers, and must not be used in your own code.
Additionally, I would say that the macros you suggest are all very bad ideas, because they hide from the reader what is going on. The only justification for them seems to be to save you a very small amount of typing. Generally, you should only be using macros when there is no sensible alternative. In this case there is one - simply write the code.
You can put whitespace in by escaping the newline
#define SOMETHING whatever\
This is part of the macro
But as others have said it's not really a great way to to do this.
It would be much better to look into editor macros so you could type the shortcut and have the editor expand it.
You are headed into a wrong path. DO NOT make up your own cpp directives that are unfamiliar to others - this will make your code hard to understand, and at some point maintain.
Try to find some good C code to read - good C code does not use these things, for a good reason.
DON'T DO IT. Nobody else will be able to read your code.
As a cautionary example, check out Steve Bourne's original sources for the Bourne shell, where he used macros to write the code in a kind of pidgin Algol style.
You could do this, but this sort of "personal language" is not generally used in the C world, especially if you expect anybody else to read your code in the future.
If you're doing this just for yourself, then feel free to #define whatever you want, but expect that once you start working with (or for) anybody else, you won't be able to continue using this sort of thing.
Using C macros unnecessarily can lead you into a world of pain, especially if you attempt to use it to expand code. There are uses for C macros, but this is not it.
Edit: I realize that my answer is tangential to your question, but I thought I should mention this since you say you are a C novice. Search for "C macro pitfalls" to get a full list of reasons why not to use macros. It's been previously discussed here.
In general, I strongly agree with the other respondents who tell you not to define your own macros purely for the sake of saving typing. The obfuscation is not worth it. Also, the particular macros you suggest are heinous. However, in Stroustrup's 1st Ed, he does something I rather like (sometimes):
#define Kase break; case
I became accustomed to the Python elif construct, so I often define the following:
#define elif(test) else if(test)
My purpose in doing this isn't to reduce typing, it's to keep indentation logical while maintaining consistent code width (I don't let my code go wider than 80 characters). I say this because to me this...
if(...) ...
else if(...) ...
else ...
...should be...
if(...)
{
...
}
else
if(...)
{
...
}
else
{
...
}
With my macro this becomes:
if(...)
{
...
}
elif(...)
{
...
}
else
{
...
}
It is always better to pass the loop variable to the macro.
A block - a macro has certain optimization problems. All compilers do not guarantee an optimized obj code for the "block scope" variables.
for example, the following code, when compiled with out any optimization options to gcc, prints two separate addresses for &i. And the same code when compiled with -O2 option will print the same address in both the blocks.
{
int i;
printf("address of i in first block is %u\n", &i);
}
{
int i;
printf("address of i in sec block is %u\n", &i);
}
Naming the language constructs appropriately makes the code more readable.
I like your idea, if you put it in the following way.
#define GREEN 1
#define YELLOW 2
#define RED 3
# define NUM_COLORS 3
#define COLOR_ITER (color,i) \
for(i=GREEN, color = colors[i]; \
i < NUM_COLORS; \
color = colors[++i])
int colors[3] = {GREEN, YELLOW, RED};
int
fun () {
int j;
color_t clr;
COLOR_ITER(clr, j) {
paint(clr);
}
}
Here, regardless of how it is written, the macro, COLOR_ITER, by its name, implies that you are looping for all available colors and doing "something" for each color. And this is a very easy-to-use macro.
And your quesion
Can I use the proprocessor to replace my sourcecode with my personal include to formatted source without the include ?
As everybody explained preprocessor will not help you in this case.
You can use your editor commands to automatically format your code, as you type it.