bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: getopt: checking exlusive options?


From: Daniel Santos
Subject: Re: getopt: checking exlusive options?
Date: Tue, 23 Jul 2013 17:01:12 -0500
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130620 Thunderbird/17.0.6


On 07/23/2013 04:24 PM, Daniel Santos wrote:
On 07/23/2013 10:55 AM, Bernhard Voelker wrote:
Is there already something available in gnulib like
err_exclusive_options() in util-linux [1] to automatically
catch mutual exclusiveness of options inside the getopt loop?

After spending an inordinate amount of time experimenting with gcc's compile-time constant support, I'm bet that its possible to write an inline function that will generate a compile-time error for this! Basically, something like this:

extern int _getopt (int ___argc, char *const *___argv, const char *__shortopts) __THROW;

static inline void __validate_opts(const char *__shortopts) {
    /* insert magic here */
}

static inline int getopt (int ___argc, char *const *___argv, const char *__shortopts) {
    if (__builtin_constant_p(*__shortopts))
        __validate_opts(__shortopts);
    return _getopt (___argc, ___argv, __shortopts);
}

When __validate_opts() is called, we know that they have passed a compile-time constant value, so we can process the shortopts w/o worrying about a run-time overhead. I would have to experiment further to figure the rest out and then see what the oldest version of gcc is that would treat it all as compile-time.

Daniel


Well, it does seem possible indeed, but I haven't figured out a way to get gcc to unroll a loop the way I need it to so that I can avoid using static offsets. Short of doing so, the compile-time check would require repetitive code that supplies static offsets. Here is an example that will detect a dupe for up to 8 characters. It could be modified to check up to as many characters as you like, but becoming increasingly large (in source code at least)

extern void break_build(void) __attribute__((error ("die")));

static inline __attribute__((always_inline)) void
__check_dupe(const char *str, unsigned a, unsigned b) {
    if (__builtin_constant_p(str[a]) && __builtin_constant_p(str[b])
        && str[a] && str[a] != ':' && str[a] == str[b])
            break_build();
}

static inline __attribute__((always_inline)) void
__validate_opts(const char *str) {
    if (__builtin_constant_p(*str)) {
        __check_dupe(str, 0, 1);
        __check_dupe(str, 0, 2);
        __check_dupe(str, 0, 3);
        __check_dupe(str, 0, 4);
        __check_dupe(str, 0, 5);
        __check_dupe(str, 0, 6);
        __check_dupe(str, 0, 7);
        __check_dupe(str, 0, 8);
        __check_dupe(str, 1, 2);
        __check_dupe(str, 1, 3);
        __check_dupe(str, 1, 4);
        __check_dupe(str, 1, 5);
        __check_dupe(str, 1, 6);
        __check_dupe(str, 1, 7);
        __check_dupe(str, 1, 8);
        __check_dupe(str, 2, 3);
        __check_dupe(str, 2, 4);
        __check_dupe(str, 2, 5);
        __check_dupe(str, 2, 6);
        __check_dupe(str, 2, 7);
        __check_dupe(str, 2, 8);
        __check_dupe(str, 3, 4);
        __check_dupe(str, 3, 5);
        __check_dupe(str, 3, 6);
        __check_dupe(str, 3, 7);
        __check_dupe(str, 3, 8);
        __check_dupe(str, 4, 5);
        __check_dupe(str, 4, 6);
        __check_dupe(str, 4, 7);
        __check_dupe(str, 4, 8);
        __check_dupe(str, 5, 6);
        __check_dupe(str, 5, 7);
        __check_dupe(str, 5, 8);
        __check_dupe(str, 6, 7);
        __check_dupe(str, 6, 8);
        __check_dupe(str, 7, 8);
    }
}

int main(int argc, char *argv[]) {
    __validate_opts("asdfghd");
}

Of course, it will need a no-op version of __validate_opts if the preprocessor detects that we aren't using gcc or that optimizations aren't enabled. And this __validate_opts generates zero instructions when compiled -O2.

Daniel




reply via email to

[Prev in Thread] Current Thread [Next in Thread]