#define push_to_sll(lhead, ltail, new) \
  if ((ltail)) { \
    assert((lhead)); \
    (ltail)->next = (new); \
  } else { \
    assert(!(ltail)); \
    (lhead) = (new); \
  } \
  (ltail) = (new)

#define push_to_dll(lhead, ltail, new) \
  if ((ltail)) { \
    assert((lhead)); \
    (ltail)->next = (new); \
    (new)->prev = (ltail); \
  } else { \
    assert(!(ltail)); \
    (lhead) = (new); \
  } \
  (ltail) = (new)

#define pop_from_dll(lhead, ltail, popped) do { \
  if ((popped)->prev) { \
    (popped)->prev->next = (popped)->next; \
  } else { \
    (lhead) = (popped)->next; \
  } \
  if ((popped)->next) { \
    (popped)->next->prev = (popped)->prev; \
  } else { \
    (ltail) = (popped)->prev; \
  } \
} while (0)