// File: /workspace/github_c_makefile_star2_O0/theovosse[P]llgen/llgen.c
// Function: DetermineFollowRule
static void DetermineFollowRule(TREE *follow, Node rule, Name orig, TREE followers) {
	NodeList rules;
	TREE nFollowers;
	TREE chain1EltFollowers;
	TREE chain2EltFollowers;
    TREE sequenceFirstsAndFollowers;

	for (; rule != NULL; rule = rule->next) {
		if (rule->nodeType != single || rule->element.name == orig) {
			nFollowers = NULL;
			(void) collectFirst(&nFollowers, followers, rule->next);
			switch (rule->nodeType) {
				case single: /* && rule->element.name == orig */
					if (Unite(follow, nFollowers)) {
						changes = true;
					}
					break;
				case option:
					DetermineFollowRule(follow, rule->element.sub, orig, nFollowers);
					break;
				case sequence:
                    sequenceFirstsAndFollowers = NULL;
                    (void) collectFirst(&sequenceFirstsAndFollowers, NULL, rule->element.sub);
                    Unite(&sequenceFirstsAndFollowers, nFollowers);
					DetermineFollowRule(follow, rule->element.sub, orig, sequenceFirstsAndFollowers);
                    KillTree(sequenceFirstsAndFollowers, NULL);
					break;
				case chain:
					/*	A CHAIN B, C
						FOLLOW(A) = nFollowers + FIRST(B) + (EMPTY(B)? FIRST(A) + ...: EMPTY)
						FOLLOW(B) = FIRST(A) + (EMPTY(A)? FIRST(B) + nFollowers: EMPTY) */
					chain1EltFollowers = NULL;
					chain2EltFollowers = NULL;
					(void) collectFirst(&chain2EltFollowers, nFollowers, rule->element.sub->element.sub);
					/* chain2EltFollowers = FIRST(A) + (EMPTY(A)? nFollowers: EMPTY) */
					(void) collectFirst(&chain1EltFollowers, chain2EltFollowers, rule->element.sub->next->element.sub);
					/* chain1EltFollowers = FIRST(B) + (EMPTY(B)? chain2EltFollowers: EMPTY) */
					(void) Unite(&chain1EltFollowers, nFollowers);
					/* chain1EltFollowers = nFollowers + FIRST(B) + ... */
					DetermineFollowRule(follow, rule->element.sub->element.sub, orig, chain1EltFollowers);
					KillTree(chain1EltFollowers, NULL);
					KillTree(chain2EltFollowers, NULL);
					chain1EltFollowers = NULL;
					chain2EltFollowers = NULL;
					(void) collectFirst(&chain2EltFollowers, NULL, rule->element.sub->next->element.sub);
					/* chain2EltFollowers = FIRST(B) */
					(void) Unite(&chain2EltFollowers, nFollowers);
					/* chain2EltFollowers = FIRST(B) + nFollowers */
					(void) collectFirst(&chain1EltFollowers, chain2EltFollowers, rule->element.sub->element.sub);
					/* chain1EltFollowers = FIRST(A) + (EMPTY(A)? chain2EltFollowers: EMPTY) */
					DetermineFollowRule(follow, rule->element.sub->next->element.sub, orig, chain1EltFollowers);
					KillTree(chain1EltFollowers, NULL);
					KillTree(chain2EltFollowers, NULL);
					break;
				case alternative: /* Try each one... */
					for (rules = rule->element.alternatives; rules != NULL; rules = rules->rest) {
						DetermineFollowRule(follow, rules->first, orig, nFollowers);
					}
					break;
				case breakToken:
				case errorMessage:
					// Just empty productions
					break;
				// default:
				// 	fprintf(stderr, "DetermineFollowRule: unknown nodetype %d", rule->nodeType);
				// 	return;
			}
			KillTree(nFollowers, NULL);
		}
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
cmpq $0x0, -0x10(%rbp)
je 0x6100
movq -0x10(%rbp), %rax
cmpl $0x0, 0x4(%rax)
jne 0x5eaf
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
cmpq -0x18(%rbp), %rax
jne 0x60ed
movq $0x0, -0x30(%rbp)
movq -0x20(%rbp), %rsi
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rdx
leaq -0x30(%rbp), %rdi
callq 0x5ba0
movq -0x10(%rbp), %rax
movl 0x4(%rax), %eax
movq %rax, -0x50(%rbp)
subq $0x6, %rax
ja 0x60e0
movq -0x50(%rbp), %rax
leaq 0x131a4(%rip), %rcx     # 0x19090
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x8(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x5e00
cmpw $0x0, %ax
je 0x5f11
movw $0xffff, 0x1ae6f(%rip)  # imm = 0xFFFF
jmp 0x60e0
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rsi
movq -0x18(%rbp), %rdx
movq -0x30(%rbp), %rcx
callq 0x5e70
jmp 0x60e0
movq $0x0, -0x48(%rbp)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdx
leaq -0x48(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5ba0
movq -0x30(%rbp), %rsi
leaq -0x48(%rbp), %rdi
callq 0x5e00
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rsi
movq -0x18(%rbp), %rdx
movq -0x48(%rbp), %rcx
callq 0x5e70
movq -0x48(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x106c0
jmp 0x60e0
movq $0x0, -0x38(%rbp)
movq $0x0, -0x40(%rbp)
movq -0x30(%rbp), %rsi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movq 0x18(%rax), %rdx
leaq -0x40(%rbp), %rdi
callq 0x5ba0
movq -0x40(%rbp), %rsi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movq 0x28(%rax), %rax
movq 0x18(%rax), %rdx
leaq -0x38(%rbp), %rdi
callq 0x5ba0
movq -0x30(%rbp), %rsi
leaq -0x38(%rbp), %rdi
callq 0x5e00
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movq 0x18(%rax), %rsi
movq -0x18(%rbp), %rdx
movq -0x38(%rbp), %rcx
callq 0x5e70
movq -0x38(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x106c0
movq -0x40(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x106c0
movq $0x0, -0x38(%rbp)
movq $0x0, -0x40(%rbp)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movq 0x28(%rax), %rax
movq 0x18(%rax), %rdx
leaq -0x40(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5ba0
movq -0x30(%rbp), %rsi
leaq -0x40(%rbp), %rdi
callq 0x5e00
movq -0x40(%rbp), %rsi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movq 0x18(%rax), %rdx
leaq -0x38(%rbp), %rdi
callq 0x5ba0
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movq 0x28(%rax), %rax
movq 0x18(%rax), %rsi
movq -0x18(%rbp), %rdx
movq -0x38(%rbp), %rcx
callq 0x5e70
movq -0x38(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x106c0
movq -0x40(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x106c0
jmp 0x60e0
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x28(%rbp)
je 0x60dc
movq -0x8(%rbp), %rdi
movq -0x28(%rbp), %rax
movq (%rax), %rsi
movq -0x18(%rbp), %rdx
movq -0x30(%rbp), %rcx
callq 0x5e70
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28(%rbp)
jmp 0x60af
jmp 0x60e0
jmp 0x60e0
movq -0x30(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x106c0
jmp 0x60ef
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x10(%rbp)
jmp 0x5e88
addq $0x50, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)