kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

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 }