// File: /workspace/github_c_makefile_star2_O2/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
pushq %rax
movq %rsi, %rbx
callq 0x9a48
testq %rax, %rax
je 0x4b3f
movq %rax, %r15
movq %rbx, (%rsp)
pushq $0x28
popq %rdi
callq 0x99bc
movq %rax, %rbx
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
movups %xmm0, 0x10(%rax)
andq $0x0, 0x20(%rax)
leaq 0x5728(%rip), %r12      # 0xa064
movq %r15, %rdi
movq %r12, %rsi
callq 0x4580
movq %rax, %r13
leaq 0xa21f(%rip), %rbp      # 0xeb70
testq %r13, %r13
je 0x49c9
movq %r13, %rdi
callq 0x4c11
testq %rax, %rax
je 0x496b
movl 0x8(%rax), %eax
orl %eax, 0x10(%rbx)
jmp 0x49ba
cmpl $0x0, (%rbx)
jne 0x49ba
xorl %ecx, %ecx
leaq 0x10(%rcx), %r14
cmpq $0x60, %r14
je 0x49a3
movq (%rcx,%rbp), %rdi
movq %r13, %rsi
callq 0x4540
movq %r14, %rcx
testl %eax, %eax
jne 0x4972
movl -0x8(%r14,%rbp), %eax
testl %eax, %eax
je 0x49a3
movl $0x4, (%rbx)
movl %eax, 0x8(%rbx)
jmp 0x49ba
movq %r13, %rdi
callq 0x40c0
testq %rax, %rax
je 0x49ba
movl $0x2, (%rbx)
movq %rax, 0x8(%rbx)
xorl %edi, %edi
movq %r12, %rsi
callq 0x4580
movq %rax, %r13
jmp 0x4951
movq %r15, %rdi
callq 0x42d0
movl (%rbx), %eax
testl %eax, %eax
je 0x4b29
leaq 0xad1e(%rip), %rcx      # 0xf700
movq (%rsp), %r14
movq (%rcx), %rcx
testq %rcx, %rcx
je 0x4a41
movq 0x8(%rcx), %r15
cmpl $0x4, %eax
je 0x4a11
cmpl $0x2, %eax
jne 0x49e6
movl 0x10(%r15), %edx
cmpl 0x10(%rbx), %edx
jne 0x49e6
movq 0x8(%r15), %rdx
cmpq 0x8(%rbx), %rdx
jne 0x49e6
jmp 0x4a23
movl 0x10(%r15), %edx
cmpl 0x10(%rbx), %edx
jne 0x49e6
movl 0x8(%r15), %edx
cmpl 0x8(%rbx), %edx
jne 0x49e6
movq 0xacd6(%rip), %rdi      # 0xf700
movq %r15, %rsi
callq 0x824d
movq %rax, 0xacc7(%rip)      # 0xf700
movq %r15, %rdi
callq 0x42d0
testq %r14, %r14
je 0x4b29
cmpb $0x0, (%r14)
je 0x4b29
movq %r14, %rdi
callq 0x9a48
testq %rax, %rax
je 0x4b3f
leaq 0x55f8(%rip), %r15      # 0xa064
movq %rax, (%rsp)
movq %rax, %rdi
movq %r15, %rsi
callq 0x4580
movq %rax, %r12
leaq 0xa25b(%rip), %r13      # 0xece0
leaq 0xa134(%rip), %rbp      # 0xebc0
testq %r12, %r12
je 0x4b4e
xorl %ecx, %ecx
leaq 0x18(%rcx), %r14
cmpq $0x138, %r14            # imm = 0x138
je 0x4ac7
movq (%rcx,%rbp), %rdi
movq %r12, %rsi
callq 0x4540
movq %r14, %rcx
testl %eax, %eax
jne 0x4a97
movq -0x10(%r14,%rbp), %rax
movq %rax, 0x18(%rbx)
movl -0x8(%r14,%rbp), %eax
jmp 0x4b14
movb (%r12), %al
addb $-0x30, %al
cmpb $0xa, %al
jae 0x4ae6
movb $0x0, 0x20(%rbx)
movq %r12, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x4420
movzbl %al, %eax
jmp 0x4b11
xorl %ecx, %ecx
leaq 0x10(%rcx), %r14
cmpq $0xe0, %r14
je 0x4b0f
movq (%rcx,%r13), %rdi
movq %r12, %rsi
callq 0x4540
movq %r14, %rcx
testl %eax, %eax
jne 0x4ae8
movl -0x8(%r14,%r13), %eax
jmp 0x4b11
xorl %eax, %eax
orl 0x20(%rbx), %eax
movl %eax, 0x20(%rbx)
xorl %edi, %edi
movq %r15, %rsi
callq 0x4580
movq %rax, %r12
jmp 0x4a8c
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x42d0
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
cmpq $0x0, 0x18(%rbx)
je 0x4b6d
movq 0xaba4(%rip), %rdi      # 0xf700
movq %rbx, %rsi
callq 0x8238
movq %rax, 0xab95(%rip)      # 0xf700
jmp 0x4b75
movq %rbx, %rdi
callq 0x42d0
movq (%rsp), %rdi
jmp 0x4b2c