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