// File: attractivechaos[P]udb2/stb/./stb.h
// Function: stb_free
void stb_free(void *p)
{
   if (p == NULL) return;

   // count frees so that unit tests can see what's happening
   ++stb_alloc_count_free;

   switch(stb__identify(p)) {
      case STB__chunked:
         // freeing a chunked-block with children does nothing;
         // they only get freed when the parent does
         // surely this is wrong, and it should free them immediately?
         // otherwise how are they getting put on the right chain?
         return;
      case STB__nochildren: {
         stb__nochildren *s = (stb__nochildren *) p - 1;
         // unlink from sibling chain
         *(s->prevn) = s->next;
         if (s->next)
            *stb__prevn(s->next) = s->prevn;
         free(s);
         return;
      }
      case STB__alloc: {
         stb__alloc *s = (stb__alloc *) p - 1;
         stb__chunk *c, *n;
         void *q;

         // unlink from sibling chain, if any
         *(s->prevn) = s->next;
         if (s->next)
            *stb__prevn(s->next) = s->prevn;

         // first free chunks
         c = (stb__chunk *) stb__chunks(s);
         while (c != NULL) {
            n = c->next;
            stb_alloc_count_free += c->alloc;
            free(c);
            c = n;
         }

         // validating
         stb__setchunks(s,NULL);
         s->prevn = NULL;
         s->next = NULL;

         // now free children
         while ((q = s->child) != NULL) {
            stb_free(q);
         }

         // now free self
         free(s);
         return;
      }
      default:
         assert(0); /* NOTREACHED */
   }
}

// Assembly:
subq $0x48, %rsp
movq %rdi, 0x40(%rsp)
cmpq $0x0, 0x40(%rsp)
jne 0x6e76
jmp 0x7028
movl 0x23204(%rip), %eax     # 0x2a080
incl %eax
movl %eax, 0x231fc(%rip)     # 0x2a080
movq 0x40(%rsp), %rdi
callq 0x7030
movl %eax, %ecx
movl %ecx, 0x14(%rsp)
testl %eax, %eax
je 0x6eb8
jmp 0x6e9a
movl 0x14(%rsp), %eax
subl $0x1, %eax
je 0x6eb3
jmp 0x6ea5
movl 0x14(%rsp), %eax
subl $0x2, %eax
je 0x6f17
jmp 0x7009
jmp 0x7028
movq 0x40(%rsp), %rax
addq $-0x10, %rax
movq %rax, 0x38(%rsp)
movq 0x38(%rsp), %rax
movq (%rax), %rcx
movq 0x38(%rsp), %rax
movq 0x8(%rax), %rax
movq %rcx, (%rax)
movq 0x38(%rsp), %rax
cmpq $0x0, (%rax)
je 0x6f08
movq 0x38(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x8(%rsp)
movq 0x38(%rsp), %rax
movq (%rax), %rdi
callq 0x7050
movq 0x8(%rsp), %rcx
movq %rcx, (%rax)
movq 0x38(%rsp), %rdi
callq 0x23c0
jmp 0x7028
movq 0x40(%rsp), %rax
addq $-0x20, %rax
movq %rax, 0x30(%rsp)
movq 0x30(%rsp), %rax
movq 0x10(%rax), %rcx
movq 0x30(%rsp), %rax
movq (%rax), %rax
movq %rcx, (%rax)
movq 0x30(%rsp), %rax
cmpq $0x0, 0x10(%rax)
je 0x6f66
movq 0x30(%rsp), %rax
movq (%rax), %rax
movq %rax, (%rsp)
movq 0x30(%rsp), %rax
movq 0x10(%rax), %rdi
callq 0x7050
movq (%rsp), %rcx
movq %rcx, (%rax)
movq 0x30(%rsp), %rax
movq 0x18(%rax), %rax
addq $-0x2, %rax
movq %rax, 0x28(%rsp)
cmpq $0x0, 0x28(%rsp)
je 0x6fb7
movq 0x28(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x20(%rsp)
movq 0x28(%rsp), %rax
movl 0xc(%rax), %eax
addl 0x230e5(%rip), %eax     # 0x2a080
movl %eax, 0x230df(%rip)     # 0x2a080
movq 0x28(%rsp), %rdi
callq 0x23c0
movq 0x20(%rsp), %rax
movq %rax, 0x28(%rsp)
jmp 0x6f78
movq 0x30(%rsp), %rax
movq $0x2, 0x18(%rax)
movq 0x30(%rsp), %rax
movq $0x0, (%rax)
movq 0x30(%rsp), %rax
movq $0x0, 0x10(%rax)
movq 0x30(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x18(%rsp)
cmpq $0x0, %rax
je 0x6ffd
movq 0x18(%rsp), %rdi
callq 0x6e60
jmp 0x6fdd
movq 0x30(%rsp), %rdi
callq 0x23c0
jmp 0x7028
leaq 0x1869e(%rip), %rdi     # 0x1f6ae
leaq 0x18372(%rip), %rsi     # 0x1f389
movl $0xa27, %edx            # imm = 0xA27
leaq 0x184cb(%rip), %rcx     # 0x1f4ee
callq 0x2140
addq $0x48, %rsp
retq
nopl (%rax)