#ifndef cmsg_sexp_h #define cmsg_sexp_h typedef struct sexp_data_t_ { refcount_t refcount; cmsg_bytes_t data; } sexp_data_t; typedef enum sexp_type_t_ { SEXP_BYTES, SEXP_SLICE, SEXP_DISPLAY_HINT, SEXP_PAIR } sexp_type_t; typedef struct sexp_t_ { refcount_t refcount; sexp_type_t kind; union { cmsg_bytes_t bytes; struct { sexp_data_t *data; size_t offset; size_t length; } slice; struct { struct sexp_t_ *head; struct sexp_t_ *tail; } pair; /* and display-hint */ } data; } sexp_t; extern void release_sexp_cache(void); extern void sexp_data_destructor(sexp_data_t *data); extern void sexp_destructor(sexp_t *x); extern sexp_data_t *sexp_data_copy(cmsg_bytes_t body, size_t offset, size_t length); extern sexp_data_t *sexp_data_alias(cmsg_bytes_t body); extern sexp_t *sexp_bytes(cmsg_bytes_t bytes); extern sexp_t *sexp_slice(sexp_data_t *data, size_t offset, size_t length); extern sexp_t *sexp_display_hint(sexp_t *hint, sexp_t *body); extern sexp_t *sexp_cons(sexp_t *head, sexp_t *tail); #define sexp_simple_stringp(x) ({ \ sexp_t *__x = (x); \ (__x != NULL) && ((__x->kind == SEXP_BYTES) || (__x->kind == SEXP_SLICE)); \ }) #define sexp_stringp(x) ({ \ sexp_t *__x = (x); \ sexp_simple_stringp(__x) || ((__x != NULL) && (__x->kind == SEXP_DISPLAY_HINT)); \ }) #define sexp_pairp(x) ({ \ sexp_t *__x = (x); \ (__x != NULL) && (__x->kind == SEXP_PAIR); \ }) extern cmsg_bytes_t sexp_data(sexp_t *x); #define sexp_head(x) ({sexp_t *__x = (x); assert(__x->kind == SEXP_PAIR); __x->data.pair.head;}) #define sexp_tail(x) ({sexp_t *__x = (x); assert(__x->kind == SEXP_PAIR); __x->data.pair.tail;}) #define sexp_hint(x) ({sexp_t *__x = (x); assert(__x->kind == SEXP_DISPLAY_HINT); __x->data.pair.head;}) #define sexp_body(x) ({sexp_t *__x = (x); assert(__x->kind == SEXP_DISPLAY_HINT); __x->data.pair.tail;}) #define sexp_setter_(x,y,fieldname) \ ({ \ sexp_t *__x = (x); \ sexp_t *__y = (y); \ sexp_t *__old; \ assert(__x->kind == SEXP_PAIR); \ INCREF(__y); \ __old = __x->data.pair.fieldname; \ __x->data.pair.fieldname = __y; \ DECREF(__old, sexp_destructor); \ __x; \ }) #define sexp_sethead(x,y) sexp_setter_(x,y,head) #define sexp_settail(x,y) sexp_setter_(x,y,tail) #define sexp_push(stackvar,val) \ ({ \ sexp_t *__oldstack = stackvar; \ stackvar = INCREF(sexp_cons((val), stackvar)); \ DECREF(__oldstack, sexp_destructor); \ stackvar; \ }) #define sexp_pop(stackvar) \ ({ \ sexp_t *__nextstack = INCREF(sexp_tail(stackvar)); \ sexp_t *__val = INCREF(sexp_head(stackvar)); \ DECREF(stackvar, sexp_destructor); \ stackvar = __nextstack; \ UNGRAB(__val); \ __val; \ }) extern sexp_t *sexp_assoc(sexp_t *list, cmsg_bytes_t key); #endif