#include #include #include #include /* for perror() */ #include /* for memcpy() */ #include /* for realloc(), free() */ #include /* for write() */ #define LM_ARRAY_LEN(ary) (sizeof(ary)/sizeof((ary)[0])) #define LM_CEILDIV(n, d) ( ((n)+(d)-1) / (d) ) #define LM_NEXT_POWER_OF_2(x) ( (x) ? 1ULL<<((sizeof(unsigned long long)*8)-__builtin_clzll(x)) : 1) #define LM_CAT2(a, b) a ## b #define LM_CAT2_(a, b) LM_CAT2(a, b) #define assert_notreached(msg) assert(false) struct buf { uint8_t *dat; size_t len; size_t cap; }; static void append(struct buf *buf, void *dat, size_t len) { assert(buf); assert(len == 0 || dat); if (buf->len + len > buf->cap) { buf->cap = LM_NEXT_POWER_OF_2(buf->len + len); buf->dat = realloc(buf->dat, buf->cap); assert(buf->dat); } memcpy(&buf->dat[buf->len], dat, len); buf->len += len; } static void append_u32be(struct buf *buf, uint32_t val) { assert(buf); uint8_t dat[4] = { (val>>(8*3))&0xFF, (val>>(8*2))&0xFF, (val>>(8*1))&0xFF, (val>>(8*0))&0xFF, }; append(buf, dat, sizeof(dat)); } static bool xwrite(int fd, uint8_t *dat, size_t len) { assert(len == 0 || dat); for (size_t done = 0; done < len;) { ssize_t n = write(fd, &dat[done], len-done); if (n < 0) { perror("write"); return true; } done += n; } return false; } static char font[10][8*4] = { " ## " " # # " " # # " " ## ", " # " " ## " " # " " ### ", " ## " " # # " " # " " #### ", " ## " " # " " # " " ## ", " ## " " # # " " #### " " # ", " #### " " ### " " # " " ### ", " # " " ### " " # # " " ## ", " #### " " # " " # " " # ", " ## " " # # " " #### " " ## ", " ## " " # # " " ### " " # ", }; static_assert(LM_ARRAY_LEN(font) == 10); static_assert(sizeof(font[0]) == 32);