Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use __DATE__ and __TIME__ predefined macros in as two integers, then stringify?

Want to use __ DATE __ and __ TIME __ as integer for giving automated version to my code in compile time.

#define STRINGIZER(arg)     #arg
#define STR_VALUE(arg)      STRINGIZER(arg)

#define DATE_as_int_str useD(__DATE__) // What can be done ?
#define TIME_as_int_str useT(__TIME__) // What can be done ?

#define VERSION 1.4

#define COMPLETE_VERSION STR_VALUE(VERSION) "." DATE_as_int_str "." TIME_as_int_str

and get COMPLETE_VERSION as string in a const unsigned char [].

const unsigned char completeVersion[] = ?? COMPLETE_VERSION;

Should output 1.4.1432.2234 something.

One of the possible solution could be but did not work: convert-date-to-unsigned-int

In context of compile time convertint-date-and-time-string-to-just-integers-in-c One can refer expanssion-and-stringification-how-to-get-the-marco-name-not-its-value

like image 485
Rick2047 Avatar asked Jul 28 '12 02:07

Rick2047


People also ask

What are the predefined macros?

Predefined macros are those that the compiler defines (in contrast to those user defines in the source file). Those macros must not be re-defined or undefined by user.

What is __ file __ in C?

The __FILE__ macro expands to a string whose contents are the filename, surrounded by double quotation marks ( " " ). If you change the line number and filename, the compiler ignores the previous values and continues processing with the new values. The #line directive is typically used by program generators.

What is __ LINE __ in C?

__LINE__ is a preprocessor macro that expands to current line number in the source file, as an integer. __LINE__ is useful when generating log statements, error messages intended for programmers, when throwing exceptions, or when writing debugging code.


1 Answers

If you can use a C++ compiler to build the object file that you want to contain your version string, then we can do exactly what you want! The only magic here is that C++ allows you to use expressions to statically initialize an array, while C doesn't. The expressions need to be fully computable at compile time, but these expressions are, so it's no problem.

We build up the version string one byte at a time, and get exactly what we want.

// source file version_num.h  #ifndef VERSION_NUM_H  #define VERSION_NUM_H   #define VERSION_MAJOR 1 #define VERSION_MINOR 4   #endif // VERSION_NUM_H 

// source file build_defs.h  #ifndef BUILD_DEFS_H  #define BUILD_DEFS_H   // Example of __DATE__ string: "Jul 27 2012" //                              01234567890  #define BUILD_YEAR_CH0 (__DATE__[ 7]) #define BUILD_YEAR_CH1 (__DATE__[ 8]) #define BUILD_YEAR_CH2 (__DATE__[ 9]) #define BUILD_YEAR_CH3 (__DATE__[10])   #define BUILD_MONTH_IS_JAN (__DATE__[0] == 'J' && __DATE__[1] == 'a' && __DATE__[2] == 'n') #define BUILD_MONTH_IS_FEB (__DATE__[0] == 'F') #define BUILD_MONTH_IS_MAR (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'r') #define BUILD_MONTH_IS_APR (__DATE__[0] == 'A' && __DATE__[1] == 'p') #define BUILD_MONTH_IS_MAY (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'y') #define BUILD_MONTH_IS_JUN (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'n') #define BUILD_MONTH_IS_JUL (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'l') #define BUILD_MONTH_IS_AUG (__DATE__[0] == 'A' && __DATE__[1] == 'u') #define BUILD_MONTH_IS_SEP (__DATE__[0] == 'S') #define BUILD_MONTH_IS_OCT (__DATE__[0] == 'O') #define BUILD_MONTH_IS_NOV (__DATE__[0] == 'N') #define BUILD_MONTH_IS_DEC (__DATE__[0] == 'D')   #define BUILD_MONTH_CH0 \     ((BUILD_MONTH_IS_OCT || BUILD_MONTH_IS_NOV || BUILD_MONTH_IS_DEC) ? '1' : '0')  #define BUILD_MONTH_CH1 \     ( \         (BUILD_MONTH_IS_JAN) ? '1' : \         (BUILD_MONTH_IS_FEB) ? '2' : \         (BUILD_MONTH_IS_MAR) ? '3' : \         (BUILD_MONTH_IS_APR) ? '4' : \         (BUILD_MONTH_IS_MAY) ? '5' : \         (BUILD_MONTH_IS_JUN) ? '6' : \         (BUILD_MONTH_IS_JUL) ? '7' : \         (BUILD_MONTH_IS_AUG) ? '8' : \         (BUILD_MONTH_IS_SEP) ? '9' : \         (BUILD_MONTH_IS_OCT) ? '0' : \         (BUILD_MONTH_IS_NOV) ? '1' : \         (BUILD_MONTH_IS_DEC) ? '2' : \         /* error default */    '?' \     )  #define BUILD_DAY_CH0 ((__DATE__[4] >= '0') ? (__DATE__[4]) : '0') #define BUILD_DAY_CH1 (__DATE__[ 5])    // Example of __TIME__ string: "21:06:19" //                              01234567  #define BUILD_HOUR_CH0 (__TIME__[0]) #define BUILD_HOUR_CH1 (__TIME__[1])  #define BUILD_MIN_CH0 (__TIME__[3]) #define BUILD_MIN_CH1 (__TIME__[4])  #define BUILD_SEC_CH0 (__TIME__[6]) #define BUILD_SEC_CH1 (__TIME__[7])   #if VERSION_MAJOR > 100  #define VERSION_MAJOR_INIT \     ((VERSION_MAJOR / 100) + '0'), \     (((VERSION_MAJOR % 100) / 10) + '0'), \     ((VERSION_MAJOR % 10) + '0')  #elif VERSION_MAJOR > 10  #define VERSION_MAJOR_INIT \     ((VERSION_MAJOR / 10) + '0'), \     ((VERSION_MAJOR % 10) + '0')  #else  #define VERSION_MAJOR_INIT \     (VERSION_MAJOR + '0')  #endif  #if VERSION_MINOR > 100  #define VERSION_MINOR_INIT \     ((VERSION_MINOR / 100) + '0'), \     (((VERSION_MINOR % 100) / 10) + '0'), \     ((VERSION_MINOR % 10) + '0')  #elif VERSION_MINOR > 10  #define VERSION_MINOR_INIT \     ((VERSION_MINOR / 10) + '0'), \     ((VERSION_MINOR % 10) + '0')  #else  #define VERSION_MINOR_INIT \     (VERSION_MINOR + '0')  #endif    #endif // BUILD_DEFS_H 

// source file main.c  #include "version_num.h" #include "build_defs.h"  // want something like: 1.4.1432.2234  const unsigned char completeVersion[] = {     VERSION_MAJOR_INIT,     '.',     VERSION_MINOR_INIT,     '-', 'V', '-',     BUILD_YEAR_CH0, BUILD_YEAR_CH1, BUILD_YEAR_CH2, BUILD_YEAR_CH3,     '-',     BUILD_MONTH_CH0, BUILD_MONTH_CH1,     '-',     BUILD_DAY_CH0, BUILD_DAY_CH1,     'T',     BUILD_HOUR_CH0, BUILD_HOUR_CH1,     ':',     BUILD_MIN_CH0, BUILD_MIN_CH1,     ':',     BUILD_SEC_CH0, BUILD_SEC_CH1,     '\0' };   #include <stdio.h>  int main(int argc, char **argv) {     printf("%s\n", completeVersion);     // prints something similar to: 1.4-V-2013-05-09T15:34:49 } 

This isn't exactly the format you asked for, but I still don't fully understand how you want days and hours mapped to an integer. I think it's pretty clear how to make this produce any desired string.

like image 188
steveha Avatar answered Sep 18 '22 16:09

steveha