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