// File: /workspace/github_c_makefile_star2_O3/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 0x9f30
testq %rax, %rax
je 0x4d62
movq %rax, %r14
movq %rbx, 0x10(%rsp)
movl $0x28, %edi
callq 0x9eb8
movq %rax, %rbx
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
movups %xmm0, 0x10(%rax)
movq $0x0, 0x20(%rax)
leaq 0x5569(%rip), %rsi      # 0xa064
movq %r14, 0x8(%rsp)
movq %r14, %rdi
callq 0x4580
testq %rax, %rax
je 0x4bbc
movq %rax, %r13
leaq 0xa8c5(%rip), %rbp      # 0xf3e0
leaq 0x5542(%rip), %r12      # 0xa064
leaq 0xa047(%rip), %r14      # 0xeb70
movl $0x8, %r15d
movq -0x8(%r15,%rbp), %rdi
movq %r13, %rsi
callq 0x4540
testl %eax, %eax
je 0x4b75
addq $0x10, %r15
cmpq $0xc8, %r15
jne 0x4b2f
cmpl $0x0, (%rbx)
jne 0x4b7c
movl $0x8, %r15d
movq -0x8(%r15,%r14), %rdi
movq %r13, %rsi
callq 0x4540
testl %eax, %eax
je 0x4b90
addq $0x10, %r15
cmpq $0x58, %r15
jne 0x4b58
jmp 0x4ba3
movl (%r15,%rbp), %eax
orl %eax, 0x10(%rbx)
xorl %edi, %edi
movq %r12, %rsi
callq 0x4580
movq %rax, %r13
testq %rax, %rax
jne 0x4b29
jmp 0x4bbc
movl (%r15,%r14), %eax
testl %eax, %eax
je 0x4ba3
movl $0x4, (%rbx)
movl %eax, 0x8(%rbx)
jmp 0x4b7c
movq %r13, %rdi
callq 0x40c0
testq %rax, %rax
je 0x4b7c
movl $0x2, (%rbx)
movq %rax, 0x8(%rbx)
jmp 0x4b7c
movq 0x8(%rsp), %rdi
callq 0x42d0
movl (%rbx), %eax
testl %eax, %eax
je 0x4d4c
movq 0xab29(%rip), %rdi      # 0xf700
testq %rdi, %rdi
movq 0x10(%rsp), %r14
je 0x4c3a
movq %rdi, %rcx
movq 0x8(%rcx), %r15
cmpl $0x4, %eax
je 0x4c07
cmpl $0x2, %eax
jne 0x4c19
movl 0x10(%r15), %edx
cmpl 0x10(%rbx), %edx
jne 0x4c19
movq 0x8(%r15), %rdx
cmpq 0x8(%rbx), %rdx
jne 0x4c19
jmp 0x4c23
movl 0x10(%r15), %edx
cmpl 0x10(%rbx), %edx
jne 0x4c19
movl 0x8(%r15), %edx
cmpl 0x8(%rbx), %edx
je 0x4c23
movq (%rcx), %rcx
testq %rcx, %rcx
jne 0x4be4
jmp 0x4c3a
movq %r15, %rsi
callq 0x867f
movq %rax, 0xaace(%rip)      # 0xf700
movq %r15, %rdi
callq 0x42d0
testq %r14, %r14
je 0x4d4c
cmpb $0x0, (%r14)
je 0x4d4c
movq %r14, %rdi
callq 0x9f30
testq %rax, %rax
je 0x4d62
leaq 0x53ff(%rip), %rsi      # 0xa064
movq %rax, 0x8(%rsp)
movq %rax, %rdi
callq 0x4580
testq %rax, %rax
je 0x4d2d
movq %rax, %r12
leaq 0x9f3b(%rip), %r13      # 0xebc0
leaq 0x53d8(%rip), %r15      # 0xa064
leaq 0xa04d(%rip), %rbp      # 0xece0
movl $0x10, %r14d
movq -0x10(%r14,%r13), %rdi
movq %r12, %rsi
callq 0x4540
testl %eax, %eax
je 0x4cd6
addq $0x18, %r14
cmpq $0x130, %r14            # imm = 0x130
jne 0x4c99
movb (%r12), %al
addb $-0x30, %al
cmpb $0xa, %al
jae 0x4ce5
movb $0x0, 0x20(%rbx)
movq %r12, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x4420
movzbl %al, %eax
jmp 0x4d11
movq -0x8(%r14,%r13), %rax
movq %rax, 0x18(%rbx)
movl (%r14,%r13), %eax
jmp 0x4d14
movl $0x8, %r14d
movq -0x8(%r14,%rbp), %rdi
movq %r12, %rsi
callq 0x4540
testl %eax, %eax
je 0x4d0d
addq $0x10, %r14
cmpq $0xd8, %r14
jne 0x4ceb
xorl %eax, %eax
jmp 0x4d11
movl (%r14,%rbp), %eax
orl 0x20(%rbx), %eax
movl %eax, 0x20(%rbx)
xorl %edi, %edi
movq %r15, %rsi
callq 0x4580
movq %rax, %r12
testq %rax, %rax
jne 0x4c93
cmpq $0x0, 0x18(%rbx)
je 0x4d71
movq 0xa9c5(%rip), %rdi      # 0xf700
movq %rbx, %rsi
callq 0x863c
movq %rax, 0xa9b6(%rip)      # 0xf700
jmp 0x4d79
movq %rbx, %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
movq 0x8(%rsp), %rdi
jmp 0x4d4f