aboutsummaryrefslogtreecommitdiff
path: root/math.c
blob: 1f6d093b974fe99cc680281800879e39111f1beb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include "internal.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>

/* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */

static const char math_usage[] = "math expression ...";

static double		stack[100];
static unsigned int	pointer;

static void
push(double a)
{
	if ( pointer >= (sizeof(stack) / sizeof(*stack)) ) {
		fprintf(stderr, "math: stack overflow\n");
		exit(-1);
	}
	else
		stack[pointer++] = a;
}

static double
pop()
{
	if ( pointer == 0 ) {
		fprintf(stderr, "math: stack underflow\n");
		exit(-1);
	}
	return stack[--pointer];
}

static void
add()
{
	push(pop() + pop());
}

static void
sub()
{
	double	subtrahend = pop();

	push(pop() - subtrahend);
}

static void
mul()
{
	push(pop() * pop());
}

static void
divide()
{
	double	divisor = pop();
	push(pop() / divisor);
}

static void
and()
{
	push((unsigned int)pop() & (unsigned int)pop());
}

static void
or()
{
	push((unsigned int)pop() | (unsigned int)pop());
}

static void
eor()
{
	push((unsigned int)pop() ^ (unsigned int)pop());
}

static void
not()
{
	push(~(unsigned int)pop());
}

static void
print()
{
	printf("%g\n", pop());
}

struct op {
	const char *	name;
	void			(*function)();
};

static const struct op	operators[] = {
	{	"add",	add	},
	{	"and",	and	},
	{	"div",	divide	},
	{	"eor",	eor	},
	{	"mul",	mul	},
	{	"not",	not	},
	{	"or",	or	},
	{	"sub",	sub	},
	{	0,		0	}
};

static void
stack_machine(const char * argument)
{
	char *				endPointer = 0;
	double				d;
	const struct op *	o = operators;

	if ( argument == 0 ) {
		print();
		return;
	}

	d = strtod(argument, &endPointer);

	if ( endPointer != argument ) {
		push(d);
		return;
	}

	while ( o->name != 0 ) {
		if ( strcmp(o->name, argument) == 0 ) {
			(*(o->function))();
			return;
		}
		o++;
	}
	fprintf(stderr, "math: %s: syntax error.\n", argument);
	exit(-1);
}

int
math_main(int argc, char * * argv)
{
	while ( argc >= 2 ) {
		stack_machine(argv[1]);
		argv++;
		argc--;
	}
	stack_machine(0);
	return 0;
}