MK.
MK.

Reputation: 34587

c preprocessor - fail if compiling after certain date

I would like to make the compilation of some files to fail if attempted after a certain date. The reason for this: I found a couple of Y2K38 bugs which I don't have time to fix right now, but would like to make a note of them and I think it would be nice if compilation of the module would just fail after, say, 2020. (I might be insane, but this code is 20 years old I suspect it might survive another 30)

Upvotes: 9

Views: 1712

Answers (5)

Jens Gustedt
Jens Gustedt

Reputation: 78953

__DATE__ is not the proper thing for such a goal:

If the date of translation is not available, an implementation-defined valid date shall be supplied.

Any future broken C compiler that still only implements C99 :) and not any of its followers may fix the date to "Jan  1 1970" or have it wrap once beyond the fatal date in 2038.

Upvotes: 1

Chris Lutz
Chris Lutz

Reputation: 75439

Here's a horrible solution:

  1. In your project's general-purpose header directory, run the following (Python) script:

    #!/usr/bin/python
    
    months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
              'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
    
    cutoff = 2020
    #safety = 2025
    
    for year in range(2011, cutoff):
        for month in months:
            for day in range(1, 32):
                t = open("%s %2d %d" % (month, day, year), "w")
                t.write("\n");
                t.close()
    
    #for year in range(2011, cutoff):
    #    for month in months:
    #        for day in range(1, 32):
    #            t = open("%s %2d %d" % (month, day, year), "w")
    #            t.write("#error \"Too old\"\n");
    #            t.close()
    

    Uncomment the commented-out lines to produce better diagnostic messages.

  2. In the files that need to error after the cutoff date, use this:

    #include __DATE__
    

I dare you to use this in production code.

Upvotes: 5

dan04
dan04

Reputation: 91209

Instead of dealing with the awkward format of the __DATE__ macro, why not roll your own?

gcc -DTHIS_YEAR=`/bin/date +%Y` yourprogram.c

Then your code can use expressions like #if THIS_YEAR >= 2020.

Upvotes: 5

steve
steve

Reputation: 6020

A more generic solution that should work with most compilers. It depends a bit on the format of the DATE preprocessor directive

#define DIGIT(ch) (((ch)<'0'||(ch)>'9') ? 0 : ((ch)-'0'))
#define YEAR (1000*DIGIT(__DATE__[7])+100*DIGIT(__DATE__[8])+10*DIGIT(__DATE__[9])+DIGIT(__DATE__[10]))

#ifdef YEAR-2020>0
#error too old
#endif

Upvotes: 0

nelhage
nelhage

Reputation: 2784

With GCC, you can do something like the following:

void __attribute__((error("Whoa. It's the future"))) whoa_the_future();

void check_for_the_future() {
    // "Feb  1 2011"
    const char *now = __DATE__;
    if (now[9] >= '2')
        whoa_the_future();
}

The way this works is that the error attribute tells GCC to generate a compile-time error if any calls to that function are left in the code after all of GCC's constant-folding, dead-code elimination, and similar passes have run. Since DATE is a compile-time constant, GCC can evaluate the if statement at compile time and remove the call.

At least one downside is that this depends on GCC's optimization passes, and so it won't work at gcc -O0

Honestly, you might be better off just adding a runtime check somewhere and failing fast.

Upvotes: 5

Related Questions