Detect integer sizes without running executables
Try to compile test code for sizes 1, 2, 4, 8 that only succeeds if a
type has a certain size. The test code contains an array declaration
of the form:
int a[sizeof(type) == size ? 1 : -1];
The array size is a valid constant expression but produces a
compilation error unless the the size of the type matches. This makes
it possible to determine the size of types without executing any test
programs when cross-compiling.
Inspired by Autoconf's AC_CHECK_SIZEOF.
diff --git a/src/Charmonizer/Core/HeaderChecker.c b/src/Charmonizer/Core/HeaderChecker.c
index a2b46db..eaf9663 100644
--- a/src/Charmonizer/Core/HeaderChecker.c
+++ b/src/Charmonizer/Core/HeaderChecker.c
@@ -173,6 +173,44 @@
return retval;
}
+int
+chaz_HeadCheck_size_of_type(const char *type, const char *includes, int hint) {
+ static const char sizeof_code[] =
+ CHAZ_QUOTE( #include <stddef.h> )
+ CHAZ_QUOTE( %s )
+ CHAZ_QUOTE( int a[sizeof(%s)==%d?1:-1]; );
+ size_t needed = sizeof(sizeof_code)
+ + strlen(type)
+ + strlen(includes)
+ + 10;
+ char *buf = (char*)malloc(needed);
+ static const int sizes[] = { 4, 8, 2, 1 };
+ int retval = 0;
+ int i;
+
+ for (i = -1; i < (int)(sizeof(sizes) / sizeof(sizes[0])); i++) {
+ int size;
+
+ if (i < 0) {
+ if (hint != 0) { size = hint; }
+ else { continue; }
+ }
+ else {
+ if (sizes[i] != hint) { size = sizes[i]; }
+ else { continue; }
+ }
+
+ sprintf(buf, sizeof_code, includes, type, size);
+ if (chaz_CC_test_compile(buf)) {
+ retval = size;
+ break;
+ }
+ }
+
+ free(buf);
+ return retval;
+}
+
static int
chaz_HeadCheck_compare_headers(const void *vptr_a, const void *vptr_b) {
chaz_CHeader *const *const a = (chaz_CHeader*const*)vptr_a;
diff --git a/src/Charmonizer/Core/HeaderChecker.h b/src/Charmonizer/Core/HeaderChecker.h
index e7c14cb..1f8110d 100644
--- a/src/Charmonizer/Core/HeaderChecker.h
+++ b/src/Charmonizer/Core/HeaderChecker.h
@@ -53,6 +53,14 @@
chaz_HeadCheck_contains_member(const char *struct_name, const char *member,
const char *includes);
+/*
+ * Return the size of the type or 0 if can't be determined. Only checks for
+ * sizes 1, 2, 4, 8. If hint != 0, try this size first to speed up the
+ * detection.
+ */
+int
+chaz_HeadCheck_size_of_type(const char *type, const char *includes, int hint);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/Charmonizer/Probe/Integers.c b/src/Charmonizer/Probe/Integers.c
index c680141..6ae12a0 100644
--- a/src/Charmonizer/Probe/Integers.c
+++ b/src/Charmonizer/Probe/Integers.c
@@ -28,30 +28,10 @@
static int
chaz_Integers_machine_is_big_endian(void);
-static const char chaz_Integers_sizes_code[] =
- CHAZ_QUOTE( #include <stdio.h> )
- CHAZ_QUOTE( int main () { )
- CHAZ_QUOTE( printf("%d ", (int)sizeof(char)); )
- CHAZ_QUOTE( printf("%d ", (int)sizeof(short)); )
- CHAZ_QUOTE( printf("%d ", (int)sizeof(int)); )
- CHAZ_QUOTE( printf("%d ", (int)sizeof(long)); )
- CHAZ_QUOTE( printf("%d ", (int)sizeof(void*)); )
- CHAZ_QUOTE( printf("%d ", (int)sizeof(size_t)); )
- CHAZ_QUOTE( return 0; )
- CHAZ_QUOTE( } );
-
static const char chaz_Integers_stdint_type_code[] =
CHAZ_QUOTE( #include <stdint.h> )
CHAZ_QUOTE( %s i; );
-static const char chaz_Integers_type64_code[] =
- CHAZ_QUOTE( #include <stdio.h> )
- CHAZ_QUOTE( int main() )
- CHAZ_QUOTE( { )
- CHAZ_QUOTE( printf("%%d", (int)sizeof(%s)); )
- CHAZ_QUOTE( return 0; )
- CHAZ_QUOTE( } );
-
static const char chaz_Integers_literal64_code[] =
CHAZ_QUOTE( int f() { return (int)9000000000000000000%s; } );
@@ -98,42 +78,24 @@
}
/* Record sizeof() for several common integer types. */
- output = chaz_CC_capture_output(chaz_Integers_sizes_code, &output_len);
- if (output != NULL) {
- char *ptr = output;
- char *end_ptr = output;
-
- sizeof_char = strtol(ptr, &end_ptr, 10);
- ptr = end_ptr;
- sizeof_short = strtol(ptr, &end_ptr, 10);
- ptr = end_ptr;
- sizeof_int = strtol(ptr, &end_ptr, 10);
- ptr = end_ptr;
- sizeof_long = strtol(ptr, &end_ptr, 10);
- ptr = end_ptr;
- sizeof_ptr = strtol(ptr, &end_ptr, 10);
- ptr = end_ptr;
- sizeof_size_t = strtol(ptr, &end_ptr, 10);
-
- free(output);
- }
+ sizeof_char = chaz_HeadCheck_size_of_type("char", "", 1);
+ sizeof_short = chaz_HeadCheck_size_of_type("short", "", 2);
+ sizeof_int = chaz_HeadCheck_size_of_type("int", "", 4);
+ sizeof_long = chaz_HeadCheck_size_of_type("long", "", 4);
+ sizeof_ptr = chaz_HeadCheck_size_of_type("void*", "", 4);
+ sizeof_size_t = chaz_HeadCheck_size_of_type("size_t",
+ "#include <stddef.h>", 4);
/* Determine whether long longs are available. */
- sprintf(code_buf, chaz_Integers_type64_code, "long long");
- output = chaz_CC_capture_output(code_buf, &output_len);
- if (output != NULL) {
+ if (chaz_CC_test_compile("long long l;")) {
has_long_long = true;
- sizeof_long_long = strtol(output, NULL, 10);
- free(output);
+ sizeof_long_long = chaz_HeadCheck_size_of_type("long long", "", 8);
}
/* Determine whether the __int64 type is available. */
- sprintf(code_buf, chaz_Integers_type64_code, "__int64");
- output = chaz_CC_capture_output(code_buf, &output_len);
- if (output != NULL) {
+ if (chaz_CC_test_compile("__int64 i;")) {
has___int64 = true;
- sizeof___int64 = strtol(output, NULL, 10);
- free(output);
+ sizeof___int64 = chaz_HeadCheck_size_of_type("__int64", "", 8);
}
/* Determine whether the intptr_t type is available (it's optional in