+/* 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. */
+
+#define GET_LIST_LENGTH(list, len) do { \
+ Lisp_Object GLL_tail; \
+ for (GLL_tail = list, len = 0; \
+ !NILP (GLL_tail); \
+ GLL_tail = XCDR (GLL_tail), ++len) \
+ DO_NOTHING; \
+} while (0)
+
+#define GET_EXTERNAL_LIST_LENGTH(list, len) \
+do { \
+ Lisp_Object GELL_elt, GELL_tail; \
+ EXTERNAL_LIST_LOOP_4_NO_DECLARE (GELL_elt, list, GELL_tail, len) \
+ ; \
+} while (0)
+
+/* For a list that's known to be in valid list format, where we may
+ be deleting the current element out of the list --
+ will abort() if the list is not in valid format */
+#define LIST_LOOP_DELETING(consvar, nextconsvar, list) \
+ for (consvar = list; \
+ !NILP (consvar) ? (nextconsvar = XCDR (consvar), 1) :0; \
+ consvar = nextconsvar)
+
+/* LIST_LOOP_DELETE_IF and EXTERNAL_LIST_LOOP_DELETE_IF:
+
+ These two macros delete all elements of LIST (either an internal or
+ external list, according to which macro is used) satisfying
+ CONDITION, a C expression referring to variable ELT. ELT is
+ automatically declared. Circularities are trapped in external
+ lists (and cause errors). Neither macro need be declared inside
+ brackets. */
+
+#define LIST_LOOP_DELETE_IF(elt, list, condition) do { \
+ /* Do not use ##list when creating new variables because \
+ that may not be just a variable name. */ \
+ Lisp_Object prev_tail_##elt = Qnil; \
+ LIST_LOOP_3 (elt, list, tail_##elt) \
+ { \
+ if (condition) \
+ { \
+ if (NILP (prev_tail_##elt)) \
+ list = XCDR (tail_##elt); \
+ else \
+ XCDR (prev_tail_##elt) = XCDR (tail_##elt); \
+ } \
+ else \
+ prev_tail_##elt = tail_##elt; \
+ } \
+} while (0)
+
+#define EXTERNAL_LIST_LOOP_DELETE_IF(elt, list, condition) do { \
+ Lisp_Object prev_tail_##elt = Qnil; \
+ EXTERNAL_LIST_LOOP_4 (elt, list, tail_##elt, len_##elt) \
+ { \
+ if (condition) \
+ { \
+ if (NILP (prev_tail_##elt)) \
+ list = XCDR (tail_##elt); \
+ else \
+ XCDR (prev_tail_##elt) = XCDR (tail_##elt); \
+ /* Keep tortoise from ever passing hare. */ \
+ len_##elt = 0; \
+ } \
+ else \
+ prev_tail_##elt = tail_##elt; \
+ } \
+} while (0)
+
+
+/* Macros for looping over external alists.
+
+ *** ALL OF THESE MACROS MUST BE DECLARED INSIDE BRACES -- SEE ABOVE. ***
+
+ EXTERNAL_ALIST_LOOP_4 is similar to EXTERNAL_LIST_LOOP_2, but it
+ assumes the elements are aconses (the elements in an alist) and
+ sets two additional argument variables ELT_CAR and ELT_CDR to the
+ car and cdr of the acons. All of the variables ELT, ELT_CAR and
+ ELT_CDR are automatically declared.