// File: /workspace/github_c_makefile_star2_O1/mati75[P]evilwm/bind.c
// Function: bind_control
void bind_control(const char *ctlname, const char *func) {
	// Parse control string
	char *ctldup = xstrdup(ctlname);
	if (!ctldup)
		return;
	struct bind *newbind = xmalloc(sizeof(*newbind));
	*newbind = (struct bind){0};

	for (char *tmp = strtok(ctldup, ",+"); tmp; tmp = strtok(NULL, ",+")) {
		// is this a modifier?
		struct name_to_modifier *m = modifier_by_name(tmp);
		if (m) {
			newbind->state |= m->value;
			continue;
		}

		// only consider first key or button listed
		if (newbind->type)
			continue;

		// maybe it's a button?
		unsigned b = button_by_name(tmp);
		if (b) {
			newbind->type = ButtonPress;
			newbind->control.button = b;
			continue;
		}

		// ok, see if it's recognised as a key name
		KeySym k = XStringToKeysym(tmp);
		if (k != NoSymbol) {
			newbind->type = KeyPress;
			newbind->control.key = k;
			continue;
		}
	}
	free(ctldup);

	// No known control type?  Abort.
	if (!newbind->type) {
		free(newbind);
		return;
	}

	// always unbind any existing matching control
	for (struct list *l = controls; l; l = l->next) {
		struct bind *b = l->data;
		if (newbind->type == KeyPress && b->state == newbind->state && b->control.key == newbind->control.key) {
			controls = list_delete(controls, b);
			free(b);
			break;
		}
		if (newbind->type == ButtonPress && b->state == newbind->state && b->control.button == newbind->control.button) {
			controls = list_delete(controls, b);
			free(b);
			break;
		}
	}

	// empty function definition implies unbind.  already done, so return.
	if (!func || *func == 0) {
		free(newbind);
		return;
	}

	// parse the second string for function & flags

	char *funcdup = xstrdup(func);
	if (!funcdup)
		return;

	for (char *tmp = strtok(funcdup, ",+"); tmp; tmp = strtok(NULL, ",+")) {
		// function name?
		struct function_def *fn = func_by_name(tmp);
		if (fn) {
			newbind->func = fn->func;
			newbind->flags = fn->flags;
			continue;
		}

		// a simple number?
		if (*tmp >= '0' && *tmp <= '9') {
			newbind->flags &= ~FL_VALUEMASK;
			newbind->flags |= strtol(tmp, NULL, 0) & FL_VALUEMASK;
			continue;
		}

		// treat it as a flag name then
		newbind->flags |= flags_by_name(tmp);
	}

	if (newbind->func) {
		controls = list_prepend(controls, newbind);
	} else {
		free(newbind);
	}

	free(funcdup);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rsi, %rbx
callq 0xa128
testq %rax, %rax
je 0x4d8c
movq %rax, %r14
movq %rbx, 0x8(%rsp)
movl $0x28, %edi
callq 0xa0b0
movq %rax, %rbx
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
movups %xmm0, 0x10(%rax)
movq $0x0, 0x20(%rax)
leaq 0x6559(%rip), %rsi      # 0xb064
movq %r14, 0x10(%rsp)
movq %r14, %rdi
callq 0x4580
testq %rax, %rax
je 0x4bd9
movq %rax, %r13
leaq 0xb8c5(%rip), %rbp      # 0x103f0
leaq 0xb03e(%rip), %r14      # 0xfb70
leaq 0x652b(%rip), %r12      # 0xb064
xorl %r15d, %r15d
movq (%r15,%rbp), %rdi
movq %r13, %rsi
callq 0x4540
testl %eax, %eax
je 0x4b5e
addq $0x10, %r15
cmpq $0xc0, %r15
jne 0x4b3c
xorl %r15d, %r15d
jmp 0x4b61
addq %rbp, %r15
testq %r15, %r15
je 0x4b6f
movl 0x8(%r15), %eax
orl %eax, 0x10(%rbx)
jmp 0x4bc3
cmpl $0x0, (%rbx)
jne 0x4bc3
movl $0x8, %r15d
movq -0x8(%r15,%r14), %rdi
movq %r13, %rsi
callq 0x4540
testl %eax, %eax
je 0x4b99
addq $0x10, %r15
cmpq $0x58, %r15
jne 0x4b7a
xorl %eax, %eax
jmp 0x4b9d
movl (%r15,%r14), %eax
testl %eax, %eax
je 0x4bac
movl $0x4, (%rbx)
movl %eax, 0x8(%rbx)
jmp 0x4bc3
movq %r13, %rdi
callq 0x40c0
testq %rax, %rax
je 0x4bc3
movl $0x2, (%rbx)
movq %rax, 0x8(%rbx)
xorl %edi, %edi
movq %r12, %rsi
callq 0x4580
movq %rax, %r13
testq %rax, %rax
jne 0x4b39
movq 0x10(%rsp), %rdi
callq 0x42d0
movl (%rbx), %eax
testl %eax, %eax
je 0x4d73
movq 0xbb1c(%rip), %rcx      # 0x10710
testq %rcx, %rcx
movq 0x8(%rsp), %r14
je 0x4c5e
movq 0x8(%rcx), %r15
cmpl $0x4, %eax
je 0x4c24
cmpl $0x2, %eax
jne 0x4c36
movl 0x10(%r15), %edx
cmpl 0x10(%rbx), %edx
jne 0x4c1f
movq 0x8(%r15), %rdx
cmpq 0x8(%rbx), %rdx
je 0x4c40
cmpl $0x4, %eax
jne 0x4c36
movl 0x10(%r15), %edx
cmpl 0x10(%rbx), %edx
jne 0x4c36
movl 0x8(%r15), %edx
cmpl 0x8(%rbx), %edx
je 0x4c40
movq (%rcx), %rcx
testq %rcx, %rcx
jne 0x4bfe
jmp 0x4c5e
movq 0xbac9(%rip), %rdi      # 0x10710
movq %r15, %rsi
callq 0x87d5
movq %rax, 0xbaba(%rip)      # 0x10710
movq %r15, %rdi
callq 0x42d0
testq %r14, %r14
je 0x4d73
cmpb $0x0, (%r14)
je 0x4d73
movq %r14, %rdi
callq 0xa128
testq %rax, %rax
je 0x4d8c
movq %rax, %r14
leaq 0x63d8(%rip), %rsi      # 0xb064
movq %rax, %rdi
callq 0x4580
testq %rax, %rax
je 0x4d54
movq %rax, %r12
leaq 0xaf19(%rip), %r13      # 0xfbc0
leaq 0xb032(%rip), %rbp      # 0xfce0
xorl %r15d, %r15d
movq (%r15,%r13), %rdi
movq %r12, %rsi
callq 0x4540
testl %eax, %eax
je 0x4cd3
addq $0x18, %r15
cmpq $0x120, %r15            # imm = 0x120
jne 0x4cb1
xorl %r15d, %r15d
jmp 0x4cd6
addq %r13, %r15
testq %r15, %r15
je 0x4cec
movq 0x8(%r15), %rax
movq %rax, 0x18(%rbx)
movl 0x10(%r15), %eax
movl %eax, 0x20(%rbx)
jmp 0x4d3a
movb (%r12), %al
addb $-0x30, %al
cmpb $0xa, %al
jae 0x4d0b
movb $0x0, 0x20(%rbx)
movq %r12, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x4420
movzbl %al, %eax
jmp 0x4d37
movl $0x8, %r15d
movq -0x8(%r15,%rbp), %rdi
movq %r12, %rsi
callq 0x4540
testl %eax, %eax
je 0x4d33
addq $0x10, %r15
cmpq $0xd8, %r15
jne 0x4d11
xorl %eax, %eax
jmp 0x4d37
movl (%r15,%rbp), %eax
orl %eax, 0x20(%rbx)
xorl %edi, %edi
leaq 0x6321(%rip), %rsi      # 0xb064
callq 0x4580
movq %rax, %r12
testq %rax, %rax
jne 0x4cae
cmpq $0x0, 0x18(%rbx)
je 0x4d9b
movq 0xb9ae(%rip), %rdi      # 0x10710
movq %rbx, %rsi
callq 0x8789
movq %rax, 0xb99f(%rip)      # 0x10710
jmp 0x4d76
movq %rbx, %r14
movq %r14, %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x42d0
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rbx, %rdi
callq 0x42d0
jmp 0x4d76