|
@@ -1,845 +0,0 @@
|
|
|
-#include <assert.h>
|
|
|
|
|
-#include <devutil.h>
|
|
|
|
|
-#include <fcntl.h>
|
|
|
|
|
-#include <list.h>
|
|
|
|
|
-#include <stdint.h>
|
|
|
|
|
-#include <stdio.h>
|
|
|
|
|
-#include <stdarg.h>
|
|
|
|
|
-#include <stdlib.h>
|
|
|
|
|
-#include <string.h>
|
|
|
|
|
-#include <unistd.h>
|
|
|
|
|
-#include <priv-vars.h>
|
|
|
|
|
-
|
|
|
|
|
-static inline int __feof_or_error(FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- return !!(stream->flags & (FILE_ERROR | FILE_EOF));
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// where n is in the range of [0, 9]
|
|
|
|
|
-static inline char d_to_c(int32_t n)
|
|
|
|
|
-{
|
|
|
|
|
- return '0' + n;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// where n is between 0 and 15
|
|
|
|
|
-// base is either 'a' of 'A',
|
|
|
|
|
-// depending on you want capitalized
|
|
|
|
|
-// or not
|
|
|
|
|
-static inline char hex_to_c(int32_t n, char base)
|
|
|
|
|
-{
|
|
|
|
|
- if (n < 10) {
|
|
|
|
|
- // n belongs to [0, 9]
|
|
|
|
|
- return d_to_c(n);
|
|
|
|
|
- } else {
|
|
|
|
|
- // n belongs to [10, 15]
|
|
|
|
|
- return base + (n - 10);
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-static inline char x_to_c(int32_t n)
|
|
|
|
|
-{
|
|
|
|
|
- return hex_to_c(n, 'a');
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-static inline char X_to_c(int32_t n)
|
|
|
|
|
-{
|
|
|
|
|
- return hex_to_c(n, 'A');
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// this will check if there is still free space
|
|
|
|
|
-// in the buffer. if so, push the char into it,
|
|
|
|
|
-// change the value of buf_size and move pointer
|
|
|
|
|
-// forward
|
|
|
|
|
-//
|
|
|
|
|
-// x: char* buf
|
|
|
|
|
-// y: size_t buf_size
|
|
|
|
|
-// z: char c
|
|
|
|
|
-#define do_write_if_free(x, y, z) \
|
|
|
|
|
- if ((y) > 1) { \
|
|
|
|
|
- *((x)++) = (z); \
|
|
|
|
|
- --(y); \
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-static inline ssize_t
|
|
|
|
|
-snprint_decimal32(
|
|
|
|
|
- char* buf,
|
|
|
|
|
- size_t buf_size,
|
|
|
|
|
- int32_t num)
|
|
|
|
|
-{
|
|
|
|
|
- ssize_t n_write = 0;
|
|
|
|
|
-
|
|
|
|
|
- if (num < 0) {
|
|
|
|
|
- do_write_if_free(buf, buf_size, '-');
|
|
|
|
|
- ++n_write;
|
|
|
|
|
- num *= (-1);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- char* orig_buf = buf;
|
|
|
|
|
-
|
|
|
|
|
- do {
|
|
|
|
|
- do_write_if_free(buf, buf_size, d_to_c(num % 10));
|
|
|
|
|
- num /= 10;
|
|
|
|
|
- ++n_write;
|
|
|
|
|
- } while (num != 0);
|
|
|
|
|
-
|
|
|
|
|
- // prepend trailing '\0'
|
|
|
|
|
- if (buf_size > 0)
|
|
|
|
|
- *buf = 0x00;
|
|
|
|
|
-
|
|
|
|
|
- // move buf pointer to the last digit of number
|
|
|
|
|
- --buf;
|
|
|
|
|
-
|
|
|
|
|
- // reverse output
|
|
|
|
|
- while (orig_buf < buf) {
|
|
|
|
|
- char c = *buf;
|
|
|
|
|
- *buf = *orig_buf;
|
|
|
|
|
- *orig_buf = c;
|
|
|
|
|
- --buf;
|
|
|
|
|
- ++orig_buf;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return n_write;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-static inline ssize_t
|
|
|
|
|
-snprint_decimal64(
|
|
|
|
|
- char* buf,
|
|
|
|
|
- size_t buf_size,
|
|
|
|
|
- int64_t num)
|
|
|
|
|
-{
|
|
|
|
|
- ssize_t n_write = 0;
|
|
|
|
|
-
|
|
|
|
|
- if (num < 0) {
|
|
|
|
|
- do_write_if_free(buf, buf_size, '-');
|
|
|
|
|
- ++n_write;
|
|
|
|
|
- num *= (-1);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- char* orig_buf = buf;
|
|
|
|
|
-
|
|
|
|
|
- do {
|
|
|
|
|
- do_write_if_free(buf, buf_size, d_to_c(num % 10));
|
|
|
|
|
- num /= 10;
|
|
|
|
|
- ++n_write;
|
|
|
|
|
- } while (num != 0);
|
|
|
|
|
-
|
|
|
|
|
- // prepend trailing '\0'
|
|
|
|
|
- if (buf_size > 0)
|
|
|
|
|
- *buf = 0x00;
|
|
|
|
|
-
|
|
|
|
|
- // move buf pointer to the last digit of number
|
|
|
|
|
- --buf;
|
|
|
|
|
-
|
|
|
|
|
- // reverse output
|
|
|
|
|
- while (orig_buf < buf) {
|
|
|
|
|
- char c = *buf;
|
|
|
|
|
- *buf = *orig_buf;
|
|
|
|
|
- *orig_buf = c;
|
|
|
|
|
- --buf;
|
|
|
|
|
- ++orig_buf;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return n_write;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-static inline ssize_t
|
|
|
|
|
-snprint_hex32(
|
|
|
|
|
- char* buf,
|
|
|
|
|
- size_t buf_size,
|
|
|
|
|
- uint32_t num,
|
|
|
|
|
- int32_t capitalized)
|
|
|
|
|
-{
|
|
|
|
|
- ssize_t n_write = 0;
|
|
|
|
|
-
|
|
|
|
|
- do_write_if_free(buf, buf_size, '0');
|
|
|
|
|
- if (capitalized) {
|
|
|
|
|
- do_write_if_free(buf, buf_size, 'X');
|
|
|
|
|
- } else {
|
|
|
|
|
- do_write_if_free(buf, buf_size, 'x');
|
|
|
|
|
- }
|
|
|
|
|
- n_write += 2;
|
|
|
|
|
-
|
|
|
|
|
- char* orig_buf = buf;
|
|
|
|
|
-
|
|
|
|
|
- do {
|
|
|
|
|
- if (capitalized) {
|
|
|
|
|
- do_write_if_free(buf, buf_size, X_to_c(num % 16));
|
|
|
|
|
- } else {
|
|
|
|
|
- do_write_if_free(buf, buf_size, x_to_c(num % 16));
|
|
|
|
|
- }
|
|
|
|
|
- num /= 16;
|
|
|
|
|
- ++n_write;
|
|
|
|
|
- } while (num != 0);
|
|
|
|
|
-
|
|
|
|
|
- // prepend trailing '\0'
|
|
|
|
|
- if (buf_size > 0)
|
|
|
|
|
- *buf = 0x00;
|
|
|
|
|
-
|
|
|
|
|
- // move buf pointer to the last digit of number
|
|
|
|
|
- --buf;
|
|
|
|
|
-
|
|
|
|
|
- // reverse output
|
|
|
|
|
- while (orig_buf < buf) {
|
|
|
|
|
- char c = *buf;
|
|
|
|
|
- *buf = *orig_buf;
|
|
|
|
|
- *orig_buf = c;
|
|
|
|
|
- --buf;
|
|
|
|
|
- ++orig_buf;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return n_write;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-static inline ssize_t
|
|
|
|
|
-snprint_hex64(
|
|
|
|
|
- char* buf,
|
|
|
|
|
- size_t buf_size,
|
|
|
|
|
- uint64_t num,
|
|
|
|
|
- int32_t capitalized)
|
|
|
|
|
-{
|
|
|
|
|
- ssize_t n_write = 0;
|
|
|
|
|
-
|
|
|
|
|
- do_write_if_free(buf, buf_size, '0');
|
|
|
|
|
- if (capitalized) {
|
|
|
|
|
- do_write_if_free(buf, buf_size, 'X');
|
|
|
|
|
- } else {
|
|
|
|
|
- do_write_if_free(buf, buf_size, 'x');
|
|
|
|
|
- }
|
|
|
|
|
- n_write += 2;
|
|
|
|
|
-
|
|
|
|
|
- char* orig_buf = buf;
|
|
|
|
|
-
|
|
|
|
|
- do {
|
|
|
|
|
- if (capitalized) {
|
|
|
|
|
- do_write_if_free(buf, buf_size, X_to_c(num % 16));
|
|
|
|
|
- } else {
|
|
|
|
|
- do_write_if_free(buf, buf_size, x_to_c(num % 16));
|
|
|
|
|
- }
|
|
|
|
|
- num /= 16;
|
|
|
|
|
- ++n_write;
|
|
|
|
|
- } while (num != 0);
|
|
|
|
|
-
|
|
|
|
|
- // prepend trailing '\0'
|
|
|
|
|
- if (buf_size > 0)
|
|
|
|
|
- *buf = 0x00;
|
|
|
|
|
-
|
|
|
|
|
- // move buf pointer to the last digit of number
|
|
|
|
|
- --buf;
|
|
|
|
|
-
|
|
|
|
|
- // reverse output
|
|
|
|
|
- while (orig_buf < buf) {
|
|
|
|
|
- char c = *buf;
|
|
|
|
|
- *buf = *orig_buf;
|
|
|
|
|
- *orig_buf = c;
|
|
|
|
|
- --buf;
|
|
|
|
|
- ++orig_buf;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return n_write;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-static inline ssize_t
|
|
|
|
|
-snprint_char(
|
|
|
|
|
- char* buf,
|
|
|
|
|
- size_t buf_size,
|
|
|
|
|
- char c)
|
|
|
|
|
-{
|
|
|
|
|
- if (buf_size > 1)
|
|
|
|
|
- *buf = c;
|
|
|
|
|
- return sizeof(c);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int snprintf(char* buf, size_t bufsize, const char* fmt, ...)
|
|
|
|
|
-{
|
|
|
|
|
- va_list lst;
|
|
|
|
|
- va_start(lst, fmt);
|
|
|
|
|
-
|
|
|
|
|
- int ret = vsnprintf(buf, bufsize, fmt, lst);
|
|
|
|
|
-
|
|
|
|
|
- va_end(lst);
|
|
|
|
|
-
|
|
|
|
|
- return ret;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int vsnprintf(char* buf, size_t buf_size, const char* fmt, va_list arg)
|
|
|
|
|
-{
|
|
|
|
|
- ssize_t n_write = 0;
|
|
|
|
|
-
|
|
|
|
|
- for (char c; (c = *fmt) != 0x00; ++fmt) {
|
|
|
|
|
- if (c == '%') {
|
|
|
|
|
- size_t n_tmp_write = 0;
|
|
|
|
|
-
|
|
|
|
|
- switch (*(++fmt)) {
|
|
|
|
|
-
|
|
|
|
|
- // int
|
|
|
|
|
- case 'd':
|
|
|
|
|
- n_tmp_write = snprint_decimal32(buf, buf_size, va_arg(arg, int));
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case 'x':
|
|
|
|
|
- n_tmp_write = snprint_hex32(buf, buf_size, va_arg(arg, unsigned int), 0);
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case 'X':
|
|
|
|
|
- n_tmp_write = snprint_hex32(buf, buf_size, va_arg(arg, unsigned int), 1);
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- // long decimal
|
|
|
|
|
- case 'l':
|
|
|
|
|
- switch (*(++fmt)) {
|
|
|
|
|
- // long long aka int64
|
|
|
|
|
- case 'l':
|
|
|
|
|
- switch (*(++fmt)) {
|
|
|
|
|
- case 'd':
|
|
|
|
|
- n_tmp_write = snprint_decimal64(buf, buf_size, va_arg(arg, long long));
|
|
|
|
|
- break;
|
|
|
|
|
- case 'x':
|
|
|
|
|
- n_tmp_write = snprint_hex64(buf, buf_size, va_arg(arg, unsigned long long), 0);
|
|
|
|
|
- break;
|
|
|
|
|
- case 'X':
|
|
|
|
|
- n_tmp_write = snprint_hex64(buf, buf_size, va_arg(arg, unsigned long long), 1);
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- break;
|
|
|
|
|
- // long int aka int32
|
|
|
|
|
- case 'd':
|
|
|
|
|
- n_tmp_write = snprint_decimal32(buf, buf_size, va_arg(arg, long));
|
|
|
|
|
- break;
|
|
|
|
|
- case 'x':
|
|
|
|
|
- n_tmp_write = snprint_hex32(buf, buf_size, va_arg(arg, unsigned long), 0);
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case 'X':
|
|
|
|
|
- n_tmp_write = snprint_hex32(buf, buf_size, va_arg(arg, unsigned long), 1);
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- // c string
|
|
|
|
|
- case 's':
|
|
|
|
|
- n_tmp_write = snprintf(buf, buf_size, va_arg(arg, const char*));
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- // int8 char
|
|
|
|
|
- case 'c':
|
|
|
|
|
- n_tmp_write = snprint_char(buf, buf_size, va_arg(arg, int));
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- // pointer
|
|
|
|
|
- case 'p':
|
|
|
|
|
-#ifdef __32bit_system
|
|
|
|
|
- n_tmp_write = snprint_hex32(buf, buf_size, va_arg(arg, size_t), 0);
|
|
|
|
|
-#else
|
|
|
|
|
- n_tmp_write = snprint_hex64(buf, buf_size, va_arg(arg, size_t), 0);
|
|
|
|
|
-#endif
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- default:
|
|
|
|
|
- n_tmp_write = snprint_char(buf, buf_size, *(fmt - 1));
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- n_write += n_tmp_write;
|
|
|
|
|
- if (buf_size > 1) {
|
|
|
|
|
- if (buf_size > n_tmp_write) {
|
|
|
|
|
- buf += n_tmp_write;
|
|
|
|
|
- buf_size -= n_tmp_write;
|
|
|
|
|
- } else {
|
|
|
|
|
- // no enough space
|
|
|
|
|
- // shrink buf_size to one
|
|
|
|
|
- buf += (buf_size - 1);
|
|
|
|
|
- buf_size = 1;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- } else {
|
|
|
|
|
- ++n_write;
|
|
|
|
|
- do_write_if_free(buf, buf_size, c);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (buf_size > 0)
|
|
|
|
|
- *buf = 0x00;
|
|
|
|
|
-
|
|
|
|
|
- return n_write;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int sprintf(char* buf, const char* fmt, ...)
|
|
|
|
|
-{
|
|
|
|
|
- va_list lst;
|
|
|
|
|
- va_start(lst, fmt);
|
|
|
|
|
-
|
|
|
|
|
- int ret = vsnprintf(buf, __SIZE_MAX__, fmt, lst);
|
|
|
|
|
-
|
|
|
|
|
- va_end(lst);
|
|
|
|
|
-
|
|
|
|
|
- return ret;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int puts(const char* str)
|
|
|
|
|
-{
|
|
|
|
|
- return fputs(str, stdout);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-char* gets(char* buf)
|
|
|
|
|
-{
|
|
|
|
|
- int c, num = 0;
|
|
|
|
|
- while ((c = getchar()) != EOF && c != '\n')
|
|
|
|
|
- buf[num++] = c;
|
|
|
|
|
- buf[num] = 0;
|
|
|
|
|
-
|
|
|
|
|
- if (c == EOF)
|
|
|
|
|
- return NULL;
|
|
|
|
|
- return buf;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int vfprintf_u32(uint32_t num, FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- if (num <= 9) {
|
|
|
|
|
- fputc(d_to_c(num), stream);
|
|
|
|
|
- return 1;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- int ret = vfprintf_u32(num / 10, stream);
|
|
|
|
|
- fputc(d_to_c(num % 10), stream);
|
|
|
|
|
- return ret + 1;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int vfprintf_d32(int32_t num, FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- if (num < 0) {
|
|
|
|
|
- fputc('-', stream);
|
|
|
|
|
- return vfprintf_u32(-num, stream) + 1;
|
|
|
|
|
- }
|
|
|
|
|
- return vfprintf_u32(num, stream);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int vfprintf_u64(uint64_t num, FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- if (num <= 9) {
|
|
|
|
|
- fputc(d_to_c(num), stream);
|
|
|
|
|
- return 1;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- int ret = vfprintf_u64(num / 10, stream);
|
|
|
|
|
- fputc(d_to_c(num % 10), stream);
|
|
|
|
|
- return ret + 1;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int vfprintf_d64(int64_t num, FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- if (num < 0) {
|
|
|
|
|
- fputc('-', stream);
|
|
|
|
|
- return vfprintf_u64(-num, stream) + 1;
|
|
|
|
|
- }
|
|
|
|
|
- return vfprintf_u64(num, stream);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int vfprintf_x32(uint32_t num, int off, FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- // print leading 0x
|
|
|
|
|
- if (off & 1) {
|
|
|
|
|
- --off;
|
|
|
|
|
- fputc('0', stream);
|
|
|
|
|
- fputc('X' + off, stream);
|
|
|
|
|
- return vfprintf_x32(num, off, stream) + 2;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (num <= 15) {
|
|
|
|
|
- fputc(X_to_c(num) + off, stream);
|
|
|
|
|
- return 1;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- int ret = vfprintf_x32(num >> 4, off, stream);
|
|
|
|
|
- fputc(X_to_c(num & 0xf) + off, stream);
|
|
|
|
|
- return ret + 1;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int vfprintf_x64(uint64_t num, int off, FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- // print leading 0x
|
|
|
|
|
- if (off & 1) {
|
|
|
|
|
- --off;
|
|
|
|
|
- fputc('0', stream);
|
|
|
|
|
- fputc('X' + off, stream);
|
|
|
|
|
- return vfprintf_x64(num, off, stream) + 2;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (num <= 15) {
|
|
|
|
|
- fputc(X_to_c(num) + off, stream);
|
|
|
|
|
- return 1;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- int ret = vfprintf_x64(num >> 4, off, stream);
|
|
|
|
|
- fputc(X_to_c(num & 0xf) + off, stream);
|
|
|
|
|
- return ret + 1;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int vfprintf(FILE* stream, const char* fmt, va_list args)
|
|
|
|
|
-{
|
|
|
|
|
- int n = 0;
|
|
|
|
|
-
|
|
|
|
|
- for (char c = 0; (c = *fmt) != 0x00; ++fmt) {
|
|
|
|
|
- if (c == '%') {
|
|
|
|
|
- switch (*(++fmt)) {
|
|
|
|
|
-
|
|
|
|
|
- // int
|
|
|
|
|
- case 'd':
|
|
|
|
|
- n += vfprintf_d32(va_arg(args, int), stream);
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case 'x':
|
|
|
|
|
- n += vfprintf_x32(va_arg(args, unsigned int), 'a' - 'A' + 1, stream);
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case 'X':
|
|
|
|
|
- n += vfprintf_x32(va_arg(args, unsigned int), 1, stream);
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- // long decimal
|
|
|
|
|
- case 'l':
|
|
|
|
|
- switch (*(++fmt)) {
|
|
|
|
|
- // long long aka int64
|
|
|
|
|
- case 'l':
|
|
|
|
|
- switch (*(++fmt)) {
|
|
|
|
|
- case 'd':
|
|
|
|
|
- n += vfprintf_d64(va_arg(args, long long), stream);
|
|
|
|
|
- break;
|
|
|
|
|
- case 'x':
|
|
|
|
|
- n += vfprintf_x64(va_arg(args, unsigned long long), 'a' - 'A' + 1, stream);
|
|
|
|
|
- break;
|
|
|
|
|
- case 'X':
|
|
|
|
|
- n += vfprintf_x64(va_arg(args, unsigned long long), 'a' - 'A' + 1, stream);
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- break;
|
|
|
|
|
- // long int aka int32
|
|
|
|
|
- case 'd':
|
|
|
|
|
- n += vfprintf_d32(va_arg(args, int), stream);
|
|
|
|
|
- break;
|
|
|
|
|
- case 'x':
|
|
|
|
|
- n += vfprintf_x32(va_arg(args, unsigned int), 'a' - 'A' + 1, stream);
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case 'X':
|
|
|
|
|
- n += vfprintf_x32(va_arg(args, unsigned int), 1, stream);
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- // c string
|
|
|
|
|
- case 's':
|
|
|
|
|
- n += fprintf(stream, va_arg(args, const char*));
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- // int8 char
|
|
|
|
|
- case 'c':
|
|
|
|
|
- ++n;
|
|
|
|
|
- fputc(va_arg(args, int), stream);
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- // pointer
|
|
|
|
|
- case 'p':
|
|
|
|
|
-#ifdef __32bit_system
|
|
|
|
|
- n += vfprintf_x32(va_arg(args, size_t), 'a' - 'A' + 1, stream);
|
|
|
|
|
-#else
|
|
|
|
|
- n += vfprintf_x64(va_arg(args, size_t), 'a' - 'A' + 1, stream);
|
|
|
|
|
-#endif
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- default:
|
|
|
|
|
- ++n;
|
|
|
|
|
- fputc(*(fmt - 1), stream);
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- ++n;
|
|
|
|
|
- fputc(c, stream);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return n;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int fprintf(FILE* stream, const char* fmt, ...)
|
|
|
|
|
-{
|
|
|
|
|
- va_list args;
|
|
|
|
|
- va_start(args, fmt);
|
|
|
|
|
-
|
|
|
|
|
- int ret = vfprintf(stream, fmt, args);
|
|
|
|
|
-
|
|
|
|
|
- va_end(args);
|
|
|
|
|
- return ret;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int vprintf(const char* fmt, va_list args)
|
|
|
|
|
-{
|
|
|
|
|
- return vfprintf(stdout, fmt, args);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int printf(const char* fmt, ...)
|
|
|
|
|
-{
|
|
|
|
|
- va_list args;
|
|
|
|
|
- va_start(args, fmt);
|
|
|
|
|
-
|
|
|
|
|
- int ret = vprintf(fmt, args);
|
|
|
|
|
-
|
|
|
|
|
- va_end(args);
|
|
|
|
|
- return ret;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int putchar(int c)
|
|
|
|
|
-{
|
|
|
|
|
- fputc(c, stdout);
|
|
|
|
|
- return c;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-FILE* fopen(const char* path, const char* mode)
|
|
|
|
|
-{
|
|
|
|
|
- uint32_t flags = 0, file_flags = 0;
|
|
|
|
|
-
|
|
|
|
|
- if (strcmp(mode, "r") == 0)
|
|
|
|
|
- flags = O_RDONLY, file_flags = FILE_READ;
|
|
|
|
|
-
|
|
|
|
|
- if (strcmp(mode, "r+") == 0)
|
|
|
|
|
- flags = O_RDWR, file_flags = FILE_READ | FILE_WRITE;
|
|
|
|
|
-
|
|
|
|
|
- if (strcmp(mode, "w") == 0)
|
|
|
|
|
- flags = O_WRONLY | O_CREAT | O_TRUNC, file_flags = FILE_WRITE;
|
|
|
|
|
-
|
|
|
|
|
- if (strcmp(mode, "w+") == 0)
|
|
|
|
|
- flags = O_RDWR | O_CREAT | O_TRUNC, file_flags = FILE_READ | FILE_WRITE;
|
|
|
|
|
-
|
|
|
|
|
- assert(flags);
|
|
|
|
|
-
|
|
|
|
|
- int fd = open(path, flags, 0644);
|
|
|
|
|
- if (fd < 0)
|
|
|
|
|
- goto open_fail;
|
|
|
|
|
-
|
|
|
|
|
- FILE* file = malloc(sizeof(FILE));
|
|
|
|
|
- if (!file)
|
|
|
|
|
- goto file_malloc_fail;
|
|
|
|
|
-
|
|
|
|
|
- file->fd = fd;
|
|
|
|
|
- file->flags = file_flags;
|
|
|
|
|
-
|
|
|
|
|
- if (file_flags & FILE_READ) {
|
|
|
|
|
- file->rbuf = malloc(BUFSIZ);
|
|
|
|
|
- if (!file->rbuf)
|
|
|
|
|
- goto rbuf_malloc_fail;
|
|
|
|
|
- file->rbsz = BUFSIZ;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (file_flags & FILE_WRITE) {
|
|
|
|
|
- file->wbuf = malloc(BUFSIZ);
|
|
|
|
|
- if (!file->wbuf)
|
|
|
|
|
- goto wbuf_malloc_fail;
|
|
|
|
|
- file->wbsz = BUFSIZ;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return file;
|
|
|
|
|
-
|
|
|
|
|
-wbuf_malloc_fail:
|
|
|
|
|
- free(file->rbuf);
|
|
|
|
|
-
|
|
|
|
|
-rbuf_malloc_fail:
|
|
|
|
|
- free(file);
|
|
|
|
|
-
|
|
|
|
|
-file_malloc_fail:
|
|
|
|
|
- close(fd);
|
|
|
|
|
-
|
|
|
|
|
-open_fail:
|
|
|
|
|
- return NULL;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int fflush(FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- if (__feof_or_error(stream))
|
|
|
|
|
- return EOF;
|
|
|
|
|
-
|
|
|
|
|
- if (stream->wbuf && stream->wpos) {
|
|
|
|
|
- int ret = write(stream->fd, stream->wbuf, stream->wpos);
|
|
|
|
|
- if (ret < 0) {
|
|
|
|
|
- stream->flags |= FILE_ERROR;
|
|
|
|
|
- return EOF;
|
|
|
|
|
- }
|
|
|
|
|
- if (ret == 0) {
|
|
|
|
|
- stream->flags |= FILE_EOF;
|
|
|
|
|
- return EOF;
|
|
|
|
|
- }
|
|
|
|
|
- stream->wpos = 0;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // TODO: call flush()
|
|
|
|
|
-
|
|
|
|
|
- return 0;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int fclose(FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- if (fflush(stream) == EOF)
|
|
|
|
|
- return EOF;
|
|
|
|
|
-
|
|
|
|
|
- free(stream->rbuf);
|
|
|
|
|
- free(stream->wbuf);
|
|
|
|
|
- stream->rbsz = 0;
|
|
|
|
|
- stream->wbsz = 0;
|
|
|
|
|
-
|
|
|
|
|
- if (close(stream->fd) < 0)
|
|
|
|
|
- return EOF;
|
|
|
|
|
-
|
|
|
|
|
- NDERASE(NDPTR(stream));
|
|
|
|
|
-
|
|
|
|
|
- return 0;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int fputc_unlocked(int c, FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- return putc_unlocked(c, stream);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int fputs_unlocked(const char* s, FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- // 1 is for the trailing '\n'
|
|
|
|
|
- int len = 1;
|
|
|
|
|
- for (const char* p = s; *p; ++p, ++len)
|
|
|
|
|
- fputc_unlocked(*p, stream);
|
|
|
|
|
- fputc_unlocked('\n', stream);
|
|
|
|
|
- return len;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int fputc(int c, FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- // TODO: lock the stream
|
|
|
|
|
- return putc_unlocked(c, stream);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int fputs(const char* s, FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- // TODO: lock the stream
|
|
|
|
|
- return fputs_unlocked(s, stream);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-static inline int __fillbuf(FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- if ((stream->rcnt = read(stream->fd, stream->rbuf, stream->rbsz)) >= 2147483648U) {
|
|
|
|
|
- stream->rcnt = 0;
|
|
|
|
|
- stream->flags |= FILE_ERROR;
|
|
|
|
|
- return EOF;
|
|
|
|
|
- }
|
|
|
|
|
- if (stream->rcnt == 0) {
|
|
|
|
|
- stream->flags |= FILE_EOF;
|
|
|
|
|
- return EOF;
|
|
|
|
|
- }
|
|
|
|
|
- stream->rpos = 0;
|
|
|
|
|
- return 0;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int getc_unlocked(FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- if (__feof_or_error(stream))
|
|
|
|
|
- return EOF;
|
|
|
|
|
-
|
|
|
|
|
- if (stream->rbuf) {
|
|
|
|
|
- if (stream->rpos == stream->rcnt) {
|
|
|
|
|
- if (__fillbuf(stream) < 0)
|
|
|
|
|
- return EOF;
|
|
|
|
|
- }
|
|
|
|
|
- return stream->rbuf[stream->rpos++];
|
|
|
|
|
- } else {
|
|
|
|
|
- int c;
|
|
|
|
|
- int ret = read(stream->fd, &c, 1);
|
|
|
|
|
- if (ret < 0) {
|
|
|
|
|
- stream->flags |= FILE_ERROR;
|
|
|
|
|
- return EOF;
|
|
|
|
|
- }
|
|
|
|
|
- if (ret == 0) {
|
|
|
|
|
- stream->flags |= FILE_EOF;
|
|
|
|
|
- return EOF;
|
|
|
|
|
- }
|
|
|
|
|
- return c;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int putc_unlocked(int c, FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- if (__feof_or_error(stream))
|
|
|
|
|
- return EOF;
|
|
|
|
|
-
|
|
|
|
|
- if (stream->wbuf) {
|
|
|
|
|
- stream->wbuf[stream->wpos++] = c;
|
|
|
|
|
- if (stream->wpos == stream->wbsz || c == '\n')
|
|
|
|
|
- if (fflush(stream) == EOF)
|
|
|
|
|
- return EOF;
|
|
|
|
|
- } else {
|
|
|
|
|
- if (write(stream->fd, &c, 1) < 0) {
|
|
|
|
|
- stream->flags |= FILE_ERROR;
|
|
|
|
|
- return EOF;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return c;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int getchar(void)
|
|
|
|
|
-{
|
|
|
|
|
- return fgetc(stdin);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int fgetc(FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- return getc_unlocked(stream);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int ferror(FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- // TODO: lock the stream
|
|
|
|
|
- return ferror_unlocked(stream);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int ferror_unlocked(FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- return stream->flags & FILE_ERROR;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int feof(FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- return stream->flags & FILE_EOF;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-void clearerr(FILE* stream)
|
|
|
|
|
-{
|
|
|
|
|
- stream->flags &= ~FILE_ERROR;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int vasprintf(char** strp, const char* fmt, va_list args)
|
|
|
|
|
-{
|
|
|
|
|
- // TODO: this is WAY TOO SLOWWWWWWWWW
|
|
|
|
|
- int sz = 8, n;
|
|
|
|
|
- char* buf = NULL;
|
|
|
|
|
-
|
|
|
|
|
- do {
|
|
|
|
|
- buf = realloc(buf, sz *= 2);
|
|
|
|
|
- if (!buf)
|
|
|
|
|
- return -1;
|
|
|
|
|
-
|
|
|
|
|
- n = vsnprintf(buf, sz, fmt, args);
|
|
|
|
|
- if (sz > n)
|
|
|
|
|
- break;
|
|
|
|
|
- } while (1);
|
|
|
|
|
-
|
|
|
|
|
- *strp = buf;
|
|
|
|
|
- return n;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int asprintf(char** strp, const char* fmt, ...)
|
|
|
|
|
-{
|
|
|
|
|
- va_list lst;
|
|
|
|
|
- va_start(lst, fmt);
|
|
|
|
|
-
|
|
|
|
|
- int ret = vasprintf(strp, fmt, lst);
|
|
|
|
|
-
|
|
|
|
|
- va_end(lst);
|
|
|
|
|
-
|
|
|
|
|
- return ret;
|
|
|
|
|
-}
|
|
|