/**
* @file main.c
* @author Ron Brash
* @date Nov 16, 2017
* @brief Create a simple math helper for CLI usage in Bash
*
* @note To compile:
* gcc -Wall -O2 -o mhelper main.c -lm
*/
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#define USAGE "%s <param1> <operation> <param2>\n"
#define TRUE 1
#define FALSE 0
// Function pointer for math operations
typedef void (*mathfpr_t) (double, double, uint8_t, uint8_t);
// Typedef of structure containing math operation function pointers
// think array of callbacks
typedef struct mathop_s {
char op;
mathfpr_t func;
} mathop_t;
// Forward function declarations
static void subtract(double a, double b, uint8_t a_type, uint8_t b_type);
static void addition(double a, double b, uint8_t a_type, uint8_t b_type);
static void divide(double a, double b, uint8_t a_type, uint8_t b_type);
static void multiply(double a, double b, uint8_t a_type, uint8_t b_type);
static inline int is_whole(double a);
static inline int has_decimal(char *a);
// Declared function pointer array
static mathop_t math_arr[] = { {'-', subtract}, {'+', addition}, {'*', multiply}, {'/', divide}, };
static inline int has_decimal(char *a)
{
int len = 0;
for (len = strlen(a); len > 0; len--) {
if (a[len] == '.') {
return (TRUE);
}
}
return (FALSE);
}
static inline int is_whole(double a)
{
if (a == (int)a) {
// true
return (TRUE);
}
// false
return (FALSE);
}
static inline void print_val(double a, int type)
{
if (type == 0) {
printf("%.2f\n", a); // Only print out two decimal points
} else {
printf("%i\n", (int)a);
}
}
static void subtract(double a, double b, uint8_t a_type, uint8_t b_type)
{
double res = a - b;
print_val(res, is_whole(res));
}
static void divide(double a, double b, uint8_t a_type, uint8_t b_type)
{
double res = a / b;
print_val(res, is_whole(res));
}
static void multiply(double a, double b, uint8_t a_type, uint8_t b_type)
{
double res = a * b;
print_val(res, is_whole(res));
}
static void addition(double a, double b, uint8_t a_type, uint8_t b_type)
{
double res = a + b;
print_val(res, is_whole(res));
}
static void set_param(char *param, double *val, int *type)
{
char *tmp;
if (has_decimal(param) > 0) {
*val = strtof(param, NULL);
*type = 1;
} else {
*val = strtoll(param, &tmp, 10);
}
}
int main(int argc, char *argv[])
{
/// Initialize function variables in the stack
double a = 0, b = 0;
int a_type = 0, b_type = 0;
char op = '\0';
/// There are four parameters including the binary itself on the CLI
if (argc == 4) {
/// Copy params to values
strncpy(&op, argv[2], sizeof(char));
/// Let's set & check if it has a decimal (signify a float early)
set_param(argv[1], &a, &a_type);
set_param(argv[3], &b, &b_type);
int i = 0;
for (i = 0; i < sizeof(math_arr); i++) {
if (op == math_arr[i].op) {
math_arr[i].func(a, b, a_type, b_type);
return (TRUE);
break;
}
}
}
printf(USAGE, argv[0]);
return (FALSE);
}