// Jonas Altrock <ew20b126@technikum-wien.at>
//
// [To overview](../).
//
// [The whole source file `calc.c`.](./calc.c)
/* Compile with `clang -std=c99 -Wall -o calc calc.c` */

// Include C-libraries for input/output, math, allocation of memory,
// and string manipulations.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>

// ## Task
// Implement a calculator. The calculator should be able to execute seven
// instructions in total and should use decimal numbers (double).

// First read a decimal number, then read an arbitrary number of instructions
// (all separated by space or newline). These instructions are executed and the
// result is used for the next instruction. Finally, after `=` has been printed,
// your program should print `Result: `, followed by the final result and terminate.
// Your program should handle the following instructions:
//   - `+` (addition),
//   - `-` (subtraction),
//   - `*` (multiplication),
//   - `/` (division),
//   - `neg` (negate) and
//   - `sqrt` (square root).
//
// The instructions `+`, `-`, `*` and `/` are followed by another number,
// the second argument.
// The result should be printed with three decimal numbers.

// ## Solution

// These are macros, they are replaced by the pre-processor.
// An instruction is at most 4 characters, which is the length of the longest
// instruction `sqrt`. For a string buffer that holds an instruction, we need
// one more character for the null-termination.
#define BUFFER_LENGTH 5

// An instruction is a string, so read with format `%s` with length `4`.
#define instruction(x) scanf("%4s", x)

// A number is read with `%lf` to read a double (long float).
#define number(x) scanf("%lf", &(x))

// The main part of the program.
int main() {
    // We only ever need two numbers - the result from a previous calculation
    // and the next number we want to add, subtract etc.
    double x, y;

    // Our instruction buffer.
    char *op = calloc(BUFFER_LENGTH, sizeof(char));

    // Start by reading a number.
    number(x);

    // Next, read an instruction.
    instruction(op);

    // Continue reading and calculating until a `=` is read.
    while (op[0] != '=') {
        // The switch construct lets us decide on the first character of the
        // instruction, which is thankfully enough to decide between all 7
        // instructions.
        switch (op[0]) {
        case '+':
            number(y);
            x = x + y;
            break;
        case '-':
            number(y);
            x = x - y;
            break;
        case '*':
            number(y);
            x = x * y;
            break;
        case '/':
            number(y);
            x = x / y;
            break;
        case 'n':
            if (strcmp(op, "neg") != 0) printf("Interpreted '%s' as neg\n", op);
            x = -x;
            break;
        case 's':
            if (strcmp(op, "sqrt") != 0) printf("Interpreted '%s' as sqrt\n", op);
            x = sqrt(x);
            break;
        default:
            printf("Unrecognized instruction: %s\n", op);
            break;
        }

        // Read in next instruction.
        instruction(op);
    }

    // Finally, print result.
    printf("Result: %.3lf\n", x);
    return 0;
}