mirror of
https://github.com/sheumann/hush.git
synced 2024-08-01 01:28:57 +00:00
Apply vodz's last_patch53.gz (bb_asprintf.c) and last_patch54.gz
(arith.c).
This commit is contained in:
parent
7829b8d067
commit
4d0884a1ea
141
libbb/arith.c
141
libbb/arith.c
@ -140,8 +140,7 @@ 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)
|
||||||
@ -157,82 +156,68 @@ typedef char operator;
|
|||||||
|
|
||||||
/* "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;
|
||||||
|
|
||||||
/* There is no operator that can work without arguments */
|
if (NUMPTR == numstack) goto err; /* There is no operator that can work
|
||||||
if (NUMPTR == numstack) {
|
without arguments */
|
||||||
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
|
||||||
/* ... and binary operators need two arguments */
|
arguments */
|
||||||
if (NUMPTR_M1 == numstack) {
|
numptr_val = *--NUMPTR; /* ... and they pop one */
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
/* ... and they pop one */
|
|
||||||
numptr_val = *--NUMPTR;
|
|
||||||
|
|
||||||
NUMPTR_M1 = NUMPTR - 1;
|
NUMPTR_M1 = NUMPTR - 1;
|
||||||
|
if (op == TOK_BOR)
|
||||||
if (op == TOK_BOR) {
|
|
||||||
*NUMPTR_M1 |= numptr_val;
|
*NUMPTR_M1 |= numptr_val;
|
||||||
} else if (op == TOK_OR) {
|
else if (op == TOK_OR)
|
||||||
*NUMPTR_M1 = numptr_val || *NUMPTR_M1;
|
*NUMPTR_M1 = numptr_val || *NUMPTR_M1;
|
||||||
} else if (op == TOK_BAND) {
|
else if (op == TOK_BAND)
|
||||||
*NUMPTR_M1 &= numptr_val;
|
*NUMPTR_M1 &= numptr_val;
|
||||||
} else if (op == TOK_AND) {
|
else if (op == TOK_AND)
|
||||||
*NUMPTR_M1 = *NUMPTR_M1 && numptr_val;
|
*NUMPTR_M1 = *NUMPTR_M1 && numptr_val;
|
||||||
} else if (op == TOK_EQ) {
|
else if (op == TOK_EQ)
|
||||||
*NUMPTR_M1 = (*NUMPTR_M1 == numptr_val);
|
*NUMPTR_M1 = (*NUMPTR_M1 == numptr_val);
|
||||||
} else if (op == TOK_NE) {
|
else if (op == TOK_NE)
|
||||||
*NUMPTR_M1 = (*NUMPTR_M1 != numptr_val);
|
*NUMPTR_M1 = (*NUMPTR_M1 != numptr_val);
|
||||||
} else if (op == TOK_GE) {
|
else if (op == TOK_GE)
|
||||||
*NUMPTR_M1 = (*NUMPTR_M1 >= numptr_val);
|
*NUMPTR_M1 = (*NUMPTR_M1 >= numptr_val);
|
||||||
} else if (op == TOK_RSHIFT) {
|
else if (op == TOK_RSHIFT)
|
||||||
*NUMPTR_M1 >>= numptr_val;
|
*NUMPTR_M1 >>= numptr_val;
|
||||||
} else if (op == TOK_LSHIFT) {
|
else if (op == TOK_LSHIFT)
|
||||||
*NUMPTR_M1 <<= numptr_val;
|
*NUMPTR_M1 <<= numptr_val;
|
||||||
} else if (op == TOK_GT) {
|
else if (op == TOK_GT)
|
||||||
*NUMPTR_M1 = (*NUMPTR_M1 > numptr_val);
|
*NUMPTR_M1 = (*NUMPTR_M1 > numptr_val);
|
||||||
} else if (op == TOK_LT) {
|
else if (op == TOK_LT)
|
||||||
*NUMPTR_M1 = (*NUMPTR_M1 < numptr_val);
|
*NUMPTR_M1 = (*NUMPTR_M1 < numptr_val);
|
||||||
} else if (op == TOK_LE) {
|
else if (op == TOK_LE)
|
||||||
*NUMPTR_M1 = (*NUMPTR_M1 <= numptr_val);
|
*NUMPTR_M1 = (*NUMPTR_M1 <= numptr_val);
|
||||||
} else if (op == TOK_MUL) {
|
else if (op == TOK_MUL)
|
||||||
*NUMPTR_M1 *= numptr_val;
|
*NUMPTR_M1 *= numptr_val;
|
||||||
} else if (op == TOK_ADD) {
|
else if (op == TOK_ADD)
|
||||||
*NUMPTR_M1 += numptr_val;
|
*NUMPTR_M1 += numptr_val;
|
||||||
} else if (op == TOK_SUB) {
|
else if (op == TOK_SUB)
|
||||||
*NUMPTR_M1 -= numptr_val;
|
*NUMPTR_M1 -= numptr_val;
|
||||||
}
|
else if(numptr_val==0) /* zero divisor check */
|
||||||
/* zero divisor check */
|
|
||||||
else if (numptr_val == 0) {
|
|
||||||
return -2;
|
return -2;
|
||||||
} else if (op == TOK_DIV) {
|
else if (op == TOK_DIV)
|
||||||
*NUMPTR_M1 /= numptr_val;
|
*NUMPTR_M1 /= numptr_val;
|
||||||
} else if (op == TOK_REM) {
|
else if (op == TOK_REM)
|
||||||
*NUMPTR_M1 %= numptr_val;
|
*NUMPTR_M1 %= numptr_val;
|
||||||
}
|
|
||||||
/* WARNING!!! WARNING!!! WARNING!!! */
|
/* WARNING!!! WARNING!!! WARNING!!! */
|
||||||
/* Any new operators should be added BEFORE the zero divisor check! */
|
/* Any new operators should be added BEFORE the zero divisor check! */
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
err: return(-1);
|
||||||
return (-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char endexpression[] = ")";
|
static const char endexpression[] = ")";
|
||||||
@ -242,7 +227,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,
|
||||||
@ -253,33 +238,34 @@ 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) + 2;
|
||||||
|
|
||||||
/* 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 + 1) / 2) * sizeof(long));
|
long *numstack = alloca(((datasizes)/2)*sizeof(long)),
|
||||||
long *numstackptr = numstack;
|
*numstackptr = numstack;
|
||||||
|
|
||||||
/* Stack of operator tokens */
|
/* Stack of operator tokens */
|
||||||
operator * stack = alloca((datasizes + 1) * sizeof(operator));
|
operator *stack = alloca((datasizes) * sizeof(operator)),
|
||||||
operator * stackptr = stack;
|
*stackptr = stack;
|
||||||
|
|
||||||
/* start off with a left paren */
|
*numstack = 0;
|
||||||
*stackptr++ = lasttok = TOK_LPAREN;
|
*stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
if ((arithval = *expr) == 0) {
|
if ((arithval = *expr) == 0) {
|
||||||
/* Null expression. */
|
if (p == endexpression) { /* Null expression. */
|
||||||
if (p == endexpression) {
|
*errcode = 0;
|
||||||
return (*errcode = 0);
|
return *numstack;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is only reached after all tokens have been extracted from the
|
/* This is only reached after all tokens have been extracted from the
|
||||||
@ -292,7 +278,7 @@ extern long arith(const char *expr, int *errcode)
|
|||||||
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 */
|
||||||
@ -300,12 +286,10 @@ extern long arith(const char *expr, int *errcode)
|
|||||||
return *numstack;
|
return *numstack;
|
||||||
} else {
|
} else {
|
||||||
/* Continue processing the expression. */
|
/* Continue processing the expression. */
|
||||||
/* Skip whitespace */
|
|
||||||
if (isspace(arithval)) {
|
if (isspace(arithval)) {
|
||||||
goto prologue;
|
goto prologue; /* Skip whitespace */
|
||||||
}
|
}
|
||||||
/* isdigit ? */
|
if ((unsigned)arithval-'0' <= 9) /* 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;
|
||||||
@ -315,21 +299,20 @@ 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;
|
||||||
/* single = */
|
if (arithval == '=') { /* single = */
|
||||||
if (arithval == '=') {
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
p += NUM_PAIR_SAME;
|
p += NUM_PAIR_SAME;
|
||||||
@ -338,11 +321,9 @@ 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 >=
|
&& (p >= op_token + NUM_PAIR_SAME + NUM_PAIR_EQUAL
|
||||||
(op_token + NUM_PAIR_SAME + NUM_PAIR_EQUAL +
|
+ sizeof(op_char) - 2)) {
|
||||||
sizeof(op_char) - 2))) {
|
p += 2; /* Unary plus or minus */
|
||||||
/* Unary plus or minus */
|
|
||||||
p += 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -358,11 +339,8 @@ 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 */
|
||||||
/* not left paren or unary */
|
if (lasttok != TOK_NUM) { /* binary op must be preceded by a num */
|
||||||
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) {
|
||||||
@ -372,10 +350,7 @@ 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 */
|
||||||
/* Any operator directly after a */
|
|
||||||
lasttok = TOK_NUM;
|
|
||||||
|
|
||||||
/* close paren should consider itself binary */
|
/* close paren should consider itself binary */
|
||||||
goto prologue;
|
goto prologue;
|
||||||
}
|
}
|
||||||
@ -383,9 +358,7 @@ extern long arith(const char *expr, int *errcode)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
*errcode = ARITH_APPLY(*--stackptr);
|
*errcode = ARITH_APPLY(*--stackptr);
|
||||||
if (*errcode) {
|
if(*errcode) return *errcode;
|
||||||
return *errcode;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (op == TOK_RPAREN) {
|
if (op == TOK_RPAREN) {
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -7,83 +7,15 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef TEST
|
#include "libbb.h"
|
||||||
extern void *xrealloc(void *p, size_t size);
|
|
||||||
#else
|
|
||||||
#include "libbb.h" /* busybox source */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Exchange glibc vasprintf - minimize allocate memory version */
|
|
||||||
/* libc5 and uclibc have not vasprintf function */
|
|
||||||
void bb_vasprintf(char **string_ptr, const char *format, va_list args)
|
|
||||||
{
|
|
||||||
int bs = 128;
|
|
||||||
char stack_buff[128];
|
|
||||||
char *buff = stack_buff;
|
|
||||||
int done;
|
|
||||||
|
|
||||||
/* two or more loop, first - calculate memory size only */
|
|
||||||
while(1) {
|
|
||||||
done = vsnprintf (buff, bs, format, args);
|
|
||||||
/* Different libc have different interpretation vsnprintf returned value */
|
|
||||||
if(done >= 0) {
|
|
||||||
if(done < bs && buff != stack_buff) {
|
|
||||||
/* allocated */
|
|
||||||
*string_ptr = buff;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
/* true calculate memory size */
|
|
||||||
bs = done+1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* Old libc. Incrementaly test.
|
|
||||||
* Exact not minimize allocate memory.
|
|
||||||
*/
|
|
||||||
bs += 128;
|
|
||||||
}
|
|
||||||
buff = xrealloc((buff == stack_buff ? NULL : buff), bs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void bb_asprintf(char **string_ptr, const char *format, ...)
|
void bb_asprintf(char **string_ptr, const char *format, ...)
|
||||||
{
|
{
|
||||||
va_list p;
|
va_list p;
|
||||||
|
|
||||||
va_start(p, format);
|
va_start(p, format);
|
||||||
bb_vasprintf(string_ptr, format, p);
|
if(vasprintf(string_ptr, format, p)<0)
|
||||||
|
error_msg_and_die(memory_exhausted);
|
||||||
va_end(p);
|
va_end(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TEST
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
char *out_buf;
|
|
||||||
char big_buf[200];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
bb_asprintf(&out_buf, "Hi!\nargc=%d argv[0]=%s\n", argc, argv[0]);
|
|
||||||
printf(out_buf);
|
|
||||||
free(out_buf);
|
|
||||||
|
|
||||||
for(i=0; i < sizeof(big_buf)-1; i++)
|
|
||||||
big_buf[i]='x';
|
|
||||||
big_buf[i]=0;
|
|
||||||
bb_asprintf(&out_buf, "Test Big\n%s\n", big_buf);
|
|
||||||
printf(out_buf);
|
|
||||||
free(out_buf);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *xrealloc(void *p, size_t size)
|
|
||||||
{
|
|
||||||
void *p2 = realloc(p, size);
|
|
||||||
if(p2==0) {
|
|
||||||
fprintf(stderr, "TEST: memory_exhausted\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
return p2;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
Loading…
Reference in New Issue
Block a user