Apply vodz last_patch51_2 and run through indent

This commit is contained in:
Glenn L McGrath 2002-08-23 12:04:23 +00:00
parent e599b6d96e
commit de9e803149

View File

@ -26,14 +26,14 @@
* listed in #defines below. Parens, order of operations, and error handling * listed in #defines below. Parens, order of operations, and error handling
* are supported. This code is threadsafe. The exact expression format should * are supported. This code is threadsafe. The exact expression format should
* be that which POSIX specifies for shells. */ * be that which POSIX specifies for shells. */
/* The code uses a simple two-stack algorithm. See /* The code uses a simple two-stack algorithm. See
* http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
* for a detailed explaination of the infix-to-postfix algorithm on which * for a detailed explaination of the infix-to-postfix algorithm on which
* this is based (this code differs in that it applies operators immediately * this is based (this code differs in that it applies operators immediately
* to the stack instead of adding them to a queue to end up with an * to the stack instead of adding them to a queue to end up with an
* expression). */ * expression). */
/* To use the routine, call it with an expression string and error return /* To use the routine, call it with an expression string and error return
* pointer */ * pointer */
@ -140,7 +140,8 @@ typedef char operator;
#define TOK_REM tok_decl(10,2) #define TOK_REM tok_decl(10,2)
/* For now all unary operators have the same precedence, and that's used to /* For now all unary operators have the same precedence, and that's used to
* identify them as unary operators */ * identify them as unary operators
*/
#define UNARYPREC 14 #define UNARYPREC 14
#define TOK_BNOT tok_decl(UNARYPREC,0) #define TOK_BNOT tok_decl(UNARYPREC,0)
#define TOK_NOT tok_decl(UNARYPREC,1) #define TOK_NOT tok_decl(UNARYPREC,1)
@ -149,75 +150,89 @@ typedef char operator;
#define TOK_NUM tok_decl(15,0) #define TOK_NUM tok_decl(15,0)
#define TOK_RPAREN tok_decl(15,1) #define TOK_RPAREN tok_decl(15,1)
#define TOK_ERROR tok_decl(15,2) /* just a place-holder really */ #define TOK_ERROR tok_decl(15,2) /* just a place-holder really */
#define ARITH_APPLY(op) arith_apply(op, numstack, &numstackptr) #define ARITH_APPLY(op) arith_apply(op, numstack, &numstackptr)
#define NUMPTR (*numstackptr) #define NUMPTR (*numstackptr)
/* "applying" a token means performing it on the top elements on the integer /* "applying" a token means performing it on the top elements on the integer
* stack. For a unary operator it will only change the top element, but a * stack. For a unary operator it will only change the top element, but a
* binary operator will pop two arguments and push a result */ * binary operator will pop two arguments and push a result
static short arith_apply(operator op, long *numstack, long **numstackptr) */
static short arith_apply(operator op, long *numstack, long **numstackptr)
{ {
long numptr_val; long numptr_val;
long *NUMPTR_M1; long *NUMPTR_M1;
if (NUMPTR == numstack) goto err; /* There is no operator that can work /* There is no operator that can work without arguments */
without arguments */ if (NUMPTR == numstack) {
goto err;
}
NUMPTR_M1 = NUMPTR - 1; NUMPTR_M1 = NUMPTR - 1;
if (op == TOK_UMINUS) if (op == TOK_UMINUS) {
*NUMPTR_M1 *= -1; *NUMPTR_M1 *= -1;
else if (op == TOK_NOT) } else if (op == TOK_NOT) {
*NUMPTR_M1 = !(*NUMPTR_M1); *NUMPTR_M1 = !(*NUMPTR_M1);
else if (op == TOK_BNOT) } else if (op == TOK_BNOT) {
*NUMPTR_M1 = ~(*NUMPTR_M1); *NUMPTR_M1 = ~(*NUMPTR_M1);
else if (op != TOK_UPLUS) { } else if (op != TOK_UPLUS) {
/* Binary operators */ /* Binary operators */
if (NUMPTR_M1 == numstack) goto err; /* ... and binary operators need two
arguments */ /* ... and binary operators need two arguments */
numptr_val = *--NUMPTR; /* ... and they pop one */ if (NUMPTR_M1 == numstack) {
NUMPTR_M1 = NUMPTR - 1; goto err;
if (op == TOK_BOR) }
*NUMPTR_M1 |= numptr_val; /* ... and they pop one */
else if (op == TOK_OR) numptr_val = *--NUMPTR;
*NUMPTR_M1 = numptr_val || *NUMPTR_M1;
else if (op == TOK_BAND) NUMPTR_M1 = NUMPTR - 1;
*NUMPTR_M1 &= numptr_val;
else if (op == TOK_AND) if (op == TOK_BOR) {
*NUMPTR_M1 = *NUMPTR_M1 && numptr_val; *NUMPTR_M1 |= numptr_val;
else if (op == TOK_EQ) } else if (op == TOK_OR) {
*NUMPTR_M1 = (*NUMPTR_M1 == numptr_val); *NUMPTR_M1 = numptr_val || *NUMPTR_M1;
else if (op == TOK_NE) } else if (op == TOK_BAND) {
*NUMPTR_M1 = (*NUMPTR_M1 != numptr_val); *NUMPTR_M1 &= numptr_val;
else if (op == TOK_GE) } else if (op == TOK_AND) {
*NUMPTR_M1 = (*NUMPTR_M1 >= numptr_val); *NUMPTR_M1 = *NUMPTR_M1 && numptr_val;
else if (op == TOK_RSHIFT) } else if (op == TOK_EQ) {
*NUMPTR_M1 >>= numptr_val; *NUMPTR_M1 = (*NUMPTR_M1 == numptr_val);
else if (op == TOK_LSHIFT) } else if (op == TOK_NE) {
*NUMPTR_M1 <<= numptr_val; *NUMPTR_M1 = (*NUMPTR_M1 != numptr_val);
else if (op == TOK_GT) } else if (op == TOK_GE) {
*NUMPTR_M1 = (*NUMPTR_M1 > numptr_val); *NUMPTR_M1 = (*NUMPTR_M1 >= numptr_val);
else if (op == TOK_LT) } else if (op == TOK_RSHIFT) {
*NUMPTR_M1 = (*NUMPTR_M1 < numptr_val); *NUMPTR_M1 >>= numptr_val;
else if (op == TOK_LE) } else if (op == TOK_LSHIFT) {
*NUMPTR_M1 = (*NUMPTR_M1 <= numptr_val); *NUMPTR_M1 <<= numptr_val;
else if (op == TOK_MUL) } else if (op == TOK_GT) {
*NUMPTR_M1 *= numptr_val; *NUMPTR_M1 = (*NUMPTR_M1 > numptr_val);
else if (op == TOK_ADD) } else if (op == TOK_LT) {
*NUMPTR_M1 += numptr_val; *NUMPTR_M1 = (*NUMPTR_M1 < numptr_val);
else if (op == TOK_SUB) } else if (op == TOK_LE) {
*NUMPTR_M1 -= numptr_val; *NUMPTR_M1 = (*NUMPTR_M1 <= numptr_val);
else if(numptr_val==0) /* zero divisor check */ } else if (op == TOK_MUL) {
return -2; *NUMPTR_M1 *= numptr_val;
else if (op == TOK_DIV) } else if (op == TOK_ADD) {
*NUMPTR_M1 /= numptr_val; *NUMPTR_M1 += numptr_val;
else if (op == TOK_REM) } else if (op == TOK_SUB) {
*NUMPTR_M1 %= numptr_val; *NUMPTR_M1 -= numptr_val;
/* WARNING!!! WARNING!!! WARNING!!! */ }
/* Any new operators should be added BEFORE the zero divisor check! */ /* zero divisor check */
else if (numptr_val == 0) {
return -2;
} else if (op == TOK_DIV) {
*NUMPTR_M1 /= numptr_val;
} else if (op == TOK_REM) {
*NUMPTR_M1 %= numptr_val;
}
/* WARNING!!! WARNING!!! WARNING!!! */
/* Any new operators should be added BEFORE the zero divisor check! */
} }
return 0; return 0;
err: return(-1); err:
return (-1);
} }
static const char endexpression[] = ")"; static const char endexpression[] = ")";
@ -227,7 +242,7 @@ static const char op_char[] = "!<>=|&*/%~()+-";
static const char op_token[] = { static const char op_token[] = {
/* paired with equal */ /* paired with equal */
TOK_NE, TOK_LE, TOK_GE, TOK_NE, TOK_LE, TOK_GE,
/* paired with self -- note: ! is special-cased below*/ /* paired with self -- note: ! is special-cased below */
TOK_ERROR, TOK_LSHIFT, TOK_RSHIFT, TOK_EQ, TOK_OR, TOK_AND, TOK_ERROR, TOK_LSHIFT, TOK_RSHIFT, TOK_EQ, TOK_OR, TOK_AND,
/* singles */ /* singles */
TOK_NOT, TOK_LT, TOK_GT, TOK_ERROR, TOK_BOR, TOK_BAND, TOK_NOT, TOK_LT, TOK_GT, TOK_ERROR, TOK_BOR, TOK_BAND,
@ -238,31 +253,32 @@ static const char op_token[] = {
#define NUM_PAIR_EQUAL 3 #define NUM_PAIR_EQUAL 3
#define NUM_PAIR_SAME 6 #define NUM_PAIR_SAME 6
extern long arith (const char *expr, int *errcode) extern long arith(const char *expr, int *errcode)
{ {
register char arithval; /* Current character under analysis */ register char arithval; /* Current character under analysis */
operator lasttok, op; operator lasttok, op;
unsigned char prec; unsigned char prec;
const char *p = endexpression; const char *p = endexpression;
size_t datasizes = strlen(expr); size_t datasizes = strlen(expr);
/* Stack of integers */ /* Stack of integers */
/* The proof that there can be no more than strlen(startbuf)/2+1 integers /* The proof that there can be no more than strlen(startbuf)/2+1 integers
* in any given correct or incorrect expression is left as an excersize to * in any given correct or incorrect expression is left as an excersize to
* the reader. */ * the reader. */
long *numstack = alloca((datasizes/2)*sizeof(long)), long *numstack = alloca(((datasizes + 1) / 2) * sizeof(long));
*numstackptr = numstack; long *numstackptr = numstack;
/* Stack of operator tokens */ /* Stack of operator tokens */
operator *stack = alloca((datasizes+1) * sizeof(operator)), operator * stack = alloca((datasizes + 1) * sizeof(operator));
*stackptr = stack; operator * stackptr = stack;
*stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */ /* start off with a left paren */
*stackptr++ = lasttok = TOK_LPAREN;
loop: loop:
if ((arithval = *expr) == 0) { if ((arithval = *expr) == 0) {
if (p == endexpression) { /* Null expression. */ /* Null expression. */
if (p == endexpression) {
return (*errcode = 0); return (*errcode = 0);
} }
@ -271,23 +287,25 @@ extern long arith (const char *expr, int *errcode)
* are to be applied in order. At the end, there should be a final * are to be applied in order. At the end, there should be a final
* result on the integer stack */ * result on the integer stack */
if (expr != endexpression + 1) { /* If we haven't done so already, */ if (expr != endexpression + 1) { /* If we haven't done so already, */
expr = endexpression; /* append a closing right paren */ expr = endexpression; /* append a closing right paren */
goto loop; /* and let the loop process it. */ goto loop; /* and let the loop process it. */
} }
/* At this point, we're done with the expression. */ /* At this point, we're done with the expression. */
if (numstackptr != numstack+1) {/* ... but if there isn't, it's bad */ if (numstackptr != numstack + 1) { /* ... but if there isn't, it's bad */
err: err:
return (*errcode = -1); return (*errcode = -1);
/* NOTREACHED */ /* NOTREACHED */
} }
return *numstack; return *numstack;
} else { } else {
/* Continue processing the expression. */ /* Continue processing the expression. */
/* Skip whitespace */
if (isspace(arithval)) { if (isspace(arithval)) {
goto prologue; /* Skip whitespace */ goto prologue;
} }
if ((unsigned)arithval-'0' <= 9) /* isdigit */ { /* isdigit ? */
if ((unsigned) arithval - '0' <= 9) {
*numstackptr++ = strtol(expr, (char **) &expr, 10); *numstackptr++ = strtol(expr, (char **) &expr, 10);
lasttok = TOK_NUM; lasttok = TOK_NUM;
goto loop; goto loop;
@ -297,20 +315,21 @@ extern long arith (const char *expr, int *errcode)
goto err; goto err;
} }
#else #else
for ( p=op_char ; *p != arithval ; p++ ) { for (p = op_char; *p != arithval; p++) {
if (!*p) { if (!*p) {
goto err; goto err;
} }
} }
#endif #endif
p = op_token + (int)(p - op_char); p = op_token + (int) (p - op_char);
++expr; ++expr;
if ((p >= op_token + NUM_PAIR_EQUAL) || (*expr != '=')) { if ((p >= op_token + NUM_PAIR_EQUAL) || (*expr != '=')) {
p += NUM_PAIR_EQUAL; p += NUM_PAIR_EQUAL;
if ((p >= op_token + NUM_PAIR_SAME + NUM_PAIR_EQUAL) if ((p >= op_token + NUM_PAIR_SAME + NUM_PAIR_EQUAL)
|| (*expr != arithval) || (arithval == '!')) { || (*expr != arithval) || (arithval == '!')) {
--expr; --expr;
if (arithval == '=') { /* single = */ /* single = */
if (arithval == '=') {
goto err; goto err;
} }
p += NUM_PAIR_SAME; p += NUM_PAIR_SAME;
@ -319,9 +338,11 @@ extern long arith (const char *expr, int *errcode)
* a number, since it evaluates to one). Think about it. * a number, since it evaluates to one). Think about it.
* It makes sense. */ * It makes sense. */
if ((lasttok != TOK_NUM) if ((lasttok != TOK_NUM)
&& (p >= op_token + NUM_PAIR_SAME + NUM_PAIR_EQUAL && (p >=
+ sizeof(op_char) - 2)) { (op_token + NUM_PAIR_SAME + NUM_PAIR_EQUAL +
p += 2; /* Unary plus or minus */ sizeof(op_char) - 2))) {
/* Unary plus or minus */
p += 2;
} }
} }
} }
@ -337,8 +358,11 @@ extern long arith (const char *expr, int *errcode)
/* Left paren is given the lowest priority so it will never be /* Left paren is given the lowest priority so it will never be
* "applied" in this way */ * "applied" in this way */
prec = PREC(op); prec = PREC(op);
if ((prec > 0) && (prec != UNARYPREC)) { /* not left paren or unary */
if (lasttok != TOK_NUM) { /* binary op must be preceded by a num */ /* not left paren or unary */
if ((prec > 0) && (prec != UNARYPREC)) {
/* binary op must be preceded by a num */
if (lasttok != TOK_NUM) {
goto err; goto err;
} }
while (stackptr != stack) { while (stackptr != stack) {
@ -348,15 +372,20 @@ extern long arith (const char *expr, int *errcode)
* tokens and apply them */ * tokens and apply them */
if (stackptr[-1] == TOK_LPAREN) { if (stackptr[-1] == TOK_LPAREN) {
--stackptr; --stackptr;
lasttok = TOK_NUM; /* Any operator directly after a */
/* close paren should consider itself binary */ /* Any operator directly after a */
lasttok = TOK_NUM;
/* close paren should consider itself binary */
goto prologue; goto prologue;
} }
} else if (PREC(stackptr[-1]) < prec) { } else if (PREC(stackptr[-1]) < prec) {
break; break;
} }
*errcode = ARITH_APPLY(*--stackptr); *errcode = ARITH_APPLY(*--stackptr);
if(*errcode) return *errcode; if (*errcode) {
return *errcode;
}
} }
if (op == TOK_RPAREN) { if (op == TOK_RPAREN) {
goto err; goto err;
@ -366,7 +395,7 @@ extern long arith (const char *expr, int *errcode)
/* Push this operator to the stack and remember it. */ /* Push this operator to the stack and remember it. */
*stackptr++ = lasttok = op; *stackptr++ = lasttok = op;
prologue: prologue:
++expr; ++expr;
goto loop; goto loop;
} }