Thread: Strange macro, valid?

  1. #16
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Exit View Post
    Your implication was that a space had been omitted - that is not the case.
    It is the case. A space SHOULD have been there for clarity. It's not. Thus, everybody wonders what this "weird new syntax is."

    Consider, also, the actual requirement, which I have detailed.
    The requirement doesn't change the fact that there is NO SUCH MACRO SYNTAX as A(x)B(y). Running the macro through the preprocessor proves it definitively.

    The programmer was simply trying to be one of the "Three C's": Cute, Clever, or Confusing.

  2. #17
    Registered User ssharish2005's Avatar
    Join Date
    Sep 2005
    Location
    Cambridge, UK
    Posts
    1,732
    The only use of this type of macro

    Code:
    #define MMM_X(x)_Z(z)	(0x0C + (((x)-1)*3 + ((z)-1))*4)
    Which i can see is that; you call this macro with two name such as MMM_X and Z. What do you all tthink. Is there any other use of using that?

    ssharish2005

  3. #18
    Registered User
    Join Date
    Aug 2003
    Posts
    15
    There are no other macros defined in the header. All the other defines are either constant base addresses, register offsets or bit masks.

  4. #19
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Exit View Post
    There are no other macros defined in the header. All the other defines are either constant base addresses, register offsets or bit masks.
    I really don't get what your question is anymore. You asked if the macro is valid. You also say it compiles. This pretty much proves the macro is "valid" in that sense. But this doesn't mean there is some kind of macro syntax A(x)B(y) which takes two arguments x and y. It would be written AB(x, y) instead. The preprocessor proves THIS.

    So what we have here is some bizarre code with unclear motivations. In other words, bad code.

  5. #20
    Registered User
    Join Date
    Jun 2005
    Posts
    6,814
    Quote Originally Posted by Exit View Post
    In a header I was looking at, I saw this...

    Code:
    #define MMM_X(x)_Z(z)	(0x0C + (((x)-1)*3 + ((z)-1))*4)
    ... is that valid? I don't recall seeing a macro like that before.
    Subject to a few conditions, this is valid. Although it would be more clearly expressed with an additional space before the _Z, that space is not mandatory.

    As to what it does: that depends on what _Z actually is. In practice, it is probably another macro and z is probably a variable that is accessible at the point where the macro MMM_X is used (eg a global).

  6. #21
    Registered User
    Join Date
    Aug 2003
    Posts
    15
    I really don't get what your question is anymore.
    That wasn't an additional question, simply a statement of fact.
    As to what it does: that depends on what _Z actually is. In practice, it is probably another macro and z is probably a variable that is accessible at the point where the macro MMM_X is used (eg a global).
    That line is the only line in the header which contains macro definition, all other lines are constant addresses, register offsets or bitmasks. There are no global variables.

  7. #22
    Registered User
    Join Date
    Aug 2003
    Posts
    15
    Okay, I am in the office now and have had the chance to play with it a little.
    Code:
    #include <stdio.h>
    #define MMM_P(x)_C(z) (0x0C + (((x)-1)*3 + ((z)-1))*4)
    #define OFFSET (0xF0000 + 0xe800)
    
    int main()
    {
    	int i;
    	int j;
    	unsigned int x;
    
    	for (i=1; i<6; i++)
    	{
    		for (j=1; j<4; j++)
    		{
    			x = OFFSET + MMM_P(i)_C(j);
    			printf("Port %i Register %i addr : %08X\n", i,j,x);
    		}
    		printf("\n");
    	}
    	
    	return 0;
    }
    This program, with the odd looking macro construction does not compile. I get the following errors from gcc...

    Code:
    junk2.c: In function ‘main’:
    junk2.c:15: error: ‘z’ undeclared (first use in this function)
    junk2.c:15: error: (Each undeclared identifier is reported only once
    junk2.c:15: error: for each function it appears in.)
    junk2.c:15: error: called object ‘_C(<erroneous-expression>)’ is not a function
    junk2.c:15: error: expected ‘;’ before ‘_C’
    This program, with a more traditional looking macro definition does compile...

    Code:
    #include <stdio.h>
    #define MMM_P_C(x,z) (0x0C + (((x)-1)*3 + ((z)-1))*4)
    #define OFFSET (0xF0000 + 0xe800)
    
    int main()
    {
    	int i;
    	int j;
    	unsigned int x;
    
    	for (i=1; i<6; i++)
    	{
    		for (j=1; j<4; j++)
    		{
    			x = OFFSET + MMM_P_C(i,j);
    			printf("Port %i Register %i addr : %08X\n", i,j,x);
    		}
    		printf("\n");
    	}
    	
    	return 0;
    }
    ... and gives the expected output.

    Code:
    Port 1 Register 1 addr : 000FE80C
    Port 1 Register 2 addr : 000FE810
    Port 1 Register 3 addr : 000FE814
    
    Port 2 Register 1 addr : 000FE818
    Port 2 Register 2 addr : 000FE81C
    Port 2 Register 3 addr : 000FE820
    
    Port 3 Register 1 addr : 000FE824
    Port 3 Register 2 addr : 000FE828
    Port 3 Register 3 addr : 000FE82C
    
    Port 4 Register 1 addr : 000FE830
    Port 4 Register 2 addr : 000FE834
    Port 4 Register 3 addr : 000FE838
    
    Port 5 Register 1 addr : 000FE83C
    Port 5 Register 2 addr : 000FE840
    Port 5 Register 3 addr : 000FE844
    The strange macro construct does not prevent the program compiling if it is not used.

    Well, there you go.

  8. #23
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    That is exactly what I'd expect from the two code-snippets you show - that is, that one of them contains an invalid macro. I suspect also that you will find a macro
    Code:
    #define _Z(z) int z = something;
    someplace in your code - this may NOT be in the same header-file that you have the MMM macro tho' (e.g. it may be in the file that USES the latter macro, and it may even differ from one function to another!

    [Obviously, the code-snippet I've shown here is absolutely a guess, and it may well be quite different in all sorts of ways - but I'm 100% sure that such a macro definition exists, and that it most likely declares a local variable!]

    --
    Mats

  9. #24
    Registered User
    Join Date
    Aug 2003
    Posts
    15
    I've just done a grep on my entire Linux tree structure, (and as it caters for about 40 different architectures - that is a lot!), looking for ' _C(' and it returned nothing.

    If there was a second macro declaring z how would the value of the control register offset get into the calculation? This is an obvious requirement after all.

    Since this is a relatively new chip, it is entirley possible this code has never been used before and that it is a bug. This afternoon, I will be recompiling the OS with some new device drivers that I am still working on. I will try to use the macro there and see if the kernel build fails.

    We have been using the chip in another product, but that did not require the Ethernet switch to be programmed, it was using the chip's PCI bridge to control IEEE1394, (FireWire (tm)), chips.
    Last edited by Exit; 09-03-2007 at 03:40 AM.

  10. #25
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    So, could you tell us which driver this belongs to, as you've already explained that it's the Linux kernel that it belongs to?

    --
    Mats

  11. #26
    Registered User
    Join Date
    Aug 2003
    Posts
    15
    I get these errors from a kernel build when I try to use the "strange" macro construction in a device driver. If there is another macro/function it is sufficiently well hidden that a regular OS make can't find it.

    Code:
    drivers/dxl/cardid.c: In function `cardid_ioctl':
    drivers/dxl/cardid.c:173: warning: implicit declaration of function `_C'
    drivers/dxl/cardid.c:173: error: `z' undeclared (first use in this function)
    drivers/dxl/cardid.c:173: error: (Each undeclared identifier is reported only once
    drivers/dxl/cardid.c:173: error: for each function it appears in.)
    drivers/dxl/cardid.c:173: error: called object is not a function
    drivers/dxl/cardid.c:173: error: syntax error before "_C"
    So, could you tell us which driver this belongs to
    It is not a driver, that is what I am writing! It is the addresses, register offsets and bit masks for configuration of the onboard 5 port ethernet switch on a Micrel KS8695PX chip. This, and dozens of other header files came with the developers kit I think. The guy that built it into our "buildroot" embedded Linux system no longer works here so I am not 100&#37; sure.
    Last edited by Exit; 09-03-2007 at 07:30 AM. Reason: Added Micrel link.

  12. #27
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Exit View Post
    I get these errors from a kernel build when I try to use the "strange" macro construction in a device driver. If there is another macro/function it is sufficiently well hidden that a regular OS make can't find it.

    Code:
    drivers/dxl/cardid.c: In function `cardid_ioctl':
    drivers/dxl/cardid.c:173: warning: implicit declaration of function `_C'
    drivers/dxl/cardid.c:173: error: `z' undeclared (first use in this function)
    drivers/dxl/cardid.c:173: error: (Each undeclared identifier is reported only once
    drivers/dxl/cardid.c:173: error: for each function it appears in.)
    drivers/dxl/cardid.c:173: error: called object is not a function
    drivers/dxl/cardid.c:173: error: syntax error before "_C"
    I thought you said that it compiles and builds correctly - am I the one that is confused or are you?

    Thanks for the details of what component it is that are causing a problem.

    --
    Mats

  13. #28
    Registered User
    Join Date
    Aug 2003
    Posts
    15
    LOL. Yes, it compiles and builds fine until I try and use it, at that point, it gives the errors I posted. Sorry, should have been clearer. I am using other values from the same header without issue, only when I try to obtain the offset to a port control register using the macro does it fail.

  14. #29
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Ehm, yes, and there's something broken somewhere, either the macro itself is broken, or there's a missing _C macro somewhere (perhaps there used to be one somewhere else and it got lost at some point). I'd contact the producer of that driver, as it appears that the source isn't on the web - if I google for dxl/cardid.c, it comes up with very little useful stuff.

    --
    Mats

  15. #30
    Registered User
    Join Date
    Aug 2003
    Posts
    15
    I'd be suprised if it came up with anything at all, cardid.c is one of my drivers and I only wrote it last week! The header comes with the developers kit for the KS8695PX chip.

    I will write a patch for the header and submit it to the maintainer of that particular branch of the kernel.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem building Quake source
    By Silvercord in forum Game Programming
    Replies: 16
    Last Post: 07-11-2010, 09:13 AM
  2. Errors including <windows.h>
    By jw232 in forum Windows Programming
    Replies: 4
    Last Post: 07-29-2008, 01:29 PM
  3. Quantum Random Bit Generator
    By shawnt in forum C++ Programming
    Replies: 62
    Last Post: 06-18-2008, 10:17 AM
  4. recursion error
    By cchallenged in forum C Programming
    Replies: 2
    Last Post: 12-18-2006, 09:15 AM
  5. Strange results using dnsapi and windns
    By Niara in forum Networking/Device Communication
    Replies: 3
    Last Post: 08-13-2005, 10:21 AM