what does __p in unsigned int __p mean?

Hello frenz,

I was searching for driver code for SMC91C111 and came across some code in uboot. the following is a piece of code from that the smc91c111.h file. #define SMC_outb(d,r) ({ word __d = (byte)(d); \ word __w = SMC_inw((r)&~1); \ __w &= ((r)&1) ? 0x00FF : 0xFF00; \ __w |= ((r)&1) ? __d

Reply to
Anil
Loading thread data ...

Since it is tight with the variable name it can't be. It is simply to make it a bit more unique.

--
42Bastian
Do not email to bastian42@yahoo.com, it's a spam-only account :-)
 Click to see the full signature
Reply to
42Bastian Schick

hi, I could have considered it that way but the following piece of code does not support that idea.

#define SMC_inb(p) ({ \ unsigned int __p = (unsigned int)(SMC_BASE_ADDRESS + (p)); \ unsigned int __v = *(volatile unsigned short *)((__p) & ~1); \ if (__p & 1) __v >>= 8; \ else __v &= 0xff; \ __v; })

the significance of the underscore in the last line of macro is still unclear.

Reply to
Anil

It looks as if the underscores have been put there by the code's author to ensure that the (local) variable names don't conflict with other similar, single letter, variable names that might be present in application code.

Andrew

Reply to
Andrew Jackson

You seem to have a particlarly ugly case of writing inline functions. The code on both functions is complicated enough to need an own function each.

In the SMC_inb() function, there is only a variable '__v', no variable called 'v'.

Probably, the purpose of the last statetment is to get the value of __v as the return value of the function.

The function finds the 16-bit word for the register at offset p in the SMC controller register block, reads the 16-bit register and splits the desired byte and returns it.

A function for similar use:

static unsigned char SMC_inb(int p) { volatile unsigned short *wordaddress; unsigned int value;

wordaddress = (volatile unsigned short *) (SMC_BASE_ADDRESS + (p & ~1));

value = *wordaddress;

if (p & 1) return (unsigned char)(value >> 8);

return (unsigned char)(value & 0xff); }

If you're using GCC, the effect of the original macro can be achieved by declaring the function above with the 'inline' qualifier (and it's much cleaner).

Similar considerations apply to the output function/macro.

--
Tauno Voipio
tauno voipio (at) iki fi
 Click to see the full signature
Reply to
Tauno Voipio

What is "that way" in this context ?

This declares a variable called __p, which is available only in this {} block.

and calculate and store the address of the register into __p

Make that address even, read a 16 bit word (in little endian format) from the hardware register and store it into the local variable __v.

Reply to
Paul Keinanen

It has none --- for starters because there *is* no variable named "p" nor "__p" in the above.

The __ has no significance of its own. It's not even a syntactical element of its own: it's just a part of the variable names "__d" and "__w", put there to avoid collisions of these names with variables used in functions that might invoke this macro. It's essentially a "no user-serviceable parts inside" sticker.

Frankly, if you don't understand this much of C, I don't think you should be messing around with system header files yet.

--
Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
Reply to
Hans-Bernhard Broeker

Unfortunately identifiers beginning __ are reserved by the compiler for any purpose (as are _ followed by an uppercase letter).

--
Paul Black                        mailto:paul.black@oxsemi.com
Oxford Semiconductor Ltd          http://www.oxsemi.com
 Click to see the full signature
Reply to
Paul Black

Indeed: someone not following the standard!

Andrew

Reply to
Andrew Jackson

That's not necessarily true. Remember this macro was found in a hardware-specific header file of Uboot. Uboot is infrastructure code, just like the OS on a more conventional hosted implementation. So its headers could justifiably be considered part of the C implementation for normal programs, which would allow it to use the reserved names.

--
Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
Reply to
Hans-Bernhard Broeker

In C, identifiers beginning with two underscores or an underscore followed by a uppercase letter are reserved for the implementation (compiler), thus are not to be declared by the programmer. There are other reserved identifiers as well. This way the implementor can declare symbols guaranteed not to collide with user code which conforms to the standard.

That said, the above code uses a non-standard extension in which a bracketed list of statements is contained within an expression, which should make declared variables strictly local to the declaration, obviating the need for variables in the implementor's name space.

Thad

Reply to
Thad Smith

"Anil" wrote in news:1126244062.200998.107180 @g49g2000cwa.googlegroups.com:

It is strictly to make it far less likely that the names will conflict with variable names created by users of the function macro.

--
Richard
Reply to
Richard

How so?

There is none. It's just a name. It happens to start with underscores to minimize the chances that it will collide with another name.

--
Grant Edwards                   grante             Yow!  Darling, my ELBOW
                                  at               is FLYING over FRANKFURT,
 Click to see the full signature
Reply to
Grant Edwards

p and __p are two totally different expressions.

p is what the compiler will resolve each time the macro is "called". whereas __p is a stack allocated variable on the stack frame created by the macro. By watching the code it is clear that the variable __p is a copy of what p might be at compile-time.

There is NOTHING special about the underscores preceding the declared temp variable as Grant Edwards points out.

Cheers

Grant Edwards wrote:

Reply to
rTrenado

On 8 Sep 2005 22:15:33 -0700, "Anil" wrote in comp.arch.embedded:

Actually, the identifiers defined with leading double underscores in this macro, and the other macro you quote in another post, are absolutely unnecessary inclusions by someone whose understanding of the C language standard is somewhat weak.

As others have pointed out, all identifiers beginning with two underscores, or an underscore followed by an upper case letter, are reserved for the implementation. That means the compiler, its headers, and its libraries, not a 3rd party application like uboot, no matter how "system" it seems to be.

But regardless of whether or not uboot should be using identifiers of this pattern is rather immaterial, because they are absolutely unnecessary in this context.

Both macros open a block that contains their variable definitions and code. That block establishes its own scope, so if they happened to define a variable, say 'x', that exists in an outer scope, the 'x' defined inside the block completely hides the 'x' in the outer scope.

--
Jack Klein
Home: http://JK-Technology.Com
 Click to see the full signature
Reply to
Jack Klein

Some compilers will warn about a variable hidden in outer scope; perhaps that is what the author was trying to prevent.

--
John W. Temples, III
Reply to
John Temples

Which would be a bad thing if the user supplied 'x' as the macro parameter.

Paul

Reply to
Paul Keinanen

Wrong. For a macro like this, they're absolutely necessary to keep the macro universally usable. They avoid a name conflict between the actual macro argument and the variables created inside the macro body.

Which will explode nicely into your face as soon as somebody invokes the macros with the parameter being named 'x', too.

But all this is somewhat beside the point: those macros are 100% evil. Creating local variables inside a macro is a gold-plated invitation for nasty problems. This should really be done either in an inline function. Failing that (some compilers may not support inline), it should be re-written as a single-statement macro: no local variables, no strange compiler-specific extensions to allow a block to return a value.

--
Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
Reply to
Hans-Bernhard Broeker

Good point.

Sorry, I can't agree with the 100% evil. They are simply the implementation for access functions in a custom header. Yes, they use extensions that aren't strictly required, but that's OK for a specific compiler+target, which this is. You might consider it an invitation, but nothing bad happens if you simply use the code as is. Its worse aspect, i think, is that it sets a poor example for the average Joe programmer peeking under the hood, but it works.

Thad

Reply to
Thad Smith

... until the day the makers of some (maybe: the) compiler for the platform this header is supposed to be used with decide to exercise the privilige granted to them by the standard and put

#define __p some very strange stuff here

in one of the system headers, or even make __p an inescapable predefined macro.

Basically, what those macros try to do is impossible to achieve in C. You unavoidably risk colliding either with user-space names, or with names reserved to the compiler. The latter adds causing undefined behaviour to the bill --- that's as close to 100% evil as you can possibly be and still get a compilable program.

It would be quite a bit more sensible to use prefixed names like "uboot__private_p" for such cases. Those are in user-land, so they avoid undefined behaviour. And if they ever do collide with the third-party code, you can plausibly deny responsibility for the consequences. You could even go ahead an put a phrase like "All identifiers beginning with uboot__ are belong to us!" in the documentation, to strengthen your case.

--
Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
Reply to
Hans-Bernhard Broeker

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.