+/* The following macros are for traversing lisp lists.
+ Signal an error if LIST is not properly acyclic and nil-terminated.
+
+ Use tortoise/hare algorithm to check for cycles, but only if it
+ looks like the list is getting too long. Not only is the hare
+ faster than the tortoise; it even gets a head start! */
+
+/* Optimized and safe macros for looping over external lists. */
+#define CIRCULAR_LIST_SUSPICION_LENGTH 1024
+
+#define EXTERNAL_LIST_LOOP_1(list) \
+Lisp_Object ELL1_elt, ELL1_hare, ELL1_tortoise; \
+EMACS_INT ELL1_len; \
+PRIVATE_EXTERNAL_LIST_LOOP_6 (ELL1_elt, list, ELL1_len, ELL1_hare, \
+ ELL1_tortoise, CIRCULAR_LIST_SUSPICION_LENGTH)
+
+#define EXTERNAL_LIST_LOOP_2(elt, list) \
+Lisp_Object elt, hare_##elt, tortoise_##elt; \
+EMACS_INT len_##elt; \
+PRIVATE_EXTERNAL_LIST_LOOP_6 (elt, list, len_##elt, hare_##elt, \
+ tortoise_##elt, CIRCULAR_LIST_SUSPICION_LENGTH)
+
+#define EXTERNAL_LIST_LOOP_3(elt, list, tail) \
+Lisp_Object elt, tail, tortoise_##elt; \
+EMACS_INT len_##elt; \
+PRIVATE_EXTERNAL_LIST_LOOP_6 (elt, list, len_##elt, tail, \
+ tortoise_##elt, CIRCULAR_LIST_SUSPICION_LENGTH)
+
+#define EXTERNAL_LIST_LOOP_4_NO_DECLARE(elt, list, tail, len) \
+Lisp_Object tortoise_##elt; \
+PRIVATE_EXTERNAL_LIST_LOOP_6 (elt, list, len, tail, \
+ tortoise_##elt, CIRCULAR_LIST_SUSPICION_LENGTH)
+
+#define EXTERNAL_LIST_LOOP_4(elt, list, tail, len) \
+Lisp_Object elt, tail, tortoise_##elt; \
+EMACS_INT len; \
+PRIVATE_EXTERNAL_LIST_LOOP_6 (elt, list, len, tail, \
+ tortoise_##elt, CIRCULAR_LIST_SUSPICION_LENGTH)
+
+
+#define PRIVATE_EXTERNAL_LIST_LOOP_6(elt, list, len, hare, \
+ tortoise, suspicion_length) \
+ for (tortoise = hare = list, len = 0; \
+ \
+ (CONSP (hare) ? ((elt = XCAR (hare)), 1) : \
+ (NILP (hare) ? 0 : \
+ (signal_malformed_list_error (list), 0))); \
+ \
+ hare = XCDR (hare), \
+ (void) \
+ ((++len > suspicion_length) \
+ && \
+ ((((len & 1) != 0) && (tortoise = XCDR (tortoise), 0)), \
+ (EQ (hare, tortoise) && (signal_circular_list_error (list), 0)))))
+
+/* GET_LIST_LENGTH and GET_EXTERNAL_LIST_LENGTH:
+
+ These two macros return the length of LIST (either an internal or external
+ list, according to which macro is used), stored into LEN (which must
+ be declared by the caller). Circularities are trapped in external lists
+ (and cause errors). Neither macro need be declared inside brackets. */
+