kit

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

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 }