// File: /workspace/github_c_makefile_star2_O0/mohuangrui[P]ArtraCFD/calculator.c
// Function: SolveExpression
static int SolveExpression(CalcVar *var, const char *str, Operand *oprd, Operator *oprt)
{
    /* use a new space to avoid modify the original expression */
    String space = {'\0'};
    /*
     * Use as a flag to check whether '+' and '-' are unary operator based on
     * the assumption that if "+" "-" appears as unary operator then it must
     * after a parentheses except at the beginning of an expression. By putting
     * a "(" at the front of the expression, then this rule is always true.
     */
    space[0] = '(';
    /* target expression begins at the second position of storage address */
    char *expr = space + 1;
    /*
     * Copy the expression to space, because need to access expr[2] and even
     * later position when search and convert the expr to math expression,
     * limit the available space for copy is a safety choice.
     */
    strncpy(expr, str, (int)(sizeof space) - LENOPRT);
    if (0 != TranslateToMath(expr)) {
        return 1;
    }
    char toprt = '\0'; /* store the top operator of operator stack */
    char coprt = '\0'; /* store the current operator */
    Real oprdx = 0.0; /* first top operand in stack */
    Real oprdy = 0.0; /* second top operand in stack */
    Real coprd = 0.0; /* store the current operand */
    /* always initialize and reset the stack status */
    oprt->top = oprt->bom;
    oprd->top = oprd->bom;
    PushOperator(oprt,'\0'); /* push a end flag to the operator stack */
    /* calculation loop */
    while (('\0' != *expr) || ('\0' != GetTopOperator(oprt))) {
        if (IsDigit(*expr)) { /* find a operand */
            coprd = ExtractFirstFloat(&expr);
            if (0 != PushOperand(oprd, coprd)) {
                return 1;
            }
            continue;
        }
        if (IsConstant(*expr)) { /* find a constant */
            coprd = ExtractConstant(var, &expr);
            if (0 != PushOperand(oprd, coprd)) {
                return 1;
            }
            continue;
        }
        /* treat everything left as an operator */
        if (!IsOperator(*expr)) {
            ShowWarning("undefined operator in expression");
            return 1;
        }
        coprt = *expr;
        switch (QueryPriority(oprt, GetTopOperator(oprt), coprt)) {
            case '<': /* push the new high-priority operator into stack */
                if (IsDualOperatorActAsUnary(expr)) {
                    /*
                     * Dual operator (they can both be unary and binary)
                     * '+' '-' show as a unary operator, then push a 0 to
                     * operand stack to make them become binary operator
                     */
                    if (0 != PushOperand(oprd, 0)) {
                        return 1;
                    }
                }
                if (0 != PushOperator(oprt, coprt)) {
                    return 1;
                }
                ++expr;
                break;
            case '=': /* dump the two same-priority operators as they are control operators */
                if (0 != PopOperator(oprt, &coprt)) {
                    return 1;
                }
                ++expr;
                break;
            case '>': /* hold the new low-priority operator and finish the old high-priority operator */
                if (0 != PopOperator(oprt, &toprt)) {
                    return 1;
                }
                if (IsPureUnaryOperator(toprt)) {
                    if (0 != PopOperand(oprd, &oprdx)) {
                        return 1;
                    }
                    if (0 != DoUnary(toprt, oprdx, &coprd)) {
                        return 1;
                    }
                    if (0 != PushOperand(oprd, coprd)) {
                        return 1;
                    }
                } else {
                    if (0 != PopOperand(oprd, &oprdx)) {
                        return 1;
                    }
                    if (0 != PopOperand(oprd, &oprdy)) {
                        return 1;
                    }
                    if (0 != DoBinary(oprdy, toprt, oprdx, &coprd)) {
                        return 1;
                    }
                    if (0 != PushOperand(oprd, coprd)) {
                        return 1;
                    }
                }
                break;
            default:
                ShowWarning("can not match parenthesis");
                return 1;
        }
    }
    /*
     * If the loop successfully exit, then it means the expression
     * and operator stack are all processed, now need to check the
     * operand stack, if there are more than one element left,
     * it means something wrong happened.
     */
    if (1 != (oprd->top - oprd->bom)) {
        ShowWarning("wrong expression");
        return 1;
    }
    /* save the result to answer */
    var->ans = GetTopOperand(oprd);
    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x130, %rsp            # imm = 0x130
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
leaq -0xf0(%rbp), %rdi
xorl %esi, %esi
movl $0xc8, %edx
callq 0x20d0
movb $0x28, -0xf0(%rbp)
leaq -0xf0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xf8(%rbp)
movq -0xf8(%rbp), %rdi
movq -0x18(%rbp), %rsi
movl $0xc3, %edx
callq 0x2040
movq -0xf8(%rbp), %rdi
callq 0x3890
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
je 0x343c
movl $0x1, -0x4(%rbp)
jmp 0x3884
movb $0x0, -0xf9(%rbp)
movb $0x0, -0xfa(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x108(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x110(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x118(%rbp)
movq -0x28(%rbp), %rax
movq (%rax), %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x20(%rbp), %rax
movq (%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x28(%rbp), %rdi
xorl %esi, %esi
callq 0x3d90
movq -0xf8(%rbp), %rax
movsbl (%rax), %edx
movb $0x1, %al
xorl %ecx, %ecx
cmpl %edx, %ecx
movb %al, -0x119(%rbp)
jne 0x34c5
movq -0x28(%rbp), %rdi
callq 0x3e10
movsbl %al, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
setne %al
movb %al, -0x119(%rbp)
movb -0x119(%rbp), %al
testb $0x1, %al
jne 0x34d4
jmp 0x3834
movq -0xf8(%rbp), %rax
movsbl (%rax), %edi
callq 0x3e30
cmpl $0x0, %eax
je 0x3526
leaq -0xf8(%rbp), %rdi
callq 0x3e70
movsd %xmm0, -0x118(%rbp)
movq -0x20(%rbp), %rdi
movsd -0x118(%rbp), %xmm0
callq 0x3f30
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
je 0x3521
movl $0x1, -0x4(%rbp)
jmp 0x3884
jmp 0x3494
movq -0xf8(%rbp), %rax
movsbl (%rax), %edi
callq 0x3fb0
cmpl $0x0, %eax
je 0x357c
movq -0x10(%rbp), %rdi
leaq -0xf8(%rbp), %rsi
callq 0x4030
movsd %xmm0, -0x118(%rbp)
movq -0x20(%rbp), %rdi
movsd -0x118(%rbp), %xmm0
callq 0x3f30
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
je 0x3577
movl $0x1, -0x4(%rbp)
jmp 0x3884
jmp 0x3494
movq -0xf8(%rbp), %rax
movsbl (%rax), %edi
callq 0x4150
cmpl $0x0, %eax
jne 0x35aa
leaq 0x211a3(%rip), %rdi     # 0x2473a
movb $0x0, %al
callq 0xbb20
movl $0x1, -0x4(%rbp)
jmp 0x3884
movq -0xf8(%rbp), %rax
movb (%rax), %al
movb %al, -0xfa(%rbp)
movq -0x28(%rbp), %rdi
movq %rdi, -0x128(%rbp)
callq 0x3e10
movq -0x128(%rbp), %rdi
movsbl -0xfa(%rbp), %edx
movsbl %al, %esi
callq 0x41f0
movsbl %al, %eax
movl %eax, -0x120(%rbp)
subl $0x3c, %eax
je 0x3614
jmp 0x35ef
movl -0x120(%rbp), %eax
subl $0x3d, %eax
je 0x3682
jmp 0x3600
movl -0x120(%rbp), %eax
subl $0x3e, %eax
je 0x36bd
jmp 0x3818
movq -0xf8(%rbp), %rdi
callq 0x4240
cmpl $0x0, %eax
je 0x3647
movq -0x20(%rbp), %rdi
xorps %xmm0, %xmm0
callq 0x3f30
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
je 0x3645
movl $0x1, -0x4(%rbp)
jmp 0x3884
jmp 0x3647
movq -0x28(%rbp), %rdi
movsbl -0xfa(%rbp), %esi
callq 0x3d90
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
je 0x366b
movl $0x1, -0x4(%rbp)
jmp 0x3884
movq -0xf8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xf8(%rbp)
jmp 0x382f
movq -0x28(%rbp), %rdi
leaq -0xfa(%rbp), %rsi
callq 0x4290
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
je 0x36a6
movl $0x1, -0x4(%rbp)
jmp 0x3884
movq -0xf8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xf8(%rbp)
jmp 0x382f
movq -0x28(%rbp), %rdi
leaq -0xf9(%rbp), %rsi
callq 0x4290
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
je 0x36e1
movl $0x1, -0x4(%rbp)
jmp 0x3884
movsbl -0xf9(%rbp), %edi
callq 0x4300
cmpl $0x0, %eax
je 0x3771
movq -0x20(%rbp), %rdi
leaq -0x108(%rbp), %rsi
callq 0x43a0
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
je 0x3716
movl $0x1, -0x4(%rbp)
jmp 0x3884
movb -0xf9(%rbp), %al
movsd -0x108(%rbp), %xmm0
leaq -0x118(%rbp), %rsi
movsbl %al, %edi
callq 0x4410
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
je 0x3747
movl $0x1, -0x4(%rbp)
jmp 0x3884
movq -0x20(%rbp), %rdi
movsd -0x118(%rbp), %xmm0
callq 0x3f30
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
je 0x376c
movl $0x1, -0x4(%rbp)
jmp 0x3884
jmp 0x3816
movq -0x20(%rbp), %rdi
leaq -0x108(%rbp), %rsi
callq 0x43a0
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
je 0x3795
movl $0x1, -0x4(%rbp)
jmp 0x3884
movq -0x20(%rbp), %rdi
leaq -0x110(%rbp), %rsi
callq 0x43a0
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
je 0x37b9
movl $0x1, -0x4(%rbp)
jmp 0x3884
movsd -0x110(%rbp), %xmm0
movb -0xf9(%rbp), %al
movsd -0x108(%rbp), %xmm1
leaq -0x118(%rbp), %rsi
movsbl %al, %edi
callq 0x45e0
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
je 0x37f2
movl $0x1, -0x4(%rbp)
jmp 0x3884
movq -0x20(%rbp), %rdi
movsd -0x118(%rbp), %xmm0
callq 0x3f30
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
je 0x3814
movl $0x1, -0x4(%rbp)
jmp 0x3884
jmp 0x3816
jmp 0x382f
leaq 0x20f3c(%rip), %rdi     # 0x2475b
movb $0x0, %al
callq 0xbb20
movl $0x1, -0x4(%rbp)
jmp 0x3884
jmp 0x3494
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rcx
movq -0x20(%rbp), %rax
movq (%rax), %rax
subq %rax, %rcx
sarq $0x3, %rcx
movl $0x1, %eax
cmpq %rcx, %rax
je 0x386b
leaq 0x20f1a(%rip), %rdi     # 0x24775
movb $0x0, %al
callq 0xbb20
movl $0x1, -0x4(%rbp)
jmp 0x3884
movq -0x20(%rbp), %rdi
callq 0x4710
movq -0x10(%rbp), %rax
movsd %xmm0, 0x20(%rax)
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x130, %rsp            # imm = 0x130
popq %rbp
retq