#include <ctype.h>
#include <assert.h>
-#define BUFSIZE 100
+#define NDEBUG
+
+#define BUFSIZE 1024
+
+#define bail(arg...) do { fprintf(stderr, ##arg); exit(EXIT_FAILURE); } while (0)
char *arg;
char opstack[BUFSIZE];
int istackp,opstackp;
+#ifdef NDEBUG
+#define dump(x)
+#else
+static void dump(char *pref)
+{
+int i;
+ fprintf(stderr,"%s: i[",pref);
+ for (i=0;i<istackp;i++) {
+ if (i) fputc(',',stderr);
+ fprintf(stderr,"%d",istack[i]);
+ }
+ fprintf(stderr,"],op=[");
+ for (i=0;i<opstackp;i++) fputc(opstack[i],stderr);
+ fprintf(stderr,"]\n");
+}
+#endif
+
static char lex(int *ip)
{
char c;
*ip=l;
return 'n';
default:
- fprintf(stderr,"Invalid characted in string: %s\n",arg);
- exit(EXIT_FAILURE);
+ bail("Invalid characted in string: %s\n",arg);
}
}
static void evalit(void)
{
- assert(opstackp);
- if (istackp<2) {
- fprintf(stderr,"2 arguments for operator required!\n");
- exit(EXIT_FAILURE);
- }
+ dump("evalit()");
+ assert(opstackp); opstackp--;
+ if (istackp<2)
+ if (opstack[opstackp]!='(') bail("2 arguments for operator '%c' required!\n",opstack[opstackp]);
+ else bail("Stray '('!\n");
istackp--;
- switch (opstack[--opstackp]) {
+ switch (opstack[opstackp]) {
case '+': istack[istackp-1]+=istack[istackp]; break;
case '-': istack[istackp-1]-=istack[istackp]; break;
case '*': istack[istackp-1]*=istack[istackp]; break;
case '/':
- if (!istack[istackp]) {
- fprintf(stderr,"Division of %d by zero not supported!\n",istack[istackp-1]);
- exit(EXIT_FAILURE);
- }
+ if (!istack[istackp]) bail("Division of %d by zero not supported!\n",istack[istackp-1]);
istack[istackp-1]/=istack[istackp];
break;
}
evalit();
if (!op) return;
if (op==')') {
- if (!opstackp || opstack[opstackp-1]!='(') {
- fprintf(stderr,"Not enough content for brackets-inside space!\n");
- exit(EXIT_FAILURE);
- }
+ if (!opstackp || opstack[opstackp-1]!='(')
+ bail("Not enough content for brackets-inside space!\n");
opstackp--;
return;
}
- assert(opstackp<BUFSIZE);
+ if (opstackp>=BUFSIZE) bail("Too many operators (%d is max)!\n",BUFSIZE);
opstack[opstackp++]=op;
}
static void process(void)
{
-char lastop=0,op;
+char lastop,op;
int curi;
istackp=opstackp=0;
- for (;;) switch ((op=lex(&curi))) {
+ for (lastop=0;;lastop=op) switch (op=lex(&curi)) {
case 'n':
- if (lastop=='n') {
- fprintf(stderr,"Two successive numbers not permitted!\n");
- exit(EXIT_FAILURE);
- }
- assert(istackp<BUFSIZE);
+ if (lastop=='n') bail("Two successive numbers not permitted!\n");
+ if (istackp>=BUFSIZE) bail("Too many operators (%d is max)!\n",BUFSIZE);
istack[istackp++]=curi;
break;
case '(':
- if (lastop=='n') {
- fprintf(stderr,"Open-bracket not permitted after number!\n");
- exit(EXIT_FAILURE);
- }
+ if (lastop=='n') bail("Open-bracket not permitted after number!\n");
pushop(op);
break;
case '+': case '-': case '*': case '/': case ')': pushop(op); break;
case 0:
pushop(op);
- if (istackp!=1||opstackp) {
- fprintf(stderr,"Machine not in sane state on the end of expression, ints=%d,ops=%d!\n",istackp,opstackp);
- exit(EXIT_FAILURE);
- }
+ if (istackp!=1||opstackp)
+ bail("Machine not in sane state on the end of expression, ints=%d,ops=%d!\n",istackp,opstackp);
printf("%d\n",istack[0]);
return;
default: assert(0);