freestanding_lib.c (7500B)
1 #include <assert.h> 2 #include <inttypes.h> 3 #include <limits.h> 4 #include <stdarg.h> 5 #include <stdbool.h> 6 #include <stddef.h> 7 #include <stdbit.h> 8 #include <stdckdint.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 13 static int cmp_int(const void* a, const void* b) { 14 int lhs = *(const int*)a; 15 int rhs = *(const int*)b; 16 return (lhs > rhs) - (lhs < rhs); 17 } 18 19 static int check_vsnprintf(char* out, size_t n, const char* fmt, ...) { 20 va_list ap; 21 int rc; 22 va_start(ap, fmt); 23 rc = vsnprintf(out, n, fmt, ap); 24 va_end(ap); 25 return rc; 26 } 27 28 static int check_vsprintf(char* out, const char* fmt, ...) { 29 va_list ap; 30 int rc; 31 va_start(ap, fmt); 32 rc = vsprintf(out, fmt, ap); 33 va_end(ap); 34 return rc; 35 } 36 37 struct CallbackOut { 38 char buf[32]; 39 int len; 40 }; 41 42 static void capture_ch(char ch, void* arg) { 43 struct CallbackOut* out = (struct CallbackOut*)arg; 44 if (out->len < (int)sizeof(out->buf) - 1) { 45 out->buf[out->len] = ch; 46 } 47 out->len++; 48 } 49 50 static int strings_ok(void) { 51 char buf[32]; 52 char small[8]; 53 const char* text = "alpha beta"; 54 55 memset(buf, 0, sizeof(buf)); 56 memcpy(buf, "abc", 4); 57 memmove(buf + 1, buf, 3); 58 if (strcmp(buf, "aabc") != 0) return 0; 59 if (memcmp(buf, "aabc", 4) != 0) return 0; 60 if (*(char*)memchr(buf, 'b', 4) != 'b') return 0; 61 62 strcpy(buf, "alpha"); 63 strcat(buf, " "); 64 strncat(buf, "beta!", 4); 65 if (strcmp(buf, text) != 0) return 0; 66 if (strncmp(buf, "alpha", 5) != 0) return 0; 67 if (strlen(buf) != 10) return 0; 68 if (strnlen(buf, 4) != 4) return 0; 69 if (strchr(buf, ' ') != buf + 5) return 0; 70 if (strrchr(buf, 'a') != buf + 9) return 0; 71 if (strspn(buf, "alph ") != 6) return 0; 72 if (strcspn(buf, "tb") != 6) return 0; 73 if (strpbrk(buf, "tb") != buf + 6) return 0; 74 if (strstr(buf, "ha be") != buf + 3) return 0; 75 76 strncpy(small, "xy", sizeof(small)); 77 if (small[0] != 'x' || small[1] != 'y' || small[2] != '\0') return 0; 78 79 memset(small, '?', sizeof(small)); 80 if (memccpy(small, "abcd", 'c', 4) != small + 3) return 0; 81 if (memcmp(small, "abc?", 4) != 0) return 0; 82 memset_explicit(small, 0, sizeof(small)); 83 if (small[0] != '\0' || small[sizeof(small) - 1] != '\0') return 0; 84 return 1; 85 } 86 87 static int stdlib_ok(void) { 88 char* end; 89 int values[6] = {5, 1, 4, 2, 3, 0}; 90 int key = 4; 91 int* found; 92 div_t d; 93 ldiv_t ld; 94 lldiv_t lld; 95 imaxdiv_t imd; 96 char aligned[32]; 97 98 if (atoi(" -42x") != -42) return 0; 99 if (atol("123") != 123L) return 0; 100 if (atoll("-456") != -456LL) return 0; 101 if (strtol("0x2a!", &end, 0) != 42 || *end != '!') return 0; 102 if (strtoll("-077", &end, 0) != -63 || *end != '\0') return 0; 103 if (strtoul("101", &end, 2) != 5UL || *end != '\0') return 0; 104 if (strtoull("ff", &end, 16) != 255ULL || *end != '\0') return 0; 105 if ((int)(strtod("12.5e1z", &end) + 0.5) != 125 || *end != 'z') return 0; 106 if ((int)(strtof("4.25", &end) * 4.0f) != 17 || *end != '\0') return 0; 107 if ((int)strtold("9.0", &end) != 9 || *end != '\0') return 0; 108 if (strtoimax("-9223372036854775807", &end, 10) != 109 (intmax_t)-9223372036854775807LL || 110 *end != '\0') 111 return 0; 112 if (strtoumax("18446744073709551615", &end, 10) != 113 (uintmax_t)18446744073709551615ULL || 114 *end != '\0') 115 return 0; 116 117 if (abs(-7) != 7 || labs(-8L) != 8L || llabs(-9LL) != 9LL) return 0; 118 if (imaxabs((intmax_t)-10) != (intmax_t)10) return 0; 119 d = div(17, 5); 120 ld = ldiv(17L, 5L); 121 lld = lldiv(17LL, 5LL); 122 imd = imaxdiv((intmax_t)17, (intmax_t)5); 123 if (d.quot != 3 || d.rem != 2) return 0; 124 if (ld.quot != 3 || ld.rem != 2) return 0; 125 if (lld.quot != 3 || lld.rem != 2) return 0; 126 if (imd.quot != 3 || imd.rem != 2) return 0; 127 if (memalignment(NULL) != 0) return 0; 128 if (memalignment(aligned) < 1) return 0; 129 130 qsort(values, 6, sizeof(values[0]), cmp_int); 131 for (int i = 0; i < 6; i++) { 132 if (values[i] != i) return 0; 133 } 134 found = bsearch(&key, values, 6, sizeof(values[0]), cmp_int); 135 if (found == NULL || *found != key) return 0; 136 return 1; 137 } 138 139 static int c23_bits_ok(void) { 140 int out; 141 142 if (CHAR_WIDTH != 8 || INT_WIDTH != 32 || INT64_WIDTH != 64) return 0; 143 if (stdc_leading_zeros_uc((unsigned char)0x10u) != 3) return 0; 144 if (stdc_trailing_zeros_ui(0x20u) != 5) return 0; 145 if (stdc_count_ones_ui(0xb1u) != 4) return 0; 146 if (stdc_count_zeros_uc((unsigned char)0xf0u) != 4) return 0; 147 if (!stdc_has_single_bit_ui(0x8000u)) return 0; 148 if (stdc_has_single_bit_ui(0x8001u)) return 0; 149 if (stdc_bit_width_ui(0x80u) != 8) return 0; 150 if (stdc_bit_floor_ui(130u) != 128u) return 0; 151 if (stdc_bit_ceil_ui(129u) != 256u) return 0; 152 if (stdc_first_leading_one_uc((unsigned char)0x10u) != 4) return 0; 153 if (stdc_first_trailing_one_ui(0x10u) != 5) return 0; 154 if (stdc_first_leading_zero_uc((unsigned char)0xefu) != 4) return 0; 155 if (stdc_first_trailing_zero_ui(0xefu) != 5) return 0; 156 if (stdc_leading_ones((unsigned char)0xf0u) != 4) return 0; 157 if (stdc_trailing_ones((unsigned int)0x0fu) != 4) return 0; 158 if (stdc_count_zeros((unsigned char)0xf0u) != 4) return 0; 159 if (stdc_bit_width((unsigned int)0x80u) != 8) return 0; 160 if (stdc_bit_floor((unsigned int)130u) != 128u) return 0; 161 if (stdc_bit_ceil((unsigned int)129u) != 256u) return 0; 162 163 if (ckd_add(&out, INT_MAX, 1) != true) return 0; 164 if (ckd_add(&out, 10, 20) != false || out != 30) return 0; 165 if (ckd_sub(&out, INT_MIN, 1) != true) return 0; 166 if (ckd_mul(&out, 7, 6) != false || out != 42) return 0; 167 return 1; 168 } 169 170 static int stdio_ok(void) { 171 char buf[64]; 172 int rc; 173 174 rc = snprintf(buf, sizeof(buf), "%s:%d:%04x:%c", "id", -7, 26, '!'); 175 if (rc != 12 || strcmp(buf, "id:-7:001a:!") != 0) return 31; 176 177 rc = snprintf(buf, sizeof(buf), "%" PRIdMAX "/%" PRIuMAX, (intmax_t)-9, 178 (uintmax_t)10); 179 if (rc != 5 || strcmp(buf, "-9/10") != 0) return 30; 180 181 rc = snprintf(buf, 6, "abcdef"); 182 if (rc != 6 || strcmp(buf, "abcde") != 0) return 32; 183 184 rc = sprintf(buf, "%u/%ld/%p", 12U, 34L, (void*)0x1234); 185 if (rc <= 0 || strstr(buf, "12/34/") != buf) return 33; 186 187 rc = check_vsnprintf(buf, sizeof(buf), "%s %02d", "v", 3); 188 if (rc != 4 || strcmp(buf, "v 03") != 0) return 34; 189 190 rc = check_vsprintf(buf, "%lld", 123456789LL); 191 if (rc != 9 || strcmp(buf, "123456789") != 0) return 35; 192 193 rc = snprintf(buf, sizeof(buf), "%.2f/%+.1f", 12.375, 4.26); 194 if (rc != 10 || strcmp(buf, "12.38/+4.3") != 0) return 36; 195 196 rc = snprintf(buf, sizeof(buf), "%.2e %.4g", 1234.0, 12.340); 197 if (rc != 14 || strcmp(buf, "1.23e+03 12.34") != 0) return 37; 198 199 { 200 struct CallbackOut out; 201 out.len = 0; 202 memset(out.buf, 0, sizeof(out.buf)); 203 rc = fctprintf(capture_ch, &out, "%s:%04d", "cb", 9); 204 if (out.len >= (int)sizeof(out.buf)) return 38; 205 out.buf[out.len] = '\0'; 206 if (rc != 7 || strcmp(out.buf, "cb:0009") != 0) return 39; 207 } 208 209 /* '*' width/precision taken from an int argument (codes skip 42, the 210 * run.sh pass sentinel). */ 211 rc = snprintf(buf, sizeof(buf), "%.*s-%.*s", 7, "riscv64xx", 5, "linuxyy"); 212 if (rc != 13 || strcmp(buf, "riscv64-linux") != 0) return 40; 213 214 rc = snprintf(buf, sizeof(buf), "%*d", 5, 42); 215 if (rc != 5 || strcmp(buf, " 42") != 0) return 41; 216 217 /* Negative '*' width is read as a '-' flag plus a positive width. */ 218 rc = snprintf(buf, sizeof(buf), "%*d|", -5, 42); 219 if (rc != 6 || strcmp(buf, "42 |") != 0) return 43; 220 221 return 0; 222 } 223 224 int test_main(void) { 225 int rc; 226 assert(1); 227 if (!strings_ok()) return 1; 228 if (!stdlib_ok()) return 2; 229 if (!c23_bits_ok()) return 3; 230 rc = stdio_ok(); 231 if (rc != 0) return rc; 232 return 42; 233 }