/* Copyright (C) 2014 by Alexandru Cojocaru */
/* This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
#include
#include
#include
#include
#define STRINGIZE(m) #m
#define STRINGIZE2(m) STRINGIZE(m)
#define N_MAXDIGS 10
enum {
STMAXDEPTH = 100,
};
static double stack[STMAXDEPTH];
static int stackind = 0;
static int
checkargs (int needed)
{
if (stackind < needed)
error (1, 0, "stack underflow: args present %d, args needed %d\n",
stackind, needed);
}
static int
skipws (FILE *in)
{
int c;
do
c = getc (in);
while (isspace (c));
ungetc (c, in);
}
static int
getnum (FILE *in)
{
double v;
char buf[N_MAXDIGS + 1];
char *tailp = NULL;
char *p = buf;
int c;
fscanf (in, "%" STRINGIZE2 (N_MAXDIGS) "s", buf);
errno = 0;
v = strtod (buf, &tailp);
if (errno != 0 || (tailp != NULL && *tailp != '\0'))
error (1, errno, "can't decode number: `%s'\n", buf, tailp);
printf ("v: %f\n", v);
stack[stackind] = v;
return 1;
}
/* return: EOF on EOF, 0 on failure, 1 on success */
static int
next (FILE *in)
{
int c;
int r = 1;
if (stackind == STMAXDEPTH)
error (1, 0, "exceded stack limit of %u\n", STMAXDEPTH);
skipws (in);
c = getc (in);
switch (c) {
case '0' ... '9':
ungetc (c, in);
r = getnum (in);
break;
case '+':; case '-':;
int nextc = getc (in);
ungetc (nextc, in);
if (isdigit (nextc)) {
r = getnum (in);
break;
}
case '*': case '/': /* fail trough */
checkargs (2);
double res;
switch (c) {
case '+': res = stack[stackind - 2] + stack[stackind - 1]; break;
case '-': res = stack[stackind - 2] - stack[stackind - 1]; break;
case '*': res = stack[stackind - 2] * stack[stackind - 1]; break;
case '/': res = stack[stackind - 2] / stack[stackind - 1]; break;
}
stackind -= 2;
stack[stackind] = res;
break;
case EOF:
return EOF;
default:
printf ("unknown character: %c\n", c);
break;
}
++stackind;
return r;
}
int
main (void)
{
int r;
while ((r = next (stdin)) == 1)
;
if (r == EOF)
puts ("EOF");
if (stackind == 0)
error (1, 0, "the stack must contain at least one element\n");
printf ("%f\n", stack[stackind-1]);
}