// File: /workspace/github_c_makefile_star2_O1/theovosse[P]llgen/llgen.c
// Function: determineEmptyRule
static Boolean determineEmptyRule(Node rule) {
	Boolean empty = true, firstPrinted;
	NodeList* rules, emptyRule;

	if (rule == NULL || rule->empty) {
		return true;
	}
	for (Node ptr = rule; ptr != NULL; ptr = ptr->next) {
		switch (ptr->nodeType) {
			case single: /* Only if identifier produces empty, not if string; ignore code and output */
				if (!((ptr->element.name->nameType == identifier && ptr->element.name->empty) ||
					  ptr->element.name->nameType == output ||
					  ptr->element.name->nameType == code)) {
					empty = false;
				}
				break;
			case option: /* Bien sure */
				break;
			case sequence: /* Only if subpart is empty */
				if (!determineEmptyRule(ptr->element.sub)) {
					empty = false;
				}
				break;
			case chain: /* Only if first part of chain is empty, second doesn't matter */
				if (!determineEmptyRule(ptr->element.sub->element.sub)) {
					empty = false;
				}
				break;
			case alternative: /* Only if one of the alternatives is empty */
				firstPrinted = false;
				rules = &ptr->element.alternatives;
				emptyRule = NULL;
				if (!ptr->element.alternatives->empty) {
					while (*rules != NULL) {
						if (determineEmptyRule((*rules)->first)) {
							if (emptyRule != NULL) {
								if (!firstPrinted) {
									if (emptyRule->first != NULL) {
										fprintf(stderr, "%s:%d:error: more than one empty alternative\n",
												inputFileName, emptyRule->first->lineNr);
									} else {
										fprintf(stderr, "%s:%d:error: more than one empty alternative following this line\n",
												inputFileName, ptr->lineNr);
									}
									firstPrinted = true;
								}
								if ((*rules)->first != NULL) {
									fprintf(stderr, "%s:%d:error: and here\n",
											inputFileName, (*rules)->first->lineNr);
								} else {
									fprintf(stderr, "%s:%d:error: and following this line\n",
											inputFileName, ptr->lineNr);
								}
								notLLError = true;
								rules = &(*rules)->rest;
							} else {
								// Take this out of the list and move it to the end
								emptyRule = *rules;
								*rules = emptyRule->rest;
								emptyRule->rest = NULL;
							}
						} else {
							rules = &(*rules)->rest;
						}
					}
					if (emptyRule != NULL) {
						// Reorder such that emptyRule goes to the end.
						*rules = emptyRule;
						ptr->element.alternatives->empty = true;
					} else {
						empty = false;
					}
				}
				break;
			case breakToken:
			case errorMessage:
				break;
			// default:
			// 	fprintf(stderr, "determineEmptyRule: unknown nodetype %d\n", ptr->nodeType);
			// 	return empty;
		}
	}
	rule->empty = empty;
	return empty;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movw $0xffff, %bx            # imm = 0xFFFF
testq %rdi, %rdi
je 0x65e5
cmpw $0x0, 0x22(%rdi)
jne 0x65e5
movw $0xffff, %bx            # imm = 0xFFFF
leaq 0xabc4(%rip), %r13      # 0x1103c
xorl %r14d, %r14d
movq %rdi, 0x10(%rsp)
movq %rdi, %r15
movl 0x4(%r15), %eax
cmpq $0x4, %rax
ja 0x65cf
movslq (%r13,%rax,4), %rax
addq %r13, %rax
jmpq *%rax
movq 0x18(%r15), %rcx
movl 0x38(%rcx), %eax
testl %eax, %eax
je 0x65a4
andl $-0x2, %eax
cmpl $0x2, %eax
cmovnel %r14d, %ebx
jmp 0x65cf
movq 0x18(%r15), %rax
movq 0x18(%rax), %rdi
jmp 0x64c7
movq 0x18(%r15), %rdi
callq 0x6447
testw %ax, %ax
cmovel %r14d, %ebx
jmp 0x65cf
movq 0x18(%r15), %rax
cmpw $0x0, 0x10(%rax)
jne 0x65cf
leaq 0x18(%r15), %r14
movq (%r14), %rax
testq %rax, %rax
je 0x65b0
xorl %r12d, %r12d
movq %r14, %rbp
movq $0x0, 0x8(%rsp)
movq (%rax), %rdi
callq 0x6447
testw %ax, %ax
je 0x6530
testq %r12, %r12
jne 0x6543
movq (%rbp), %r12
movq 0x8(%r12), %rax
movq %rax, (%rbp)
movq $0x0, 0x8(%r12)
jmp 0x6538
movq (%rbp), %rbp
addq $0x8, %rbp
movq (%rbp), %rax
testq %rax, %rax
jne 0x6506
jmp 0x65b6
cmpw $0x0, 0x8(%rsp)
jne 0x6556
movq %r12, %rdi
movq %r15, %rsi
callq 0x3389
movq (%rbp), %rax
movq (%rax), %rax
testq %rax, %rax
cmoveq %r15, %rax
leaq 0xadb5(%rip), %rsi      # 0x11320
leaq 0xadc5(%rip), %rcx      # 0x11337
cmoveq %rcx, %rsi
movq 0x12a7b(%rip), %rcx     # 0x18ff8
movq (%rcx), %rdi
movq 0x12c01(%rip), %rdx     # 0x19188
movswl (%rax), %ecx
xorl %eax, %eax
callq 0x3160
movq (%rbp), %rbp
addq $0x8, %rbp
movw $0xffff, %ax            # imm = 0xFFFF
movq %rax, 0x8(%rsp)
jmp 0x6538
cmpw $0x0, 0x30(%rcx)
jne 0x65cf
jmp 0x64aa
movq %r14, %rbp
xorl %r12d, %r12d
testq %r12, %r12
je 0x65ca
movq %r12, (%rbp)
movq (%r14), %rax
movw $0xffff, 0x10(%rax)     # imm = 0xFFFF
jmp 0x65cc
xorl %ebx, %ebx
xorl %r14d, %r14d
movq 0x28(%r15), %r15
testq %r15, %r15
jne 0x6483
movq 0x10(%rsp), %rax
movw %bx, 0x22(%rax)
movl %ebx, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq