Page 1 of 1

making macros

Posted: Sat Jan 07, 2006 5:52 pm
by GLneo
hello all, ok i'm trying to turn this:

Code: Select all

void cli()
{
    asm("cli");
}
in to a macro:

Code: Select all

#define cli() { asm("cli"); }
or

Code: Select all

#define cli() { asm("cli") }
but this makes horrible errors i cant explain, like random undifinded veriables in c files that dont even use these functions!!!, help, thx

Re:making macros

Posted: Sat Jan 07, 2006 6:26 pm
by Rob
How about the C compiler you are using and which version? What do the errors say?

Re:making macros

Posted: Sat Jan 07, 2006 6:34 pm
by GLneo
djgpp, as for errors, when i include the semi-colin every file #includeing syslib.h(where i put the macro) goes crazy ??? ??? ???, but when i dont include the semi-colin i get a few "pause error befor '}' token" right after where i use this macro

Re:making macros

Posted: Sat Jan 07, 2006 6:36 pm
by Simon
Try it this way:

Code: Select all

#define cli() __asm volatile("cli\n")
Then use it like this:

Code: Select all

cli();

Re:making macros

Posted: Sat Jan 07, 2006 7:05 pm
by GLneo
thx, that worked, but what about more advanced function to macro convertions???:

Code: Select all

inline unsigned char inport(unsigned short port)
{
    unsigned char result;
    asm volatile("inb %1, %0" : "=a" (result) : "dN" (port));
    return result;
}

inline void outport(unsigned short port, unsigned char data)
{
    asm volatile("outb %1, %0" : : "dN" (port), "a" (data));
}

inline unsigned short inportw(unsigned short port)
{
    unsigned short result;
    asm volatile("inw %1, %0" : "=a" (result) : "dN" (port));
    return result;
}

inline void outportw(unsigned short port, unsigned short data)
{
    asm volatile("outw %1, %0" : : "dN" (port), "a" (data));
}

Re:making macros

Posted: Sun Jan 08, 2006 4:46 am
by Kemp
Well, the single line ones can be done using exactly the same method AFAIK

Re:making macros

Posted: Sun Jan 08, 2006 6:41 am
by Solar
The problem here is that your first cli() is a function, whereas your second cli() (the macro) is a statement.

Remember that macros are expanded by the preprocessor, i.e. before the compiler even gets to see the source.

If you define:

Code: Select all

#define cli() { asm("cli") }
and then write

Code: Select all

int main()
{
    foo();
    cli();
    bar();
}
that will get expanded to

Code: Select all

int main()
{
    foo();
    { asm("cli"); };
    bar();
}
It should be easy to see where the extra brackets and the additional semicolon could lead to troubles, e.g. in an [tt]if[/tt] statement.

A traditional way of encapsuling multi-line blocks in a macro (taking the first of your later examples) is the do-while-block:

Code: Select all

#define cli() do { asm("cli"); } while (0)
That way, the trailing semicolon gets "eaten" by the while-statement.

A macro cannot "return" a value, as it is not a function. With a bit of skill, you can make a macro evaluate to a certain value, which for all practical purposes is the same. Beware of side-effects, syntactical loopholes and multiple evaluation of parameters, though.

Bottom line, stay away from macros unless you really must use them.

Re:making macros

Posted: Sun Jan 08, 2006 9:48 am
by GLneo
ok, thx, so i put those functions in the syslib.h file but now every file that include that file and uses those functions gets multiple definition errors, is there a way to inline functions with out errors???, thx

Re:making macros

Posted: Sun Jan 08, 2006 10:24 am
by Kemp
Something to check... have you actually defined things more than once? Check the header files aren't included from more than one place as well.

Re:making macros

Posted: Sun Jan 08, 2006 11:02 am
by Solar
GLneo wrote: ok, thx, so i put those functions in the syslib.h file but now every file that include that file and uses those functions gets multiple definition errors, is there a way to inline functions with out errors???, thx
Read GCC manual on "inline" functions.