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 22:42:18 -0500
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130620 Thunderbird/17.0.6


On 07/23/2013 05:01 PM, Daniel Santos wrote:
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!

So, once again, here is a proof-of-concept implementation that will detect duplicate characters (excluding ':') on a string of up to 20 chars at compile-time.

extern void break_build(void) __attribute__((error ("string has duplicate chars")));

static inline __attribute__((always_inline)) void
__check_dupe1(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
__check_dupe0(const char *str, const unsigned start) {
    if (!__builtin_constant_p(str[0]) || !__builtin_constant_p(start)
     || !__builtin_constant_p(str[start]) || !str[start])
        return;

    __check_dupe1(str, start, start + 1);
    __check_dupe1(str, start, start + 2);
    __check_dupe1(str, start, start + 3);
    __check_dupe1(str, start, start + 4);
    __check_dupe1(str, start, start + 5);
    __check_dupe1(str, start, start + 6);
    __check_dupe1(str, start, start + 7);
    __check_dupe1(str, start, start + 8);
    __check_dupe1(str, start, start + 9);
    __check_dupe1(str, start, start + 10);
    __check_dupe1(str, start, start + 11);
    __check_dupe1(str, start, start + 12);
    __check_dupe1(str, start, start + 13);
    __check_dupe1(str, start, start + 14);
    __check_dupe1(str, start, start + 15);
    __check_dupe1(str, start, start + 16);
    __check_dupe1(str, start, start + 17);
    __check_dupe1(str, start, start + 18);
    __check_dupe1(str, start, start + 19);
}

static inline __attribute__((always_inline)) void
__break_build_on_dupe(const char *str) {
    if (!__builtin_constant_p(str[0]) || !str[0])
        return;

    __check_dupe0(str, 0);
    __check_dupe0(str, 1);
    __check_dupe0(str, 2);
    __check_dupe0(str, 3);
    __check_dupe0(str, 4);
    __check_dupe0(str, 5);
    __check_dupe0(str, 6);
    __check_dupe0(str, 7);
    __check_dupe0(str, 8);
    __check_dupe0(str, 9);
    __check_dupe0(str, 10);
    __check_dupe0(str, 11);
    __check_dupe0(str, 12);
    __check_dupe0(str, 13);
    __check_dupe0(str, 14);
    __check_dupe0(str, 15);
    __check_dupe0(str, 16);
    __check_dupe0(str, 17);
    __check_dupe0(str, 18);
    __check_dupe0(str, 19);
}

int main(int argc, char *argv[]) {
__break_build_on_dupe("asdfghj:k:l::qwertyuiopzxcvbnm");
}

It has a number of draw-backs as it is, this snippet alone takes 560mS to compile on my AMD Phenom machine, it produces an error for each dupe, etc., but this can be cleaned up a lot and I get the compile time to scale to the number of characters in the string (i.e., stop evaluating once the end of the string is reached) and reduce compile time quite a bit. (Heavy compiler CPU usage is a side-effect of all forms of metaprogramming) However, this does prove it can be done in a sane number of lines of code -- again, while generating no instructions when optimized:

Disassembly of section .text:
        __check_dupe0(str, 19);
}

int main(int argc, char *argv[]) {
__break_build_on_dupe("asdfghj:k:l::qwertyuiopzxcvbnm");
}
0000000000400400 <main> repz retq




reply via email to

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