freestanding_lib.c (4830B)
1 #include <assert.h> 2 #include <stdarg.h> 3 #include <stddef.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 8 static int cmp_int(const void* a, const void* b) { 9 int lhs = *(const int*)a; 10 int rhs = *(const int*)b; 11 return (lhs > rhs) - (lhs < rhs); 12 } 13 14 static int check_vsnprintf(char* out, size_t n, const char* fmt, ...) { 15 va_list ap; 16 int rc; 17 va_start(ap, fmt); 18 rc = vsnprintf(out, n, fmt, ap); 19 va_end(ap); 20 return rc; 21 } 22 23 static int check_vsprintf(char* out, const char* fmt, ...) { 24 va_list ap; 25 int rc; 26 va_start(ap, fmt); 27 rc = vsprintf(out, fmt, ap); 28 va_end(ap); 29 return rc; 30 } 31 32 struct CallbackOut { 33 char buf[32]; 34 int len; 35 }; 36 37 static void capture_ch(char ch, void* arg) { 38 struct CallbackOut* out = (struct CallbackOut*)arg; 39 if (out->len < (int)sizeof(out->buf) - 1) { 40 out->buf[out->len] = ch; 41 } 42 out->len++; 43 } 44 45 static int strings_ok(void) { 46 char buf[32]; 47 char small[8]; 48 const char* text = "alpha beta"; 49 50 memset(buf, 0, sizeof(buf)); 51 memcpy(buf, "abc", 4); 52 memmove(buf + 1, buf, 3); 53 if (strcmp(buf, "aabc") != 0) return 0; 54 if (memcmp(buf, "aabc", 4) != 0) return 0; 55 if (*(char*)memchr(buf, 'b', 4) != 'b') return 0; 56 57 strcpy(buf, "alpha"); 58 strcat(buf, " "); 59 strncat(buf, "beta!", 4); 60 if (strcmp(buf, text) != 0) return 0; 61 if (strncmp(buf, "alpha", 5) != 0) return 0; 62 if (strlen(buf) != 10) return 0; 63 if (strnlen(buf, 4) != 4) return 0; 64 if (strchr(buf, ' ') != buf + 5) return 0; 65 if (strrchr(buf, 'a') != buf + 9) return 0; 66 if (strstr(buf, "ha be") != buf + 3) return 0; 67 68 strncpy(small, "xy", sizeof(small)); 69 if (small[0] != 'x' || small[1] != 'y' || small[2] != '\0') return 0; 70 return 1; 71 } 72 73 static int stdlib_ok(void) { 74 char* end; 75 int values[6] = {5, 1, 4, 2, 3, 0}; 76 int key = 4; 77 int* found; 78 div_t d; 79 ldiv_t ld; 80 lldiv_t lld; 81 82 if (atoi(" -42x") != -42) return 0; 83 if (atol("123") != 123L) return 0; 84 if (atoll("-456") != -456LL) return 0; 85 if (strtol("0x2a!", &end, 0) != 42 || *end != '!') return 0; 86 if (strtoll("-077", &end, 0) != -63 || *end != '\0') return 0; 87 if (strtoul("101", &end, 2) != 5UL || *end != '\0') return 0; 88 if (strtoull("ff", &end, 16) != 255ULL || *end != '\0') return 0; 89 if ((int)(strtod("12.5e1z", &end) + 0.5) != 125 || *end != 'z') return 0; 90 if ((int)(strtof("4.25", &end) * 4.0f) != 17 || *end != '\0') return 0; 91 if ((int)strtold("9.0", &end) != 9 || *end != '\0') return 0; 92 93 if (abs(-7) != 7 || labs(-8L) != 8L || llabs(-9LL) != 9LL) return 0; 94 d = div(17, 5); 95 ld = ldiv(17L, 5L); 96 lld = lldiv(17LL, 5LL); 97 if (d.quot != 3 || d.rem != 2) return 0; 98 if (ld.quot != 3 || ld.rem != 2) return 0; 99 if (lld.quot != 3 || lld.rem != 2) return 0; 100 101 qsort(values, 6, sizeof(values[0]), cmp_int); 102 for (int i = 0; i < 6; i++) { 103 if (values[i] != i) return 0; 104 } 105 found = bsearch(&key, values, 6, sizeof(values[0]), cmp_int); 106 if (found == NULL || *found != key) return 0; 107 return 1; 108 } 109 110 static int stdio_ok(void) { 111 char buf[64]; 112 int rc; 113 114 rc = snprintf(buf, sizeof(buf), "%s:%d:%04x:%c", "id", -7, 26, '!'); 115 if (rc != 12 || strcmp(buf, "id:-7:001a:!") != 0) return 31; 116 117 rc = snprintf(buf, 6, "abcdef"); 118 if (rc != 6 || strcmp(buf, "abcde") != 0) return 32; 119 120 rc = sprintf(buf, "%u/%ld/%p", 12U, 34L, (void*)0x1234); 121 if (rc <= 0 || strstr(buf, "12/34/") != buf) return 33; 122 123 rc = check_vsnprintf(buf, sizeof(buf), "%s %02d", "v", 3); 124 if (rc != 4 || strcmp(buf, "v 03") != 0) return 34; 125 126 rc = check_vsprintf(buf, "%lld", 123456789LL); 127 if (rc != 9 || strcmp(buf, "123456789") != 0) return 35; 128 129 rc = snprintf(buf, sizeof(buf), "%.2f/%+.1f", 12.375, 4.26); 130 if (rc != 10 || strcmp(buf, "12.38/+4.3") != 0) return 36; 131 132 rc = snprintf(buf, sizeof(buf), "%.2e %.4g", 1234.0, 12.340); 133 if (rc != 14 || strcmp(buf, "1.23e+03 12.34") != 0) return 37; 134 135 { 136 struct CallbackOut out; 137 out.len = 0; 138 memset(out.buf, 0, sizeof(out.buf)); 139 rc = fctprintf(capture_ch, &out, "%s:%04d", "cb", 9); 140 if (out.len >= (int)sizeof(out.buf)) return 38; 141 out.buf[out.len] = '\0'; 142 if (rc != 7 || strcmp(out.buf, "cb:0009") != 0) return 39; 143 } 144 145 /* '*' width/precision taken from an int argument (codes skip 42, the 146 * run.sh pass sentinel). */ 147 rc = snprintf(buf, sizeof(buf), "%.*s-%.*s", 7, "riscv64xx", 5, "linuxyy"); 148 if (rc != 13 || strcmp(buf, "riscv64-linux") != 0) return 40; 149 150 rc = snprintf(buf, sizeof(buf), "%*d", 5, 42); 151 if (rc != 5 || strcmp(buf, " 42") != 0) return 41; 152 153 /* Negative '*' width is read as a '-' flag plus a positive width. */ 154 rc = snprintf(buf, sizeof(buf), "%*d|", -5, 42); 155 if (rc != 6 || strcmp(buf, "42 |") != 0) return 43; 156 157 return 0; 158 } 159 160 int test_main(void) { 161 int rc; 162 assert(1); 163 if (!strings_ok()) return 1; 164 if (!stdlib_ok()) return 2; 165 rc = stdio_ok(); 166 if (rc != 0) return rc; 167 return 42; 168 }