1

I'm having a project that does lots of this

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
// do some legacy stuff
#else
// do current stuff
#endif

where KERNEL_VERSION is defined as

#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))

I'd like to eliminate the defines that are not relevant for the current version, but tools like sunifdef don't evaluate the KERNEL_VERSION macro, so something like

 sunifdef --replace -DKERNEL_VERSION\(a,b,c\)=\(\(\(a\)\<\<16\)+\(\(b\)\<\<8\)+\(c\)\) -DLINUX_VERSION_CODE=3.13.1 *

fails with the message

sunifdef: error 0x04200: Garbage in argument "-DKERNEL_VERSION(a,b,c)=(((a)<<16)+((b)<<8)+(c))"

How do I get around this?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
user1273684
  • 1,559
  • 15
  • 24

3 Answers3

2

The successor to sunifdef seems to be coan, and the following command seemed to work (on one simple file):

coan source "-DLINUX_VERSION=KERNEL_VERSION(2,18,1)" \
            "-DKERNEL_VERSION(a,b,c)=((a)*0x10000 + (b)*0x100 + (c))" \
            testfile.c

I think using the KERNEL_VERSION macro to define LINUX_VERSION is prettier, but you might prefer Chris Dodd's version in hex. Two dots in a number is definitely not going to work.

rici
  • 234,347
  • 28
  • 237
  • 341
2

With sunifdef 3.1.3, you can't do it, as you demonstrated. Nor can you do it with earlier versions of coan such as 4.2.2.

However, with coan 5.2 (the current version), you can almost do what you are after.

$ cat legacy.c
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
do(some,legacy,stuff)
#else
do(current,stuff)
#endif
$ coan source -DLINUX_VERSION_CODE=0x020635 legacy.c
coan: /Users/jleffler/soq/legacy.c: line 1: warning 0x0041c: "-DKERNEL_VERSION(a,b,c)=(((a) << 16) + ((b) << 8) + (c))" has been assumed for the current file
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
do(current,stuff)
$ coan source -DLINUX_VERSION_CODE=0x020624 legacy.c
coan: /Users/jleffler/soq/legacy.c: line 1: warning 0x0041c: "-DKERNEL_VERSION(a,b,c)=(((a) << 16) + ((b) << 8) + (c))" has been assumed for the current file
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
do(some,legacy,stuff)
$

This is close to what you want, but not quite. It gives 'correct' output, but maybe not 'helpful' output. It gives you the code that would be compiled for the LINUX_VERSION_CODE specified on the command line, whereas you'd probably like the conditionals based on LINUX_VERSION_CODE and KERNEL_VERSION that are not false to survive into the output.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

The error is coming from the fact that you can't define macros with arguments on the command line with -D -- you can only define simple macros. However, you shouldn't NEED to define KERNEL_VERSION on the command line as the #define in the source should be fine. You should only need
-DLINUX_VERSION_CODE=0x30d01 -- you need to define it as a single integer constant (hex is easiest) rather than withs dots.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • Complete preprocessors do support defining macros with arguments on the command line. What the OP tried to do would have worked if it was an argument to `gcc` or `clang` instead of `sunifdef`. – zwol Sep 18 '13 at 23:06