diff options
| -rw-r--r-- | any_log.h | 15 | ||||
| -rw-r--r-- | any_sexp.h | 63 | ||||
| -rw-r--r-- | test/log.c | 2 | ||||
| -rw-r--r-- | test/sexp.c | 4 |
4 files changed, 49 insertions, 35 deletions
@@ -142,15 +142,15 @@ typedef enum { // f | double | "%lf" // s | char * (0-terminated) | "%s" // -// c | any_log_formatter_t (function), void * +// g | any_log_formatter_t (function), void * // // If no type specifier is given the function will assume the type given // by ANY_LOG_VALUE_DEFAULT_TYPE (by default string). // -// You can log custom types with the 'c' specifier. Then you will have to -// pass two parameters: a format function of type any_log_formatter_t and -// a value parameter of type void *. -// By defining ANY_LOG_NO_CUSTOM you can disable the custom type specifier. +// The 'g' specifier is handled differently than the others. It needs two parameters, +// the first must be a custom formatter function (of type any_log_formatter_t) to +// format the second value of type void *. +// By defining ANY_LOG_NO_CUSTOM you can disable this custom type specifier. // // Example usage of value logging // @@ -160,7 +160,7 @@ typedef enum { // "p:window", window_handle, // "f:scale", scale_factor_dpi, // "b:hidden", visibility == HIDDEN, -// "c:widgets", ANY_LOG_FORMATTER(widget_format), widgets, +// "g:widgets", ANY_LOG_FORMATTER(widget_format), widgets, // "appname", "nice app"); // // In the implementation you can customize the format of every key-value pair @@ -180,6 +180,7 @@ typedef enum { // #define ANY_LOG_VALUE_DOUBLE(key, value) "\"%s\": %lf", key, value // #define ANY_LOG_VALUE_STRING(key, value) "\"%s \": \"%s\"", key, value // #define ANY_LOG_VALUE_AFTER(level, module, func, message) "}\n" +// #define ANY_LOG_NO_CUSTOM // #include "any_log.h" // // As with log_trace and log_debug, log_value_trace and log_value_debug can be @@ -609,7 +610,7 @@ void any_log_value(any_log_level_t level, const char *module, } #ifndef ANY_LOG_NO_CUSTOM - case 'c': { + case 'g': { any_log_formatter_t formatter = va_arg(args, any_log_formatter_t); void *value = va_arg(args, void *); ANY_LOG_VALUE_CUSTOM(key, any_log_stream, formatter, value); @@ -65,11 +65,12 @@ typedef void *any_sexp_t; #define ANY_SEXP_ERROR (any_sexp_t)UINTPTR_MAX #define ANY_SEXP_NIL (any_sexp_t)NULL -#define ANY_SEXP_BITS_SHIFT (sizeof(uintptr_t) * 8 - 4) -#define ANY_SEXP_UNTAG(sexp) (any_sexp_t)((uintptr_t)(sexp) & ~((uintptr_t)0xf << ANY_SEXP_BITS_SHIFT)) +#define ANY_SEXP_BIT_SHIFT (sizeof(uintptr_t) * 8 - 4) +#define ANY_SEXP_BIT_SIGN ((uintptr_t)1 << (ANY_SEXP_BIT_SHIFT - 1)) +#define ANY_SEXP_UNTAG(sexp) (any_sexp_t)((uintptr_t)(sexp) & ~((uintptr_t)0xf << ANY_SEXP_BIT_SHIFT)) -#define ANY_SEXP_TAG(sexp, tag) (any_sexp_t)((uintptr_t)(sexp) | ((uintptr_t)tag << ANY_SEXP_BITS_SHIFT)) -#define ANY_SEXP_GET_TAG(sexp) (((uintptr_t)(sexp) >> ANY_SEXP_BITS_SHIFT) & 0xf) +#define ANY_SEXP_TAG(sexp, tag) (any_sexp_t)((uintptr_t)(sexp) | ((uintptr_t)tag << ANY_SEXP_BIT_SHIFT)) +#define ANY_SEXP_GET_TAG(sexp) (((uintptr_t)(sexp) >> ANY_SEXP_BIT_SHIFT) & 0xf) #define ANY_SEXP_GET_CONS(sexp) ((any_sexp_cons_t *)ANY_SEXP_UNTAG(sexp)) #define ANY_SEXP_GET_SYMBOL(sexp) (((char *)ANY_SEXP_UNTAG(sexp))) #define ANY_SEXP_GET_STRING(sexp) (((char *)ANY_SEXP_UNTAG(sexp))) @@ -78,12 +79,11 @@ typedef void *any_sexp_t; static inline intptr_t any_sexp_number_untag(any_sexp_t sexp) { uintptr_t ptr = (uintptr_t)ANY_SEXP_UNTAG(sexp); - uintptr_t sign_bit = (uintptr_t)1 << (ANY_SEXP_BITS_SHIFT - 1); - uintptr_t clear = ptr & ~(sign_bit | (uintptr_t)0xf << ANY_SEXP_BITS_SHIFT); + uintptr_t clear = ptr & ~((uintptr_t)0x1f << (ANY_SEXP_BIT_SHIFT - 1)); // NOTE: Pad with 1's to adjust the two's complement when the sign is negative - if (ptr & sign_bit) - clear |= (uintptr_t)0x1f << (ANY_SEXP_BITS_SHIFT - 1); + if (ptr & ANY_SEXP_BIT_SIGN) + clear |= (uintptr_t)0x1f << (ANY_SEXP_BIT_SHIFT - 1); return *(intptr_t *)&clear; } @@ -411,7 +411,7 @@ static int any_sexp_writer_puts(any_sexp_writer_t *writer, const char *string) static int any_sexp_writer_putnum(any_sexp_writer_t *writer, intptr_t value) { - int c; + int c = 0; if (value > 9) { c = any_sexp_writer_putnum(writer, value / 10); value %= 10; @@ -435,16 +435,17 @@ int any_sexp_write(any_sexp_writer_t *writer, any_sexp_t sexp) case ANY_SEXP_TAG_ERROR: return any_sexp_writer_puts(writer, "<error>"); - case ANY_SEXP_TAG_NIL: - return writer->putc(ANY_SEXP_CHAR_OPEN, writer->stream) == EOF - || writer->putc(ANY_SEXP_CHAR_CLOSE, writer->stream) == EOF - ? EOF : 2; + case ANY_SEXP_TAG_NIL: { + const char nil[3] = { ANY_SEXP_CHAR_OPEN, ANY_SEXP_CHAR_CLOSE, '\0' }; + return any_sexp_writer_puts(writer, nil); + } case ANY_SEXP_TAG_CONS: { + any_sexp_t car = any_sexp_car(sexp), cdr = any_sexp_cdr(sexp); + #ifndef ANY_SEXP_NO_QUOTE - any_sexp_t cdr = any_sexp_cdr(sexp); - if (ANY_SEXP_IS_SYMBOL(any_sexp_car(sexp)) && ANY_SEXP_IS_NIL(any_sexp_cdr(cdr)) && - !strcmp(ANY_SEXP_GET_SYMBOL(any_sexp_car(sexp)), ANY_SEXP_QUOTE_SYMBOL)) { + if (ANY_SEXP_IS_SYMBOL(car) && ANY_SEXP_IS_NIL(any_sexp_cdr(cdr)) && + !strcmp(ANY_SEXP_GET_SYMBOL(car), ANY_SEXP_QUOTE_SYMBOL)) { if (writer->putc(ANY_SEXP_CHAR_QUOTE, writer->stream) == EOF) return EOF; @@ -457,19 +458,28 @@ int any_sexp_write(any_sexp_writer_t *writer, any_sexp_t sexp) return EOF; int c = 2, tmp; - while (!ANY_SEXP_IS_NIL(sexp) && !ANY_SEXP_IS_ERROR(sexp)) { - tmp = any_sexp_write(writer, any_sexp_car(sexp)); - sexp = any_sexp_cdr(sexp); - + while (true) { + tmp = any_sexp_write(writer, car); if (tmp == EOF) return EOF; + c += tmp; - if (!ANY_SEXP_IS_NIL(sexp)) { + if (ANY_SEXP_IS_CONS(cdr)) { if (writer->putc(' ', writer->stream) == EOF) return EOF; - tmp++; - } - c += tmp; + + car = any_sexp_car(cdr); + cdr = any_sexp_cdr(cdr); + c++; + } else if (!ANY_SEXP_IS_NIL(cdr)) { + if (any_sexp_writer_puts(writer, " . ") == EOF) + return EOF; + + car = cdr; + cdr = ANY_SEXP_NIL; + c += 3; + } else + break; } if (writer->putc(ANY_SEXP_CHAR_CLOSE, writer->stream) == EOF) @@ -590,12 +600,11 @@ any_sexp_t any_sexp_number(intptr_t value) #ifndef ANY_SEXP_NO_BOXING // Handle the sign bit! - uintptr_t sign_bit = (uintptr_t)1 << (ANY_SEXP_BITS_SHIFT - 1); uintptr_t sexp = *(uintptr_t *)&value; - sexp &= ~(sign_bit | (uintptr_t)0xf << ANY_SEXP_BITS_SHIFT); + sexp &= ~((uintptr_t)0x1f << (ANY_SEXP_BIT_SHIFT - 1)); if (value < 0) - sexp |= sign_bit; + sexp |= ANY_SEXP_BIT_SIGN; return ANY_SEXP_TAG(sexp, ANY_SEXP_TAG_NUMBER); #else @@ -93,7 +93,7 @@ int main() "p:window", NULL, "f:scale", 1.23, "b:hidden", true, - "c:pairs", ANY_LOG_FORMATTER(pairs_format), pairs, + "g:pairs", ANY_LOG_FORMATTER(pairs_format), pairs, "appname", "nice app"); // Test any_log_format diff --git a/test/sexp.c b/test/sexp.c index 8070156..3adf3ab 100644 --- a/test/sexp.c +++ b/test/sexp.c @@ -30,6 +30,10 @@ int main() sexp = any_sexp_read(&reader); } + any_sexp_t pair = any_sexp_cons(any_sexp_number(1), any_sexp_number(2)); + any_sexp_print(pair); + any_sexp_free_list(pair); + //printf("%zu\n", sizeof(any_sexp_t)); return 0; |
