Converting defines to strings in precompiler directives
Often times it is useful to construct a string visible to the pre-compiler and assemble it from one more more other values, defined by means of a #define dierctive. Here’s some example code (this is some custom environemnt config for U-Boot for a STM-based device I work with):
#if defined( DEVELOPER_ALAN ) #define CONFIG_ETHADDR 00:23:b0:00:00:00 #define CONFIG_NETMASK 255.255.255.0 #define CONFIG_IPADDR 192.168.0.12 #define CONFIG_GATEWAYIP 192.168.0.2 #define CONFIG_SERVERIP 192.168.0.170 #if defined( BOOT_FROM_NFS ) #define CONFIG_BOOTFILE "/work/project_A18/target/boot/uImage" #define CONFIG_BOOTCOMMAND "nfs;bootm 80000000" #define CONFIG_BOOTARGS "root=/dev/nfs rootdelay=10 \ nfsroot=192.168.0.170:/work/project_A18/target,rsize=4096,wsize=8192,tcp \ nwhwconf=device:eth0,hwaddr:00:23:b0:00:00:00 \ ip=192.168.0.12::192.168.0.2:255.255.255.0:host-nfs::off \ console=ttyAS0,115200 mem=58m" #elif defined( BOOT_FROM_USBFAT ) #define CONFIG_BOOTFILE "/boot/uImage" #define CONFIG_BOOTCOMMAND "usb reset;fatload usb 0:1 80000000 /uImage;\ bootm 80000000" #define CONFIG_BOOTARGS "root=/dev/sda2 rootdelay=10 \ nwhwconf=device:eth0,hwaddr:00:23:b0:00:00:00 \ ip=192.168.0.12::192.168.0.2:255.255.255.0:host-usb::off \ console=ttyAS0,115200 mem=58m bigphysarea=1000" #else #error "No valid boot option selected." #endif #elif defined( DEVELOPER_BOB ) #define CONFIG_ETHADDR 00:23:b0:00:00:01 #define CONFIG_NETMASK 255.255.255.0 #define CONFIG_IPADDR 192.168.0.13 #define CONFIG_GATEWAYIP 192.168.0.2 #define CONFIG_SERVERIP 192.168.0.174 #if defined( BOOT_FROM_NFS ) ... #endif #endif
It’s easily seen that each of the 5 defines CONFIG_ETHADDR, CONFIG_NETMASK, CONFIG_IPADDR, CONFIG_GATEWAYIP and CONFIG_SERVERIP is then used as one of the building blocks for the CONFIG_BOOTARGS define a little further down. So it would be nice to re-use these already defined values to construct the CONFIG_BOOTARGS define.
“No problem” – you say – “I’ll just use the stringizing operator ‘#’…”. Yup, first thing that comes to mind is to use stringification to substitute the defines’ values in the BOOTARGS define:
#define CONFIG_BOOTARGS "root=/dev/nfs rootdelay=5 \ nfsroot=" #CONFIG_SERVERIP ":/work/project_A18/target,rsize=4096,wsize=8192,tcp \ nwhwconf=device:eth0,hwaddr:" #CONFIG_ETHADDR " ip=" #CONFIG_IPADDR "::\ " #CONFIG_GATEWAYIP ":" #CONFIG_NETMASK ":no-nfs::off"
While the key to converting a #define into a string is indeed the stringification operator ‘#’, saddly, the above define as it is writen, breaks compilation.
To make it work we’ll use two macros which will convert the defines values to strings and after that there should be no problem:
#define DEF2STR(x) #x #define MK_STR(x) DEF2STR(x) #if defined( DEVELOPER_ALAN ) #define CONFIG_ETHADDR 00:23:D0:00:00:00 #define CONFIG_NETMASK 255.255.255.0 #define CONFIG_IPADDR 192.168.0.12 #define CONFIG_GATEWAYIP 192.168.0.2 #define CONFIG_SERVERIP 192.168.0.170 #ifdef BOOT_FROM_NFS #define CONFIG_BOOTCOMMAND "nfs;bootm 80000000" #define CONFIG_BOOTFILE "/work/project_A18/target/boot/uImage" #define CONFIG_BOOTARGS "root=/dev/nfs rootdelay=5 \ nfsroot=" MK_STR(CONFIG_SERVERIP) ":/work/project_A18/target,rsize=4096,wsize=8192,tcp \ nwhwconf=device:eth0,hwaddr:" MK_STR(CONFIG_ETHADDR) " ip=" MK_STR(CONFIG_IPADDR) "::\ " MK_STR(CONFIG_GATEWAYIP) ":" MK_STR(CONFIG_NETMASK) ":ae-nfs::off \ console=ttyAS0,115200 mem=58m bigphysarea=1000" #elif defined( BOOT_FROM_USBFAT ) ... #endif
This code DOES compile and it is easy to re-use it – just configure the 5 defines according to your setup and CONFIG_BOOTARGS will be generated correctly from these values 🙂
-
Categories
- Android Development
- Bash
- C programming
- dpkg/apt-get
- drupal
- Emacs
- Git
- Java
- Linux administration
- Linux device drivers
- Linux Gaming
- Linux kernel
- Linux Networking
- Linux on Windows
- Linux printing
- Linux sound and ALSA
- Package Managers
- Programming
- RPM
- Shell and environment
- Tips and tricks
- Uncategorized
- VirtualBox
- Virtualization
- web development
- wine
- WMaker
- Wordpress Tips
- X Window System
- XFCE
-
Articles
- August 2020
- August 2019
- May 2019
- July 2017
- February 2017
- January 2017
- November 2016
- October 2016
- September 2016
- August 2016
- July 2016
- June 2016
- April 2016
- March 2016
- December 2015
- November 2015
- September 2015
- June 2015
- May 2015
- April 2015
- March 2015
- February 2015
- January 2015
- December 2014
- October 2014
- February 2014
- January 2014
- November 2013
- October 2013
- June 2013
- April 2013
- March 2013
- February 2013
- January 2013
- December 2012
- October 2012
- August 2012
- July 2012
- June 2012
- May 2012
- April 2012
- March 2012
- February 2012
- September 2011
- August 2011
- June 2011
- May 2011
- April 2011
- March 2011
- February 2011
-
Meta
Cloud
audio bash boot compile C programming cups drupal emacs etc Fedora git grep how to httpd init kernel libc linux linux partition localtime login make mount mp3 mysql networking oracle package managers password phpMyAdmin programming rpm shell sql vbox version control system virtual box vm web server wordpress www xargs xfce xwin yum