~ chicken-core (chicken-5) dcb09a2b47ecf7c678199c2e9e36d87e4c234ef8


commit dcb09a2b47ecf7c678199c2e9e36d87e4c234ef8
Author:     Peter Bex <peter.bex@xs4all.nl>
AuthorDate: Sat Oct 5 09:59:22 2013 +0200
Commit:     Peter Bex <peter.bex@xs4all.nl>
CommitDate: Sat Oct 5 10:30:34 2013 +0200

    Simplify evil C macroloy & remove misleading comment about how I *thought* it worked :)

diff --git a/chicken.h b/chicken.h
index dc0af17c..07e4fe8c 100644
--- a/chicken.h
+++ b/chicken.h
@@ -868,52 +868,47 @@ DECL_C_PROC_p0 (128,  1,0,0,0,0,0,0,0)
  *    do_something_with(obj);
  * This works around the fact obj may be an expression with side-effects.
  *
- * We'd like semantics like (let ((x 1)) (let ((x x)) x)) => 1, but in C
- * int x = x; results in undefined behaviour because x refers to itself, so
- * we need to keep around a reference to the previous level (one scope up).
- * After initialisers are run, "previous" is redefined to mean "current".
- * Multiple ACCESS calls yield successively larger chains of "prev" access.
+ * To make this work with nested expansions, we need semantics like
+ * (let ((x 1)) (let ((x x)) x)) => 1, but in C, int x = x; results in
+ * undefined behaviour because x refers to itself.  As a workaround,
+ * we keep around a reference to the previous level (one scope up).
+ * After initialisation, "previous" is redefined to mean "current".
  */
-# define C_VAL(x,y) C__PREV_TMPST.x
-static const int C__TMPST = 0;
-static const int C__PREV_TMPST = 0;
-# define C__STR(x)   #x
+# define C_VAL1(x)                 C__PREV_TMPST.n1
+# define C_VAL2(x)                 C__PREV_TMPST.n2
+# define C__STR(x)                 #x
 # define C__CHECK_panic(a,s,f,l)                                       \
   ((a) ? (void)0 :                                                     \
    C_panic_hook("Low-level type assertion " s " failed at " f ":" C__STR(l)))
-# define C__CHECK_core(n,v,a,s,x)                                       \
+# define C__CHECK_core(v,a,s,x)                                         \
   ({ struct {                                                           \
-      typeof(v) n;                                                      \
-      typeof(C__PREV_TMPST) C__TMPST;                                   \
-  } C__TMPST = { .C__TMPST = C__PREV_TMPST};                            \
-    C__TMPST.n = (v);                                                   \
+      typeof(v) n1;                                                     \
+  } C__TMPST = { .n1 = (v) };                                           \
     typeof(C__TMPST) C__PREV_TMPST=C__TMPST;                            \
     C__CHECK_panic(a,s,__FILE__,__LINE__);                              \
     x; })
-# define C__CHECK2_core(n1,v1,n2,v2,a,s,x)                              \
+# define C__CHECK2_core(v1,v2,a,s,x)                                    \
   ({ struct {                                                           \
       typeof(v1) n1;                                                    \
       typeof(v2) n2;                                                    \
-      typeof(C__PREV_TMPST) C__TMPST;                                   \
-  } C__TMPST = { .C__TMPST = C__PREV_TMPST};                            \
-    C__TMPST.n1 = (v1);                                                 \
-    C__TMPST.n2 = (v2);                                                 \
+  } C__TMPST = { .n1 = (v1), .n2 = (v2) };                              \
     typeof(C__TMPST) C__PREV_TMPST=C__TMPST;                            \
     C__CHECK_panic(a,s,__FILE__,__LINE__);                              \
     x; })
-# define C_CHECK(n,v,a,x)             C__CHECK_core(n,v,a,#a,x)
-# define C_CHECK2(n1,v1,n2,v2,a,x)    C__CHECK2_core(n1,v1,n2,v2,a,#a,x)
+# define C_CHECK(v,a,x)            C__CHECK_core(v,a,#a,x)
+# define C_CHECK2(v1,v2,a,x)       C__CHECK2_core(v1,v2,a,#a,x)
 /*
  * Convenience for using Scheme-predicates.
  */
-# define C_CHECKp(n,v,a,x)            C__CHECK_core(n,v,C_truep(a),#a"=#t",x)
-# define C_CHECK2p(n1,v1,n2,v2,a,x)   C__CHECK2_core(n1,v1,n2,v2,C_truep(a),#a"=#t",x)
+# define C_CHECKp(v,a,x)           C__CHECK_core(v,C_truep(a),#a"=#t",x)
+# define C_CHECK2p(v1,v2,a,x)      C__CHECK2_core(v1,v2,C_truep(a),#a"=#t",x)
 #else
-# define C_VAL(x,y)                   (y)
-# define C_CHECK(n,v,a,x)             (x)
-# define C_CHECK2(n1,v1,n2,v2,a,x)    (x)
-# define C_CHECKp(n,v,a,x)            (x)
-# define C_CHECK2p(n1,v1,n2,v2,a,x)   (x)
+# define C_VAL1(x)                 (x)
+# define C_VAL2(x)                 (x)
+# define C_CHECK(v,a,x)            (x)
+# define C_CHECK2(v1,v2,a,x)       (x)
+# define C_CHECKp(v,a,x)           (x)
+# define C_CHECK2p(v1,v2,a,x)      (x)
 #endif
 
 #ifndef C_PROVIDE_LIBC_STUBS
@@ -1050,8 +1045,8 @@ extern double trunc(double);
 /* Without check: initialisation of a newly allocated header */
 #define C_block_header_init(x,h)   (((C_SCHEME_BLOCK *)(x))->header = (h))
 /* These two must result in an lvalue, hence the (*foo(&bar)) faffery */
-#define C_block_header(x)          (*C_CHECKp(__x,x,C_blockp((C_word)C_VAL(__x,x)),&(((C_SCHEME_BLOCK *)(C_VAL(__x,x)))->header)))
-#define C_block_item(x,i)          (*C_CHECK2(__x,x,__i,i,(C_header_size(C_VAL(__x,x))>(C_VAL(__i,i))),&(((C_SCHEME_BLOCK *)(C_VAL(__x,x)))->data [ C_VAL(__i,i) ])))
+#define C_block_header(x)          (*C_CHECKp(x,C_blockp((C_word)C_VAL1(x)),&(((C_SCHEME_BLOCK *)(C_VAL1(x)))->header)))
+#define C_block_item(x,i)          (*C_CHECK2(x,i,(C_header_size(C_VAL1(x))>(C_VAL2(i))),&(((C_SCHEME_BLOCK *)(C_VAL1(x)))->data [ C_VAL2(i) ])))
 #define C_set_block_item(x,i,y)    (C_block_item(x, i) = (y))
 #define C_header_bits(bh)          (C_block_header(bh) & C_HEADER_BITS_MASK)
 #define C_header_size(bh)          (C_block_header(bh) & C_HEADER_SIZE_MASK)
@@ -1081,12 +1076,12 @@ extern double trunc(double);
 #define C_stack_pointer_test       ((C_word *)C_alloca(1))
 #define C_demand_2(n)              (((C_word *)C_fromspace_top + (n)) < (C_word *)C_fromspace_limit)
 #define C_fix(n)                   (((C_word)(n) << C_FIXNUM_SHIFT) | C_FIXNUM_BIT)
-#define C_unfix(x)                 C_CHECKp(__x,x,C_fixnump(C_VAL(__x,x)),((C_VAL(__x,x)) >> C_FIXNUM_SHIFT))
+#define C_unfix(x)                 C_CHECKp(x,C_fixnump(C_VAL1(x)),((C_VAL1(x)) >> C_FIXNUM_SHIFT))
 #define C_make_character(c)        (((((C_uword)(c)) & C_CHAR_BIT_MASK) << C_CHAR_SHIFT) | C_CHARACTER_BITS)
-#define C_character_code(x)        C_CHECKp(__x,x,C_charp(C_VAL(__x,x)),((C_word)(C_VAL(__x,x)) >> C_CHAR_SHIFT) & C_CHAR_BIT_MASK)
-#define C_flonum_magnitude(x)      (*C_CHECKp(__x,x,C_flonump(C_VAL(__x,x)),(double *)C_data_pointer(C_VAL(__x,x))))
+#define C_character_code(x)        C_CHECKp(x,C_charp(C_VAL1(x)),((C_word)(C_VAL1(x)) >> C_CHAR_SHIFT) & C_CHAR_BIT_MASK)
+#define C_flonum_magnitude(x)      (*C_CHECKp(x,C_flonump(C_VAL1(x)),(double *)C_data_pointer(C_VAL1(x))))
 /* XXX Sometimes this is (ab)used on bytevectors (ie, blob=? uses string_compare) */
-#define C_c_string(x)              C_CHECK(__x,x,(C_truep(C_stringp(C_VAL(__x,x))) || C_truep(C_bytevectorp(C_VAL(__x,x)))),(C_char *)C_data_pointer(C_VAL(__x,x)))
+#define C_c_string(x)              C_CHECK(x,(C_truep(C_stringp(C_VAL1(x))) || C_truep(C_bytevectorp(C_VAL1(x)))),(C_char *)C_data_pointer(C_VAL1(x)))
 
 #define C_c_pointer(x)             ((void *)(x))
 #define C_c_pointer_nn(x)          ((void *)C_block_item(x, 0))
@@ -1094,8 +1089,8 @@ extern double trunc(double);
 #define C_immediatep(x)            ((x) & C_IMMEDIATE_MARK_BITS)
 #define C_mk_bool(x)               ((x) ? C_SCHEME_TRUE : C_SCHEME_FALSE)
 #define C_mk_nbool(x)              ((x) ? C_SCHEME_FALSE : C_SCHEME_TRUE)
-#define C_port_file(p)             C_CHECKp(__p,p,C_portp(C_VAL(__p,p)),(C_FILEPTR)C_block_item(C_VAL(__p,p), 0))
-#define C_data_pointer(b)          C_CHECKp(__b,b,C_blockp((C_word)C_VAL(__b,b)),(void *)(((C_SCHEME_BLOCK *)(C_VAL(__b,b)))->data))
+#define C_port_file(p)             C_CHECKp(p,C_portp(C_VAL1(p)),(C_FILEPTR)C_block_item(C_VAL1(p), 0))
+#define C_data_pointer(b)          C_CHECKp(b,C_blockp((C_word)C_VAL1(b)),(void *)(((C_SCHEME_BLOCK *)(C_VAL1(b)))->data))
 #define C_invert_flag(f)           (!(f))
 #define C_fitsinfixnump(n)         (((n) & C_INT_SIGN_BIT) == (((n) & C_INT_TOP_BIT) << 1))
 #define C_ufitsinfixnump(n)        (((n) & (C_INT_SIGN_BIT | (C_INT_SIGN_BIT >> 1))) == 0)
Trap